blob: df84a9f3f02796af3b47bae026500218aa96f95f [file] [log] [blame]
Daniel Stone903721a2017-04-04 17:54:20 +01001/*
2 * Copyright © 2016 Collabora, Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Author: Daniel Stone <daniels@collabora.com>
24 */
25
26#include "config.h"
27
28#include <endian.h>
29#include <inttypes.h>
30#include <stdbool.h>
31#include <unistd.h>
32#include <drm_fourcc.h>
33
34#include "helpers.h"
35#include "wayland-util.h"
36#include "pixel-formats.h"
37
38#if ENABLE_EGL
39#include <EGL/egl.h>
40#include <EGL/eglext.h>
41#include <GLES2/gl2.h>
42#include <GLES2/gl2ext.h>
43#define GL_FORMAT(fmt) .gl_format = (fmt)
44#define GL_TYPE(type) .gl_type = (type)
45#define SAMPLER_TYPE(type) .sampler_type = (type)
46#else
47#define GL_FORMAT(fmt) .gl_format = 0
48#define GL_TYPE(type) .gl_type = 0
49#define SAMPLER_TYPE(type) .sampler_type = 0
50#endif
51
52#include "weston-egl-ext.h"
53
54/**
55 * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are
56 * supported. Indexed/greyscale formats, and formats not containing complete
57 * colour channels, are not supported.
58 */
59static const struct pixel_format_info pixel_format_table[] = {
60 {
61 .format = DRM_FORMAT_XRGB4444,
62 },
63 {
64 .format = DRM_FORMAT_ARGB4444,
65 .opaque_substitute = DRM_FORMAT_XRGB4444,
66 },
67 {
68 .format = DRM_FORMAT_XBGR4444,
69 },
70 {
71 .format = DRM_FORMAT_ABGR4444,
72 .opaque_substitute = DRM_FORMAT_XBGR4444,
73 },
74 {
75 .format = DRM_FORMAT_RGBX4444,
76# if __BYTE_ORDER == __LITTLE_ENDIAN
77 GL_FORMAT(GL_RGBA),
78 GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
79#endif
80 },
81 {
82 .format = DRM_FORMAT_RGBA4444,
83 .opaque_substitute = DRM_FORMAT_RGBX4444,
84# if __BYTE_ORDER == __LITTLE_ENDIAN
85 GL_FORMAT(GL_RGBA),
86 GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
87#endif
88 },
89 {
90 .format = DRM_FORMAT_BGRX4444,
91 },
92 {
93 .format = DRM_FORMAT_BGRA4444,
94 .opaque_substitute = DRM_FORMAT_BGRX4444,
95 },
96 {
97 .format = DRM_FORMAT_XRGB1555,
98 .depth = 15,
99 .bpp = 16,
100 },
101 {
102 .format = DRM_FORMAT_ARGB1555,
103 .opaque_substitute = DRM_FORMAT_XRGB1555,
104 },
105 {
106 .format = DRM_FORMAT_XBGR1555,
107 },
108 {
109 .format = DRM_FORMAT_ABGR1555,
110 .opaque_substitute = DRM_FORMAT_XBGR1555,
111 },
112 {
113 .format = DRM_FORMAT_RGBX5551,
114# if __BYTE_ORDER == __LITTLE_ENDIAN
115 GL_FORMAT(GL_RGBA),
116 GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
117#endif
118 },
119 {
120 .format = DRM_FORMAT_RGBA5551,
121 .opaque_substitute = DRM_FORMAT_RGBX5551,
122# if __BYTE_ORDER == __LITTLE_ENDIAN
123 GL_FORMAT(GL_RGBA),
124 GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
125#endif
126 },
127 {
128 .format = DRM_FORMAT_BGRX5551,
129 },
130 {
131 .format = DRM_FORMAT_BGRA5551,
132 .opaque_substitute = DRM_FORMAT_BGRX5551,
133 },
134 {
135 .format = DRM_FORMAT_RGB565,
136 .depth = 16,
137 .bpp = 16,
138# if __BYTE_ORDER == __LITTLE_ENDIAN
139 GL_FORMAT(GL_RGB),
140 GL_TYPE(GL_UNSIGNED_SHORT_5_6_5),
141#endif
142 },
143 {
144 .format = DRM_FORMAT_BGR565,
145 },
146 {
147 .format = DRM_FORMAT_RGB888,
148 },
149 {
150 .format = DRM_FORMAT_BGR888,
151 GL_FORMAT(GL_RGB),
152 GL_TYPE(GL_UNSIGNED_BYTE),
153 },
154 {
155 .format = DRM_FORMAT_XRGB8888,
156 .depth = 24,
157 .bpp = 32,
158 GL_FORMAT(GL_BGRA_EXT),
159 GL_TYPE(GL_UNSIGNED_BYTE),
160 },
161 {
162 .format = DRM_FORMAT_ARGB8888,
163 .opaque_substitute = DRM_FORMAT_XRGB8888,
164 .depth = 32,
165 .bpp = 32,
166 GL_FORMAT(GL_BGRA_EXT),
167 GL_TYPE(GL_UNSIGNED_BYTE),
168 },
169 {
170 .format = DRM_FORMAT_XBGR8888,
171 GL_FORMAT(GL_RGBA),
172 GL_TYPE(GL_UNSIGNED_BYTE),
173 },
174 {
175 .format = DRM_FORMAT_ABGR8888,
176 .opaque_substitute = DRM_FORMAT_XBGR8888,
177 GL_FORMAT(GL_RGBA),
178 GL_TYPE(GL_UNSIGNED_BYTE),
179 },
180 {
181 .format = DRM_FORMAT_RGBX8888,
182 },
183 {
184 .format = DRM_FORMAT_RGBA8888,
185 .opaque_substitute = DRM_FORMAT_RGBX8888,
186 },
187 {
188 .format = DRM_FORMAT_BGRX8888,
189 },
190 {
191 .format = DRM_FORMAT_BGRA8888,
192 .opaque_substitute = DRM_FORMAT_BGRX8888,
193 },
194 {
195 .format = DRM_FORMAT_XRGB2101010,
196 .depth = 30,
197 .bpp = 32,
198 },
199 {
200 .format = DRM_FORMAT_ARGB2101010,
201 .opaque_substitute = DRM_FORMAT_XRGB2101010,
202 },
203 {
204 .format = DRM_FORMAT_XBGR2101010,
205# if __BYTE_ORDER == __LITTLE_ENDIAN
206 GL_FORMAT(GL_RGBA),
207 GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
208#endif
209 },
210 {
211 .format = DRM_FORMAT_ABGR2101010,
212 .opaque_substitute = DRM_FORMAT_XBGR2101010,
213# if __BYTE_ORDER == __LITTLE_ENDIAN
214 GL_FORMAT(GL_RGBA),
215 GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
216#endif
217 },
218 {
219 .format = DRM_FORMAT_RGBX1010102,
220 },
221 {
222 .format = DRM_FORMAT_RGBA1010102,
223 .opaque_substitute = DRM_FORMAT_RGBX1010102,
224 },
225 {
226 .format = DRM_FORMAT_BGRX1010102,
227 },
228 {
229 .format = DRM_FORMAT_BGRA1010102,
230 .opaque_substitute = DRM_FORMAT_BGRX1010102,
231 },
232 {
233 .format = DRM_FORMAT_YUYV,
234 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
235 .num_planes = 1,
236 .hsub = 2,
237 },
238 {
239 .format = DRM_FORMAT_YVYU,
240 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
241 .num_planes = 1,
242 .chroma_order = ORDER_VU,
243 .hsub = 2,
244 },
245 {
246 .format = DRM_FORMAT_UYVY,
247 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
248 .num_planes = 1,
249 .luma_chroma_order = ORDER_CHROMA_LUMA,
250 .hsub = 2,
251 },
252 {
253 .format = DRM_FORMAT_VYUY,
254 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
255 .num_planes = 1,
256 .luma_chroma_order = ORDER_CHROMA_LUMA,
257 .chroma_order = ORDER_VU,
258 .hsub = 2,
259 },
260 {
261 .format = DRM_FORMAT_NV12,
262 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
263 .num_planes = 2,
264 .hsub = 2,
265 .vsub = 2,
266 },
267 {
268 .format = DRM_FORMAT_NV21,
269 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
270 .num_planes = 2,
271 .chroma_order = ORDER_VU,
272 .hsub = 2,
273 .vsub = 2,
274 },
275 {
276 .format = DRM_FORMAT_NV16,
277 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
278 .num_planes = 2,
279 .hsub = 2,
280 .vsub = 1,
281 },
282 {
283 .format = DRM_FORMAT_NV61,
284 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
285 .num_planes = 2,
286 .chroma_order = ORDER_VU,
287 .hsub = 2,
288 .vsub = 1,
289 },
290 {
291 .format = DRM_FORMAT_NV24,
292 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
293 .num_planes = 2,
294 },
295 {
296 .format = DRM_FORMAT_NV42,
297 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
298 .num_planes = 2,
299 .chroma_order = ORDER_VU,
300 },
301 {
302 .format = DRM_FORMAT_YUV410,
303 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
304 .num_planes = 3,
305 .hsub = 4,
306 .vsub = 4,
307 },
308 {
309 .format = DRM_FORMAT_YVU410,
310 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
311 .num_planes = 3,
312 .chroma_order = ORDER_VU,
313 .hsub = 4,
314 .vsub = 4,
315 },
316 {
317 .format = DRM_FORMAT_YUV411,
318 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
319 .num_planes = 3,
320 .hsub = 4,
321 .vsub = 1,
322 },
323 {
324 .format = DRM_FORMAT_YVU411,
325 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
326 .num_planes = 3,
327 .chroma_order = ORDER_VU,
328 .hsub = 4,
329 .vsub = 1,
330 },
331 {
332 .format = DRM_FORMAT_YUV420,
333 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
334 .num_planes = 3,
335 .hsub = 2,
336 .vsub = 2,
337 },
338 {
339 .format = DRM_FORMAT_YVU420,
340 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
341 .num_planes = 3,
342 .chroma_order = ORDER_VU,
343 .hsub = 2,
344 .vsub = 2,
345 },
346 {
347 .format = DRM_FORMAT_YUV422,
348 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
349 .num_planes = 3,
350 .hsub = 2,
351 .vsub = 1,
352 },
353 {
354 .format = DRM_FORMAT_YVU422,
355 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
356 .num_planes = 3,
357 .chroma_order = ORDER_VU,
358 .hsub = 2,
359 .vsub = 1,
360 },
361 {
362 .format = DRM_FORMAT_YUV444,
363 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
364 .num_planes = 3,
365 },
366 {
367 .format = DRM_FORMAT_YVU444,
368 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
369 .num_planes = 3,
370 .chroma_order = ORDER_VU,
371 },
372};
373
374WL_EXPORT const struct pixel_format_info *
375pixel_format_get_info(uint32_t format)
376{
377 unsigned int i;
378
379 for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
380 if (pixel_format_table[i].format == format)
381 return &pixel_format_table[i];
382 }
383
384 return NULL;
385}
386
387WL_EXPORT unsigned int
388pixel_format_get_plane_count(const struct pixel_format_info *info)
389{
390 return info->num_planes ? info->num_planes : 1;
391}
392
393WL_EXPORT bool
394pixel_format_is_opaque(const struct pixel_format_info *info)
395{
396 return !info->opaque_substitute;
397}
398
399WL_EXPORT const struct pixel_format_info *
400pixel_format_get_opaque_substitute(const struct pixel_format_info *info)
401{
402 if (!info->opaque_substitute)
403 return info;
404 else
405 return pixel_format_get_info(info->opaque_substitute);
406}
407
408WL_EXPORT unsigned int
409pixel_format_width_for_plane(const struct pixel_format_info *info,
410 unsigned int plane,
411 unsigned int width)
412{
413 /* We don't support any formats where the first plane is subsampled. */
414 if (plane == 0 || !info->hsub)
415 return width;
416
417 return width / info->hsub;
418}
419
420WL_EXPORT unsigned int
421pixel_format_height_for_plane(const struct pixel_format_info *info,
422 unsigned int plane,
423 unsigned int height)
424{
425 /* We don't support any formats where the first plane is subsampled. */
426 if (plane == 0 || !info->vsub)
427 return height;
428
429 return height / info->vsub;
430}