[Mesa-dev] [RFC]: __DRIbuffer in the multi-winsys world

christopher.halse.rogers at canonical.com christopher.halse.rogers at canonical.com
Sun Nov 3 14:32:00 PST 2013


From: Christopher James Halse Rogers <christopher.halse.rogers at canonical.com>

With DRI3 and the various EGL loaders, GEM names are no longer the
lingua franca of winsys integration. Passing around GEM names in the
__DRIbuffer struct is getting passé.

Attached is a rough first pass at what passing GEM handles rather than
names around in the __DRIbuffer would look like; needs the obvious libdrm
patches to compile :).

Kristian suggested on IRC a separate loader entrypoint, based on __DRIimages
rather than __DRIbuffers. That would have the additional nice property of
hiding the details entirely in the driver, at the cost of either requiring
we keep around the existing loader infrastructure for DRI2 or dropping the
fiction that different GLX clients will see the same auxilliary buffers.

---
 include/GL/internal/dri_interface.h                |  5 +-
 src/egl/drivers/dri2/egl_dri2.h                    |  2 +-
 src/egl/drivers/dri2/platform_drm.c                |  6 +--
 src/egl/drivers/dri2/platform_wayland.c            | 14 ++---
 src/egl/drivers/dri2/platform_x11.c                | 23 +++++++--
 src/gallium/state_trackers/dri/drm/dri2.c          | 25 +++++----
 src/gbm/backends/dri/gbm_dri.c                     |  2 +-
 src/glx/dri2_glx.c                                 | 25 +++++++--
 src/mesa/drivers/dri/i915/intel_context.c          | 54 ++++++++++++++++++--
 src/mesa/drivers/dri/i915/intel_mipmap_tree.c      |  2 +-
 src/mesa/drivers/dri/i915/intel_regions.c          | 47 ++++++++++++++---
 src/mesa/drivers/dri/i915/intel_regions.h          | 11 +++-
 src/mesa/drivers/dri/i915/intel_screen.c           |  5 +-
 src/mesa/drivers/dri/i915/intel_screen.h           |  1 +
 src/mesa/drivers/dri/i965/brw_context.c            | 59 ++++++++++++++++++++--
 src/mesa/drivers/dri/i965/intel_mipmap_tree.c      |  2 +-
 src/mesa/drivers/dri/i965/intel_regions.c          | 55 +++++++++++++++-----
 src/mesa/drivers/dri/i965/intel_regions.h          |  9 +++-
 src/mesa/drivers/dri/i965/intel_screen.c           |  5 +-
 src/mesa/drivers/dri/nouveau/nouveau_context.c     |  8 ++-
 .../drivers/dri/radeon/radeon_common_context.c     | 30 ++++-------
 21 files changed, 297 insertions(+), 93 deletions(-)

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 48993b9..2d17c07 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -783,14 +783,15 @@ struct __DRIswrastExtensionRec {
 
 struct __DRIbufferRec {
     unsigned int attachment;
-    unsigned int name;
+    unsigned int handle;
     unsigned int pitch;
     unsigned int cpp;
     unsigned int flags;
+    unsigned int size;
 };
 
 #define __DRI_DRI2_LOADER "DRI_DRI2Loader"
-#define __DRI_DRI2_LOADER_VERSION 3
+#define __DRI_DRI2_LOADER_VERSION 4
 struct __DRIdri2LoaderExtensionRec {
     __DRIextension base;
 
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index c7d6484..360436c 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -189,7 +189,7 @@ struct dri2_egl_surface
 #ifdef HAVE_WAYLAND_PLATFORM
       struct wl_buffer   *wl_buffer;
       __DRIimage         *dri_image;
-      int                 pitch, name;
+      int                 pitch, handle;
 #endif
 #ifdef HAVE_DRM_PLATFORM
       struct gbm_bo       *bo;
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 7b1e3a1..e9c5173 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -181,7 +181,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
       dri2_egl_display(dri2_surf->base.Resource.Display);
    struct gbm_dri_bo *bo;
    struct gbm_dri_surface *surf = dri2_surf->gbm_surf;
-   int i, name, pitch;
+   int i, handle, pitch;
 
    if (dri2_surf->back == NULL) {
       for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) {
@@ -203,11 +203,11 @@ get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
 
    bo = (struct gbm_dri_bo *) dri2_surf->back->bo;
 
-   dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_NAME, &name);
+   dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, &handle);
    dri2_dpy->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
 
    buffer->attachment = __DRI_BUFFER_BACK_LEFT;
-   buffer->name = name;
+   buffer->handle = handle;
    buffer->pitch = pitch;
    buffer->cpp = 4;
    buffer->flags = 0;
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index c0de16b..a990ed8 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -262,7 +262,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
    struct dri2_egl_display *dri2_dpy =
       dri2_egl_display(dri2_surf->base.Resource.Display);
    __DRIimage *image;
-   int i, name, pitch;
+   int i, handle, pitch;
 
    /* There might be a buffer release already queued that wasn't processed */
    wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_dpy->wl_queue);
@@ -297,14 +297,14 @@ get_back_bo(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
 
    image = dri2_surf->back->dri_image;
 
-   dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
+   dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE, &handle);
    dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
 
-   dri2_surf->back->name = name;
+   dri2_surf->back->handle = handle;
    dri2_surf->back->pitch = pitch;
 
    buffer->attachment = __DRI_BUFFER_BACK_LEFT;
-   buffer->name = name;
+   buffer->handle = handle;
    buffer->pitch = pitch;
    buffer->cpp = 4;
    buffer->flags = 0;
@@ -459,7 +459,7 @@ create_wl_buffer(struct dri2_egl_surface *dri2_surf)
 {
    struct dri2_egl_display *dri2_dpy =
       dri2_egl_display(dri2_surf->base.Resource.Display);
-   int fd;
+   int fd, name;
 
    if (dri2_surf->current->wl_buffer != NULL)
       return;
@@ -479,9 +479,11 @@ create_wl_buffer(struct dri2_egl_surface *dri2_surf)
                                     0, 0);
       close(fd);
    } else {
+      dri2_dpy->image->queryImage(dri2_surf->current->dri_image,
+                                  __DRI_IMAGE_ATTRIB_NAME, &name);
       dri2_surf->current->wl_buffer =
          wl_drm_create_buffer(dri2_dpy->wl_drm,
-                              dri2_surf->current->name,
+                              name,
                               dri2_surf->base.Width,
                               dri2_surf->base.Height,
                               dri2_surf->current->pitch,
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index a518db1..511141f 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -348,7 +348,7 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
  * Processes the list of buffers received in a reply from the server to either
  * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
  */
-static void
+static int
 dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
 		     xcb_dri2_dri2_buffer_t *buffers, unsigned count)
 {
@@ -356,6 +356,7 @@ dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
       dri2_egl_display(dri2_surf->base.Resource.Display);
    xcb_rectangle_t rectangle;
    unsigned i;
+   struct drm_gem_open open_arg;
 
    dri2_surf->buffer_count = count;
    dri2_surf->have_fake_front = 0;
@@ -364,7 +365,6 @@ dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
     * __DRIbuffer tokens. */
    for (i = 0; i < count; i++) {
       dri2_surf->buffers[i].attachment = buffers[i].attachment;
-      dri2_surf->buffers[i].name = buffers[i].name;
       dri2_surf->buffers[i].pitch = buffers[i].pitch;
       dri2_surf->buffers[i].cpp = buffers[i].cpp;
       dri2_surf->buffers[i].flags = buffers[i].flags;
@@ -376,6 +376,14 @@ dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
        * to the same window must see the same aux buffers. */
       if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
          dri2_surf->have_fake_front = 1;
+
+      memset(&open_arg, 0, sizeof(open_arg));
+      open_arg.name = buffers[i].name;
+      if (drmIoctl(dri2_dpy->fd, DRM_IOCTL_GEM_OPEN, &open_arg))
+         return EGL_FALSE;
+
+      dri2_surf->buffers[i].handle = open_arg.handle;
+      dri2_surf->buffers[i].size = open_arg.size;
    }
 
    if (dri2_surf->region != XCB_NONE)
@@ -387,6 +395,7 @@ dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
    rectangle.height = dri2_surf->base.Height;
    dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
    xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
+   return EGL_TRUE;
 }
 
 static __DRIbuffer *
@@ -415,7 +424,10 @@ dri2_get_buffers(__DRIdrawable * driDrawable,
    *out_count = reply->count;
    dri2_surf->base.Width = *width = reply->width;
    dri2_surf->base.Height = *height = reply->height;
-   dri2_process_buffers(dri2_surf, buffers, *out_count);
+   if (!dri2_process_buffers(dri2_surf, buffers, *out_count)) {
+      free(reply);
+      return NULL;
+   }
 
    free(reply);
 
@@ -453,7 +465,10 @@ dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
    dri2_surf->base.Width = *width = reply->width;
    dri2_surf->base.Height = *height = reply->height;
    *out_count = reply->count;
-   dri2_process_buffers(dri2_surf, buffers, *out_count);
+   if (!dri2_process_buffers(dri2_surf, buffers, *out_count)) {
+      free(reply);
+      return NULL;
+   }
 
    free(reply);
 
diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c
index 46d2afd..5d2832b 100644
--- a/src/gallium/state_trackers/dri/drm/dri2.c
+++ b/src/gallium/state_trackers/dri/drm/dri2.c
@@ -72,7 +72,7 @@ static const __DRI2flushExtension dri2FlushExtension = {
 static __DRIbuffer *
 dri2_drawable_get_buffers(struct dri_drawable *drawable,
                           const enum st_attachment_type *atts,
-                          unsigned *count)
+                          unsigned *count, int *version)
 {
    __DRIdrawable *dri_drawable = drawable->dPriv;
    struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader;
@@ -85,6 +85,8 @@ dri2_drawable_get_buffers(struct dri_drawable *drawable,
    assert(loader);
    with_format = dri_with_format(drawable->sPriv);
 
+   *version = loader->base.version;
+
    num_attachments = 0;
 
    /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
@@ -159,8 +161,7 @@ dri2_drawable_get_buffers(struct dri_drawable *drawable,
             &num_buffers, dri_drawable->loaderPrivate);
    }
 
-   if (buffers)
-      *count = num_buffers;
+   *count = num_buffers;
 
    return buffers;
 }
@@ -172,6 +173,7 @@ static void
 dri2_drawable_process_buffers(struct dri_context *ctx,
                               struct dri_drawable *drawable,
                               __DRIbuffer *buffers, unsigned buffer_count,
+                              int buffer_version,
                               const enum st_attachment_type *atts,
                               unsigned att_count)
 {
@@ -262,8 +264,11 @@ dri2_drawable_process_buffers(struct dri_context *ctx,
 
       templ.format = format;
       templ.bind = bind;
-      whandle.type = DRM_API_HANDLE_TYPE_SHARED;
-      whandle.handle = buf->name;
+      if (buffer_version < 4)
+         whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+      else
+         whandle.type = DRM_API_HANDLE_TYPE_KMS;
+      whandle.handle = buf->handle;
       whandle.stride = buf->pitch;
 
       drawable->textures[statt] =
@@ -433,12 +438,12 @@ dri2_allocate_buffer(__DRIscreen *sPriv,
    }
 
    memset(&whandle, 0, sizeof(whandle));
-   whandle.type = DRM_API_HANDLE_TYPE_SHARED;
+   whandle.type = DRM_API_HANDLE_TYPE_KMS;
    screen->base.screen->resource_get_handle(screen->base.screen,
          buffer->resource, &whandle);
 
    buffer->base.attachment = attachment;
-   buffer->base.name = whandle.handle;
+   buffer->base.handle = whandle.handle;
    buffer->base.cpp = util_format_get_blocksize(pf);
    buffer->base.pitch = whandle.stride;
 
@@ -465,12 +470,14 @@ dri2_allocate_textures(struct dri_context *ctx,
                        unsigned statts_count)
 {
    __DRIbuffer *buffers;
+   int buffers_version;
    unsigned num_buffers = statts_count;
 
-   buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
+   buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers,
+                                       &buffers_version);
    if (buffers)
       dri2_drawable_process_buffers(ctx, drawable, buffers, num_buffers,
-                                    statts, statts_count);
+                                    buffers_version, statts, statts_count);
 }
 
 static void
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index e95fcc7..0878def 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -114,7 +114,7 @@ static const __DRIimageLookupExtension image_lookup_extension = {
 };
 
 const __DRIdri2LoaderExtension dri2_loader_extension = {
-   { __DRI_DRI2_LOADER, 3 },
+   { __DRI_DRI2_LOADER, 4 },
    dri_get_buffers,
    dri_flush_front_buffer,
    dri_get_buffers_with_format,
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index cfa5856..c9495a8 100644
--- a/src/glx/dri2_glx.c
+++ b/src/glx/dri2_glx.c
@@ -726,11 +726,13 @@ dri2DestroyScreen(struct glx_screen *base)
  * Processes the list of buffers received in a reply from the server to either
  * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
  */
-static void
+static int
 process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers,
                 unsigned count)
 {
    int i;
+   struct drm_gem_open open_arg;
+   struct dri2_screen *psc = (struct dri2_screen *)pdraw->base.psc;
 
    pdraw->bufferCount = count;
    pdraw->have_fake_front = 0;
@@ -740,7 +742,6 @@ process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers,
     * __DRIbuffer tokens. */
    for (i = 0; i < count; i++) {
       pdraw->buffers[i].attachment = buffers[i].attachment;
-      pdraw->buffers[i].name = buffers[i].name;
       pdraw->buffers[i].pitch = buffers[i].pitch;
       pdraw->buffers[i].cpp = buffers[i].cpp;
       pdraw->buffers[i].flags = buffers[i].flags;
@@ -748,8 +749,16 @@ process_buffers(struct dri2_drawable * pdraw, DRI2Buffer * buffers,
          pdraw->have_fake_front = 1;
       if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
          pdraw->have_back = 1;
-   }
 
+      memset(&open_arg, 0, sizeof(open_arg));
+      open_arg.name = buffers[i].name;
+      if (drmIoctl(psc->fd, DRM_IOCTL_GEM_OPEN, &open_arg))
+         return 0;
+
+      pdraw->buffers[i].handle = open_arg.handle;
+      pdraw->buffers[i].size = open_arg.size;
+   }
+   return 1;
 }
 
 unsigned dri2GetSwapEventType(Display* dpy, XID drawable)
@@ -888,7 +897,10 @@ dri2GetBuffers(__DRIdrawable * driDrawable,
 
    pdraw->width = *width;
    pdraw->height = *height;
-   process_buffers(pdraw, buffers, *out_count);
+   if (!process_buffers(pdraw, buffers, *out_count)) {
+      free(buffers);
+      return NULL;
+   }
 
    free(buffers);
 
@@ -913,7 +925,10 @@ dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
 
    pdraw->width = *width;
    pdraw->height = *height;
-   process_buffers(pdraw, buffers, *out_count);
+   if (!process_buffers(pdraw, buffers, *out_count)) {
+      free(buffers);
+      return NULL;
+   }
 
    free(buffers);
 
diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
index 2748514..89bb823 100644
--- a/src/mesa/drivers/dri/i915/intel_context.c
+++ b/src/mesa/drivers/dri/i915/intel_context.c
@@ -719,6 +719,48 @@ intel_query_dri2_buffers(struct intel_context *intel,
 							drawable->loaderPrivate);
 }
 
+static void
+intel_process_dri2_buffer_v3(struct intel_context *intel,
+                             __DRIdrawable *drawable,
+                             __DRIbuffer *buffer,
+                             struct intel_renderbuffer *rb,
+                             const char *buffer_name)
+{
+   struct intel_region *region = NULL;
+
+   if (!rb)
+      return;
+
+   /* No attempt is made to avoid reopening the same bo.
+    * This codepath will only be hit when old loaders try to use
+    * new DRI drivers. If this is a performance bottleneck for you,
+    * upgrade your DRI2 loader!
+    */
+   if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
+      fprintf(stderr,
+              "attaching buffer %d, at %d, cpp %d, pitch %d\n",
+              buffer->handle, buffer->attachment,
+              buffer->cpp, buffer->pitch);
+   }
+
+   intel_miptree_release(&rb->mt);
+   region = intel_region_alloc_for_name(intel->intelScreen,
+                                        buffer->cpp,
+                                        drawable->w,
+                                        drawable->h,
+                                        buffer->pitch,
+                                        buffer->handle,
+                                        buffer_name);
+   if (!region)
+      return;
+
+   rb->mt = intel_miptree_create_for_dri2_buffer(intel,
+                                                 buffer->attachment,
+                                                 intel_rb_format(rb),
+                                                 region);
+   intel_region_release(&region);
+}
+
 /**
  * \brief Assign a DRI buffer's DRM region to a renderbuffer.
  *
@@ -746,19 +788,24 @@ intel_process_dri2_buffer(struct intel_context *intel,
    if (!rb)
       return;
 
+   if (intel->intelScreen->driScrnPriv->dri2.loader->base.version < 4) {
+      intel_process_dri2_buffer_v3(intel, drawable, buffer, rb, buffer_name);
+      return;
+   }
+
    /* We try to avoid closing and reopening the same BO name, because the first
     * use of a mapping of the buffer involves a bunch of page faulting which is
     * moderately expensive.
     */
    if (rb->mt &&
        rb->mt->region &&
-       rb->mt->region->name == buffer->name)
+       rb->mt->region->handle == buffer->handle)
       return;
 
    if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
       fprintf(stderr,
 	      "attaching buffer %d, at %d, cpp %d, pitch %d\n",
-	      buffer->name, buffer->attachment,
+	      buffer->handle, buffer->attachment,
 	      buffer->cpp, buffer->pitch);
    }
 
@@ -768,7 +815,8 @@ intel_process_dri2_buffer(struct intel_context *intel,
                                           drawable->w,
                                           drawable->h,
                                           buffer->pitch,
-                                          buffer->name,
+                                          buffer->handle,
+                                          buffer->size,
                                           buffer_name);
    if (!region)
       return;
diff --git a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
index 8432b6d..73e0da8 100644
--- a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
@@ -317,7 +317,7 @@ intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
                                     region->tiling);
    if (!mt)
       return NULL;
-   mt->region->name = region->name;
+   mt->region->handle = region->handle;
 
    return mt;
 }
diff --git a/src/mesa/drivers/dri/i915/intel_regions.c b/src/mesa/drivers/dri/i915/intel_regions.c
index 44f7030..9059448 100644
--- a/src/mesa/drivers/dri/i915/intel_regions.c
+++ b/src/mesa/drivers/dri/i915/intel_regions.c
@@ -161,28 +161,59 @@ intel_region_alloc(struct intel_screen *screen,
 bool
 intel_region_flink(struct intel_region *region, uint32_t *name)
 {
-   if (region->name == 0) {
-      if (drm_intel_bo_flink(region->bo, &region->name))
-	 return false;
+   if (drm_intel_bo_flink(region->bo, name))
+      return false;
+
+   return true;
+}
+
+struct intel_region *
+intel_region_alloc_for_name(struct intel_screen *screen,
+                            GLuint cpp,
+                            GLuint width, GLuint height, GLuint pitch,
+                            GLuint gem_name, const char *name)
+{
+   struct intel_region *region;
+   drm_intel_bo *buffer;
+   int ret;
+   uint32_t bit_6_swizzle, tiling;
+
+   buffer = intel_bo_gem_create_from_name(screen->bufmgr, name, gem_name);
+   if (buffer == NULL)
+      return NULL;
+   ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
+   if (ret != 0) {
+      fprintf(stderr, "Couldn't get tiling of buffer %d (%s): %s\n",
+              gem_name, name, strerror(-ret));
+      drm_intel_bo_unreference(buffer);
+      return NULL;
    }
 
-   *name = region->name;
+   region = intel_region_alloc_internal(screen, cpp,
+                                        width, height, pitch, tiling, buffer);
+   if (region == NULL) {
+      drm_intel_bo_unreference(buffer);
+      return NULL;
+   }
 
-   return true;
+   region->handle = buffer->handle;
+
+   return region;
 }
 
 struct intel_region *
 intel_region_alloc_for_handle(struct intel_screen *screen,
 			      GLuint cpp,
 			      GLuint width, GLuint height, GLuint pitch,
-			      GLuint handle, const char *name)
+			      GLuint handle, int size,
+                              const char *name)
 {
    struct intel_region *region;
    drm_intel_bo *buffer;
    int ret;
    uint32_t bit_6_swizzle, tiling;
 
-   buffer = intel_bo_gem_create_from_name(screen->bufmgr, name, handle);
+   buffer = drm_intel_bo_gem_wrap_handle(screen->bufmgr, name, handle, size);
    if (buffer == NULL)
       return NULL;
    ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
@@ -200,7 +231,7 @@ intel_region_alloc_for_handle(struct intel_screen *screen,
       return NULL;
    }
 
-   region->name = handle;
+   region->handle = buffer->handle;
 
    return region;
 }
diff --git a/src/mesa/drivers/dri/i915/intel_regions.h b/src/mesa/drivers/dri/i915/intel_regions.h
index 5c612a9..afd0264 100644
--- a/src/mesa/drivers/dri/i915/intel_regions.h
+++ b/src/mesa/drivers/dri/i915/intel_regions.h
@@ -68,7 +68,7 @@ struct intel_region
 
    uint32_t tiling; /**< Which tiling mode the region is in */
 
-   uint32_t name; /**< Global name for the bo */
+   uint32_t handle; /**< Kernel name for the bo */
 };
 
 
@@ -85,7 +85,14 @@ struct intel_region *
 intel_region_alloc_for_handle(struct intel_screen *screen,
 			      GLuint cpp,
 			      GLuint width, GLuint height, GLuint pitch,
-			      unsigned int handle, const char *name);
+			      unsigned int handle, int size,
+            const char *name);
+
+struct intel_region *
+intel_region_alloc_for_name(struct intel_screen *screen,
+            GLuint cpp,
+            GLuint width, GLuint height, GLuint pitch,
+            unsigned int gem_name, const char *name);
 
 struct intel_region *
 intel_region_alloc_for_fd(struct intel_screen *screen,
diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index 3f54752..632af8f 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -356,7 +356,7 @@ intel_create_image_from_name(__DRIscreen *screen,
        cpp = 1;
     else
        cpp = _mesa_get_format_bytes(image->format);
-    image->region = intel_region_alloc_for_handle(intelScreen,
+    image->region = intel_region_alloc_for_name(intelScreen,
 						  cpp, width, height,
 						  pitch * cpp, name, "image");
     if (image->region == NULL) {
@@ -1171,8 +1171,7 @@ intelAllocateBuffer(__DRIscreen *screen,
 	   return NULL;
    }
    
-   intel_region_flink(intelBuffer->region, &intelBuffer->base.name);
-
+   intelBuffer->base.handle = intelBuffer->region->handle;
    intelBuffer->base.attachment = attachment;
    intelBuffer->base.cpp = intelBuffer->region->cpp;
    intelBuffer->base.pitch = intelBuffer->region->pitch;
diff --git a/src/mesa/drivers/dri/i915/intel_screen.h b/src/mesa/drivers/dri/i915/intel_screen.h
index 4ae259c..fc16813 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.h
+++ b/src/mesa/drivers/dri/i915/intel_screen.h
@@ -61,6 +61,7 @@ struct intel_screen
 #define intel_region_alloc                  old_intel_region_alloc
 #define intel_region_alloc_for_fd           old_intel_region_alloc_for_fd
 #define intel_region_alloc_for_handle       old_intel_region_alloc_for_handle
+#define intel_region_alloc_for_name         old_intel_region_alloc_for_name
 #define intel_region_flink                  old_intel_region_flink
 #define intel_region_get_aligned_offset     old_intel_region_get_aligned_offset
 #define intel_region_get_tile_masks         old_intel_region_get_tile_masks
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 38147e9..eeece98 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -1117,6 +1117,51 @@ intel_query_dri2_buffers(struct brw_context *brw,
                                                         drawable->loaderPrivate);
 }
 
+static void
+intel_process_dri2_buffer_v3(struct brw_context *brw,
+                             __DRIdrawable *drawable,
+                             __DRIbuffer *buffer,
+                             struct intel_renderbuffer *rb,
+                             const char *buffer_name)
+{
+   struct intel_region *region = NULL;
+
+   if (!rb)
+      return;
+
+  unsigned num_samples = rb->Base.Base.NumSamples;
+
+   /* No attempt is made to avoid reopening the same bo.
+    * This codepath will only be hit when old loaders try to use
+    * new DRI drivers. If this is a performance bottleneck for you,
+    * upgrade your DRI2 loader!
+    */
+   if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
+      fprintf(stderr,
+              "attaching buffer %d, at %d, cpp %d, pitch %d\n",
+              buffer->handle, buffer->attachment,
+              buffer->cpp, buffer->pitch);
+   }
+
+   intel_miptree_release(&rb->mt);
+   region = intel_region_alloc_for_name(brw->intelScreen,
+                                        buffer->cpp,
+                                        drawable->w,
+                                        drawable->h,
+                                        buffer->pitch,
+                                        buffer->handle,
+                                        buffer_name);
+   if (!region)
+      return;
+
+   rb->mt = intel_miptree_create_for_dri2_buffer(brw,
+                                                 buffer->attachment,
+                                                 intel_rb_format(rb),
+                                                 num_samples,
+                                                 region);
+   intel_region_release(&region);
+}
+
 /**
  * \brief Assign a DRI buffer's DRM region to a renderbuffer.
  *
@@ -1144,6 +1189,11 @@ intel_process_dri2_buffer(struct brw_context *brw,
    if (!rb)
       return;
 
+   if (brw->intelScreen->driScrnPriv->dri2.loader->base.version < 4) {
+      intel_process_dri2_buffer_v3(brw, drawable, buffer, rb, buffer_name);
+      return;
+   }
+
    unsigned num_samples = rb->Base.Base.NumSamples;
 
    /* We try to avoid closing and reopening the same BO name, because the first
@@ -1153,20 +1203,20 @@ intel_process_dri2_buffer(struct brw_context *brw,
    if (num_samples == 0) {
        if (rb->mt &&
            rb->mt->region &&
-           rb->mt->region->name == buffer->name)
+           rb->mt->region->handle == buffer->handle)
           return;
    } else {
        if (rb->mt &&
            rb->mt->singlesample_mt &&
            rb->mt->singlesample_mt->region &&
-           rb->mt->singlesample_mt->region->name == buffer->name)
+           rb->mt->singlesample_mt->region->handle == buffer->handle)
           return;
    }
 
    if (unlikely(INTEL_DEBUG & DEBUG_DRI)) {
       fprintf(stderr,
               "attaching buffer %d, at %d, cpp %d, pitch %d\n",
-              buffer->name, buffer->attachment,
+              buffer->handle, buffer->attachment,
               buffer->cpp, buffer->pitch);
    }
 
@@ -1176,7 +1226,8 @@ intel_process_dri2_buffer(struct brw_context *brw,
                                           drawable->w,
                                           drawable->h,
                                           buffer->pitch,
-                                          buffer->name,
+                                          buffer->handle,
+                                          buffer->size,
                                           buffer_name);
    if (!region)
       return;
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index 2f5e04f..0d23e9f 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -690,7 +690,7 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw,
                                                  region->tiling);
    if (!singlesample_mt)
       return NULL;
-   singlesample_mt->region->name = region->name;
+   singlesample_mt->region->handle = region->handle;
 
    /* If this miptree is capable of supporting fast color clears, set
     * mcs_state appropriately to ensure that fast clears will occur.
diff --git a/src/mesa/drivers/dri/i965/intel_regions.c b/src/mesa/drivers/dri/i965/intel_regions.c
index a6b80fd..279f049 100644
--- a/src/mesa/drivers/dri/i965/intel_regions.c
+++ b/src/mesa/drivers/dri/i965/intel_regions.c
@@ -161,46 +161,77 @@ intel_region_alloc(struct intel_screen *screen,
 bool
 intel_region_flink(struct intel_region *region, uint32_t *name)
 {
-   if (region->name == 0) {
-      if (drm_intel_bo_flink(region->bo, &region->name))
-	 return false;
+   if (drm_intel_bo_flink(region->bo, name))
+      return false;
+
+   return true;
+}
+
+struct intel_region *
+intel_region_alloc_for_name(struct intel_screen *screen,
+                            GLuint cpp,
+                            GLuint width, GLuint height, GLuint pitch,
+                            GLuint gem_name, const char *name)
+{
+   struct intel_region *region;
+   drm_intel_bo *buffer;
+   int ret;
+   uint32_t bit_6_swizzle, tiling;
+
+   buffer = intel_bo_gem_create_from_name(screen->bufmgr, name, gem_name);
+   if (buffer == NULL)
+      return NULL;
+   ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
+   if (ret != 0) {
+      fprintf(stderr, "Couldn't get tiling of buffer %d (%s): %s\n",
+              gem_name, name, strerror(-ret));
+      drm_intel_bo_unreference(buffer);
+      return NULL;
    }
 
-   *name = region->name;
+   region = intel_region_alloc_internal(screen, cpp,
+                                        width, height, pitch, tiling, buffer);
+   if (region == NULL) {
+      drm_intel_bo_unreference(buffer);
+      return NULL;
+   }
 
-   return true;
+   region->handle = buffer->handle;
+
+   return region;
 }
 
 struct intel_region *
 intel_region_alloc_for_handle(struct intel_screen *screen,
-			      GLuint cpp,
-			      GLuint width, GLuint height, GLuint pitch,
-			      GLuint handle, const char *name)
+            GLuint cpp,
+            GLuint width, GLuint height, GLuint pitch,
+            GLuint handle, int size,
+                              const char *name)
 {
    struct intel_region *region;
    drm_intel_bo *buffer;
    int ret;
    uint32_t bit_6_swizzle, tiling;
 
-   buffer = intel_bo_gem_create_from_name(screen->bufmgr, name, handle);
+   buffer = drm_intel_bo_gem_wrap_handle(screen->bufmgr, name, handle, size);
    if (buffer == NULL)
       return NULL;
    ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
    if (ret != 0) {
       fprintf(stderr, "Couldn't get tiling of buffer %d (%s): %s\n",
-	      handle, name, strerror(-ret));
+        handle, name, strerror(-ret));
       drm_intel_bo_unreference(buffer);
       return NULL;
    }
 
    region = intel_region_alloc_internal(screen, cpp,
-					width, height, pitch, tiling, buffer);
+          width, height, pitch, tiling, buffer);
    if (region == NULL) {
       drm_intel_bo_unreference(buffer);
       return NULL;
    }
 
-   region->name = handle;
+   region->handle = buffer->handle;
 
    return region;
 }
diff --git a/src/mesa/drivers/dri/i965/intel_regions.h b/src/mesa/drivers/dri/i965/intel_regions.h
index f08a113..755d777 100644
--- a/src/mesa/drivers/dri/i965/intel_regions.h
+++ b/src/mesa/drivers/dri/i965/intel_regions.h
@@ -69,7 +69,7 @@ struct intel_region
 
    uint32_t tiling; /**< Which tiling mode the region is in */
 
-   uint32_t name; /**< Global name for the bo */
+   uint32_t handle; /**< Kernel name for the bo */
 };
 
 
@@ -84,6 +84,13 @@ struct intel_region *intel_region_alloc(struct intel_screen *screen,
 
 struct intel_region *
 intel_region_alloc_for_handle(struct intel_screen *screen,
+            GLuint cpp,
+            GLuint width, GLuint height, GLuint pitch,
+            unsigned int handle, int size,
+            const char *name);
+
+struct intel_region *
+intel_region_alloc_for_name(struct intel_screen *screen,
 			      GLuint cpp,
 			      GLuint width, GLuint height, GLuint pitch,
 			      unsigned int handle, const char *name);
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index eafafa2..3a4dd55 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -417,7 +417,7 @@ intel_create_image_from_name(__DRIscreen *screen,
        cpp = 1;
     else
        cpp = _mesa_get_format_bytes(image->format);
-    image->region = intel_region_alloc_for_handle(intelScreen,
+    image->region = intel_region_alloc_for_name(intelScreen,
 						  cpp, width, height,
 						  pitch * cpp, name, "image");
     if (image->region == NULL) {
@@ -1295,8 +1295,7 @@ intelAllocateBuffer(__DRIscreen *screen,
 	   return NULL;
    }
    
-   intel_region_flink(intelBuffer->region, &intelBuffer->base.name);
-
+   intelBuffer->base.handle = intelBuffer->region->handle;
    intelBuffer->base.attachment = attachment;
    intelBuffer->base.cpp = intelBuffer->region->cpp;
    intelBuffer->base.pitch = intelBuffer->region->pitch;
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index 0b648ac..3c53567 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -255,7 +255,6 @@ nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw)
 	for (i = 0; i < count; i++) {
 		struct gl_renderbuffer *rb;
 		struct nouveau_surface *s;
-		uint32_t old_name;
 		int index;
 
 		switch (buffers[i].attachment) {
@@ -286,18 +285,17 @@ nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw)
 		s->cpp = buffers[i].cpp;
 
 		if (index == BUFFER_DEPTH && s->bo) {
-			ret = nouveau_bo_name_get(s->bo, &old_name);
 			/*
 			 * Disable fast Z clears in the next frame, the
 			 * depth buffer contents are undefined.
 			 */
-			if (!ret && old_name != buffers[i].name)
+			if (s->bo->handle != buffers[i].handle)
 				nctx->hierz.clear_seq = 0;
 		}
 
 		nouveau_bo_ref(NULL, &s->bo);
-		ret = nouveau_bo_name_ref(context_dev(ctx),
-					  buffers[i].name, &s->bo);
+		ret = nouveau_bo_wrap(context_dev(ctx),
+					  buffers[i].handle, &s->bo);
 		assert(!ret);
 	}
 
diff --git a/src/mesa/drivers/dri/radeon/radeon_common_context.c b/src/mesa/drivers/dri/radeon/radeon_common_context.c
index 6dec137..793c23f 100644
--- a/src/mesa/drivers/dri/radeon/radeon_common_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_common_context.c
@@ -461,16 +461,13 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 		if (rb == NULL)
 			continue;
 
-		if (rb->bo) {
-			uint32_t name = radeon_gem_name_bo(rb->bo);
-			if (name == buffers[i].name)
-				continue;
-		}
+		if (rb->bo && (radeon_bo_get_handle(rb->bo) == buffers[i].handle))
+			continue;
 
 		if (RADEON_DEBUG & RADEON_DRI)
 			fprintf(stderr,
 				"attaching buffer %s, %d, at %d, cpp %d, pitch %d\n",
-				regname, buffers[i].name, buffers[i].attachment,
+				regname, buffers[i].handle, buffers[i].attachment,
 				buffers[i].cpp, buffers[i].pitch);
 
 		rb->cpp = buffers[i].cpp;
@@ -488,16 +485,13 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 			uint32_t tiling_flags = 0, pitch = 0;
 			int ret;
 
-			bo = radeon_bo_open(radeon->radeonScreen->bom,
-						buffers[i].name,
-						0,
-						0,
-						RADEON_GEM_DOMAIN_VRAM,
-						buffers[i].flags);
+			bo = radeon_gem_bo_wrap_handle(radeon->radeonScreen->bom,
+						buffers[i].handle,
+						buffers[i].size);
 
 			if (bo == NULL) {
 				fprintf(stderr, "failed to attach %s %d\n",
-					regname, buffers[i].name);
+					regname, buffers[i].handle);
 				continue;
 			}
 
@@ -505,7 +499,7 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 			if (ret) {
 				fprintf(stderr,
 					"failed to get tiling for %s %d\n",
-					regname, buffers[i].name);
+					regname, buffers[i].handle);
 				radeon_bo_unref(bo);
 				bo = NULL;
 				continue;
@@ -531,11 +525,9 @@ radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable,
 			if (rb != NULL) {
 				struct radeon_bo *stencil_bo = NULL;
 
-				if (rb->bo) {
-					uint32_t name = radeon_gem_name_bo(rb->bo);
-					if (name == buffers[i].name)
-						continue;
-				}
+				if (rb->bo &&
+					(radeon_bo_get_handle(rb->bo) == buffers[i].handle))
+					continue;
 
 				stencil_bo = bo;
 				radeon_bo_ref(stencil_bo);
-- 
1.8.4.2



More information about the mesa-dev mailing list