gallium/dri: Support DRI Image extension version 7
[mesa.git] / src / gallium / state_trackers / dri / drm / dri2.c
index 59c072235cbe1afbdede799bac8f6cffe24a382e..8ff77b38507a372bd9ca3d5d9898c5bb62efdadb 100644 (file)
@@ -530,14 +530,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;
 
@@ -577,13 +577,10 @@ dri2_create_image_from_name(__DRIscreen *_screen,
    templ.depth0 = 1;
    templ.array_size = 1;
 
-   memset(&whandle, 0, sizeof(whandle));
-   whandle.handle = name;
-   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
-   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;
@@ -597,6 +594,39 @@ dri2_create_image_from_name(__DRIscreen *_screen,
    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;
+
+   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)
@@ -708,6 +738,12 @@ 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;
+      return GL_TRUE;
    case __DRI_IMAGE_ATTRIB_FORMAT:
       *value = image->dri_format;
       return GL_TRUE;
@@ -897,6 +933,56 @@ dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
    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 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)
 {
@@ -943,6 +1029,7 @@ dri2_init_screen(__DRIscreen * sPriv)
    struct dri_screen *screen;
    struct pipe_screen *pscreen;
    const struct drm_conf_ret *throttle_ret = NULL;
+   const struct drm_conf_ret *dmabuf_ret = NULL;
 
    screen = CALLOC_STRUCT(dri_screen);
    if (!screen)
@@ -954,14 +1041,21 @@ dri2_init_screen(__DRIscreen * sPriv)
    sPriv->driverPrivate = (void *)screen;
 
    pscreen = driver_descriptor.create_screen(screen->fd);
-   if (driver_descriptor.configuration)
+   if (driver_descriptor.configuration) {
       throttle_ret = driver_descriptor.configuration(DRM_CONF_THROTTLE);
+      dmabuf_ret = driver_descriptor.configuration(DRM_CONF_SHARE_FD);
+   }
 
    if (throttle_ret && throttle_ret->val.val_int != -1) {
       screen->throttling_enabled = TRUE;
       screen->default_throttle_frames = throttle_ret->val.val_int;
    }
 
+   if (dmabuf_ret && dmabuf_ret->val.val_bool) {
+      dri2ImageExtension.base.version = 7;
+      dri2ImageExtension.createImageFromFds = dri2_from_fds;
+   }
+
    sPriv->extensions = dri_screen_extensions;
 
    /* dri_init_screen_helper checks pscreen for us */