From 89e20bcda63aa9535bdfeed6f51d8113ba2d041a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Molinari?= Date: Thu, 21 Nov 2024 12:47:13 +0100 Subject: [PATCH] tests: Add support and tests for 16-bit YUV wl_shm format variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the offset issue in gl_renderer_attach_shm(). Signed-off-by: Loïc Molinari --- libweston/renderer-gl/gl-renderer.c | 8 +- tests/reference/yuv-buffer-01.png | Bin 0 -> 44280 bytes tests/yuv-buffer-test.c | 172 +++++++++++++++++++++++++--- 3 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 tests/reference/yuv-buffer-01.png diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index aea68fec4..60bc2a5c8 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -2947,10 +2947,6 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer) int shm_offset[3] = { 0 }; int bpp = buffer->pixel_format->bpp; - /* XXX: Pitch here is given in pixel units, whereas offset is - * given in byte units. This is fragile and will break with - * new formats. - */ if (!bpp) bpp = pixel_format_get_info(yuv->plane[0].format)->bpp; pitch = buffer->stride / (bpp / 8); @@ -2963,10 +2959,12 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer) for (i = 1; i < shm_plane_count; i++) { int hsub, vsub; + bpp = pixel_format_get_info(yuv->plane[i - 1].format)->bpp; hsub = pixel_format_hsub(buffer->pixel_format, i - 1); vsub = pixel_format_vsub(buffer->pixel_format, i - 1); shm_offset[i] = shm_offset[i - 1] + - ((pitch / hsub) * (buffer->height / vsub)); + (buffer->stride / hsub) * + (buffer->height / vsub); } num_planes = yuv->output_planes; diff --git a/tests/reference/yuv-buffer-01.png b/tests/reference/yuv-buffer-01.png new file mode 100644 index 0000000000000000000000000000000000000000..ef8b6ca191eaa73102fb0976313dfa5d3b6a8ad3 GIT binary patch literal 44280 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 d> 16) & 0xff; + double g = (xrgb >> 8) & 0xff; + double b = (xrgb >> 0) & 0xff; + + /* Rec. ITU-R BT.709-6 defines D as 1 or 4 for 8-bit or 10-bit + * quantization respectively. We extrapolate here to [9, 16]-bit depths + * by setting D to 2^(depth - 8). */ + assert(depth >= 9 && depth <= 16); + d = 1 << (depth - 8); + + /* normalize to [0.0, 1.0] */ + r /= 255.0; + g /= 255.0; + b /= 255.0; + + /* Y normalized to [0.0, 1.0], Cb and Cr [-0.5, 0.5] */ + y = 0.2126 * r + 0.7152 * g + 0.0722 * b; + cr = (r - y) / 1.5748; + cb = (b - y) / 1.8556; + + /* limited range quantization to [9, 16]-bit aligned to the MSB */ + *y_out = (uint16_t) round((219.0 * y + 16.0) * d) << (16 - depth); + if (cr_out) + *cr_out = (uint16_t) + round((224.0 * cr + 128.0) * d) << (16 - depth); + if (cb_out) + *cb_out = (uint16_t) + round((224.0 * cb + 128.0) * d) << (16 - depth); +} + /* * 3 plane YCbCr * plane 0: Y plane, [7:0] Y @@ -636,6 +683,95 @@ xyuv8888_create_buffer(struct client *client, return buf; } +/* + * 2 plane YCbCr MSB aligned + * + * P016: index 0 = Y plane, [15:0] Y little endian + * index 1 = Cr:Cb plane, [31:0] Cr:Cb [16:16] little endian + * 2x2 subsampled Cr:Cb plane 16 bits per channel + * + * P012: index 0 = Y plane, [15:0] Y:x [12:4] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [12:4:12:4] little endian + * 2x2 subsampled Cr:Cb plane 12 bits per channel + * + * P010: index 0 = Y plane, [15:0] Y:x [10:6] little endian + * index 1 = Cr:Cb plane, [31:0] Cr:x:Cb:x [10:6:10:6] little endian + * 2x2 subsampled Cr:Cb plane 10 bits per channel + */ +static struct yuv_buffer * +p016_create_buffer(struct client *client, + uint32_t drm_format, + pixman_image_t *rgb_image) +{ + struct image_header rgb = image_header_from(rgb_image); + struct yuv_buffer *buf; + size_t bytes; + int depth, x, y; + uint32_t *rgb_row; + uint16_t *y_base; + uint32_t *uv_base; + uint16_t *y_row; + uint32_t *uv_row; + uint32_t argb; + uint16_t cr; + uint16_t cb; + + switch (drm_format) { + case DRM_FORMAT_P016: + depth = 16; + break; + case DRM_FORMAT_P012: + depth = 12; + break; + case DRM_FORMAT_P010: + depth = 10; + break; + default: + assert(0 && "Invalid format!"); + }; + + /* Full size Y, quarter UV */ + bytes = rgb.width * rgb.height * sizeof(uint16_t) + + (rgb.width / 2) * (rgb.height / 2) * sizeof(uint32_t); + buf = yuv_buffer_create(client, bytes, rgb.width, rgb.height, + rgb.width * sizeof(uint16_t), drm_format); + + y_base = buf->data; + uv_base = (uint32_t *)(y_base + rgb.width * rgb.height); + + for (y = 0; y < rgb.height; y++) { + rgb_row = image_header_get_row_u32(&rgb, y / 2 * 2); + y_row = y_base + y * rgb.width; + uv_row = uv_base + (y / 2) * (rgb.width / 2); + + for (x = 0; x < rgb.width; x++) { + /* + * Sub-sample the source image instead, so that U and V + * sub-sampling does not require proper + * filtering/averaging/siting. + */ + argb = *(rgb_row + x / 2 * 2); + + /* + * A stupid way of "sub-sampling" chroma. This does not + * do the necessary filtering/averaging/siting. + */ + if ((x & 1) == 0 && (y & 1) == 0) { + x8r8g8b8_to_ycbcr16_bt709(argb, depth, + y_row + x, &cb, &cr); + *(uv_row + x / 2) = + ((uint32_t) cr << 16) | + ((uint32_t) cb << 0); + } else { + x8r8g8b8_to_ycbcr16_bt709(argb, depth, + y_row + x, NULL, NULL); + } + } + } + + return buf; +} + static void show_window_with_yuv(struct client *client, struct yuv_buffer *buf) { @@ -654,21 +790,24 @@ 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), y_u_v_create_buffer }, - { FMT(YVU420), y_u_v_create_buffer }, - { FMT(YUV444), y_u_v_create_buffer }, - { FMT(YVU444), y_u_v_create_buffer }, - { FMT(NV12), nv12_create_buffer }, - { FMT(NV21), nv12_create_buffer }, - { FMT(NV16), nv16_create_buffer }, - { FMT(NV61), nv16_create_buffer }, - { FMT(NV24), nv24_create_buffer }, - { FMT(NV42), nv24_create_buffer }, - { FMT(YUYV), yuyv_create_buffer }, - { FMT(YVYU), yuyv_create_buffer }, - { FMT(UYVY), yuyv_create_buffer }, - { FMT(VYUY), yuyv_create_buffer }, - { FMT(XYUV8888), xyuv8888_create_buffer }, + { FMT(YUV420), 0, y_u_v_create_buffer }, + { FMT(YVU420), 0, y_u_v_create_buffer }, + { FMT(YUV444), 0, y_u_v_create_buffer }, + { FMT(YVU444), 0, y_u_v_create_buffer }, + { FMT(NV12), 0, nv12_create_buffer }, + { FMT(NV21), 0, nv12_create_buffer }, + { FMT(NV16), 0, nv16_create_buffer }, + { FMT(NV61), 0, nv16_create_buffer }, + { FMT(NV24), 0, nv24_create_buffer }, + { FMT(NV42), 0, nv24_create_buffer }, + { FMT(YUYV), 0, yuyv_create_buffer }, + { FMT(YVYU), 0, yuyv_create_buffer }, + { FMT(UYVY), 0, yuyv_create_buffer }, + { FMT(VYUY), 0, yuyv_create_buffer }, + { FMT(XYUV8888), 0, xyuv8888_create_buffer }, + { FMT(P016), 1, p016_create_buffer }, + { FMT(P012), 1, p016_create_buffer }, + { FMT(P010), 1, p016_create_buffer }, #undef FMT }; @@ -720,7 +859,8 @@ TEST_P(yuv_buffer_shm, yuv_cases) } show_window_with_yuv(client, buf); - match = verify_screen_content(client, "yuv-buffer", 0, NULL, 0, NULL); + match = verify_screen_content(client, "yuv-buffer", my_case->ref_seq_no, + NULL, 0, NULL); assert(match); yuv_buffer_destroy(buf);