gl-renderer: Remove special-cased YUV SHM formats

Now that we can pull everything we need from pixel-formats, go one step
further and reuse the same YUV format descriptors we use to emulate
dmabuf/EGLImage imports for SHM.

This eliminates all special-case YUV/SHM handling.

Signed-off-by: Daniel Stone <daniels@collabora.com>
This commit is contained in:
Daniel Stone 2022-04-28 02:25:20 +01:00 committed by Pekka Paalanen
parent 1a86963d51
commit 18a31a6af8

View File

@ -139,17 +139,15 @@ struct gl_buffer_state {
pixman_region32_t texture_damage;
/* Only needed between attach() and flush_damage() */
int pitch;
GLenum gl_format[3];
int pitch; /* plane 0 pitch in pixels */
GLenum gl_pixel_type;
GLenum gl_format[3];
int offset[3]; /* per-plane pitch in bytes */
EGLImageKHR images[3];
int num_images;
enum gl_shader_texture_variant shader_variant;
/* Extension needed for SHM YUV texture */
int offset[3]; /* offset per plane */
GLuint textures[3];
int num_textures;
@ -240,6 +238,69 @@ shadow_exists(const struct gl_output_state *go)
return go->shadow.fbo != 0;
}
struct yuv_format_descriptor yuv_formats[] = {
{
.format = DRM_FORMAT_YUYV,
.output_planes = 2,
.shader_variant = SHADER_VARIANT_Y_XUXV,
{{
.format = DRM_FORMAT_GR88,
.plane_index = 0
}, {
.format = DRM_FORMAT_ARGB8888,
.plane_index = 0
}}
}, {
.format = DRM_FORMAT_NV12,
.output_planes = 2,
.shader_variant = SHADER_VARIANT_Y_UV,
{{
.format = DRM_FORMAT_R8,
.plane_index = 0
}, {
.format = DRM_FORMAT_GR88,
.plane_index = 1
}}
}, {
.format = DRM_FORMAT_YUV420,
.output_planes = 3,
.shader_variant = SHADER_VARIANT_Y_U_V,
{{
.format = DRM_FORMAT_R8,
.plane_index = 0
}, {
.format = DRM_FORMAT_R8,
.plane_index = 1
}, {
.format = DRM_FORMAT_R8,
.plane_index = 2
}}
}, {
.format = DRM_FORMAT_YUV444,
.output_planes = 3,
.shader_variant = SHADER_VARIANT_Y_U_V,
{{
.format = DRM_FORMAT_R8,
.plane_index = 0
}, {
.format = DRM_FORMAT_R8,
.plane_index = 1
}, {
.format = DRM_FORMAT_R8,
.plane_index = 2
}}
}, {
.format = DRM_FORMAT_XYUV8888,
.output_planes = 1,
.shader_variant = SHADER_VARIANT_XYUV,
{{
.format = DRM_FORMAT_XBGR8888,
.plane_index = 0
}}
}
};
static void
timeline_render_point_destroy(struct timeline_render_point *trp)
{
@ -1901,69 +1962,82 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer)
enum gl_shader_texture_variant shader_variant;
int pitch;
int offset[3] = { 0, 0, 0 };
unsigned int num_planes;
unsigned int i;
int num_planes = 1;
int bpp;
bool using_glesv2 = gr->gl_version < gr_gl_version(3, 0);
const struct yuv_format_descriptor *yuv = NULL;
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 / 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;
break;
case DRM_FORMAT_NV12:
shader_variant = SHADER_VARIANT_Y_UV;
pitch = wl_shm_buffer_get_stride(shm_buffer);
gl_pixel_type = GL_UNSIGNED_BYTE;
num_planes = 2;
offset[1] = offset[0] + pitch * buffer->height;
gl_format[0] = GL_R8_EXT;
gl_format[1] = GL_RG8_EXT;
break;
case DRM_FORMAT_YUYV:
shader_variant = SHADER_VARIANT_Y_XUXV;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
gl_pixel_type = GL_UNSIGNED_BYTE;
num_planes = 2;
offset[1] = 0;
gl_format[0] = GL_RG8_EXT;
gl_format[1] = GL_BGRA_EXT;
break;
case DRM_FORMAT_XYUV8888:
/*
* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian
* a:b: g: r in SHADER_VARIANT_XYUV
/* When sampling YUV input textures and converting to RGB by hand, we
* have to bind to each plane separately, with a different format. For
* example, YUYV will have a single wl_shm input plane, but be bound as
* two planes within gl-renderer, one as GR88 and one as ARGB8888.
*
* The yuv_formats array gives us this translation.
*/
for (i = 0; i < ARRAY_LENGTH(yuv_formats); ++i) {
if (yuv_formats[i].format == buffer->pixel_format->format) {
yuv = &yuv_formats[i];
break;
}
}
if (yuv) {
unsigned int out;
unsigned int shm_plane_count;
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.
*/
shader_variant = SHADER_VARIANT_XYUV;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
gl_format[0] = GL_RGBA;
if (!bpp)
bpp = pixel_format_get_info(yuv->plane[0].format)->bpp;
pitch = wl_shm_buffer_get_stride(shm_buffer) / (bpp / 8);
/* well, they all are so far ... */
gl_pixel_type = GL_UNSIGNED_BYTE;
break;
default:
shader_variant = yuv->shader_variant;
/* pre-compute all plane offsets in shm buffer */
shm_plane_count = pixel_format_get_plane_count(buffer->pixel_format);
assert(shm_plane_count <= ARRAY_LENGTH(shm_offset));
for (i = 1; i < shm_plane_count; i++) {
int hsub, vsub;
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));
}
num_planes = yuv->output_planes;
for (out = 0; out < num_planes; out++) {
const struct pixel_format_info *sub_info =
pixel_format_get_info(yuv->plane[out].format);
assert(sub_info);
assert(yuv->plane[out].plane_index < (int) shm_plane_count);
gl_format[out] = sub_info->gl_format;
offset[out] = shm_offset[yuv->plane[out].plane_index];
}
} else {
int bpp = buffer->pixel_format->bpp;
assert(pixel_format_get_plane_count(buffer->pixel_format) == 1);
num_planes = 1;
if (pixel_format_is_opaque(buffer->pixel_format))
shader_variant = SHADER_VARIANT_RGBX;
else
shader_variant = SHADER_VARIANT_RGBA;
bpp = buffer->pixel_format->bpp;
assert(bpp > 0 && !(bpp & 7));
pitch = wl_shm_buffer_get_stride(shm_buffer) / (bpp / 8);
gl_format[0] = buffer->pixel_format->gl_format;
gl_pixel_type = buffer->pixel_format->gl_type;
break;
}
for (i = 0; i < ARRAY_LENGTH(gb->gl_format); i++) {
@ -2283,68 +2357,6 @@ import_simple_dmabuf(struct gl_renderer *gr,
EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
}
struct yuv_format_descriptor yuv_formats[] = {
{
.format = DRM_FORMAT_YUYV,
.output_planes = 2,
.shader_variant = SHADER_VARIANT_Y_XUXV,
{{
.format = DRM_FORMAT_GR88,
.plane_index = 0
}, {
.format = DRM_FORMAT_ARGB8888,
.plane_index = 0
}}
}, {
.format = DRM_FORMAT_NV12,
.output_planes = 2,
.shader_variant = SHADER_VARIANT_Y_UV,
{{
.format = DRM_FORMAT_R8,
.plane_index = 0
}, {
.format = DRM_FORMAT_GR88,
.plane_index = 1
}}
}, {
.format = DRM_FORMAT_YUV420,
.output_planes = 3,
.shader_variant = SHADER_VARIANT_Y_U_V,
{{
.format = DRM_FORMAT_R8,
.plane_index = 0
}, {
.format = DRM_FORMAT_R8,
.plane_index = 1
}, {
.format = DRM_FORMAT_R8,
.plane_index = 2
}}
}, {
.format = DRM_FORMAT_YUV444,
.output_planes = 3,
.shader_variant = SHADER_VARIANT_Y_U_V,
{{
.format = DRM_FORMAT_R8,
.plane_index = 0
}, {
.format = DRM_FORMAT_R8,
.plane_index = 1
}, {
.format = DRM_FORMAT_R8,
.plane_index = 2
}}
}, {
.format = DRM_FORMAT_XYUV8888,
.output_planes = 1,
.shader_variant = SHADER_VARIANT_XYUV,
{{
.format = DRM_FORMAT_XBGR8888,
.plane_index = 0
}}
}
};
static EGLImageKHR
import_dmabuf_single_plane(struct gl_renderer *gr,
const struct pixel_format_info *info,