diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 7f3bb01f..7fcf1f9d 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -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); diff --git a/tests/yuv-buffer-test.c b/tests/yuv-buffer-test.c index ad0b298b..eb17c680 100644 --- a/tests/yuv-buffer-test.c +++ b/tests/yuv-buffer-test.c @@ -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 },