[Mesa-dev] [PATCH 2/2] intel: Support new dri image interface v2

Kristian Høgsberg krh at bitplanet.net
Fri Aug 31 09:39:24 PDT 2012


On Fri, Aug 31, 2012 at 9:22 AM, Jakob Bornecrantz <jakob at vmware.com> wrote:
> Follow up to the previous patch, kept seperate for easier viewing,
> will be merged with previous patch before commiting.
>
> v2: Should fix YUV pitch/stride == 0.
>
> Signed-off-by: Jakob Bornecrantz <jakob at vmware.com>

Works here too:

Tested-by: Kristian Høgsberg <krh at bitplanet.net>
Reviewed-by: Kristian Høgsberg <krh at bitplanet.net>

thanks,
Kristian


> ---
>  src/mesa/drivers/dri/intel/intel_regions.h |   26 ++++++
>  src/mesa/drivers/dri/intel/intel_screen.c  |  135 ++++++++++++++++++++++++++--
>  2 files changed, 153 insertions(+), 8 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/intel/intel_regions.h b/src/mesa/drivers/dri/intel/intel_regions.h
> index 4ff0efe..c0fdc95 100644
> --- a/src/mesa/drivers/dri/intel/intel_regions.h
> +++ b/src/mesa/drivers/dri/intel/intel_regions.h
> @@ -141,12 +141,38 @@ uint32_t
>  intel_region_get_aligned_offset(struct intel_region *region, uint32_t x,
>                                  uint32_t y);
>
> +/**
> + * Used with images created with image_from_names
> + * to help support planar images.
> + */
> +typedef struct intel_image_format {
> +   int fourcc;
> +   int components;
> +   int nplanes;
> +   struct {
> +      int buffer_index;
> +      int width_shift;
> +      int height_shift;
> +      uint32_t dri_format;
> +      int cpp;
> +   } planes[3];
> +} intel_image_format_t;
> +
>  struct __DRIimageRec {
>     struct intel_region *region;
>     GLenum internal_format;
>     uint32_t dri_format;
>     GLuint format;
>     uint32_t offset;
> +
> +   /*
> +    * Need to save these here between calls to
> +    * image_from_names and calls to image_from_planar.
> +    */
> +   uint32_t strides[3];
> +   uint32_t offsets[3];
> +   struct intel_image_format *planar_format;
> +
>     void *data;
>  };
>
> diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
> index 55cebac..f20b072 100644
> --- a/src/mesa/drivers/dri/intel/intel_screen.c
> +++ b/src/mesa/drivers/dri/intel/intel_screen.c
> @@ -190,6 +190,59 @@ static const struct __DRI2flushExtensionRec intelFlushExtension = {
>      dri2InvalidateDrawable,
>  };
>
> +intel_image_format_t intel_image_formats[] = {
> +   { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
> +     { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
> +
> +   { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1,
> +     { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
> +
> +   { __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_COMPONENTS_Y_U_V, 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_COMPONENTS_Y_U_V, 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_COMPONENTS_Y_U_V, 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_COMPONENTS_Y_U_V, 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_COMPONENTS_Y_U_V, 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_NV12, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
> +     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
> +       { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } },
> +
> +   { __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
> +     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
> +       { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } },
> +
> +   /* For YUYV 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 and samples YUYV 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_COMPONENTS_Y_XUXV, 2,
> +     { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
> +       { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }
> +};
> +
>  static __DRIimage *
>  intel_allocate_image(int dri_format, void *loaderPrivate)
>  {
> @@ -249,7 +302,7 @@ intel_create_image_from_name(__DRIscreen *screen,
>
>      image = intel_allocate_image(format, loaderPrivate);
>      if (image->format == MESA_FORMAT_NONE)
> -       cpp = 0;
> +       cpp = 1;
>      else
>         cpp = _mesa_get_format_bytes(image->format);
>      image->region = intel_region_alloc_for_handle(intelScreen,
> @@ -372,6 +425,11 @@ intel_query_image(__DRIimage *image, int attrib, int *value)
>     case __DRI_IMAGE_ATTRIB_HEIGHT:
>        *value = image->region->height;
>        return true;
> +   case __DRI_IMAGE_ATTRIB_COMPONENTS:
> +      if (image->planar_format == NULL)
> +         return false;
> +      *value = image->planar_format->components;
> +      return true;
>    default:
>        return false;
>     }
> @@ -393,11 +451,15 @@ intel_dup_image(__DRIimage *orig_image, void *loaderPrivate)
>     }
>
>     image->internal_format = orig_image->internal_format;
> +   image->planar_format   = orig_image->planar_format;
>     image->dri_format      = orig_image->dri_format;
>     image->format          = orig_image->format;
>     image->offset          = orig_image->offset;
>     image->data            = loaderPrivate;
> -
> +
> +   memcpy(image->strides, orig_image->strides, sizeof(image->strides));
> +   memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets));
> +
>     return image;
>  }
>
> @@ -413,16 +475,72 @@ intel_validate_usage(__DRIimage *image, unsigned int use)
>  }
>
>  static __DRIimage *
> -intel_create_sub_image(__DRIimage *parent,
> -                       int width, int height, int dri_format,
> -                       int offset, int pitch, void *loaderPrivate)
> +intel_create_image_from_names(__DRIscreen *screen,
> +                              int width, int height, int fourcc,
> +                              int *names, int num_names,
> +                              int *strides, int *offsets,
> +                              void *loaderPrivate)
>  {
> +    struct intel_image_format *f = NULL;
>      __DRIimage *image;
> -    int cpp;
> +    int i, index;
> +
> +    if (screen == NULL || names == NULL || num_names != 1)
> +        return NULL;
> +
> +    for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) {
> +        if (intel_image_formats[i].fourcc == fourcc) {
> +           f = &intel_image_formats[i];
> +        }
> +    }
> +
> +    if (f == NULL)
> +        return NULL;
> +
> +    image = intel_create_image_from_name(screen, width, height,
> +                                         __DRI_IMAGE_FORMAT_NONE,
> +                                         names[0], strides[0],
> +                                         loaderPrivate);
> +
> +    if (image == NULL)
> +        return NULL;
> +
> +    image->planar_format = f;
> +    for (i = 0; i < f->nplanes; i++) {
> +        index = f->planes[i].buffer_index;
> +        image->offsets[index] = offsets[index];
> +        image->strides[index] = strides[index];
> +    }
> +
> +    return image;
> +}
> +
> +static __DRIimage *
> +intel_from_planar(__DRIimage *parent, int plane, void *loaderPrivate)
> +{
> +    int width, height, offset, stride, dri_format, cpp, index, pitch;
> +    struct intel_image_format *f;
>      uint32_t mask_x, mask_y;
> +    __DRIimage *image;
> +
> +    if (parent == NULL || parent->planar_format == NULL)
> +        return NULL;
> +
> +    f = parent->planar_format;
> +
> +    if (plane >= f->nplanes)
> +        return NULL;
> +
> +    width = parent->region->width >> f->planes[plane].width_shift;
> +    height = parent->region->height >> f->planes[plane].height_shift;
> +    dri_format = f->planes[plane].dri_format;
> +    index = f->planes[plane].buffer_index;
> +    offset = parent->offsets[index];
> +    stride = parent->strides[index];
>
>      image = intel_allocate_image(dri_format, loaderPrivate);
> -    cpp = _mesa_get_format_bytes(image->format);
> +    cpp = _mesa_get_format_bytes(image->format); /* safe since no none format */
> +    pitch = stride / cpp;
>      if (offset + height * cpp * pitch > parent->region->bo->size) {
>         _mesa_warning(NULL, "intel_create_sub_image: subimage out of bounds");
>         FREE(image);
> @@ -463,7 +581,8 @@ static struct __DRIimageExtensionRec intelImageExtension = {
>      intel_query_image,
>      intel_dup_image,
>      intel_validate_usage,
> -    intel_create_sub_image
> +    intel_create_image_from_names,
> +    intel_from_planar
>  };
>
>  static const __DRIextension *intelScreenExtensions[] = {
> --
> 1.7.9.5
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list