[Mesa-dev] [PATCH 1/4] st/dri: move image extension into the common file

gurchetansingh at chromium.org gurchetansingh at chromium.org
Fri Jun 9 00:26:36 UTC 2017


From: Gurchetan Singh <gurchetansingh at chromium.org>

This image extension is is needed by the Android studio emulator
when using the host's GLES implementation.

This patch moves the extension code from dri2.c to dri_extensions.c.
Since some functions in this extension are initialized at runtime by
dri2.c, we need to expose them in dri_extensions.h.
---
 src/gallium/state_trackers/dri/dri2.c           | 756 -----------------------
 src/gallium/state_trackers/dri/dri_extensions.c | 770 +++++++++++++++++++++++-
 src/gallium/state_trackers/dri/dri_extensions.h |  17 +
 3 files changed, 784 insertions(+), 759 deletions(-)

diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c
index 625678f257..b68d93bdaa 100644
--- a/src/gallium/state_trackers/dri/dri2.c
+++ b/src/gallium/state_trackers/dri/dri2.c
@@ -35,7 +35,6 @@
 #include "util/u_inlines.h"
 #include "util/u_format.h"
 #include "util/u_debug.h"
-#include "state_tracker/drm_driver.h"
 #include "state_tracker/st_cb_bufferobjects.h"
 #include "state_tracker/st_cb_fbo.h"
 #include "state_tracker/st_cb_texture.h"
@@ -52,126 +51,6 @@
 #include "dri_query_renderer.h"
 #include "dri2_buffer.h"
 
-static int convert_fourcc(int format, int *dri_components_p)
-{
-   int dri_components;
-   switch(format) {
-   case __DRI_IMAGE_FOURCC_RGB565:
-      format = __DRI_IMAGE_FORMAT_RGB565;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
-      break;
-   case __DRI_IMAGE_FOURCC_ARGB8888:
-      format = __DRI_IMAGE_FORMAT_ARGB8888;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
-      break;
-   case __DRI_IMAGE_FOURCC_XRGB8888:
-      format = __DRI_IMAGE_FORMAT_XRGB8888;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
-      break;
-   case __DRI_IMAGE_FOURCC_ABGR8888:
-      format = __DRI_IMAGE_FORMAT_ABGR8888;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
-      break;
-   case __DRI_IMAGE_FOURCC_XBGR8888:
-      format = __DRI_IMAGE_FORMAT_XBGR8888;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
-      break;
-   case __DRI_IMAGE_FOURCC_R8:
-      format = __DRI_IMAGE_FORMAT_R8;
-      dri_components = __DRI_IMAGE_COMPONENTS_R;
-      break;
-   case __DRI_IMAGE_FOURCC_GR88:
-      format = __DRI_IMAGE_FORMAT_GR88;
-      dri_components = __DRI_IMAGE_COMPONENTS_RG;
-      break;
-   /*
-    * For multi-planar YUV formats, we return the format of the first
-    * plane only.  Since there is only one caller which supports multi-
-    * planar YUV it gets to figure out the remaining planes on it's
-    * own.
-    */
-   case __DRI_IMAGE_FOURCC_YUV420:
-   case __DRI_IMAGE_FOURCC_YVU420:
-      format = __DRI_IMAGE_FORMAT_R8;
-      dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V;
-      break;
-   case __DRI_IMAGE_FOURCC_NV12:
-      format = __DRI_IMAGE_FORMAT_R8;
-      dri_components = __DRI_IMAGE_COMPONENTS_Y_UV;
-      break;
-   default:
-      return -1;
-   }
-   *dri_components_p = dri_components;
-   return format;
-}
-
-/* NOTE this probably isn't going to do the right thing for YUV images
- * (but I think the same can be said for intel_query_image()).  I think
- * only needed for exporting dmabuf's, so I think I won't loose much
- * sleep over it.
- */
-static int convert_to_fourcc(int format)
-{
-   switch(format) {
-   case __DRI_IMAGE_FORMAT_RGB565:
-      format = __DRI_IMAGE_FOURCC_RGB565;
-      break;
-   case __DRI_IMAGE_FORMAT_ARGB8888:
-      format = __DRI_IMAGE_FOURCC_ARGB8888;
-      break;
-   case __DRI_IMAGE_FORMAT_XRGB8888:
-      format = __DRI_IMAGE_FOURCC_XRGB8888;
-      break;
-   case __DRI_IMAGE_FORMAT_ABGR8888:
-      format = __DRI_IMAGE_FOURCC_ABGR8888;
-      break;
-   case __DRI_IMAGE_FORMAT_XBGR8888:
-      format = __DRI_IMAGE_FOURCC_XBGR8888;
-      break;
-   case __DRI_IMAGE_FORMAT_R8:
-      format = __DRI_IMAGE_FOURCC_R8;
-      break;
-   case __DRI_IMAGE_FORMAT_GR88:
-      format = __DRI_IMAGE_FOURCC_GR88;
-      break;
-   default:
-      return -1;
-   }
-   return format;
-}
-
-static enum pipe_format dri2_format_to_pipe_format (int format)
-{
-   enum pipe_format pf;
-
-   switch (format) {
-   case __DRI_IMAGE_FORMAT_RGB565:
-      pf = PIPE_FORMAT_B5G6R5_UNORM;
-      break;
-   case __DRI_IMAGE_FORMAT_XRGB8888:
-      pf = PIPE_FORMAT_BGRX8888_UNORM;
-      break;
-   case __DRI_IMAGE_FORMAT_ARGB8888:
-      pf = PIPE_FORMAT_BGRA8888_UNORM;
-      break;
-   case __DRI_IMAGE_FORMAT_ABGR8888:
-      pf = PIPE_FORMAT_RGBA8888_UNORM;
-      break;
-   case __DRI_IMAGE_FORMAT_R8:
-      pf = PIPE_FORMAT_R8_UNORM;
-      break;
-   case __DRI_IMAGE_FORMAT_GR88:
-      pf = PIPE_FORMAT_RG88_UNORM;
-      break;
-   default:
-      pf = PIPE_FORMAT_NONE;
-      break;
-   }
-
-   return pf;
-}
-
 /**
  * DRI2 flush extension.
  */
@@ -780,641 +659,6 @@ dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
    return img;
 }
 
-static __DRIimage *
-dri2_create_image_from_winsys(__DRIscreen *_screen,
-                              int width, int height, int format,
-                              int num_handles, struct winsys_handle *whandle,
-                              void *loaderPrivate)
-{
-   struct dri_screen *screen = dri_screen(_screen);
-   struct pipe_screen *pscreen = screen->base.screen;
-   __DRIimage *img;
-   struct pipe_resource templ;
-   unsigned tex_usage;
-   enum pipe_format pf;
-   int i;
-
-   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
-
-   pf = dri2_format_to_pipe_format (format);
-   if (pf == PIPE_FORMAT_NONE)
-      return NULL;
-
-   img = CALLOC_STRUCT(__DRIimageRec);
-   if (!img)
-      return NULL;
-
-   memset(&templ, 0, sizeof(templ));
-   templ.bind = tex_usage;
-   templ.target = screen->target;
-   templ.last_level = 0;
-   templ.depth0 = 1;
-   templ.array_size = 1;
-
-   for (i = num_handles - 1; i >= 0; i--) {
-      struct pipe_resource *tex;
-
-      /* TODO: something a lot less ugly */
-      switch (i) {
-      case 0:
-         templ.width0 = width;
-         templ.height0 = height;
-         templ.format = pf;
-         break;
-      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,
-            &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE);
-      if (!tex) {
-         pipe_resource_reference(&img->texture, NULL);
-         FREE(img);
-         return NULL;
-      }
-
-      tex->next = img->texture;
-      img->texture = tex;
-   }
-
-   img->level = 0;
-   img->layer = 0;
-   img->dri_format = format;
-   img->use = 0;
-   img->loader_private = loaderPrivate;
-
-   return img;
-}
-
-static __DRIimage *
-dri2_create_image_from_name(__DRIscreen *_screen,
-                            int width, int height, int format,
-                            int name, int pitch, void *loaderPrivate)
-{
-   struct winsys_handle whandle;
-   enum pipe_format pf;
-
-   memset(&whandle, 0, sizeof(whandle));
-   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
-   whandle.handle = name;
-
-   pf = dri2_format_to_pipe_format (format);
-   if (pf == PIPE_FORMAT_NONE)
-      return NULL;
-
-   whandle.stride = pitch * util_format_get_blocksize(pf);
-
-   return dri2_create_image_from_winsys(_screen, width, height, format,
-                                        1, &whandle, loaderPrivate);
-}
-
-static __DRIimage *
-dri2_create_image_from_fd(__DRIscreen *_screen,
-                          int width, int height, int fourcc,
-                          int *fds, int num_fds, int *strides,
-                          int *offsets, unsigned *error,
-                          int *dri_components, void *loaderPrivate)
-{
-   struct winsys_handle whandles[3];
-   int format;
-   __DRIimage *img = NULL;
-   unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
-   int expected_num_fds, i;
-
-   switch (fourcc) {
-   case __DRI_IMAGE_FOURCC_YUV420:
-   case __DRI_IMAGE_FOURCC_YVU420:
-      expected_num_fds = 3;
-      break;
-   case __DRI_IMAGE_FOURCC_NV12:
-      expected_num_fds = 2;
-      break;
-   default:
-      expected_num_fds = 1;
-      break;
-   }
-
-   if (num_fds != expected_num_fds) {
-      err = __DRI_IMAGE_ERROR_BAD_MATCH;
-      goto exit;
-   }
-
-   format = convert_fourcc(fourcc, dri_components);
-   if (format == -1) {
-      err = __DRI_IMAGE_ERROR_BAD_MATCH;
-      goto exit;
-   }
-
-   memset(whandles, 0, sizeof(whandles));
-
-   for (i = 0; i < num_fds; i++) {
-      if (fds[i] < 0) {
-         err = __DRI_IMAGE_ERROR_BAD_ALLOC;
-         goto exit;
-      }
-
-      whandles[i].type = DRM_API_HANDLE_TYPE_FD;
-      whandles[i].handle = (unsigned)fds[i];
-      whandles[i].stride = (unsigned)strides[i];
-      whandles[i].offset = (unsigned)offsets[i];
-   }
-
-   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;
-   }
-
-   img = dri2_create_image_from_winsys(_screen, width, height, format,
-                                       num_fds, whandles, loaderPrivate);
-   if(img == NULL)
-      err = __DRI_IMAGE_ERROR_BAD_ALLOC;
-
-exit:
-   if (error)
-      *error = err;
-
-   return img;
-}
-
-static __DRIimage *
-dri2_create_image_from_renderbuffer(__DRIcontext *context,
-				    int renderbuffer, void *loaderPrivate)
-{
-   struct dri_context *ctx = dri_context(context);
-
-   if (!ctx->st->get_resource_for_egl_image)
-      return NULL;
-
-   /* TODO */
-   return NULL;
-}
-
-static __DRIimage *
-dri2_create_image(__DRIscreen *_screen,
-                   int width, int height, int format,
-                   unsigned int use, void *loaderPrivate)
-{
-   struct dri_screen *screen = dri_screen(_screen);
-   __DRIimage *img;
-   struct pipe_resource templ;
-   unsigned tex_usage;
-   enum pipe_format pf;
-
-   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
-   if (use & __DRI_IMAGE_USE_SCANOUT)
-      tex_usage |= PIPE_BIND_SCANOUT;
-   if (use & __DRI_IMAGE_USE_SHARE)
-      tex_usage |= PIPE_BIND_SHARED;
-   if (use & __DRI_IMAGE_USE_LINEAR)
-      tex_usage |= PIPE_BIND_LINEAR;
-   if (use & __DRI_IMAGE_USE_CURSOR) {
-      if (width != 64 || height != 64)
-         return NULL;
-      tex_usage |= PIPE_BIND_CURSOR;
-   }
-
-   pf = dri2_format_to_pipe_format (format);
-   if (pf == PIPE_FORMAT_NONE)
-      return NULL;
-
-   img = CALLOC_STRUCT(__DRIimageRec);
-   if (!img)
-      return NULL;
-
-   memset(&templ, 0, sizeof(templ));
-   templ.bind = tex_usage;
-   templ.format = pf;
-   templ.target = PIPE_TEXTURE_2D;
-   templ.last_level = 0;
-   templ.width0 = width;
-   templ.height0 = height;
-   templ.depth0 = 1;
-   templ.array_size = 1;
-
-   img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
-   if (!img->texture) {
-      FREE(img);
-      return NULL;
-   }
-
-   img->level = 0;
-   img->layer = 0;
-   img->dri_format = format;
-   img->dri_components = 0;
-   img->use = use;
-
-   img->loader_private = loaderPrivate;
-   return img;
-}
-
-static GLboolean
-dri2_query_image(__DRIimage *image, int attrib, int *value)
-{
-   struct winsys_handle whandle;
-   unsigned usage;
-
-   if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
-      usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
-   else
-      usage = PIPE_HANDLE_USAGE_READ_WRITE;
-
-   memset(&whandle, 0, sizeof(whandle));
-
-   switch (attrib) {
-   case __DRI_IMAGE_ATTRIB_STRIDE:
-      whandle.type = DRM_API_HANDLE_TYPE_KMS;
-      image->texture->screen->resource_get_handle(image->texture->screen,
-            NULL, image->texture, &whandle, usage);
-      *value = whandle.stride;
-      return GL_TRUE;
-   case __DRI_IMAGE_ATTRIB_HANDLE:
-      whandle.type = DRM_API_HANDLE_TYPE_KMS;
-      image->texture->screen->resource_get_handle(image->texture->screen,
-         NULL, image->texture, &whandle, usage);
-      *value = whandle.handle;
-      return GL_TRUE;
-   case __DRI_IMAGE_ATTRIB_NAME:
-      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
-      image->texture->screen->resource_get_handle(image->texture->screen,
-         NULL, image->texture, &whandle, usage);
-      *value = whandle.handle;
-      return GL_TRUE;
-   case __DRI_IMAGE_ATTRIB_FD:
-      whandle.type= DRM_API_HANDLE_TYPE_FD;
-      if (!image->texture->screen->resource_get_handle(image->texture->screen,
-            NULL, image->texture, &whandle, usage))
-         return GL_FALSE;
-
-      *value = whandle.handle;
-      return GL_TRUE;
-   case __DRI_IMAGE_ATTRIB_FORMAT:
-      *value = image->dri_format;
-      return GL_TRUE;
-   case __DRI_IMAGE_ATTRIB_WIDTH:
-      *value = image->texture->width0;
-      return GL_TRUE;
-   case __DRI_IMAGE_ATTRIB_HEIGHT:
-      *value = image->texture->height0;
-      return GL_TRUE;
-   case __DRI_IMAGE_ATTRIB_COMPONENTS:
-      if (image->dri_components == 0)
-         return GL_FALSE;
-      *value = image->dri_components;
-      return GL_TRUE;
-   case __DRI_IMAGE_ATTRIB_FOURCC:
-      *value = convert_to_fourcc(image->dri_format);
-      return GL_TRUE;
-   case __DRI_IMAGE_ATTRIB_NUM_PLANES:
-      *value = 1;
-      return GL_TRUE;
-   default:
-      return GL_FALSE;
-   }
-}
-
-static __DRIimage *
-dri2_dup_image(__DRIimage *image, void *loaderPrivate)
-{
-   __DRIimage *img;
-
-   img = CALLOC_STRUCT(__DRIimageRec);
-   if (!img)
-      return NULL;
-
-   img->texture = NULL;
-   pipe_resource_reference(&img->texture, image->texture);
-   img->level = image->level;
-   img->layer = image->layer;
-   img->dri_format = image->dri_format;
-   /* This should be 0 for sub images, but dup is also used for base images. */
-   img->dri_components = image->dri_components;
-   img->loader_private = loaderPrivate;
-
-   return img;
-}
-
-static GLboolean
-dri2_validate_usage(__DRIimage *image, unsigned int use)
-{
-   /*
-    * Gallium drivers are bad at adding usages to the resources
-    * once opened again in another process, which is the main use
-    * case for this, so we have to lie.
-    */
-   if (image != NULL)
-      return GL_TRUE;
-   else
-      return GL_FALSE;
-}
-
-static __DRIimage *
-dri2_from_names(__DRIscreen *screen, int width, int height, int format,
-                int *names, int num_names, int *strides, int *offsets,
-                void *loaderPrivate)
-{
-   __DRIimage *img;
-   int dri_components;
-   struct winsys_handle whandle;
-
-   if (num_names != 1)
-      return NULL;
-
-   format = convert_fourcc(format, &dri_components);
-   if (format == -1)
-      return NULL;
-
-   memset(&whandle, 0, sizeof(whandle));
-   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
-   whandle.handle = names[0];
-   whandle.stride = strides[0];
-   whandle.offset = offsets[0];
-
-   img = dri2_create_image_from_winsys(screen, width, height, format,
-                                       1, &whandle, loaderPrivate);
-   if (img == NULL)
-      return NULL;
-
-   img->dri_components = dri_components;
-   return img;
-}
-
-static __DRIimage *
-dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
-{
-   __DRIimage *img;
-
-   if (plane != 0)
-      return NULL;
-
-   if (image->dri_components == 0)
-      return NULL;
-
-   img = dri2_dup_image(image, loaderPrivate);
-   if (img == NULL)
-      return NULL;
-
-   if (img->texture->screen->resource_changed)
-      img->texture->screen->resource_changed(img->texture->screen,
-                                             img->texture);
-
-   /* set this to 0 for sub images. */
-   img->dri_components = 0;
-   return img;
-}
-
-static __DRIimage *
-dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
-                         int depth, int level, unsigned *error,
-                         void *loaderPrivate)
-{
-   __DRIimage *img;
-   struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
-   struct gl_texture_object *obj;
-   struct pipe_resource *tex;
-   GLuint face = 0;
-
-   obj = _mesa_lookup_texture(ctx, texture);
-   if (!obj || obj->Target != target) {
-      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
-      return NULL;
-   }
-
-   tex = st_get_texobj_resource(obj);
-   if (!tex) {
-      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
-      return NULL;
-   }
-
-   if (target == GL_TEXTURE_CUBE_MAP)
-      face = depth;
-
-   _mesa_test_texobj_completeness(ctx, obj);
-   if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
-      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
-      return NULL;
-   }
-
-   if (level < obj->BaseLevel || level > obj->_MaxLevel) {
-      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
-      return NULL;
-   }
-
-   if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
-      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
-      return NULL;
-   }
-
-   img = CALLOC_STRUCT(__DRIimageRec);
-   if (!img) {
-      *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
-      return NULL;
-   }
-
-   img->level = level;
-   img->layer = depth;
-   img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
-
-   img->loader_private = loaderPrivate;
-
-   if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
-      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
-      free(img);
-      return NULL;
-   }
-
-   pipe_resource_reference(&img->texture, tex);
-
-   *error = __DRI_IMAGE_ERROR_SUCCESS;
-   return img;
-}
-
-static __DRIimage *
-dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
-              int *fds, int num_fds, int *strides, int *offsets,
-              void *loaderPrivate)
-{
-   __DRIimage *img;
-   int dri_components;
-
-   img = dri2_create_image_from_fd(screen, width, height, fourcc,
-                                   fds, num_fds, strides, offsets, NULL,
-                                   &dri_components, loaderPrivate);
-   if (img == NULL)
-      return NULL;
-
-   img->dri_components = dri_components;
-   return img;
-}
-
-static __DRIimage *
-dri2_from_dma_bufs(__DRIscreen *screen,
-                   int width, int height, int fourcc,
-                   int *fds, int num_fds,
-                   int *strides, int *offsets,
-                   enum __DRIYUVColorSpace yuv_color_space,
-                   enum __DRISampleRange sample_range,
-                   enum __DRIChromaSiting horizontal_siting,
-                   enum __DRIChromaSiting vertical_siting,
-                   unsigned *error,
-                   void *loaderPrivate)
-{
-   __DRIimage *img;
-   int dri_components;
-
-   img = dri2_create_image_from_fd(screen, width, height, fourcc,
-                                   fds, num_fds, strides, offsets, error,
-                                   &dri_components, loaderPrivate);
-   if (img == NULL)
-      return NULL;
-
-   img->yuv_color_space = yuv_color_space;
-   img->sample_range = sample_range;
-   img->horizontal_siting = horizontal_siting;
-   img->vertical_siting = vertical_siting;
-   img->dri_components = dri_components;
-
-   *error = __DRI_IMAGE_ERROR_SUCCESS;
-   return img;
-}
-
-static void
-dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
-                int dstx0, int dsty0, int dstwidth, int dstheight,
-                int srcx0, int srcy0, int srcwidth, int srcheight,
-                int flush_flag)
-{
-   struct dri_context *ctx = dri_context(context);
-   struct pipe_context *pipe = ctx->st->pipe;
-   struct pipe_screen *screen;
-   struct pipe_fence_handle *fence;
-   struct pipe_blit_info blit;
-
-   if (!dst || !src)
-      return;
-
-   memset(&blit, 0, sizeof(blit));
-   blit.dst.resource = dst->texture;
-   blit.dst.box.x = dstx0;
-   blit.dst.box.y = dsty0;
-   blit.dst.box.width = dstwidth;
-   blit.dst.box.height = dstheight;
-   blit.dst.box.depth = 1;
-   blit.dst.format = dst->texture->format;
-   blit.src.resource = src->texture;
-   blit.src.box.x = srcx0;
-   blit.src.box.y = srcy0;
-   blit.src.box.width = srcwidth;
-   blit.src.box.height = srcheight;
-   blit.src.box.depth = 1;
-   blit.src.format = src->texture->format;
-   blit.mask = PIPE_MASK_RGBA;
-   blit.filter = PIPE_TEX_FILTER_NEAREST;
-
-   pipe->blit(pipe, &blit);
-
-   if (flush_flag == __BLIT_FLAG_FLUSH) {
-      pipe->flush_resource(pipe, dst->texture);
-      ctx->st->flush(ctx->st, 0, NULL);
-   } else if (flush_flag == __BLIT_FLAG_FINISH) {
-      screen = dri_screen(ctx->sPriv)->base.screen;
-      pipe->flush_resource(pipe, dst->texture);
-      ctx->st->flush(ctx->st, 0, &fence);
-      (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
-      screen->fence_reference(screen, &fence, NULL);
-   }
-}
-
-static void *
-dri2_map_image(__DRIcontext *context, __DRIimage *image,
-                int x0, int y0, int width, int height,
-                unsigned int flags, int *stride, void **data)
-{
-   struct dri_context *ctx = dri_context(context);
-   struct pipe_context *pipe = ctx->st->pipe;
-   enum pipe_transfer_usage pipe_access = 0;
-   struct pipe_transfer *trans;
-   void *map;
-
-   if (!image || !data || *data)
-      return NULL;
-
-   if (flags & __DRI_IMAGE_TRANSFER_READ)
-         pipe_access |= PIPE_TRANSFER_READ;
-   if (flags & __DRI_IMAGE_TRANSFER_WRITE)
-         pipe_access |= PIPE_TRANSFER_WRITE;
-
-   map = pipe_transfer_map(pipe, image->texture,
-                           0, 0, pipe_access, x0, y0, width, height,
-                           &trans);
-   if (map) {
-      *data = trans;
-      *stride = trans->stride;
-   }
-
-   return map;
-}
-
-static void
-dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
-{
-   struct dri_context *ctx = dri_context(context);
-   struct pipe_context *pipe = ctx->st->pipe;
-
-   pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
-}
-
-static void
-dri2_destroy_image(__DRIimage *img)
-{
-   pipe_resource_reference(&img->texture, NULL);
-   FREE(img);
-}
-
-static int
-dri2_get_capabilities(__DRIscreen *_screen)
-{
-   struct dri_screen *screen = dri_screen(_screen);
-
-   return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
-}
-
-/* The extension is modified during runtime if DRI_PRIME is detected */
-static __DRIimageExtension dri2ImageExtension = {
-    .base = { __DRI_IMAGE, 12 },
-
-    .createImageFromName          = dri2_create_image_from_name,
-    .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
-    .destroyImage                 = dri2_destroy_image,
-    .createImage                  = dri2_create_image,
-    .queryImage                   = dri2_query_image,
-    .dupImage                     = dri2_dup_image,
-    .validateUsage                = dri2_validate_usage,
-    .createImageFromNames         = dri2_from_names,
-    .fromPlanar                   = dri2_from_planar,
-    .createImageFromTexture       = dri2_create_from_texture,
-    .createImageFromFds           = NULL,
-    .createImageFromDmaBufs       = NULL,
-    .blitImage                    = dri2_blit_image,
-    .getCapabilities              = dri2_get_capabilities,
-    .mapImage                     = dri2_map_image,
-    .unmapImage                   = dri2_unmap_image,
-};
-
 static const __DRIrobustnessExtension dri2Robustness = {
    .base = { __DRI2_ROBUSTNESS, 1 }
 };
diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c
index b3a2cb78f9..c3daca1762 100644
--- a/src/gallium/state_trackers/dri/dri_extensions.c
+++ b/src/gallium/state_trackers/dri/dri_extensions.c
@@ -21,10 +21,139 @@
  */
 
 #include <dlfcn.h>
-#include "dri_context.h"
-#include "dri_screen.h"
-#include "pipe/p_screen.h"
 #include "util/u_memory.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
+#include "state_tracker/st_texture.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/drm_driver.h"
+#include "pipe/p_screen.h"
+#include "main/texobj.h"
+
+#include "dri_screen.h"
+#include "dri_context.h"
+#include "dri_extensions.h"
+
+static int convert_fourcc(int format, int *dri_components_p)
+{
+   int dri_components;
+   switch(format) {
+   case __DRI_IMAGE_FOURCC_RGB565:
+      format = __DRI_IMAGE_FORMAT_RGB565;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
+      break;
+   case __DRI_IMAGE_FOURCC_ARGB8888:
+      format = __DRI_IMAGE_FORMAT_ARGB8888;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
+      break;
+   case __DRI_IMAGE_FOURCC_XRGB8888:
+      format = __DRI_IMAGE_FORMAT_XRGB8888;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
+      break;
+   case __DRI_IMAGE_FOURCC_ABGR8888:
+      format = __DRI_IMAGE_FORMAT_ABGR8888;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
+      break;
+   case __DRI_IMAGE_FOURCC_XBGR8888:
+      format = __DRI_IMAGE_FORMAT_XBGR8888;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
+      break;
+   case __DRI_IMAGE_FOURCC_R8:
+      format = __DRI_IMAGE_FORMAT_R8;
+      dri_components = __DRI_IMAGE_COMPONENTS_R;
+      break;
+   case __DRI_IMAGE_FOURCC_GR88:
+      format = __DRI_IMAGE_FORMAT_GR88;
+      dri_components = __DRI_IMAGE_COMPONENTS_RG;
+      break;
+   /*
+    * For multi-planar YUV formats, we return the format of the first
+    * plane only.  Since there is only one caller which supports multi-
+    * planar YUV it gets to figure out the remaining planes on it's
+    * own.
+    */
+   case __DRI_IMAGE_FOURCC_YUV420:
+   case __DRI_IMAGE_FOURCC_YVU420:
+      format = __DRI_IMAGE_FORMAT_R8;
+      dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V;
+      break;
+   case __DRI_IMAGE_FOURCC_NV12:
+      format = __DRI_IMAGE_FORMAT_R8;
+      dri_components = __DRI_IMAGE_COMPONENTS_Y_UV;
+      break;
+   default:
+      return -1;
+   }
+   *dri_components_p = dri_components;
+   return format;
+}
+
+/* NOTE this probably isn't going to do the right thing for YUV images
+ * (but I think the same can be said for intel_query_image()).  I think
+ * only needed for exporting dmabuf's, so I think I won't loose much
+ * sleep over it.
+ */
+static int convert_to_fourcc(int format)
+{
+   switch(format) {
+   case __DRI_IMAGE_FORMAT_RGB565:
+      format = __DRI_IMAGE_FOURCC_RGB565;
+      break;
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      format = __DRI_IMAGE_FOURCC_ARGB8888;
+      break;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      format = __DRI_IMAGE_FOURCC_XRGB8888;
+      break;
+   case __DRI_IMAGE_FORMAT_ABGR8888:
+      format = __DRI_IMAGE_FOURCC_ABGR8888;
+      break;
+   case __DRI_IMAGE_FORMAT_XBGR8888:
+      format = __DRI_IMAGE_FOURCC_XBGR8888;
+      break;
+   case __DRI_IMAGE_FORMAT_R8:
+      format = __DRI_IMAGE_FOURCC_R8;
+      break;
+   case __DRI_IMAGE_FORMAT_GR88:
+      format = __DRI_IMAGE_FOURCC_GR88;
+      break;
+   default:
+      return -1;
+   }
+   return format;
+}
+
+static enum pipe_format dri2_format_to_pipe_format (int format)
+{
+   enum pipe_format pf;
+
+   switch (format) {
+   case __DRI_IMAGE_FORMAT_RGB565:
+      pf = PIPE_FORMAT_B5G6R5_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      pf = PIPE_FORMAT_BGRX8888_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      pf = PIPE_FORMAT_BGRA8888_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_ABGR8888:
+      pf = PIPE_FORMAT_RGBA8888_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_R8:
+      pf = PIPE_FORMAT_R8_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_GR88:
+      pf = PIPE_FORMAT_RG88_UNORM;
+      break;
+   default:
+      pf = PIPE_FORMAT_NONE;
+      break;
+   }
+
+   return pf;
+}
+
 
 static bool
 dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen)
@@ -227,4 +356,639 @@ const __DRI2fenceExtension dri2FenceExtension = {
    .get_fence_fd = dri2_get_fence_fd,
 };
 
+static __DRIimage *
+dri2_create_image_from_winsys(__DRIscreen *_screen,
+                              int width, int height, int format,
+                              int num_handles, struct winsys_handle *whandle,
+                              void *loaderPrivate)
+{
+   struct dri_screen *screen = dri_screen(_screen);
+   struct pipe_screen *pscreen = screen->base.screen;
+   __DRIimage *img;
+   struct pipe_resource templ;
+   unsigned tex_usage;
+   enum pipe_format pf;
+   int i;
+
+   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+
+   pf = dri2_format_to_pipe_format (format);
+   if (pf == PIPE_FORMAT_NONE)
+      return NULL;
+
+   img = CALLOC_STRUCT(__DRIimageRec);
+   if (!img)
+      return NULL;
+
+   memset(&templ, 0, sizeof(templ));
+   templ.bind = tex_usage;
+   templ.target = screen->target;
+   templ.last_level = 0;
+   templ.depth0 = 1;
+   templ.array_size = 1;
+
+   for (i = num_handles - 1; i >= 0; i--) {
+      struct pipe_resource *tex;
+
+      /* TODO: something a lot less ugly */
+      switch (i) {
+      case 0:
+         templ.width0 = width;
+         templ.height0 = height;
+         templ.format = pf;
+         break;
+      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,
+            &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE);
+      if (!tex) {
+         pipe_resource_reference(&img->texture, NULL);
+         FREE(img);
+         return NULL;
+      }
+
+      tex->next = img->texture;
+      img->texture = tex;
+   }
+
+   img->level = 0;
+   img->layer = 0;
+   img->dri_format = format;
+   img->use = 0;
+   img->loader_private = loaderPrivate;
+
+   return img;
+}
+
+static __DRIimage *
+dri2_create_image_from_name(__DRIscreen *_screen,
+                            int width, int height, int format,
+                            int name, int pitch, void *loaderPrivate)
+{
+   struct winsys_handle whandle;
+   enum pipe_format pf;
+
+   memset(&whandle, 0, sizeof(whandle));
+   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+   whandle.handle = name;
+
+   pf = dri2_format_to_pipe_format (format);
+   if (pf == PIPE_FORMAT_NONE)
+      return NULL;
+
+   whandle.stride = pitch * util_format_get_blocksize(pf);
+
+   return dri2_create_image_from_winsys(_screen, width, height, format,
+                                        1, &whandle, loaderPrivate);
+}
+
+static __DRIimage *
+dri2_create_image_from_fd(__DRIscreen *_screen,
+                          int width, int height, int fourcc,
+                          int *fds, int num_fds, int *strides,
+                          int *offsets, unsigned *error,
+                          int *dri_components, void *loaderPrivate)
+{
+   struct winsys_handle whandles[3];
+   int format;
+   __DRIimage *img = NULL;
+   unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
+   int expected_num_fds, i;
+
+   switch (fourcc) {
+   case __DRI_IMAGE_FOURCC_YUV420:
+   case __DRI_IMAGE_FOURCC_YVU420:
+      expected_num_fds = 3;
+      break;
+   case __DRI_IMAGE_FOURCC_NV12:
+      expected_num_fds = 2;
+      break;
+   default:
+      expected_num_fds = 1;
+      break;
+   }
+
+   if (num_fds != expected_num_fds) {
+      err = __DRI_IMAGE_ERROR_BAD_MATCH;
+      goto exit;
+   }
+
+   format = convert_fourcc(fourcc, dri_components);
+   if (format == -1) {
+      err = __DRI_IMAGE_ERROR_BAD_MATCH;
+      goto exit;
+   }
+
+   memset(whandles, 0, sizeof(whandles));
+
+   for (i = 0; i < num_fds; i++) {
+      if (fds[i] < 0) {
+         err = __DRI_IMAGE_ERROR_BAD_ALLOC;
+         goto exit;
+      }
+
+      whandles[i].type = DRM_API_HANDLE_TYPE_FD;
+      whandles[i].handle = (unsigned)fds[i];
+      whandles[i].stride = (unsigned)strides[i];
+      whandles[i].offset = (unsigned)offsets[i];
+   }
+
+   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;
+   }
+
+   img = dri2_create_image_from_winsys(_screen, width, height, format,
+                                       num_fds, whandles, loaderPrivate);
+   if(img == NULL)
+      err = __DRI_IMAGE_ERROR_BAD_ALLOC;
+
+exit:
+   if (error)
+      *error = err;
+
+   return img;
+}
+
+static __DRIimage *
+dri2_create_image_from_renderbuffer(__DRIcontext *context,
+				    int renderbuffer, void *loaderPrivate)
+{
+   struct dri_context *ctx = dri_context(context);
+
+   if (!ctx->st->get_resource_for_egl_image)
+      return NULL;
+
+   /* TODO */
+   return NULL;
+}
+
+static __DRIimage *
+dri2_create_image(__DRIscreen *_screen,
+                   int width, int height, int format,
+                   unsigned int use, void *loaderPrivate)
+{
+   struct dri_screen *screen = dri_screen(_screen);
+   __DRIimage *img;
+   struct pipe_resource templ;
+   unsigned tex_usage;
+   enum pipe_format pf;
+
+   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+   if (use & __DRI_IMAGE_USE_SCANOUT)
+      tex_usage |= PIPE_BIND_SCANOUT;
+   if (use & __DRI_IMAGE_USE_SHARE)
+      tex_usage |= PIPE_BIND_SHARED;
+   if (use & __DRI_IMAGE_USE_LINEAR)
+      tex_usage |= PIPE_BIND_LINEAR;
+   if (use & __DRI_IMAGE_USE_CURSOR) {
+      if (width != 64 || height != 64)
+         return NULL;
+      tex_usage |= PIPE_BIND_CURSOR;
+   }
+
+   pf = dri2_format_to_pipe_format (format);
+   if (pf == PIPE_FORMAT_NONE)
+      return NULL;
+
+   img = CALLOC_STRUCT(__DRIimageRec);
+   if (!img)
+      return NULL;
+
+   memset(&templ, 0, sizeof(templ));
+   templ.bind = tex_usage;
+   templ.format = pf;
+   templ.target = PIPE_TEXTURE_2D;
+   templ.last_level = 0;
+   templ.width0 = width;
+   templ.height0 = height;
+   templ.depth0 = 1;
+   templ.array_size = 1;
+
+   img->texture = screen->base.screen->resource_create(screen->base.screen, &templ);
+   if (!img->texture) {
+      FREE(img);
+      return NULL;
+   }
+
+   img->level = 0;
+   img->layer = 0;
+   img->dri_format = format;
+   img->dri_components = 0;
+   img->use = use;
+
+   img->loader_private = loaderPrivate;
+   return img;
+}
+
+static GLboolean
+dri2_query_image(__DRIimage *image, int attrib, int *value)
+{
+   struct winsys_handle whandle;
+   unsigned usage;
+
+   if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
+      usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
+   else
+      usage = PIPE_HANDLE_USAGE_READ_WRITE;
+
+   memset(&whandle, 0, sizeof(whandle));
+
+   switch (attrib) {
+   case __DRI_IMAGE_ATTRIB_STRIDE:
+      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      image->texture->screen->resource_get_handle(image->texture->screen,
+            NULL, image->texture, &whandle, usage);
+      *value = whandle.stride;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_HANDLE:
+      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      image->texture->screen->resource_get_handle(image->texture->screen,
+         NULL, image->texture, &whandle, usage);
+      *value = whandle.handle;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_NAME:
+      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+      image->texture->screen->resource_get_handle(image->texture->screen,
+         NULL, image->texture, &whandle, usage);
+      *value = whandle.handle;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_FD:
+      whandle.type= DRM_API_HANDLE_TYPE_FD;
+      if (!image->texture->screen->resource_get_handle(image->texture->screen,
+            NULL, image->texture, &whandle, usage))
+         return GL_FALSE;
+
+      *value = whandle.handle;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_FORMAT:
+      *value = image->dri_format;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_WIDTH:
+      *value = image->texture->width0;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_HEIGHT:
+      *value = image->texture->height0;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_COMPONENTS:
+      if (image->dri_components == 0)
+         return GL_FALSE;
+      *value = image->dri_components;
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_FOURCC:
+      *value = convert_to_fourcc(image->dri_format);
+      return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_NUM_PLANES:
+      *value = 1;
+      return GL_TRUE;
+   default:
+      return GL_FALSE;
+   }
+}
+
+static __DRIimage *
+dri2_dup_image(__DRIimage *image, void *loaderPrivate)
+{
+   __DRIimage *img;
+
+   img = CALLOC_STRUCT(__DRIimageRec);
+   if (!img)
+      return NULL;
+
+   img->texture = NULL;
+   pipe_resource_reference(&img->texture, image->texture);
+   img->level = image->level;
+   img->layer = image->layer;
+   img->dri_format = image->dri_format;
+   /* This should be 0 for sub images, but dup is also used for base images. */
+   img->dri_components = image->dri_components;
+   img->loader_private = loaderPrivate;
+
+   return img;
+}
+
+static GLboolean
+dri2_validate_usage(__DRIimage *image, unsigned int use)
+{
+   /*
+    * Gallium drivers are bad at adding usages to the resources
+    * once opened again in another process, which is the main use
+    * case for this, so we have to lie.
+    */
+   if (image != NULL)
+      return GL_TRUE;
+   else
+      return GL_FALSE;
+}
+
+static __DRIimage *
+dri2_from_names(__DRIscreen *screen, int width, int height, int format,
+                int *names, int num_names, int *strides, int *offsets,
+                void *loaderPrivate)
+{
+   __DRIimage *img;
+   int dri_components;
+   struct winsys_handle whandle;
+
+   if (num_names != 1)
+      return NULL;
+
+   format = convert_fourcc(format, &dri_components);
+   if (format == -1)
+      return NULL;
+
+   memset(&whandle, 0, sizeof(whandle));
+   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+   whandle.handle = names[0];
+   whandle.stride = strides[0];
+   whandle.offset = offsets[0];
+
+   img = dri2_create_image_from_winsys(screen, width, height, format,
+                                       1, &whandle, loaderPrivate);
+   if (img == NULL)
+      return NULL;
+
+   img->dri_components = dri_components;
+   return img;
+}
+
+static __DRIimage *
+dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
+{
+   __DRIimage *img;
+
+   if (plane != 0)
+      return NULL;
+
+   if (image->dri_components == 0)
+      return NULL;
+
+   img = dri2_dup_image(image, loaderPrivate);
+   if (img == NULL)
+      return NULL;
+
+   if (img->texture->screen->resource_changed)
+      img->texture->screen->resource_changed(img->texture->screen,
+                                             img->texture);
+
+   /* set this to 0 for sub images. */
+   img->dri_components = 0;
+   return img;
+}
+
+static __DRIimage *
+dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
+                         int depth, int level, unsigned *error,
+                         void *loaderPrivate)
+{
+   __DRIimage *img;
+   struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
+   struct gl_texture_object *obj;
+   struct pipe_resource *tex;
+   GLuint face = 0;
+
+   obj = _mesa_lookup_texture(ctx, texture);
+   if (!obj || obj->Target != target) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      return NULL;
+   }
+
+   tex = st_get_texobj_resource(obj);
+   if (!tex) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      return NULL;
+   }
+
+   if (target == GL_TEXTURE_CUBE_MAP)
+      face = depth;
+
+   _mesa_test_texobj_completeness(ctx, obj);
+   if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      return NULL;
+   }
+
+   if (level < obj->BaseLevel || level > obj->_MaxLevel) {
+      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+      return NULL;
+   }
+
+   if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
+      *error = __DRI_IMAGE_ERROR_BAD_MATCH;
+      return NULL;
+   }
+
+   img = CALLOC_STRUCT(__DRIimageRec);
+   if (!img) {
+      *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
+      return NULL;
+   }
+
+   img->level = level;
+   img->layer = depth;
+   img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
+
+   img->loader_private = loaderPrivate;
+
+   if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
+      *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+      free(img);
+      return NULL;
+   }
+
+   pipe_resource_reference(&img->texture, tex);
+
+   *error = __DRI_IMAGE_ERROR_SUCCESS;
+   return img;
+}
+
+__DRIimage *
+dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
+              int *fds, int num_fds, int *strides, int *offsets,
+              void *loaderPrivate)
+{
+   __DRIimage *img;
+   int dri_components;
+
+   img = dri2_create_image_from_fd(screen, width, height, fourcc,
+                                   fds, num_fds, strides, offsets, NULL,
+                                   &dri_components, loaderPrivate);
+   if (img == NULL)
+      return NULL;
+
+   img->dri_components = dri_components;
+   return img;
+}
+
+__DRIimage *
+dri2_from_dma_bufs(__DRIscreen *screen,
+                   int width, int height, int fourcc,
+                   int *fds, int num_fds,
+                   int *strides, int *offsets,
+                   enum __DRIYUVColorSpace yuv_color_space,
+                   enum __DRISampleRange sample_range,
+                   enum __DRIChromaSiting horizontal_siting,
+                   enum __DRIChromaSiting vertical_siting,
+                   unsigned *error,
+                   void *loaderPrivate)
+{
+   __DRIimage *img;
+   int dri_components;
+
+   img = dri2_create_image_from_fd(screen, width, height, fourcc,
+                                   fds, num_fds, strides, offsets, error,
+                                   &dri_components, loaderPrivate);
+   if (img == NULL)
+      return NULL;
+
+   img->yuv_color_space = yuv_color_space;
+   img->sample_range = sample_range;
+   img->horizontal_siting = horizontal_siting;
+   img->vertical_siting = vertical_siting;
+   img->dri_components = dri_components;
+
+   *error = __DRI_IMAGE_ERROR_SUCCESS;
+   return img;
+}
+
+static void
+dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
+                int dstx0, int dsty0, int dstwidth, int dstheight,
+                int srcx0, int srcy0, int srcwidth, int srcheight,
+                int flush_flag)
+{
+   struct dri_context *ctx = dri_context(context);
+   struct pipe_context *pipe = ctx->st->pipe;
+   struct pipe_screen *screen;
+   struct pipe_fence_handle *fence;
+   struct pipe_blit_info blit;
+
+   if (!dst || !src)
+      return;
+
+   memset(&blit, 0, sizeof(blit));
+   blit.dst.resource = dst->texture;
+   blit.dst.box.x = dstx0;
+   blit.dst.box.y = dsty0;
+   blit.dst.box.width = dstwidth;
+   blit.dst.box.height = dstheight;
+   blit.dst.box.depth = 1;
+   blit.dst.format = dst->texture->format;
+   blit.src.resource = src->texture;
+   blit.src.box.x = srcx0;
+   blit.src.box.y = srcy0;
+   blit.src.box.width = srcwidth;
+   blit.src.box.height = srcheight;
+   blit.src.box.depth = 1;
+   blit.src.format = src->texture->format;
+   blit.mask = PIPE_MASK_RGBA;
+   blit.filter = PIPE_TEX_FILTER_NEAREST;
+
+   pipe->blit(pipe, &blit);
+
+   if (flush_flag == __BLIT_FLAG_FLUSH) {
+      pipe->flush_resource(pipe, dst->texture);
+      ctx->st->flush(ctx->st, 0, NULL);
+   } else if (flush_flag == __BLIT_FLAG_FINISH) {
+      screen = dri_screen(ctx->sPriv)->base.screen;
+      pipe->flush_resource(pipe, dst->texture);
+      ctx->st->flush(ctx->st, 0, &fence);
+      (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
+      screen->fence_reference(screen, &fence, NULL);
+   }
+}
+
+static void *
+dri2_map_image(__DRIcontext *context, __DRIimage *image,
+                int x0, int y0, int width, int height,
+                unsigned int flags, int *stride, void **data)
+{
+   struct dri_context *ctx = dri_context(context);
+   struct pipe_context *pipe = ctx->st->pipe;
+   enum pipe_transfer_usage pipe_access = 0;
+   struct pipe_transfer *trans;
+   void *map;
+
+   if (!image || !data || *data)
+      return NULL;
+
+   if (flags & __DRI_IMAGE_TRANSFER_READ)
+         pipe_access |= PIPE_TRANSFER_READ;
+   if (flags & __DRI_IMAGE_TRANSFER_WRITE)
+         pipe_access |= PIPE_TRANSFER_WRITE;
+
+   map = pipe_transfer_map(pipe, image->texture,
+                           0, 0, pipe_access, x0, y0, width, height,
+                           &trans);
+   if (map) {
+      *data = trans;
+      *stride = trans->stride;
+   }
+
+   return map;
+}
+
+static void
+dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
+{
+   struct dri_context *ctx = dri_context(context);
+   struct pipe_context *pipe = ctx->st->pipe;
+
+   pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
+}
+
+static void
+dri2_destroy_image(__DRIimage *img)
+{
+   pipe_resource_reference(&img->texture, NULL);
+   FREE(img);
+}
+
+static int
+dri2_get_capabilities(__DRIscreen *_screen)
+{
+   struct dri_screen *screen = dri_screen(_screen);
+
+   return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
+}
+
+/* The extension is modified during runtime if DRI_PRIME is detected */
+__DRIimageExtension dri2ImageExtension = {
+    .base = { __DRI_IMAGE, 12 },
+
+    .createImageFromName          = dri2_create_image_from_name,
+    .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
+    .destroyImage                 = dri2_destroy_image,
+    .createImage                  = dri2_create_image,
+    .queryImage                   = dri2_query_image,
+    .dupImage                     = dri2_dup_image,
+    .validateUsage                = dri2_validate_usage,
+    .createImageFromNames         = dri2_from_names,
+    .fromPlanar                   = dri2_from_planar,
+    .createImageFromTexture       = dri2_create_from_texture,
+    .createImageFromFds           = NULL,
+    .createImageFromDmaBufs       = NULL,
+    .blitImage                    = dri2_blit_image,
+    .getCapabilities              = dri2_get_capabilities,
+    .mapImage                     = dri2_map_image,
+    .unmapImage                   = dri2_unmap_image,
+};
+
 /* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_extensions.h b/src/gallium/state_trackers/dri/dri_extensions.h
index 89b01cd3ed..6c19ccac75 100644
--- a/src/gallium/state_trackers/dri/dri_extensions.h
+++ b/src/gallium/state_trackers/dri/dri_extensions.h
@@ -24,7 +24,24 @@
 #define DRI_EXTENSIONS_H
 
 extern const __DRI2fenceExtension dri2FenceExtension;
+extern __DRIimageExtension dri2ImageExtension;
 
+__DRIimage *
+dri2_from_dma_bufs(__DRIscreen *screen,
+                   int width, int height, int fourcc,
+                   int *fds, int num_fds,
+                   int *strides, int *offsets,
+                   enum __DRIYUVColorSpace yuv_color_space,
+                   enum __DRISampleRange sample_range,
+                   enum __DRIChromaSiting horizontal_siting,
+                   enum __DRIChromaSiting vertical_siting,
+                   unsigned *error,
+                   void *loaderPrivate);
+
+__DRIimage *
+dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
+              int *fds, int num_fds, int *strides, int *offsets,
+              void *loaderPrivate);
 #endif
 
 /* vim: set sw=3 ts=8 sts=3 expandtab: */
-- 
2.12.2



More information about the mesa-dev mailing list