[Mesa-dev] [PATCH 1/4] gallium/dri: Allow drivers to support DRI Image v7

christopher.halse.rogers at canonical.com christopher.halse.rogers at canonical.com
Sun Apr 21 23:38:04 PDT 2013


From: Christopher James Halse Rogers <raof at ubuntu.com>

This is only exposed by drivers wich support the new PIPE_CAP_PRIME parameter,
for PRIME import/export.
---

This stubs out texture_from_renderbuffer, which I don't care about, but
that looks like it wouldn't be terribly painful to implement if it's a blocker
for the PRIME support, which I do care about.

 src/gallium/drivers/freedreno/freedreno_screen.c   |   1 +
 src/gallium/drivers/i915/i915_screen.c             |   1 +
 src/gallium/drivers/llvmpipe/lp_screen.c           |   2 +
 src/gallium/drivers/nv30/nv30_screen.c             |   1 +
 src/gallium/drivers/nv50/nv50_screen.c             |   2 +
 src/gallium/drivers/nvc0/nvc0_screen.c             |   2 +
 src/gallium/drivers/r300/r300_screen.c             |   1 +
 src/gallium/drivers/r600/r600_pipe.c               |   1 +
 src/gallium/drivers/radeonsi/radeonsi_pipe.c       |   1 +
 src/gallium/drivers/softpipe/sp_screen.c           |   2 +
 src/gallium/drivers/svga/svga_screen.c             |   1 +
 src/gallium/include/pipe/p_defines.h               |   3 +-
 src/gallium/include/state_tracker/drm_driver.h     |   9 +-
 src/gallium/state_trackers/dri/drm/dri2.c          | 120 +++++++++++++++++++--
 .../state_trackers/egl/common/native_helper.c      |   1 +
 src/gallium/state_trackers/egl/x11/native_dri2.c   |   1 +
 16 files changed, 137 insertions(+), 12 deletions(-)

diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index 4a9a54e..db122d3 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -201,6 +201,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
 	case PIPE_CAP_USER_INDEX_BUFFERS:
 	case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
 	case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+	case PIPE_CAP_PRIME:   
 		return 0;
 
 	/* Stream output. */
diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
index dfb76b3..6623dca 100644
--- a/src/gallium/drivers/i915/i915_screen.c
+++ b/src/gallium/drivers/i915/i915_screen.c
@@ -214,6 +214,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
    case PIPE_CAP_TEXTURE_MULTISAMPLE:
    case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
    case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+   case PIPE_CAP_PRIME:
       return 0;
 
    case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
index 667ade1..5ff30f1 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.c
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -228,6 +228,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
       return 0;
+   case PIPE_CAP_PRIME:
+      return 0;
    }
    /* should only get here on unhandled cases */
    debug_printf("Unexpected PIPE_CAP %d query\n", param);
diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c
index 5b3b470..97471a7 100644
--- a/src/gallium/drivers/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nv30/nv30_screen.c
@@ -124,6 +124,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
    case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
    case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+   case PIPE_CAP_PRIME:
       return 0;
    case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index 5aa8ef3..1177c1b 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -188,6 +188,8 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return 0;
    case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
       return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50;
+   case PIPE_CAP_PRIME:
+      return 0;
    default:
       NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
       return 0;
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c
index 8dfd4d1..e3eff40 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c
@@ -178,6 +178,8 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
       return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50;
+   case PIPE_CAP_PRIME:
+      return 0;
    default:
       NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
       return 0;
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index a932be9..000c71d 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -163,6 +163,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
         case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
         case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
         case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+        case PIPE_CAP_PRIME:
             return 0;
 
         /* SWTCL-only features. */
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index 4948ddd..b056041 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -612,6 +612,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 	case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
 	case PIPE_CAP_VERTEX_COLOR_CLAMPED:
 	case PIPE_CAP_USER_VERTEX_BUFFERS:
+	case PIPE_CAP_PRIME:
 		return 0;
 
 	/* Stream output. */
diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
index 4e97f51..1705e3e 100644
--- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c
+++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
@@ -381,6 +381,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
 	case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
 	case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
 	case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
+	case PIPE_CAP_PRIME:
 		return 0;
 
 	/* Stream output. */
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 53ee7d3..0323f82 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -180,6 +180,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_TGSI_TEXCOORD:
    case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
       return 0;
+   case PIPE_CAP_PRIME:
+      return 0;
    }
    /* should only get here on unhandled cases */
    debug_printf("Unexpected PIPE_CAP %d query\n", param);
diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c
index 60e0442..683203b 100644
--- a/src/gallium/drivers/svga/svga_screen.c
+++ b/src/gallium/drivers/svga/svga_screen.c
@@ -265,6 +265,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
    case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
    case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
+   case PIPE_CAP_PRIME:
       return 0;
    case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
       return 1;
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 2d38ce1..7e626dc 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -506,7 +506,8 @@ enum pipe_cap {
    PIPE_CAP_TGSI_TEXCOORD = 79,
    PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER = 80,
    PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81,
-   PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK = 82
+   PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK = 82,
+   PIPE_CAP_PRIME = 83
 };
 
 #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0)
diff --git a/src/gallium/include/state_tracker/drm_driver.h b/src/gallium/include/state_tracker/drm_driver.h
index f9bd222..5b76d87 100644
--- a/src/gallium/include/state_tracker/drm_driver.h
+++ b/src/gallium/include/state_tracker/drm_driver.h
@@ -10,6 +10,8 @@ struct pipe_resource;
 
 #define DRM_API_HANDLE_TYPE_SHARED 0
 #define DRM_API_HANDLE_TYPE_KMS    1
+#define DRM_API_HANDLE_TYPE_FD     2
+
 
 /**
  * For use with pipe_screen::{texture_from_handle|texture_get_handle}.
@@ -17,9 +19,10 @@ struct pipe_resource;
 struct winsys_handle
 {
    /**
-    * Unused for texture_from_handle, always
-    * DRM_API_HANDLE_TYPE_SHARED.  Input to texture_get_handle,
-    * use TEXTURE_USAGE to select handle for kms or ipc.
+    * Input for texture_from_handle, valid values are
+    * DRM_API_HANDLE_TYPE_SHARED or DRM_API_HANDLE_TYPE_FD.
+    * Input to texture_get_handle,
+    * to select handle for kms, flink, or prime.
     */
    unsigned type;
    /**
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c
index f8d311c..7f1dc0e 100644
--- a/src/gallium/state_trackers/dri/drm/dri2.c
+++ b/src/gallium/state_trackers/dri/drm/dri2.c
@@ -231,6 +231,7 @@ dri2_drawable_process_buffers(struct dri_drawable *drawable,
 
       templ.format = format;
       templ.bind = bind;
+      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
       whandle.handle = buf->name;
       whandle.stride = buf->pitch;
 
@@ -452,14 +453,14 @@ dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
 }
 
 static __DRIimage *
-dri2_create_image_from_name(__DRIscreen *_screen,
-                            int width, int height, int format,
-                            int name, int pitch, void *loaderPrivate)
+dri2_create_image_from_winsys(__DRIscreen *_screen,
+                              int width, int height, int format,
+                              struct winsys_handle *whandle, int pitch,
+                              void *loaderPrivate)
 {
    struct dri_screen *screen = dri_screen(_screen);
    __DRIimage *img;
    struct pipe_resource templ;
-   struct winsys_handle whandle;
    unsigned tex_usage;
    enum pipe_format pf;
 
@@ -499,12 +500,10 @@ dri2_create_image_from_name(__DRIscreen *_screen,
    templ.depth0 = 1;
    templ.array_size = 1;
 
-   memset(&whandle, 0, sizeof(whandle));
-   whandle.handle = name;
-   whandle.stride = pitch * util_format_get_blocksize(pf);
+   whandle->stride = pitch * util_format_get_blocksize(pf);
 
    img->texture = screen->base.screen->resource_from_handle(screen->base.screen,
-         &templ, &whandle);
+         &templ, whandle);
    if (!img->texture) {
       FREE(img);
       return NULL;
@@ -519,6 +518,39 @@ dri2_create_image_from_name(__DRIscreen *_screen,
 }
 
 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;
+
+   memset(&whandle, 0, sizeof(whandle));
+   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+   whandle.handle = name;
+
+   return dri2_create_image_from_winsys(_screen, width, height, format,
+                                        &whandle, pitch, loaderPrivate);
+}
+
+static __DRIimage *
+dri2_create_image_from_fd(__DRIscreen *_screen,
+                          int width, int height, int format,
+                          int fd, int pitch, void *loaderPrivate)
+{
+   struct winsys_handle whandle;
+
+   if (fd < 0)
+      return NULL;
+
+   memset(&whandle, 0, sizeof(whandle));
+   whandle.type = DRM_API_HANDLE_TYPE_FD;
+   whandle.handle = (unsigned)fd;
+
+   return dri2_create_image_from_winsys(_screen, width, height, format,
+                                        &whandle, pitch, loaderPrivate);
+}
+
+static __DRIimage *
 dri2_create_image_from_renderbuffer(__DRIcontext *context,
 				    int renderbuffer, void *loaderPrivate)
 {
@@ -626,6 +658,11 @@ dri2_query_image(__DRIimage *image, int attrib, int *value)
          image->texture, &whandle);
       *value = whandle.handle;
       return GL_TRUE;
+   case __DRI_IMAGE_ATTRIB_FD:
+      whandle.type= DRM_API_HANDLE_TYPE_FD;
+      image->texture->screen->resource_get_handle(image->texture->screen,
+         image->texture, &whandle);
+      *value = whandle.handle;
    case __DRI_IMAGE_ATTRIB_FORMAT:
       *value = image->dri_format;
       return GL_TRUE;
@@ -749,6 +786,67 @@ dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
    return img;
 }
 
+static __DRIimage *
+dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
+                         int depth, int level, unsigned *error,
+                         void *loaderPrivate)
+{
+   /* Bad parameter seems like the least-incorrect error */
+   *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
+   return NULL;
+}
+
+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 format, stride, dri_components;
+
+   if (num_fds != 1)
+      return NULL;
+   if (offsets[0] != 0)
+      return NULL;
+
+   switch(fourcc) {
+   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;
+   default:
+      return NULL;
+   }
+
+   /* Strides are in bytes not pixels. */
+   stride = strides[0] /4;
+
+   img = dri2_create_image_from_fd(screen, width, height, format,
+                                   fds[0], stride, loaderPrivate);
+   if (img == NULL)
+      return NULL;
+
+   img->dri_components = dri_components;
+   return img;
+}
+
+
 static void
 dri2_destroy_image(__DRIimage *img)
 {
@@ -813,6 +911,12 @@ dri2_init_screen(__DRIscreen * sPriv)
       screen->default_throttle_frames = throttle_ret->val.val_int;
    }
 
+   if (pscreen->get_param(pscreen, PIPE_CAP_PRIME)) {
+      dri2ImageExtension.base.version = 7;
+      dri2ImageExtension.createImageFromTexture = dri2_create_from_texture;
+      dri2ImageExtension.createImageFromFds = dri2_from_fds;
+   }
+
    sPriv->extensions = dri_screen_extensions;
 
    /* dri_init_screen_helper checks pscreen for us */
diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c
index 99259b8..eda6668 100644
--- a/src/gallium/state_trackers/egl/common/native_helper.c
+++ b/src/gallium/state_trackers/egl/common/native_helper.c
@@ -428,6 +428,7 @@ drm_display_import_native_buffer(struct native_display *ndpy,
 
          memset(&wsh, 0, sizeof(wsh));
          wsh.handle = nbuf->u.drm.name;
+         wsh.type = DRM_API_HANDLE_TYPE_SHARED;
          wsh.stride = nbuf->u.drm.stride;
 
          res = screen->resource_from_handle(screen, &nbuf->u.drm.templ, &wsh);
diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c
index fc18a4c..673e3d7 100644
--- a/src/gallium/state_trackers/egl/x11/native_dri2.c
+++ b/src/gallium/state_trackers/egl/x11/native_dri2.c
@@ -177,6 +177,7 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
       }
 
       memset(&whandle, 0, sizeof(whandle));
+      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
       whandle.stride = xbuf->pitch;
       whandle.handle = xbuf->name;
       dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle(
-- 
1.8.1.2



More information about the mesa-dev mailing list