| // 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 fuchsia.hardware.display.controller; |
| |
| using fuchsia.hardware.audiotypes; |
| using zx; |
| |
| alias ZxPixelFormat = uint32; |
| |
| alias ZxUnownedHandle = uint32; |
| |
| type ImageType = strict enum : uint32 { |
| /// The image is linear and VMO backed. |
| SIMPLE = 0; |
| |
| // Intentionally left some gap between SIMPLE and CAPTURE. |
| |
| /// The image is used for capture |
| CAPTURE = 10; |
| }; |
| |
| /// A structure containing information about an image. |
| type Image = struct { |
| /// The width and height of the image in pixels. |
| width uint32; |
| height uint32; |
| |
| /// The pixel format of the image. |
| pixel_format ZxPixelFormat; |
| |
| /// The type conveys information about what is providing the pixel data. If this is not |
| /// IMAGE_TYPE_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. |
| type uint32; |
| |
| /// A driver-defined handle to the image. Each handle must be unique. |
| handle uint64; |
| }; |
| |
| const INVALID_DISPLAY_ID uint32 = 0; |
| const INVALID_ID uint32 = 0; |
| const INVALID_CONFIG_STAMP_VALUE uint64 = 0; |
| |
| /// A unique stamp representing a unique set of display configuration |
| /// in ApplyConfiguration(). |
| type ConfigStamp = struct { |
| /// For valid configurations, the value should not be equal to |
| /// `INVALID_CONFIG_STAMP_VALUE`. |
| value uint64; |
| }; |
| |
| /// A fallback structure to convey display information without an edid. |
| type DisplayParams = struct { |
| width uint32; |
| height uint32; |
| refresh_rate_e2 uint32; |
| }; |
| |
| /// Info about valid cursor configurations. |
| type CursorInfo = struct { |
| /// The width and height of the cursor configuration, in pixels. |
| width uint32; |
| height uint32; |
| format ZxPixelFormat; |
| }; |
| |
| type Panel = strict union { |
| /// The bus_id to use to read this display's edid from the device's i2c protocol. |
| 1: i2c_bus_id uint32; |
| /// The display's parameters if an edid is not present. |
| 2: params DisplayParams; |
| }; |
| |
| /// A structure containing information a connected display. |
| type AddedDisplayArgs = struct { |
| display_id uint64; |
| |
| /// 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. |
| edid_present bool; |
| panel Panel; |
| |
| /// A list of pixel formats supported by the display. The first entry is the |
| /// preferred pixel format. |
| pixel_format vector<ZxPixelFormat>:MAX; |
| |
| /// 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. |
| cursor_info vector<CursorInfo>:MAX; |
| }; |
| |
| /// Out parameters will be populated before on_displays_changed returns. |
| type AddedDisplayInfo = struct { |
| is_hdmi_out bool; |
| is_standard_srgb_out bool; |
| |
| audio_format_count uint32; |
| |
| /// All strings are null-terminated. |manufacturer_id| is guaranteed to have |
| /// length 3, all other strings may be empty. |
| manufacturer_id string:4; |
| /// non-null |
| manufacturer_name string:MAX; |
| /// null-terminated |
| monitor_name string:14; |
| /// null-terminated |
| monitor_serial string:14; |
| |
| // physical horizontal size in millimeters |
| horizontal_size_mm uint32; |
| // physical vertical size in millimeters |
| vertical_size_mm uint32; |
| }; |
| |
| /// The client will not make any `ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL` calls into the device |
| /// during these callbacks. |
| @transport("Banjo") |
| @banjo_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(struct { |
| added_display vector<AddedDisplayArgs>:MAX; |
| removed_display vector<uint64>:MAX; |
| }) -> (struct { |
| display_info vector<AddedDisplayInfo>:MAX; |
| }); |
| |
| /// Events which are invoked when display vsync occurs. |
| /// |
| /// Arguments |
| /// - |timestamp| |
| /// The ZX_CLOCK_MONOTONIC timestamp at which the vsync occurred. |
| /// - |config_stamp| |
| /// The config stamp of the latest configuration that is currently |
| /// fully applied to all the layers of the display with `display_id`. |
| /// If none of the configurations are currently fully applied to |
| /// this display, a null value will be passed to the driver. |
| /// Note that an `ApplyConfiguration()` call may contain multiple |
| /// configurations with a certain `config_stamp`; Only the application |
| /// status of the configuration with ID `display_id` is related. |
| /// |
| /// The driver must call this function for all vsync events, even if the |
| /// display has no images displayed. |
| OnDisplayVsync(struct { |
| display_id uint64; |
| timestamp zx.time; |
| config_stamp box<ConfigStamp>; |
| }) -> (); |
| |
| GetAudioFormat(struct { |
| display_id uint64; |
| fmt_idx uint32; |
| }) -> (struct { |
| s zx.status; |
| fmt fuchsia.hardware.audiotypes.AudioTypesAudioStreamFormatRange; |
| }); |
| }; |
| |
| type Alpha = strict enum : uint8 { |
| DISABLE = 0; |
| PREMULTIPLIED = 1; |
| HW_MULTIPLY = 2; |
| }; |
| |
| /// Rotations are applied counter-clockwise, and are applied before reflections. |
| type FrameTransform = strict enum : 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; |
| }; |
| |
| type Frame = struct { |
| /// (|x_pos|, |y_pos|) specifies the position of the upper-left corner |
| /// of the frame. |
| x_pos uint32; |
| y_pos uint32; |
| width uint32; |
| height uint32; |
| }; |
| |
| type PrimaryLayer = struct { |
| 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_mode Alpha; |
| alpha_layer_val float32; |
| |
| transform_mode FrameTransform; |
| |
| /// 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. |
| src_frame 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. |
| dest_frame Frame; |
| }; |
| |
| type CursorLayer = struct { |
| 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. |
| x_pos int32; |
| y_pos int32; |
| }; |
| |
| type ColorLayer = struct { |
| format ZxPixelFormat; |
| /// The color to use for the layer. The color is little-endian, and is |
| /// guaranteed to be of the appropriate size. |
| color vector<uint8>:MAX; |
| }; |
| |
| /// Types of layers. |
| type LayerType = strict enum : uint32 { |
| PRIMARY = 0; |
| CURSOR = 1; |
| COLOR = 2; |
| }; |
| |
| type LayerConfig = strict union { |
| 1: primary PrimaryLayer; |
| 2: cursor CursorLayer; |
| 3: color ColorLayer; |
| }; |
| |
| type Layer = struct { |
| type LayerType; |
| /// z_index of the layer. See |check_configuration| and |apply_configuration|. |
| z_index uint32; |
| cfg LayerConfig; |
| }; |
| |
| /// constants for display_config's mode_flags field |
| type ModeFlag = strict enum : uint32 { |
| VSYNC_POSITIVE = 0x1; |
| HSYNC_POSITIVE = 0x2; |
| INTERLACED = 0x4; |
| ALTERNATING_VBLANK = 0x8; |
| DOUBLE_CLOCKED = 0x10; |
| }; |
| |
| /// The video parameters which specify the display mode. |
| type DisplayMode = struct { |
| 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 uint32; |
| /// A bitmask of MODE_FLAG_* values |
| flags uint32; |
| }; |
| |
| type ColorConversion = strict enum : 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; |
| }; |
| |
| type DisplayConfig = struct { |
| /// the display id to which the configuration applies |
| display_id uint64; |
| |
| mode DisplayMode; |
| |
| /// Bitmask of COLOR_CONVERSION_* flags |
| cc_flags uint32; |
| /// 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. |
| cc_preoffsets array<float32, 3>; |
| cc_coefficients array<array<float32, 3>, 3>; |
| cc_postoffsets array<float32, 3>; |
| |
| @mutable |
| @out_of_line_contents |
| layer vector<Layer>:MAX; |
| |
| /// Flag to indicate valid gamma table |
| gamma_table_present bool; |
| /// Flag to indicate whether display driver should re-apply gamma correction table to hardware |
| apply_gamma_table bool; |
| /// Gamma Table (Red, Green and Blue) |
| @mutable |
| gamma_red vector<float32>:MAX; |
| @mutable |
| gamma_green vector<float32>:MAX; |
| @mutable |
| gamma_blue vector<float32>:MAX; |
| }; |
| |
| type ConfigDisplay = strict enum : 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; |
| }; |
| |
| type Client = strict enum : 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 cannot control the display gamma, and must accept |
| /// the uncalibrated output. Clients are expected to produce linear |
| /// buffers, and as such they cannot perform software gamma |
| /// correction. |
| GAMMA = 0x100; |
| }; |
| |
| /// The client guarantees that check_configuration and apply_configuration are always |
| /// made from a single thread. The client makes no other threading guarantees. |
| @transport("Banjo") |
| @banjo_layout("ddk-protocol") |
| protocol DisplayControllerImpl { |
| /// The function will only be called once, and it will be called before any other |
| /// functions are called. |
| SetDisplayControllerInterface(resource struct { |
| intf client_end:DisplayControllerInterface; |
| }) -> (); |
| |
| /// Imports an image from a buffer collection into the driver. The driver should set |
| /// image->handle. |
| ImportImage(struct { |
| @in_out |
| image Image; |
| collection ZxUnownedHandle; |
| index uint32; |
| }) -> (struct { |
| s zx.status; |
| }); |
| |
| /// 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(struct { |
| @in_out |
| 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(struct { |
| @inner_pointer |
| display_config vector<DisplayConfig>:MAX; |
| }) -> (struct { |
| display_cfg_result uint32; |
| @callee_allocated |
| layer_cfg_result vector<uint32>:MAX; |
| }); |
| |
| /// 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. |
| /// |
| /// `config_stamp` is a non-zero unique stamp to identify each configuration. |
| /// Callers must guarantee that `config_stamp` is unique for each `ApplyConfiguration()` |
| /// call. |
| /// |
| /// The driver must not retain references to the configuration after this function returns. |
| ApplyConfiguration(struct { |
| @inner_pointer |
| display_config vector<DisplayConfig>:MAX; |
| config_stamp ConfigStamp; |
| }) -> (); |
| |
| /// Set ELD for one display. |
| /// |
| /// This method is called independently from the CheckConfiguration and ApplyConfiguration |
| /// methods. The display_id may be unconfigured at the time this method is called. |
| /// raw_eld is the ELD raw data formatted according to the HDA specification version 1.0a |
| /// section 7.3.3.34.1. |
| /// https://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/high-definition-audio-specification.pdf |
| /// The driver must not retain references to the ELD after this function returns. |
| SetEld(struct { |
| display_id uint64; |
| raw_eld vector<uint8>:MAX; |
| }) -> (); |
| |
| // Connects the handle to the sysmem service. |
| GetSysmemConnection(resource struct { |
| sysmem_handle zx.handle:CHANNEL; |
| }) -> (struct { |
| s zx.status; |
| }); |
| |
| // Set sysmem buffer collection contraints needed to ensure an image can be imported with config |
| // |config| on the fuchsia.sysmem.BufferCollection handle |collection|. |
| SetBufferCollectionConstraints(struct { |
| config Image; |
| collection ZxUnownedHandle; |
| }) -> (struct { |
| s zx.status; |
| }); |
| |
| // Power off/on the display panel. Newly added displays are turned on by default. |
| // |
| // Displays that are turned off will not deliver VSync events. |
| // This may include the vsync event for the most recently applied |
| // config. |
| SetDisplayPower(struct { |
| display_id uint64; |
| power_on bool; |
| }) -> (struct { |
| s zx.status; |
| }); |
| }; |