[Mesa-dev] [PATCH 4/4] i965: Refactor DRI image code

Ander Conselvan de Oliveira conselvan2 at gmail.com
Wed Nov 27 07:52:08 PST 2013


From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>

The DRI image extension gained a lot of new entry points lately. Some
of the new additions have a slightly different signature. The planar
image introduces the concept of an image without a format from which
different well structured images can be created. The way this has
been done means that one can't aways rely on all of the fields in a
__DRIimage to be valid or useable.

This patch tries to make the whole implementation more consistent. All
images become planar with a valid intel_image_format. The dri_image and
gl_format fields are dropped, and when creating an image from a texture
or renderbuffer, a custom intel_image_format is allocated to match that
of the original object. Every image has at least one plane and a field
inside the image tells to which plane that particular image refers to.

For allocating the image, both DRI_FORMAT_* and DRI_FOURCC_* were used.
Now the allocation code always takes fourcc and the extension entry
points convert from dri format when necessary. Also, intel_image_format
now holds a regular gl_format, so dri_format is not used internally
anymore.

The bulk of the image code is moved to a separate file and the part in
intel_screen.c only does some parameter conversion and calls into the
other file.
---
 src/mesa/drivers/dri/i965/Makefile.sources  |    1 +
 src/mesa/drivers/dri/i965/intel_fbo.c       |   11 +-
 src/mesa/drivers/dri/i965/intel_image.c     |  390 ++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/intel_image.h     |   73 +++++
 src/mesa/drivers/dri/i965/intel_regions.h   |    9 +-
 src/mesa/drivers/dri/i965/intel_screen.c    |  427 +++++----------------------
 src/mesa/drivers/dri/i965/intel_tex_image.c |    8 +-
 7 files changed, 559 insertions(+), 360 deletions(-)
 create mode 100644 src/mesa/drivers/dri/i965/intel_image.c
 create mode 100644 src/mesa/drivers/dri/i965/intel_image.h

diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources
index 5724458..abd9890 100644
--- a/src/mesa/drivers/dri/i965/Makefile.sources
+++ b/src/mesa/drivers/dri/i965/Makefile.sources
@@ -10,6 +10,7 @@ i965_FILES = \
 	intel_debug.c \
 	intel_extensions.c \
 	intel_fbo.c \
+	intel_image.c \
 	intel_mipmap_tree.c \
 	intel_regions.c \
 	intel_resolve_map.c \
diff --git a/src/mesa/drivers/dri/i965/intel_fbo.c b/src/mesa/drivers/dri/i965/intel_fbo.c
index ae978f1..87c3b33 100644
--- a/src/mesa/drivers/dri/i965/intel_fbo.c
+++ b/src/mesa/drivers/dri/i965/intel_fbo.c
@@ -254,6 +254,7 @@ intel_image_target_renderbuffer_storage(struct gl_context *ctx,
    struct intel_renderbuffer *irb;
    __DRIscreen *screen;
    __DRIimage *image;
+   gl_format format;
 
    screen = brw->intelScreen->driScrnPriv;
    image = screen->dri2.image->lookupEGLImage(screen, image_handle,
@@ -261,7 +262,7 @@ intel_image_target_renderbuffer_storage(struct gl_context *ctx,
    if (image == NULL)
       return;
 
-   if (image->planar_format && image->planar_format->nplanes > 1) {
+   if (image->format->nplanes > 1) {
       _mesa_error(ctx, GL_INVALID_OPERATION,
             "glEGLImageTargetRenderbufferStorage(planar buffers are not "
                "supported as render targets.");
@@ -276,7 +277,9 @@ intel_image_target_renderbuffer_storage(struct gl_context *ctx,
    }
 
    /* __DRIimage is opaque to the core so it has to be checked here */
-   switch (image->format) {
+   format = image->format->planes[0].format;
+
+   switch (format) {
    case MESA_FORMAT_RGBA8888_REV:
       _mesa_error(ctx, GL_INVALID_OPERATION,
             "glEGLImageTargetRenderbufferStorage(unsupported image format");
@@ -290,7 +293,7 @@ intel_image_target_renderbuffer_storage(struct gl_context *ctx,
    intel_miptree_release(&irb->mt);
    irb->mt = intel_miptree_create_for_bo(brw,
                                          image->region->bo,
-                                         image->format,
+                                         format,
                                          image->region->offset,
                                          image->region->width,
                                          image->region->height,
@@ -302,7 +305,7 @@ intel_image_target_renderbuffer_storage(struct gl_context *ctx,
    rb->InternalFormat = image->internal_format;
    rb->Width = image->region->width;
    rb->Height = image->region->height;
-   rb->Format = image->format;
+   rb->Format = format;
    rb->_BaseFormat = _mesa_base_fbo_format(ctx, image->internal_format);
    rb->NeedsFinishRenderTexture = true;
 }
diff --git a/src/mesa/drivers/dri/i965/intel_image.c b/src/mesa/drivers/dri/i965/intel_image.c
new file mode 100644
index 0000000..cb258cf
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_image.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "main/formats.h"
+#include "main/macros.h"
+
+#include "dri_util.h"
+
+#include "intel_image.h"
+#include "intel_regions.h"
+
+#include "i915_drm.h"
+
+static struct intel_image_format intel_image_formats[] = {
+   { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
+     { { 0, 0, 0, MESA_FORMAT_ARGB8888, 4 } } },
+
+   { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1,
+     { { 0, 0, 0, MESA_FORMAT_XRGB8888, 4 }, } },
+
+   { __DRI_IMAGE_FOURCC_ABGR8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
+     { { 0, 0, 0, MESA_FORMAT_RGBA8888_REV, 4 } } },
+
+   { __DRI_IMAGE_FOURCC_XBGR8888, __DRI_IMAGE_COMPONENTS_RGB, 1,
+     { { 0, 0, 0, MESA_FORMAT_RGBX8888_REV, 4 }, } },
+
+   { __DRI_IMAGE_FOURCC_RGB565, __DRI_IMAGE_COMPONENTS_RGB, 1,
+     { { 0, 0, 0, MESA_FORMAT_RGB565, 2 } } },
+
+   { __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, MESA_FORMAT_R8, 1 },
+       { 1, 2, 2, MESA_FORMAT_R8, 1 },
+       { 2, 2, 2, MESA_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YUV411, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, MESA_FORMAT_R8, 1 },
+       { 1, 2, 0, MESA_FORMAT_R8, 1 },
+       { 2, 2, 0, MESA_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, MESA_FORMAT_R8, 1 },
+       { 1, 1, 1, MESA_FORMAT_R8, 1 },
+       { 2, 1, 1, MESA_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YUV422, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, MESA_FORMAT_R8, 1 },
+       { 1, 1, 0, MESA_FORMAT_R8, 1 },
+       { 2, 1, 0, MESA_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YUV444, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, MESA_FORMAT_R8, 1 },
+       { 1, 0, 0, MESA_FORMAT_R8, 1 },
+       { 2, 0, 0, MESA_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
+     { { 0, 0, 0, MESA_FORMAT_R8, 1 },
+       { 1, 1, 1, MESA_FORMAT_GR88, 2 } } },
+
+   { __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
+     { { 0, 0, 0, MESA_FORMAT_R8, 1 },
+       { 1, 1, 0, MESA_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, MESA_FORMAT_GR88, 2 },
+       { 0, 1, 0, MESA_FORMAT_ARGB8888, 4 } } }
+};
+
+int
+dri_format_to_fourcc(int dri_format)
+{
+   switch (dri_format) {
+   case __DRI_IMAGE_FORMAT_RGB565:
+      return __DRI_IMAGE_FOURCC_RGB565;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      return __DRI_IMAGE_FOURCC_XRGB8888;
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      return __DRI_IMAGE_FOURCC_ARGB8888;
+   case __DRI_IMAGE_FORMAT_ABGR8888:
+      return __DRI_IMAGE_FOURCC_ABGR8888;
+   case __DRI_IMAGE_FORMAT_XBGR8888:
+      return __DRI_IMAGE_FOURCC_XBGR8888;
+   default:
+      return 0;
+   }
+}
+
+struct intel_image_format *
+intel_image_format_lookup(int fourcc)
+{
+   struct intel_image_format *f = NULL;
+
+   for (unsigned i = 0; i < ARRAY_SIZE(intel_image_formats); i++) {
+      if (intel_image_formats[i].fourcc == fourcc) {
+	 f = &intel_image_formats[i];
+	 break;
+      }
+   }
+
+   return f;
+}
+
+void
+intel_image_destroy(intel_image_t *image)
+{
+   intel_region_release(&image->region);
+
+   if (image->format->fourcc == 0)
+      free(image->format);
+
+   free(image);
+}
+
+void
+intel_image_set_gl_format(intel_image_t *image,
+                          GLenum internal_format, GLuint gl_format)
+{
+   struct intel_image_format *f = image->format;
+
+   if (f->fourcc != 0) {
+      _mesa_warning(NULL, "intel_image_set_gl_format: "
+                    "image already has a format, skipping");
+      return;
+   }
+
+   memset(f, 0, sizeof *f);
+
+   switch (internal_format) {
+   case GL_RGB:
+      f->components = __DRI_IMAGE_COMPONENTS_RGB;
+      break;
+   case GL_RGBA:
+      f->components = __DRI_IMAGE_COMPONENTS_RGBA;
+      break;
+   default:
+      f->components = 0;
+   }
+
+   f->nplanes = 1;
+   f->planes[0].format = gl_format;
+
+   image->internal_format = internal_format;
+}
+
+intel_image_t *
+intel_image_create_from_region(int fourcc, struct intel_region *region,
+                               int *strides, int *offsets, int plane)
+{
+   intel_image_t *image;
+   struct intel_image_format *f;
+   int i, index;
+   gl_format format;
+
+   if (fourcc != 0)
+      f = intel_image_format_lookup(fourcc);
+   else
+      f = calloc(1, sizeof *f);
+
+   if (f == NULL)
+      return NULL;
+
+   image = calloc(1, sizeof *image);
+   if (image == NULL)
+      return NULL;
+
+   image->region = region;
+   image->format = f;
+   image->plane = plane;
+
+   format = f->planes[plane].format;
+   image->internal_format = _mesa_get_format_base_format(format);
+
+   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 uint32_t
+choose_tiling(int use)
+{
+   uint32_t tiling;
+
+   tiling = I915_TILING_X;
+
+   if (use & __DRI_IMAGE_USE_LINEAR)
+      tiling = I915_TILING_NONE;
+
+   return tiling;
+}
+
+int
+intel_image_validate_usage(intel_image_t *image, int use)
+{
+   if (use & __DRI_IMAGE_USE_CURSOR) {
+      if (image->region->width != 64 || image->region->height != 64)
+        return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+intel_image_t *
+intel_image_create(drm_intel_bufmgr *bufmgr,
+                   int width, int height, int fourcc, int use)
+{
+   intel_image_t *image;
+   struct intel_region *region;
+   struct intel_image_format *f = intel_image_format_lookup(fourcc);
+   uint32_t tiling = choose_tiling(use);
+   int stride, offset;
+
+   if (f == NULL || f->nplanes != 1)
+      return NULL;
+
+   region = intel_region_alloc(bufmgr, tiling, f->planes[0].cpp,
+                               width, height, true);
+   if (!region)
+      return NULL;
+
+   stride = region->pitch;
+   offset = region->offset;
+
+   image = intel_image_create_from_region(fourcc, region,
+                                          &stride, &offset, 0);
+   if (!image) {
+      intel_region_release(&region);
+      return NULL;
+   }
+
+   if (!intel_image_validate_usage(image, use)) {
+      intel_image_destroy(image);
+      return NULL;
+   }
+
+   return image;
+}
+
+intel_image_t *
+intel_image_create_from_names(drm_intel_bufmgr *bufmgr,
+                              int width, int height, int fourcc,
+                              int *names, int num_names,
+                              int *strides, int *offsets)
+{
+   intel_image_t *image;
+   struct intel_region *region;
+   struct intel_image_format *f = intel_image_format_lookup(fourcc);
+
+   if (f == NULL || names == NULL || num_names != 1)
+      return NULL;
+
+   region =
+      intel_region_alloc_for_handle(bufmgr, f->planes[0].cpp, width, height,
+                                    strides[0] * f->planes[0].cpp, names[0],
+                                    "image");
+   if (!region)
+      return NULL;
+
+   image = intel_image_create_from_region(fourcc, region,
+                                          strides, offsets, 0);
+   if (!image) {
+      intel_region_release(&region);
+      return NULL;
+   }
+
+   return image;
+}
+
+intel_image_t *
+intel_image_create_from_fds(drm_intel_bufmgr *bufmgr,
+                            int width, int height, int fourcc,
+                            int *fds, int num_fds,
+                            int *strides, int *offsets)
+{
+   intel_image_t *image;
+   struct intel_region *region;
+   struct intel_image_format *f = intel_image_format_lookup(fourcc);
+
+   if (f == NULL || fds == NULL || num_fds != 1)
+      return NULL;
+
+   region = intel_region_alloc_for_fd(bufmgr, f->planes[0].cpp, width, height,
+                                      strides[0], height * strides[0], fds[0],
+                                      "image");
+   if (!region)
+      return NULL;
+
+   image = intel_image_create_from_region(fourcc, region,
+                                          strides, offsets, 0);
+   if (!image) {
+      intel_region_release(&region);
+      return NULL;
+   }
+
+   return image;
+}
+
+intel_image_t *
+intel_image_dup(intel_image_t *orig_image)
+{
+   intel_image_t *image;
+
+   image = calloc(1, sizeof *image);
+   if (image == NULL)
+      return NULL;
+
+   intel_region_reference(&image->region, orig_image->region);
+   if (image->region == NULL) {
+      free(image);
+      return NULL;
+   }
+
+   memcpy(image, orig_image, sizeof *image);
+
+   return image;
+}
+
+intel_image_t *
+intel_image_create_from_plane(intel_image_t *parent, int plane)
+{
+   intel_image_t *image;
+   struct intel_region *region;
+   struct intel_image_format *f = parent->format;
+   int width, height, offset, stride, index, cpp;
+   uint32_t mask_x, mask_y;
+   gl_format 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;
+   index = f->planes[plane].buffer_index;
+   offset = parent->offsets[index];
+   stride = parent->strides[index];
+
+   format = f->planes[plane].format;
+   cpp = _mesa_get_format_bytes(format);
+
+   region = intel_region_alloc_subregion(parent->region, cpp, width, height,
+                                         stride, offset, 0, 0);
+   if (region == NULL)
+      return NULL;
+
+   image = intel_image_create_from_region(f->fourcc, region,
+                                          (int *) parent->strides,
+                                          (int *) parent->offsets,
+                                          plane);
+   if (image == NULL) {
+      intel_region_release(&region);
+      return NULL;
+   }
+
+   intel_region_get_tile_masks(image->region, &mask_x, &mask_y, false);
+   if (offset & mask_x)
+      _mesa_warning(NULL,
+                     "intel_create_sub_image: offset not on tile boundary");
+
+   return image;
+}
diff --git a/src/mesa/drivers/dri/i965/intel_image.h b/src/mesa/drivers/dri/i965/intel_image.h
new file mode 100644
index 0000000..0429830
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/intel_image.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef INTEL_IMAGE_H
+#define INTEL_IMAGE_H
+
+#include "intel_regions.h"
+
+typedef __DRIimage intel_image_t;
+
+int
+dri_format_to_fourcc(int dri_format);
+
+struct intel_image_format *
+intel_image_format_lookup(int fourcc);
+
+void
+intel_image_set_gl_format(intel_image_t *image,
+                          GLenum internal_format, GLuint gl_format);
+void
+intel_image_destroy(intel_image_t *image);
+
+int
+intel_image_validate_usage(intel_image_t *image, int use);
+
+intel_image_t *
+intel_image_create_from_region(int fourcc, struct intel_region *region,
+                               int *strides, int *offsets, int plane);
+
+intel_image_t *
+intel_image_create(drm_intel_bufmgr *bufmgr,
+                   int width, int height, int fourcc, int use);
+
+intel_image_t *
+intel_image_create_from_names(drm_intel_bufmgr *bufmgr,
+                              int width, int height, int fourcc,
+                              int *names, int num_names,
+                              int *strides, int *offsets);
+
+intel_image_t *
+intel_image_create_from_fds(drm_intel_bufmgr *bufmgr,
+                            int width, int height, int fourcc,
+                            int *fds, int num_fds,
+                            int *strides, int *offsets);
+
+intel_image_t *
+intel_image_dup(intel_image_t *orig_image);
+
+intel_image_t *
+intel_image_create_from_plane(intel_image_t *parent, int plane);
+
+#endif /* INTEL_IMAGE_H */
diff --git a/src/mesa/drivers/dri/i965/intel_regions.h b/src/mesa/drivers/dri/i965/intel_regions.h
index 9ab5ce8..396aa46 100644
--- a/src/mesa/drivers/dri/i965/intel_regions.h
+++ b/src/mesa/drivers/dri/i965/intel_regions.h
@@ -134,16 +134,16 @@ struct intel_image_format {
       int buffer_index;
       int width_shift;
       int height_shift;
-      uint32_t dri_format;
+      GLuint format;
       int cpp;
    } planes[3];
 };
 
 struct __DRIimageRec {
    struct intel_region *region;
+   struct intel_image_format *format;
    GLenum internal_format;
-   uint32_t dri_format;
-   GLuint format;
+   int plane;
 
    /*
     * Need to save these here between calls to
@@ -151,7 +151,6 @@ struct __DRIimageRec {
     */
    uint32_t strides[3];
    uint32_t offsets[3];
-   struct intel_image_format *planar_format;
 
    /* particular miptree level */
    bool has_depthstencil;
@@ -168,8 +167,6 @@ struct __DRIimageRec {
    enum __DRISampleRange sample_range;
    enum __DRIChromaSiting horizontal_siting;
    enum __DRIChromaSiting vertical_siting;
-
-   void *data;
 };
 
 #ifdef __cplusplus
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index fe412b5..0019b8c 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -96,6 +96,7 @@ DRI_CONF_END
 #include "intel_bufmgr.h"
 #include "intel_chipset.h"
 #include "intel_fbo.h"
+#include "intel_image.h"
 #include "intel_mipmap_tree.h"
 #include "intel_screen.h"
 #include "intel_tex.h"
@@ -216,108 +217,62 @@ static const struct __DRI2flushExtensionRec intelFlushExtension = {
     .flush_with_flags   = intel_dri2_flush_with_flags,
 };
 
-static struct intel_image_format 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_RGB565, __DRI_IMAGE_COMPONENTS_RGB, 1,
-     { { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565, 2 } } },
-
-   { __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 struct intel_image_format *
-intel_image_format_lookup(int fourcc)
+static __DRIimage *
+intel_dri_image_create_from_name(__DRIscreen *screen,
+                                 int width, int height, int format,
+                                 int name, int pitch, void *loaderPrivate)
 {
-   struct intel_image_format *f = NULL;
-
-   for (unsigned i = 0; i < ARRAY_SIZE(intel_image_formats); i++) {
-      if (intel_image_formats[i].fourcc == fourcc) {
-	 f = &intel_image_formats[i];
-	 break;
-      }
-   }
+   struct intel_screen *intelScreen = screen->driverPrivate;
+   int fourcc = dri_format_to_fourcc(format);
+   int offset = 0;
 
-   return f;
+   return intel_image_create_from_names(intelScreen->bufmgr, width, height,
+                                        fourcc, &name, 1, &pitch, &offset);
 }
 
 static __DRIimage *
-intel_allocate_image(int dri_format, void *loaderPrivate)
+intel_dri_image_create_from_renderbuffer(__DRIcontext *context,
+                                         int renderbuffer,
+                                         void *loaderPrivate)
 {
-    __DRIimage *image;
+   __DRIimage *image;
+   struct intel_region *region = NULL;
+   struct brw_context *brw = context->driverPrivate;
+   struct gl_context *ctx = &brw->ctx;
+   struct gl_renderbuffer *rb;
+   struct intel_renderbuffer *irb;
+   int stride, offset;
+
+   rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
+   if (!rb) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
+      return NULL;
+   }
 
-    image = calloc(1, sizeof *image);
-    if (image == NULL)
-	return NULL;
+   irb = intel_renderbuffer(rb);
+   intel_miptree_make_shareable(brw, irb->mt);
+   intel_region_reference(&region, irb->mt->region);
 
-    image->dri_format = dri_format;
+   stride = region->pitch;
+   offset = 0;
 
-    image->format = driImageFormatToGLFormat(dri_format);
-    if (dri_format != __DRI_IMAGE_FORMAT_NONE &&
-        image->format == MESA_FORMAT_NONE) {
-       free(image);
-       return NULL;
-    }
+   image = intel_image_create_from_region(0, region, &stride, &offset, 0);
+   if (image == NULL) {
+      intel_region_release(&region);
+      return NULL;
+   }
 
-    image->internal_format = _mesa_get_format_base_format(image->format);
-    image->data = loaderPrivate;
+   intel_image_set_gl_format(image, rb->InternalFormat, rb->Format);
+   image->has_depthstencil = irb->mt->stencil_mt? true : false;
 
-    return image;
+   rb->NeedsFinishRenderTexture = true;
+   return image;
 }
 
-/**
- * Sets up a DRIImage structure to point to our shared image in a region
- */
-static void
-intel_setup_image_from_mipmap_tree(struct brw_context *brw, __DRIimage *image,
-                                   struct intel_mipmap_tree *mt, GLuint level,
-                                   GLuint zoffset)
+static struct intel_region *
+intel_region_alloc_from_mipmap_tree(struct brw_context *brw,
+                                    struct intel_mipmap_tree *mt, GLuint level,
+                                    GLuint zoffset)
 {
    unsigned int draw_x, draw_y;
    uint32_t mask_x, mask_y;
@@ -341,82 +296,9 @@ intel_setup_image_from_mipmap_tree(struct brw_context *brw, __DRIimage *image,
                                             draw_y & ~mask_y,
                                             false);
 
-   image->region = intel_region_alloc_subregion(mt->region,
-                                                mt->region->cpp,
-                                                width, height,
-                                                mt->region->pitch,
-                                                offset, tile_x, tile_y);
-}
-
-static void
-intel_setup_image_from_dimensions(__DRIimage *image)
-{
-   image->has_depthstencil = false;
-}
-
-static __DRIimage *
-intel_dri_image_create_from_name(__DRIscreen *screen,
-                                 int width, int height, int format,
-                                 int name, int pitch, void *loaderPrivate)
-{
-    struct intel_screen *intelScreen = screen->driverPrivate;
-    __DRIimage *image;
-    int cpp;
-
-    image = intel_allocate_image(format, loaderPrivate);
-    if (image == NULL)
-       return NULL;
-
-    if (image->format == MESA_FORMAT_NONE)
-       cpp = 1;
-    else
-       cpp = _mesa_get_format_bytes(image->format);
-    image->region = intel_region_alloc_for_handle(intelScreen->bufmgr,
-						  cpp, width, height,
-						  pitch * cpp, name, "image");
-    if (image->region == NULL) {
-       free(image);
-       return NULL;
-    }
-
-    intel_setup_image_from_dimensions(image);
-
-    return image;	
-}
-
-static __DRIimage *
-intel_dri_image_create_from_renderbuffer(__DRIcontext *context,
-                                         int renderbuffer,
-                                         void *loaderPrivate)
-{
-   __DRIimage *image;
-   struct brw_context *brw = context->driverPrivate;
-   struct gl_context *ctx = &brw->ctx;
-   struct gl_renderbuffer *rb;
-   struct intel_renderbuffer *irb;
-
-   rb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
-   if (!rb) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA");
-      return NULL;
-   }
-
-   irb = intel_renderbuffer(rb);
-   intel_miptree_make_shareable(brw, irb->mt);
-   image = calloc(1, sizeof *image);
-   if (image == NULL)
-      return NULL;
-
-   image->internal_format = rb->InternalFormat;
-   image->format = rb->Format;
-   image->data = loaderPrivate;
-   intel_region_reference(&image->region, irb->mt->region);
-   intel_setup_image_from_dimensions(image);
-   image->dri_format = driGLFormatToImageFormat(image->format);
-   image->has_depthstencil = irb->mt->stencil_mt? true : false;
-
-   rb->NeedsFinishRenderTexture = true;
-   return image;
+   return intel_region_alloc_subregion(mt->region, mt->region->cpp,
+                                       width, height, mt->region->pitch,
+                                       offset, tile_x, tile_y);
 }
 
 static __DRIimage *
@@ -427,9 +309,11 @@ intel_dri_image_create_from_texture(__DRIcontext *context, int target,
                                     void *loaderPrivate)
 {
    __DRIimage *image;
+   struct intel_region *region = NULL;
    struct brw_context *brw = context->driverPrivate;
    struct gl_texture_object *obj;
    struct intel_texture_object *iobj;
+   int stride, offset;
    GLuint face = 0;
 
    obj = _mesa_lookup_texture(&brw->ctx, texture);
@@ -457,24 +341,26 @@ intel_dri_image_create_from_texture(__DRIcontext *context, int target,
       *error = __DRI_IMAGE_ERROR_BAD_MATCH;
       return NULL;
    }
-   image = calloc(1, sizeof *image);
-   if (image == NULL) {
+
+   region = intel_region_alloc_from_mipmap_tree(brw, iobj->mt, level, zoffset);
+   if (!region) {
       *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
       return NULL;
    }
 
-   image->internal_format = obj->Image[face][level]->InternalFormat;
-   image->format = obj->Image[face][level]->TexFormat;
-   image->data = loaderPrivate;
-   intel_setup_image_from_mipmap_tree(brw, image, iobj->mt, level, zoffset);
-   image->dri_format = driGLFormatToImageFormat(image->format);
-   image->has_depthstencil = iobj->mt->stencil_mt? true : false;
-   if (image->dri_format == MESA_FORMAT_NONE) {
-      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
-      free(image);
+   stride = region->pitch;
+   offset = 0;
+   image = intel_image_create_from_region(0, region, &stride, &offset, 0);
+   if (!image) {
+      *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
       return NULL;
    }
 
+   intel_image_set_gl_format(image,
+                             obj->Image[face][level]->InternalFormat,
+                             obj->Image[face][level]->TexFormat);
+   image->has_depthstencil = iobj->mt->stencil_mt? true : false;
+
    *error = __DRI_IMAGE_ERROR_SUCCESS;
    return image;
 }
@@ -482,8 +368,7 @@ intel_dri_image_create_from_texture(__DRIcontext *context, int target,
 static void
 intel_dri_image_destroy(__DRIimage *image)
 {
-    intel_region_release(&image->region);
-    free(image);
+   intel_image_destroy(image);
 }
 
 static __DRIimage *
@@ -492,42 +377,17 @@ intel_dri_image_create(__DRIscreen *screen,
                        unsigned int use,
                        void *loaderPrivate)
 {
-   __DRIimage *image;
    struct intel_screen *intelScreen = screen->driverPrivate;
-   uint32_t tiling;
-   int cpp;
-
-   tiling = I915_TILING_X;
-   if (use & __DRI_IMAGE_USE_CURSOR) {
-      if (width != 64 || height != 64)
-	 return NULL;
-      tiling = I915_TILING_NONE;
-   }
-
-   if (use & __DRI_IMAGE_USE_LINEAR)
-      tiling = I915_TILING_NONE;
-
-   image = intel_allocate_image(format, loaderPrivate);
-   if (image == NULL)
-      return NULL;
-
-   cpp = _mesa_get_format_bytes(image->format);
-   image->region =
-      intel_region_alloc(intelScreen->bufmgr, tiling, cpp,
-                         width, height, true);
-   if (image->region == NULL) {
-      free(image);
-      return NULL;
-   }
-   
-   intel_setup_image_from_dimensions(image);
+   int fourcc = dri_format_to_fourcc(format);
 
-   return image;
+   return intel_image_create(intelScreen->bufmgr, width, height, fourcc, use);
 }
 
 static GLboolean
 intel_dri_image_query(__DRIimage *image, int attrib, int *value)
 {
+   GLuint format;
+
    switch (attrib) {
    case __DRI_IMAGE_ATTRIB_STRIDE:
       *value = image->region->pitch;
@@ -538,7 +398,8 @@ intel_dri_image_query(__DRIimage *image, int attrib, int *value)
    case __DRI_IMAGE_ATTRIB_NAME:
       return intel_region_flink(image->region, (uint32_t *) value);
    case __DRI_IMAGE_ATTRIB_FORMAT:
-      *value = image->dri_format;
+      format = image->format->planes[image->plane].format;
+      *value = driGLFormatToImageFormat(format);
       return true;
    case __DRI_IMAGE_ATTRIB_WIDTH:
       *value = image->region->width;
@@ -547,9 +408,9 @@ intel_dri_image_query(__DRIimage *image, int attrib, int *value)
       *value = image->region->height;
       return true;
    case __DRI_IMAGE_ATTRIB_COMPONENTS:
-      if (image->planar_format == NULL)
+      if (image->format == NULL)
          return false;
-      *value = image->planar_format->components;
+      *value = image->format->components;
       return true;
    case __DRI_IMAGE_ATTRIB_FD:
       if (drm_intel_bo_gem_export_to_prime(image->region->bo, value) == 0)
@@ -563,40 +424,13 @@ intel_dri_image_query(__DRIimage *image, int attrib, int *value)
 static __DRIimage *
 intel_dri_image_dup(__DRIimage *orig_image, void *loaderPrivate)
 {
-   __DRIimage *image;
-
-   image = calloc(1, sizeof *image);
-   if (image == NULL)
-      return NULL;
-
-   intel_region_reference(&image->region, orig_image->region);
-   if (image->region == NULL) {
-      free(image);
-      return NULL;
-   }
-
-   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->has_depthstencil = orig_image->has_depthstencil;
-   image->data            = loaderPrivate;
-
-   memcpy(image->strides, orig_image->strides, sizeof(image->strides));
-   memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets));
-
-   return image;
+   return intel_image_dup(orig_image);
 }
 
 static GLboolean
 intel_dri_image_validate_usage(__DRIimage *image, unsigned int use)
 {
-   if (use & __DRI_IMAGE_USE_CURSOR) {
-      if (image->region->width != 64 || image->region->height != 64)
-	 return GL_FALSE;
-   }
-
-   return GL_TRUE;
+   return intel_image_validate_usage(image, use);
 }
 
 static __DRIimage *
@@ -606,33 +440,11 @@ intel_dri_image_create_from_names(__DRIscreen *screen,
                                   int *strides, int *offsets,
                                   void *loaderPrivate)
 {
-    struct intel_image_format *f = NULL;
-    __DRIimage *image;
-    int i, index;
-
-    if (screen == NULL || names == NULL || num_names != 1)
-        return NULL;
-
-    f = intel_image_format_lookup(fourcc);
-    if (f == NULL)
-        return NULL;
-
-    image = intel_dri_image_create_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];
-    }
+    struct intel_screen *intelScreen = screen->driverPrivate;
 
-    return image;
+    return intel_image_create_from_names(intelScreen->bufmgr, width, height,
+                                         fourcc, names, num_names,
+                                         strides, offsets);
 }
 
 static __DRIimage *
@@ -642,43 +454,9 @@ intel_dri_image_create_from_fds(__DRIscreen *screen,
                                 int *offsets, void *loaderPrivate)
 {
    struct intel_screen *intelScreen = screen->driverPrivate;
-   struct intel_image_format *f;
-   __DRIimage *image;
-   int i, index;
-
-   if (fds == NULL || num_fds != 1)
-      return NULL;
-
-   f = intel_image_format_lookup(fourcc);
-   if (f == NULL)
-      return NULL;
-
-   if (f->nplanes == 1)
-      image = intel_allocate_image(f->planes[0].dri_format, loaderPrivate);
-   else
-      image = intel_allocate_image(__DRI_IMAGE_FORMAT_NONE, loaderPrivate);
-
-   if (image == NULL)
-      return NULL;
-
-   image->region = intel_region_alloc_for_fd(intelScreen->bufmgr,
-                                             f->planes[0].cpp, width, height, strides[0],
-                                             height * strides[0], fds[0], "image");
-   if (image->region == NULL) {
-      free(image);
-      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];
-   }
-
-   intel_setup_image_from_dimensions(image);
-
-   return image;
+   return intel_image_create_from_fds(intelScreen->bufmgr, width, height,
+                                      fourcc, fds, num_fds, strides, offsets);
 }
 
 static __DRIimage *
@@ -730,52 +508,7 @@ static __DRIimage *
 intel_dri_image_create_from_planar(__DRIimage *parent, int plane,
                                    void *loaderPrivate)
 {
-    int width, height, offset, stride, dri_format, index, cpp;
-    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);
-    if (image == NULL)
-       return NULL;
-
-    if (offset + height * stride > parent->region->bo->size) {
-       _mesa_warning(NULL, "intel_create_sub_image: subimage out of bounds");
-       free(image);
-       return NULL;
-    }
-
-    cpp = _mesa_get_format_bytes(image->format);
-    image->region = intel_region_alloc_subregion(parent->region, cpp,
-                                                 width, height, stride,
-                                                 offset, 0, 0);
-    if (image->region == NULL) {
-        free(image);
-        return NULL;
-    }
-    intel_setup_image_from_dimensions(image);
-
-    intel_region_get_tile_masks(image->region, &mask_x, &mask_y, false);
-    if (offset & mask_x)
-       _mesa_warning(NULL,
-                     "intel_create_sub_image: offset not on tile boundary");
-
-    return image;
+    return intel_image_create_from_plane(parent, plane);
 }
 
 static struct __DRIimageExtensionRec intelImageExtension = {
diff --git a/src/mesa/drivers/dri/i965/intel_tex_image.c b/src/mesa/drivers/dri/i965/intel_tex_image.c
index 9e87003..c2bafd0 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_image.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_image.c
@@ -18,6 +18,7 @@
 #include "intel_mipmap_tree.h"
 #include "intel_buffer_objects.h"
 #include "intel_batchbuffer.h"
+#include "intel_image.h"
 #include "intel_tex.h"
 #include "intel_blit.h"
 #include "intel_fbo.h"
@@ -373,9 +374,10 @@ intel_image_target_texture_2d(struct gl_context *ctx, GLenum target,
       return;
    }
 
-   intel_set_texture_image_region(ctx, texImage, image->region,
-				  target, image->internal_format,
-                                  image->format, image->region->offset,
+   intel_set_texture_image_region(ctx, texImage, image->region, target,
+                                  image->internal_format,
+                                  image->format->planes[image->plane].format,
+                                  image->region->offset,
                                   image->region->width, image->region->height,
                                   image->region->tile_x,
                                   image->region->tile_y);
-- 
1.7.9.5



More information about the mesa-dev mailing list