| // 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 <zircon/device/display-controller.h> |
| #include <zircon/types.h> |
| #include <lib/zx/channel.h> |
| |
| #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<Display>& displays); |
| |
| virtual ~VirtualLayer() {} |
| |
| // 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<Display*> displays_; |
| fbl::Vector<layer_t> layers_; |
| |
| uint32_t width_; |
| uint32_t height_; |
| }; |
| |
| class PrimaryLayer : public VirtualLayer { |
| public: |
| explicit PrimaryLayer(Display* display); |
| explicit PrimaryLayer(const fbl::Vector<Display>& 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<Display>& 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<Display>& 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; } |
| }; |