// Copyright 2018 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #pragma once #include #include #include #include "display.h" #include "fuchsia/hardware/display/c/fidl.h" #include "image.h" typedef struct frame { uint32_t width; uint32_t height; uint32_t x_pos; uint32_t y_pos; } frame_t; typedef struct layer { uint64_t id; bool active; bool done; frame_t src; frame_t dest; image_import_t import_info[2]; } layer_t; // A layer whose output can appear on multiple displays. class VirtualLayer { public: explicit VirtualLayer(Display* display); explicit VirtualLayer(const fbl::Vector& displays); // Finish initializing the layer. All Set* methods should be called before this. virtual bool Init(zx_handle_t channel) = 0; // Steps the local layout state to frame_num. virtual void StepLayout(int32_t frame_num) = 0; // Waits for the display controller to be done with the previous version of this frame. virtual bool WaitForReady() = 0; // Sets the current layout to the display contorller. virtual void SendLayout(zx_handle_t channel) = 0; // Renders the current frame (and signals the fence if necessary). virtual void Render(int32_t frame_num) = 0; // Gets the display controller layer ID for usage on the given display. uint64_t id(uint64_t display_id) const { for (unsigned i = 0; i < displays_.size(); i++) { if (displays_[i]->id() == display_id && layers_[i].active) { return layers_[i].id; } } return INVALID_ID; } // Gets the ID of the image on the given display. virtual uint64_t image_id(uint64_t display_id) const = 0; void set_frame_done(uint64_t display_id) { for (unsigned i = 0; i < displays_.size(); i++) { if (displays_[i]->id() == display_id) { layers_[i].done = true; } } } virtual bool is_done() const { bool done = true; for (unsigned i = 0; i < displays_.size(); i++) { done &= !layers_[i].active || layers_[i].done; } return done; } void clear_done() { for (unsigned i = 0; i < displays_.size(); i++) { layers_[i].done = false; } } protected: layer_t* CreateLayer(zx_handle_t dc_handle); void SetLayerImages(zx_handle_t handle, bool alt_image); fbl::Vector displays_; fbl::Vector layers_; uint32_t width_; uint32_t height_; }; class PrimaryLayer : public VirtualLayer { public: explicit PrimaryLayer(Display* display); explicit PrimaryLayer(const fbl::Vector& displays); // Set* methods to configure the layer. void SetImageDimens(uint32_t width, uint32_t height) { image_width_ = width; image_height_ = height; src_frame_.width = width; src_frame_.height = height; dest_frame_.width = width; dest_frame_.height = height; } void SetSrcFrame(uint32_t width, uint32_t height) { src_frame_.width = width; src_frame_.height = height; } void SetDestFrame(uint32_t width, uint32_t height) { dest_frame_.width = width; dest_frame_.height = height; } void SetLayerFlipping(bool flip) { layer_flipping_ = flip; } void SetPanSrc(bool pan) { pan_src_ = pan; } void SetPanDest(bool pan) { pan_dest_ = pan; } void SetLayerToggle(bool toggle) { layer_toggle_ = toggle; } void SetRotates(bool rotates) { rotates_ = rotates; } void SetAlpha(bool enable, float val) { alpha_enable_ = enable; alpha_val_ = val; } void SetScaling(bool enable) { scaling_ = enable; } void SetImageFormat(uint32_t image_format) { image_format_ = image_format; } bool Init(zx_handle_t channel) override; void StepLayout(int32_t frame_num) override; bool WaitForReady() override; void SendLayout(zx_handle_t channel) override; void Render(int32_t frame_num) override; uint64_t image_id(uint64_t display_id) const override { for (unsigned i = 0; i < displays_.size(); i++) { if (displays_[i]->id() == display_id && layers_[i].active) { return layers_[i].import_info[alt_image_].id; } } return INVALID_ID; } private: void SetLayerPositions(zx_handle_t handle); bool Wait(uint32_t idx); void InitImageDimens(); uint32_t image_width_ = 0; uint32_t image_height_ = 0; uint32_t image_format_ = 0; frame_t src_frame_ = {}; frame_t dest_frame_ = {}; uint8_t rotation_ = fuchsia_hardware_display_Transform_IDENTITY; bool layer_flipping_ = false; bool pan_src_ = false; bool pan_dest_ = false; bool layer_toggle_ = false; bool rotates_ = false; bool alpha_enable_ = false; float alpha_val_ = 0.f; bool scaling_ = false; bool alt_image_ = false; Image* images_[2]; }; class CursorLayer : public VirtualLayer { public: explicit CursorLayer(Display* display); explicit CursorLayer(const fbl::Vector& displays); bool Init(zx_handle_t channel) override; void StepLayout(int32_t frame_num) override; void SendLayout(zx_handle_t channel) override; bool WaitForReady() override { return true; } void Render(int32_t frame_num) override {} uint64_t image_id(uint64_t display_id) const override { for (unsigned i = 0; i < displays_.size(); i++) { if (displays_[i]->id() == display_id && layers_[i].active) { return layers_[i].import_info[0].id; } } return INVALID_ID; } private: uint32_t x_pos_ = 0; uint32_t y_pos_ = 0; Image* image_; }; class ColorLayer : public VirtualLayer { public: explicit ColorLayer(Display* display); explicit ColorLayer(const fbl::Vector& displays); bool Init(zx_handle_t channel) override; void SendLayout(zx_handle_t channel) override {}; void StepLayout(int32_t frame_num) override {}; bool WaitForReady() override { return true; } void Render(int32_t frame_num) override {} uint64_t image_id(uint64_t display_id) const override { return INVALID_ID; } virtual bool is_done() const override { return true; } };