gl-renderer: Add wl_shm support to all declared YUV pixel formats

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 <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2025-01-22 17:30:25 +01:00 committed by Daniel Stone
parent cf43e7da9f
commit 20f246eaef

View file

@ -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;