From 1ea79ec164a2bb20aebc51acb8e5417c12cab726 Mon Sep 17 00:00:00 2001 From: "Eric R. Smith" Date: Tue, 12 Nov 2024 19:14:59 -0400 Subject: [PATCH] egl, mesa: add support for NV15 and NV20 textures Support external images with 10 bit YUV in NV15 and NV20 formats. These are produced by some hardware decoders, so this will be useful. Signed-off-by: Eric R. Smith Reviewed-by: Erik Faye-Lund Part-of: --- src/egl/drivers/dri2/egl_dri2.c | 3 ++ src/gallium/frontends/dri/dri2.c | 35 +++++++++++++++++ src/gallium/frontends/dri/dri_helpers.c | 12 ++++++ src/mesa/state_tracker/st_cb_eglimage.c | 48 +++++++++++++++++++++++- src/mesa/state_tracker/st_program.h | 12 ++++++ src/mesa/state_tracker/st_sampler_view.c | 12 ++++++ src/util/format/u_format.yaml | 25 +++++++++++- src/util/format/u_format_table.py | 4 ++ src/util/format/u_formats.h | 4 ++ 9 files changed, 152 insertions(+), 3 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index abab8c9edbc..a31d7c58080 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -2332,6 +2332,9 @@ dri2_num_fourcc_format_planes(EGLint format) case DRM_FORMAT_NV21: case DRM_FORMAT_NV16: case DRM_FORMAT_NV61: + case DRM_FORMAT_NV15: + case DRM_FORMAT_NV20: + case DRM_FORMAT_NV30: case DRM_FORMAT_P010: case DRM_FORMAT_P012: case DRM_FORMAT_P016: diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c index 54ce3cf78c5..4c97c045354 100644 --- a/src/gallium/frontends/dri/dri2.c +++ b/src/gallium/frontends/dri/dri2.c @@ -856,6 +856,26 @@ static const struct dri2_format_mapping g8r8_b8r8_mapping = { { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } }; +static const struct dri2_format_mapping r10_g10b10_mapping = { + DRM_FORMAT_NV15, + __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UV, + PIPE_FORMAT_R10_G10B10_420_UNORM, + 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_NONE }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_NONE } } +}; + +static const struct dri2_format_mapping r10_g10b10_mapping_422 = { + DRM_FORMAT_NV20, + __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UV, + PIPE_FORMAT_R10_G10B10_422_UNORM, + 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_NONE }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_NONE } } +}; + static enum __DRIFixedRateCompression to_dri_compression_rate(uint32_t rate) { @@ -944,6 +964,21 @@ dri_create_image_from_winsys(struct dri_screen *screen, tex_usage |= PIPE_BIND_SAMPLER_VIEW; } + /* For NV15, see if we have support for sampling r10_g10b10 */ + if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV15 && + pscreen->is_format_supported(pscreen, PIPE_FORMAT_R10_G10B10_420_UNORM, + screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { + map = &r10_g10b10_mapping; + tex_usage |= PIPE_BIND_SAMPLER_VIEW; + } + + if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV20 && + pscreen->is_format_supported(pscreen, PIPE_FORMAT_R10_G10B10_422_UNORM, + screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { + map = &r10_g10b10_mapping_422; + tex_usage |= PIPE_BIND_SAMPLER_VIEW; + } + /* For YV12 and I420, see if we have support for sampling r8_b8_g8 or r8_g8_b8 */ if (!tex_usage && map->pipe_format == PIPE_FORMAT_IYUV) { if (map->dri_fourcc == DRM_FORMAT_YUV420 && diff --git a/src/gallium/frontends/dri/dri_helpers.c b/src/gallium/frontends/dri/dri_helpers.c index c5bdd3aa5b3..c3e91fb8b49 100644 --- a/src/gallium/frontends/dri/dri_helpers.c +++ b/src/gallium/frontends/dri/dri_helpers.c @@ -550,6 +550,18 @@ static const struct dri2_format_mapping dri2_format_table[] = { { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } } }, + /* 10 bit 4:2:0 and 4:2:2 formats; the components + are tightly packed, so the planes don't correspond + to any native DRI format */ + { DRM_FORMAT_NV15, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV15, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_NONE }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_NONE } } }, + { DRM_FORMAT_NV20, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV20, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_NONE }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_NONE } } }, + { DRM_FORMAT_P010, __DRI_IMAGE_FORMAT_NONE, __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P010, 2, { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c index f1294d70d9d..ab7cdd97875 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.c +++ b/src/mesa/state_tracker/st_cb_eglimage.c @@ -167,7 +167,7 @@ is_format_supported(struct pipe_screen *screen, enum pipe_format format, } static bool -is_nv12_as_r8_g8b8_supported(struct pipe_screen *screen, struct st_egl_image *out, +is_fmt_as_r8_g8b8_supported(struct pipe_screen *screen, struct st_egl_image *out, unsigned usage, bool *native_supported) { if (out->format == PIPE_FORMAT_NV12 && @@ -205,6 +205,33 @@ is_nv12_as_r8_g8b8_supported(struct pipe_screen *screen, struct st_egl_image *ou return false; } +static bool +is_fmt_as_r10_g10b10_supported(struct pipe_screen *screen, struct st_egl_image *out, + unsigned usage, bool *native_supported) +{ + if (out->format == PIPE_FORMAT_NV15 && + out->texture->format == PIPE_FORMAT_R10_G10B10_420_UNORM && + screen->is_format_supported(screen, PIPE_FORMAT_R10_G10B10_420_UNORM, + PIPE_TEXTURE_2D, + out->texture->nr_samples, + out->texture->nr_storage_samples, + usage)) { + *native_supported = false; + return true; + } + if (out->format == PIPE_FORMAT_NV20 && + out->texture->format == PIPE_FORMAT_R10_G10B10_422_UNORM && + screen->is_format_supported(screen, PIPE_FORMAT_R10_G10B10_422_UNORM, + PIPE_TEXTURE_2D, + out->texture->nr_samples, + out->texture->nr_storage_samples, + usage)) { + *native_supported = false; + return true; + } + return false; +} + static bool is_i420_as_r8_g8_b8_420_supported(struct pipe_screen *screen, struct st_egl_image *out, @@ -257,7 +284,8 @@ st_get_egl_image(struct gl_context *ctx, GLeglImageOES image_handle, return false; } - if (!is_nv12_as_r8_g8b8_supported(screen, out, usage, native_supported) && + if (!is_fmt_as_r8_g8b8_supported(screen, out, usage, native_supported) && + !is_fmt_as_r10_g10b10_supported(screen, out, usage, native_supported) && !is_i420_as_r8_g8_b8_420_supported(screen, out, usage, native_supported) && !is_format_supported(screen, out->format, out->texture->nr_samples, out->texture->nr_storage_samples, usage, @@ -404,6 +432,22 @@ st_bind_egl_image(struct gl_context *ctx, texObj->RequiredTextureImageUnits = 2; } break; + case PIPE_FORMAT_NV15: + if (stimg->texture->format == PIPE_FORMAT_R10_G10B10_420_UNORM) { + texFormat = MESA_FORMAT_R10G10B10X2_UNORM; + texObj->RequiredTextureImageUnits = 1; + } else { + unreachable("NV15 emulation requires R10_G10B10_420_UNORM support"); + } + break; + case PIPE_FORMAT_NV20: + if (stimg->texture->format == PIPE_FORMAT_R10_G10B10_422_UNORM) { + texFormat = MESA_FORMAT_R10G10B10X2_UNORM; + texObj->RequiredTextureImageUnits = 1; + } else { + unreachable("NV20 emulation requires R10_G10B10_422_UNORM support"); + } + break; case PIPE_FORMAT_P010: case PIPE_FORMAT_P012: case PIPE_FORMAT_P016: diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 5358d176483..b81770afc9f 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -96,6 +96,12 @@ st_get_external_sampler_key(struct st_context *st, struct gl_program *prog) break; } FALLTHROUGH; + case PIPE_FORMAT_NV15: + if (stObj->pt->format == PIPE_FORMAT_R10_G10B10_420_UNORM) { + key.lower_yuv |= (1 << unit); + break; + } + FALLTHROUGH; case PIPE_FORMAT_P010: case PIPE_FORMAT_P012: case PIPE_FORMAT_P016: @@ -109,6 +115,12 @@ st_get_external_sampler_key(struct st_context *st, struct gl_program *prog) } key.lower_nv21 |= (1 << unit); break; + case PIPE_FORMAT_NV20: + if (stObj->pt->format == PIPE_FORMAT_R10_G10B10_422_UNORM) { + key.lower_yuv |= (1 << unit); + break; + } + FALLTHROUGH; case PIPE_FORMAT_IYUV: if (stObj->pt->format == PIPE_FORMAT_R8_G8_B8_420_UNORM || stObj->pt->format == PIPE_FORMAT_R8_B8_G8_420_UNORM) { diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c index 4b94397f8df..89e89fd103d 100644 --- a/src/mesa/state_tracker/st_sampler_view.c +++ b/src/mesa/state_tracker/st_sampler_view.c @@ -415,6 +415,18 @@ st_get_sampler_view_format(const struct st_context *st, } format = PIPE_FORMAT_R8_UNORM; break; + case PIPE_FORMAT_NV15: + if (texObj->pt->format == PIPE_FORMAT_R10_G10B10_420_UNORM) { + format = PIPE_FORMAT_R10_G10B10_420_UNORM; + break; + } + FALLTHROUGH; + case PIPE_FORMAT_NV20: + if (texObj->pt->format == PIPE_FORMAT_R10_G10B10_422_UNORM) { + format = PIPE_FORMAT_R10_G10B10_422_UNORM; + break; + } + FALLTHROUGH; case PIPE_FORMAT_P010: case PIPE_FORMAT_P012: case PIPE_FORMAT_P016: diff --git a/src/util/format/u_format.yaml b/src/util/format/u_format.yaml index 30913dd1e02..c0f46eb89f4 100644 --- a/src/util/format/u_format.yaml +++ b/src/util/format/u_format.yaml @@ -1900,7 +1900,18 @@ block: {width: 1, height: 1, depth: 1} channels: [UN8] swizzles: [X, 0, 0, 1] - +- name: NV15 + layout: planar2 + colorspace: YUV + block: {width: 1, height: 1, depth: 1} + channels: [] + swizzles: [X, Y, Z, W] +- name: NV20 + layout: planar2 + colorspace: YUV + block: {width: 1, height: 1, depth: 1} + channels: [] + swizzles: [X, Y, Z, W] # RGB versions of NV12, YV12, P010, and P012 for hardware that supports sampling # from multiplane textures but needs color-space conversion in the shader. @@ -1922,6 +1933,18 @@ block: {width: 1, height: 1, depth: 1} channels: [UN8] swizzles: [X, Y, Z, W] +- name: R10_G10B10_420_UNORM + layout: planar2 + colorspace: RGB + block: {width: 4, height: 1, depth: 1} + channels: [UN40] + swizzles: [X, Y, Z, W] +- name: R10_G10B10_422_UNORM + layout: planar2 + colorspace: RGB + block: {width: 4, height: 1, depth: 1} + channels: [UN40] + swizzles: [X, Y, Z, W] - name: R8_G8_B8_420_UNORM layout: planar3 colorspace: RGB diff --git a/src/util/format/u_format_table.py b/src/util/format/u_format_table.py index fda24594002..4a3873d2e9b 100644 --- a/src/util/format/u_format_table.py +++ b/src/util/format/u_format_table.py @@ -86,6 +86,8 @@ def has_access(format): 'nv12', 'nv16', 'nv21', + 'nv15', + 'nv20', 'p010', 'p012', 'p016', @@ -118,6 +120,8 @@ def has_access(format): 'r8_g8b8_420_unorm', 'r8_b8g8_420_unorm', 'g8_b8r8_420_unorm', + 'r10_g10b10_420_unorm', + 'r10_g10b10_422_unorm', 'r8_g8_b8_420_unorm', 'r8_b8_g8_420_unorm', 'g8_b8_r8_420_unorm', diff --git a/src/util/format/u_formats.h b/src/util/format/u_formats.h index 677691a2a35..7b6e7d8f7c8 100644 --- a/src/util/format/u_formats.h +++ b/src/util/format/u_formats.h @@ -306,6 +306,8 @@ enum pipe_format { PIPE_FORMAT_NV12, PIPE_FORMAT_NV21, PIPE_FORMAT_NV16, + PIPE_FORMAT_NV15, + PIPE_FORMAT_NV20, PIPE_FORMAT_Y8_400_UNORM, /* PIPE_FORMAT_Y8_U8_V8_420_UNORM = IYUV */ @@ -526,6 +528,8 @@ enum pipe_format { PIPE_FORMAT_R8_G8B8_420_UNORM, PIPE_FORMAT_R8_B8G8_420_UNORM, PIPE_FORMAT_G8_B8R8_420_UNORM, + PIPE_FORMAT_R10_G10B10_420_UNORM, + PIPE_FORMAT_R10_G10B10_422_UNORM, PIPE_FORMAT_R8_G8_B8_420_UNORM, PIPE_FORMAT_R8_B8_G8_420_UNORM, PIPE_FORMAT_G8_B8_R8_420_UNORM,