| // 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.i2cimpl; |
| using zx; |
| |
| type ImageTilingType = strict enum : uint32 { |
| /// The image is linear and VMO backed. |
| LINEAR = 0; |
| |
| // Intentionally left some gap between LINEAR 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 type conveys information about what is providing the pixel data. If this is not |
| /// IMAGE_TILING_TYPE_LINEAR, 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. |
| tiling_type uint32; |
| |
| /// A driver-defined handle to the image. Each handle must be unique. |
| handle uint64; |
| }; |
| |
| /// The intended usage for a sysmem BufferCollection holding image buffers. |
| /// |
| /// Each buffer in the collection will store a single image, which is intended |
| /// to be used as described below. |
| type ImageBufferUsage = struct { |
| /// Specifies how individual pixels are arranged in an image buffer. |
| /// |
| /// See [`fuchsia.hardware.display.types/ImageTilingTypeIdValue`]. |
| tiling_type uint32; |
| }; |
| |
| /// Describes how an image is stored in a buffer of a sysmem BufferCollection. |
| /// |
| /// The buffer is dedicated to storing a single image. The properties below are |
| /// needed for decoding the image from the buffer. |
| // TODO(https://fxbug.dev/329163718): sysmem already has some of the information |
| // here. Prune this structure, replacing members with querying properties on the |
| // associated sysmem BufferCollection. |
| type ImageMetadata = struct { |
| /// The width and height of the image in pixels. |
| width uint32; |
| height uint32; |
| |
| /// Specifies how individual pixels are arranged in an image buffer. |
| /// |
| /// See [`fuchsia.hardware.display.types/ImageTilingTypeIdValue`]. |
| tiling_type uint32; |
| }; |
| |
| const INVALID_DISPLAY_ID uint64 = 0; |
| const INVALID_ID uint64 = 0; |
| |
| /// Indicates that a ConfigStamp is invalid. |
| const INVALID_CONFIG_STAMP_VALUE uint64 = 0; |
| |
| /// A unique stamp representing a unique set of display configuration. |
| /// The value is always strictly increasing in chronological order. |
| type ConfigStamp = struct { |
| /// For valid configurations, the value should not be equal to |
| /// `INVALID_CONFIG_STAMP_VALUE`. |
| value uint64; |
| }; |
| |
| /// The capabilities of a display panel. |
| type Panel = strict resource union { |
| /// The i2c bus to use to read this display's EDID. |
| 1: i2c client_end:fuchsia.hardware.i2cimpl.I2cImpl; |
| |
| /// Hard-coded display configuration. |
| /// |
| /// Can be used when the device does not implement EDID, |
| /// or when the driver needs to override the EDID contents. |
| 2: mode DisplayMode; |
| }; |
| |
| type PanelCapabilitiesSource = strict enum { |
| /// The panel uses Extended Display Identification Data (EDID) over the |
| /// I2C bus to communicate its capabilities. |
| EDID_I2C = 1; |
| |
| /// The panel provides a DisplayMode struct to express its capabilities. |
| DISPLAY_MODE = 2; |
| }; |
| |
| /// A structure containing information a connected display. |
| type AddedDisplayArgs = resource struct { |
| display_id uint64; |
| |
| /// If `panel_capabilities_source` is `EDID_I2C`, `panel.i2c` must be a |
| /// valid I2c client. The rest fields in `panel` are ignored. |
| /// |
| /// If `panel_capabilities_source` is `DISPLAY_MODE`, `panel.display_mode` |
| /// must be valid. The rest fields in `panel` are ignored. |
| panel_capabilities_source PanelCapabilitiesSource; |
| panel Panel; |
| |
| /// A list of pixel formats supported by the display. The first entry is the |
| /// preferred pixel format. |
| pixel_format vector<FuchsiaImages2PixelFormatEnumValue>:MAX; |
| }; |
| |
| /// The client will not make any `ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL` calls into the device |
| /// during these callbacks. |
| @transport("Banjo") |
| @banjo_layout("ddk-interface") |
| closed 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. |
| strict OnDisplaysChanged(resource struct { |
| added_displays vector<AddedDisplayArgs>:MAX; |
| removed_display_ids vector<uint64>: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 as close as possible to the start of |
| /// every display's VSync period, even if the display has no images |
| /// displayed. |
| strict OnDisplayVsync(struct { |
| display_id uint64; |
| timestamp zx.Time; |
| config_stamp box<ConfigStamp>; |
| }) -> (); |
| |
| /// Called when the previous display capture triggered by |
| /// [`DisplayControllerImpl.StartCapture`] is completed. |
| /// |
| /// Each `OnCaptureComplete` call must be paired with a previous successful |
| /// call to [`DisplayControllerImpl.StartCapture`]. |
| strict OnCaptureComplete() -> (); |
| }; |
| |
| 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 { |
| /// The result of a successful ImportImage() call. |
| image_handle uint64; |
| |
| /// Must match the ImportImage() argument for `image_handle`. |
| image_metadata ImageMetadata; |
| |
| /// 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 ColorLayer = struct { |
| /// The format of `color` bytes. |
| format FuchsiaImages2PixelFormatEnumValue; |
| |
| /// The color to use for the layer. The color is little-endian, and is |
| /// guaranteed to be of the exact size of one pixel in `format`. |
| color vector<uint8>:MAX; |
| }; |
| |
| /// Types of layers. |
| type LayerType = strict enum : uint32 { |
| PRIMARY = 0; |
| COLOR = 1; |
| }; |
| |
| type LayerConfig = strict union { |
| 1: primary PrimaryLayer; |
| 2: 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_hz int64; |
| 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 flags defined in the ColorConversion enum. |
| 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>; |
| |
| layer vector<Layer>:MAX; |
| }; |
| |
| type ConfigCheckResult = 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; |
| }; |
| |
| /// Contains client operations needed on a Layer to make it supported by |
| /// the display device. There may be multiple operations to be applied on a |
| /// single Layer. |
| /// |
| /// Individual bit positions map to the values of the FIDL enum |
| /// [`fuchsia.hardware.display.types/ClientCompositionOpcode`]. |
| type ClientCompositionOpcode = strict bits : 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. |
| @transport("Banjo") |
| @banjo_layout("ddk-protocol") |
| closed protocol DisplayControllerImpl { |
| /// The function will only be called once, and it will be called before any other |
| /// functions are called. |
| strict SetDisplayControllerInterface(resource struct { |
| intf client_end:DisplayControllerInterface; |
| }) -> (); |
| |
| /// Resets the DisplayControllerInterface client (if set) and will not call |
| /// DisplayControllerInterface callback methods anymore. |
| strict ResetDisplayControllerInterface() -> (); |
| |
| /// Import a sysmem buffer collection token. |
| /// |
| /// Returns ZX_ERR_ALREADY_EXISTS if `collection_id` is in use. |
| strict ImportBufferCollection(resource struct { |
| collection_id uint64; |
| // TODO(https://fxbug.dev/42171012): This is a client end channel of FIDL protocol |
| // fuchsia.sysmem.BufferCollectionToken. The raw channel needs to be |
| // replaced with FIDL client end once banjo to FIDL migration finishes. |
| collection_token zx.Handle:CHANNEL; |
| }) -> (struct { |
| s zx.Status; |
| }); |
| |
| /// Release an imported buffer collection. |
| /// |
| /// Returns ZX_ERR_NOT_FOUND if `collection_id` isn't successfully imported. |
| strict ReleaseBufferCollection(struct { |
| collection_id uint64; |
| }) -> (struct { |
| s zx.Status; |
| }); |
| |
| /// Imports an image from a imported BufferCollection into the driver. |
| /// |
| /// Returns ZX_OK and the imported image's handle, if the image is imported |
| /// succesfully. |
| /// Returns ZX_ERR_NOT_FOUND if `collection_id` is not imported yet. |
| /// Returns ZX_ERR_SHOULD_WAIT if the buffer collection is not already |
| /// allocated. |
| strict ImportImage(struct { |
| // TODO(https://fxbug.dev/329163718): Some of the information in |
| // `image_metadata` was negotiated by sysmem. The display coordinator or |
| // engine drivers should read that information directly from sysmem. |
| image_metadata ImageMetadata; |
| collection_id uint64; |
| index uint32; |
| }) -> (struct { |
| s zx.Status; |
| image_handle uint64; |
| }); |
| |
| /// Import BufferCollection backed VMO pointed to by `index`. |
| /// Importing the VMO usually involves pinning the VMO and updating display |
| /// controller hardware registers with the physical address of the VMO to be |
| /// used for capture. Returns out_capture_handle which maps to the allocated |
| /// resource. |
| /// |
| /// If display capture is not supported, returns ZX_ERR_NOT_SUPPORTED and |
| /// the value of `capture_handle` will be undefined. |
| /// |
| /// Returns ZX_ERR_NOT_FOUND if `collection_id` is not imported yet. |
| /// Returns ZX_ERR_SHOULD_WAIT if the buffer collection is not already |
| /// allocated. |
| strict ImportImageForCapture(struct { |
| collection_id uint64; |
| index uint32; |
| }) -> (struct { |
| s zx.Status; |
| capture_handle uint64; |
| }); |
| |
| /// 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. |
| strict ReleaseImage(struct { |
| image_handle uint64; |
| }) -> (); |
| |
| /// 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. |
| /// |
| /// `config_check_result` should be set to a CONFIG_DISPLAY_* error if the combination of |
| /// display modes is not supported. |
| /// |
| /// `client_composition_opcodes` are per-layer client operations |
| /// to make the layer configuration supported by the display hardware. If |
| /// the `config_check_result` is not `CONFIG_CHECK_RESULT_OK`, the values of |
| /// `client_composition_opcodes` are undefined and should be ignored by the |
| /// client. |
| /// |
| /// `client_composition_opcodes` is an array with one element for each |
| /// layer in |
| /// each display_config element. The elements map to layers following a |
| /// DFS traversal of a tree where the first-level children are the |
| /// `display_config` elements, and the second-level children are each |
| /// `DisplayConfig`'s layers. |
| /// |
| /// The element ordering matches flattening the array obtained by mapping |
| /// each display_config element to its `DisplayConfig.layers` value: |
| /// [ display 0 layer 0, display 0 layer 1, ..., |
| /// display 1 layer 0, display 1 layer 1, ..., |
| /// display (N-1) layer 0, ..., display (N-1) layer (M-1) ]. |
| /// |
| /// The driver must not retain references to the configuration after this function returns. |
| strict CheckConfiguration(struct { |
| display_config vector<DisplayConfig>:MAX; |
| }) -> (struct { |
| config_check_result ConfigCheckResult; |
| client_composition_opcodes vector<ClientCompositionOpcode>:MAX; |
| }); |
| |
| /// Applies the configuration. |
| /// |
| /// All configurations passed to this function must 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 turning 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. |
| strict ApplyConfiguration(struct { |
| display_config vector<DisplayConfig>:MAX; |
| |
| /// Identifies the configuration to be applied. Must be a valid value. |
| /// Must be strictly increasing across calls. |
| 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. |
| strict SetEld(struct { |
| display_id uint64; |
| raw_eld vector<uint8>:MAX; |
| }) -> (); |
| |
| /// Conveys the display hardware's limitations on image buffers to sysmem. |
| /// |
| /// The sysmem BufferCollection imported with `collection_id` will receive |
| /// constraints representing the display hardware's limitations for image |
| /// buffers that will be used according to `usage`. Once this succeeds, |
| /// calls to ImportImage() or ImportImageForCapture() that are consistent |
| /// with `usage` will not fail. |
| /// |
| /// Returns ZX_ERR_NOT_FOUND if `collection_id` is not imported yet. |
| strict SetBufferCollectionConstraints(struct { |
| usage ImageBufferUsage; |
| collection_id uint64; |
| }) -> (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. |
| strict SetDisplayPower(struct { |
| display_id uint64; |
| power_on bool; |
| }) -> (struct { |
| s zx.Status; |
| }); |
| |
| /// Returns true iff the display engine supports capturing the pixels |
| /// on the display device. |
| strict IsCaptureSupported() -> (struct { |
| is_supported bool; |
| }); |
| |
| /// Starts capture into the resource mapped by capture_handle (non-blocking) |
| /// Only one active capture is allowed at a time. |
| /// A valid image must be displayed during capture. Otherwise unexpected hardware |
| /// behavior might occur. |
| /// Drivers should not leave display hardware in this unexpected state. |
| /// Drivers are expected to stop and/or abort capture if no valid |
| /// image is being displayed. |
| /// |
| /// Returns ZX_ERR_NOT_SUPPORTED if display capture feature is not |
| /// supported. |
| strict StartCapture(struct { |
| capture_handle uint64; |
| }) -> (struct { |
| s zx.Status; |
| }); |
| |
| /// Releases resources allocated by capture_handle. |
| /// Releasing resources from an active capture is not allowed and will cause |
| /// unexpected behavior. |
| /// |
| /// Returns ZX_ERR_NOT_SUPPORTED if display capture feature is not |
| /// supported. |
| strict ReleaseCapture(struct { |
| capture_handle uint64; |
| }) -> (struct { |
| s zx.Status; |
| }); |
| |
| /// Returns true if display capture is supported and the previous capture is |
| /// completed. False otherwise. |
| strict IsCaptureCompleted() -> (struct { |
| is_capture_completed bool; |
| }); |
| |
| /// Set the minimum value of RGB channels. |
| /// |
| /// Returns ZX_ERR_NOT_SUPPORTED if RGB clamping is not supported. |
| // |
| // TODO(https://fxbug.dev/328903017): This is a provisional method meant |
| // to address a hardware issue where RGB channels need to get clamped in |
| // order to reduce backlight bleeding. Revise this API when migrating this |
| // protocol to FIDL. |
| strict SetMinimumRgb(struct { |
| /// Must be >= 0 and <= 255. |
| minimum_rgb uint8; |
| }) -> (struct { |
| s zx.Status; |
| }); |
| }; |