blob: c64a9b9e56cca9f7a46f069266061a789a33a919 [file] [log] [blame]
Daniel Stone903721a2017-04-04 17:54:20 +01001/*
2 * Copyright © 2016 Collabora, Ltd.
Pekka Paalanene7c91b62018-09-26 14:00:34 +03003 * Copyright (c) 2018 DisplayLink (UK) Ltd.
Daniel Stone903721a2017-04-04 17:54:20 +01004 *
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>
Pekka Paalanenf5ed7432018-09-26 14:26:53 +030033#include <string.h>
Daniel Stone903721a2017-04-04 17:54:20 +010034#include <drm_fourcc.h>
35
36#include "helpers.h"
37#include "wayland-util.h"
38#include "pixel-formats.h"
39
40#if ENABLE_EGL
41#include <EGL/egl.h>
42#include <EGL/eglext.h>
43#include <GLES2/gl2.h>
44#include <GLES2/gl2ext.h>
45#define GL_FORMAT(fmt) .gl_format = (fmt)
46#define GL_TYPE(type) .gl_type = (type)
47#define SAMPLER_TYPE(type) .sampler_type = (type)
48#else
49#define GL_FORMAT(fmt) .gl_format = 0
50#define GL_TYPE(type) .gl_type = 0
51#define SAMPLER_TYPE(type) .sampler_type = 0
52#endif
53
Pekka Paalanene7c91b62018-09-26 14:00:34 +030054#define DRM_FORMAT(f) .format = DRM_FORMAT_ ## f, .drm_format_name = #f
55
Daniel Stone903721a2017-04-04 17:54:20 +010056#include "weston-egl-ext.h"
57
58/**
59 * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are
60 * supported. Indexed/greyscale formats, and formats not containing complete
61 * colour channels, are not supported.
62 */
63static const struct pixel_format_info pixel_format_table[] = {
64 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030065 DRM_FORMAT(XRGB4444),
Daniel Stone903721a2017-04-04 17:54:20 +010066 },
67 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030068 DRM_FORMAT(ARGB4444),
Daniel Stone903721a2017-04-04 17:54:20 +010069 .opaque_substitute = DRM_FORMAT_XRGB4444,
70 },
71 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030072 DRM_FORMAT(XBGR4444),
Daniel Stone903721a2017-04-04 17:54:20 +010073 },
74 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030075 DRM_FORMAT(ABGR4444),
Daniel Stone903721a2017-04-04 17:54:20 +010076 .opaque_substitute = DRM_FORMAT_XBGR4444,
77 },
78 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030079 DRM_FORMAT(RGBX4444),
Daniel Stone903721a2017-04-04 17:54:20 +010080# if __BYTE_ORDER == __LITTLE_ENDIAN
81 GL_FORMAT(GL_RGBA),
82 GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
83#endif
84 },
85 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030086 DRM_FORMAT(RGBA4444),
Daniel Stone903721a2017-04-04 17:54:20 +010087 .opaque_substitute = DRM_FORMAT_RGBX4444,
88# if __BYTE_ORDER == __LITTLE_ENDIAN
89 GL_FORMAT(GL_RGBA),
90 GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
91#endif
92 },
93 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030094 DRM_FORMAT(BGRX4444),
Daniel Stone903721a2017-04-04 17:54:20 +010095 },
96 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030097 DRM_FORMAT(BGRA4444),
Daniel Stone903721a2017-04-04 17:54:20 +010098 .opaque_substitute = DRM_FORMAT_BGRX4444,
99 },
100 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300101 DRM_FORMAT(XRGB1555),
Daniel Stone903721a2017-04-04 17:54:20 +0100102 .depth = 15,
103 .bpp = 16,
104 },
105 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300106 DRM_FORMAT(ARGB1555),
Daniel Stone903721a2017-04-04 17:54:20 +0100107 .opaque_substitute = DRM_FORMAT_XRGB1555,
108 },
109 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300110 DRM_FORMAT(XBGR1555),
Daniel Stone903721a2017-04-04 17:54:20 +0100111 },
112 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300113 DRM_FORMAT(ABGR1555),
Daniel Stone903721a2017-04-04 17:54:20 +0100114 .opaque_substitute = DRM_FORMAT_XBGR1555,
115 },
116 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300117 DRM_FORMAT(RGBX5551),
Daniel Stone903721a2017-04-04 17:54:20 +0100118# if __BYTE_ORDER == __LITTLE_ENDIAN
119 GL_FORMAT(GL_RGBA),
120 GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
121#endif
122 },
123 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300124 DRM_FORMAT(RGBA5551),
Daniel Stone903721a2017-04-04 17:54:20 +0100125 .opaque_substitute = DRM_FORMAT_RGBX5551,
126# if __BYTE_ORDER == __LITTLE_ENDIAN
127 GL_FORMAT(GL_RGBA),
128 GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
129#endif
130 },
131 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300132 DRM_FORMAT(BGRX5551),
Daniel Stone903721a2017-04-04 17:54:20 +0100133 },
134 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300135 DRM_FORMAT(BGRA5551),
Daniel Stone903721a2017-04-04 17:54:20 +0100136 .opaque_substitute = DRM_FORMAT_BGRX5551,
137 },
138 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300139 DRM_FORMAT(RGB565),
Daniel Stone903721a2017-04-04 17:54:20 +0100140 .depth = 16,
141 .bpp = 16,
142# if __BYTE_ORDER == __LITTLE_ENDIAN
143 GL_FORMAT(GL_RGB),
144 GL_TYPE(GL_UNSIGNED_SHORT_5_6_5),
145#endif
146 },
147 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300148 DRM_FORMAT(BGR565),
Daniel Stone903721a2017-04-04 17:54:20 +0100149 },
150 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300151 DRM_FORMAT(RGB888),
Daniel Stone903721a2017-04-04 17:54:20 +0100152 },
153 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300154 DRM_FORMAT(BGR888),
Daniel Stone903721a2017-04-04 17:54:20 +0100155 GL_FORMAT(GL_RGB),
156 GL_TYPE(GL_UNSIGNED_BYTE),
157 },
158 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300159 DRM_FORMAT(XRGB8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100160 .depth = 24,
161 .bpp = 32,
162 GL_FORMAT(GL_BGRA_EXT),
163 GL_TYPE(GL_UNSIGNED_BYTE),
164 },
165 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300166 DRM_FORMAT(ARGB8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100167 .opaque_substitute = DRM_FORMAT_XRGB8888,
168 .depth = 32,
169 .bpp = 32,
170 GL_FORMAT(GL_BGRA_EXT),
171 GL_TYPE(GL_UNSIGNED_BYTE),
172 },
173 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300174 DRM_FORMAT(XBGR8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100175 GL_FORMAT(GL_RGBA),
176 GL_TYPE(GL_UNSIGNED_BYTE),
177 },
178 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300179 DRM_FORMAT(ABGR8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100180 .opaque_substitute = DRM_FORMAT_XBGR8888,
181 GL_FORMAT(GL_RGBA),
182 GL_TYPE(GL_UNSIGNED_BYTE),
183 },
184 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300185 DRM_FORMAT(RGBX8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100186 },
187 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300188 DRM_FORMAT(RGBA8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100189 .opaque_substitute = DRM_FORMAT_RGBX8888,
190 },
191 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300192 DRM_FORMAT(BGRX8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100193 },
194 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300195 DRM_FORMAT(BGRA8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100196 .opaque_substitute = DRM_FORMAT_BGRX8888,
197 },
198 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300199 DRM_FORMAT(XRGB2101010),
Daniel Stone903721a2017-04-04 17:54:20 +0100200 .depth = 30,
201 .bpp = 32,
202 },
203 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300204 DRM_FORMAT(ARGB2101010),
Daniel Stone903721a2017-04-04 17:54:20 +0100205 .opaque_substitute = DRM_FORMAT_XRGB2101010,
206 },
207 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300208 DRM_FORMAT(XBGR2101010),
Daniel Stone903721a2017-04-04 17:54:20 +0100209# if __BYTE_ORDER == __LITTLE_ENDIAN
210 GL_FORMAT(GL_RGBA),
211 GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
212#endif
213 },
214 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300215 DRM_FORMAT(ABGR2101010),
Daniel Stone903721a2017-04-04 17:54:20 +0100216 .opaque_substitute = DRM_FORMAT_XBGR2101010,
217# if __BYTE_ORDER == __LITTLE_ENDIAN
218 GL_FORMAT(GL_RGBA),
219 GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
220#endif
221 },
222 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300223 DRM_FORMAT(RGBX1010102),
Daniel Stone903721a2017-04-04 17:54:20 +0100224 },
225 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300226 DRM_FORMAT(RGBA1010102),
Daniel Stone903721a2017-04-04 17:54:20 +0100227 .opaque_substitute = DRM_FORMAT_RGBX1010102,
228 },
229 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300230 DRM_FORMAT(BGRX1010102),
Daniel Stone903721a2017-04-04 17:54:20 +0100231 },
232 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300233 DRM_FORMAT(BGRA1010102),
Daniel Stone903721a2017-04-04 17:54:20 +0100234 .opaque_substitute = DRM_FORMAT_BGRX1010102,
235 },
236 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300237 DRM_FORMAT(YUYV),
Daniel Stone903721a2017-04-04 17:54:20 +0100238 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
239 .num_planes = 1,
240 .hsub = 2,
241 },
242 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300243 DRM_FORMAT(YVYU),
Daniel Stone903721a2017-04-04 17:54:20 +0100244 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
245 .num_planes = 1,
246 .chroma_order = ORDER_VU,
247 .hsub = 2,
248 },
249 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300250 DRM_FORMAT(UYVY),
Daniel Stone903721a2017-04-04 17:54:20 +0100251 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
252 .num_planes = 1,
253 .luma_chroma_order = ORDER_CHROMA_LUMA,
254 .hsub = 2,
255 },
256 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300257 DRM_FORMAT(VYUY),
Daniel Stone903721a2017-04-04 17:54:20 +0100258 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
259 .num_planes = 1,
260 .luma_chroma_order = ORDER_CHROMA_LUMA,
261 .chroma_order = ORDER_VU,
262 .hsub = 2,
263 },
264 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300265 DRM_FORMAT(NV12),
Daniel Stone903721a2017-04-04 17:54:20 +0100266 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
267 .num_planes = 2,
268 .hsub = 2,
269 .vsub = 2,
270 },
271 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300272 DRM_FORMAT(NV21),
Daniel Stone903721a2017-04-04 17:54:20 +0100273 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
274 .num_planes = 2,
275 .chroma_order = ORDER_VU,
276 .hsub = 2,
277 .vsub = 2,
278 },
279 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300280 DRM_FORMAT(NV16),
Daniel Stone903721a2017-04-04 17:54:20 +0100281 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
282 .num_planes = 2,
283 .hsub = 2,
284 .vsub = 1,
285 },
286 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300287 DRM_FORMAT(NV61),
Daniel Stone903721a2017-04-04 17:54:20 +0100288 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
289 .num_planes = 2,
290 .chroma_order = ORDER_VU,
291 .hsub = 2,
292 .vsub = 1,
293 },
294 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300295 DRM_FORMAT(NV24),
Daniel Stone903721a2017-04-04 17:54:20 +0100296 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
297 .num_planes = 2,
298 },
299 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300300 DRM_FORMAT(NV42),
Daniel Stone903721a2017-04-04 17:54:20 +0100301 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
302 .num_planes = 2,
303 .chroma_order = ORDER_VU,
304 },
305 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300306 DRM_FORMAT(YUV410),
Daniel Stone903721a2017-04-04 17:54:20 +0100307 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
308 .num_planes = 3,
309 .hsub = 4,
310 .vsub = 4,
311 },
312 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300313 DRM_FORMAT(YVU410),
Daniel Stone903721a2017-04-04 17:54:20 +0100314 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
315 .num_planes = 3,
316 .chroma_order = ORDER_VU,
317 .hsub = 4,
318 .vsub = 4,
319 },
320 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300321 DRM_FORMAT(YUV411),
Daniel Stone903721a2017-04-04 17:54:20 +0100322 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
323 .num_planes = 3,
324 .hsub = 4,
325 .vsub = 1,
326 },
327 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300328 DRM_FORMAT(YVU411),
Daniel Stone903721a2017-04-04 17:54:20 +0100329 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
330 .num_planes = 3,
331 .chroma_order = ORDER_VU,
332 .hsub = 4,
333 .vsub = 1,
334 },
335 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300336 DRM_FORMAT(YUV420),
Daniel Stone903721a2017-04-04 17:54:20 +0100337 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
338 .num_planes = 3,
339 .hsub = 2,
340 .vsub = 2,
341 },
342 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300343 DRM_FORMAT(YVU420),
Daniel Stone903721a2017-04-04 17:54:20 +0100344 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
345 .num_planes = 3,
346 .chroma_order = ORDER_VU,
347 .hsub = 2,
348 .vsub = 2,
349 },
350 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300351 DRM_FORMAT(YUV422),
Daniel Stone903721a2017-04-04 17:54:20 +0100352 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
353 .num_planes = 3,
354 .hsub = 2,
355 .vsub = 1,
356 },
357 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300358 DRM_FORMAT(YVU422),
Daniel Stone903721a2017-04-04 17:54:20 +0100359 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
360 .num_planes = 3,
361 .chroma_order = ORDER_VU,
362 .hsub = 2,
363 .vsub = 1,
364 },
365 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300366 DRM_FORMAT(YUV444),
Daniel Stone903721a2017-04-04 17:54:20 +0100367 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
368 .num_planes = 3,
369 },
370 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300371 DRM_FORMAT(YVU444),
Daniel Stone903721a2017-04-04 17:54:20 +0100372 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
373 .num_planes = 3,
374 .chroma_order = ORDER_VU,
375 },
376};
377
378WL_EXPORT const struct pixel_format_info *
379pixel_format_get_info(uint32_t format)
380{
381 unsigned int i;
382
383 for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
384 if (pixel_format_table[i].format == format)
385 return &pixel_format_table[i];
386 }
387
388 return NULL;
389}
390
Pekka Paalanenf5ed7432018-09-26 14:26:53 +0300391WL_EXPORT const struct pixel_format_info *
392pixel_format_get_info_by_drm_name(const char *drm_format_name)
393{
394 const struct pixel_format_info *info;
395 unsigned int i;
396
397 for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
398 info = &pixel_format_table[i];
399 if (strcasecmp(info->drm_format_name, drm_format_name) == 0)
400 return info;
401 }
402
403 return NULL;
404}
405
Daniel Stone903721a2017-04-04 17:54:20 +0100406WL_EXPORT unsigned int
407pixel_format_get_plane_count(const struct pixel_format_info *info)
408{
409 return info->num_planes ? info->num_planes : 1;
410}
411
412WL_EXPORT bool
413pixel_format_is_opaque(const struct pixel_format_info *info)
414{
415 return !info->opaque_substitute;
416}
417
418WL_EXPORT const struct pixel_format_info *
419pixel_format_get_opaque_substitute(const struct pixel_format_info *info)
420{
421 if (!info->opaque_substitute)
422 return info;
423 else
424 return pixel_format_get_info(info->opaque_substitute);
425}
426
427WL_EXPORT unsigned int
428pixel_format_width_for_plane(const struct pixel_format_info *info,
429 unsigned int plane,
430 unsigned int width)
431{
432 /* We don't support any formats where the first plane is subsampled. */
433 if (plane == 0 || !info->hsub)
434 return width;
435
436 return width / info->hsub;
437}
438
439WL_EXPORT unsigned int
440pixel_format_height_for_plane(const struct pixel_format_info *info,
441 unsigned int plane,
442 unsigned int height)
443{
444 /* We don't support any formats where the first plane is subsampled. */
445 if (plane == 0 || !info->vsub)
446 return height;
447
448 return height / info->vsub;
449}