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 <eric.smith@collabora.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31854>
This commit is contained in:
Eric R. Smith
2024-11-12 19:14:59 -04:00
committed by Marge Bot
parent 440b69210a
commit 1ea79ec164
9 changed files with 152 additions and 3 deletions
+3
View File
@@ -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:
+35
View File
@@ -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 &&
+12
View File
@@ -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 },
+46 -2
View File
@@ -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:
+12
View File
@@ -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) {
+12
View File
@@ -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:
+24 -1
View File
@@ -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
+4
View File
@@ -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',
+4
View File
@@ -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,