blob: 6fa9ceb1818ea00738de94afcb3fcbdd612a66ec [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 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.
// Intentionally left some gap between SIMPLE and CAPTURE.
/// The image is used for capture
/// 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;
/// 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
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.
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 {
/// Rotations are applied counter-clockwise, and are applied before reflections.
type FrameTransform = strict enum : uint32 {
ROT_90 = 3;
ROT_180 = 4;
ROT_270 = 5;
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 {
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 {
/// 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
/// If set, use the identity matrix for the color conversion coefficients
/// If set, use the 0 vector for the color conversion postoffset
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>;
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)
gamma_red vector<float32>:MAX;
gamma_green vector<float32>:MAX;
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.
/// 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.
type Client = strict enum : 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 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.
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 {
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 {
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 {
display_config vector<DisplayConfig>:MAX;
}) -> (struct {
display_cfg_result uint32;
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 {
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
/// 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;