From a554b45d736073bbea4978118c02f7929f75cd77 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Fri, 6 Sep 2019 09:26:08 -0400 Subject: [PATCH] st/mesa: don't lower YUV when driver supports it natively This fixes YUYV support on etnaviv. Fixes: 7404833c "gallium: add handling for YUV planar surfaces" Signed-off-by: Jonathan Marek Reviewed-by: Christian Gmeiner Part-of: --- src/gallium/state_trackers/dri/dri2.c | 28 ++++---- src/mesa/state_tracker/st_atom_sampler.c | 3 +- src/mesa/state_tracker/st_atom_texture.c | 4 ++ src/mesa/state_tracker/st_cb_eglimage.c | 89 ++++++++++++++---------- src/mesa/state_tracker/st_program.h | 9 ++- src/mesa/state_tracker/st_sampler_view.c | 4 ++ 6 files changed, 82 insertions(+), 55 deletions(-) diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c index 54a05c916f1..e6f0e40465a 100644 --- a/src/gallium/state_trackers/dri/dri2.c +++ b/src/gallium/state_trackers/dri/dri2.c @@ -738,7 +738,7 @@ dri2_create_image_from_winsys(__DRIscreen *_screen, struct pipe_resource templ; unsigned tex_usage = 0; int i; - bool is_yuv = util_format_is_yuv(map->pipe_format); + bool use_lowered = false; if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0, PIPE_BIND_RENDER_TARGET)) @@ -747,13 +747,14 @@ dri2_create_image_from_winsys(__DRIscreen *_screen, PIPE_BIND_SAMPLER_VIEW)) tex_usage |= PIPE_BIND_SAMPLER_VIEW; - if (!tex_usage && is_yuv) { + if (!tex_usage && util_format_is_yuv(map->pipe_format)) { /* YUV format sampling can be emulated by the Mesa state tracker by * using multiple samplers of varying formats. * If no tex_usage is set and we detect a YUV format, * test for support of the first plane's sampler format and * add sampler view usage. */ + use_lowered = true; if (pscreen->is_format_supported(pscreen, dri2_get_pipe_format_for_dri_format(map->planes[0].dri_format), screen->target, 0, 0, @@ -775,19 +776,20 @@ dri2_create_image_from_winsys(__DRIscreen *_screen, templ.depth0 = 1; templ.array_size = 1; - for (i = num_handles - 1; i >= 0; i--) { + for (i = (use_lowered ? map->nplanes : num_handles) - 1; i >= 0; i--) { struct pipe_resource *tex; templ.width0 = width >> map->planes[i].width_shift; templ.height0 = height >> map->planes[i].height_shift; - if (is_yuv) + if (use_lowered) templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format); else templ.format = map->pipe_format; assert(templ.format != PIPE_FORMAT_NONE); tex = pscreen->resource_from_handle(pscreen, - &templ, &whandle[i], PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); + &templ, &whandle[use_lowered ? map->planes[i].buffer_index : i], + PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); if (!tex) { pipe_resource_reference(&img->texture, NULL); FREE(img); @@ -911,25 +913,23 @@ dri2_create_image_from_fd(__DRIscreen *_screen, memset(whandles, 0, sizeof(whandles)); - for (i = 0; i < num_handles; i++) { - int fdnum = i >= num_fds ? 0 : i; - int index = i >= map->nplanes ? i : map->planes[i].buffer_index; - if (fds[fdnum] < 0) { + for (i = 0; i < num_fds; i++) { + if (fds[i] < 0) { err = __DRI_IMAGE_ERROR_BAD_ALLOC; goto exit; } whandles[i].type = WINSYS_HANDLE_TYPE_FD; - whandles[i].handle = (unsigned)fds[fdnum]; - whandles[i].stride = (unsigned)strides[index]; - whandles[i].offset = (unsigned)offsets[index]; + whandles[i].handle = (unsigned)fds[i]; + whandles[i].stride = (unsigned)strides[i]; + whandles[i].offset = (unsigned)offsets[i]; whandles[i].format = map->pipe_format; whandles[i].modifier = modifier; - whandles[i].plane = index; + whandles[i].plane = i; } img = dri2_create_image_from_winsys(_screen, width, height, map, - num_handles, whandles, loaderPrivate); + num_fds, whandles, loaderPrivate); if(img == NULL) { err = __DRI_IMAGE_ERROR_BAD_ALLOC; goto exit; diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index c0f43befa4d..b74d47b691f 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -304,7 +304,8 @@ update_shader_samplers(struct st_context *st, st_get_texture_object(st->ctx, prog, unit); struct pipe_sampler_state *sampler = samplers + unit; - if (!stObj) + /* if resource format matches then YUV wasn't lowered */ + if (!stObj || st_get_view_format(stObj) == stObj->pt->format) continue; switch (st_get_view_format(stObj)) { diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index ef54bc5a77f..5a0f91ccb14 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -182,6 +182,10 @@ update_textures(struct st_context *st, /* use original view as template: */ tmpl = *sampler_views[unit]; + /* if resource format matches then YUV wasn't lowered */ + if (st_get_view_format(stObj) == stObj->pt->format) + continue; + switch (st_get_view_format(stObj)) { case PIPE_FORMAT_NV12: /* we need one additional R8G8 view: */ diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c index d441c161449..5b03c5eb580 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.c +++ b/src/mesa/state_tracker/st_cb_eglimage.c @@ -42,11 +42,12 @@ static bool is_format_supported(struct pipe_screen *screen, enum pipe_format format, unsigned nr_samples, unsigned nr_storage_samples, - unsigned usage) + unsigned usage, bool *native_supported) { bool supported = screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, nr_samples, nr_storage_samples, usage); + *native_supported = supported; /* for sampling, some formats can be emulated.. it doesn't matter that * the surface will have a format that the driver can't cope with because @@ -115,7 +116,8 @@ is_format_supported(struct pipe_screen *screen, enum pipe_format format, */ static bool st_get_egl_image(struct gl_context *ctx, GLeglImageOES image_handle, - unsigned usage, const char *error, struct st_egl_image *out) + unsigned usage, const char *error, struct st_egl_image *out, + bool *native_supported) { struct st_context *st = st_context(ctx); struct pipe_screen *screen = st->pipe->screen; @@ -133,7 +135,8 @@ st_get_egl_image(struct gl_context *ctx, GLeglImageOES image_handle, } if (!is_format_supported(screen, out->format, out->texture->nr_samples, - out->texture->nr_storage_samples, usage)) { + out->texture->nr_storage_samples, usage, + native_supported)) { /* unable to specify a texture object using the specified EGL image */ pipe_resource_reference(&out->texture, NULL); _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format not supported)", error); @@ -180,10 +183,11 @@ st_egl_image_target_renderbuffer_storage(struct gl_context *ctx, { struct st_renderbuffer *strb = st_renderbuffer(rb); struct st_egl_image stimg; + bool native_supported; if (st_get_egl_image(ctx, image_handle, PIPE_BIND_RENDER_TARGET, "glEGLImageTargetRenderbufferStorage", - &stimg)) { + &stimg, &native_supported)) { struct pipe_context *pipe = st_context(ctx)->pipe; struct pipe_surface *ps, surf_tmpl; @@ -212,7 +216,8 @@ st_bind_egl_image(struct gl_context *ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage, struct st_egl_image *stimg, - bool tex_storage) + bool tex_storage, + bool native_supported) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj; @@ -239,34 +244,39 @@ st_bind_egl_image(struct gl_context *ctx, /* TODO RequiredTextureImageUnits should probably be reset back * to 1 somewhere if different texture is bound?? */ - switch (stimg->format) { - case PIPE_FORMAT_NV12: - texFormat = MESA_FORMAT_R_UNORM8; - texObj->RequiredTextureImageUnits = 2; - break; - case PIPE_FORMAT_P016: - texFormat = MESA_FORMAT_R_UNORM16; - texObj->RequiredTextureImageUnits = 2; - break; - case PIPE_FORMAT_IYUV: - texFormat = MESA_FORMAT_R_UNORM8; - texObj->RequiredTextureImageUnits = 3; - break; - case PIPE_FORMAT_YUYV: - case PIPE_FORMAT_UYVY: - texFormat = MESA_FORMAT_RG_UNORM8; - texObj->RequiredTextureImageUnits = 2; - break; - case PIPE_FORMAT_AYUV: - texFormat = MESA_FORMAT_R8G8B8A8_UNORM; - internalFormat = GL_RGBA; - texObj->RequiredTextureImageUnits = 1; - break; - case PIPE_FORMAT_XYUV: - texFormat = MESA_FORMAT_R8G8B8X8_UNORM; - texObj->RequiredTextureImageUnits = 1; - break; - default: + if (!native_supported) { + switch (stimg->format) { + case PIPE_FORMAT_NV12: + texFormat = MESA_FORMAT_R_UNORM8; + texObj->RequiredTextureImageUnits = 2; + break; + case PIPE_FORMAT_P016: + texFormat = MESA_FORMAT_R_UNORM16; + texObj->RequiredTextureImageUnits = 2; + break; + case PIPE_FORMAT_IYUV: + texFormat = MESA_FORMAT_R_UNORM8; + texObj->RequiredTextureImageUnits = 3; + break; + case PIPE_FORMAT_YUYV: + case PIPE_FORMAT_UYVY: + texFormat = MESA_FORMAT_RG_UNORM8; + texObj->RequiredTextureImageUnits = 2; + break; + case PIPE_FORMAT_AYUV: + texFormat = MESA_FORMAT_R8G8B8A8_UNORM; + internalFormat = GL_RGBA; + texObj->RequiredTextureImageUnits = 1; + break; + case PIPE_FORMAT_XYUV: + texFormat = MESA_FORMAT_R8G8B8X8_UNORM; + texObj->RequiredTextureImageUnits = 1; + break; + default: + unreachable("unexpected emulated format"); + break; + } + } else { texFormat = st_pipe_format_to_mesa_format(stimg->format); /* Use previously derived internalformat as specified by * EXT_EGL_image_storage. @@ -279,7 +289,6 @@ st_bind_egl_image(struct gl_context *ctx, return; } } - break; } assert(texFormat != MESA_FORMAT_NONE); @@ -311,12 +320,14 @@ st_egl_image_target_texture_2d(struct gl_context *ctx, GLenum target, GLeglImageOES image_handle) { struct st_egl_image stimg; + bool native_supported; if (!st_get_egl_image(ctx, image_handle, PIPE_BIND_SAMPLER_VIEW, - "glEGLImageTargetTexture2D", &stimg)) + "glEGLImageTargetTexture2D", &stimg, + &native_supported)) return; - st_bind_egl_image(ctx, texObj, texImage, &stimg, false); + st_bind_egl_image(ctx, texObj, texImage, &stimg, false, native_supported); pipe_resource_reference(&stimg.texture, NULL); } @@ -327,12 +338,14 @@ st_egl_image_target_tex_storage(struct gl_context *ctx, GLenum target, GLeglImageOES image_handle) { struct st_egl_image stimg; + bool native_supported; if (!st_get_egl_image(ctx, image_handle, PIPE_BIND_SAMPLER_VIEW, - "glEGLImageTargetTexture2D", &stimg)) + "glEGLImageTargetTexture2D", &stimg, + &native_supported)) return; - st_bind_egl_image(ctx, texObj, texImage, &stimg, true); + st_bind_egl_image(ctx, texObj, texImage, &stimg, true, native_supported); pipe_resource_reference(&stimg.texture, NULL); } diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 69ad595143f..6b49f8d4681 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -71,8 +71,13 @@ st_get_external_sampler_key(struct st_context *st, struct gl_program *prog) unsigned unit = u_bit_scan(&mask); struct st_texture_object *stObj = st_get_texture_object(st->ctx, prog, unit); + enum pipe_format format = st_get_view_format(stObj); - switch (st_get_view_format(stObj)) { + /* if resource format matches then YUV wasn't lowered */ + if (format == stObj->pt->format) + continue; + + switch (format) { case PIPE_FORMAT_NV12: case PIPE_FORMAT_P010: case PIPE_FORMAT_P016: @@ -95,7 +100,7 @@ st_get_external_sampler_key(struct st_context *st, struct gl_program *prog) break; default: printf("mesa: st_get_external_sampler_key: unhandled pipe format %u\n", - st_get_view_format(stObj)); + format); break; } } diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c index 8c0277fe42a..102908e1029 100644 --- a/src/mesa/state_tracker/st_sampler_view.c +++ b/src/mesa/state_tracker/st_sampler_view.c @@ -489,6 +489,10 @@ get_sampler_view_format(struct st_context *st, if (srgb_skip_decode) format = util_format_linear(format); + /* if resource format matches then YUV wasn't lowered */ + if (format == stObj->pt->format) + return format; + /* Use R8_UNORM for video formats */ switch (format) { case PIPE_FORMAT_NV12: -- 2.30.2