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