summaryrefslogtreecommitdiffstats
path: root/shared/pixel-formats.h
blob: 8df5b4545367266ddb991d697dd86664ae0db3a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/*
 * Copyright © 2016, 2019 Collabora, Ltd.
 * Copyright (c) 2018 DisplayLink (UK) Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Author: Daniel Stone <daniels@collabora.com>
 */

#include <inttypes.h>
#include <stdbool.h>
#include <pixman.h>

/**
 * Contains information about pixel formats, mapping format codes from
 * wl_shm and drm_fourcc.h (which are deliberately identical, but for the
 * special cases of WL_SHM_ARGB8888 and WL_SHM_XRGB8888) into various
 * sets of information. Helper functions are provided for dealing with these
 * raw structures.
 */
struct pixel_format_info {
	/** DRM/wl_shm format code */
	uint32_t format;

	/** The DRM format name without the DRM_FORMAT_ prefix. */
	const char *drm_format_name;

	/** If true, is only for internal use and should not be advertised to
	 * clients to allow them to create buffers of this format. */
	bool hide_from_clients;

	/** If non-zero, number of planes in base (non-modified) format. */
	int num_planes;

	/** If format contains alpha channel, opaque equivalent of format,
	 *  i.e. alpha channel replaced with X. */
	uint32_t opaque_substitute;

	/** How the format should be sampled, expressed in terms of tokens
	 *  from the EGL_WL_bind_wayland_display extension. If not set,
	 *  assumed to be either RGB or RGBA, depending on whether or not
	 *  the format contains an alpha channel. The samplers may still
	 *  return alpha even for opaque formats; users must manually set
	 *  the alpha channel to 1.0 (or ignore it) if the format is
	 *  opaque. */
	uint32_t sampler_type;

	/** GL internal format; to be used when creating FBO renderbuffers */
	int gl_internalformat;

	/** GL format, if data can be natively/directly uploaded. Note that
	 *  whilst DRM formats are little-endian unless explicitly specified,
	 *  (i.e. DRM_FORMAT_ARGB8888 is stored BGRA as sequential bytes in
	 *  memory), GL uses the sequential byte order, so that format maps to
	 *  GL_BGRA_EXT plus GL_UNSIGNED_BYTE. To add to the confusion, the
	 *  explicitly-sized types (e.g. GL_UNSIGNED_SHORT_5_5_5_1) read in
	 *  machine-endian order, so for these types, the correspondence
	 *  depends on endianness. */
	int gl_format;

	/** GL data type, if data can be natively/directly uploaded. */
	int gl_type;

	/** Pixman data type, if it agrees exactly with the wl_shm format */
	pixman_format_code_t pixman_format;

	/** If set, this format can be used with the legacy drmModeAddFB()
	 *  function (not AddFB2), using this and the bpp member. */
	int addfb_legacy_depth;

	/** Number of bits required to store a single pixel, for
	 *  single-planar formats. */
	int bpp;

	/** Horizontal subsampling; if non-zero, divide the width by this
	 *  member to obtain the number of columns in the source buffer for
	 *  secondary planes only. Stride is not affected by horizontal
	 *  subsampling. */
	int hsub;

	/** Vertical subsampling; if non-zero, divide the height by this
	 *  member to obtain the number of rows in the source buffer for
	 *  secondary planes only. */
	int vsub;

	/* Ordering of chroma components. */
	enum {
		ORDER_UV = 0,
		ORDER_VU,
	} chroma_order;

	/* If packed YUV (num_planes == 1), ordering of luma/chroma
	 * components. */
	enum {
		ORDER_LUMA_CHROMA = 0,
		ORDER_CHROMA_LUMA,
	} luma_chroma_order;

	/** How many significant bits each channel has, or zero if N/A. */
	struct {
		int r;
		int g;
		int b;
		int a;
	} bits;

	/** How channel bits are interpreted, fixed (uint) or floating-point */
	enum {
		PIXEL_COMPONENT_TYPE_FIXED = 0,
		PIXEL_COMPONENT_TYPE_FLOAT,
	} component_type;
};

/**
 * Get pixel format information for a DRM format code
 *
 * Given a DRM format code, return a pixel format info structure describing
 * the properties of that format.
 *
 * @param format DRM format code to get info for
 * @returns A pixel format structure (must not be freed), or NULL if the
 *          format could not be found
 */
const struct pixel_format_info *
pixel_format_get_info(uint32_t format);

/**
 * Get pixel format information for a SHM format code
 *
 * Given a SHM format code, return a DRM pixel format info structure describing
 * the properties of that format.
 *
 * @param format SHM format code to get info for.
 * @returns A pixel format structure (must not be freed), or NULL if the
 *          format could not be found.
 */
const struct pixel_format_info *
pixel_format_get_info_shm(uint32_t format);

/**
 * Get pixel format information by table index
 *
 * Given a 0-based index in the format table, return the corresponding
 * DRM pixel format info structure.
 *
 * @param index Index of the pixel format in the table
 * @returns A pixel format structure (must not be freed), or NULL if the
 *          index is out of range.
 */
const struct pixel_format_info *
pixel_format_get_info_by_index(unsigned int index);

/**
 * Return the size of the pixel format table
 *
 * @returns The number of entries in the pixel format table
 */
unsigned int
pixel_format_get_info_count(void);

/**
 * Get pixel format information for a named DRM format
 *
 * Given a DRM format name, return a pixel format info structure describing
 * the properties of that format.
 *
 * The DRM format name is the preprocessor token name from drm_fourcc.h
 * without the DRM_FORMAT_ prefix. The search is also case-insensitive.
 * Both "xrgb8888" and "XRGB8888" searches will find DRM_FORMAT_XRGB8888
 * for example.
 *
 * @param drm_format_name DRM format name to get info for (not NULL)
 * @returns A pixel format structure (must not be freed), or NULL if the
 *          name could not be found
 */
const struct pixel_format_info *
pixel_format_get_info_by_drm_name(const char *drm_format_name);

/**
 * Get pixel format information for a Pixman format code
 *
 * Given a Pixman format code, return a pixel format info structure describing
 * the properties of that format.
 *
 * @param pixman_format Pixman format code to get info for
 * @returns A pixel format structure (must not be freed), or NULL if the
 *          format could not be found
 */
const struct pixel_format_info *
pixel_format_get_info_by_pixman(pixman_format_code_t pixman_format);

/**
 * Get number of planes used by a pixel format
 *
 * Given a pixel format info structure, return the number of planes
 * required for a buffer. Note that this is not necessarily identical to
 * the number of samplers required to be bound, as two views into a single
 * plane are sometimes required.
 *
 * @param format Pixel format info structure
 * @returns Number of planes required for the format
 */
unsigned int
pixel_format_get_plane_count(const struct pixel_format_info *format);

/**
 * Determine if a pixel format is opaque or contains alpha
 *
 * Returns whether or not the pixel format is opaque, or contains a
 * significant alpha channel. Note that the suggested EGL sampler type may
 * still sample undefined data into the alpha channel; users must consider
 * alpha as 1.0 if the format is opaque, and not rely on the sampler to
 * return this when sampling from the alpha channel.
 *
 * @param format Pixel format info structure
 * @returns True if the format is opaque, or false if it has significant alpha
 */
bool
pixel_format_is_opaque(const struct pixel_format_info *format);

/**
 * Get compatible opaque equivalent for a format
 *
 * Given a pixel format info structure, return a format which is wholly
 * compatible with the input format, but opaque, ignoring the alpha channel.
 * If an alpha format is provided, but the content is known to all be opaque,
 * then this can be used as a substitute to avoid blending.
 *
 * If the input format is opaque, this function will return the input format.
 *
 * @param format Pixel format info structure
 * @returns A pixel format info structure for the compatible opaque substitute
 */
const struct pixel_format_info *
pixel_format_get_opaque_substitute(const struct pixel_format_info *format);

/**
 * For an opaque format, get the equivalent format with alpha instead of an
 * ignored channel
 *
 * This is the opposite lookup from pixel_format_get_opaque_substitute().
 * Finds the format whose opaque substitute is the given format.
 *
 * If the input format is not opaque or does not have ignored (X) bits, then
 * the search cannot find a match.
 *
 * @param format DRM format code to search for
 * @returns A pixel format info structure for the pixel format whose opaque
 * substitute is the argument, or NULL if no match.
 */
const struct pixel_format_info *
pixel_format_get_info_by_opaque_substitute(uint32_t format);

/**
 * Return the horizontal subsampling factor for a given plane
 *
 * When horizontal subsampling is effective, a sampler bound to a secondary
 * plane must bind the sampler with a smaller effective width. This function
 * returns the subsampling factor to use for the given plane.
 *
 * @param format Pixel format info structure
 * @param plane Zero-indexed plane number
 * @returns Horizontal subsampling factor for the given plane
 */
unsigned int
pixel_format_hsub(const struct pixel_format_info *format,
		  unsigned int plane);

/**
 * Return the vertical subsampling factor for a given plane
 *
 * When vertical subsampling is effective, a sampler bound to a secondary
 * plane must bind the sampler with a smaller effective height. This function
 * returns the subsampling factor to use for the given plane.
 *
 * @param format Pixel format info structure
 * @param plane Zero-indexed plane number
 * @returns Vertical subsampling factor for the given plane
 */
unsigned int
pixel_format_vsub(const struct pixel_format_info *format,
		  unsigned int plane);

/**
 * Return the effective sampling width for a given plane
 *
 * When horizontal subsampling is effective, a sampler bound to a secondary
 * plane must bind the sampler with a smaller effective width. This function
 * returns the effective width to use for the sampler, i.e. dividing by hsub.
 *
 * If horizontal subsampling is not in effect, this will be equal to the
 * width.
 *
 * @param format Pixel format info structure
 * @param plane Zero-indexed plane number
 * @param width Width of the buffer
 * @returns Effective width for sampling
 */
unsigned int
pixel_format_width_for_plane(const struct pixel_format_info *format,
			     unsigned int plane,
			     unsigned int width);

/**
 * Return the effective sampling height for a given plane
 *
 * When vertical subsampling is in effect, a sampler bound to a secondary
 * plane must bind the sampler with a smaller effective height. This function
 * returns the effective height to use for the sampler, i.e. dividing by vsub.
 *
 * If vertical subsampling is not in effect, this will be equal to the height.
 *
 * @param format Pixel format info structure
 * @param plane Zero-indexed plane number
 * @param height Height of the buffer
 * @returns Effective width for sampling
 */
unsigned int
pixel_format_height_for_plane(const struct pixel_format_info *format,
			      unsigned int plane,
			      unsigned int height);
/**
 * Return a human-readable format modifier. Comprised from the modifier name,
 * the vendor name, and the original encoded value in hexadecimal, using
 * 'VENDOR_NAME_MODIFIER_NAME (modifier_encoded_value)' pattern. In case the
 * modifier name (and the vendor name) isn't found, this returns the original
 * encoded value, as a string value.
 *
 * @param modifier  the modifier in question
 * @returns a malloc'ed string, caller responsible for freeing after use.
 */
char *
pixel_format_get_modifier(uint64_t modifier);

/**
 * Return the wl_shm format code
 *
 * @param info Pixel format info structure
 * @returns The wl_shm format code for this pixel format.
 */
uint32_t
pixel_format_get_shm_format(const struct pixel_format_info *info);

/**
 * Get pixel format array for an array of DRM format codes
 *
 * Given an array of DRM format codes, return an array of corresponding pixel
 * format info pointers.
 *
 * @param formats Array of DRM format codes to get info for
 * @param formats_count Number of entries in formats.
 * @returns An array of pixel format info pointers, or NULL if any format could
 *          not be found. Must be freed by the caller.
 */
const struct pixel_format_info **
pixel_format_get_array(const uint32_t *formats, unsigned int formats_count);