blob: 7a1e98e2153d1e8e07abceedc9e4fbe85da7cbe5 [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.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;
});
};