[Mesa-dev] [PATCH] st/xvmc: deal with drivers wanting different texture formats

Ilia Mirkin imirkin at alum.mit.edu
Tue May 9 00:08:14 UTC 2017


On Sun, May 7, 2017 at 9:48 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
> Previously, texture formats were being used unconditionally without
> checking. However nv30 supports neither RGBX8 nor R4A4/A4R4 formats. Add
> sufficient fallbacks so that the nv30 driver can have working OSD.
>
> Tested on a NV44A/PCI.
>
> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
> ---
>
> I need to double-check that I didn't break everything on nv50+, which does
> support all the various formats. Will definitely do that before pushing.

I tested this on a G92 with the xvmc frontend to both the VP2 and
PMPEG backends (although the 3D bit remains the same). Seems to work.
Acts funny with bobdeint turned on, but it did before this patch too.
I know basically no one cares about XvMC, so I'm just going to push
this after a week of no comments.

  -ilia

>
>  src/gallium/state_trackers/xvmc/subpicture.c | 151 ++++++++++++++++++++-------
>  1 file changed, 115 insertions(+), 36 deletions(-)
>
> diff --git a/src/gallium/state_trackers/xvmc/subpicture.c b/src/gallium/state_trackers/xvmc/subpicture.c
> index 8b95a4e..bc26976 100644
> --- a/src/gallium/state_trackers/xvmc/subpicture.c
> +++ b/src/gallium/state_trackers/xvmc/subpicture.c
> @@ -48,22 +48,43 @@
>  #define FOURCC_AI44 0x34344941
>  #define FOURCC_IA44 0x34344149
>
> -static enum pipe_format XvIDToPipe(int xvimage_id)
> +static enum pipe_format XvIDToPipe(struct pipe_screen *screen,
> +                                   int xvimage_id)
>  {
> -   switch (xvimage_id) {
> -      case FOURCC_RGB:
> -         return PIPE_FORMAT_B8G8R8X8_UNORM;
> -
> -      case FOURCC_AI44:
> -         return PIPE_FORMAT_R4A4_UNORM;
> +   enum pipe_format ret;
> +   assert(screen);
>
> -      case FOURCC_IA44:
> -         return PIPE_FORMAT_A4R4_UNORM;
> +   switch (xvimage_id) {
> +   case FOURCC_RGB:
> +      ret = PIPE_FORMAT_B8G8R8X8_UNORM;
> +      break;
> +
> +   case FOURCC_AI44:
> +      ret = PIPE_FORMAT_R4A4_UNORM;
> +      if (!screen->is_format_supported(
> +                screen, ret, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW))
> +         ret = PIPE_FORMAT_B4G4R4A4_UNORM;
> +      break;
> +
> +   case FOURCC_IA44:
> +      ret = PIPE_FORMAT_A4R4_UNORM;
> +      if (!screen->is_format_supported(
> +                screen, ret, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW))
> +         ret = PIPE_FORMAT_B4G4R4A4_UNORM;
> +      break;
> +
> +   default:
> +      XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id);
> +      return PIPE_FORMAT_NONE;
> +   }
>
> -      default:
> -         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id);
> -         return PIPE_FORMAT_NONE;
> +   if (!screen->is_format_supported(
> +             screen, ret, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW)) {
> +      XVMC_MSG(XVMC_ERR, "[XvMC] Unsupported 2D format %s for Xv image ID 0x%08X.\n", util_format_name(ret), xvimage_id);
> +      ret = PIPE_FORMAT_NONE;
>     }
> +   return ret;
> +
>  }
>
>  static unsigned NumPaletteEntries4XvID(int xvimage_id)
> @@ -82,29 +103,44 @@ static unsigned NumPaletteEntries4XvID(int xvimage_id)
>     }
>  }
>
> -static int PipeToComponentOrder(enum pipe_format format, char *component_order)
> +static int PipeToComponentOrder(struct pipe_screen *screen,
> +                                enum pipe_format format,
> +                                enum pipe_format *palette_format,
> +                                char *component_order)
>  {
> +   assert(screen);
>     assert(component_order);
> +   assert(palette_format);
>
>     switch (format) {
> -      case PIPE_FORMAT_B8G8R8X8_UNORM:
> -         return 0;
> -
> -      case PIPE_FORMAT_A4R4_UNORM:
> -      case PIPE_FORMAT_R4A4_UNORM:
> -         component_order[0] = 'Y';
> -         component_order[1] = 'U';
> -         component_order[2] = 'V';
> -         component_order[3] = 'A';
> -         return 4;
> -
> -      default:
> -         XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format);
> -         component_order[0] = 0;
> -         component_order[1] = 0;
> -         component_order[2] = 0;
> -         component_order[3] = 0;
> -         return 0;
> +   case PIPE_FORMAT_B8G8R8X8_UNORM:
> +      return 0;
> +
> +   case PIPE_FORMAT_A4R4_UNORM:
> +   case PIPE_FORMAT_R4A4_UNORM:
> +   case PIPE_FORMAT_B4G4R4A4_UNORM:
> +      *palette_format = PIPE_FORMAT_R8G8B8X8_UNORM;
> +      component_order[0] = 'Y';
> +      component_order[1] = 'U';
> +      component_order[2] = 'V';
> +      component_order[3] = 'A';
> +      if (!screen->is_format_supported(
> +                screen, *palette_format, PIPE_TEXTURE_1D, 0,
> +                PIPE_BIND_SAMPLER_VIEW)) {
> +         /* One of these formats better be supported... */
> +         *palette_format = PIPE_FORMAT_B8G8R8X8_UNORM;
> +         component_order[0] = 'V';
> +         component_order[2] = 'Y';
> +      }
> +      return 4;
> +
> +   default:
> +      XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format);
> +      component_order[0] = 0;
> +      component_order[1] = 0;
> +      component_order[2] = 0;
> +      component_order[3] = 0;
> +      return 0;
>     }
>  }
>
> @@ -186,6 +222,41 @@ upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst,
>     pipe->transfer_unmap(pipe, transfer);
>  }
>
> +static void
> +upload_sampler_convert(struct pipe_context *pipe, struct pipe_sampler_view *dst,
> +                       const struct pipe_box *dst_box, const XvImage *image,
> +                       unsigned src_x, unsigned src_y)
> +{
> +   struct pipe_transfer *transfer;
> +   int i, j;
> +   char *map, *src;
> +
> +   map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE,
> +                            dst_box, &transfer);
> +   if (!map)
> +      return;
> +
> +   src = image->data;
> +   src += src_y * image->width + src_x;
> +   if (image->id == FOURCC_AI44) {
> +      /* The format matches what we want, we just have to insert dummy
> +       * bytes. So just copy the same value in twice.
> +       */
> +      for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width)
> +         for (j = 0; j < dst_box->width; j++)
> +            map[j * 2 + 0] = map[j * 2 + 1] = src[j];
> +   } else {
> +      assert(image->id == FOURCC_IA44);
> +      /* Same idea as above, but we have to swap the low and high nibbles.
> +       */
> +      for (i = 0; i < dst_box->height; i++, map += transfer->stride, src += image->width)
> +         for (j = 0; j < dst_box->width; j++)
> +            map[j * 2 + 0] = map[j * 2 + 1] = (src[j] >> 4) | (src[j] << 4);
> +   }
> +
> +   pipe->transfer_unmap(pipe, transfer);
> +}
> +
>  PUBLIC
>  Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture,
>                              unsigned short width, unsigned short height, int xvimage_id)
> @@ -195,6 +266,7 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *
>     struct pipe_context *pipe;
>     struct pipe_resource tex_templ, *tex;
>     struct pipe_sampler_view sampler_templ;
> +   enum pipe_format palette_format;
>     Status ret;
>
>     XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture);
> @@ -224,7 +296,7 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *
>
>     memset(&tex_templ, 0, sizeof(tex_templ));
>     tex_templ.target = PIPE_TEXTURE_2D;
> -   tex_templ.format = XvIDToPipe(xvimage_id);
> +   tex_templ.format = XvIDToPipe(pipe->screen, xvimage_id);
>     tex_templ.last_level = 0;
>     if (pipe->screen->get_video_param(pipe->screen,
>                                       PIPE_VIDEO_PROFILE_UNKNOWN,
> @@ -262,12 +334,14 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *
>     subpicture->width = width;
>     subpicture->height = height;
>     subpicture->num_palette_entries = NumPaletteEntries4XvID(xvimage_id);
> -   subpicture->entry_bytes = PipeToComponentOrder(tex_templ.format, subpicture->component_order);
> +   subpicture->entry_bytes = PipeToComponentOrder(
> +         pipe->screen, tex_templ.format, &palette_format,
> +         subpicture->component_order);
>     subpicture->privData = subpicture_priv;
>
>     if (subpicture->num_palette_entries > 0) {
>        tex_templ.target = PIPE_TEXTURE_1D;
> -      tex_templ.format = PIPE_FORMAT_R8G8B8X8_UNORM;
> +      tex_templ.format = palette_format;
>        tex_templ.width0 = subpicture->num_palette_entries;
>        tex_templ.height0 = 1;
>        tex_templ.usage = PIPE_USAGE_DEFAULT;
> @@ -366,8 +440,13 @@ Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage
>
>     /* clipping should be done by upload_sampler and regardles what the documentation
>     says image->pitches[0] doesn't seems to be in bytes, so don't use it */
> -   src_stride = image->width * util_format_get_blocksize(subpicture_priv->sampler->texture->format);
> -   upload_sampler(pipe, subpicture_priv->sampler, &dst_box, image->data, src_stride, srcx, srcy);
> +   if ((image->id == FOURCC_IA44 || image->id == FOURCC_AI44) &&
> +       subpicture_priv->sampler->texture->format == PIPE_FORMAT_B4G4R4A4_UNORM) {
> +      upload_sampler_convert(pipe, subpicture_priv->sampler, &dst_box, image, srcx, srcy);
> +   } else {
> +      src_stride = image->width * util_format_get_blocksize(subpicture_priv->sampler->texture->format);
> +      upload_sampler(pipe, subpicture_priv->sampler, &dst_box, image->data, src_stride, srcx, srcy);
> +   }
>
>     XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture);
>
> --
> 2.10.2
>


More information about the mesa-dev mailing list