blob: 72cb34fbefa54a20e1a90aab577569ee808eb4e3 [file] [log] [blame] [edit]
// Copyright 2023 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.engine;
using fuchsia.hardware.display.types;
using fuchsia.images2;
using fuchsia.math;
using fuchsia.sysmem2;
using zx;
type ColorConversion = strict bits : 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;
};
/// Constants for display_config's mode_flags field
type ModeFlag = strict bits : uint32 {
VSYNC_POSITIVE = 0x1;
HSYNC_POSITIVE = 0x2;
INTERLACED = 0x4;
ALTERNATING_VBLANK = 0x8;
DOUBLE_CLOCKED = 0x10;
};
/// The video parameters which specify the display mode.
/// TODO(https://fxbug.dev/42085013): Replace this type with something more similar
/// to //src/graphics/display/lib/api-types-cpp/display-timing.h.
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;
flags ModeFlag;
};
type Layer = struct {
/// The display image (composited output) region occupied by the layer.
///
/// The rectangle uses the Vulkan coordinate space. The origin is at the
/// display's top-left corner. The X axis points to the right, and the Y axis
/// points downwards.
///
/// A valid layer definition requires a valid non-empty display destination
/// rectangle that is entirely contained within the display. A rectangle is
/// empty iff its size is 0x0 (width and height are both zero).
display_destination fuchsia.math.RectU;
/// The associated image region whose pixels are drawn by the layer.
///
/// The rectangle uses the Vulkan coordinate space. The origin is at the
/// image's top-left corner. The X axis points to the right, and the Y axis
/// points downwards.
///
/// A valid layer definition requires a valid image source rectangle that is
/// entirely contained within the image. If the rectangle is empty, the
/// hardware is configured to skip fetching image pixels, and instead fill
/// `display_destination` using a constant color, which is `fallback_color`
/// defined below.
///
/// Hardware image scaling is requested implicitly, when the region's
/// dimensions differ from the dimensions of `display_destination`. Some
/// display hardware may not support scaling. All display hardware has
/// limitations in scaling support.
image_source fuchsia.math.RectU;
/// The image whose pixels are drawn by this layer.
///
/// If valid, the image ID must be the result of a successful call to
/// [`fuchsia.hardware.display.engine/Engine.ImportImage`].
///
/// A valid layer definition requires that the image ID is invalid iff
/// `image_source` specifies an empty rectangle.
///
/// To allow for future evolution, Layer consumers must ignore the image ID
/// if `image_source` specifies an empty rectangle.
///
/// Hardware image cropping is requested implicitly, when the source
/// region's dimensions differ from the image's dimensions. Some display
/// hardware may not support cropping.
image_id ImageId;
/// The arguments used to import `image_id`.
///
/// If `image_id` is valid, the metadata must equal the argument passed
/// to [`fuchsia.hardware.display.engine/Engine.ImportImage`].
///
/// A valid layer definition requires that the metadata is valid. A valid
/// layer definition requires that the metadata specifies an empty (0x0)
/// image with linear tiling if `image_source` specifies an empty rectangle.
image_metadata fuchsia.hardware.display.types.ImageMetadata;
/// Fallback when the pixel data for the layer's image cannot be retrieved.
///
/// A valid layer definition requires that the color is valid.
///
/// If `image_source` specifies an empty region, the hardware is configured
/// to fill the layer's pixels using this color. Conceptually, the source
/// image's pixel data will never be available for the image.
///
/// The hardware may also use this color as a last resort for situations
/// such as buffer underruns, when the pixel data for the layer's image
/// cannot be retrieved fast enough to meet the display connection's timing
/// requirements.
fallback_color fuchsia.hardware.display.types.Color;
/// If `alpha_mode` is `AlphaMode.DISABLE`, the layer is opaque and
/// `alpha_layer_val` is ignored.
///
/// If `alpha_mode` is `AlphaMode.PREMULTIPLIED` or `HW_MULTIPLY`, the
/// alpha used when blending is determined by the product of
/// `alpha_layer_val` and any per-pixel alpha.
///
/// Additionally, if `alpha_mode` is `AlphaMode.PREMULTIPLIED`, then the
/// hardware must premultiply the color channel with `alpha_layer_val`
/// before blending.
///
/// `alpha_layer_val` must be in the range [0, 1].
alpha_mode fuchsia.hardware.display.types.AlphaMode;
alpha_layer_val float32;
/// Applied to the input image pixels specified by `image_source`.
///
/// `display_destination` must account for image dimensions changes caused
/// by rotations. For example, rotating a 600x300 pixel image by 90 degrees
/// would specify 300x600 pixel dimensions in `display_destination`.
///
/// A valid layer definition requires that the transformation is the
/// identity transformation if `image_source` specifies an empty rectangle.
///
/// To allow for future evolution, Layer consumers must ignore the
/// transformation if `image_source` specifies an empty rectangle.
image_source_transformation fuchsia.hardware.display.types.CoordinateTransformation;
};
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>;
/// Valid display configurations have at least one layer.
layer vector<Layer>:MAX;
};
// An E-EDID can contain up to 256 data blocks, each of which contains 128
// bytes. So it can contain up to 256 * 128 = 32768 bytes of data.
const MAX_COUNT_EDID_BYTES uint32 = 32768;
const MAX_COUNT_DISPLAY_PIXEL_FORMATS uint32 = fuchsia.sysmem2.MAX_COUNT_PIXEL_FORMAT_AND_MODIFIERS;
const MAX_COUNT_DISPLAY_INFO_PREFERRED_MODES uint32 = 4;
// TODO(https://fxbug.dev/42150719): Convert RawDisplayInfo to a table, for
// extensibility. The comments about empty vectors will mention members not
// being present, instead.
/// Collects the information reported by the engine hardware about a display.
///
/// The data representation closely matches the formats used by display engine
/// hardware. The display coordinator is responsible for parsing these formats
/// and converting the information into forms that are more suitable for
/// higher-level software.
type RawDisplayInfo = resource struct {
display_id uint64;
/// Operational modes known to be supported by the display.
///
/// When this vector is not empty, the display modes here take precedence
/// over the modes retrieved from `edid_bytes`. The modes are ordered by
/// suitability. The first mode is most preferred. The display modes here
/// may overlap with the modes encoded in the display's E-EDID.
///
/// Drivers for internal (embedded) displays typically report the display's
/// only supported operational mode in this member. Drivers that support
/// seamless display handoff from a bootloader report the display's initial
/// mode in this member.
preferred_modes vector<DisplayMode>:<MAX_COUNT_DISPLAY_INFO_PREFERRED_MODES>;
/// Display capabilities, encoded using the E-EDID standard.
///
/// E-EDID (Enhanced Extended Display Identification Data) is a VESA
/// standard that describes display capabilities as a series of 128-byte
/// data blocks.
///
/// When this vector is not empty and contains valid E-EDID information, it
/// is used as the definitive description of the display's capabilities.
///
/// Drivers for external (connected) displays use this member to report the
/// display's E-EDID, when it is exposed in a non-standard manner.
edid_bytes vector<uint8>:<MAX_COUNT_EDID_BYTES>;
/// A list of pixel formats supported by the display.
///
/// The pixel formats modes are ordered by suitability. The first format is
/// most preferred.
pixel_formats vector<fuchsia.images2.PixelFormat>:MAX_COUNT_DISPLAY_PIXEL_FORMATS;
};
/// Receives events on a display engine.
///
/// An [`EngineListener`] may be registered to the engine through the [`Engine`]
/// protocol before it receives any events.
///
/// This protocol only consists of one-way calls.
///
/// This protocol is `open` while under development.
/// TODO(https://fxbug.dev/316631158): Make it `closed` once the API is
/// stabilized.
@transport("Driver")
open protocol EngineListener {
/// Called when a display is connected.
///
/// Display Engine drivers must emit this event for all displays connected
/// prior to initialization.
flexible OnDisplayAdded(resource struct {
display_info RawDisplayInfo;
});
/// Called when a display is removed.
///
/// `display_id` must be a valid display ID that occurred in a previous
/// `OnDisplayAdded()` event.
///
/// Display Engine drivers must have finished accessing all images which
/// were on the removed display before calling `OnDisplayRemoved()`.
flexible OnDisplayRemoved(struct {
display_id uint64;
});
/// Called at the start of each display device's vertical synchronization
/// (Vsync) period, regardless of whether the display has applied any
/// configuration.
///
/// 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.
flexible OnDisplayVsync(struct {
display_id uint64;
timestamp zx.Time;
config_stamp ConfigStamp;
});
/// Called when a previous display capture triggered by
/// [`Engine.StartCapture`] is completed.
///
/// The display engine only emits [`OnCaptureComplete`] events if capture is
/// supported. Capture support is reported in
/// [`EngineInfo.is_capture_supported`] returned by
/// [`Engine.CompleteCoordinatorConnection`].
flexible OnCaptureComplete();
};
/// Upper bound on the number of layers in one display configuration.
///
/// This limit applies to [`EngineInfo.max_layer_count`]. The value reflects
/// design assumptions in the display stack. The value may be increased in the
/// future.
const MAX_ALLOWED_MAX_LAYER_COUNT uint16 = 8;
/// Upper bound on the number of concurrently connected displays.
///
/// This limit applies to [`EngineInfo.max_connected_display_count`]. The value
/// reflects design assumptions in the display stack. The value will be
/// increased in the future, when the display stack supports multi-display
/// systems.
const MAX_ALLOWED_MAX_CONNECTED_DISPLAY_COUNT uint16 = 1;
/// Static description of the hardware managed by a display engine driver.
///
/// The information here is assumed to remain immutable during a boot cycle.
type EngineInfo = struct {
/// Maximum number of layers in one display configuration.
///
/// The engine driver will never support a display configuration where the
/// total number of layers (across all displays) exceeds this value.
///
/// The value may reflect hardware limitations, such as the number of image
/// data fetch units in the hardware, or driver implementation limitations.
///
/// In valid instances, the value is positve and at most
/// [`MAX_ALLOWED_MAX_LAYER_COUNT`].
max_layer_count uint16;
/// Maximum number of displays that can be connected at once.
///
/// The number of connected displays reported by the display engine
/// will never exceed this value.
///
/// The value may reflect hardware limitations, such as the number of
/// digital display interfaces in the hardware, or driver implementation
/// limitations.
///
/// In valid instances, the value is positve and at most
/// [`MAX_ALLOWED_MAX_CONNECTED_DISPLAY_COUNT`].
max_connected_display_count uint16;
/// True if the driver and hardware implement display capture.
is_capture_supported bool;
};
/// This protocol is `open` while under development.
/// TODO(b/316631158): We should make it `closed` once the API is stabilized.
@discoverable
@transport("Driver")
open protocol Engine {
/// Starts the information flow from the engine driver to the Coordinator.
///
/// Must be called exactly once, before all the other calls below.
flexible CompleteCoordinatorConnection(resource struct {
/// Receives events from the engine driver.
engine_listener client_end:EngineListener;
}) -> (struct {
engine_info EngineInfo;
});
/// Sets up this driver to use a Sysmem BufferCollection.
///
/// Fails with ZX_ERR_INTERNAL if any error occurs during the setup process,
/// which mainly consists of communicating with the Sysmem service.
flexible ImportBufferCollection2(resource struct {
/// Identifies the imported BufferCollection.
///
/// The ID must not be invalid, and must not be already assigned.
///
/// The ID is assigned to the imported collection from the moment this
/// call is issued until the moment this call fails, or until the moment
/// a call to [`Engine.ReleaseBufferCollection`] with the same ID
/// completes.
buffer_collection_id BufferCollectionId;
/// Identifies the BufferCollection to the Sysmem service.
collection_token client_end:fuchsia.sysmem2.BufferCollectionToken;
}) -> () error zx.Status;
/// Releases the resources needed to use a Sysmem BufferCollection.
///
/// TODO(https://fxbug.dev/394954078): Make this method infallible.
flexible ReleaseBufferCollection(struct {
/// Identifies a previously imported BufferCollection.
///
/// The ID must be assigned to an imported BufferCollection, via a
/// successful call to [`Enigne.ImportBufferCollection2`].
///
/// When the call completes, the ID is no longer assigned to the
/// BufferCollection, and can be used in a future call to
/// [`Engine.ImportBufferCollection2`].
collection_id uint64;
}) -> () error zx.Status;
/// Sets up the hardware to use a buffer as a display image data source.
///
/// Fails with ZX_ERR_SHOULD_WAIT if Sysmem reports that the
/// BufferCollection's buffers are not yet allocated. Fails with
/// ZX_ERR_INTERNAL if any other error occurs while obtaining the buffer
/// from the Sysmem service.
flexible 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 fuchsia.hardware.display.types.ImageMetadata;
/// Identifies a previously imported BufferCollection.
///
/// The ID must be assigned to an imported BufferCollection, via a
/// successful [`DisplayEnigne.ImportBufferCollection`] call.
buffer_id BufferId;
}) -> (struct {
/// Assigned to the imported image buffer.
///
/// The ID is assigned to the imported image from the moment the call
/// succeeds until the moment a call to [`Engine.ReleaseImage`] with the
/// same ID completes.
image_id ImageId;
}) error zx.Status;
/// Sets up the hardware to use a buffer for display capture output.
///
/// This call must only be issued when the engine driver supports capture.
/// Capture support is reported in [`EngineInfo.is_capture_supported`]
/// returned by [`Engine.CompleteCoordinatorConnection`].
///
/// Fails with ZX_ERR_SHOULD_WAIT if Sysmem reports that the
/// BufferCollection's buffers are not yet allocated. Fails with
/// ZX_ERR_INTERNAL if any other error occurs while obtaining the buffer
/// from the Sysmem service.
flexible ImportImageForCapture(struct {
/// Identifies a previously imported BufferCollection.
///
/// The ID must be assigned to an imported BufferCollection, via a
/// successful [`DisplayEnigne.ImportBufferCollection`] call.
buffer_id BufferId;
}) -> (struct {
/// Assigned to the imported capture image buffer.
///
/// The ID is assigned to the imported capture image from the moment the
/// call succeeds until the moment a call to
/// [`DisplayEngine.ReleaseImageCapture`] with the same ID completes.
capture_image_id ImageId;
}) error zx.Status;
/// Releases resources for using a buffer as a display image data source.
flexible ReleaseImage(struct {
/// Identifies a previously imported display image data source buffer.
///
/// The ID must be assigned to an imported image buffer, via a
/// successful [`DisplayEngine.ImportImage`] call.
///
/// The buffer must not be used by a display configuration that is
/// applied or waiting to be applied.
///
/// When the call completes, the ID is no longer assigned to the
/// imported image. The ID may be reused by a future call to
/// [`Engine.ImportImage`].
image_id ImageId;
});
/// Verifies that a configuration can be presented on a display.
///
/// The verification result must be valid for any configuration derived from
/// the given configuration.
///
/// A derived configuration can be obtained from another configuration by
/// applying one or more of the following operations. The list of operations
/// is expected to slowly grow over time.
///
/// * Replace an image ID with another image ID. The two IDs must identify
/// images that were imported with the same metadata.
flexible CheckConfiguration(struct {
/// The display configuration to be validated.
///
/// TODO(https://fxbug.dev/399954526): Update the contract to cover
/// configurations that reference an unassigned DisplayId.
display_config DisplayConfig;
}) -> () error fuchsia.hardware.display.types.ConfigResult;
/// Submits a configuration for future presentation on a display.
flexible ApplyConfiguration(struct {
/// The display configuration to be submitted for presentation.
///
/// Must be derived from a configuration that was validated via
/// [`Engine.CheckConfiguration`]. That call's documentation includes
/// the definition of a derived configuration.
///
/// While the configuration is transmitted to the display, the driver
/// will hold references to the image whose handles are included in the
/// configuration.
///
/// TODO(https://fxbug.dev/399954526): Update the contract to cover
/// configurations that reference an unassigned DisplayId.
display_config DisplayConfig;
/// Identifies the configuration to be applied. Must be a valid value.
/// Must be strictly increasing across calls.
config_stamp ConfigStamp;
}) -> ();
/// Conveys the display hardware's limitations on image buffers to sysmem.
///
/// Fails with ZX_ERR_INTERNAL if any error occurs while communicating with
/// the the Sysmem service.
flexible SetBufferCollectionConstraints(struct {
/// Describes how the image buffers will be used.
///
/// After this call succeeds, calls to [`Engine.ImportImage`] or
/// [`Engine.ImportImageForCapture`] that are consistent with the
/// usage declared here are expected to succeed.
usage fuchsia.hardware.display.types.ImageBufferUsage;
/// Identifies a previously imported BufferCollection.
///
/// The ID must be assigned to an imported BufferCollection, via a
/// successful [`DisplayEnigne.ImportBufferCollection`] call.
buffer_collection_id BufferCollectionId;
}) -> () error zx.Status;
/// Sets a display's power state.
flexible SetDisplayPower(struct {
/// Identifies the display whose power state is changed.
///
/// Must be a valid ID assigned to a display connected to the system.
///
/// TODO(https://fxbug.dev/399954526): Update the contract to cover
/// configurations that reference an unassigned DisplayId.
display_id uint64;
/// The display's new power state.
///
/// Displays are powered on when they are connected to the system.
///
/// When a display is powered off, it does not deliver VSync events.
power_on bool;
}) -> () error zx.Status;
/// Set the minimum value of RGB channels.
///
/// Fails with ZX_ERR_NOT_SUPPORTED if RGB clamping is not supported. Most
/// engine drivers are expected to fail in this manner.
//
// 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 method when stabilizing the
// Engine protocol API.
flexible SetMinimumRgb(struct {
/// Must be >= 0 and <= 255.
minimum_rgb uint8;
}) -> () error zx.Status;
/// Starts a display capture operation.
///
/// The engine driver must not be performing another capture operation. The
/// capture operation is considered to be in-progress from the moment when a
/// successful call to [`DisplayEngine.StartCapture`] is issued, until the
/// moment when the engine driver issues a call to
/// [`DisplayEngineListener.OnCaptureComplete`].
///
/// This call must only be issued when the engine driver supports capture.
/// Capture support is reported in [`EngineInfo.is_capture_supported`]
/// returned by [`Engine.CompleteCoordinatorConnection`].
///
/// This call must only be issued after a configuration has been applied to
/// the display.
///
/// Fails with ZX_ERR_IO_REFUSED if the display engine hardware failed to
/// start the capture. This error could point to a systemic issue, such as
/// the system having insufficient DRAM bandwidth to capture the currently
/// applied display configuration. This error could also be caused by a
/// temporary hardware failure.
flexible StartCapture(struct {
/// Identifies a previously imported display capture output buffer.
///
/// The ID must be assigned to an imported capture output buffer, via a
/// successful [`Engine.ImportImageForCapture`] call.
///
/// If the call succeeds, the display capture output buffer is used by
/// the in-progress display capture operation. While this operation is
/// in-progress, the buffer must not be passed in calls to
/// [`Engine.StartCapture`] or [`Engine.ReleaseCapture`].
///
/// Once the capture operation completes, the buffer will store the
/// image data captured from the display.
capture_image_id ImageId;
}) -> () error zx.Status;
/// Releases resources for using a buffer for display capture output.
///
/// This call must only be issued when the engine driver supports capture.
/// Capture support is reported in [`EngineInfo.is_capture_supported`]
/// returned by [`Engine.CompleteCoordinatorConnection`].
///
/// TODO(https://fxbug.dev/394954078): Make this method infallible.
flexible ReleaseCapture(struct {
/// Identifies a previously imported display capture output buffer.
///
/// The ID must be assigned to an imported display capture output
/// buffer, via a successful [`Engine.ImportImageForCapture`] call.
///
/// The display capture output buffer must not be used by an in-progress
/// display capture operation. See [`DisplayEngine.StartCapture`] for
/// the definition of an in-progress display capture operation.
///
/// When the call completes, the ID is no longer assigned to the display
/// capture output buffer. The ID may be reused by a future call to
/// [`Engine.ImportImageForCapture`].
capture_image_id ImageId;
}) -> () error zx.Status;
// A noop method with a response from the server that should be used
// by clients who optionally use this library to determine availability.
flexible IsAvailable() -> ();
};
service Service {
engine client_end:Engine;
};