gallium: add handling for YUV planar surfaces

st/dri:
this adds a table (similar to the one in i965) which provides
mappings for turning various planar formats into multiple sampler views.
whereas only NV12 and IYUV were supported, now many more formats are
supported here:
* P0XX
* YUV4XX
* YVU4XX
* AYUV
* XYUV
* YUYV
* UYVY

the table is used directly to handle image creation, simplifying
a lot of code and resolving related TODO/FIXME items where workarounds were
previously in place to manage NV12 and IYUV formats exclusively

st/mesa:
the changes here relate to setting up samplers for the planar formats.
this requires:
* checking for driver support for all the sampler formats
* creating the samplers with the corresponding formats and swizzling
* running nir_lower_tex with the appropriate options to trigger the lowering
  for each plane->sampler

fixes kwg/mesa#36

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Mike Blumenkrantz
2019-05-29 17:14:32 -04:00
committed by Kenneth Graunke
parent 338a29b08f
commit 7404833c2e
8 changed files with 328 additions and 84 deletions

View File

@@ -67,52 +67,164 @@ dri2_buffer(__DRIbuffer * driBufferPriv)
struct dri2_format_mapping { struct dri2_format_mapping {
int dri_fourcc; int dri_fourcc;
int dri_format; int dri_format; /* image format */
int dri_components; int dri_components;
enum pipe_format pipe_format; enum pipe_format pipe_format;
int nplanes;
struct {
int buffer_index;
int width_shift;
int height_shift;
uint32_t dri_format; /* plane format */
int cpp;
} planes[3];
}; };
static const struct dri2_format_mapping dri2_format_table[] = { static const struct dri2_format_mapping dri2_format_table[] = {
{ __DRI_IMAGE_FOURCC_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010, { __DRI_IMAGE_FOURCC_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010,
__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B10G10R10A2_UNORM }, __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B10G10R10A2_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB2101010, 4 } } },
{ __DRI_IMAGE_FOURCC_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010, { __DRI_IMAGE_FOURCC_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010,
__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B10G10R10X2_UNORM }, __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B10G10R10X2_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB2101010, 4 } } },
{ __DRI_IMAGE_FOURCC_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010, { __DRI_IMAGE_FOURCC_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010,
__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R10G10B10A2_UNORM }, __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R10G10B10A2_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR2101010, 4 } } },
{ __DRI_IMAGE_FOURCC_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010, { __DRI_IMAGE_FOURCC_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010,
__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R10G10B10X2_UNORM }, __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R10G10B10X2_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR2101010, 4 } } },
{ __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888,
__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM }, __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
{ __DRI_IMAGE_FOURCC_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, { __DRI_IMAGE_FOURCC_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888,
__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM }, __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } },
{ __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_FORMAT_SARGB8, { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_FORMAT_SARGB8,
__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_SRGB }, __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_SRGB, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } },
{ __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888, { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888,
__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_BGRX8888_UNORM }, __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_BGRX8888_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
{ __DRI_IMAGE_FOURCC_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888, { __DRI_IMAGE_FOURCC_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888,
__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_RGBX8888_UNORM }, __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_RGBX8888_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 }, } },
{ __DRI_IMAGE_FOURCC_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555, { __DRI_IMAGE_FOURCC_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555,
__DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B5G5R5A1_UNORM }, __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B5G5R5A1_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB1555, 2 } } },
{ __DRI_IMAGE_FOURCC_RGB565, __DRI_IMAGE_FORMAT_RGB565, { __DRI_IMAGE_FOURCC_RGB565, __DRI_IMAGE_FORMAT_RGB565,
__DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B5G6R5_UNORM }, __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B5G6R5_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565, 2 } } },
{ __DRI_IMAGE_FOURCC_R8, __DRI_IMAGE_FORMAT_R8, { __DRI_IMAGE_FOURCC_R8, __DRI_IMAGE_FORMAT_R8,
__DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R8_UNORM }, __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R8_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, } },
{ __DRI_IMAGE_FOURCC_R16, __DRI_IMAGE_FORMAT_R16, { __DRI_IMAGE_FOURCC_R16, __DRI_IMAGE_FORMAT_R16,
__DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R16_UNORM }, __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R16_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 1 }, } },
{ __DRI_IMAGE_FOURCC_GR88, __DRI_IMAGE_FORMAT_GR88, { __DRI_IMAGE_FOURCC_GR88, __DRI_IMAGE_FORMAT_GR88,
__DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM }, __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, } },
{ __DRI_IMAGE_FOURCC_GR1616, __DRI_IMAGE_FORMAT_GR1616, { __DRI_IMAGE_FOURCC_GR1616, __DRI_IMAGE_FORMAT_GR1616,
__DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG1616_UNORM }, __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG1616_UNORM, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616, 2 }, } },
{ __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_YUV411, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_FORMAT_NONE, { __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV }, __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_YUV422, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_YUV444, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_YVU410, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_YVU411, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_YVU420, __DRI_IMAGE_FORMAT_NONE, { __DRI_IMAGE_FOURCC_YVU420, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12 }, __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_YVU422, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_YVU444, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
{ __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_FORMAT_NONE, { __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12 }, __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2,
{ __DRI_IMAGE_FOURCC_YUYV, __DRI_IMAGE_FORMAT_YUYV, { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
__DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_YUYV }, { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } },
{ __DRI_IMAGE_FOURCC_UYVY, __DRI_IMAGE_FORMAT_UYVY,
__DRI_IMAGE_COMPONENTS_Y_UXVX, PIPE_FORMAT_UYVY }, { __DRI_IMAGE_FOURCC_P010, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 },
{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } },
{ __DRI_IMAGE_FOURCC_P012, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 },
{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } },
{ __DRI_IMAGE_FOURCC_P016, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 },
{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } },
{ __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
{ 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } },
{ __DRI_IMAGE_FOURCC_AYUV, __DRI_IMAGE_FORMAT_ABGR8888,
__DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_AYUV, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } },
{ __DRI_IMAGE_FOURCC_XYUV8888, __DRI_IMAGE_FORMAT_XBGR8888,
__DRI_IMAGE_COMPONENTS_XYUV, PIPE_FORMAT_XYUV, 1,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 } } },
/* For YUYV and UYVY buffers, we set up two overlapping DRI images
* and treat them as planar buffers in the compositors.
* Plane 0 is GR88 and samples YU or YV pairs and places Y into
* the R component, while plane 1 is ARGB/ABGR and samples YUYV/UYVY
* clusters and places pairs and places U into the G component and
* V into A. This lets the texture sampler interpolate the Y
* components correctly when sampling from plane 0, and interpolate
* U and V correctly when sampling from plane 1. */
{ __DRI_IMAGE_FOURCC_YUYV, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_YUYV, 2,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
{ 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
{ __DRI_IMAGE_FOURCC_UYVY, __DRI_IMAGE_FORMAT_NONE,
__DRI_IMAGE_COMPONENTS_Y_UXVX, PIPE_FORMAT_UYVY, 2,
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
{ 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } }
}; };
static const struct dri2_format_mapping * static const struct dri2_format_mapping *
@@ -137,6 +249,17 @@ dri2_get_mapping_by_format(int format)
return NULL; return NULL;
} }
static enum pipe_format
dri2_get_pipe_format_for_dri_format(int format)
{
for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {
if (dri2_format_table[i].dri_format == format)
return dri2_format_table[i].pipe_format;
}
return PIPE_FORMAT_NONE;
}
/** /**
* DRI2 flush extension. * DRI2 flush extension.
*/ */
@@ -791,22 +914,25 @@ dri2_create_image_from_winsys(__DRIscreen *_screen,
struct pipe_resource templ; struct pipe_resource templ;
unsigned tex_usage = 0; unsigned tex_usage = 0;
int i; int i;
enum pipe_format pf = map->pipe_format; bool is_yuv = util_format_is_yuv(map->pipe_format);
if (pscreen->is_format_supported(pscreen, pf, screen->target, 0, 0, if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
PIPE_BIND_RENDER_TARGET)) PIPE_BIND_RENDER_TARGET))
tex_usage |= PIPE_BIND_RENDER_TARGET; tex_usage |= PIPE_BIND_RENDER_TARGET;
if (pscreen->is_format_supported(pscreen, pf, screen->target, 0, 0, if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
PIPE_BIND_SAMPLER_VIEW)) PIPE_BIND_SAMPLER_VIEW))
tex_usage |= PIPE_BIND_SAMPLER_VIEW; tex_usage |= PIPE_BIND_SAMPLER_VIEW;
if (!tex_usage && util_format_is_yuv(pf)) { if (!tex_usage && is_yuv) {
/* YUV format sampling can be emulated by the Mesa state tracker by /* YUV format sampling can be emulated by the Mesa state tracker by
* using multiple R8/RG88 samplers. So try to rewrite the pipe format. * 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.
*/ */
pf = PIPE_FORMAT_R8_UNORM; if (pscreen->is_format_supported(pscreen,
dri2_get_pipe_format_for_dri_format(map->planes[0].dri_format),
if (pscreen->is_format_supported(pscreen, pf, screen->target, 0, 0, screen->target, 0, 0,
PIPE_BIND_SAMPLER_VIEW)) PIPE_BIND_SAMPLER_VIEW))
tex_usage |= PIPE_BIND_SAMPLER_VIEW; tex_usage |= PIPE_BIND_SAMPLER_VIEW;
} }
@@ -828,28 +954,13 @@ dri2_create_image_from_winsys(__DRIscreen *_screen,
for (i = num_handles - 1; i >= 0; i--) { for (i = num_handles - 1; i >= 0; i--) {
struct pipe_resource *tex; struct pipe_resource *tex;
/* TODO: something a lot less ugly */ templ.width0 = width >> map->planes[i].width_shift;
switch (i) { templ.height0 = height >> map->planes[i].height_shift;
case 0: if (is_yuv)
templ.width0 = width; templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format);
templ.height0 = height; else
templ.format = pf; templ.format = map->pipe_format;
break; assert(templ.format != PIPE_FORMAT_NONE);
case 1:
templ.width0 = width / 2;
templ.height0 = height / 2;
templ.format = (num_handles == 2) ?
PIPE_FORMAT_RG88_UNORM : /* NV12, etc */
PIPE_FORMAT_R8_UNORM; /* I420, etc */
break;
case 2:
templ.width0 = width / 2;
templ.height0 = height / 2;
templ.format = PIPE_FORMAT_R8_UNORM;
break;
default:
unreachable("too many planes!");
}
tex = pscreen->resource_from_handle(pscreen, tex = pscreen->resource_from_handle(pscreen,
&templ, &whandle[i], PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); &templ, &whandle[i], PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
@@ -914,7 +1025,7 @@ dri2_create_image_from_fd(__DRIscreen *_screen,
const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
__DRIimage *img = NULL; __DRIimage *img = NULL;
unsigned err = __DRI_IMAGE_ERROR_SUCCESS; unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
int expected_num_fds, i; int i, expected_num_fds;
if (!map) { if (!map) {
err = __DRI_IMAGE_ERROR_BAD_MATCH; err = __DRI_IMAGE_ERROR_BAD_MATCH;
@@ -922,15 +1033,12 @@ dri2_create_image_from_fd(__DRIscreen *_screen,
} }
switch (fourcc) { switch (fourcc) {
case __DRI_IMAGE_FOURCC_YUV420: case __DRI_IMAGE_FOURCC_YUYV:
case __DRI_IMAGE_FOURCC_YVU420: case __DRI_IMAGE_FOURCC_UYVY:
expected_num_fds = 3; expected_num_fds = 1;
break;
case __DRI_IMAGE_FOURCC_NV12:
expected_num_fds = 2;
break; break;
default: default:
expected_num_fds = 1; expected_num_fds = map->nplanes;
break; break;
} }
@@ -941,30 +1049,23 @@ dri2_create_image_from_fd(__DRIscreen *_screen,
memset(whandles, 0, sizeof(whandles)); memset(whandles, 0, sizeof(whandles));
for (i = 0; i < num_fds; i++) { for (i = 0; i < map->nplanes; i++) {
if (fds[i] < 0) { int fdnum = i >= num_fds ? 0 : i;
int index = map->planes[i].buffer_index;
if (fds[fdnum] < 0) {
err = __DRI_IMAGE_ERROR_BAD_ALLOC; err = __DRI_IMAGE_ERROR_BAD_ALLOC;
goto exit; goto exit;
} }
whandles[i].type = WINSYS_HANDLE_TYPE_FD; whandles[i].type = WINSYS_HANDLE_TYPE_FD;
whandles[i].handle = (unsigned)fds[i]; whandles[i].handle = (unsigned)fds[fdnum];
whandles[i].stride = (unsigned)strides[i]; whandles[i].stride = (unsigned)strides[index];
whandles[i].offset = (unsigned)offsets[i]; whandles[i].offset = (unsigned)offsets[index];
whandles[i].modifier = modifier; whandles[i].modifier = modifier;
} }
if (fourcc == __DRI_IMAGE_FOURCC_YVU420) {
/* convert to YUV420 by swapping 2nd and 3rd planes: */
struct winsys_handle tmp = whandles[1];
whandles[1] = whandles[2];
whandles[2] = tmp;
fourcc = __DRI_IMAGE_FOURCC_YUV420;
map = dri2_get_mapping_by_fourcc(fourcc);
}
img = dri2_create_image_from_winsys(_screen, width, height, map, img = dri2_create_image_from_winsys(_screen, width, height, map,
num_fds, whandles, loaderPrivate); map->nplanes, whandles, loaderPrivate);
if(img == NULL) { if(img == NULL) {
err = __DRI_IMAGE_ERROR_BAD_ALLOC; err = __DRI_IMAGE_ERROR_BAD_ALLOC;
goto exit; goto exit;

View File

@@ -438,7 +438,22 @@ dri_get_egl_image(struct st_manager *smapi,
stimg->format = PIPE_FORMAT_IYUV; stimg->format = PIPE_FORMAT_IYUV;
break; break;
case __DRI_IMAGE_COMPONENTS_Y_UV: case __DRI_IMAGE_COMPONENTS_Y_UV:
if (img->texture->format == PIPE_FORMAT_R8_UNORM)
stimg->format = PIPE_FORMAT_NV12; stimg->format = PIPE_FORMAT_NV12;
else /* P0XX uses R16 for first texture */
stimg->format = PIPE_FORMAT_P016;
break;
case __DRI_IMAGE_COMPONENTS_AYUV:
stimg->format = PIPE_FORMAT_RGBA8888_UNORM;
break;
case __DRI_IMAGE_COMPONENTS_XYUV:
stimg->format = PIPE_FORMAT_RGBX8888_UNORM;
break;
case __DRI_IMAGE_COMPONENTS_Y_XUXV:
stimg->format = PIPE_FORMAT_YUYV;
break;
case __DRI_IMAGE_COMPONENTS_Y_UXVX:
stimg->format = PIPE_FORMAT_UYVY;
break; break;
default: default:
stimg->format = img->texture->format; stimg->format = img->texture->format;

View File

@@ -309,6 +309,9 @@ update_shader_samplers(struct st_context *st,
switch (st_get_view_format(stObj)) { switch (st_get_view_format(stObj)) {
case PIPE_FORMAT_NV12: case PIPE_FORMAT_NV12:
case PIPE_FORMAT_P016:
case PIPE_FORMAT_YUYV:
case PIPE_FORMAT_UYVY:
/* we need one additional sampler: */ /* we need one additional sampler: */
extra = u_bit_scan(&free_slots); extra = u_bit_scan(&free_slots);
states[extra] = sampler; states[extra] = sampler;

View File

@@ -191,6 +191,14 @@ update_textures(struct st_context *st,
sampler_views[extra] = sampler_views[extra] =
st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl); st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl);
break; break;
case PIPE_FORMAT_P016:
/* we need one additional R16G16 view: */
tmpl.format = PIPE_FORMAT_RG1616_UNORM;
tmpl.swizzle_g = PIPE_SWIZZLE_Y; /* tmpl from Y plane is R16 */
extra = u_bit_scan(&free_slots);
sampler_views[extra] =
st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl);
break;
case PIPE_FORMAT_IYUV: case PIPE_FORMAT_IYUV:
/* we need two additional R8 views: */ /* we need two additional R8 views: */
tmpl.format = PIPE_FORMAT_R8_UNORM; tmpl.format = PIPE_FORMAT_R8_UNORM;
@@ -201,6 +209,24 @@ update_textures(struct st_context *st,
sampler_views[extra] = sampler_views[extra] =
st->pipe->create_sampler_view(st->pipe, stObj->pt->next->next, &tmpl); st->pipe->create_sampler_view(st->pipe, stObj->pt->next->next, &tmpl);
break; break;
case PIPE_FORMAT_YUYV:
/* we need one additional BGRA8888 view: */
tmpl.format = PIPE_FORMAT_BGRA8888_UNORM;
tmpl.swizzle_b = PIPE_SWIZZLE_Z;
tmpl.swizzle_a = PIPE_SWIZZLE_W;
extra = u_bit_scan(&free_slots);
sampler_views[extra] =
st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl);
break;
case PIPE_FORMAT_UYVY:
/* we need one additional RGBA8888 view: */
tmpl.format = PIPE_FORMAT_RGBA8888_UNORM;
tmpl.swizzle_b = PIPE_SWIZZLE_Z;
tmpl.swizzle_a = PIPE_SWIZZLE_W;
extra = u_bit_scan(&free_slots);
sampler_views[extra] =
st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl);
break;
default: default:
break; break;
} }

View File

@@ -54,17 +54,56 @@ is_format_supported(struct pipe_screen *screen, enum pipe_format format,
* a shader variant that converts. * a shader variant that converts.
*/ */
if ((usage == PIPE_BIND_SAMPLER_VIEW) && !supported) { if ((usage == PIPE_BIND_SAMPLER_VIEW) && !supported) {
if (format == PIPE_FORMAT_IYUV) { switch (format) {
case PIPE_FORMAT_IYUV:
supported = screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM, supported = screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM,
PIPE_TEXTURE_2D, nr_samples, PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage); nr_storage_samples, usage);
} else if (format == PIPE_FORMAT_NV12) { break;
case PIPE_FORMAT_NV12:
supported = screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM, supported = screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM,
PIPE_TEXTURE_2D, nr_samples, PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage) && nr_storage_samples, usage) &&
screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM, screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM,
PIPE_TEXTURE_2D, nr_samples, PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage); nr_storage_samples, usage);
break;
case PIPE_FORMAT_P016:
supported = screen->is_format_supported(screen, PIPE_FORMAT_R16_UNORM,
PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage) &&
screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM,
PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage);
break;
case PIPE_FORMAT_YUYV:
supported = screen->is_format_supported(screen, PIPE_FORMAT_RG88_UNORM,
PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage) &&
screen->is_format_supported(screen, PIPE_FORMAT_BGRA8888_UNORM,
PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage);
break;
case PIPE_FORMAT_UYVY:
supported = screen->is_format_supported(screen, PIPE_FORMAT_RG88_UNORM,
PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage) &&
screen->is_format_supported(screen, PIPE_FORMAT_RGBA8888_UNORM,
PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage);
break;
case PIPE_FORMAT_AYUV:
supported = screen->is_format_supported(screen, PIPE_FORMAT_RGBA8888_UNORM,
PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage);
break;
case PIPE_FORMAT_XYUV:
supported = screen->is_format_supported(screen, PIPE_FORMAT_RGBX8888_UNORM,
PIPE_TEXTURE_2D, nr_samples,
nr_storage_samples, usage);
break;
default:
break;
} }
} }
@@ -204,10 +243,28 @@ st_bind_egl_image(struct gl_context *ctx,
texFormat = MESA_FORMAT_R_UNORM8; texFormat = MESA_FORMAT_R_UNORM8;
texObj->RequiredTextureImageUnits = 2; texObj->RequiredTextureImageUnits = 2;
break; break;
case PIPE_FORMAT_P016:
texFormat = MESA_FORMAT_R_UNORM16;
texObj->RequiredTextureImageUnits = 2;
break;
case PIPE_FORMAT_IYUV: case PIPE_FORMAT_IYUV:
texFormat = MESA_FORMAT_R_UNORM8; texFormat = MESA_FORMAT_R_UNORM8;
texObj->RequiredTextureImageUnits = 3; texObj->RequiredTextureImageUnits = 3;
break; break;
case PIPE_FORMAT_YUYV:
case PIPE_FORMAT_UYVY:
texFormat = MESA_FORMAT_R8G8_UNORM;
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: default:
texFormat = st_pipe_format_to_mesa_format(stimg->format); texFormat = st_pipe_format_to_mesa_format(stimg->format);
break; break;

View File

@@ -1201,20 +1201,28 @@ st_create_fp_variant(struct st_context *st,
NIR_PASS_V(tgsi.ir.nir, nir_lower_drawpixels, &options); NIR_PASS_V(tgsi.ir.nir, nir_lower_drawpixels, &options);
} }
if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv)) { if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
key->external.lower_xy_uxvx || key->external.lower_yx_xuxv ||
key->external.lower_ayuv || key->external.lower_xyuv)) {
nir_lower_tex_options options = {0}; nir_lower_tex_options options = {0};
options.lower_y_uv_external = key->external.lower_nv12; options.lower_y_uv_external = key->external.lower_nv12;
options.lower_y_u_v_external = key->external.lower_iyuv; options.lower_y_u_v_external = key->external.lower_iyuv;
options.lower_xy_uxvx_external = key->external.lower_xy_uxvx;
options.lower_yx_xuxv_external = key->external.lower_yx_xuxv;
options.lower_ayuv_external = key->external.lower_ayuv;
options.lower_xyuv_external = key->external.lower_xyuv;
NIR_PASS_V(tgsi.ir.nir, nir_lower_tex, &options); NIR_PASS_V(tgsi.ir.nir, nir_lower_tex, &options);
} }
st_finalize_nir(st, &stfp->Base, stfp->shader_program, tgsi.ir.nir); st_finalize_nir(st, &stfp->Base, stfp->shader_program, tgsi.ir.nir);
if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv)) { if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
key->external.lower_xy_uxvx || key->external.lower_yx_xuxv)) {
/* This pass needs to happen *after* nir_lower_sampler */ /* This pass needs to happen *after* nir_lower_sampler */
NIR_PASS_V(tgsi.ir.nir, st_nir_lower_tex_src_plane, NIR_PASS_V(tgsi.ir.nir, st_nir_lower_tex_src_plane,
~stfp->Base.SamplersUsed, ~stfp->Base.SamplersUsed,
key->external.lower_nv12, key->external.lower_nv12 || key->external.lower_xy_uxvx ||
key->external.lower_yx_xuxv,
key->external.lower_iyuv); key->external.lower_iyuv);
} }
@@ -1318,7 +1326,8 @@ st_create_fp_variant(struct st_context *st,
fprintf(stderr, "mesa: cannot create a shader for glDrawPixels\n"); fprintf(stderr, "mesa: cannot create a shader for glDrawPixels\n");
} }
if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv)) { if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
key->external.lower_xy_uxvx || key->external.lower_yx_xuxv)) {
const struct tgsi_token *tokens; const struct tgsi_token *tokens;
/* samplers inserted would conflict, but this should be unpossible: */ /* samplers inserted would conflict, but this should be unpossible: */
@@ -1326,7 +1335,9 @@ st_create_fp_variant(struct st_context *st,
tokens = st_tgsi_lower_yuv(tgsi.tokens, tokens = st_tgsi_lower_yuv(tgsi.tokens,
~stfp->Base.SamplersUsed, ~stfp->Base.SamplersUsed,
key->external.lower_nv12, key->external.lower_nv12 ||
key->external.lower_xy_uxvx ||
key->external.lower_yx_xuxv,
key->external.lower_iyuv); key->external.lower_iyuv);
if (tokens) { if (tokens) {
if (tgsi.tokens != stfp->tgsi.tokens) if (tgsi.tokens != stfp->tgsi.tokens)

View File

@@ -53,6 +53,10 @@ struct st_external_sampler_key
{ {
GLuint lower_nv12; /**< bitmask of 2 plane YUV samplers */ GLuint lower_nv12; /**< bitmask of 2 plane YUV samplers */
GLuint lower_iyuv; /**< bitmask of 3 plane YUV samplers */ GLuint lower_iyuv; /**< bitmask of 3 plane YUV samplers */
GLuint lower_xy_uxvx; /**< bitmask of 2 plane YUV samplers */
GLuint lower_yx_xuxv; /**< bitmask of 2 plane YUV samplers */
GLuint lower_ayuv;
GLuint lower_xyuv;
}; };
static inline struct st_external_sampler_key static inline struct st_external_sampler_key
@@ -70,12 +74,26 @@ st_get_external_sampler_key(struct st_context *st, struct gl_program *prog)
switch (st_get_view_format(stObj)) { switch (st_get_view_format(stObj)) {
case PIPE_FORMAT_NV12: case PIPE_FORMAT_NV12:
case PIPE_FORMAT_P016:
key.lower_nv12 |= (1 << unit); key.lower_nv12 |= (1 << unit);
break; break;
case PIPE_FORMAT_IYUV: case PIPE_FORMAT_IYUV:
key.lower_iyuv |= (1 << unit); key.lower_iyuv |= (1 << unit);
break; break;
case PIPE_FORMAT_YUYV:
key.lower_yx_xuxv |= (1 << unit);
break;
case PIPE_FORMAT_UYVY:
key.lower_xy_uxvx |= (1 << unit);
break;
case PIPE_FORMAT_AYUV:
key.lower_ayuv |= (1 << unit);
break;
case PIPE_FORMAT_XYUV:
key.lower_xyuv |= (1 << unit);
break;
default: default:
printf("unhandled %u\n", st_get_view_format(stObj));
break; break;
} }
} }

View File

@@ -495,6 +495,19 @@ get_sampler_view_format(struct st_context *st,
case PIPE_FORMAT_IYUV: case PIPE_FORMAT_IYUV:
format = PIPE_FORMAT_R8_UNORM; format = PIPE_FORMAT_R8_UNORM;
break; break;
case PIPE_FORMAT_P016:
format = PIPE_FORMAT_R16_UNORM;
break;
case PIPE_FORMAT_YUYV:
case PIPE_FORMAT_UYVY:
format = PIPE_FORMAT_R8G8_UNORM;
break;
case PIPE_FORMAT_AYUV:
format = PIPE_FORMAT_RGBA8888_UNORM;
break;
case PIPE_FORMAT_XYUV:
format = PIPE_FORMAT_RGBX8888_UNORM;
break;
default: default:
break; break;
} }