blob: 62bedbfcf5a3c43f27847fd9e62a861c47100322 [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.
#pragma once
#include <zircon/compiler.h>
#include <zircon/device/audio.h>
#include <zircon/types.h>
#include <zircon/pixelformat.h>
__BEGIN_CDECLS;
/**
* protocol/display-controller.h - display controller protocol definitions
*/
// The image is linear and VMO backed.
#define IMAGE_TYPE_SIMPLE 0
// a structure containing information about each plane of an image.
typedef struct image_plane {
uint32_t byte_offset;
uint32_t bytes_per_row;
} image_plane_t;
// a structure containing information about an image
typedef struct image {
// the width and height of the image in pixels
uint32_t width;
uint32_t height;
// the pixel format of the image
zx_pixel_format_t pixel_format;
// The type conveys information about what is providing the pixel data. If this is not
// IMAGE_FORMAT_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.
uint32_t type;
image_plane_t planes[4];
// A driver-defined handle to the image. Each handle must be unique.
void* handle;
} image_t;
#define INVALID_DISPLAY_ID 0
// a fallback structure to convey display information without an edid
typedef struct display_params {
uint32_t width;
uint32_t height;
uint32_t refresh_rate_e2;
} display_params_t;
// Info about valid cursor configurations.
typedef struct cursor_info {
// The width and height of the cursor configuration, in pixels.
uint32_t width;
uint32_t height;
zx_pixel_format_t format;
} cursor_info_t;
// a structure containing information a connected display
typedef struct added_display_args {
uint64_t display_id;
// 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.
bool edid_present;
union {
// the bus_id to use to read this display's edid from the device's i2c protocol
uint32_t i2c_bus_id;
// the display's parameters if an edid is not present
display_params_t params;
} panel;
// A list of pixel formats supported by the display. The first entry is the
// preferred pixel format.
const zx_pixel_format_t* pixel_formats;
uint32_t pixel_format_count;
// 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.
const cursor_info_t* cursor_infos;
uint32_t cursor_info_count;
// Out parameters will be populated before on_displays_changed returns.
bool is_hdmi_out;
bool is_standard_srgb_out;
uint32_t audio_format_count;
// All strings are null-terminated. |manufacturer_id| is guaranteed to have
// length 3, all other strings may be empty.
char manufacturer_id[4];
const char* manufacturer_name; // non-null
char monitor_name[14];
char monitor_serial[14];
} added_display_args_t;
// The client will not make any ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL calls into the device
// during these callbacks.
typedef struct display_controller_cb {
// Callbacks which are invoked when displays are added or removed. |displays_added| and
// |displays_removed| point to arrays of the display ids which were added and removed. If
// |added_count| or |removed_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.
void (*on_displays_changed)(void* ctx,
added_display_args_t* added_displays, uint32_t added_count,
uint64_t* removed_displays, uint32_t removed_count);
// |timestamp| is the ZX_CLOCK_MONOTONIC timestamp at which the vsync occurred.
// |handles| points to an array of image handles of each framebuffer being
// displayed, in increasing z-order.
void (*on_display_vsync)(void* ctx, uint64_t display_id, zx_time_t timestamp,
void** handles, uint32_t handle_count);
zx_status_t (*get_audio_format)(void* ctx, uint64_t display_id, uint32_t fmt_idx,
audio_stream_format_range_t* fmt_out);
} display_controller_cb_t;
#define ALPHA_DISABLE 0
#define ALPHA_PREMULTIPLIED 1
#define ALPHA_HW_MULTIPLY 2
// Rotations are applied counter-clockwise, and are applied before reflections.
#define FRAME_TRANSFORM_IDENTITY 0
#define FRAME_TRANSFORM_REFLECT_X 1
#define FRAME_TRANSFORM_REFLECT_Y 2
#define FRAME_TRANSFORM_ROT_90 3
#define FRAME_TRANSFORM_ROT_180 4
#define FRAME_TRANSFORM_ROT_270 5
#define FRAME_TRANSFORM_ROT_90_REFLECT_X 6
#define FRAME_TRANSFORM_ROT_90_REFLECT_Y 7
typedef struct frame {
// (x_pos, y_pos) specifies the position of the upper-left corner
// of the frame.
uint32_t x_pos;
uint32_t y_pos;
uint32_t width;
uint32_t height;
} frame_t;
typedef struct primary_layer {
image_t 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].
uint32_t alpha_mode;
float alpha_layer_val;
uint32_t transform_mode;
// 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.
frame_t src_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.
frame_t dest_frame;
} primary_layer_t;
typedef struct cursor_layer {
image_t 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.
int32_t x_pos;
int32_t y_pos;
} cursor_layer_t;
typedef struct color_layer {
zx_pixel_format_t format;
// The color to use for the layer. The color is little-endian, and is
// guaranteed to be of the appropriate size.
uint8_t* color;
} color_layer_t;
// Types of layers.
#define LAYER_PRIMARY 0
#define LAYER_CURSOR 1
#define LAYER_COLOR 2
typedef struct layer {
// One of the LAYER_* flags.
uint32_t type;
// z_index of the layer. See |check_configuration| and |apply_configuration|.
uint32_t z_index;
union {
primary_layer_t primary;
cursor_layer_t cursor;
color_layer_t color;
} cfg;
} layer_t;
// constants for display_config's mode_flags field
#define MODE_FLAG_VSYNC_POSITIVE (1 << 0)
#define MODE_FLAG_HSYNC_POSITIVE (1 << 1)
#define MODE_FLAG_INTERLACED (1 << 2)
#define MODE_FLAG_ALTERNATING_VBLANK (1 << 3)
#define MODE_FLAG_DOUBLE_CLOCKED (1 << 4)
// The video parameters which specify the display mode.
typedef struct display_mode {
uint32_t pixel_clock_10khz;
uint32_t h_addressable;
uint32_t h_front_porch;
uint32_t h_sync_pulse;
uint32_t h_blanking;
uint32_t v_addressable;
uint32_t v_front_porch;
uint32_t v_sync_pulse;
uint32_t v_blanking;
uint32_t flags; // A bitmask of MODE_FLAG_* values
} display_mode_t;
// If set, use the 0 vector for the color conversion preoffset
#define COLOR_CONVERSION_PREOFFSET (1 << 0)
// If set, use the identity matrix for the color conversion coefficients
#define COLOR_CONVERSION_COEFFICIENTS (1 << 1)
// If set, use the 0 vector for the color conversion postoffset
#define COLOR_CONVERSION_POSTOFFSET (1 << 2)
typedef struct display_config {
// the display id to which the configuration applies
uint64_t display_id;
display_mode_t mode;
// Bitmask of COLOR_CONVERSION_* flags
uint32_t cc_flags;
// 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.
float cc_preoffsets[3];
float cc_coefficients[3][3];
float cc_postoffsets[3];
uint32_t layer_count;
layer_t** layers;
} display_config_t;
// The display mode configuration is valid. Note that this is distinct from
// whether or not the layer configuration is valid.
#define CONFIG_DISPLAY_OK 0
// Error indicating that the hardware cannot simultaneously support the
// requested number of displays.
#define CONFIG_DISPLAY_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.
#define CONFIG_DISPLAY_UNSUPPORTED_MODES 2
// The client should convert the corresponding layer to a primary layer.
#define CLIENT_USE_PRIMARY (1 << 0)
// 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.
#define CLIENT_MERGE_BASE (1 << 1)
#define CLIENT_MERGE_SRC (1 << 2)
// The client should pre-scale the image so that src_frame's dimensions are equal
// to dest_frame's dimensions.
#define CLIENT_FRAME_SCALE (1 << 3)
// The client should pre-clip the image so that src_frame's dimensions are equal to
// the image's dimensions.
#define CLIENT_SRC_FRAME (1 << 4)
// The client should pre-apply the transformation so TRANSFORM_IDENTITY can be used.
#define CLIENT_TRANSFORM (1 << 5)
// The client should apply the color conversion.
#define CLIENT_COLOR_CONVERSION (1 << 6)
// The client should apply the alpha transformation itself.
#define CLIENT_ALPHA (1 << 7)
// The client guarantees that check_configuration and apply_configuration are always
// made from a single thread. The client makes no other threading guarantees.
typedef struct display_controller_protocol_ops {
// The function will only be called once, and it will be called before any other
// functions are called.
void (*set_display_controller_cb)(void* ctx, void* cb_ctx, display_controller_cb_t* cb);
// Imports a VMO backed image into the driver. The driver should set image->handle. The
// driver does not own the vmo handle passed to this function.
zx_status_t (*import_vmo_image)(void* ctx, image_t* image,
zx_handle_t vmo, size_t offset);
// 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.
void (*release_image)(void* ctx, image_t* 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.
void (*check_configuration)(void* ctx, const display_config_t** display_config,
uint32_t* display_cfg_result, uint32_t** layer_cfg_result,
uint32_t display_count);
// 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.
void (*apply_configuration)(void* ctx,
const display_config_t** display_configs, uint32_t display_count);
// Computes the stride (in pixels) necessary for a linear image with the given width
// and pixel format. Returns 0 on error.
uint32_t (*compute_linear_stride)(void* ctx, uint32_t width, zx_pixel_format_t pixel_format);
// Allocates a VMO of the requested size which can be used for images.
// TODO: move this functionality into a separate video buffer management system.
zx_status_t (*allocate_vmo)(void* ctx, uint64_t size, zx_handle_t* vmo_out);
} display_controller_protocol_ops_t;
typedef struct zx_display_controller_protocol {
display_controller_protocol_ops_t* ops;
void* ctx;
} display_controller_protocol_t;
__END_CDECLS;