blob: 23d7d5b9f769b60b062d56576b4c2619ffccdc42 [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>
Marius Vlada9a63042018-11-20 17:04:57 +020035#include <wayland-client-protocol.h>
Daniel Stone903721a2017-04-04 17:54:20 +010036
37#include "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
Pekka Paalanene7c91b62018-09-26 14:00:34 +030055#define DRM_FORMAT(f) .format = DRM_FORMAT_ ## f, .drm_format_name = #f
56
Daniel Stone903721a2017-04-04 17:54:20 +010057#include "weston-egl-ext.h"
58
59/**
60 * Table of DRM formats supported by Weston; RGB, ARGB and YUV formats are
61 * supported. Indexed/greyscale formats, and formats not containing complete
62 * colour channels, are not supported.
63 */
64static const struct pixel_format_info pixel_format_table[] = {
65 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030066 DRM_FORMAT(XRGB4444),
Daniel Stone903721a2017-04-04 17:54:20 +010067 },
68 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030069 DRM_FORMAT(ARGB4444),
Daniel Stone903721a2017-04-04 17:54:20 +010070 .opaque_substitute = DRM_FORMAT_XRGB4444,
71 },
72 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030073 DRM_FORMAT(XBGR4444),
Daniel Stone903721a2017-04-04 17:54:20 +010074 },
75 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030076 DRM_FORMAT(ABGR4444),
Daniel Stone903721a2017-04-04 17:54:20 +010077 .opaque_substitute = DRM_FORMAT_XBGR4444,
78 },
79 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030080 DRM_FORMAT(RGBX4444),
Daniel Stone903721a2017-04-04 17:54:20 +010081# if __BYTE_ORDER == __LITTLE_ENDIAN
82 GL_FORMAT(GL_RGBA),
83 GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
84#endif
85 },
86 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030087 DRM_FORMAT(RGBA4444),
Daniel Stone903721a2017-04-04 17:54:20 +010088 .opaque_substitute = DRM_FORMAT_RGBX4444,
89# if __BYTE_ORDER == __LITTLE_ENDIAN
90 GL_FORMAT(GL_RGBA),
91 GL_TYPE(GL_UNSIGNED_SHORT_4_4_4_4),
92#endif
93 },
94 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030095 DRM_FORMAT(BGRX4444),
Daniel Stone903721a2017-04-04 17:54:20 +010096 },
97 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +030098 DRM_FORMAT(BGRA4444),
Daniel Stone903721a2017-04-04 17:54:20 +010099 .opaque_substitute = DRM_FORMAT_BGRX4444,
100 },
101 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300102 DRM_FORMAT(XRGB1555),
Daniel Stone903721a2017-04-04 17:54:20 +0100103 .depth = 15,
104 .bpp = 16,
105 },
106 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300107 DRM_FORMAT(ARGB1555),
Daniel Stone903721a2017-04-04 17:54:20 +0100108 .opaque_substitute = DRM_FORMAT_XRGB1555,
109 },
110 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300111 DRM_FORMAT(XBGR1555),
Daniel Stone903721a2017-04-04 17:54:20 +0100112 },
113 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300114 DRM_FORMAT(ABGR1555),
Daniel Stone903721a2017-04-04 17:54:20 +0100115 .opaque_substitute = DRM_FORMAT_XBGR1555,
116 },
117 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300118 DRM_FORMAT(RGBX5551),
Daniel Stone903721a2017-04-04 17:54:20 +0100119# if __BYTE_ORDER == __LITTLE_ENDIAN
120 GL_FORMAT(GL_RGBA),
121 GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
122#endif
123 },
124 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300125 DRM_FORMAT(RGBA5551),
Daniel Stone903721a2017-04-04 17:54:20 +0100126 .opaque_substitute = DRM_FORMAT_RGBX5551,
127# if __BYTE_ORDER == __LITTLE_ENDIAN
128 GL_FORMAT(GL_RGBA),
129 GL_TYPE(GL_UNSIGNED_SHORT_5_5_5_1),
130#endif
131 },
132 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300133 DRM_FORMAT(BGRX5551),
Daniel Stone903721a2017-04-04 17:54:20 +0100134 },
135 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300136 DRM_FORMAT(BGRA5551),
Daniel Stone903721a2017-04-04 17:54:20 +0100137 .opaque_substitute = DRM_FORMAT_BGRX5551,
138 },
139 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300140 DRM_FORMAT(RGB565),
Daniel Stone903721a2017-04-04 17:54:20 +0100141 .depth = 16,
142 .bpp = 16,
143# if __BYTE_ORDER == __LITTLE_ENDIAN
144 GL_FORMAT(GL_RGB),
145 GL_TYPE(GL_UNSIGNED_SHORT_5_6_5),
146#endif
147 },
148 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300149 DRM_FORMAT(BGR565),
Daniel Stone903721a2017-04-04 17:54:20 +0100150 },
151 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300152 DRM_FORMAT(RGB888),
Daniel Stone903721a2017-04-04 17:54:20 +0100153 },
154 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300155 DRM_FORMAT(BGR888),
Daniel Stone903721a2017-04-04 17:54:20 +0100156 GL_FORMAT(GL_RGB),
157 GL_TYPE(GL_UNSIGNED_BYTE),
158 },
159 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300160 DRM_FORMAT(XRGB8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100161 .depth = 24,
162 .bpp = 32,
163 GL_FORMAT(GL_BGRA_EXT),
164 GL_TYPE(GL_UNSIGNED_BYTE),
165 },
166 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300167 DRM_FORMAT(ARGB8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100168 .opaque_substitute = DRM_FORMAT_XRGB8888,
169 .depth = 32,
170 .bpp = 32,
171 GL_FORMAT(GL_BGRA_EXT),
172 GL_TYPE(GL_UNSIGNED_BYTE),
173 },
174 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300175 DRM_FORMAT(XBGR8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100176 GL_FORMAT(GL_RGBA),
177 GL_TYPE(GL_UNSIGNED_BYTE),
178 },
179 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300180 DRM_FORMAT(ABGR8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100181 .opaque_substitute = DRM_FORMAT_XBGR8888,
182 GL_FORMAT(GL_RGBA),
183 GL_TYPE(GL_UNSIGNED_BYTE),
184 },
185 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300186 DRM_FORMAT(RGBX8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100187 },
188 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300189 DRM_FORMAT(RGBA8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100190 .opaque_substitute = DRM_FORMAT_RGBX8888,
191 },
192 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300193 DRM_FORMAT(BGRX8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100194 },
195 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300196 DRM_FORMAT(BGRA8888),
Daniel Stone903721a2017-04-04 17:54:20 +0100197 .opaque_substitute = DRM_FORMAT_BGRX8888,
198 },
199 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300200 DRM_FORMAT(XRGB2101010),
Daniel Stone903721a2017-04-04 17:54:20 +0100201 .depth = 30,
202 .bpp = 32,
203 },
204 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300205 DRM_FORMAT(ARGB2101010),
Daniel Stone903721a2017-04-04 17:54:20 +0100206 .opaque_substitute = DRM_FORMAT_XRGB2101010,
207 },
208 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300209 DRM_FORMAT(XBGR2101010),
Daniel Stone903721a2017-04-04 17:54:20 +0100210# if __BYTE_ORDER == __LITTLE_ENDIAN
211 GL_FORMAT(GL_RGBA),
212 GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
213#endif
214 },
215 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300216 DRM_FORMAT(ABGR2101010),
Daniel Stone903721a2017-04-04 17:54:20 +0100217 .opaque_substitute = DRM_FORMAT_XBGR2101010,
218# if __BYTE_ORDER == __LITTLE_ENDIAN
219 GL_FORMAT(GL_RGBA),
220 GL_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV_EXT),
221#endif
222 },
223 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300224 DRM_FORMAT(RGBX1010102),
Daniel Stone903721a2017-04-04 17:54:20 +0100225 },
226 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300227 DRM_FORMAT(RGBA1010102),
Daniel Stone903721a2017-04-04 17:54:20 +0100228 .opaque_substitute = DRM_FORMAT_RGBX1010102,
229 },
230 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300231 DRM_FORMAT(BGRX1010102),
Daniel Stone903721a2017-04-04 17:54:20 +0100232 },
233 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300234 DRM_FORMAT(BGRA1010102),
Daniel Stone903721a2017-04-04 17:54:20 +0100235 .opaque_substitute = DRM_FORMAT_BGRX1010102,
236 },
237 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300238 DRM_FORMAT(YUYV),
Daniel Stone903721a2017-04-04 17:54:20 +0100239 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
240 .num_planes = 1,
241 .hsub = 2,
242 },
243 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300244 DRM_FORMAT(YVYU),
Daniel Stone903721a2017-04-04 17:54:20 +0100245 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
246 .num_planes = 1,
247 .chroma_order = ORDER_VU,
248 .hsub = 2,
249 },
250 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300251 DRM_FORMAT(UYVY),
Daniel Stone903721a2017-04-04 17:54:20 +0100252 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
253 .num_planes = 1,
254 .luma_chroma_order = ORDER_CHROMA_LUMA,
255 .hsub = 2,
256 },
257 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300258 DRM_FORMAT(VYUY),
Daniel Stone903721a2017-04-04 17:54:20 +0100259 SAMPLER_TYPE(EGL_TEXTURE_Y_XUXV_WL),
260 .num_planes = 1,
261 .luma_chroma_order = ORDER_CHROMA_LUMA,
262 .chroma_order = ORDER_VU,
263 .hsub = 2,
264 },
265 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300266 DRM_FORMAT(NV12),
Daniel Stone903721a2017-04-04 17:54:20 +0100267 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
268 .num_planes = 2,
269 .hsub = 2,
270 .vsub = 2,
271 },
272 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300273 DRM_FORMAT(NV21),
Daniel Stone903721a2017-04-04 17:54:20 +0100274 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
275 .num_planes = 2,
276 .chroma_order = ORDER_VU,
277 .hsub = 2,
278 .vsub = 2,
279 },
280 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300281 DRM_FORMAT(NV16),
Daniel Stone903721a2017-04-04 17:54:20 +0100282 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
283 .num_planes = 2,
284 .hsub = 2,
285 .vsub = 1,
286 },
287 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300288 DRM_FORMAT(NV61),
Daniel Stone903721a2017-04-04 17:54:20 +0100289 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
290 .num_planes = 2,
291 .chroma_order = ORDER_VU,
292 .hsub = 2,
293 .vsub = 1,
294 },
295 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300296 DRM_FORMAT(NV24),
Daniel Stone903721a2017-04-04 17:54:20 +0100297 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
298 .num_planes = 2,
299 },
300 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300301 DRM_FORMAT(NV42),
Daniel Stone903721a2017-04-04 17:54:20 +0100302 SAMPLER_TYPE(EGL_TEXTURE_Y_UV_WL),
303 .num_planes = 2,
304 .chroma_order = ORDER_VU,
305 },
306 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300307 DRM_FORMAT(YUV410),
Daniel Stone903721a2017-04-04 17:54:20 +0100308 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
309 .num_planes = 3,
310 .hsub = 4,
311 .vsub = 4,
312 },
313 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300314 DRM_FORMAT(YVU410),
Daniel Stone903721a2017-04-04 17:54:20 +0100315 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
316 .num_planes = 3,
317 .chroma_order = ORDER_VU,
318 .hsub = 4,
319 .vsub = 4,
320 },
321 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300322 DRM_FORMAT(YUV411),
Daniel Stone903721a2017-04-04 17:54:20 +0100323 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
324 .num_planes = 3,
325 .hsub = 4,
326 .vsub = 1,
327 },
328 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300329 DRM_FORMAT(YVU411),
Daniel Stone903721a2017-04-04 17:54:20 +0100330 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
331 .num_planes = 3,
332 .chroma_order = ORDER_VU,
333 .hsub = 4,
334 .vsub = 1,
335 },
336 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300337 DRM_FORMAT(YUV420),
Daniel Stone903721a2017-04-04 17:54:20 +0100338 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
339 .num_planes = 3,
340 .hsub = 2,
341 .vsub = 2,
342 },
343 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300344 DRM_FORMAT(YVU420),
Daniel Stone903721a2017-04-04 17:54:20 +0100345 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
346 .num_planes = 3,
347 .chroma_order = ORDER_VU,
348 .hsub = 2,
349 .vsub = 2,
350 },
351 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300352 DRM_FORMAT(YUV422),
Daniel Stone903721a2017-04-04 17:54:20 +0100353 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
354 .num_planes = 3,
355 .hsub = 2,
356 .vsub = 1,
357 },
358 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300359 DRM_FORMAT(YVU422),
Daniel Stone903721a2017-04-04 17:54:20 +0100360 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
361 .num_planes = 3,
362 .chroma_order = ORDER_VU,
363 .hsub = 2,
364 .vsub = 1,
365 },
366 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300367 DRM_FORMAT(YUV444),
Daniel Stone903721a2017-04-04 17:54:20 +0100368 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
369 .num_planes = 3,
370 },
371 {
Pekka Paalanene7c91b62018-09-26 14:00:34 +0300372 DRM_FORMAT(YVU444),
Daniel Stone903721a2017-04-04 17:54:20 +0100373 SAMPLER_TYPE(EGL_TEXTURE_Y_U_V_WL),
374 .num_planes = 3,
375 .chroma_order = ORDER_VU,
376 },
377};
378
379WL_EXPORT const struct pixel_format_info *
Marius Vlada9a63042018-11-20 17:04:57 +0200380pixel_format_get_info_shm(uint32_t format)
381{
382 if (format == WL_SHM_FORMAT_XRGB8888)
383 return pixel_format_get_info(DRM_FORMAT_XRGB8888);
384 else if (format == WL_SHM_FORMAT_ARGB8888)
385 return pixel_format_get_info(DRM_FORMAT_ARGB8888);
386 else
387 return pixel_format_get_info(format);
388}
389
390WL_EXPORT const struct pixel_format_info *
Daniel Stone903721a2017-04-04 17:54:20 +0100391pixel_format_get_info(uint32_t format)
392{
393 unsigned int i;
394
395 for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
396 if (pixel_format_table[i].format == format)
397 return &pixel_format_table[i];
398 }
399
400 return NULL;
401}
402
Pekka Paalanenf5ed7432018-09-26 14:26:53 +0300403WL_EXPORT const struct pixel_format_info *
404pixel_format_get_info_by_drm_name(const char *drm_format_name)
405{
406 const struct pixel_format_info *info;
407 unsigned int i;
408
409 for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
410 info = &pixel_format_table[i];
411 if (strcasecmp(info->drm_format_name, drm_format_name) == 0)
412 return info;
413 }
414
415 return NULL;
416}
417
Daniel Stone903721a2017-04-04 17:54:20 +0100418WL_EXPORT unsigned int
419pixel_format_get_plane_count(const struct pixel_format_info *info)
420{
421 return info->num_planes ? info->num_planes : 1;
422}
423
424WL_EXPORT bool
425pixel_format_is_opaque(const struct pixel_format_info *info)
426{
427 return !info->opaque_substitute;
428}
429
Daniel Stone903721a2017-04-04 17:54:20 +0100430WL_EXPORT const struct pixel_format_info *
431pixel_format_get_opaque_substitute(const struct pixel_format_info *info)
432{
433 if (!info->opaque_substitute)
434 return info;
435 else
436 return pixel_format_get_info(info->opaque_substitute);
437}
438
Pekka Paalanen8ba775d2019-09-13 14:44:24 +0300439WL_EXPORT const struct pixel_format_info *
440pixel_format_get_info_by_opaque_substitute(uint32_t format)
441{
442 unsigned int i;
443
444 for (i = 0; i < ARRAY_LENGTH(pixel_format_table); i++) {
445 if (pixel_format_table[i].opaque_substitute == format)
446 return &pixel_format_table[i];
447 }
448
449 return NULL;
450}
451
Daniel Stone903721a2017-04-04 17:54:20 +0100452WL_EXPORT unsigned int
453pixel_format_width_for_plane(const struct pixel_format_info *info,
454 unsigned int plane,
455 unsigned int width)
456{
457 /* We don't support any formats where the first plane is subsampled. */
458 if (plane == 0 || !info->hsub)
459 return width;
460
461 return width / info->hsub;
462}
463
464WL_EXPORT unsigned int
465pixel_format_height_for_plane(const struct pixel_format_info *info,
466 unsigned int plane,
467 unsigned int height)
468{
469 /* We don't support any formats where the first plane is subsampled. */
470 if (plane == 0 || !info->vsub)
471 return height;
472
473 return height / info->vsub;
474}