| // 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 zircon.device.audio; |
| 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, zircon.device.audio.AudioStreamFormatRange fmt); |
| }; |
| |
| enum Alpha : uint8 { |
| DISABLE = 0; |
| PREMULTIPLIED = 1; |
| HW_MULTIPLY = 2; |
| }; |
| |
| /// Rotations are applied counter-clockwise, and are applied before reflections. |
| enum FrameTransform : uint32 { |
| IDENTITY = 0; |
| REFLECT_X = 1; |
| REFLECT_Y = 2; |
| ROT_90 = 3; |
| ROT_180 = 4; |
| ROT_270 = 5; |
| ROT_90_REFLECT_X = 6; |
| ROT_90_REFLECT_Y = 7; |
| }; |
| |
| 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 { |
| PRIMARY = 0; |
| CURSOR = 1; |
| 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 { |
| VSYNC_POSITIVE = 0x1; |
| HSYNC_POSITIVE = 0x2; |
| INTERLACED = 0x4; |
| ALTERNATING_VBLANK = 0x8; |
| DOUBLE_CLOCKED = 0x10; |
| }; |
| |
| /// 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 |
| PREOFFSET = 0x1; |
| /// If set, use the identity matrix for the color conversion coefficients |
| COEFFICIENTS = 0x2; |
| /// If set, use the 0 vector for the color conversion postoffset |
| POSTOFFSET = 0x4; |
| }; |
| |
| 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. |
| TOO_MANY = 1; |
| /// 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. |
| UNSUPPORTED_MODES = 2; |
| }; |
| |
| enum Client : uint32 { |
| /// The client should convert the corresponding layer to a primary layer. |
| USE_PRIMARY = 0x1; |
| /// 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_BASE = 0x2; |
| MERGE_SRC = 0x4; |
| /// The client should pre-scale the image so that src_frame's dimensions are equal |
| /// to dest_frame's dimensions. |
| FRAME_SCALE = 0x8; |
| /// 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. |
| TRANSFORM = 0x20; |
| /// The client should apply the color conversion. |
| COLOR_CONVERSION = 0x40; |
| /// 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); |
| }; |