blob: 24aab00170aaa7dcf1e057512f26f33cfb06b97e [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.
library ddk.protocol.display.controller;
using zx;
//using ZxPixelFormat = uint32;
enum ZxPixelFormat : uint32 {
// using ZxUnownedHandle = uint32;
// TODO(ZX-3369) replace with normal banjo type.
enum ZxUnownedHandle : uint32 {
/// The image is linear and VMO backed.
const uint32 IMAGE_TYPE_SIMPLE = 0;
/// A structure containing information about each plane of an image.
struct ImagePlane {
uint32 byte_offset;
uint32 bytes_per_row;
/// A structure containing information about an image.
struct Image {
/// The width and height of the image in pixels.
uint32 width;
uint32 height;
/// The pixel format of the image.
ZxPixelFormat pixel_format;
/// The type conveys information about what is providing the pixel data. If this is not
/// IMAGE_FORMAT_SIMPLE, it is up to the driver and buffer producer to agree on the meaning
/// of the value through some mechanism outside the scope of this API.
uint32 type;
array<ImagePlane>:4 planes;
/// A driver-defined handle to the image. Each handle must be unique.
uint64 @handle;
const uint32 INVALID_DISPLAY_ID = 0;
/// A fallback structure to convey display information without an edid.
struct DisplayParams {
uint32 width;
uint32 height;
uint32 refresh_rate_e2;
/// Info about valid cursor configurations.
struct CursorInfo {
/// The width and height of the cursor configuration, in pixels.
uint32 width;
uint32 height;
ZxPixelFormat format;
union Panel {
/// The bus_id to use to read this display's edid from the device's i2c protocol.
uint32 i2c_bus_id;
/// The display's parameters if an edid is not present.
DisplayParams params;
/// A structure containing information a connected display.
struct AddedDisplayArgs {
uint64 display_id;
/// A flag indicating whether or not the display has a valid edid.
/// If true, the device should expose an ZX_PROTOCOL_I2C_IMPL device through get_protocol, in
/// addition to the ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL protocol. Note that the i2c device
/// will be called from the on_displays_changed callback, so care should be taken to avoid
/// deadlocks or double-locking.
/// If no edid is present, then the meaning of display_config's mode structure is
/// undefined, and drivers should ignore it in check_configuration and apply_configuration.
bool edid_present;
Panel panel;
/// A list of pixel formats supported by the display. The first entry is the
/// preferred pixel format.
vector<ZxPixelFormat> pixel_format;
/// A list of cursor configurations most likely to be accepted by the driver. Can
/// be null if cursor_count is 0.
/// The driver may reject some of these configurations in some circumstances, and
/// it may accept other configurations, but at least one of these configurations
/// should be valid at most times.
vector<CursorInfo> cursor_info;
/// Out parameters will be populated before on_displays_changed returns.
struct AddedDisplayInfo {
bool is_hdmi_out;
bool is_standard_srgb_out;
uint32 audio_format_count;
/// All strings are null-terminated. |manufacturer_id| is guaranteed to have
/// length 3, all other strings may be empty.
string:4 manufacturer_id;
/// non-null
string manufacturer_name;
/// null-terminated
string:14 monitor_name;
/// null-terminated
string:14 monitor_serial;
/// The client will not make any `ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL` calls into the device
/// during these callbacks.
[Layout = "ddk-interface"]
protocol DisplayControllerInterface {
/// Callbacks which are invoked when displays are added or removed. |added_display_list| and
/// |removed_display_list| point to arrays of the display ids which were added and removed. If
/// |added_display_count| or |removed_display_count| is 0, the corresponding array can be NULL.
/// The driver must be done accessing any images which were on the removed displays.
/// The driver should call this function when the callback is registered if any displays
/// are present.
OnDisplaysChanged(vector<AddedDisplayArgs> added_display,
vector<uint64> removed_display) -> (vector<AddedDisplayInfo> display_info);
/// |timestamp| is the ZX_CLOCK_MONOTONIC timestamp at which the vsync occurred.
/// |handles| points to an array of image handles of each framebuffer being
/// displayed, in increasing z-order.
OnDisplayVsync(uint64 display_id, zx.time timestamp, vector<uint64> @handle) -> ();
GetAudioFormat(uint64 display_id, uint32 fmt_idx)
-> (zx.status s, fmt);
enum Alpha : uint8 {
/// Rotations are applied counter-clockwise, and are applied before reflections.
enum FrameTransform : uint32 {
ROT_90 = 3;
ROT_180 = 4;
ROT_270 = 5;
struct Frame {
/// (|x_pos|, |y_pos|) specifies the position of the upper-left corner
/// of the frame.
uint32 x_pos;
uint32 y_pos;
uint32 width;
uint32 height;
struct PrimaryLayer {
Image image;
/// An ALPHA_* constant.
/// If |alpha_mode| == `ALPHA_DISABLED`, the layer is opaque and alpha_layer_val is ignored.
/// If |alpha_mode| == `PREMULTIPLIED` or `HW_MULTIPLY` and |alpha_layer_val| is NaN, the alpha
/// used when blending is determined by the per-pixel alpha channel.
/// If |alpha_mode| == `PREMULTIPLIED` or `HW_MULTIPLY` and |alpha_layer_val| is not NaN, the
/// alpha used when blending is the product of alpha_layer_val and any per-pixel alpha.
/// Additionally, if alpha_mode == PREMULTIPLIED, then the hardware must premultiply the color
/// channel with alpha_layer_val before blending.
/// If alpha_layer_val is not NaN, it will be in the range [0, 1].
Alpha alpha_mode;
float32 alpha_layer_val;
FrameTransform transform_mode;
/// The source frame, where (0,0) is the top-left corner of the image. The
/// client guarantees that src_frame lies entirely within the image.
Frame src_frame;
/// The destination frame, where (0,0) is the top-left corner of the
/// composed output. The client guarantees that dest_frame lies entirely
/// within the composed output.
Frame dest_frame;
struct CursorLayer {
Image image;
/// The position of the top-left corner of the cursor's image. When being
/// applied to a display, the cursor is guaranteed to have at least one
/// pixel of overlap with the display.
int32 x_pos;
int32 y_pos;
struct ColorLayer {
ZxPixelFormat format;
/// The color to use for the layer. The color is little-endian, and is
/// guaranteed to be of the appropriate size.
vector<uint8> color;
/// Types of layers.
enum LayerType : uint32 {
COLOR = 2;
union LayerConfig {
PrimaryLayer primary;
CursorLayer cursor;
ColorLayer color;
struct Layer {
LayerType type;
/// z_index of the layer. See |check_configuration| and |apply_configuration|.
uint32 z_index;
LayerConfig cfg;
/// constants for display_config's mode_flags field
enum ModeFlag : uint32 {
/// The video parameters which specify the display mode.
struct DisplayMode {
uint32 pixel_clock_10khz;
uint32 h_addressable;
uint32 h_front_porch;
uint32 h_sync_pulse;
uint32 h_blanking;
uint32 v_addressable;
uint32 v_front_porch;
uint32 v_sync_pulse;
uint32 v_blanking;
/// A bitmask of MODE_FLAG_* values
uint32 flags;
enum ColorConversion : uint32 {
/// If set, use the 0 vector for the color conversion preoffset
/// If set, use the identity matrix for the color conversion coefficients
/// If set, use the 0 vector for the color conversion postoffset
struct DisplayConfig {
/// the display id to which the configuration applies
uint64 display_id;
DisplayMode mode;
/// Bitmask of COLOR_CONVERSION_* flags
uint32 cc_flags;
/// Color conversion is applied to each pixel according to the formula:
/// (cc_coefficients * (pixel + cc_preoffsets)) + cc_postoffsets
/// where pixel is a column vector consisting of the pixel's 3 components.
array<float32>:3 cc_preoffsets;
array<array<float32>:3>:3 cc_coefficients;
array<float32>:3 cc_postoffsets;
vector<Layer?>? layer;
enum ConfigDisplay : uint32 {
/// The display mode configuration is valid. Note that this is distinct from
/// whether or not the layer configuration is valid.
OK = 0;
/// Error indicating that the hardware cannot simultaneously support the
/// requested number of displays.
/// Error indicating that the hardware cannot simultaneously support the given
/// set of display modes. To support a mode, the display must be able to display
/// a single layer with width and height equal to the requested mode and the
/// preferred pixel format.
enum Client : uint32 {
/// The client should convert the corresponding layer to a primary layer.
/// The client should compose all layers with MERGE_BASE and MERGE_SRC into a new,
/// single primary layer at the MERGE_BASE layer's z-order. The driver must accept
/// a fullscreen layer with the default pixel format, but may accept other layer
/// parameters.
/// MERGE_BASE should only be set on one layer per display. If it is set on multiple
/// layers, the client will arbitrarily pick one and change the rest to MERGE_SRC.
MERGE_SRC = 0x4;
/// The client should pre-scale the image so that src_frame's dimensions are equal
/// to dest_frame's dimensions.
/// The client should pre-clip the image so that src_frame's dimensions are equal to
/// the image's dimensions.
SRC_FRAME = 0x10;
/// The client should pre-apply the transformation so TRANSFORM_IDENTITY can be used.
/// The client should apply the color conversion.
/// The client should apply the alpha transformation itself.
ALPHA = 0x80;
/// The client guarantees that check_configuration and apply_configuration are always
/// made from a single thread. The client makes no other threading guarantees.
[Layout = "ddk-protocol"]
protocol DisplayControllerImpl {
/// The function will only be called once, and it will be called before any other
/// functions are called.
SetDisplayControllerInterface(DisplayControllerInterface intf) -> ();
/// Imports a VMO backed image into the driver. The driver should set image->handle. The
/// driver does not own the vmo handle passed to this function.
ImportVmoImage(Image? image, handle<vmo> vmo, usize offset) -> (zx.status s);
/// Imports an image from a buffer collection into the driver. The driver should set
/// image->handle.
ImportImage(Image? image, ZxUnownedHandle collection, uint32 index)
-> (zx.status s);
/// Releases any driver state associated with the given image. The client guarantees that
/// any images passed to apply_config will not be released until a vsync occurs with a
/// more recent image.
ReleaseImage(Image? image) -> ();
/// Validates the given configuration.
/// The configuration may not include all displays. Omitted displays should be treated as
/// whichever of off or displaying a blank screen results in a more permissive validation.
/// All displays in a configuration will have at least one layer. The layers will be
/// arranged in increasing z-order, and their z_index fields will be set consecutively.
/// Whether or not the driver can accept the configuration cannot depend on the
/// particular image handles, as it must always be possible to present a new image in
/// place of another image with a matching configuration. It also cannot depend on the
/// cursor position, as that can be updated without another call to check_configuration.
/// display_cfg_result should be set to a CONFIG_DISPLAY_* error if the combination of
/// display modes is not supported.
/// layer_cfg_result points to an array of arrays. The primary length is display_count, the
/// secondary lengths are the corresponding display_cfg's layer_count. If display_cfg_result
/// is CONFIG_DISPLAY_OK, any errors in layer configuration should be returned as a CLIENT*
/// flag in the corresponding layer_cfg_result entry.
/// The driver must not retain references to the configuration after this function returns.
/// TODO: Fix me...
CheckConfiguration(vector<DisplayConfig?> display_config)
-> (uint32 display_cfg_result, vector<uint32>? layer_cfg_result);
/// Applies the configuration.
/// All configurations passed to this function will be derived from configurations which
/// have been successfully validated, with the only differences either being omitted layers
/// or different image handles. To account for any layers which are not present, the driver
/// must use the z_index values of the present layers to configure them as if the whole
/// configuration was present.
/// Unlike with check_configuration, displays included in the configuration are not
/// guaranteed to include any layers. Both omitted displays and displays with no layers
/// can either be turned off or set to display a blank screen, but for displays with no
/// layers there is a strong preference to display a blank screen instead of turn them off.
/// In either case, the driver must drop all references to old images and invoke the vsync
/// callback after doing so.
/// The driver must not retain references to the configuration after this function returns.
ApplyConfiguration(vector<DisplayConfig?> display_config) -> ();
/// Computes the stride (in pixels) necessary for a linear image with the given width
/// and pixel format. Returns 0 on error.
ComputeLinearStride(uint32 width, ZxPixelFormat pixel_format) -> (uint32 s);
/// Allocates a VMO of the requested size which can be used for images.
// TODO: move this functionality into a seperate video buffer management system.
AllocateVmo(uint64 size) -> (zx.status s, handle<vmo> vmo);
// Connects the handle to the sysmem service.
GetSysmemConnection(handle<channel> sysmem_handle) -> (zx.status s);
// Set sysmem buffer collection contraints needed to ensure an image can be imported with config
// |config| on the fuchsia.sysmem.BufferCollection handle |collection|.
SetBufferCollectionConstraints(Image config, ZxUnownedHandle collection) -> (zx.status s);
// If the system only supports single-buffered mode with a single framebuffer, then this returns
// that buffer and its stride. Otherwise it can return ZX_ERR_NOT_SUPPORTED.
GetSingleBufferFramebuffer() -> (zx.status res, handle<vmo>? vmo, uint32 stride);
CaptureDisplayOutput() -> (zx.status s, handle<vmo> vmo);