blob: 4565d8a3b5a8c612c309ef475ba60f1b7c8fe4a5 [file] [log] [blame]
// 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; }
void SetIntelYTiling(bool enable) {
intel_y_tiling_ = enable;
}
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 intel_y_tiling_ = 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; }
};