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>
dev
Daniel Stone 2 years ago committed by Pekka Paalanen
parent c2cfadfce9
commit 820f3ae866
  1. 6
      libweston/renderer-gl/gl-renderer.c
  2. 28
      tests/yuv-buffer-test.c

@ -1918,12 +1918,15 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer)
switch (buffer->pixel_format->format) { switch (buffer->pixel_format->format) {
case DRM_FORMAT_YUV420: case DRM_FORMAT_YUV420:
case DRM_FORMAT_YUV444:
shader_variant = SHADER_VARIANT_Y_U_V; shader_variant = SHADER_VARIANT_Y_U_V;
pitch = wl_shm_buffer_get_stride(shm_buffer); pitch = wl_shm_buffer_get_stride(shm_buffer);
gl_pixel_type = GL_UNSIGNED_BYTE; gl_pixel_type = GL_UNSIGNED_BYTE;
num_planes = 3; num_planes = 3;
offset[1] = offset[0] + pitch * buffer->height; 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[0] = GL_R8_EXT;
gl_format[1] = GL_R8_EXT; gl_format[1] = GL_R8_EXT;
gl_format[2] = 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_RGB565);
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUV420); 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_NV12);
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUYV); wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUYV);
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_XYUV8888); wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_XYUV8888);

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

Loading…
Cancel
Save