blob: e2f6e0c65bcc18524bc811a864c530af0bd9e36d [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 fuchsia.hardware.i2cimpl;
using zx;
type ImageType = strict enum : uint32 {
/// The image is linear and VMO backed.
SIMPLE = 0;
// Intentionally left some gap between SIMPLE 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_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;
/// 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;
};
/// 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;
/// Pixel format type of the cursor buffer.
format FuchsiaImages2PixelFormatEnumValue;
};
type Panel = strict resource union {
// The i2c bus to use to read this display's edid.
1: i2c client_end:fuchsia.hardware.i2cimpl.I2cImpl;
/// The display's parameters if an edid is not present.
2: params DisplayParams;
};
/// A structure containing information a connected display.
type AddedDisplayArgs = resource struct {
display_id uint64;
/// A flag indicating whether or not the display has a valid edid.
///
/// If true, the device should provide a fuchsia.hardware.i2cimpl.I2cImpl client in the `Panel`
/// union. 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<FuchsiaImages2PixelFormatEnumValue>: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.
@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_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.
strict OnDisplayVsync(struct {
display_id uint64;
timestamp zx.Time;
config_stamp box<ConfigStamp>;
}) -> ();
strict GetAudioFormat(struct {
display_id uint64;
fmt_idx uint32;
}) -> (struct {
s zx.Status;
fmt fuchsia.hardware.audiotypes.AudioTypesAudioStreamFormatRange;
});
};
@transport("Banjo")
@banjo_layout("ddk-interface")
closed protocol DisplayCaptureInterface {
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 {
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 {
/// 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;
CURSOR = 1;
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 {
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_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
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>;
@mutable
@out_of_line_contents
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;
};
type Client = strict enum : 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;
}) -> ();
/// Initialize the display capture interface. Must be called only once
/// before importing resources for capture and starting display capture.
///
/// Returns ZX_ERR_NOT_SUPPORTED if display capture is not supported.
strict SetDisplayCaptureInterface(resource struct {
intf client_end:DisplayCaptureInterface;
}) -> (struct {
s zx.Status;
});
/// 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(fxbug.dev/89649): 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.
///
/// Sets `image->handle` iff the image is imported successfully.
///
/// Returns ZX_OK 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 {
@in_out
image Image;
collection_id uint64;
index uint32;
}) -> (struct {
s zx.Status;
});
/// 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 {
@in_out
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_CHECK_RESULT_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...
strict CheckConfiguration(struct {
@inner_pointer
display_config vector<DisplayConfig>:MAX;
}) -> (struct {
display_cfg_result ConfigCheckResult;
@callee_allocated
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.
///
/// The driver must not retain references to the configuration after this function returns.
strict ApplyConfiguration(struct {
@inner_pointer
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;
}) -> ();
// Connects the handle to the sysmem service.
strict 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` on the imported BufferCollecition with
/// `collection_id`.
///
/// Returns ZX_ERR_NOT_FOUND if `collection_id` is not imported yet.
strict SetBufferCollectionConstraints(struct {
config Image;
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;
});
/// 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 {
b bool;
});
};