From 20f246eaefb85d25c2824806ed03ee67d530aa3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Molinari?= Date: Wed, 22 Jan 2025 17:30:25 +0100 Subject: [PATCH] gl-renderer: Add wl_shm support to all declared YUV pixel formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support more YUV formats using texture swizzles. Automatise wl_shm format addition based on the format table using the new texture format utility gl_texture_is_format_supported(). Signed-off-by: Loïc Molinari --- libweston/renderer-gl/gl-renderer.c | 135 ++++++++++++++++++++-------- 1 file changed, 96 insertions(+), 39 deletions(-) diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 6eda8163a..7416cb915 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -67,6 +67,11 @@ #define BUFFER_DAMAGE_COUNT 2 +#define SWIZZLES_0G0A { GL_ZERO, GL_GREEN, GL_ZERO, GL_ALPHA } +#define SWIZZLES_R000 { GL_RED, GL_ZERO, GL_ZERO, GL_ZERO } +#define SWIZZLES_RG00 { GL_RED, GL_GREEN, GL_ZERO, GL_ZERO } +#define SWIZZLES_RGB0 { GL_RED, GL_GREEN, GL_BLUE, GL_ZERO } + enum gl_debug_mode { DEBUG_MODE_NONE = 0, DEBUG_MODE_WIREFRAME, @@ -218,6 +223,10 @@ struct dmabuf_format { struct yuv_plane_descriptor { uint32_t format; int plane_index; + union { + struct { int r, g, b, a; }; + int array[4]; + } swizzles; }; struct yuv_format_descriptor { @@ -367,10 +376,12 @@ struct yuv_format_descriptor yuv_formats[] = { .shader_variant = SHADER_VARIANT_Y_XUXV, {{ .format = DRM_FORMAT_GR88, - .plane_index = 0 + .plane_index = 0, + .swizzles.array = SWIZZLES_R000, }, { - .format = DRM_FORMAT_ARGB8888, - .plane_index = 0 + .format = DRM_FORMAT_ABGR8888, + .plane_index = 0, + .swizzles.array = SWIZZLES_0G0A, }} }, { .format = DRM_FORMAT_NV12, @@ -378,10 +389,12 @@ struct yuv_format_descriptor yuv_formats[] = { .shader_variant = SHADER_VARIANT_Y_UV, {{ .format = DRM_FORMAT_R8, - .plane_index = 0 + .plane_index = 0, + .swizzles.array = SWIZZLES_R000, }, { .format = DRM_FORMAT_GR88, - .plane_index = 1 + .plane_index = 1, + .swizzles.array = SWIZZLES_RG00, }} }, { .format = DRM_FORMAT_NV16, @@ -389,10 +402,12 @@ struct yuv_format_descriptor yuv_formats[] = { .shader_variant = SHADER_VARIANT_Y_UV, {{ .format = DRM_FORMAT_R8, - .plane_index = 0 + .plane_index = 0, + .swizzles.array = SWIZZLES_R000, }, { .format = DRM_FORMAT_GR88, - .plane_index = 1 + .plane_index = 1, + .swizzles.array = SWIZZLES_RG00, }} }, { .format = DRM_FORMAT_NV24, @@ -400,32 +415,42 @@ struct yuv_format_descriptor yuv_formats[] = { .shader_variant = SHADER_VARIANT_Y_UV, {{ .format = DRM_FORMAT_R8, - .plane_index = 0 + .plane_index = 0, + .swizzles.array = SWIZZLES_R000, }, { .format = DRM_FORMAT_GR88, - .plane_index = 1 + .plane_index = 1, + .swizzles.array = SWIZZLES_RG00, }} }, { + /* XXX The 6 lsb per component aren't masked out. Add a new + * sampling variant? or maybe a new post-sampling step? */ .format = DRM_FORMAT_P010, .output_planes = 2, .shader_variant = SHADER_VARIANT_Y_UV, {{ .format = DRM_FORMAT_R16, - .plane_index = 0 + .plane_index = 0, + .swizzles.array = SWIZZLES_R000 }, { .format = DRM_FORMAT_GR1616, - .plane_index = 1 + .plane_index = 1, + .swizzles.array = SWIZZLES_RG00 }} }, { + /* XXX The 4 lsb per component aren't masked out. Add a new + * sampling variant? or maybe a new post-sampling step? */ .format = DRM_FORMAT_P012, .output_planes = 2, .shader_variant = SHADER_VARIANT_Y_UV, {{ .format = DRM_FORMAT_R16, - .plane_index = 0 + .plane_index = 0, + .swizzles.array = SWIZZLES_R000 }, { .format = DRM_FORMAT_GR1616, - .plane_index = 1 + .plane_index = 1, + .swizzles.array = SWIZZLES_RG00 }} }, { .format = DRM_FORMAT_P016, @@ -433,10 +458,12 @@ struct yuv_format_descriptor yuv_formats[] = { .shader_variant = SHADER_VARIANT_Y_UV, {{ .format = DRM_FORMAT_R16, - .plane_index = 0 + .plane_index = 0, + .swizzles.array = SWIZZLES_R000 }, { .format = DRM_FORMAT_GR1616, - .plane_index = 1 + .plane_index = 1, + .swizzles.array = SWIZZLES_RG00 }} }, { .format = DRM_FORMAT_YUV420, @@ -444,13 +471,16 @@ struct yuv_format_descriptor yuv_formats[] = { .shader_variant = SHADER_VARIANT_Y_U_V, {{ .format = DRM_FORMAT_R8, - .plane_index = 0 + .plane_index = 0, + .swizzles.array = SWIZZLES_R000, }, { .format = DRM_FORMAT_R8, - .plane_index = 1 + .plane_index = 1, + .swizzles.array = SWIZZLES_R000, }, { .format = DRM_FORMAT_R8, - .plane_index = 2 + .plane_index = 2, + .swizzles.array = SWIZZLES_R000, }} }, { .format = DRM_FORMAT_YUV444, @@ -458,21 +488,25 @@ struct yuv_format_descriptor yuv_formats[] = { .shader_variant = SHADER_VARIANT_Y_U_V, {{ .format = DRM_FORMAT_R8, - .plane_index = 0 + .plane_index = 0, + .swizzles.array = SWIZZLES_R000, }, { .format = DRM_FORMAT_R8, - .plane_index = 1 + .plane_index = 1, + .swizzles.array = SWIZZLES_R000, }, { .format = DRM_FORMAT_R8, - .plane_index = 2 + .plane_index = 2, + .swizzles.array = SWIZZLES_R000, }} }, { .format = DRM_FORMAT_XYUV8888, .output_planes = 1, .shader_variant = SHADER_VARIANT_XYUV, {{ - .format = DRM_FORMAT_XBGR8888, - .plane_index = 0 + .format = DRM_FORMAT_ABGR8888, + .plane_index = 0, + .swizzles.array = SWIZZLES_RGB0, }} } }; @@ -2773,7 +2807,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer) int pitch, hsub, vsub; int offset[3] = { 0, 0, 0 }; unsigned int num_planes; - unsigned int i; + unsigned int i, j; const struct yuv_format_descriptor *yuv = NULL; /* When sampling YUV input textures and converting to RGB by hand, we @@ -2820,22 +2854,36 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer) num_planes = yuv->output_planes; for (out = 0; out < num_planes; out++) { - const GLint swizzles_rg[] = { - GL_RED, GL_ALPHA, GL_ZERO, GL_ONE - }; const struct pixel_format_info *info; + GLint *swizzles; info = pixel_format_get_info(yuv->plane[out].format); assert(info); - texture_format[out] = info->gl; + texture_format[out].internal = info->gl.internal; + texture_format[out].external = info->gl.external; + texture_format[out].type = info->gl.type; + + /* The YUV swizzles take precedence over the ones from + * the texture format. */ + ARRAY_COPY(texture_format[out].swizzles.array, + yuv->plane[out].swizzles.array); /* Emulate red-green texture behaviour when * gl_texture_2d_init() implicitly falls back to a * luminance-alpha texture format. */ if (!gl_features_has(gr, FEATURE_TEXTURE_RG) && - texture_format[out].internal == GL_RG8) - ARRAY_COPY(texture_format[out].swizzles.array, - swizzles_rg); + (texture_format[out].internal == GL_RG8 || + texture_format[out].internal == GL_RG16_EXT)) { + swizzles = texture_format[out].swizzles.array; + for (j = 0; j < 4; j++) { + if (swizzles[j] == GL_GREEN) + swizzles[j] = GL_ALPHA; + else if (swizzles[j] == GL_BLUE) + swizzles[j] = GL_ZERO; + else if (swizzles[j] == GL_ALPHA) + swizzles[j] = GL_ONE; + } + } assert(yuv->plane[out].plane_index < (int) shm_plane_count); offset[out] = shm_offset[yuv->plane[out].plane_index]; @@ -4460,7 +4508,8 @@ gl_renderer_display_create(struct weston_compositor *ec, { struct gl_renderer *gr; const struct pixel_format_info *info; - int ret, nformats, i; + int ret, nformats, i, j; + bool supported; gr = zalloc(sizeof *gr); if (gr == NULL) @@ -4595,13 +4644,21 @@ gl_renderer_display_create(struct weston_compositor *ec, wl_display_add_shm_format(ec->wl_display, info->format); } - 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_NV16); - wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_NV24); - wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUYV); - wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_XYUV8888); + /* Register supported wl_shm YUV formats. */ + for (i = 0; i < (int) ARRAY_LENGTH(yuv_formats); i++) { + supported = true; + for (j = 0; j < yuv_formats[i].output_planes; j++) { + info = pixel_format_get_info(yuv_formats[i].plane[j].format); + if (info->gl.internal == 0 || + !gl_texture_is_format_supported(gr, info->gl.internal)) { + supported = false; + break; + } + } + if (supported) + wl_display_add_shm_format(ec->wl_display, + yuv_formats[i].format); + } return 0;