git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

scenefx/render/pixel_format.c (8.1K)

  1 #include <assert.h>
  2 #include <drm_fourcc.h>
  3 #include <wlr/util/log.h>
  4 #include "render/pixel_format.h"
  5 
  6 static const struct wlr_pixel_format_info pixel_format_info[] = {
  7 	{
  8 		.drm_format = DRM_FORMAT_XRGB8888,
  9 		.bytes_per_block = 4,
 10 	},
 11 	{
 12 		.drm_format = DRM_FORMAT_ARGB8888,
 13 		.opaque_substitute = DRM_FORMAT_XRGB8888,
 14 		.bytes_per_block = 4,
 15 	},
 16 	{
 17 		.drm_format = DRM_FORMAT_XBGR8888,
 18 		.bytes_per_block = 4,
 19 	},
 20 	{
 21 		.drm_format = DRM_FORMAT_ABGR8888,
 22 		.opaque_substitute = DRM_FORMAT_XBGR8888,
 23 		.bytes_per_block = 4,
 24 	},
 25 	{
 26 		.drm_format = DRM_FORMAT_RGBX8888,
 27 		.bytes_per_block = 4,
 28 	},
 29 	{
 30 		.drm_format = DRM_FORMAT_RGBA8888,
 31 		.opaque_substitute = DRM_FORMAT_RGBX8888,
 32 		.bytes_per_block = 4,
 33 	},
 34 	{
 35 		.drm_format = DRM_FORMAT_BGRX8888,
 36 		.bytes_per_block = 4,
 37 	},
 38 	{
 39 		.drm_format = DRM_FORMAT_BGRA8888,
 40 		.opaque_substitute = DRM_FORMAT_BGRX8888,
 41 		.bytes_per_block = 4,
 42 	},
 43 	{
 44 		.drm_format = DRM_FORMAT_R8,
 45 		.bytes_per_block = 1,
 46 	},
 47 	{
 48 		.drm_format = DRM_FORMAT_R16F,
 49 		.bytes_per_block = 2,
 50 	},
 51 	{
 52 		.drm_format = DRM_FORMAT_R32F,
 53 		.bytes_per_block = 4,
 54 	},
 55 	{
 56 		.drm_format = DRM_FORMAT_GR88,
 57 		.bytes_per_block = 2,
 58 	},
 59 	{
 60 		.drm_format = DRM_FORMAT_GR1616F,
 61 		.bytes_per_block = 4,
 62 	},
 63 	{
 64 		.drm_format = DRM_FORMAT_GR3232F,
 65 		.bytes_per_block = 8,
 66 	},
 67 	{
 68 		.drm_format = DRM_FORMAT_RGB888,
 69 		.bytes_per_block = 3,
 70 	},
 71 	{
 72 		.drm_format = DRM_FORMAT_BGR888,
 73 		.bytes_per_block = 3,
 74 	},
 75 	{
 76 		.drm_format = DRM_FORMAT_BGR161616,
 77 		.bytes_per_block = 6,
 78 	},
 79 	{
 80 		.drm_format = DRM_FORMAT_BGR161616F,
 81 		.bytes_per_block = 6,
 82 	},
 83 	{
 84 		.drm_format = DRM_FORMAT_BGR323232F,
 85 		.bytes_per_block = 12,
 86 	},
 87 	{
 88 		.drm_format = DRM_FORMAT_RGBX4444,
 89 		.bytes_per_block = 2,
 90 	},
 91 	{
 92 		.drm_format = DRM_FORMAT_RGBA4444,
 93 		.opaque_substitute = DRM_FORMAT_RGBX4444,
 94 		.bytes_per_block = 2,
 95 	},
 96 	{
 97 		.drm_format = DRM_FORMAT_BGRX4444,
 98 		.bytes_per_block = 2,
 99 	},
100 	{
101 		.drm_format = DRM_FORMAT_BGRA4444,
102 		.opaque_substitute = DRM_FORMAT_BGRX4444,
103 		.bytes_per_block = 2,
104 	},
105 	{
106 		.drm_format = DRM_FORMAT_RGBX5551,
107 		.bytes_per_block = 2,
108 	},
109 	{
110 		.drm_format = DRM_FORMAT_RGBA5551,
111 		.opaque_substitute = DRM_FORMAT_RGBX5551,
112 		.bytes_per_block = 2,
113 	},
114 	{
115 		.drm_format = DRM_FORMAT_BGRX5551,
116 		.bytes_per_block = 2,
117 	},
118 	{
119 		.drm_format = DRM_FORMAT_BGRA5551,
120 		.opaque_substitute = DRM_FORMAT_BGRX5551,
121 		.bytes_per_block = 2,
122 	},
123 	{
124 		.drm_format = DRM_FORMAT_XRGB1555,
125 		.bytes_per_block = 2,
126 	},
127 	{
128 		.drm_format = DRM_FORMAT_ARGB1555,
129 		.opaque_substitute = DRM_FORMAT_XRGB1555,
130 		.bytes_per_block = 2,
131 	},
132 	{
133 		.drm_format = DRM_FORMAT_RGB565,
134 		.bytes_per_block = 2,
135 	},
136 	{
137 		.drm_format = DRM_FORMAT_BGR565,
138 		.bytes_per_block = 2,
139 	},
140 	{
141 		.drm_format = DRM_FORMAT_XRGB2101010,
142 		.bytes_per_block = 4,
143 	},
144 	{
145 		.drm_format = DRM_FORMAT_ARGB2101010,
146 		.opaque_substitute = DRM_FORMAT_XRGB2101010,
147 		.bytes_per_block = 4,
148 	},
149 	{
150 		.drm_format = DRM_FORMAT_XBGR2101010,
151 		.bytes_per_block = 4,
152 	},
153 	{
154 		.drm_format = DRM_FORMAT_ABGR2101010,
155 		.opaque_substitute = DRM_FORMAT_XBGR2101010,
156 		.bytes_per_block = 4,
157 	},
158 	{
159 		.drm_format = DRM_FORMAT_XBGR16161616F,
160 		.bytes_per_block = 8,
161 	},
162 	{
163 		.drm_format = DRM_FORMAT_ABGR16161616F,
164 		.opaque_substitute = DRM_FORMAT_XBGR16161616F,
165 		.bytes_per_block = 8,
166 	},
167 	{
168 		.drm_format = DRM_FORMAT_ABGR32323232F,
169 		.bytes_per_block = 16,
170 	},
171 	{
172 		.drm_format = DRM_FORMAT_XBGR16161616,
173 		.bytes_per_block = 8,
174 	},
175 	{
176 		.drm_format = DRM_FORMAT_ABGR16161616,
177 		.opaque_substitute = DRM_FORMAT_XBGR16161616,
178 		.bytes_per_block = 8,
179 	},
180 	{
181 		.drm_format = DRM_FORMAT_YVYU,
182 		.bytes_per_block = 4,
183 		.block_width = 2,
184 		.block_height = 1,
185 	},
186 	{
187 		.drm_format = DRM_FORMAT_VYUY,
188 		.bytes_per_block = 4,
189 		.block_width = 2,
190 		.block_height = 1,
191 	},
192 };
193 
194 static const uint32_t opaque_pixel_formats[] = {
195 	DRM_FORMAT_XRGB8888,
196 	DRM_FORMAT_XBGR8888,
197 	DRM_FORMAT_RGBX8888,
198 	DRM_FORMAT_BGRX8888,
199 	DRM_FORMAT_R8,
200 	DRM_FORMAT_GR88,
201 	DRM_FORMAT_RGB888,
202 	DRM_FORMAT_BGR888,
203 	DRM_FORMAT_RGBX4444,
204 	DRM_FORMAT_BGRX4444,
205 	DRM_FORMAT_RGBX5551,
206 	DRM_FORMAT_BGRX5551,
207 	DRM_FORMAT_XRGB1555,
208 	DRM_FORMAT_RGB565,
209 	DRM_FORMAT_BGR565,
210 	DRM_FORMAT_XRGB2101010,
211 	DRM_FORMAT_XBGR2101010,
212 	DRM_FORMAT_XBGR16161616F,
213 	DRM_FORMAT_XBGR16161616,
214 	DRM_FORMAT_YVYU,
215 	DRM_FORMAT_VYUY,
216 	DRM_FORMAT_NV12,
217 	DRM_FORMAT_P010,
218 };
219 
220 static const size_t pixel_format_info_size =
221 	sizeof(pixel_format_info) / sizeof(pixel_format_info[0]);
222 
223 static const size_t opaque_pixel_formats_size =
224 	sizeof(opaque_pixel_formats) / sizeof(opaque_pixel_formats[0]);
225 
226 const struct wlr_pixel_format_info *drm_get_pixel_format_info(uint32_t fmt) {
227 	for (size_t i = 0; i < pixel_format_info_size; ++i) {
228 		if (pixel_format_info[i].drm_format == fmt) {
229 			return &pixel_format_info[i];
230 		}
231 	}
232 
233 	return NULL;
234 }
235 
236 uint32_t convert_wl_shm_format_to_drm(enum wl_shm_format fmt) {
237 	switch (fmt) {
238 	case WL_SHM_FORMAT_XRGB8888:
239 		return DRM_FORMAT_XRGB8888;
240 	case WL_SHM_FORMAT_ARGB8888:
241 		return DRM_FORMAT_ARGB8888;
242 	default:
243 		return (uint32_t)fmt;
244 	}
245 }
246 
247 enum wl_shm_format convert_drm_format_to_wl_shm(uint32_t fmt) {
248 	switch (fmt) {
249 	case DRM_FORMAT_XRGB8888:
250 		return WL_SHM_FORMAT_XRGB8888;
251 	case DRM_FORMAT_ARGB8888:
252 		return WL_SHM_FORMAT_ARGB8888;
253 	default:
254 		return (enum wl_shm_format)fmt;
255 	}
256 }
257 
258 uint32_t pixel_format_info_pixels_per_block(const struct wlr_pixel_format_info *info) {
259 	uint32_t pixels = info->block_width * info->block_height;
260 	return pixels > 0 ? pixels : 1;
261 }
262 
263 static int32_t div_round_up(int32_t dividend, int32_t divisor) {
264 	int32_t quotient = dividend / divisor;
265 	if (dividend % divisor != 0) {
266 		quotient++;
267 	}
268 	return quotient;
269 }
270 
271 int32_t pixel_format_info_min_stride(const struct wlr_pixel_format_info *fmt, int32_t width) {
272 	int32_t pixels_per_block = (int32_t)pixel_format_info_pixels_per_block(fmt);
273 	int32_t bytes_per_block = (int32_t)fmt->bytes_per_block;
274 	if (width > INT32_MAX / bytes_per_block) {
275 		wlr_log(WLR_DEBUG, "Invalid width %d (overflow)", width);
276 		return 0;
277 	}
278 	return div_round_up(width * bytes_per_block, pixels_per_block);
279 }
280 
281 bool pixel_format_info_check_stride(const struct wlr_pixel_format_info *fmt,
282 		int32_t stride, int32_t width) {
283 	int32_t bytes_per_block = (int32_t)fmt->bytes_per_block;
284 	if (stride % bytes_per_block != 0) {
285 		wlr_log(WLR_DEBUG, "Invalid stride %d (incompatible with %d "
286 			"bytes-per-block)", stride, bytes_per_block);
287 		return false;
288 	}
289 
290 	int32_t min_stride = pixel_format_info_min_stride(fmt, width);
291 	if (min_stride <= 0) {
292 		return false;
293 	} else if (stride < min_stride) {
294 		wlr_log(WLR_DEBUG, "Invalid stride %d (too small for %d "
295 			"bytes-per-block and width %d)", stride, bytes_per_block, width);
296 		return false;
297 	}
298 
299 	return true;
300 }
301 
302 bool pixel_format_has_alpha(uint32_t fmt) {
303 	for (size_t i = 0; i < opaque_pixel_formats_size; i++) {
304 		if (fmt == opaque_pixel_formats[i]) {
305 			return false;
306 		}
307 	}
308 	return true;
309 }
310 
311 bool pixel_format_is_ycbcr(uint32_t format) {
312 	switch (format) {
313 	case DRM_FORMAT_AYUV:
314 	case DRM_FORMAT_NV12:
315 	case DRM_FORMAT_NV15:
316 	case DRM_FORMAT_NV16:
317 	case DRM_FORMAT_NV20:
318 	case DRM_FORMAT_NV21:
319 	case DRM_FORMAT_NV24:
320 	case DRM_FORMAT_NV30:
321 	case DRM_FORMAT_NV42:
322 	case DRM_FORMAT_NV61:
323 	case DRM_FORMAT_P010:
324 	case DRM_FORMAT_P012:
325 	case DRM_FORMAT_P016:
326 	case DRM_FORMAT_P030:
327 	case DRM_FORMAT_P210:
328 	case DRM_FORMAT_Q401:
329 	case DRM_FORMAT_Q410:
330 	case DRM_FORMAT_S010:
331 	case DRM_FORMAT_S012:
332 	case DRM_FORMAT_S016:
333 	case DRM_FORMAT_S210:
334 	case DRM_FORMAT_S212:
335 	case DRM_FORMAT_S216:
336 	case DRM_FORMAT_S410:
337 	case DRM_FORMAT_S412:
338 	case DRM_FORMAT_S416:
339 	case DRM_FORMAT_UYVY:
340 	case DRM_FORMAT_VUY101010:
341 	case DRM_FORMAT_VUY888:
342 	case DRM_FORMAT_VYUY:
343 	case DRM_FORMAT_X0L0:
344 	case DRM_FORMAT_X0L2:
345 	case DRM_FORMAT_XVYU12_16161616:
346 	case DRM_FORMAT_XVYU16161616:
347 	case DRM_FORMAT_XVYU2101010:
348 	case DRM_FORMAT_XYUV8888:
349 	case DRM_FORMAT_Y0L0:
350 	case DRM_FORMAT_Y0L2:
351 	case DRM_FORMAT_Y210:
352 	case DRM_FORMAT_Y212:
353 	case DRM_FORMAT_Y216:
354 	case DRM_FORMAT_Y410:
355 	case DRM_FORMAT_Y412:
356 	case DRM_FORMAT_Y416:
357 	case DRM_FORMAT_YUV410:
358 	case DRM_FORMAT_YUV411:
359 	case DRM_FORMAT_YUV420:
360 	case DRM_FORMAT_YUV420_10BIT:
361 	case DRM_FORMAT_YUV420_8BIT:
362 	case DRM_FORMAT_YUV422:
363 	case DRM_FORMAT_YUV444:
364 	case DRM_FORMAT_YUYV:
365 	case DRM_FORMAT_YVU410:
366 	case DRM_FORMAT_YVU411:
367 	case DRM_FORMAT_YVU420:
368 	case DRM_FORMAT_YVU422:
369 	case DRM_FORMAT_YVU444:
370 	case DRM_FORMAT_YVYU:
371 		return true;
372 	}
373 	return false;
374 }