• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2016, 2019 Collabora, Ltd.
3  * Copyright (c) 2018 DisplayLink (UK) Ltd.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Author: Daniel Stone <daniels@collabora.com>
25  */
26 
27 #include "config.h"
28 
29 #include <endian.h>
30 #include <inttypes.h>
31 #include <stdbool.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <drm_fourcc.h>
35 #include <wayland-client-protocol.h>
36 
37 #include "shared/helpers.h"
38 #include "wayland-util.h"
39 #include "pixel-formats.h"
40 
41 #if ENABLE_EGL
42 #include <EGL/egl.h>
43 #include <EGL/eglext.h>
44 #include <GLES2/gl2.h>
45 #include <GLES2/gl2ext.h>
46 #define GL_FORMAT(fmt) .gl_format = (fmt)
47 #define GL_TYPE(type) .gl_type = (type)
48 #define SAMPLER_TYPE(type) .sampler_type = (type)
49 #else
50 #define GL_FORMAT(fmt) .gl_format = 0
51 #define GL_TYPE(type) .gl_type = 0
52 #define SAMPLER_TYPE(type) .sampler_type = 0
53 #endif
54 
55 #define DRM_FORMAT(f) .format = DRM_FORMAT_ ## f, .drm_format_name = #f
56 #define BITS_RGBA_FIXED(r_, g_, b_, a_) \
57 	.bits.r = r_, \
58 	.bits.g = g_, \
59 	.bits.b = b_, \
60 	.bits.a = a_, \
61 	.component_type = PIXEL_COMPONENT_TYPE_FIXED
62 
63 #include "shared/weston-egl-ext.h"
64 
65 /**
66  * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are
67  * supported. Indexed/greyscale formats, and formats not containing complete
68  * colour channels, are not supported.
69  */
70 static const struct pixel_format_info pixel_format_table[] = {
71 	{
72 		DRM_FORMAT(XRGB4444),
73 		BITS_RGBA_FIXED(4, 4, 4, 0),
74 	},
75 	{
76 		DRM_FORMAT(ARGB4444),
77 		BITS_RGBA_FIXED(4, 4, 4, 4),
78 		.opaque_substitute = DRM_FORMAT_XRGB4444,
79 	},
80 	{
81 		DRM_FORMAT(XBGR4444),
82 		BITS_RGBA_FIXED(4, 4, 4, 0),
83 	},
84 	{
85 		DRM_FORMAT(ABGR4444),
86 		BITS_RGBA_FIXED(4, 4, 4, 4),
87 		.opaque_substitute = DRM_FORMAT_XBGR4444,
88 	},
89 	{
90 		DRM_FORMAT(RGBX4444),
91 		BITS_RGBA_FIXED(4, 4, 4, 0),
92 # if __BYTE_ORDER == __LITTLE_ENDIAN
93 		GL_FORMAT(GL_RGBA),
94 		GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
95 #endif
96 	},
97 	{
98 		DRM_FORMAT(RGBA4444),
99 		BITS_RGBA_FIXED(4, 4, 4, 4),
100 		.opaque_substitute = DRM_FORMAT_RGBX4444,
101 # if __BYTE_ORDER == __LITTLE_ENDIAN
102 		GL_FORMAT(GL_RGBA),
103 		GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
104 #endif
105 	},
106 	{
107 		DRM_FORMAT(BGRX4444),
108 		BITS_RGBA_FIXED(4, 4, 4, 0),
109 	},
110 	{
111 		DRM_FORMAT(BGRA4444),
112 		BITS_RGBA_FIXED(4, 4, 4, 4),
113 		.opaque_substitute = DRM_FORMAT_BGRX4444,
114 	},
115 	{
116 		DRM_FORMAT(XRGB1555),
117 		BITS_RGBA_FIXED(5, 5, 5, 0),
118 		.depth = 15,
119 		.bpp = 16,
120 	},
121 	{
122 		DRM_FORMAT(ARGB1555),
123 		BITS_RGBA_FIXED(5, 5, 5, 1),
124 		.opaque_substitute = DRM_FORMAT_XRGB1555,
125 	},
126 	{
127 		DRM_FORMAT(XBGR1555),
128 		BITS_RGBA_FIXED(5, 5, 5, 0),
129 	},
130 	{
131 		DRM_FORMAT(ABGR1555),
132 		BITS_RGBA_FIXED(5, 5, 5, 1),
133 		.opaque_substitute = DRM_FORMAT_XBGR1555,
134 	},
135 	{
136 		DRM_FORMAT(RGBX5551),
137 		BITS_RGBA_FIXED(5, 5, 5, 0),
138 # if __BYTE_ORDER == __LITTLE_ENDIAN
139 		GL_FORMAT(GL_RGBA),
140 		GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
141 #endif
142 	},
143 	{
144 		DRM_FORMAT(RGBA5551),
145 		BITS_RGBA_FIXED(5, 5, 5, 1),
146 		.opaque_substitute = DRM_FORMAT_RGBX5551,
147 # if __BYTE_ORDER == __LITTLE_ENDIAN
148 		GL_FORMAT(GL_RGBA),
149 		GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
150 #endif
151 	},
152 	{
153 		DRM_FORMAT(BGRX5551),
154 		BITS_RGBA_FIXED(5, 5, 5, 0),
155 	},
156 	{
157 		DRM_FORMAT(BGRA5551),
158 		BITS_RGBA_FIXED(5, 5, 5, 1),
159 		.opaque_substitute = DRM_FORMAT_BGRX5551,
160 	},
161 	{
162 		DRM_FORMAT(RGB565),
163 		BITS_RGBA_FIXED(5, 6, 5, 0),
164 		.depth = 16,
165 		.bpp = 16,
166 # if __BYTE_ORDER == __LITTLE_ENDIAN
167 		GL_FORMAT(GL_RGB),
168 		GL_TYPE(GL_UNSIGNED_SHORT_5_6_5),
169 #endif
170 	},
171 	{
172 		DRM_FORMAT(BGR565),
173 		BITS_RGBA_FIXED(5, 6, 5, 0),
174 	},
175 	{
176 		DRM_FORMAT(RGB888),
177 		BITS_RGBA_FIXED(8, 8, 8, 0),
178 	},
179 	{
180 		DRM_FORMAT(BGR888),
181 		BITS_RGBA_FIXED(8, 8, 8, 0),
182 		GL_FORMAT(GL_RGB),
183 		GL_TYPE(GL_UNSIGNED_BYTE),
184 	},
185 	{
186 		DRM_FORMAT(XRGB8888),
187 		BITS_RGBA_FIXED(8, 8, 8, 0),
188 		.depth = 24,
189 		.bpp = 32,
190 		GL_FORMAT(GL_BGRA_EXT),
191 		GL_TYPE(GL_UNSIGNED_BYTE),
192 	},
193 	{
194 		DRM_FORMAT(ARGB8888),
195 		BITS_RGBA_FIXED(8, 8, 8, 8),
196 		.opaque_substitute = DRM_FORMAT_XRGB8888,
197 		.depth = 32,
198 		.bpp = 32,
199 		GL_FORMAT(GL_BGRA_EXT),
200 		GL_TYPE(GL_UNSIGNED_BYTE),
201 	},
202 	{
203 		DRM_FORMAT(XBGR8888),
204 		BITS_RGBA_FIXED(8, 8, 8, 0),
205 		GL_FORMAT(GL_RGBA),
206 		GL_TYPE(GL_UNSIGNED_BYTE),
207 	},
208 	{
209 		DRM_FORMAT(ABGR8888),
210 		BITS_RGBA_FIXED(8, 8, 8, 8),
211 		.opaque_substitute = DRM_FORMAT_XBGR8888,
212 		GL_FORMAT(GL_RGBA),
213 		GL_TYPE(GL_UNSIGNED_BYTE),
214 	},
215 	{
216 		DRM_FORMAT(RGBX8888),
217 		BITS_RGBA_FIXED(8, 8, 8, 0),
218 	},
219 	{
220 		DRM_FORMAT(RGBA8888),
221 		BITS_RGBA_FIXED(8, 8, 8, 8),
222 		.opaque_substitute = DRM_FORMAT_RGBX8888,
223 	},
224 	{
225 		DRM_FORMAT(BGRX8888),
226 		BITS_RGBA_FIXED(8, 8, 8, 0),
227 	},
228 	{
229 		DRM_FORMAT(BGRA8888),
230 		BITS_RGBA_FIXED(8, 8, 8, 8),
231 		.opaque_substitute = DRM_FORMAT_BGRX8888,
232 	},
233 	{
234 		DRM_FORMAT(XRGB2101010),
235 		BITS_RGBA_FIXED(10, 10, 10, 0),
236 		.depth = 30,
237 		.bpp = 32,
238 	},
239 	{
240 		DRM_FORMAT(ARGB2101010),
241 		BITS_RGBA_FIXED(10, 10, 10, 2),
242 		.opaque_substitute = DRM_FORMAT_XRGB2101010,
243 	},
244 	{
245 		DRM_FORMAT(XBGR2101010),
246 		BITS_RGBA_FIXED(10, 10, 10, 0),
247 # if __BYTE_ORDER == __LITTLE_ENDIAN
248 		GL_FORMAT(GL_RGBA),
249 		GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
250 #endif
251 	},
252 	{
253 		DRM_FORMAT(ABGR2101010),
254 		BITS_RGBA_FIXED(10, 10, 10, 2),
255 		.opaque_substitute = DRM_FORMAT_XBGR2101010,
256 # if __BYTE_ORDER == __LITTLE_ENDIAN
257 		GL_FORMAT(GL_RGBA),
258 		GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
259 #endif
260 	},
261 	{
262 		DRM_FORMAT(RGBX1010102),
263 		BITS_RGBA_FIXED(10, 10, 10, 0),
264 	},
265 	{
266 		DRM_FORMAT(RGBA1010102),
267 		BITS_RGBA_FIXED(10, 10, 10, 2),
268 		.opaque_substitute = DRM_FORMAT_RGBX1010102,
269 	},
270 	{
271 		DRM_FORMAT(BGRX1010102),
272 		BITS_RGBA_FIXED(10, 10, 10, 0),
273 	},
274 	{
275 		DRM_FORMAT(BGRA1010102),
276 		BITS_RGBA_FIXED(10, 10, 10, 2),
277 		.opaque_substitute = DRM_FORMAT_BGRX1010102,
278 	},
279 	{
280 		DRM_FORMAT(YUYV),
281 		SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
282 		.num_planes = 1,
283 		.hsub = 2,
284 	},
285 	{
286 		DRM_FORMAT(YVYU),
287 		SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
288 		.num_planes = 1,
289 		.chroma_order = ORDER_VU,
290 		.hsub = 2,
291 	},
292 	{
293 		DRM_FORMAT(UYVY),
294 		SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
295 		.num_planes = 1,
296 		.luma_chroma_order = ORDER_CHROMA_LUMA,
297 		.hsub = 2,
298 	},
299 	{
300 		DRM_FORMAT(VYUY),
301 		SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
302 		.num_planes = 1,
303 		.luma_chroma_order = ORDER_CHROMA_LUMA,
304 		.chroma_order = ORDER_VU,
305 		.hsub = 2,
306 	},
307 	{
308 		DRM_FORMAT(NV12),
309 		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
310 		.num_planes = 2,
311 		.hsub = 2,
312 		.vsub = 2,
313 	},
314 	{
315 		DRM_FORMAT(NV21),
316 		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
317 		.num_planes = 2,
318 		.chroma_order = ORDER_VU,
319 		.hsub = 2,
320 		.vsub = 2,
321 	},
322 	{
323 		DRM_FORMAT(NV16),
324 		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
325 		.num_planes = 2,
326 		.hsub = 2,
327 		.vsub = 1,
328 	},
329 	{
330 		DRM_FORMAT(NV61),
331 		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
332 		.num_planes = 2,
333 		.chroma_order = ORDER_VU,
334 		.hsub = 2,
335 		.vsub = 1,
336 	},
337 	{
338 		DRM_FORMAT(NV24),
339 		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
340 		.num_planes = 2,
341 	},
342 	{
343 		DRM_FORMAT(NV42),
344 		SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
345 		.num_planes = 2,
346 		.chroma_order = ORDER_VU,
347 	},
348 	{
349 		DRM_FORMAT(YUV410),
350 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
351 		.num_planes = 3,
352 		.hsub = 4,
353 		.vsub = 4,
354 	},
355 	{
356 		DRM_FORMAT(YVU410),
357 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
358 		.num_planes = 3,
359 		.chroma_order = ORDER_VU,
360 		.hsub = 4,
361 		.vsub = 4,
362 	},
363 	{
364 		DRM_FORMAT(YUV411),
365 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
366 		.num_planes = 3,
367 		.hsub = 4,
368 		.vsub = 1,
369 	},
370 	{
371 		DRM_FORMAT(YVU411),
372 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
373 		.num_planes = 3,
374 		.chroma_order = ORDER_VU,
375 		.hsub = 4,
376 		.vsub = 1,
377 	},
378 	{
379 		DRM_FORMAT(YUV420),
380 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
381 		.num_planes = 3,
382 		.hsub = 2,
383 		.vsub = 2,
384 	},
385 	{
386 		DRM_FORMAT(YVU420),
387 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
388 		.num_planes = 3,
389 		.chroma_order = ORDER_VU,
390 		.hsub = 2,
391 		.vsub = 2,
392 	},
393 	{
394 		DRM_FORMAT(YUV422),
395 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
396 		.num_planes = 3,
397 		.hsub = 2,
398 		.vsub = 1,
399 	},
400 	{
401 		DRM_FORMAT(YVU422),
402 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
403 		.num_planes = 3,
404 		.chroma_order = ORDER_VU,
405 		.hsub = 2,
406 		.vsub = 1,
407 	},
408 	{
409 		DRM_FORMAT(YUV444),
410 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
411 		.num_planes = 3,
412 	},
413 	{
414 		DRM_FORMAT(YVU444),
415 		SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
416 		.num_planes = 3,
417 		.chroma_order = ORDER_VU,
418 	},
419 };
420 
421 WL_EXPORT const struct pixel_format_info *
pixel_format_get_info_shm(uint32_t format)422 pixel_format_get_info_shm(uint32_t format)
423 {
424 	if (format == WL_SHM_FORMAT_XRGB8888)
425 		return pixel_format_get_info(DRM_FORMAT_XRGB8888);
426 	else if (format == WL_SHM_FORMAT_ARGB8888)
427 		return pixel_format_get_info(DRM_FORMAT_ARGB8888);
428 	else
429 		return pixel_format_get_info(format);
430 }
431 
432 WL_EXPORT const struct pixel_format_info *
pixel_format_get_info(uint32_t format)433 pixel_format_get_info(uint32_t format)
434 {
435 	unsigned int i;
436 
437 	for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
438 		if (pixel_format_table[i].format == format)
439 			return &pixel_format_table[i];
440 	}
441 
442 	return NULL;
443 }
444 
445 WL_EXPORT const struct pixel_format_info *
pixel_format_get_info_by_drm_name(const char * drm_format_name)446 pixel_format_get_info_by_drm_name(const char *drm_format_name)
447 {
448 	const struct pixel_format_info *info;
449 	unsigned int i;
450 
451 	for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
452 		info = &pixel_format_table[i];
453 		if (strcasecmp(info->drm_format_name, drm_format_name) == 0)
454 			return info;
455 	}
456 
457 	return NULL;
458 }
459 
460 WL_EXPORT unsigned int
pixel_format_get_plane_count(const struct pixel_format_info * info)461 pixel_format_get_plane_count(const struct pixel_format_info *info)
462 {
463 	return info->num_planes ? info->num_planes : 1;
464 }
465 
466 WL_EXPORT bool
pixel_format_is_opaque(const struct pixel_format_info * info)467 pixel_format_is_opaque(const struct pixel_format_info *info)
468 {
469 	return !info->opaque_substitute;
470 }
471 
472 WL_EXPORT const struct pixel_format_info *
pixel_format_get_opaque_substitute(const struct pixel_format_info * info)473 pixel_format_get_opaque_substitute(const struct pixel_format_info *info)
474 {
475 	if (!info->opaque_substitute)
476 		return info;
477 	else
478 		return pixel_format_get_info(info->opaque_substitute);
479 }
480 
481 WL_EXPORT const struct pixel_format_info *
pixel_format_get_info_by_opaque_substitute(uint32_t format)482 pixel_format_get_info_by_opaque_substitute(uint32_t format)
483 {
484 	unsigned int i;
485 
486 	for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
487 		if (pixel_format_table[i].opaque_substitute == format)
488 			return &pixel_format_table[i];
489 	}
490 
491 	return NULL;
492 }
493 
494 WL_EXPORT unsigned int
pixel_format_width_for_plane(const struct pixel_format_info * info,unsigned int plane,unsigned int width)495 pixel_format_width_for_plane(const struct pixel_format_info *info,
496 			     unsigned int plane,
497 			     unsigned int width)
498 {
499 	/* We don't support any formats where the first plane is subsampled. */
500 	if (plane == 0 || !info->hsub)
501 		return width;
502 
503 	return width / info->hsub;
504 }
505 
506 WL_EXPORT unsigned int
pixel_format_height_for_plane(const struct pixel_format_info * info,unsigned int plane,unsigned int height)507 pixel_format_height_for_plane(const struct pixel_format_info *info,
508 			      unsigned int plane,
509 			      unsigned int height)
510 {
511 	/* We don't support any formats where the first plane is subsampled. */
512 	if (plane == 0 || !info->vsub)
513 		return height;
514 
515 	return height / info->vsub;
516 }
517