gl-renderer: Add support for WL_SHM_FORMAT_YUV444

We support this as an explicit YUV fallback path in gl-renderer's dmabuf
EGLImage import path, so might as well support it in the SHM path, given
it's just YUV420 with no subsampling.

Signed-off-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
Daniel Stone 2022-04-28 01:21:15 +01:00 committed by Pekka Paalanen
parent c2cfadfce9
commit 820f3ae866
2 changed files with 23 additions and 15 deletions

View file

@ -1918,12 +1918,15 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer)
switch (buffer->pixel_format->format) {
case DRM_FORMAT_YUV420:
case DRM_FORMAT_YUV444:
shader_variant = SHADER_VARIANT_Y_U_V;
pitch = wl_shm_buffer_get_stride(shm_buffer);
gl_pixel_type = GL_UNSIGNED_BYTE;
num_planes = 3;
offset[1] = offset[0] + pitch * buffer->height;
offset[2] = offset[1] + (pitch / 2) * (buffer->height / 2);
offset[2] = offset[1] +
(pitch / pixel_format_hsub(buffer->pixel_format, 1)) *
(buffer->height / pixel_format_vsub(buffer->pixel_format, 1));
gl_format[0] = GL_R8_EXT;
gl_format[1] = GL_R8_EXT;
gl_format[2] = GL_R8_EXT;
@ -3693,6 +3696,7 @@ gl_renderer_display_create(struct weston_compositor *ec,
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUV420);
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUV444);
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_NV12);
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUYV);
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_XYUV8888);

View file

@ -150,12 +150,13 @@ x8r8g8b8_to_ycbcr8_bt601(uint32_t xrgb,
* plane 0: Y plane, [7:0] Y
* plane 1: Cb plane, [7:0] Cb
* plane 2: Cr plane, [7:0] Cr
* 2x2 subsampled Cb (1) and Cr (2) planes
* YUV420: 2x2 subsampled Cb (1) and Cr (2) planes
* YUV444: no subsampling
*/
static struct yuv_buffer *
yuv420_create_buffer(struct client *client,
uint32_t drm_format,
pixman_image_t *rgb_image)
y_u_v_create_buffer(struct client *client,
uint32_t drm_format,
pixman_image_t *rgb_image)
{
struct yuv_buffer *buf;
size_t bytes;
@ -172,27 +173,29 @@ yuv420_create_buffer(struct client *client,
uint8_t *u_row;
uint8_t *v_row;
uint32_t argb;
int sub = (drm_format == DRM_FORMAT_YUV420) ? 2 : 1;
assert(drm_format == DRM_FORMAT_YUV420);
assert(drm_format == DRM_FORMAT_YUV420 ||
drm_format == DRM_FORMAT_YUV444);
width = pixman_image_get_width(rgb_image);
height = pixman_image_get_height(rgb_image);
rgb_pixels = pixman_image_get_data(rgb_image);
rgb_stride_bytes = pixman_image_get_stride(rgb_image);
/* Full size Y, quarter U and V */
bytes = width * height + (width / 2) * (height / 2) * 2;
/* Full size Y plus quarter U and V */
bytes = width * height + (width / sub) * (height / sub) * 2;
buf = yuv_buffer_create(client, bytes, width, height, width, drm_format);
y_base = buf->data;
u_base = y_base + width * height;
v_base = u_base + (width / 2) * (height / 2);
v_base = u_base + (width / sub) * (height / sub);
for (y = 0; y < height; y++) {
rgb_row = rgb_pixels + (y / 2 * 2) * rgb_stride_bytes;
y_row = y_base + y * width;
u_row = u_base + (y / 2) * (width / 2);
v_row = v_base + (y / 2) * (width / 2);
u_row = u_base + (y / sub) * (width / sub);
v_row = v_base + (y / sub) * (width / sub);
for (x = 0; x < width; x++) {
/*
@ -207,10 +210,10 @@ yuv420_create_buffer(struct client *client,
* do the necessary filtering/averaging/siting or
* alternate Cb/Cr rows.
*/
if ((y & 1) == 0 && (x & 1) == 0) {
if ((y & (sub - 1)) == 0 && (x & (sub - 1)) == 0) {
x8r8g8b8_to_ycbcr8_bt601(argb, y_row + x,
u_row + x / 2,
v_row + x / 2);
u_row + x / sub,
v_row + x / sub);
} else {
x8r8g8b8_to_ycbcr8_bt601(argb, y_row + x,
NULL, NULL);
@ -435,7 +438,8 @@ show_window_with_yuv(struct client *client, struct yuv_buffer *buf)
static const struct yuv_case yuv_cases[] = {
#define FMT(x) DRM_FORMAT_ ##x, #x
{ FMT(YUV420), yuv420_create_buffer },
{ FMT(YUV420), y_u_v_create_buffer },
{ FMT(YUV444), y_u_v_create_buffer },
{ FMT(NV12), nv12_create_buffer },
{ FMT(YUYV), yuyv_create_buffer },
{ FMT(XYUV8888), xyuv8888_create_buffer },