1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5library ddk.protocol.display.controller;
6
7using zircon.device.audio;
8using zx;
9
10//using ZxPixelFormat = uint32;
11enum ZxPixelFormat : uint32 {
12};
13
14/// The image is linear and VMO backed.
15const uint32 IMAGE_TYPE_SIMPLE = 0;
16
17/// A structure containing information about each plane of an image.
18struct ImagePlane {
19    uint32 byte_offset;
20    uint32 bytes_per_row;
21};
22
23/// A structure containing information about an image.
24struct Image {
25    /// The width and height of the image in pixels.
26    uint32 width;
27    uint32 height;
28
29    /// The pixel format of the image.
30    ZxPixelFormat pixel_format;
31
32    /// The type conveys information about what is providing the pixel data. If this is not
33    /// IMAGE_FORMAT_SIMPLE, it is up to the driver and buffer producer to agree on the meaning
34    /// of the value through some mechanism outside the scope of this API.
35    uint32 type;
36
37    array<ImagePlane>:4 planes;
38
39    /// A driver-defined handle to the image. Each handle must be unique.
40    uint64 @handle;
41};
42
43const uint32 INVALID_DISPLAY_ID = 0;
44
45/// A fallback structure to convey display information without an edid.
46struct DisplayParams {
47    uint32 width;
48    uint32 height;
49    uint32 refresh_rate_e2;
50};
51
52/// Info about valid cursor configurations.
53struct CursorInfo {
54    /// The width and height of the cursor configuration, in pixels.
55    uint32 width;
56    uint32 height;
57    ZxPixelFormat format;
58};
59
60union Panel {
61    /// The bus_id to use to read this display's edid from the device's i2c protocol.
62    uint32 i2c_bus_id;
63    /// The display's parameters if an edid is not present.
64    DisplayParams params;
65};
66
67/// A structure containing information a connected display.
68struct AddedDisplayArgs {
69    uint64 display_id;
70
71    /// A flag indicating whether or not the display has a valid edid.
72    ///
73    /// If true, the device should expose an ZX_PROTOCOL_I2C_IMPL device through get_protocol, in
74    /// addition to the ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL protocol. Note that the i2c device
75    /// will be called from the on_displays_changed callback, so care should be taken to avoid
76    /// deadlocks or double-locking.
77    ///
78    /// If no edid is present, then the meaning of display_config's mode structure is
79    /// undefined, and drivers should ignore it in check_configuration and apply_configuration.
80    bool edid_present;
81    Panel panel;
82
83    /// A list of pixel formats supported by the display. The first entry is the
84    /// preferred pixel format.
85    vector<ZxPixelFormat> pixel_format;
86
87    /// A list of cursor configurations most likely to be accepted by the driver. Can
88    /// be null if cursor_count is 0.
89    ///
90    /// The driver may reject some of these configurations in some circumstances, and
91    /// it may accept other configurations, but at least one of these configurations
92    /// should be valid at most times.
93    vector<CursorInfo> cursor_info;
94};
95
96/// Out parameters will be populated before on_displays_changed returns.
97struct AddedDisplayInfo {
98    bool is_hdmi_out;
99    bool is_standard_srgb_out;
100
101    uint32 audio_format_count;
102
103    /// All strings are null-terminated. |manufacturer_id| is guaranteed to have
104    /// length 3, all other strings may be empty.
105    string:4 manufacturer_id;
106    /// non-null
107    string manufacturer_name;
108    /// null-terminated
109    string:14 monitor_name;
110    /// null-terminated
111    string:14 monitor_serial;
112};
113
114/// The client will not make any `ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL` calls into the device
115/// during these callbacks.
116[Layout = "ddk-interface"]
117interface DisplayControllerInterface {
118    /// Callbacks which are invoked when displays are added or removed. |added_display_list| and
119    /// |removed_display_list| point to arrays of the display ids which were added and removed. If
120    /// |added_display_count| or |removed_display_count| is 0, the corresponding array can be NULL.
121    ///
122    /// The driver must be done accessing any images which were on the removed displays.
123    ///
124    /// The driver should call this function when the callback is registered if any displays
125    /// are present.
126    OnDisplaysChanged(vector<AddedDisplayArgs> added_display,
127                      vector<uint64> removed_display) -> (vector<AddedDisplayInfo> display_info);
128
129    /// |timestamp| is the ZX_CLOCK_MONOTONIC timestamp at which the vsync occurred.
130    /// |handles| points to an array of image handles of each framebuffer being
131    /// displayed, in increasing z-order.
132    OnDisplayVsync(uint64 display_id, zx.time timestamp, vector<uint64> @handle) -> ();
133
134    GetAudioFormat(uint64 display_id, uint32 fmt_idx)
135               -> (zx.status s, zircon.device.audio.AudioStreamFormatRange fmt);
136};
137
138enum Alpha : uint8 {
139    DISABLE = 0;
140    PREMULTIPLIED = 1;
141    HW_MULTIPLY = 2;
142};
143
144/// Rotations are applied counter-clockwise, and are applied before reflections.
145enum FrameTransform : uint32 {
146    IDENTITY = 0;
147    REFLECT_X = 1;
148    REFLECT_Y = 2;
149    ROT_90 = 3;
150    ROT_180 = 4;
151    ROT_270 = 5;
152    ROT_90_REFLECT_X = 6;
153    ROT_90_REFLECT_Y = 7;
154};
155
156struct Frame {
157    /// (|x_pos|, |y_pos|) specifies the position of the upper-left corner
158    /// of the frame.
159    uint32 x_pos;
160    uint32 y_pos;
161    uint32 width;
162    uint32 height;
163};
164
165struct PrimaryLayer {
166    Image image;
167
168    /// An ALPHA_* constant.
169    ///
170    /// If |alpha_mode| == `ALPHA_DISABLED`, the layer is opaque and alpha_layer_val is ignored.
171    ///
172    /// If |alpha_mode| == `PREMULTIPLIED` or `HW_MULTIPLY` and |alpha_layer_val| is NaN, the alpha
173    /// used when blending is determined by the per-pixel alpha channel.
174    ///
175    /// If |alpha_mode| == `PREMULTIPLIED` or `HW_MULTIPLY` and |alpha_layer_val| is not NaN, the
176    /// alpha used when blending is the product of alpha_layer_val and any per-pixel alpha.
177    /// Additionally, if alpha_mode == PREMULTIPLIED, then the hardware must premultiply the color
178    /// channel with alpha_layer_val before blending.
179    ///
180    /// If alpha_layer_val is not NaN, it will be in the range [0, 1].
181    Alpha alpha_mode;
182    float32 alpha_layer_val;
183
184    FrameTransform transform_mode;
185
186    /// The source frame, where (0,0) is the top-left corner of the image. The
187    /// client guarantees that src_frame lies entirely within the image.
188    Frame src_frame;
189
190    /// The destination frame, where (0,0) is the top-left corner of the
191    /// composed output. The client guarantees that dest_frame lies entirely
192    /// within the composed output.
193    Frame dest_frame;
194};
195
196struct CursorLayer {
197    Image image;
198
199    /// The position of the top-left corner of the cursor's image. When being
200    /// applied to a display, the cursor is guaranteed to have at least one
201    /// pixel of overlap with the display.
202    int32 x_pos;
203    int32 y_pos;
204};
205
206struct ColorLayer {
207    ZxPixelFormat format;
208    /// The color to use for the layer. The color is little-endian, and is
209    /// guaranteed to be of the appropriate size.
210    vector<uint8> color;
211};
212
213/// Types of layers.
214enum LayerType : uint32 {
215    PRIMARY = 0;
216    CURSOR = 1;
217    COLOR = 2;
218};
219
220union LayerConfig {
221    PrimaryLayer primary;
222    CursorLayer cursor;
223    ColorLayer color;
224};
225
226struct Layer {
227    LayerType type;
228    /// z_index of the layer. See |check_configuration| and |apply_configuration|.
229    uint32 z_index;
230    LayerConfig cfg;
231};
232
233/// constants for display_config's mode_flags field
234enum ModeFlag : uint32 {
235    VSYNC_POSITIVE = 0x1;
236    HSYNC_POSITIVE = 0x2;
237    INTERLACED = 0x4;
238    ALTERNATING_VBLANK = 0x8;
239    DOUBLE_CLOCKED = 0x10;
240};
241
242/// The video parameters which specify the display mode.
243struct DisplayMode {
244    uint32 pixel_clock_10khz;
245    uint32 h_addressable;
246    uint32 h_front_porch;
247    uint32 h_sync_pulse;
248    uint32 h_blanking;
249    uint32 v_addressable;
250    uint32 v_front_porch;
251    uint32 v_sync_pulse;
252    uint32 v_blanking;
253    /// A bitmask of MODE_FLAG_* values
254    uint32 flags;
255};
256
257enum ColorConversion : uint32 {
258    /// If set, use the 0 vector for the color conversion preoffset
259    PREOFFSET = 0x1;
260    /// If set, use the identity matrix for the color conversion coefficients
261    COEFFICIENTS = 0x2;
262    /// If set, use the 0 vector for the color conversion postoffset
263    POSTOFFSET = 0x4;
264};
265
266struct DisplayConfig {
267    /// the display id to which the configuration applies
268    uint64 display_id;
269
270    DisplayMode mode;
271
272    /// Bitmask of COLOR_CONVERSION_* flags
273    uint32 cc_flags;
274    /// Color conversion is applied to each pixel according to the formula:
275    ///
276    /// (cc_coefficients * (pixel + cc_preoffsets)) + cc_postoffsets
277    ///
278    /// where pixel is a column vector consisting of the pixel's 3 components.
279    array<float32>:3 cc_preoffsets;
280    array<array<float32>:3>:3 cc_coefficients;
281    array<float32>:3 cc_postoffsets;
282
283    vector<Layer?>? layer;
284};
285
286enum ConfigDisplay : uint32 {
287    /// The display mode configuration is valid. Note that this is distinct from
288    /// whether or not the layer configuration is valid.
289    OK = 0;
290    /// Error indicating that the hardware cannot simultaneously support the
291    /// requested number of displays.
292    TOO_MANY = 1;
293    /// Error indicating that the hardware cannot simultaneously support the given
294    /// set of display modes. To support a mode, the display must be able to display
295    /// a single layer with width and height equal to the requested mode and the
296    /// preferred pixel format.
297    UNSUPPORTED_MODES = 2;
298};
299
300enum Client : uint32 {
301    /// The client should convert the corresponding layer to a primary layer.
302    USE_PRIMARY = 0x1;
303    /// The client should compose all layers with MERGE_BASE and MERGE_SRC into a new,
304    /// single primary layer at the MERGE_BASE layer's z-order. The driver must accept
305    /// a fullscreen layer with the default pixel format, but may accept other layer
306    /// parameters.
307    ///
308    /// MERGE_BASE should only be set on one layer per display. If it is set on multiple
309    /// layers, the client will arbitrarily pick one and change the rest to MERGE_SRC.
310    MERGE_BASE = 0x2;
311    MERGE_SRC = 0x4;
312    /// The client should pre-scale the image so that src_frame's dimensions are equal
313    /// to dest_frame's dimensions.
314    FRAME_SCALE = 0x8;
315    /// The client should pre-clip the image so that src_frame's dimensions are equal to
316    /// the image's dimensions.
317    SRC_FRAME = 0x10;
318    /// The client should pre-apply the transformation so TRANSFORM_IDENTITY can be used.
319    TRANSFORM = 0x20;
320    /// The client should apply the color conversion.
321    COLOR_CONVERSION = 0x40;
322    /// The client should apply the alpha transformation itself.
323    ALPHA = 0x80;
324};
325
326/// The client guarantees that check_configuration and apply_configuration are always
327/// made from a single thread. The client makes no other threading guarantees.
328[Layout = "ddk-protocol", HandleWrappers]
329interface DisplayControllerImpl {
330    /// The function will only be called once, and it will be called before any other
331    /// functions are called.
332    SetDisplayControllerInterface(DisplayControllerInterface intf) -> ();
333
334    /// Imports a VMO backed image into the driver. The driver should set image->handle. The
335    /// driver does not own the vmo handle passed to this function.
336    ImportVmoImage(Image? image, handle<vmo> vmo, usize offset) -> (zx.status s);
337
338    /// Releases any driver state associated with the given image. The client guarantees that
339    /// any images passed to apply_config will not be released until a vsync occurs with a
340    /// more recent image.
341    ReleaseImage(Image? image) -> ();
342
343    /// Validates the given configuration.
344    ///
345    /// The configuration may not include all displays. Omitted displays should be treated as
346    /// whichever of off or displaying a blank screen results in a more permissive validation.
347    ///
348    /// All displays in a configuration will have at least one layer. The layers will be
349    /// arranged in increasing z-order, and their z_index fields will be set consecutively.
350    ///
351    /// Whether or not the driver can accept the configuration cannot depend on the
352    /// particular image handles, as it must always be possible to present a new image in
353    /// place of another image with a matching configuration. It also cannot depend on the
354    /// cursor position, as that can be updated without another call to check_configuration.
355    ///
356    /// display_cfg_result should be set to a CONFIG_DISPLAY_* error if the combination of
357    /// display modes is not supported.
358    ///
359    /// layer_cfg_result points to an array of arrays. The primary length is display_count, the
360    /// secondary lengths are the corresponding display_cfg's layer_count. If display_cfg_result
361    /// is CONFIG_DISPLAY_OK, any errors in layer configuration should be returned as a CLIENT*
362    /// flag in the corresponding layer_cfg_result entry.
363    ///
364    /// The driver must not retain references to the configuration after this function returns.
365    /// TODO: Fix me...
366    CheckConfiguration(vector<DisplayConfig?> display_config)
367                       -> (uint32 display_cfg_result, vector<uint32>? layer_cfg_result);
368
369    /// Applies the configuration.
370    ///
371    /// All configurations passed to this function will be derived from configurations which
372    /// have been successfully validated, with the only differences either being omitted layers
373    /// or different image handles. To account for any layers which are not present, the driver
374    /// must use the z_index values of the present layers to configure them as if the whole
375    /// configuration was present.
376    ///
377    /// Unlike with check_configuration, displays included in the configuration are not
378    /// guaranteed to include any layers. Both omitted displays and displays with no layers
379    /// can either be turned off or set to display a blank screen, but for displays with no
380    /// layers there is a strong preference to display a blank screen instead of turn them off.
381    /// In either case, the driver must drop all references to old images and invoke the vsync
382    /// callback after doing so.
383    ///
384    /// The driver must not retain references to the configuration after this function returns.
385    ApplyConfiguration(vector<DisplayConfig?> display_config) -> ();
386
387    /// Computes the stride (in pixels) necessary for a linear image with the given width
388    /// and pixel format. Returns 0 on error.
389    ComputeLinearStride(uint32 width, ZxPixelFormat pixel_format) -> (uint32 s);
390
391    /// Allocates a VMO of the requested size which can be used for images.
392    // TODO: move this functionality into a seperate video buffer management system.
393    AllocateVmo(uint64 size) -> (zx.status s, handle<vmo> vmo);
394};
395