blob: 7fb86031de3accec17b42b1af64afe46eae7e6ed [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;
using fuchsia.sysmem;
using zx;
// Invalid id for displays, images, and events.
const uint64 invalidId = 0;
enum VirtconMode : uint8 {
INACTIVE = 0; // the virtcon is never visible.
FALLBACK = 1; // the virtcon is visible if there is no primary client.
FORCED = 2; // the virtcon is visible even if there is a primary client.
};
// A display mode configuration.
struct Mode {
// Resolution in pixels.
uint32 horizontal_resolution;
uint32 vertical_resolution;
// Vertical refresh rate in units of (Hz / 100).
uint32 refresh_rate_e2;
// Bitfield of flags defined below which further specify the mode.
uint32 flags;
};
// === Mode flags ===
// Flag for interlaced display modes.
const int32 modeInterlaced = 0x1;
// Info about valid cursor configurations.
struct CursorInfo {
// The width and height of the cursor configuration, in pixels.
uint32 width;
uint32 height;
uint32 pixel_format;
};
const uint32 identifierMaxLen = 128;
// Info contains the information about a particular attached display.
struct Info {
uint64 id;
// Modes supported by the attached display. The first entry is the
// preferred mode.
vector<Mode> modes;
// zx_pixel_format_t constants supported by the attached display. The
// first entry is the preferred mode.
vector<uint32> pixel_format;
// A list of cursor configurations most likely to be accepted by the
// driver. Maybe be empty if there is no hardware support for cursors.
//
// 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.
vector<CursorInfo> cursor_configs;
string:identifierMaxLen manufacturer_name;
string:identifierMaxLen monitor_name;
string:identifierMaxLen monitor_serial;
};
struct ImagePlane {
// Offset from the beginning of the mapped region.
uint32 byte_offset;
uint32 bytes_per_row;
};
// An ImageConfig accompanies image data and defines how to interpret that data.
struct ImageConfig {
// The width and height of the image in pixels.
uint32 width;
uint32 height;
// A zx_pixel_format_t constant that defines the pixel format of the data.
uint32 pixel_format;
// Type conveys information about what is providing the pixel data. If this
// is not typeSimple, it is up to the driver and image producer to
// agree on the meaning of the value through some mechanism outside the scope
// of this API.
uint32 type = typeSimple;
array<ImagePlane>:4 planes;
};
const uint32 typeSimple = 0;
// Rotations are applied counter-clockwise, and are applied before reflections.
enum Transform : uint8 {
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;
};
enum AlphaMode : uint8 {
// Alpha is disabled for the plane (default).
DISABLE = 0;
// Plane alpha is premultiplied.
PREMULTIPLIED = 1;
// Hardware should multiply the alpha and color channels when blending.
HW_MULTIPLY = 2;
};
struct Frame {
// (x_pos, y_pos) specifies the position of the upper-left corner
// of the frame.
uint32 x_pos;
uint32 y_pos;
uint32 width;
uint32 height;
};
enum ClientCompositionOpcode : uint8 {
// The client should convert the corresponding layer to a primary layer.
CLIENT_USE_PRIMARY = 0;
// The client should compose all layers with CLIENT_MERGE_BASE and CLIENT_MERGE_SRC
// into a new, single primary layer at the CLIENT_MERGE_BASE layer's z-order. The
// driver must accept a fullscreen layer with the default pixel format, but may
// accept other layer parameters.
//
// CLIENT_MERGE_BASE will only be set on one layer per display.
CLIENT_MERGE_BASE = 1;
// See CLIENT_MERGE_BASE.
CLIENT_MERGE_SRC = 2;
// The client should provide a new image produced by scaling the source image
// such that the dimensions of the new image's src_frame and dest_frame are
// equal to the dimensions of the current image's dest_frame.
CLIENT_FRAME_SCALE = 3;
// The client should provide a new image produced by clipping the source image
// to the region specified by src_frame.
CLIENT_SRC_FRAME = 4;
// The client should provide a new image produced by applying the desired
// transformation, so that TRANSFORM_IDENTITY can be specified.
CLIENT_TRANSFORM = 5;
// The client should apply the color conversion itself.
CLIENT_COLOR_CONVERSION = 6;
// The client should apply the alpha itself.
CLIENT_ALPHA = 7;
};
enum ConfigResult : uint32 {
OK = 0;
// The requested layer configuration is invalid.
INVALID_CONFIG = 1;
// The requested layer configuration cannot be supported by the hardware. See
// CheckConfig struct for mode details.
UNSUPPORTED_CONFIG = 2;
// The number of requested displays cannot be supported.
TOO_MANY_DISPLAYS = 3;
// The hardware cannot support the requested modes for the displays. The client
// should try a different set of displays or display modes.
UNSUPPORTED_DISPLAY_MODES = 4;
};
struct ClientCompositionOp {
uint64 display_id;
uint64 layer_id;
ClientCompositionOpcode opcode;
};
/// Provider for display controllers.
///
/// The driver supports two simultaneous clients - a primary client and a virtcon
/// client.
[Layout = "Simple"]
protocol Provider {
/// Open a virtcon client. |device| should be a handle to one endpoint of a
/// channel that (on success) will become an open connection to a new
/// instance of a display client device. An protocol request |controller|
/// provides an interface to the Controller for the new device. Closing the
/// connection to |device| will also close the |controller| interface. If
/// the display device already has a virtcon controller then this method
/// will return ZX_ERR_ALREADY_BOUND.
// TODO(ZX-3889): Once llcpp is supported in Zircon, unify |device| and
// |controller|.
OpenVirtconController(handle<channel> device, request<Controller> controller) -> (zx.status s);
/// Open a primary client. |device| should be a handle to one endpoint of a
/// channel that (on success) will become an open connection to a new
/// instance of a display client device. An protocol request |controller|
/// provides an interface to the Controller for the new device. Closing the
/// connection to |device| will also close the |controller| interface. If
/// the display device already has a primary controller then this method
/// will return ZX_ERR_ALREADY_BOUND.
// TODO(ZX-3889): Once llcpp is supported in Zircon, unify |device| and
// |controller|.
OpenController(handle<channel> device, request<Controller> controller) -> (zx.status s);
};
/// Interface for accessing the display hardware.
///
/// A display configuration can be separated into two parts: the layer layout and
/// the layer contents. The layout includes all parts of a configuration other
/// than the image handles. The active configuration is composed of the most
/// recently applied layout and an active image from each layer - see
/// SetLayerImage for details on how the active image is defined. Note the
/// requirement that each layer has an active image. Whenever a new active
/// configuration is available, it is immediately given to the hardware. This
/// allows the layout and each layer's contents to advance independently when
/// possible.
///
/// Performing illegal actions on the interface will result in the interface
/// being closed.
protocol Controller {
// Event fired when displays are added or removed. This event will be fired
// when the callback is registered if there are any connected displays.
//
// A display change always invalidates the current configuration. When a
// client receives this event, they must either apply a new configuration
// or revalidate and reapply their current configuration.
-> DisplaysChanged(vector<Info> added, vector<uint64> removed);
// Imports a VMO backed image. If tiling is not typeSimple, it is up to
// the driver and client to agree on its meaning through some mechanism
// outside the scope of this API.
ImportVmoImage(ImageConfig image_config, handle<vmo> vmo, int32 offset) -> (zx.status res, uint64 image_id);
// Imports a Buffer-Collection backed image. If tiling is not typeSimple,
// it is up to the driver and client to agree on its meaning through some
// mechanism outside the scope of this API. The ImageConfig must be
// compatible with that passed through SetBufferCollectionConstraints on
// the collection id.
ImportImage(ImageConfig image_config, uint64 collection_id, uint32 index)
-> (zx.status res, uint64 image_id);
// Releases an image.
//
// It is safe to call this at any time. When an image is released, it
// is immediately removed from any pending or active configurations,
// and any fences associated with the image are dropped. The resources
// associated with the image will be released as soon as the image is
// no longer in use.
ReleaseImage(uint64 image_id);
// Imports an event into the driver and associates it with the given id.
//
// It is illegal for id to be equal to invalidId, and it is undefined to
// import one event with two different ids or to import two different events
// with the same id (note that ids map well to koids).
ImportEvent(handle<event> event, uint64 id);
// Releases the event imported with the given id.
//
// If any images are currently using the given event, the event will still be
// waited up or signaled as appropriate before its resources are released.
ReleaseEvent(uint64 id);
// Creates a new layer.
//
// Layers are not associated with a particular display, but they can only be
// shown on at most one display at any given time. A layer is considered in
// use from the time it is passed to SetDisplayLayers until a subsequent
// configuration is applied which does not include the layer or until its
// display is removed.
CreateLayer() -> (zx.status res, uint64 layer_id);
// Destroys the given layer.
//
// It is illegal to destroy a layer which does not exist or which is in use.
DestroyLayer(uint64 layer_id);
// Sets the display mode for the given display.
//
// It is illegal to pass a display mode which was not part of the display's Info.
SetDisplayMode(uint64 display_id, Mode mode);
// Set the color conversion applied to the display. The conversion is applied to
// to each pixel according to the formula:
//
// (coefficients * (pixel + preoffsets)) + postoffsets
//
// where pixel is a column vector consisting of the pixel's 3 components.
//
// |coefficients| is passed in row-major order. If the first entry of an
// array is NaN, the array is treated as the identity element for the relevant
// operation.
SetDisplayColorConversion(uint64 display_id,
array<float32>:3 preoffsets,
array<float32>:9 coefficients,
array<float32>:3 postoffsets);
// Sets which layers are on a display. The list is in increasing z-order.
//
// It is illegal to use a layer on multiple displays concurrently. If a layer
// needs to be moved between displays, it must be removed from the first display's
// pending config before being added to the second display's pending config. It
// is also illegal to pass an invalid layer id.
SetDisplayLayers(uint64 display_id, vector<uint64> layer_ids);
// Configures the layer as a primary layer with no image and the default
// config (no src_frame cropping, the identity transform, positioned in the
// top-left corner of the composed output, and no scaling).
//
// See the documentation on SetLayerImage for details on how this method
// affects the layer's contents.
//
// It is illegal to pass an invalid layer id.
SetLayerPrimaryConfig(uint64 layer_id, ImageConfig image_config);
// Sets the layer transform, scaling, and positioning.
//
// |src_frame| must be non-empty and must fit entirely within the source
// image. |dest_frame| must be non-empty and must fit entirely within the
// composed output. CheckConfig will return INVALID_CONFIG if any of these
// conditions is violated.
//
// Calling this on a non-primary layer or passing an invalid transform
// is illegal.
SetLayerPrimaryPosition(uint64 layer_id, Transform transform, Frame src_frame, Frame dest_frame);
// Sets the alpha mode of the plane.
//
// If |mode| == DISABLED, the layer is opaque and |val| is ignored.
//
// If |mode| == PREMULTIPLIED or HW_MULTIPLY and |val| is NaN, the alpha
// used when blending is determined by the per-pixel alpha channel.
//
// If |mode| == PREMULTIPLIED or HW_MULTIPLY and |val| is not NaN, the
// alpha used when blending is the product of |val| and any per-pixel
// alpha. Additionally, if |mode| == PREMULTIPLIED, then the hardware
// premultiplies the color channel with |val| before blending.
//
// It is illegal to call this on a non-primary layer, to pass an
// invalid mode, or to pass a value of |val| which is not NaN or
// in the range [0, 1].
SetLayerPrimaryAlpha(uint64 layer_id, AlphaMode mode, float32 val);
// Configures the layer as a cursor layer with the given config. The
// default position is (0, 0).
//
// See the documentation on SetLayerImage for details on how this method
// affects the layer's contents.
//
// It is illegal to call this on an invalid layer.
SetLayerCursorConfig(uint64 layer_id, ImageConfig image_config);
// Updates the cursor position.
//
// The driver will clamp x to [-cursor_width + 1, display_width - 1] and
// will clamp y to [-cursor_height + 1, display_height - 1].
//
// It is illegal to call this on a non-cursor layer.
SetLayerCursorPosition(uint64 layer_id, int32 x, int32 y);
// Configures the layer as a color layer with the given color. The
// color_bytes vector is little-endian and must have length appropriate
// for the pixel format.
//
// It is illegal to call this on an invalid layer or for the length of
// color_bytes to mismatch the size of the supplied format.
SetLayerColorConfig(uint64 layer_id, uint32 pixel_format, vector<uint8> color_bytes);
// Sets the image for the layer.
//
// If wait_event_id corresponds to an imported event, the driver will
// wait for ZX_EVENT_SIGNALED on the object before presenting the image.
//
// If signal_event_id is valid, then the driver will signal the event with
// ZX_EVENT_SIGNALED when the image is no longer being presented.
//
// A layer's active image is the most recently applied image which either has
// no wait event or whose wait event has been signaled. Whenever a new image
// becomes active, any older images which never became active are dropped, and
// their signal events will be fired as soon as their wait events are
// signaled. The driver also does not have any concept like 'target vsync',
// meaning that if multiple images become active within one vsync period, then
// only the last image will actually be displayed.
//
// By default, the driver retains an active image until a new image becomes
// active. However, setting a layer's ImageConfig with SetLayerPrimaryConfig
// or SetLayerCursorConfig reset the layer's active and pending images, even
// if the new ImageConfig matches the old ImageConfig.
//
// An image cannot be used for multiple layers simultaneously, nor can an
// image be given back to the display controller while it is still in use.
// An image is considered in use when it is part of a pending configuration
// or from when its configuration is applied until its signal_event_id is
// signaled.
//
// It is illegal to call this with an invalid layer or image id, to
// call it on a color layer, or to call it with an image and layer whose
// ImageConfigs do not match. It is illegal to apply a configuration
// with an image layer that has no image (note that is is not illegal to
// validate such a configuration). It is illegal to reuse a wait event which
// another layer that has not been presented is waiting on.
SetLayerImage(uint64 layer_id, uint64 image_id, uint64 wait_event_id, uint64 signal_event_id);
// Attempts to validate the current configuration.
//
// When CheckConfig is called, the driver will validate the pending
// configuration. If res is UNSUPPORTED_CONFIG, then ops will be
// non-empty.
//
// Most SetX operation require re-validating the configuration. The exception
// are SetLayerCursorPosition and SetLayerImage - these operations do not
// modify the configuration in a way which requires revalidation.
//
// If discard is true, the pending changes will be discarded after validation.
CheckConfig(bool discard) -> (ConfigResult res, vector<ClientCompositionOp> ops);
// Applies any pending changes to the current configuration. This will
// not apply pending changes to layers which are not on any display.
//
// If the pending configuration cannot be applied, this call will silently
// fail, so the client should ensure its configuration is valid with
// CheckConfig.
ApplyConfig();
// Sets whether or not vsync events will be given to this client. Defaults
// to false.
EnableVsync(bool enable);
// Event sent for every vsync.
//
// display_id is the identifies the display on which the vsync occurred, and
// timestamp indicates the time the vsync occurred. images is a (possibly
// empty) vector of all images where were actively being displayed.
-> Vsync(uint64 display_id, uint64 timestamp, vector<uint64> images);
// Sets the visibility behavior of the virtcon. It is illegal to call this
// from the primary client.
SetVirtconMode(uint8 mode);
// Event fired when the client gains or loses ownership of the displays.
//
// New clients should assume they do not have ownership of the display
// until this event informs them otherwise.
-> ClientOwnershipChange(bool has_ownership);
// Computes the stride (in pixels) necessary for a linear image with the
// given width and pixel format. Returns 0 on error.
ComputeLinearImageStride(uint32 width, uint32 pixel_format) -> (uint32 stride);
// Allocates a VMO of the requested size which can be used for images.
// TODO: move this into a separate video buffer management system.
AllocateVmo(uint64 size) -> (zx.status res, handle<vmo>? vmo);
// Import a sysmem buffer collection token. |collection_id| must not
// already be in use.
ImportBufferCollection(uint64 collection_id,
fuchsia.sysmem.BufferCollectionToken collection_token)
-> (zx.status res);
// Release an imported buffer collection.
ReleaseBufferCollection(uint64 collection_id);
// Takes an imported buffer collection and sets the constraints
// on it so that it can be imported with a specific config.
SetBufferCollectionConstraints(uint64 collection_id, ImageConfig config) -> (zx.status res);
// If the system only supports single-buffered mode with a single framebuffer, then this returns
// that buffer and its stride. Otherwise it can return ZX_ERR_NOT_SUPPORTED.
GetSingleBufferFramebuffer() -> (zx.status res, handle<vmo>? vmo, uint32 stride);
CaptureDisplayOutput() -> (zx.status res, handle<vmo>? vmo);
};