st/dri: allow both render and sampler compatible dma-buf formats
[mesa.git] / src / gallium / state_trackers / dri / dri2.c
index 1e8bb48104465f89d1b71252b2f5bf913574ce19..5c903983cac29ce51e7b7fd80221c4c9d1c4bb8e 100644 (file)
@@ -29,7 +29,6 @@
  */
 
 #include <xf86drm.h>
-#include <fcntl.h>
 #include "GL/mesa_glinterop.h"
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
 #include "main/bufferobj.h"
 #include "main/texobj.h"
 
+#include "dri_util.h"
+
 #include "dri_helpers.h"
 #include "dri_drawable.h"
 #include "dri_query_renderer.h"
-#include "dri2_buffer.h"
 
 #ifndef DRM_FORMAT_MOD_INVALID
 #define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
 #endif
 
+struct dri2_buffer
+{
+   __DRIbuffer base;
+   struct pipe_resource *resource;
+};
+
+static inline struct dri2_buffer *
+dri2_buffer(__DRIbuffer * driBufferPriv)
+{
+   return (struct dri2_buffer *) driBufferPriv;
+}
+
 static const int fourcc_formats[] = {
+   __DRI_IMAGE_FOURCC_ARGB2101010,
+   __DRI_IMAGE_FOURCC_XRGB2101010,
+   __DRI_IMAGE_FOURCC_ABGR2101010,
+   __DRI_IMAGE_FOURCC_XBGR2101010,
    __DRI_IMAGE_FOURCC_ARGB8888,
    __DRI_IMAGE_FOURCC_ABGR8888,
    __DRI_IMAGE_FOURCC_SARGB8888,
@@ -85,6 +101,10 @@ static int convert_fourcc(int format, int *dri_components_p)
 {
    int dri_components;
    switch(format) {
+   case __DRI_IMAGE_FOURCC_ARGB1555:
+      format = __DRI_IMAGE_FORMAT_ARGB1555;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
+      break;
    case __DRI_IMAGE_FOURCC_RGB565:
       format = __DRI_IMAGE_FORMAT_RGB565;
       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
@@ -105,6 +125,22 @@ static int convert_fourcc(int format, int *dri_components_p)
       format = __DRI_IMAGE_FORMAT_XBGR8888;
       dri_components = __DRI_IMAGE_COMPONENTS_RGB;
       break;
+   case __DRI_IMAGE_FOURCC_ARGB2101010:
+      format = __DRI_IMAGE_FORMAT_ARGB2101010;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
+      break;
+   case __DRI_IMAGE_FOURCC_XRGB2101010:
+      format = __DRI_IMAGE_FORMAT_XRGB2101010;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
+      break;
+   case __DRI_IMAGE_FOURCC_ABGR2101010:
+      format = __DRI_IMAGE_FORMAT_ABGR2101010;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
+      break;
+   case __DRI_IMAGE_FOURCC_XBGR2101010:
+      format = __DRI_IMAGE_FORMAT_XBGR2101010;
+      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
+      break;
    case __DRI_IMAGE_FOURCC_R8:
       format = __DRI_IMAGE_FORMAT_R8;
       dri_components = __DRI_IMAGE_COMPONENTS_R;
@@ -113,6 +149,18 @@ static int convert_fourcc(int format, int *dri_components_p)
       format = __DRI_IMAGE_FORMAT_GR88;
       dri_components = __DRI_IMAGE_COMPONENTS_RG;
       break;
+   case __DRI_IMAGE_FOURCC_R16:
+      format = __DRI_IMAGE_FORMAT_R16;
+      dri_components = __DRI_IMAGE_COMPONENTS_R;
+      break;
+   case __DRI_IMAGE_FOURCC_GR1616:
+      format = __DRI_IMAGE_FORMAT_GR1616;
+      dri_components = __DRI_IMAGE_COMPONENTS_RG;
+      break;
+   case __DRI_IMAGE_FOURCC_YUYV:
+      format = __DRI_IMAGE_FORMAT_YUYV;
+      dri_components = __DRI_IMAGE_COMPONENTS_Y_XUXV;
+      break;
    /*
     * For multi-planar YUV formats, we return the format of the first
     * plane only.  Since there is only one caller which supports multi-
@@ -143,6 +191,9 @@ static int convert_fourcc(int format, int *dri_components_p)
 static int convert_to_fourcc(int format)
 {
    switch(format) {
+   case __DRI_IMAGE_FORMAT_ARGB1555:
+      format = __DRI_IMAGE_FOURCC_ARGB1555;
+      break;
    case __DRI_IMAGE_FORMAT_RGB565:
       format = __DRI_IMAGE_FOURCC_RGB565;
       break;
@@ -158,6 +209,18 @@ static int convert_to_fourcc(int format)
    case __DRI_IMAGE_FORMAT_XBGR8888:
       format = __DRI_IMAGE_FOURCC_XBGR8888;
       break;
+   case __DRI_IMAGE_FORMAT_ARGB2101010:
+      format = __DRI_IMAGE_FOURCC_ARGB2101010;
+      break;
+   case __DRI_IMAGE_FORMAT_XRGB2101010:
+      format = __DRI_IMAGE_FOURCC_XRGB2101010;
+      break;
+   case __DRI_IMAGE_FORMAT_ABGR2101010:
+      format = __DRI_IMAGE_FOURCC_ABGR2101010;
+      break;
+   case __DRI_IMAGE_FORMAT_XBGR2101010:
+      format = __DRI_IMAGE_FOURCC_XBGR2101010;
+      break;
    case __DRI_IMAGE_FORMAT_R8:
       format = __DRI_IMAGE_FOURCC_R8;
       break;
@@ -175,6 +238,9 @@ static enum pipe_format dri2_format_to_pipe_format (int format)
    enum pipe_format pf;
 
    switch (format) {
+   case __DRI_IMAGE_FORMAT_ARGB1555:
+      pf = PIPE_FORMAT_B5G5R5A1_UNORM;
+      break;
    case __DRI_IMAGE_FORMAT_RGB565:
       pf = PIPE_FORMAT_B5G6R5_UNORM;
       break;
@@ -190,12 +256,33 @@ static enum pipe_format dri2_format_to_pipe_format (int format)
    case __DRI_IMAGE_FORMAT_ABGR8888:
       pf = PIPE_FORMAT_RGBA8888_UNORM;
       break;
+   case __DRI_IMAGE_FORMAT_XRGB2101010:
+      pf = PIPE_FORMAT_B10G10R10X2_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_ARGB2101010:
+      pf = PIPE_FORMAT_B10G10R10A2_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_XBGR2101010:
+      pf = PIPE_FORMAT_R10G10B10X2_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_ABGR2101010:
+      pf = PIPE_FORMAT_R10G10B10A2_UNORM;
+      break;
    case __DRI_IMAGE_FORMAT_R8:
       pf = PIPE_FORMAT_R8_UNORM;
       break;
    case __DRI_IMAGE_FORMAT_GR88:
       pf = PIPE_FORMAT_RG88_UNORM;
       break;
+   case __DRI_IMAGE_FORMAT_R16:
+      pf = PIPE_FORMAT_R16_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_GR1616:
+      pf = PIPE_FORMAT_R16G16_UNORM;
+      break;
+   case __DRI_IMAGE_FORMAT_YUYV:
+      pf = PIPE_FORMAT_YUYV;
+      break;
    default:
       pf = PIPE_FORMAT_NONE;
       break;
@@ -239,6 +326,18 @@ static enum pipe_format fourcc_to_pipe_format(int fourcc)
    case __DRI_IMAGE_FOURCC_XBGR8888:
       pf = PIPE_FORMAT_RGBX8888_UNORM;
       break;
+   case __DRI_IMAGE_FOURCC_ARGB2101010:
+      pf = PIPE_FORMAT_B10G10R10A2_UNORM;
+      break;
+   case __DRI_IMAGE_FOURCC_XRGB2101010:
+      pf = PIPE_FORMAT_B10G10R10X2_UNORM;
+      break;
+   case __DRI_IMAGE_FOURCC_ABGR2101010:
+      pf = PIPE_FORMAT_R10G10B10A2_UNORM;
+      break;
+   case __DRI_IMAGE_FOURCC_XBGR2101010:
+      pf = PIPE_FORMAT_R10G10B10X2_UNORM;
+      break;
 
    case __DRI_IMAGE_FOURCC_NV12:
       pf = PIPE_FORMAT_NV12;
@@ -356,10 +455,16 @@ dri2_drawable_get_buffers(struct dri_drawable *drawable,
        * may occur as the stvis->color_format.
        */
       switch(format) {
+      case PIPE_FORMAT_B10G10R10A2_UNORM:
+      case PIPE_FORMAT_R10G10B10A2_UNORM:
       case PIPE_FORMAT_BGRA8888_UNORM:
       case PIPE_FORMAT_RGBA8888_UNORM:
         depth = 32;
         break;
+      case PIPE_FORMAT_R10G10B10X2_UNORM:
+      case PIPE_FORMAT_B10G10R10X2_UNORM:
+         depth = 30;
+         break;
       case PIPE_FORMAT_BGRX8888_UNORM:
       case PIPE_FORMAT_RGBX8888_UNORM:
         depth = 24;
@@ -428,6 +533,9 @@ dri_image_drawable_get_buffers(struct dri_drawable *drawable,
       }
 
       switch (pf) {
+      case PIPE_FORMAT_B5G5R5A1_UNORM:
+         image_format = __DRI_IMAGE_FORMAT_ARGB1555;
+         break;
       case PIPE_FORMAT_B5G6R5_UNORM:
          image_format = __DRI_IMAGE_FORMAT_RGB565;
          break;
@@ -443,6 +551,18 @@ dri_image_drawable_get_buffers(struct dri_drawable *drawable,
       case PIPE_FORMAT_RGBA8888_UNORM:
          image_format = __DRI_IMAGE_FORMAT_ABGR8888;
          break;
+      case PIPE_FORMAT_B10G10R10X2_UNORM:
+         image_format = __DRI_IMAGE_FORMAT_XRGB2101010;
+         break;
+      case PIPE_FORMAT_B10G10R10A2_UNORM:
+         image_format = __DRI_IMAGE_FORMAT_ARGB2101010;
+         break;
+      case PIPE_FORMAT_R10G10B10X2_UNORM:
+         image_format = __DRI_IMAGE_FORMAT_XBGR2101010;
+         break;
+      case PIPE_FORMAT_R10G10B10A2_UNORM:
+         image_format = __DRI_IMAGE_FORMAT_ABGR2101010;
+         break;
       default:
          image_format = __DRI_IMAGE_FORMAT_NONE;
          break;
@@ -489,6 +609,9 @@ dri2_allocate_buffer(__DRIscreen *sPriv,
       case 32:
          pf = PIPE_FORMAT_BGRA8888_UNORM;
          break;
+      case 30:
+         pf = PIPE_FORMAT_B10G10R10X2_UNORM;
+         break;
       case 24:
          pf = PIPE_FORMAT_BGRX8888_UNORM;
          break;
@@ -522,13 +645,13 @@ dri2_allocate_buffer(__DRIscreen *sPriv,
 
    memset(&whandle, 0, sizeof(whandle));
    if (screen->can_share_buffer)
-      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+      whandle.type = WINSYS_HANDLE_TYPE_SHARED;
    else
-      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      whandle.type = WINSYS_HANDLE_TYPE_KMS;
 
    screen->base.screen->resource_get_handle(screen->base.screen, NULL,
          buffer->resource, &whandle,
-         PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
+         PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
 
    buffer->base.attachment = attachment;
    buffer->base.name = whandle.handle;
@@ -708,14 +831,15 @@ dri2_allocate_textures(struct dri_context *ctx,
          whandle.handle = buf->name;
          whandle.stride = buf->pitch;
          whandle.offset = 0;
+         whandle.modifier = DRM_FORMAT_MOD_INVALID;
          if (screen->can_share_buffer)
-            whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+            whandle.type = WINSYS_HANDLE_TYPE_SHARED;
          else
-            whandle.type = DRM_API_HANDLE_TYPE_KMS;
+            whandle.type = WINSYS_HANDLE_TYPE_KMS;
          drawable->textures[statt] =
             screen->base.screen->resource_from_handle(screen->base.screen,
                   &templ, &whandle,
-                  PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ);
+                  PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
          assert(drawable->textures[statt]);
       }
    }
@@ -733,6 +857,7 @@ dri2_allocate_textures(struct dri_context *ctx,
             templ.bind = drawable->textures[statt]->bind &
                          ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);
             templ.nr_samples = drawable->stvis.samples;
+            templ.nr_storage_samples = drawable->stvis.samples;
 
             /* Try to reuse the resource.
              * (the other resource parameters should be constant)
@@ -784,10 +909,12 @@ dri2_allocate_textures(struct dri_context *ctx,
 
          if (drawable->stvis.samples > 1) {
             templ.nr_samples = drawable->stvis.samples;
+            templ.nr_storage_samples = drawable->stvis.samples;
             zsbuf = &drawable->msaa_textures[statt];
          }
          else {
             templ.nr_samples = 0;
+            templ.nr_storage_samples = 0;
             zsbuf = &drawable->textures[statt];
          }
 
@@ -892,16 +1019,21 @@ dri2_create_image_from_winsys(__DRIscreen *_screen,
    struct pipe_screen *pscreen = screen->base.screen;
    __DRIimage *img;
    struct pipe_resource templ;
-   unsigned tex_usage;
+   unsigned tex_usage = 0;
    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;
 
+   if (pscreen->is_format_supported(pscreen, pf, screen->target, 0, 0,
+                                    PIPE_BIND_RENDER_TARGET))
+      tex_usage |= PIPE_BIND_RENDER_TARGET;
+   if (pscreen->is_format_supported(pscreen, pf, screen->target, 0, 0,
+                                    PIPE_BIND_SAMPLER_VIEW))
+      tex_usage |= PIPE_BIND_SAMPLER_VIEW;
+
    img = CALLOC_STRUCT(__DRIimageRec);
    if (!img)
       return NULL;
@@ -940,7 +1072,7 @@ dri2_create_image_from_winsys(__DRIscreen *_screen,
       }
 
       tex = pscreen->resource_from_handle(pscreen,
-            &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE);
+            &templ, &whandle[i], PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
       if (!tex) {
          pipe_resource_reference(&img->texture, NULL);
          FREE(img);
@@ -969,7 +1101,7 @@ dri2_create_image_from_name(__DRIscreen *_screen,
    enum pipe_format pf;
 
    memset(&whandle, 0, sizeof(whandle));
-   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+   whandle.type = WINSYS_HANDLE_TYPE_SHARED;
    whandle.handle = name;
    whandle.modifier = DRM_FORMAT_MOD_INVALID;
 
@@ -1028,7 +1160,7 @@ dri2_create_image_from_fd(__DRIscreen *_screen,
          goto exit;
       }
 
-      whandles[i].type = DRM_API_HANDLE_TYPE_FD;
+      whandles[i].type = WINSYS_HANDLE_TYPE_FD;
       whandles[i].handle = (unsigned)fds[i];
       whandles[i].stride = (unsigned)strides[i];
       whandles[i].offset = (unsigned)offsets[i];
@@ -1160,43 +1292,43 @@ dri2_query_image(__DRIimage *image, int attrib, int *value)
    unsigned usage;
 
    if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
-      usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
+      usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
    else
-      usage = PIPE_HANDLE_USAGE_READ_WRITE;
+      usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
 
    memset(&whandle, 0, sizeof(whandle));
 
    switch (attrib) {
    case __DRI_IMAGE_ATTRIB_STRIDE:
-      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      whandle.type = WINSYS_HANDLE_TYPE_KMS;
       if (!image->texture->screen->resource_get_handle(image->texture->screen,
             NULL, image->texture, &whandle, usage))
          return GL_FALSE;
       *value = whandle.stride;
       return GL_TRUE;
    case __DRI_IMAGE_ATTRIB_OFFSET:
-      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      whandle.type = WINSYS_HANDLE_TYPE_KMS;
       if (!image->texture->screen->resource_get_handle(image->texture->screen,
             NULL, image->texture, &whandle, usage))
          return GL_FALSE;
       *value = whandle.offset;
       return GL_TRUE;
    case __DRI_IMAGE_ATTRIB_HANDLE:
-      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      whandle.type = WINSYS_HANDLE_TYPE_KMS;
       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_NAME:
-      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+      whandle.type = WINSYS_HANDLE_TYPE_SHARED;
       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_FD:
-      whandle.type= DRM_API_HANDLE_TYPE_FD;
+      whandle.type= WINSYS_HANDLE_TYPE_FD;
       if (!image->texture->screen->resource_get_handle(image->texture->screen,
             NULL, image->texture, &whandle, usage))
          return GL_FALSE;
@@ -1219,12 +1351,12 @@ dri2_query_image(__DRIimage *image, int attrib, int *value)
       return GL_TRUE;
    case __DRI_IMAGE_ATTRIB_FOURCC:
       *value = convert_to_fourcc(image->dri_format);
-      return GL_TRUE;
+      return *value != -1;
    case __DRI_IMAGE_ATTRIB_NUM_PLANES:
       *value = 1;
       return GL_TRUE;
    case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
-      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      whandle.type = WINSYS_HANDLE_TYPE_KMS;
       whandle.modifier = DRM_FORMAT_MOD_INVALID;
       if (!image->texture->screen->resource_get_handle(image->texture->screen,
             NULL, image->texture, &whandle, usage))
@@ -1234,7 +1366,7 @@ dri2_query_image(__DRIimage *image, int attrib, int *value)
       *value = (whandle.modifier >> 32) & 0xffffffff;
       return GL_TRUE;
    case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
-      whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      whandle.type = WINSYS_HANDLE_TYPE_KMS;
       whandle.modifier = DRM_FORMAT_MOD_INVALID;
       if (!image->texture->screen->resource_get_handle(image->texture->screen,
             NULL, image->texture, &whandle, usage))
@@ -1272,15 +1404,29 @@ dri2_dup_image(__DRIimage *image, void *loaderPrivate)
 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 || !image->texture)
+      return false;
+
+   struct pipe_screen *screen = image->texture->screen;
+   if (!screen->check_resource_capability)
+      return true;
+
+   /* We don't want to check these:
+    *   __DRI_IMAGE_USE_SHARE (all images are shareable)
+    *   __DRI_IMAGE_USE_BACKBUFFER (all images support this)
     */
-   if (image != NULL)
-      return GL_TRUE;
-   else
-      return GL_FALSE;
+   unsigned bind = 0;
+   if (use & __DRI_IMAGE_USE_SCANOUT)
+      bind |= PIPE_BIND_SCANOUT;
+   if (use & __DRI_IMAGE_USE_LINEAR)
+      bind |= PIPE_BIND_LINEAR;
+   if (use & __DRI_IMAGE_USE_CURSOR)
+      bind |= PIPE_BIND_CURSOR;
+
+   if (!bind)
+      return true;
+
+   return screen->check_resource_capability(screen, image->texture, bind);
 }
 
 static __DRIimage *
@@ -1300,7 +1446,7 @@ dri2_from_names(__DRIscreen *screen, int width, int height, int format,
       return NULL;
 
    memset(&whandle, 0, sizeof(whandle));
-   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+   whandle.type = WINSYS_HANDLE_TYPE_SHARED;
    whandle.handle = names[0];
    whandle.stride = strides[0];
    whandle.offset = offsets[0];
@@ -1364,16 +1510,22 @@ dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats,
 {
    struct dri_screen *screen = dri_screen(_screen);
    struct pipe_screen *pscreen = screen->base.screen;
-   const unsigned bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
    int i, j;
 
    for (i = 0, j = 0; (i < ARRAY_SIZE(fourcc_formats)) &&
          (j < max || max == 0); i++) {
-      if (pscreen->is_format_supported(pscreen,
-                                       fourcc_to_pipe_format(
-                                          fourcc_formats[i]),
-                                       screen->target,
-                                       0, bind)) {
+      enum pipe_format format = fourcc_to_pipe_format(fourcc_formats[i]);
+
+      /* The sRGB format is not a real FourCC as defined by drm_fourcc.h, so we
+       * must not leak it out to clients.
+       */
+      if (fourcc_formats[i] == __DRI_IMAGE_FOURCC_SARGB8888)
+         continue;
+
+      if (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
+                                       PIPE_BIND_RENDER_TARGET) ||
+          pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
+                                       PIPE_BIND_SAMPLER_VIEW)) {
          if (j < max)
             formats[j] = fourcc_formats[i];
          j++;
@@ -1391,10 +1543,12 @@ dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,
    struct dri_screen *screen = dri_screen(_screen);
    struct pipe_screen *pscreen = screen->base.screen;
    enum pipe_format format = fourcc_to_pipe_format(fourcc);
-   const unsigned usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
 
    if (pscreen->query_dmabuf_modifiers != NULL &&
-       pscreen->is_format_supported(pscreen, format, screen->target, 0, usage)) {
+       (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
+                                     PIPE_BIND_RENDER_TARGET) ||
+        pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
+                                     PIPE_BIND_SAMPLER_VIEW))) {
       pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,
                                       external_only, count);
       return true;
@@ -1561,7 +1715,7 @@ dri2_get_capabilities(__DRIscreen *_screen)
 
 /* The extension is modified during runtime if DRI_PRIME is detected */
 static __DRIimageExtension dri2ImageExtension = {
-    .base = { __DRI_IMAGE, 15 },
+    .base = { __DRI_IMAGE, 17 },
 
     .createImageFromName          = dri2_create_image_from_name,
     .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
@@ -1579,6 +1733,12 @@ static __DRIimageExtension dri2ImageExtension = {
     .getCapabilities              = dri2_get_capabilities,
     .mapImage                     = dri2_map_image,
     .unmapImage                   = dri2_unmap_image,
+    .createImageWithModifiers     = NULL,
+    .createImageFromDmaBufs2      = NULL,
+    .queryDmaBufFormats           = NULL,
+    .queryDmaBufModifiers         = NULL,
+    .queryDmaBufFormatModifierAttribs = NULL,
+    .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
 };
 
 static const __DRIrobustnessExtension dri2Robustness = {
@@ -1662,7 +1822,7 @@ dri2_interop_export_object(__DRIcontext *_ctx,
       return MESA_GLINTEROP_INVALID_MIP_LEVEL;
 
    /* Validate the OpenGL object and get pipe_resource. */
-   mtx_lock(&ctx->Shared->Mutex);
+   simple_mtx_lock(&ctx->Shared->Mutex);
 
    if (target == GL_ARRAY_BUFFER) {
       /* Buffer objects.
@@ -1678,14 +1838,14 @@ dri2_interop_export_object(__DRIcontext *_ctx,
        *   the size of the buffer is 0."
        */
       if (!buf || buf->Size == 0) {
-         mtx_unlock(&ctx->Shared->Mutex);
+         simple_mtx_unlock(&ctx->Shared->Mutex);
          return MESA_GLINTEROP_INVALID_OBJECT;
       }
 
       res = st_buffer_object(buf)->buffer;
       if (!res) {
          /* this shouldn't happen */
-         mtx_unlock(&ctx->Shared->Mutex);
+         simple_mtx_unlock(&ctx->Shared->Mutex);
          return MESA_GLINTEROP_INVALID_OBJECT;
       }
 
@@ -1706,7 +1866,7 @@ dri2_interop_export_object(__DRIcontext *_ctx,
        *    object or if the width or height of renderbuffer is zero."
        */
       if (!rb || rb->Width == 0 || rb->Height == 0) {
-         mtx_unlock(&ctx->Shared->Mutex);
+         simple_mtx_unlock(&ctx->Shared->Mutex);
          return MESA_GLINTEROP_INVALID_OBJECT;
       }
 
@@ -1715,7 +1875,7 @@ dri2_interop_export_object(__DRIcontext *_ctx,
        *    renderbuffer object."
        */
       if (rb->NumSamples > 1) {
-         mtx_unlock(&ctx->Shared->Mutex);
+         simple_mtx_unlock(&ctx->Shared->Mutex);
          return MESA_GLINTEROP_INVALID_OPERATION;
       }
 
@@ -1725,7 +1885,7 @@ dri2_interop_export_object(__DRIcontext *_ctx,
        */
       res = st_renderbuffer(rb)->texture;
       if (!res) {
-         mtx_unlock(&ctx->Shared->Mutex);
+         simple_mtx_unlock(&ctx->Shared->Mutex);
          return MESA_GLINTEROP_OUT_OF_RESOURCES;
       }
 
@@ -1755,36 +1915,21 @@ dri2_interop_export_object(__DRIcontext *_ctx,
           obj->Target != target ||
           !obj->_BaseComplete ||
           (in->miplevel > 0 && !obj->_MipmapComplete)) {
-         mtx_unlock(&ctx->Shared->Mutex);
+         simple_mtx_unlock(&ctx->Shared->Mutex);
          return MESA_GLINTEROP_INVALID_OBJECT;
       }
 
-      /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
-       *   "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
-       *    levelbase (for OpenGL implementations) or zero (for OpenGL ES
-       *    implementations); or greater than the value of q (for both OpenGL
-       *    and OpenGL ES). levelbase and q are defined for the texture in
-       *    section 3.8.10 (Texture Completeness) of the OpenGL 2.1
-       *    specification and section 3.7.10 of the OpenGL ES 2.0."
-       */
-      if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) {
-         mtx_unlock(&ctx->Shared->Mutex);
-         return MESA_GLINTEROP_INVALID_MIP_LEVEL;
-      }
-
-      if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {
-         mtx_unlock(&ctx->Shared->Mutex);
-         return MESA_GLINTEROP_OUT_OF_RESOURCES;
-      }
+      if (target == GL_TEXTURE_BUFFER) {
+         struct st_buffer_object *stBuf =
+            st_buffer_object(obj->BufferObject);
 
-      res = st_get_texobj_resource(obj);
-      if (!res) {
-         /* Incomplete texture buffer object? This shouldn't really occur. */
-         mtx_unlock(&ctx->Shared->Mutex);
-         return MESA_GLINTEROP_INVALID_OBJECT;
-      }
+         if (!stBuf || !stBuf->buffer) {
+            /* this shouldn't happen */
+            simple_mtx_unlock(&ctx->Shared->Mutex);
+            return MESA_GLINTEROP_INVALID_OBJECT;
+         }
+         res = stBuf->buffer;
 
-      if (target == GL_TEXTURE_BUFFER) {
          out->internal_format = obj->BufferObjectFormat;
          out->buf_offset = obj->BufferOffset;
          out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :
@@ -1792,6 +1937,31 @@ dri2_interop_export_object(__DRIcontext *_ctx,
 
          obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
       } else {
+         /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
+          *   "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
+          *    levelbase (for OpenGL implementations) or zero (for OpenGL ES
+          *    implementations); or greater than the value of q (for both OpenGL
+          *    and OpenGL ES). levelbase and q are defined for the texture in
+          *    section 3.8.10 (Texture Completeness) of the OpenGL 2.1
+          *    specification and section 3.7.10 of the OpenGL ES 2.0."
+          */
+         if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) {
+            simple_mtx_unlock(&ctx->Shared->Mutex);
+            return MESA_GLINTEROP_INVALID_MIP_LEVEL;
+         }
+
+         if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {
+            simple_mtx_unlock(&ctx->Shared->Mutex);
+            return MESA_GLINTEROP_OUT_OF_RESOURCES;
+         }
+
+         res = st_get_texobj_resource(obj);
+         if (!res) {
+            /* Incomplete texture buffer object? This shouldn't really occur. */
+            simple_mtx_unlock(&ctx->Shared->Mutex);
+            return MESA_GLINTEROP_INVALID_OBJECT;
+         }
+
          out->internal_format = obj->Image[0][0]->InternalFormat;
          out->view_minlevel = obj->MinLevel;
          out->view_numlevels = obj->NumLevels;
@@ -1802,25 +1972,23 @@ dri2_interop_export_object(__DRIcontext *_ctx,
 
    /* Get the handle. */
    switch (in->access) {
-   case MESA_GLINTEROP_ACCESS_READ_WRITE:
-      usage = PIPE_HANDLE_USAGE_READ_WRITE;
-      break;
    case MESA_GLINTEROP_ACCESS_READ_ONLY:
-      usage = PIPE_HANDLE_USAGE_READ;
+      usage = 0;
       break;
+   case MESA_GLINTEROP_ACCESS_READ_WRITE:
    case MESA_GLINTEROP_ACCESS_WRITE_ONLY:
-      usage = PIPE_HANDLE_USAGE_WRITE;
+      usage = PIPE_HANDLE_USAGE_SHADER_WRITE;
       break;
    default:
       usage = 0;
    }
 
    memset(&whandle, 0, sizeof(whandle));
-   whandle.type = DRM_API_HANDLE_TYPE_FD;
+   whandle.type = WINSYS_HANDLE_TYPE_FD;
 
    success = screen->resource_get_handle(screen, st->pipe, res, &whandle,
                                          usage);
-   mtx_unlock(&ctx->Shared->Mutex);
+   simple_mtx_unlock(&ctx->Shared->Mutex);
 
    if (!success)
       return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;
@@ -1951,7 +2119,6 @@ dri2_init_screen(__DRIscreen * sPriv)
    struct pipe_screen *pscreen = NULL;
    const struct drm_conf_ret *throttle_ret;
    const struct drm_conf_ret *dmabuf_ret;
-   int fd;
 
    screen = CALLOC_STRUCT(dri_screen);
    if (!screen)
@@ -1963,11 +2130,7 @@ dri2_init_screen(__DRIscreen * sPriv)
 
    sPriv->driverPrivate = (void *)screen;
 
-   if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
-      goto free_screen;
-
-
-   if (pipe_loader_drm_probe_fd(&screen->dev, fd)) {
+   if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) {
       dri_init_options(screen);
 
       pscreen = pipe_loader_create_screen(screen->dev);
@@ -1996,9 +2159,11 @@ dri2_init_screen(__DRIscreen * sPriv)
          dri2ImageExtension.createImageFromFds = dri2_from_fds;
          dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
          dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
-         dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
-         dri2ImageExtension.queryDmaBufModifiers =
-                                    dri2_query_dma_buf_modifiers;
+         if (pscreen->query_dmabuf_modifiers) {
+            dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
+            dri2ImageExtension.queryDmaBufModifiers =
+                                       dri2_query_dma_buf_modifiers;
+         }
       }
    }
 
@@ -2026,10 +2191,7 @@ destroy_screen:
 release_pipe:
    if (screen->dev)
       pipe_loader_release(&screen->dev, 1);
-   else
-      close(fd);
 
-free_screen:
    FREE(screen);
    return NULL;
 }
@@ -2047,7 +2209,6 @@ dri_kms_init_screen(__DRIscreen * sPriv)
    struct dri_screen *screen;
    struct pipe_screen *pscreen = NULL;
    uint64_t cap;
-   int fd;
 
    screen = CALLOC_STRUCT(dri_screen);
    if (!screen)
@@ -2058,10 +2219,7 @@ dri_kms_init_screen(__DRIscreen * sPriv)
 
    sPriv->driverPrivate = (void *)screen;
 
-   if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
-      goto free_screen;
-
-   if (pipe_loader_sw_probe_kms(&screen->dev, fd)) {
+   if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd)) {
       dri_init_options(screen);
       pscreen = pipe_loader_create_screen(screen->dev);
    }
@@ -2078,8 +2236,10 @@ dri_kms_init_screen(__DRIscreen * sPriv)
       dri2ImageExtension.createImageFromFds = dri2_from_fds;
       dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
       dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
-      dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
-      dri2ImageExtension.queryDmaBufModifiers = dri2_query_dma_buf_modifiers;
+      if (pscreen->query_dmabuf_modifiers) {
+         dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
+         dri2ImageExtension.queryDmaBufModifiers = dri2_query_dma_buf_modifiers;
+      }
    }
 
    sPriv->extensions = dri_screen_extensions;
@@ -2101,10 +2261,7 @@ destroy_screen:
 release_pipe:
    if (screen->dev)
       pipe_loader_release(&screen->dev, 1);
-   else
-      close(fd);
 
-free_screen:
    FREE(screen);
 #endif // GALLIUM_SOFTPIPE
    return NULL;