All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] Add DRIimage-based DRI3/Present loader
@ 2013-11-05  2:23 Keith Packard
  2013-11-05  2:23 ` [PATCH 1/8] drivers/dri/common: A few dri2 functions are not actually DRI2 specific Keith Packard
                   ` (8 more replies)
  0 siblings, 9 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-05  2:23 UTC (permalink / raw)
  To: mesa3d-dev; +Cc: dri-devel

This sequence first adds a a couple of new DRIimage extensions to the
dri/common, dri/i915 and dri/i965 directories which define a
loader-independent API for managing window system operations.

The last patch adds a new DRI3000 loader using those new interfaces.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 1/8] drivers/dri/common: A few dri2 functions are not actually DRI2 specific
  2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
@ 2013-11-05  2:23 ` Keith Packard
  2013-11-05  2:23 ` [PATCH 2/8] dri/intel: Split out DRI2 buffer update code to separate function Keith Packard
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-05  2:23 UTC (permalink / raw)
  To: mesa3d-dev; +Cc: dri-devel

This just renames them so that they can be used with the DRI3 extension
without causing too much confusion.

Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>
---
 src/mesa/drivers/dri/common/dri_util.c | 58 +++++++++++++++++-----------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index c28b0fc..95c8b41 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -291,13 +291,13 @@ validate_context_version(__DRIscreen *screen,
 /*@{*/
 
 static __DRIcontext *
-dri2CreateContextAttribs(__DRIscreen *screen, int api,
-			 const __DRIconfig *config,
-			 __DRIcontext *shared,
-			 unsigned num_attribs,
-			 const uint32_t *attribs,
-			 unsigned *error,
-			 void *data)
+driCreateContextAttribs(__DRIscreen *screen, int api,
+                        const __DRIconfig *config,
+                        __DRIcontext *shared,
+                        unsigned num_attribs,
+                        const uint32_t *attribs,
+                        unsigned *error,
+                        void *data)
 {
     __DRIcontext *context;
     const struct gl_config *modes = (config != NULL) ? &config->modes : NULL;
@@ -442,22 +442,22 @@ dri2CreateContextAttribs(__DRIscreen *screen, int api,
 }
 
 static __DRIcontext *
-dri2CreateNewContextForAPI(__DRIscreen *screen, int api,
-			   const __DRIconfig *config,
-			   __DRIcontext *shared, void *data)
+driCreateNewContextForAPI(__DRIscreen *screen, int api,
+                          const __DRIconfig *config,
+                          __DRIcontext *shared, void *data)
 {
     unsigned error;
 
-    return dri2CreateContextAttribs(screen, api, config, shared, 0, NULL,
-				    &error, data);
+    return driCreateContextAttribs(screen, api, config, shared, 0, NULL,
+                                   &error, data);
 }
 
 static __DRIcontext *
-dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
-		      __DRIcontext *shared, void *data)
+driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
+                    __DRIcontext *shared, void *data)
 {
-    return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL,
-				      config, shared, data);
+    return driCreateNewContextForAPI(screen, __DRI_API_OPENGL,
+                                     config, shared, data);
 }
 
 /**
@@ -609,9 +609,9 @@ static void dri_put_drawable(__DRIdrawable *pdp)
 }
 
 static __DRIdrawable *
-dri2CreateNewDrawable(__DRIscreen *screen,
-		      const __DRIconfig *config,
-		      void *data)
+driCreateNewDrawable(__DRIscreen *screen,
+                     const __DRIconfig *config,
+                     void *data)
 {
     __DRIdrawable *pdraw;
 
@@ -698,7 +698,7 @@ dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val)
 }
 
 static unsigned int
-dri2GetAPIMask(__DRIscreen *screen)
+driGetAPIMask(__DRIscreen *screen)
 {
     return screen->api_mask;
 }
@@ -729,7 +729,7 @@ const __DRIcoreExtension driCoreExtension = {
     .createNewDrawable          = NULL,
     .destroyDrawable            = driDestroyDrawable,
     .swapBuffers                = driSwapBuffers, /* swrast */
-    .createNewContext           = dri2CreateNewContext, /* swrast */
+    .createNewContext           = driCreateNewContext, /* swrast */
     .copyContext                = driCopyContext,
     .destroyContext             = driDestroyContext,
     .bindContext                = driBindContext,
@@ -741,22 +741,22 @@ const __DRIdri2Extension driDRI2Extension = {
     .base = { __DRI_DRI2, 4 },
 
     .createNewScreen            = dri2CreateNewScreen,
-    .createNewDrawable          = dri2CreateNewDrawable,
-    .createNewContext           = dri2CreateNewContext,
-    .getAPIMask                 = dri2GetAPIMask,
-    .createNewContextForAPI     = dri2CreateNewContextForAPI,
+    .createNewDrawable          = driCreateNewDrawable,
+    .createNewContext           = driCreateNewContext,
+    .getAPIMask                 = driGetAPIMask,
+    .createNewContextForAPI     = driCreateNewContextForAPI,
     .allocateBuffer             = dri2AllocateBuffer,
     .releaseBuffer              = dri2ReleaseBuffer,
-    .createContextAttribs       = dri2CreateContextAttribs,
+    .createContextAttribs       = driCreateContextAttribs,
     .createNewScreen2           = dri2CreateNewScreen2,
 };
 
 const __DRIswrastExtension driSWRastExtension = {
     { __DRI_SWRAST, 4 },
     driSWRastCreateNewScreen,
-    dri2CreateNewDrawable,
-    dri2CreateNewContextForAPI,
-    dri2CreateContextAttribs,
+    driCreateNewDrawable,
+    driCreateNewContextForAPI,
+    driCreateContextAttribs,
     driSWRastCreateNewScreen2,
 };
 
-- 
1.8.4.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 2/8] dri/intel: Split out DRI2 buffer update code to separate function
  2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
  2013-11-05  2:23 ` [PATCH 1/8] drivers/dri/common: A few dri2 functions are not actually DRI2 specific Keith Packard
@ 2013-11-05  2:23 ` Keith Packard
  2013-11-05  2:23 ` [PATCH 3/8] dri/intel: Add explicit size parameter to intel_region_alloc_for_fd Keith Packard
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-05  2:23 UTC (permalink / raw)
  To: mesa3d-dev; +Cc: dri-devel

Make an easy place to splice in a DRI3 version of this function

Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>
---
 src/mesa/drivers/dri/i915/intel_context.c | 90 +++++++++++++++++--------------
 src/mesa/drivers/dri/i965/brw_context.c   | 22 ++++++--
 2 files changed, 68 insertions(+), 44 deletions(-)

diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
index 2748514..1798bc7 100644
--- a/src/mesa/drivers/dri/i915/intel_context.c
+++ b/src/mesa/drivers/dri/i915/intel_context.c
@@ -133,15 +133,58 @@ intel_process_dri2_buffer(struct intel_context *intel,
 			  struct intel_renderbuffer *rb,
 			  const char *buffer_name);
 
-void
-intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+static void
+intel_update_dri2_buffers(struct intel_context *intel, __DRIdrawable *drawable)
 {
-   struct gl_framebuffer *fb = drawable->driverPrivate;
-   struct intel_renderbuffer *rb;
-   struct intel_context *intel = context->driverPrivate;
    __DRIbuffer *buffers = NULL;
    int i, count;
    const char *region_name;
+   struct intel_renderbuffer *rb;
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+
+   intel_query_dri2_buffers(intel, drawable, &buffers, &count);
+
+   if (buffers == NULL)
+      return;
+
+   for (i = 0; i < count; i++) {
+      switch (buffers[i].attachment) {
+      case __DRI_BUFFER_FRONT_LEFT:
+         rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+         region_name = "dri2 front buffer";
+         break;
+
+      case __DRI_BUFFER_FAKE_FRONT_LEFT:
+         rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+         region_name = "dri2 fake front buffer";
+         break;
+
+      case __DRI_BUFFER_BACK_LEFT:
+         rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
+         region_name = "dri2 back buffer";
+         break;
+
+      case __DRI_BUFFER_DEPTH:
+      case __DRI_BUFFER_HIZ:
+      case __DRI_BUFFER_DEPTH_STENCIL:
+      case __DRI_BUFFER_STENCIL:
+      case __DRI_BUFFER_ACCUM:
+      default:
+         fprintf(stderr,
+                 "unhandled buffer attach event, attachment type %d\n",
+                 buffers[i].attachment);
+         return;
+      }
+
+      intel_process_dri2_buffer(intel, drawable, &buffers[i], rb, region_name);
+   }
+}
+
+void
+intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+{
+   struct intel_context *intel = context->driverPrivate;
+   __DRIscreen *screen = intel->intelScreen->driScrnPriv;
 
    /* Set this up front, so that in case our buffers get invalidated
     * while we're getting new buffers, we don't clobber the stamp and
@@ -151,42 +194,7 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
    if (unlikely(INTEL_DEBUG & DEBUG_DRI))
       fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
 
-   intel_query_dri2_buffers(intel, drawable, &buffers, &count);
-
-   if (buffers == NULL)
-      return;
-
-   for (i = 0; i < count; i++) {
-       switch (buffers[i].attachment) {
-       case __DRI_BUFFER_FRONT_LEFT:
-	   rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
-	   region_name = "dri2 front buffer";
-	   break;
-
-       case __DRI_BUFFER_FAKE_FRONT_LEFT:
-	   rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
-	   region_name = "dri2 fake front buffer";
-	   break;
-
-       case __DRI_BUFFER_BACK_LEFT:
-	   rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
-	   region_name = "dri2 back buffer";
-	   break;
-
-       case __DRI_BUFFER_DEPTH:
-       case __DRI_BUFFER_HIZ:
-       case __DRI_BUFFER_DEPTH_STENCIL:
-       case __DRI_BUFFER_STENCIL:
-       case __DRI_BUFFER_ACCUM:
-       default:
-	   fprintf(stderr,
-		   "unhandled buffer attach event, attachment type %d\n",
-		   buffers[i].attachment);
-	   return;
-       }
-
-       intel_process_dri2_buffer(intel, drawable, &buffers[i], rb, region_name);
-   }
+   intel_update_dri2_buffers(intel, drawable);
 
    driUpdateFramebufferSize(&intel->ctx, drawable);
 }
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 13569ad..2557d10 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -978,12 +978,11 @@ intel_process_dri2_buffer(struct brw_context *brw,
                           struct intel_renderbuffer *rb,
                           const char *buffer_name);
 
-void
-intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+static void
+intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable)
 {
    struct gl_framebuffer *fb = drawable->driverPrivate;
    struct intel_renderbuffer *rb;
-   struct brw_context *brw = context->driverPrivate;
    __DRIbuffer *buffers = NULL;
    int i, count;
    const char *region_name;
@@ -1033,6 +1032,23 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
        intel_process_dri2_buffer(brw, drawable, &buffers[i], rb, region_name);
    }
 
+}
+
+void
+intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
+{
+   struct brw_context *brw = context->driverPrivate;
+
+   /* Set this up front, so that in case our buffers get invalidated
+    * while we're getting new buffers, we don't clobber the stamp and
+    * thus ignore the invalidate. */
+   drawable->lastStamp = drawable->dri2.stamp;
+
+   if (unlikely(INTEL_DEBUG & DEBUG_DRI))
+      fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
+
+   intel_update_dri2_buffers(brw, drawable);
+
    driUpdateFramebufferSize(&brw->ctx, drawable);
 }
 
-- 
1.8.4.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 3/8] dri/intel: Add explicit size parameter to intel_region_alloc_for_fd
  2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
  2013-11-05  2:23 ` [PATCH 1/8] drivers/dri/common: A few dri2 functions are not actually DRI2 specific Keith Packard
  2013-11-05  2:23 ` [PATCH 2/8] dri/intel: Split out DRI2 buffer update code to separate function Keith Packard
@ 2013-11-05  2:23 ` Keith Packard
  2013-11-05 22:23   ` Kristian Høgsberg
  2013-11-05  2:23 ` [PATCH 4/8] Define __DRI_IMAGE_FORMAT_SARGB8 Keith Packard
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 36+ messages in thread
From: Keith Packard @ 2013-11-05  2:23 UTC (permalink / raw)
  To: mesa3d-dev; +Cc: dri-devel

Instead of assuming that the size will be height * pitch, have the caller pass
in the size explicitly.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 src/mesa/drivers/dri/i915/intel_regions.c | 4 ++--
 src/mesa/drivers/dri/i915/intel_regions.h | 2 +-
 src/mesa/drivers/dri/i915/intel_screen.c  | 2 +-
 src/mesa/drivers/dri/i965/intel_regions.c | 4 ++--
 src/mesa/drivers/dri/i965/intel_regions.h | 1 +
 src/mesa/drivers/dri/i965/intel_screen.c  | 2 +-
 6 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/mesa/drivers/dri/i915/intel_regions.c b/src/mesa/drivers/dri/i915/intel_regions.c
index 44f7030..9f5b89e 100644
--- a/src/mesa/drivers/dri/i915/intel_regions.c
+++ b/src/mesa/drivers/dri/i915/intel_regions.c
@@ -209,6 +209,7 @@ struct intel_region *
 intel_region_alloc_for_fd(struct intel_screen *screen,
                           GLuint cpp,
                           GLuint width, GLuint height, GLuint pitch,
+                          GLuint size,
                           int fd, const char *name)
 {
    struct intel_region *region;
@@ -216,8 +217,7 @@ intel_region_alloc_for_fd(struct intel_screen *screen,
    int ret;
    uint32_t bit_6_swizzle, tiling;
 
-   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr,
-                                               fd, height * pitch);
+   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr, fd, size);
    if (buffer == NULL)
       return NULL;
    ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
diff --git a/src/mesa/drivers/dri/i915/intel_regions.h b/src/mesa/drivers/dri/i915/intel_regions.h
index 5c612a9..6bc4a42 100644
--- a/src/mesa/drivers/dri/i915/intel_regions.h
+++ b/src/mesa/drivers/dri/i915/intel_regions.h
@@ -91,7 +91,7 @@ struct intel_region *
 intel_region_alloc_for_fd(struct intel_screen *screen,
                           GLuint cpp,
                           GLuint width, GLuint height, GLuint pitch,
-                          int fd, const char *name);
+                          GLuint size, int fd, const char *name);
 
 bool
 intel_region_flink(struct intel_region *region, uint32_t *name);
diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index 3f54752..085e894 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -653,7 +653,7 @@ intel_create_image_from_fds(__DRIscreen *screen,
       return NULL;
 
    image->region = intel_region_alloc_for_fd(intelScreen,
-                                             1, width, height,
+                                             1, width, height, height * strides[0],
                                              strides[0], fds[0], "image");
    if (image->region == NULL) {
       free(image);
diff --git a/src/mesa/drivers/dri/i965/intel_regions.c b/src/mesa/drivers/dri/i965/intel_regions.c
index a6b80fd..3920f4f 100644
--- a/src/mesa/drivers/dri/i965/intel_regions.c
+++ b/src/mesa/drivers/dri/i965/intel_regions.c
@@ -209,6 +209,7 @@ struct intel_region *
 intel_region_alloc_for_fd(struct intel_screen *screen,
                           GLuint cpp,
                           GLuint width, GLuint height, GLuint pitch,
+                          GLuint size,
                           int fd, const char *name)
 {
    struct intel_region *region;
@@ -216,8 +217,7 @@ intel_region_alloc_for_fd(struct intel_screen *screen,
    int ret;
    uint32_t bit_6_swizzle, tiling;
 
-   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr,
-                                               fd, height * pitch);
+   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr, fd, size);
    if (buffer == NULL)
       return NULL;
    ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
diff --git a/src/mesa/drivers/dri/i965/intel_regions.h b/src/mesa/drivers/dri/i965/intel_regions.h
index f08a113..05dfef3 100644
--- a/src/mesa/drivers/dri/i965/intel_regions.h
+++ b/src/mesa/drivers/dri/i965/intel_regions.h
@@ -92,6 +92,7 @@ struct intel_region *
 intel_region_alloc_for_fd(struct intel_screen *screen,
                           GLuint cpp,
                           GLuint width, GLuint height, GLuint pitch,
+                          GLuint size,
                           int fd, const char *name);
 
 bool
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index ce8124b..b89b1a5 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -718,7 +718,7 @@ intel_create_image_from_fds(__DRIscreen *screen,
       return NULL;
 
    image->region = intel_region_alloc_for_fd(intelScreen,
-                                             1, width, height,
+                                             1, width, height, height * strides[0],
                                              strides[0], fds[0], "image");
    if (image->region == NULL) {
       free(image);
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 4/8] Define __DRI_IMAGE_FORMAT_SARGB8
  2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
                   ` (2 preceding siblings ...)
  2013-11-05  2:23 ` [PATCH 3/8] dri/intel: Add explicit size parameter to intel_region_alloc_for_fd Keith Packard
@ 2013-11-05  2:23 ` Keith Packard
  2013-11-05  2:23 ` [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_* Keith Packard
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-05  2:23 UTC (permalink / raw)
  To: mesa3d-dev; +Cc: dri-devel

This format will be used by the i965 driver

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 include/GL/internal/dri_interface.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 48993b9..907aeca 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -996,6 +996,7 @@ struct __DRIdri2ExtensionRec {
 #define __DRI_IMAGE_FORMAT_NONE         0x1008
 #define __DRI_IMAGE_FORMAT_XRGB2101010  0x1009
 #define __DRI_IMAGE_FORMAT_ARGB2101010  0x100a
+#define __DRI_IMAGE_FORMAT_SARGB8       0x100b
 
 #define __DRI_IMAGE_USE_SHARE		0x0001
 #define __DRI_IMAGE_USE_SCANOUT		0x0002
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_*
  2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
                   ` (3 preceding siblings ...)
  2013-11-05  2:23 ` [PATCH 4/8] Define __DRI_IMAGE_FORMAT_SARGB8 Keith Packard
@ 2013-11-05  2:23 ` Keith Packard
  2013-11-05  3:01   ` Jordan Justen
  2013-11-05 22:35   ` Kristian Høgsberg
  2013-11-05  2:23 ` [PATCH 6/8] dri/i915, dri/i965: Use driGLFormatToImageFormat and driImageFormatToGLFormat Keith Packard
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-05  2:23 UTC (permalink / raw)
  To: mesa3d-dev; +Cc: dri-devel

The __DRI_IMAGE_FORMAT codes are used by the image extension, drivers need to
be able to translate between them. Instead of duplicating this translation in
each driver, create a shared version.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 src/mesa/drivers/dri/common/dri_util.c | 62 ++++++++++++++++++++++++++++++++++
 src/mesa/drivers/dri/common/dri_util.h |  6 ++++
 2 files changed, 68 insertions(+)

diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index 95c8b41..76c8ae5 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -792,3 +792,65 @@ driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv)
       assert(fb->Height == dPriv->h);
    }
 }
+
+uint32_t
+driGLFormatToImageFormat(gl_format format)
+{
+   switch (format) {
+   case MESA_FORMAT_RGB565:
+      return __DRI_IMAGE_FORMAT_RGB565;
+   case MESA_FORMAT_XRGB8888:
+      return __DRI_IMAGE_FORMAT_XRGB8888;
+   case MESA_FORMAT_ARGB2101010:
+      return __DRI_IMAGE_FORMAT_ARGB2101010;
+   case MESA_FORMAT_XRGB2101010_UNORM:
+      return __DRI_IMAGE_FORMAT_XRGB2101010;
+   case MESA_FORMAT_ARGB8888:
+      return __DRI_IMAGE_FORMAT_ARGB8888;
+   case MESA_FORMAT_RGBA8888_REV:
+      return __DRI_IMAGE_FORMAT_ABGR8888;
+   case MESA_FORMAT_RGBX8888_REV:
+      return __DRI_IMAGE_FORMAT_XBGR8888;
+   case MESA_FORMAT_R8:
+      return __DRI_IMAGE_FORMAT_R8;
+   case MESA_FORMAT_GR88:
+      return __DRI_IMAGE_FORMAT_GR88;
+   case MESA_FORMAT_NONE:
+      return __DRI_IMAGE_FORMAT_NONE;
+   case MESA_FORMAT_SARGB8:
+      return __DRI_IMAGE_FORMAT_SARGB8;
+   default:
+      return 0;
+   }
+}
+
+gl_format
+driImageFormatToGLFormat(uint32_t image_format)
+{
+   switch (image_format) {
+   case __DRI_IMAGE_FORMAT_RGB565:
+      return MESA_FORMAT_RGB565;
+   case __DRI_IMAGE_FORMAT_XRGB8888:
+      return MESA_FORMAT_XRGB8888;
+   case __DRI_IMAGE_FORMAT_ARGB2101010:
+      return MESA_FORMAT_ARGB2101010;
+   case __DRI_IMAGE_FORMAT_XRGB2101010:
+      return MESA_FORMAT_XRGB2101010_UNORM;
+   case __DRI_IMAGE_FORMAT_ARGB8888:
+      return MESA_FORMAT_ARGB8888;
+   case __DRI_IMAGE_FORMAT_ABGR8888:
+      return MESA_FORMAT_RGBA8888_REV;
+   case __DRI_IMAGE_FORMAT_XBGR8888:
+      return MESA_FORMAT_RGBX8888_REV;
+   case __DRI_IMAGE_FORMAT_R8:
+      return MESA_FORMAT_R8;
+   case __DRI_IMAGE_FORMAT_GR88:
+      return MESA_FORMAT_GR88;
+   case __DRI_IMAGE_FORMAT_SARGB8:
+      return MESA_FORMAT_SARGB8;
+   case __DRI_IMAGE_FORMAT_NONE:
+      return MESA_FORMAT_NONE;
+   default:
+      return MESA_FORMAT_NONE;
+   }
+}
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index 5b56061..fd40769 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -271,6 +271,12 @@ struct __DRIdrawableRec {
     } dri2;
 };
 
+extern uint32_t
+driGLFormatToImageFormat(gl_format format);
+
+extern gl_format
+driImageFormatToGLFormat(uint32_t image_format);
+
 extern void
 dri2InvalidateDrawable(__DRIdrawable *drawable);
 
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 6/8] dri/i915, dri/i965: Use driGLFormatToImageFormat and driImageFormatToGLFormat
  2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
                   ` (4 preceding siblings ...)
  2013-11-05  2:23 ` [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_* Keith Packard
@ 2013-11-05  2:23 ` Keith Packard
  2013-11-05 22:37   ` [PATCH 6/8] dri/i915,dri/i965: " Kristian Høgsberg
  2013-11-05  2:23 ` [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension Keith Packard
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 36+ messages in thread
From: Keith Packard @ 2013-11-05  2:23 UTC (permalink / raw)
  To: mesa3d-dev; +Cc: dri-devel

Remove private versions of these functions

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 src/mesa/drivers/dri/i915/intel_screen.c | 53 ++-------------------------
 src/mesa/drivers/dri/i965/intel_screen.c | 63 ++------------------------------
 2 files changed, 8 insertions(+), 108 deletions(-)

diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index 085e894..12113c7 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -244,32 +244,8 @@ intel_allocate_image(int dri_format, void *loaderPrivate)
     image->dri_format = dri_format;
     image->offset = 0;
 
-    switch (dri_format) {
-    case __DRI_IMAGE_FORMAT_RGB565:
-       image->format = MESA_FORMAT_RGB565;
-       break;
-    case __DRI_IMAGE_FORMAT_XRGB8888:
-       image->format = MESA_FORMAT_XRGB8888;
-       break;
-    case __DRI_IMAGE_FORMAT_ARGB8888:
-       image->format = MESA_FORMAT_ARGB8888;
-       break;
-    case __DRI_IMAGE_FORMAT_ABGR8888:
-       image->format = MESA_FORMAT_RGBA8888_REV;
-       break;
-    case __DRI_IMAGE_FORMAT_XBGR8888:
-       image->format = MESA_FORMAT_RGBX8888_REV;
-       break;
-    case __DRI_IMAGE_FORMAT_R8:
-       image->format = MESA_FORMAT_R8;
-       break;
-    case __DRI_IMAGE_FORMAT_GR88:
-       image->format = MESA_FORMAT_GR88;
-       break;
-    case __DRI_IMAGE_FORMAT_NONE:
-       image->format = MESA_FORMAT_NONE;
-       break;
-    default:
+    image->format = driImageFormatToGLFormat(dri_format);
+    if (image->format == 0) {
        free(image);
        return NULL;
     }
@@ -318,27 +294,6 @@ intel_setup_image_from_dimensions(__DRIimage *image)
    image->tile_y = 0;
 }
 
-static inline uint32_t
-intel_dri_format(GLuint format)
-{
-   switch (format) {
-   case MESA_FORMAT_RGB565:
-      return __DRI_IMAGE_FORMAT_RGB565;
-   case MESA_FORMAT_XRGB8888:
-      return __DRI_IMAGE_FORMAT_XRGB8888;
-   case MESA_FORMAT_ARGB8888:
-      return __DRI_IMAGE_FORMAT_ARGB8888;
-   case MESA_FORMAT_RGBA8888_REV:
-      return __DRI_IMAGE_FORMAT_ABGR8888;
-   case MESA_FORMAT_R8:
-      return __DRI_IMAGE_FORMAT_R8;
-   case MESA_FORMAT_RG88:
-      return __DRI_IMAGE_FORMAT_GR88;
-   }
-
-   return MESA_FORMAT_NONE;
-}
-
 static __DRIimage *
 intel_create_image_from_name(__DRIscreen *screen,
 			     int width, int height, int format,
@@ -396,7 +351,7 @@ intel_create_image_from_renderbuffer(__DRIcontext *context,
    image->data = loaderPrivate;
    intel_region_reference(&image->region, irb->mt->region);
    intel_setup_image_from_dimensions(image);
-   image->dri_format = intel_dri_format(image->format);
+   image->dri_format = driGLFormatToImageFormat(image->format);
 
    rb->NeedsFinishRenderTexture = true;
    return image;
@@ -450,7 +405,7 @@ intel_create_image_from_texture(__DRIcontext *context, int target,
    image->format = obj->Image[face][level]->TexFormat;
    image->data = loaderPrivate;
    intel_setup_image_from_mipmap_tree(intel, image, iobj->mt, level, zoffset);
-   image->dri_format = intel_dri_format(image->format);
+   image->dri_format = driGLFormatToImageFormat(image->format);
    if (image->dri_format == MESA_FORMAT_NONE) {
       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
       free(image);
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index b89b1a5..f9339c1 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -298,38 +298,8 @@ intel_allocate_image(int dri_format, void *loaderPrivate)
     image->dri_format = dri_format;
     image->offset = 0;
 
-    switch (dri_format) {
-    case __DRI_IMAGE_FORMAT_RGB565:
-       image->format = MESA_FORMAT_RGB565;
-       break;
-    case __DRI_IMAGE_FORMAT_XRGB8888:
-       image->format = MESA_FORMAT_XRGB8888;
-       break;
-    case __DRI_IMAGE_FORMAT_ARGB2101010:
-       image->format = MESA_FORMAT_ARGB2101010;
-       break;
-    case __DRI_IMAGE_FORMAT_XRGB2101010:
-       image->format = MESA_FORMAT_XRGB2101010_UNORM;
-       break;
-    case __DRI_IMAGE_FORMAT_ARGB8888:
-       image->format = MESA_FORMAT_ARGB8888;
-       break;
-    case __DRI_IMAGE_FORMAT_ABGR8888:
-       image->format = MESA_FORMAT_RGBA8888_REV;
-       break;
-    case __DRI_IMAGE_FORMAT_XBGR8888:
-       image->format = MESA_FORMAT_RGBX8888_REV;
-       break;
-    case __DRI_IMAGE_FORMAT_R8:
-       image->format = MESA_FORMAT_R8;
-       break;
-    case __DRI_IMAGE_FORMAT_GR88:
-       image->format = MESA_FORMAT_GR88;
-       break;
-    case __DRI_IMAGE_FORMAT_NONE:
-       image->format = MESA_FORMAT_NONE;
-       break;
-    default:
+    image->format = driImageFormatToGLFormat(dri_format);
+    if (image->format == 0) {
        free(image);
        return NULL;
     }
@@ -381,31 +351,6 @@ intel_setup_image_from_dimensions(__DRIimage *image)
    image->has_depthstencil = false;
 }
 
-static inline uint32_t
-intel_dri_format(GLuint format)
-{
-   switch (format) {
-   case MESA_FORMAT_RGB565:
-      return __DRI_IMAGE_FORMAT_RGB565;
-   case MESA_FORMAT_XRGB8888:
-      return __DRI_IMAGE_FORMAT_XRGB8888;
-   case MESA_FORMAT_ARGB8888:
-      return __DRI_IMAGE_FORMAT_ARGB8888;
-   case MESA_FORMAT_RGBA8888_REV:
-      return __DRI_IMAGE_FORMAT_ABGR8888;
-   case MESA_FORMAT_R8:
-      return __DRI_IMAGE_FORMAT_R8;
-   case MESA_FORMAT_RG88:
-      return __DRI_IMAGE_FORMAT_GR88;
-   case MESA_FORMAT_XRGB2101010_UNORM:
-      return __DRI_IMAGE_FORMAT_XRGB2101010;
-   case MESA_FORMAT_ARGB2101010:
-      return __DRI_IMAGE_FORMAT_ARGB2101010;
-   }
-
-   return MESA_FORMAT_NONE;
-}
-
 static __DRIimage *
 intel_create_image_from_name(__DRIscreen *screen,
 			     int width, int height, int format,
@@ -464,7 +409,7 @@ intel_create_image_from_renderbuffer(__DRIcontext *context,
    image->data = loaderPrivate;
    intel_region_reference(&image->region, irb->mt->region);
    intel_setup_image_from_dimensions(image);
-   image->dri_format = intel_dri_format(image->format);
+   image->dri_format = driGLFormatToImageFormat(image->format);
    image->has_depthstencil = irb->mt->stencil_mt? true : false;
 
    rb->NeedsFinishRenderTexture = true;
@@ -519,7 +464,7 @@ intel_create_image_from_texture(__DRIcontext *context, int target,
    image->format = obj->Image[face][level]->TexFormat;
    image->data = loaderPrivate;
    intel_setup_image_from_mipmap_tree(brw, image, iobj->mt, level, zoffset);
-   image->dri_format = intel_dri_format(image->format);
+   image->dri_format = driGLFormatToImageFormat(image->format);
    image->has_depthstencil = iobj->mt->stencil_mt? true : false;
    if (image->dri_format == MESA_FORMAT_NONE) {
       *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
                   ` (5 preceding siblings ...)
  2013-11-05  2:23 ` [PATCH 6/8] dri/i915, dri/i965: Use driGLFormatToImageFormat and driImageFormatToGLFormat Keith Packard
@ 2013-11-05  2:23 ` Keith Packard
  2013-11-05 20:05   ` Eric Anholt
                     ` (2 more replies)
  2013-11-05  2:23 ` [PATCH 8/8] Add DRI3+Present loader Keith Packard
  2013-11-05 16:40 ` [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
  8 siblings, 3 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-05  2:23 UTC (permalink / raw)
  To: mesa3d-dev; +Cc: dri-devel

These provide an interface between the driver and the loader to allocate
color buffers through the DRIimage extension interface rather than through a
loader-specific extension (as is used by DRI2, for instance).

The driver uses the loader 'getBuffers' interface to allocate color buffers.

The loader uses the createNewScreen2, createNewDrawable, createNewContext,
getAPIMask and createContextAttribs APIS (mostly shared with DRI2).

This interface will work with the DRI3 loader, and should also work with GBM
and other loaders so that drivers need not be customized for each new loader
interface, as long as they provide this image interface.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 include/GL/internal/dri_interface.h           | 112 +++++++++++++++++++++++++
 src/mesa/drivers/dri/common/dri_util.c        | 113 +++++++++++++++++++++++++
 src/mesa/drivers/dri/common/dri_util.h        |   6 ++
 src/mesa/drivers/dri/i915/intel_context.c     | 111 ++++++++++++++++++++++++-
 src/mesa/drivers/dri/i915/intel_mipmap_tree.c |  33 ++++++++
 src/mesa/drivers/dri/i915/intel_mipmap_tree.h |   8 ++
 src/mesa/drivers/dri/i915/intel_screen.c      |   1 +
 src/mesa/drivers/dri/i965/brw_context.c       | 114 ++++++++++++++++++++++++--
 src/mesa/drivers/dri/i965/brw_context.h       |  16 ++--
 src/mesa/drivers/dri/i965/intel_mipmap_tree.c |  61 ++++++++++++++
 src/mesa/drivers/dri/i965/intel_mipmap_tree.h |   8 ++
 src/mesa/drivers/dri/i965/intel_screen.c      |   5 +-
 12 files changed, 568 insertions(+), 20 deletions(-)

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 907aeca..8fc1fa6 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -86,6 +86,10 @@ typedef struct __DRIdri2LoaderExtensionRec	__DRIdri2LoaderExtension;
 typedef struct __DRI2flushExtensionRec	__DRI2flushExtension;
 typedef struct __DRI2throttleExtensionRec	__DRI2throttleExtension;
 
+
+typedef struct __DRIimageLoaderExtensionRec     __DRIimageLoaderExtension;
+typedef struct __DRIimageDriverExtensionRec     __DRIimageDriverExtension;
+
 /*@}*/
 
 
@@ -1288,4 +1292,112 @@ typedef struct __DRIDriverVtableExtensionRec {
     const struct __DriverAPIRec *vtable;
 } __DRIDriverVtableExtension;
 
+/**
+ * Image Loader extension. Drivers use this to allocate color buffers
+ */
+
+#define __DRI_DRIVER_EXTENSIONS "__driDriverExtensions"
+
+enum __DRIimageBufferMask {
+   __DRI_IMAGE_BUFFER_BACK = (1 << 0),
+   __DRI_IMAGE_BUFFER_FRONT = (1 << 1)
+};
+
+struct __DRIimageList {
+   __DRIimage *back;
+   __DRIimage *front;
+};
+
+#define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER"
+#define __DRI_IMAGE_LOADER_VERSION 1
+
+struct __DRIimageLoaderExtensionRec {
+    __DRIextension base;
+
+   /**
+    * Allocate color buffers.
+    *
+    * \param driDrawable
+    * \param width              Width of allocated buffers
+    * \param height             Height of allocated buffers
+    * \param format             one of __DRI_IMAGE_FORMAT_*
+    * \param stamp              Address of variable to be updated when
+    *                           getBuffers must be called again
+    * \param loaderPrivate      The loaderPrivate for driDrawable
+    * \param buffer_mask        Set of buffers to allocate
+    * \param buffers            Returned buffers
+    */
+   int (*getBuffers)(__DRIdrawable *driDrawable,
+                     int *width, int *height,
+                     unsigned int format,
+                     uint32_t *stamp,
+                     void *loaderPrivate,
+                     uint32_t buffer_mask,
+                     struct __DRIimageList *buffers);
+
+    /**
+     * Flush pending front-buffer rendering
+     *
+     * Any rendering that has been performed to the
+     * fake front will be flushed to the front
+     *
+     * \param driDrawable    Drawable whose front-buffer is to be flushed
+     * \param loaderPrivate  Loader's private data that was previously passed
+     *                       into __DRIdri2ExtensionRec::createNewDrawable
+     */
+    void (*flushFrontBuffer)(__DRIdrawable *driDrawable, void *loaderPrivate);
+};
+
+/**
+ * DRI extension.
+ */
+
+//struct gl_context;
+//struct dd_function_table;
+
+typedef __DRIscreen *
+(*__DRIcreateNewScreen2)(int screen, int fd,
+                         const __DRIextension **extensions,
+                         const __DRIextension **driver_extensions,
+                         const __DRIconfig ***driver_configs,
+                         void *loaderPrivate);
+
+typedef __DRIdrawable *
+(*__DRIcreateNewDrawable)(__DRIscreen *screen,
+                          const __DRIconfig *config,
+                          void *loaderPrivate);
+
+typedef __DRIcontext *
+(*__DRIcreateNewContext)(__DRIscreen *screen,
+                         const __DRIconfig *config,
+                         __DRIcontext *shared,
+                         void *loaderPrivate);
+
+typedef __DRIcontext *
+(*__DRIcreateContextAttribs)(__DRIscreen *screen,
+                             int api,
+                             const __DRIconfig *config,
+                             __DRIcontext *shared,
+                             unsigned num_attribs,
+                             const uint32_t *attribs,
+                             unsigned *error,
+                             void *loaderPrivate);
+
+typedef unsigned int
+(*__DRIgetAPIMask)(__DRIscreen *screen);
+
+#define __DRI_IMAGE_DRIVER           "DRI_IMAGE_DRIVER"
+#define __DRI_IMAGE_DRIVER_VERSION   1
+
+struct __DRIimageDriverExtensionRec {
+   __DRIextension               base;
+
+   /* Common DRI functions, shared with DRI2 */
+   __DRIcreateNewScreen2        createNewScreen2;
+   __DRIcreateNewDrawable       createNewDrawable;
+   __DRIcreateNewContext        createNewContext;
+   __DRIcreateContextAttribs    createContextAttribs;
+   __DRIgetAPIMask              getAPIMask;
+};
+
 #endif
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index 76c8ae5..d8cb7f6 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -854,3 +854,116 @@ driImageFormatToGLFormat(uint32_t image_format)
       return MESA_FORMAT_NONE;
    }
 }
+
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+PUBLIC const char __imageConfigOptions[] =
+   DRI_CONF_BEGIN
+      DRI_CONF_SECTION_PERFORMANCE
+         DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
+      DRI_CONF_SECTION_END
+   DRI_CONF_END;
+
+static void
+setup_image_loader_extensions(__DRIscreen *psp,
+                              const __DRIextension *const*extensions)
+{
+    int i;
+
+    for (i = 0; extensions[i]; i++) {
+        if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0)
+           psp->image.loader = (__DRIimageLoaderExtension *) extensions[i];
+    }
+}
+
+static __DRIscreen *
+image_create_new_screen_2(int scrn, int fd,
+                          const __DRIextension **extensions,
+                          const __DRIextension **driver_extensions,
+                          const __DRIconfig ***driver_configs, void *data)
+{
+    static const __DRIextension *emptyExtensionList[] = { NULL };
+    __DRIscreen *psp;
+    drmVersionPtr version;
+
+    psp = calloc(1, sizeof(*psp));
+    if (!psp)
+	return NULL;
+
+    /* By default, use the global driDriverAPI symbol (non-megadrivers). */
+    psp->driver = globalDriverAPI;
+
+    /* If the driver exposes its vtable through its extensions list
+     * (megadrivers), use that instead.
+     */
+    if (driver_extensions) {
+       for (int i = 0; driver_extensions[i]; i++) {
+          if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) {
+             psp->driver =
+                ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable;
+          }
+       }
+    }
+
+    setupLoaderExtensions(psp, extensions);
+    setup_image_loader_extensions(psp, extensions);
+
+    version = drmGetVersion(fd);
+    if (version) {
+	psp->drm_version.major = version->version_major;
+	psp->drm_version.minor = version->version_minor;
+	psp->drm_version.patch = version->version_patchlevel;
+	drmFreeVersion(version);
+    }
+
+    psp->loaderPrivate = data;
+
+    psp->extensions = emptyExtensionList;
+    psp->fd = fd;
+    psp->myNum = scrn;
+
+    psp->api_mask = (1 << __DRI_API_OPENGL);
+
+    *driver_configs = psp->driver->InitScreen(psp);
+    if (*driver_configs == NULL) {
+	free(psp);
+	return NULL;
+    }
+
+    driParseOptionInfo(&psp->optionInfo, __imageConfigOptions);
+    driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "image");
+
+    return psp;
+}
+
+
+/** Image driver interface */
+const __DRIimageDriverExtension driImageDriverExtension = {
+    .base = { __DRI_IMAGE_DRIVER, __DRI_IMAGE_DRIVER_VERSION },
+
+    .createNewScreen2           = image_create_new_screen_2,
+    .createNewDrawable          = driCreateNewDrawable,
+    .createNewContext           = driCreateNewContext,
+    .getAPIMask                 = driGetAPIMask,
+    .createContextAttribs       = driCreateContextAttribs,
+};
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index fd40769..6f5cd87 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -174,6 +174,10 @@ struct __DRIscreenRec {
 	__DRIuseInvalidateExtension *useInvalidate;
     } dri2;
 
+    struct {
+        __DRIimageLoaderExtension *loader;
+    } image;
+
     driOptionCache optionInfo;
     driOptionCache optionCache;
 
@@ -283,4 +287,6 @@ dri2InvalidateDrawable(__DRIdrawable *drawable);
 extern void
 driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv);
 
+extern const __DRIimageDriverExtension driImageDriverExtension;
+
 #endif /* _DRI_UTIL_H_ */
diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
index 1798bc7..8d369ff 100644
--- a/src/mesa/drivers/dri/i915/intel_context.c
+++ b/src/mesa/drivers/dri/i915/intel_context.c
@@ -91,6 +91,8 @@ intelGetString(struct gl_context * ctx, GLenum name)
    }
 }
 
+#define flushFront(screen)      ((screen)->image.loader ? (screen)->image.loader->flushFrontBuffer : (screen)->dri2.loader->flushFrontBuffer)
+
 static void
 intel_flush_front(struct gl_context *ctx)
 {
@@ -100,11 +102,10 @@ intel_flush_front(struct gl_context *ctx)
     __DRIscreen *const screen = intel->intelScreen->driScrnPriv;
 
     if (intel->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
-      if (screen->dri2.loader->flushFrontBuffer != NULL &&
+      if (flushFront(screen) && 
           driDrawable &&
           driDrawable->loaderPrivate) {
-         screen->dri2.loader->flushFrontBuffer(driDrawable,
-                                               driDrawable->loaderPrivate);
+         flushFront(screen)(driDrawable, driDrawable->loaderPrivate);
 
 	 /* We set the dirty bit in intel_prepare_render() if we're
 	  * front buffer rendering once we get there.
@@ -114,6 +115,9 @@ intel_flush_front(struct gl_context *ctx)
    }
 }
 
+static void
+intel_update_image_buffers(struct intel_context *intel, __DRIdrawable *drawable);
+
 static unsigned
 intel_bits_per_pixel(const struct intel_renderbuffer *rb)
 {
@@ -194,7 +198,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
    if (unlikely(INTEL_DEBUG & DEBUG_DRI))
       fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
 
-   intel_update_dri2_buffers(intel, drawable);
+   if (screen->image.loader)
+      intel_update_image_buffers(intel, drawable);
+   else
+      intel_update_dri2_buffers(intel, drawable);
 
    driUpdateFramebufferSize(&intel->ctx, drawable);
 }
@@ -787,3 +794,99 @@ intel_process_dri2_buffer(struct intel_context *intel,
                                                  region);
    intel_region_release(&region);
 }
+
+/**
+ * \brief Query DRI Image loader to obtain a DRIdrawable's buffers.
+ *
+ * To determine which DRI buffers to request, examine the renderbuffers
+ * attached to the drawable's framebuffer. Then request the buffers with
+ * dri3
+ *
+ * This is called from intel_update_renderbuffers().
+ *
+ * \param drawable      Drawable whose buffers are queried.
+ * \param buffers       [out] List of buffers returned by DRI2 query.
+ * \param buffer_count  [out] Number of buffers returned.
+ *
+ * \see intel_update_renderbuffers()
+ */
+
+static void
+intel_update_image_buffer(struct intel_context *intel,
+                          __DRIdrawable *drawable,
+                          struct intel_renderbuffer *rb,
+                          __DRIimage *buffer,
+                          enum __DRIimageBufferMask buffer_type)
+{
+   struct intel_region *region = buffer->region;
+
+   if (!rb || !region)
+      return;
+
+   unsigned num_samples = rb->Base.Base.NumSamples;
+
+   if (rb->mt &&
+       rb->mt->region &&
+       rb->mt->region == region)
+      return;
+
+   intel_miptree_release(&rb->mt);
+   rb->mt = intel_miptree_create_for_image_buffer(intel,
+                                                  buffer_type,
+                                                  intel_rb_format(rb),
+                                                  num_samples,
+                                                  region);
+}
+
+
+static void
+intel_update_image_buffers(struct intel_context *intel, __DRIdrawable *drawable)
+{
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+   __DRIscreen *screen = intel->intelScreen->driScrnPriv;
+   struct intel_renderbuffer *front_rb;
+   struct intel_renderbuffer *back_rb;
+   struct __DRIimageList images;
+   unsigned int format;
+   uint32_t buffer_mask = 0;
+
+   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
+
+   if (back_rb)
+      format = intel_rb_format(back_rb);
+   else if (front_rb)
+      format = intel_rb_format(front_rb);
+   else
+      return;
+
+   if ((intel->is_front_buffer_rendering || intel->is_front_buffer_reading || !back_rb) && front_rb)
+      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
+
+   if (back_rb)
+      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
+
+   (*screen->image.loader->getBuffers) (drawable,
+                                        &drawable->w,
+                                        &drawable->h,
+                                        driGLFormatToImageFormat(format),
+                                        &drawable->dri2.stamp,
+                                        drawable->loaderPrivate,
+                                        buffer_mask,
+                                        &images);
+
+   if (images.front) {
+      assert(front_rb);
+      intel_update_image_buffer(intel,
+                                drawable,
+                                front_rb,
+                                images.front,
+                                __DRI_IMAGE_BUFFER_FRONT);
+   }
+   if (images.back)
+      intel_update_image_buffer(intel,
+                                drawable,
+                                back_rb,
+                                images.back,
+                                __DRI_IMAGE_BUFFER_BACK);
+}
diff --git a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
index 8432b6d..66a7a92 100644
--- a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
@@ -322,6 +322,39 @@ intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
    return mt;
 }
 
+/**
+ * For a singlesample image buffer, this simply wraps the given region with a miptree.
+ *
+ * For a multisample image buffer, this wraps the given region with
+ * a singlesample miptree, then creates a multisample miptree into which the
+ * singlesample miptree is embedded as a child.
+ */
+struct intel_mipmap_tree*
+intel_miptree_create_for_image_buffer(struct intel_context *intel,
+                                      enum __DRIimageBufferMask buffer_type,
+                                      gl_format format,
+                                      uint32_t num_samples,
+                                      struct intel_region *region)
+{
+   struct intel_mipmap_tree *mt = NULL;
+
+   /* Only the front and back buffers, which are color buffers, are allocated
+    * through the image loader.
+    */
+   assert(_mesa_get_format_base_format(format) == GL_RGB ||
+          _mesa_get_format_base_format(format) == GL_RGBA);
+
+   mt = intel_miptree_create_for_bo(intel,
+                                    region->bo,
+                                    format,
+                                    0,
+                                    region->width,
+                                    region->height,
+                                    region->pitch,
+                                    region->tiling);
+   return mt;
+}
+
 struct intel_mipmap_tree*
 intel_miptree_create_for_renderbuffer(struct intel_context *intel,
                                       gl_format format,
diff --git a/src/mesa/drivers/dri/i915/intel_mipmap_tree.h b/src/mesa/drivers/dri/i915/intel_mipmap_tree.h
index 1142af6..35cad6d 100644
--- a/src/mesa/drivers/dri/i915/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/i915/intel_mipmap_tree.h
@@ -32,6 +32,7 @@
 
 #include "intel_screen.h"
 #include "intel_regions.h"
+#include "GL/internal/dri_interface.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -258,6 +259,13 @@ intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
                                      gl_format format,
                                      struct intel_region *region);
 
+struct intel_mipmap_tree*
+intel_miptree_create_for_image_buffer(struct intel_context *intel,
+                                      enum __DRIimageBufferMask buffer_type,
+                                      gl_format format,
+                                      uint32_t num_samples,
+                                      struct intel_region *region);
+
 /**
  * Create a miptree appropriate as the storage for a non-texture renderbuffer.
  * The miptree has the following properties:
diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index 12113c7..38badec 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -1166,6 +1166,7 @@ static const struct __DRIDriverVtableExtensionRec i915_vtable = {
 /* This is the table of extensions that the loader will dlsym() for. */
 static const __DRIextension *i915_driver_extensions[] = {
     &driCoreExtension.base,
+    &driImageDriverExtension.base,
     &driDRI2Extension.base,
     &i915_vtable.base,
     &i915_config_options.base,
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 2557d10..f3bf67f 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -151,6 +151,8 @@ intelInvalidateState(struct gl_context * ctx, GLuint new_state)
    brw->NewGLState |= new_state;
 }
 
+#define flushFront(screen)      ((screen)->image.loader ? (screen)->image.loader->flushFrontBuffer : (screen)->dri2.loader->flushFrontBuffer)
+
 static void
 intel_flush_front(struct gl_context *ctx)
 {
@@ -160,8 +162,7 @@ intel_flush_front(struct gl_context *ctx)
    __DRIscreen *const screen = brw->intelScreen->driScrnPriv;
 
    if (brw->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
-      if (screen->dri2.loader->flushFrontBuffer != NULL &&
-          driDrawable &&
+      if (flushFront(screen) && driDrawable &&
           driDrawable->loaderPrivate) {
 
          /* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT.
@@ -174,8 +175,7 @@ intel_flush_front(struct gl_context *ctx)
          intel_resolve_for_dri2_flush(brw, driDrawable);
          intel_batchbuffer_flush(brw);
 
-         screen->dri2.loader->flushFrontBuffer(driDrawable,
-                                               driDrawable->loaderPrivate);
+         flushFront(screen)(driDrawable, driDrawable->loaderPrivate);
 
          /* We set the dirty bit in intel_prepare_render() if we're
           * front buffer rendering once we get there.
@@ -549,7 +549,7 @@ brw_process_driconf_options(struct brw_context *brw)
       driQueryOptionb(options, "disable_glsl_line_continuations");
 }
 
-bool
+GLboolean
 brwCreateContext(gl_api api,
 	         const struct gl_config *mesaVis,
 		 __DRIcontext *driContextPriv,
@@ -979,6 +979,9 @@ intel_process_dri2_buffer(struct brw_context *brw,
                           const char *buffer_name);
 
 static void
+intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable);
+
+static void
 intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable)
 {
    struct gl_framebuffer *fb = drawable->driverPrivate;
@@ -1038,6 +1041,7 @@ void
 intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
 {
    struct brw_context *brw = context->driverPrivate;
+   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
 
    /* Set this up front, so that in case our buffers get invalidated
     * while we're getting new buffers, we don't clobber the stamp and
@@ -1047,7 +1051,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
    if (unlikely(INTEL_DEBUG & DEBUG_DRI))
       fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
 
-   intel_update_dri2_buffers(brw, drawable);
+   if (screen->image.loader)
+      intel_update_image_buffers(brw, drawable);
+   else
+      intel_update_dri2_buffers(brw, drawable);
 
    driUpdateFramebufferSize(&brw->ctx, drawable);
 }
@@ -1253,3 +1260,98 @@ intel_process_dri2_buffer(struct brw_context *brw,
                                                  region);
    intel_region_release(&region);
 }
+
+/**
+ * \brief Query DRI image loader to obtain a DRIdrawable's buffers.
+ *
+ * To determine which DRI buffers to request, examine the renderbuffers
+ * attached to the drawable's framebuffer. Then request the buffers from
+ * the image loader
+ *
+ * This is called from intel_update_renderbuffers().
+ *
+ * \param drawable      Drawable whose buffers are queried.
+ * \param buffers       [out] List of buffers returned by DRI2 query.
+ * \param buffer_count  [out] Number of buffers returned.
+ *
+ * \see intel_update_renderbuffers()
+ */
+
+static void
+intel_update_image_buffer(struct brw_context *intel,
+                          __DRIdrawable *drawable,
+                          struct intel_renderbuffer *rb,
+                          __DRIimage *buffer,
+                          enum __DRIimageBufferMask buffer_type)
+{
+   struct intel_region *region = buffer->region;
+
+   if (!rb || !region)
+      return;
+
+   unsigned num_samples = rb->Base.Base.NumSamples;
+
+   if (rb->mt &&
+       rb->mt->region &&
+       rb->mt->region == region)
+      return;
+
+   intel_miptree_release(&rb->mt);
+   rb->mt = intel_miptree_create_for_image_buffer(intel,
+                                                  buffer_type,
+                                                  intel_rb_format(rb),
+                                                  num_samples,
+                                                  region);
+}
+
+static void
+intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
+{
+   struct gl_framebuffer *fb = drawable->driverPrivate;
+   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
+   struct intel_renderbuffer *front_rb;
+   struct intel_renderbuffer *back_rb;
+   struct __DRIimageList images;
+   unsigned int format;
+   uint32_t buffer_mask = 0;
+
+   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
+   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
+
+   if (back_rb)
+      format = intel_rb_format(back_rb);
+   else if (front_rb)
+      format = intel_rb_format(front_rb);
+   else
+      return;
+
+   if ((brw->is_front_buffer_rendering || brw->is_front_buffer_reading || !back_rb) && front_rb)
+      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
+
+   if (back_rb)
+      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
+
+   (*screen->image.loader->getBuffers) (drawable,
+                                        &drawable->w,
+                                        &drawable->h,
+                                        driGLFormatToImageFormat(format),
+                                        &drawable->dri2.stamp,
+                                        drawable->loaderPrivate,
+                                        buffer_mask,
+                                        &images);
+
+   if (images.front) {
+      assert(front_rb);
+      intel_update_image_buffer(brw,
+                                drawable,
+                                front_rb,
+                                images.front,
+                                __DRI_IMAGE_BUFFER_FRONT);
+   }
+   if (images.back)
+      intel_update_image_buffer(brw,
+                                drawable,
+                                back_rb,
+                                images.back,
+                                __DRI_IMAGE_BUFFER_BACK);
+}
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index bec4d6b..1ecbfb7 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -1477,14 +1477,14 @@ void intel_prepare_render(struct brw_context *brw);
 void intel_resolve_for_dri2_flush(struct brw_context *brw,
                                   __DRIdrawable *drawable);
 
-bool brwCreateContext(gl_api api,
-		      const struct gl_config *mesaVis,
-		      __DRIcontext *driContextPriv,
-                      unsigned major_version,
-                      unsigned minor_version,
-                      uint32_t flags,
-                      unsigned *error,
-		      void *sharedContextPrivate);
+GLboolean brwCreateContext(gl_api api,
+                           const struct gl_config *mesaVis,
+                           __DRIcontext *driContextPriv,
+                           unsigned major_version,
+                           unsigned minor_version,
+                           uint32_t flags,
+                           unsigned *error,
+                           void *sharedContextPrivate);
 
 /*======================================================================
  * brw_misc_state.c
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index 2f5e04f..08dbe88 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -725,6 +725,67 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw,
    return multisample_mt;
 }
 
+/**
+ * For a singlesample image buffer, this simply wraps the given region with a miptree.
+ *
+ * For a multisample image buffer, this wraps the given region with
+ * a singlesample miptree, then creates a multisample miptree into which the
+ * singlesample miptree is embedded as a child.
+ */
+struct intel_mipmap_tree*
+intel_miptree_create_for_image_buffer(struct brw_context *intel,
+                                      enum __DRIimageBufferMask buffer_type,
+                                      gl_format format,
+                                      uint32_t num_samples,
+                                      struct intel_region *region)
+{
+   struct intel_mipmap_tree *singlesample_mt = NULL;
+   struct intel_mipmap_tree *multisample_mt = NULL;
+
+   /* Only the front and back buffers, which are color buffers, are allocated
+    * through the image loader.
+    */
+   assert(_mesa_get_format_base_format(format) == GL_RGB ||
+          _mesa_get_format_base_format(format) == GL_RGBA);
+
+   singlesample_mt = intel_miptree_create_for_bo(intel,
+                                                 region->bo,
+                                                 format,
+                                                 0,
+                                                 region->width,
+                                                 region->height,
+                                                 region->pitch,
+                                                 region->tiling);
+   if (!singlesample_mt)
+      return NULL;
+
+   intel_region_reference(&singlesample_mt->region, region);
+
+   if (num_samples == 0)
+      return singlesample_mt;
+
+   multisample_mt = intel_miptree_create_for_renderbuffer(intel,
+                                                          format,
+                                                          region->width,
+                                                          region->height,
+                                                          num_samples);
+   if (!multisample_mt) {
+      intel_miptree_release(&singlesample_mt);
+      return NULL;
+   }
+
+   multisample_mt->singlesample_mt = singlesample_mt;
+   multisample_mt->need_downsample = false;
+
+   intel_region_reference(&multisample_mt->region, region);
+
+   if (intel->is_front_buffer_rendering && buffer_type == __DRI_IMAGE_BUFFER_FRONT) {
+      intel_miptree_upsample(intel, multisample_mt);
+   }
+
+   return multisample_mt;
+}
+
 struct intel_mipmap_tree*
 intel_miptree_create_for_renderbuffer(struct brw_context *brw,
                                       gl_format format,
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
index d718125..8777a8c 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
@@ -32,6 +32,7 @@
 
 #include "intel_regions.h"
 #include "intel_resolve_map.h"
+#include <GL/internal/dri_interface.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -529,6 +530,13 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw,
                                      uint32_t num_samples,
                                      struct intel_region *region);
 
+struct intel_mipmap_tree*
+intel_miptree_create_for_image_buffer(struct brw_context *intel,
+                                     enum __DRIimageBufferMask buffer_type,
+                                     gl_format format,
+                                     uint32_t num_samples,
+                                     struct intel_region *region);
+
 /**
  * Create a miptree appropriate as the storage for a non-texture renderbuffer.
  * The miptree has the following properties:
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index f9339c1..7571921 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -1176,7 +1176,8 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
 {
    struct intel_screen *intelScreen;
 
-   if (psp->dri2.loader->base.version <= 2 ||
+   if (psp->image.loader) {
+   } else if (psp->dri2.loader->base.version <= 2 ||
        psp->dri2.loader->getBuffersWithFormat == NULL) {
       fprintf(stderr,
 	      "\nERROR!  DRI2 loader with getBuffersWithFormat() "
@@ -1264,7 +1265,6 @@ intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
    free(intelBuffer);
 }
 
-
 static const struct __DriverAPIRec brw_driver_api = {
    .InitScreen		 = intelInitScreen2,
    .DestroyScreen	 = intelDestroyScreen,
@@ -1285,6 +1285,7 @@ static const struct __DRIDriverVtableExtensionRec brw_vtable = {
 
 static const __DRIextension *brw_driver_extensions[] = {
     &driCoreExtension.base,
+    &driImageDriverExtension.base,
     &driDRI2Extension.base,
     &brw_vtable.base,
     &brw_config_options.base,
-- 
1.8.4.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 8/8] Add DRI3+Present loader
  2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
                   ` (6 preceding siblings ...)
  2013-11-05  2:23 ` [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension Keith Packard
@ 2013-11-05  2:23 ` Keith Packard
  2013-11-05 23:10   ` Eric Anholt
  2013-11-05 16:40 ` [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
  8 siblings, 1 reply; 36+ messages in thread
From: Keith Packard @ 2013-11-05  2:23 UTC (permalink / raw)
  To: mesa3d-dev; +Cc: dri-devel

Uses the __DRIimage loader interfaces.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 configure.ac          |   12 +-
 src/glx/Makefile.am   |    2 +
 src/glx/dri3_common.c |  146 +++++
 src/glx/dri3_glx.c    | 1722 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/glx/dri3_priv.h   |  199 ++++++
 src/glx/glxclient.h   |    2 +
 src/glx/glxext.c      |    6 +-
 7 files changed, 2085 insertions(+), 4 deletions(-)
 create mode 100644 src/glx/dri3_common.c
 create mode 100644 src/glx/dri3_glx.c
 create mode 100644 src/glx/dri3_priv.h

diff --git a/configure.ac b/configure.ac
index 0a25047..074368c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -38,6 +38,9 @@ LIBDRM_NVVIEUX_REQUIRED=2.4.33
 LIBDRM_NOUVEAU_REQUIRED="2.4.33 libdrm >= 2.4.41"
 LIBDRM_FREEDRENO_REQUIRED=2.4.39
 DRI2PROTO_REQUIRED=2.6
+DRI3PROTO_REQUIRED=1.0
+PRESENTPROTO_REQUIRED=1.0
+LIBUDEV_REQUIRED=151
 GLPROTO_REQUIRED=1.4.14
 LIBDRM_XORG_REQUIRED=2.4.24
 LIBKMS_XORG_REQUIRED=1.0.0
@@ -820,10 +823,13 @@ xyesno)
         fi
         PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= $DRI2PROTO_REQUIRED])
         GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV libdrm >= $LIBDRM_REQUIRED"
+        PKG_CHECK_MODULES([DRI3PROTO], [dri3proto >= $DRI3PROTO_REQUIRED])
+        PKG_CHECK_MODULES([PRESENTPROTO], [presentproto >= $PRESENTPROTO_REQUIRED])
+        PKG_CHECK_MODULES([LIBUDEV], [libudev >= $LIBUDEV_REQUIRED])
     fi
 
     # find the DRI deps for libGL
-    dri_modules="x11 xext xdamage xfixes x11-xcb xcb-glx >= 1.8.1 xcb-dri2 >= 1.8"
+    dri_modules="x11 xext xdamage xfixes x11-xcb xcb-glx >= 1.8.1 xcb-dri2 >= 1.8 xcb-dri3 xcb-present xcb-sync xshmfence"
 
     # add xf86vidmode if available
     PKG_CHECK_MODULES([XF86VIDMODE], [xxf86vm], HAVE_XF86VIDMODE=yes, HAVE_XF86VIDMODE=no)
@@ -833,8 +839,8 @@ xyesno)
 
     PKG_CHECK_MODULES([DRIGL], [$dri_modules])
     GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV $dri_modules"
-    X11_INCLUDES="$X11_INCLUDES $DRIGL_CFLAGS"
-    GL_LIB_DEPS="$DRIGL_LIBS"
+    X11_INCLUDES="$X11_INCLUDES $DRIGL_CFLAGS $LIBUDEV_CFLAGS"
+    GL_LIB_DEPS="$DRIGL_LIBS $LIBUDEV_LIBS"
 
     # need DRM libs, $PTHREAD_LIBS, etc.
     GL_LIB_DEPS="$GL_LIB_DEPS $LIBDRM_LIBS -lm $PTHREAD_LIBS $DLOPEN_LIBS"
diff --git a/src/glx/Makefile.am b/src/glx/Makefile.am
index f01709b..854025d 100644
--- a/src/glx/Makefile.am
+++ b/src/glx/Makefile.am
@@ -92,6 +92,8 @@ libglx_la_SOURCES = \
 	  glxhash.c \
 	  dri2_glx.c \
 	  dri2.c \
+          dri3_glx.c \
+          dri3_common.c \
 	  applegl_glx.c
 
 GL_LIBS = \
diff --git a/src/glx/dri3_common.c b/src/glx/dri3_common.c
new file mode 100644
index 0000000..c758f96
--- /dev/null
+++ b/src/glx/dri3_common.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * This code is derived from src/egl/drivers/dri2/common.c which
+ * carries the following copyright:
+ * 
+ * Copyright © 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Kristian Høgsberg <krh@bitplanet.net>
+ *    Benjamin Franzke <benjaminfranzke@googlemail.com>
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <GL/gl.h>
+#include "glapi.h"
+#include "glxclient.h"
+#include "xf86dri.h"
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include "xf86drm.h"
+#include "dri_common.h"
+#include "dri3_priv.h"
+
+#define DRIVER_MAP_DRI3_ONLY
+#include "pci_ids/pci_id_driver_map.h"
+
+#include <libudev.h>
+
+static struct udev_device *
+dri3_udev_device_new_from_fd(struct udev *udev, int fd)
+{
+   struct udev_device *device;
+   struct stat buf;
+
+   if (fstat(fd, &buf) < 0) {
+      ErrorMessageF("DRI3: failed to stat fd %d", fd);
+      return NULL;
+   }
+
+   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
+   if (device == NULL) {
+      ErrorMessageF("DRI3: could not create udev device for fd %d", fd);
+      return NULL;
+   }
+
+   return device;
+}
+
+char *
+dri3_get_driver_for_fd(int fd)
+{
+   struct udev *udev;
+   struct udev_device *device, *parent;
+   const char *pci_id;
+   char *driver = NULL;
+   int vendor_id, chip_id, i, j;
+
+   udev = udev_new();
+   device = dri3_udev_device_new_from_fd(udev, fd);
+   if (device == NULL)
+      return NULL;
+
+   parent = udev_device_get_parent(device);
+   if (parent == NULL) {
+      ErrorMessageF("DRI3: could not get parent device");
+      goto out;
+   }
+
+   pci_id = udev_device_get_property_value(parent, "PCI_ID");
+   if (pci_id == NULL ||
+       sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
+      ErrorMessageF("DRI3: malformed or no PCI ID");
+      goto out;
+   }
+
+   for (i = 0; driver_map[i].driver; i++) {
+      if (vendor_id != driver_map[i].vendor_id)
+         continue;
+      if (driver_map[i].num_chips_ids == -1) {
+         driver = strdup(driver_map[i].driver);
+         goto out;
+      }
+
+      for (j = 0; j < driver_map[i].num_chips_ids; j++)
+         if (driver_map[i].chip_ids[j] == chip_id) {
+            driver = strdup(driver_map[i].driver);
+            goto out;
+         }
+   }
+
+out:
+   udev_device_unref(device);
+   udev_unref(udev);
+
+   return driver;
+}
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
new file mode 100644
index 0000000..4021baa
--- /dev/null
+++ b/src/glx/dri3_glx.c
@@ -0,0 +1,1722 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * Portions of this code were adapted from dri2_glx.c which carries the
+ * following copyright:
+ *
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/Xlib-xcb.h>
+#include <X11/xshmfence.h>
+#include <xcb/xcb.h>
+#include <xcb/dri3.h>
+#include <xcb/present.h>
+#include <GL/gl.h>
+#include "glapi.h"
+#include "glxclient.h"
+#include "xf86dri.h"
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#include "xf86drm.h"
+#include "dri_common.h"
+#include "dri3_priv.h"
+
+static const struct glx_context_vtable dri3_context_vtable;
+
+static inline void
+dri3_fence_reset(xcb_connection_t *c, struct dri3_buffer *buffer) {
+   xshmfence_reset(buffer->shm_fence);
+}
+
+static inline void
+dri3_fence_set(struct dri3_buffer *buffer) {
+   xshmfence_trigger(buffer->shm_fence);
+}
+
+static inline void
+dri3_fence_trigger(xcb_connection_t *c, struct dri3_buffer *buffer) {
+   xcb_sync_trigger_fence(c, buffer->sync_fence);
+}
+
+static inline void
+dri3_fence_await(xcb_connection_t *c, struct dri3_buffer *buffer) {
+   xcb_flush(c);
+   xshmfence_await(buffer->shm_fence);
+}
+
+static inline Bool
+dri3_fence_triggered(struct dri3_buffer *buffer) {
+   return xshmfence_query(buffer->shm_fence);
+}
+
+static void
+dri3_destroy_context(struct glx_context *context)
+{
+   struct dri3_context *pcp = (struct dri3_context *) context;
+   struct dri3_screen *psc = (struct dri3_screen *) context->psc;
+
+   driReleaseDrawables(&pcp->base);
+
+   free((char *) context->extensions);
+
+   (*psc->core->destroyContext) (pcp->driContext);
+
+   free(pcp);
+}
+
+static Bool
+dri3_bind_context(struct glx_context *context, struct glx_context *old,
+		  GLXDrawable draw, GLXDrawable read)
+{
+   struct dri3_context *pcp = (struct dri3_context *) context;
+   struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
+   struct dri3_drawable *pdraw, *pread;
+
+   pdraw = (struct dri3_drawable *) driFetchDrawable(context, draw);
+   pread = (struct dri3_drawable *) driFetchDrawable(context, read);
+
+   driReleaseDrawables(&pcp->base);
+
+   if (pdraw == NULL || pread == NULL)
+      return GLXBadDrawable;
+
+   if (!(*psc->core->bindContext) (pcp->driContext,
+				   pdraw->driDrawable, pread->driDrawable))
+      return GLXBadContext;
+
+   return Success;
+}
+
+static void
+dri3_unbind_context(struct glx_context *context, struct glx_context *new)
+{
+   struct dri3_context *pcp = (struct dri3_context *) context;
+   struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
+
+   (*psc->core->unbindContext) (pcp->driContext);
+}
+
+static struct glx_context *
+dri3_create_context(struct glx_screen *base,
+		    struct glx_config *config_base,
+		    struct glx_context *shareList, int renderType)
+{
+   struct dri3_context *pcp, *pcp_shared;
+   struct dri3_screen *psc = (struct dri3_screen *) base;
+   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
+   __DRIcontext *shared = NULL;
+
+   if (shareList) {
+      /* If the shareList context is not a DRI3 context, we cannot possibly
+       * create a DRI3 context that shares it.
+       */
+      if (shareList->vtable->destroy != dri3_destroy_context) {
+	 return NULL;
+      }
+
+      pcp_shared = (struct dri3_context *) shareList;
+      shared = pcp_shared->driContext;
+   }
+
+   pcp = calloc(1, sizeof *pcp);
+   if (pcp == NULL)
+      return NULL;
+
+   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
+      free(pcp);
+      return NULL;
+   }
+
+   pcp->driContext =
+      (*psc->image_driver->createNewContext) (psc->driScreen,
+                                              config->driConfig, shared, pcp);
+
+   if (pcp->driContext == NULL) {
+      free(pcp);
+      return NULL;
+   }
+
+   pcp->base.vtable = &dri3_context_vtable;
+
+   return &pcp->base;
+}
+
+static struct glx_context *
+dri3_create_context_attribs(struct glx_screen *base,
+			    struct glx_config *config_base,
+			    struct glx_context *shareList,
+			    unsigned num_attribs,
+			    const uint32_t *attribs,
+			    unsigned *error)
+{
+   struct dri3_context *pcp = NULL;
+   struct dri3_context *pcp_shared = NULL;
+   struct dri3_screen *psc = (struct dri3_screen *) base;
+   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
+   __DRIcontext *shared = NULL;
+
+   uint32_t minor_ver = 1;
+   uint32_t major_ver = 2;
+   uint32_t flags = 0;
+   unsigned api;
+   int reset = __DRI_CTX_RESET_NO_NOTIFICATION;
+   uint32_t ctx_attribs[2 * 5];
+   unsigned num_ctx_attribs = 0;
+   uint32_t render_type;
+
+   /* Remap the GLX tokens to DRI2 tokens.
+    */
+   if (!dri2_convert_glx_attribs(num_attribs, attribs,
+				 &major_ver, &minor_ver,
+                                 &render_type, &flags, &api,
+                                 &reset, error))
+      goto error_exit;
+
+   /* Check the renderType value */
+   if (!validate_renderType_against_config(config_base, render_type))
+       goto error_exit;
+
+   if (shareList) {
+      pcp_shared = (struct dri3_context *) shareList;
+      shared = pcp_shared->driContext;
+   }
+
+   pcp = calloc(1, sizeof *pcp);
+   if (pcp == NULL) {
+      *error = __DRI_CTX_ERROR_NO_MEMORY;
+      goto error_exit;
+   }
+
+   if (!glx_context_init(&pcp->base, &psc->base, &config->base))
+      goto error_exit;
+
+   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
+   ctx_attribs[num_ctx_attribs++] = major_ver;
+   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
+   ctx_attribs[num_ctx_attribs++] = minor_ver;
+
+   /* Only send a value when the non-default value is requested.  By doing
+    * this we don't have to check the driver's DRI3 version before sending the
+    * default value.
+    */
+   if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
+      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
+      ctx_attribs[num_ctx_attribs++] = reset;
+   }
+
+   if (flags != 0) {
+      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
+
+      /* The current __DRI_CTX_FLAG_* values are identical to the
+       * GLX_CONTEXT_*_BIT values.
+       */
+      ctx_attribs[num_ctx_attribs++] = flags;
+   }
+
+   pcp->driContext =
+      (*psc->image_driver->createContextAttribs) (psc->driScreen,
+                                                  api,
+                                                  config->driConfig,
+                                                  shared,
+                                                  num_ctx_attribs / 2,
+                                                  ctx_attribs,
+                                                  error,
+                                                  pcp);
+
+   if (pcp->driContext == NULL)
+      goto error_exit;
+
+   pcp->base.vtable = &dri3_context_vtable;
+
+   return &pcp->base;
+
+error_exit:
+   free(pcp);
+
+   return NULL;
+}
+
+static void
+dri3_destroy_drawable(__GLXDRIdrawable *base)
+{
+   struct dri3_screen *psc = (struct dri3_screen *) base->psc;
+   struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
+
+   (*psc->core->destroyDrawable) (pdraw->driDrawable);
+
+   free(pdraw);
+}
+
+static __GLXDRIdrawable *
+dri3_create_drawable(struct glx_screen *base, XID xDrawable,
+                     GLXDrawable drawable, struct glx_config *config_base)
+{
+   struct dri3_drawable *pdraw;
+   struct dri3_screen *psc = (struct dri3_screen *) base;
+   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
+   GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
+
+   pdraw = calloc(1, sizeof(*pdraw));
+   if (!pdraw)
+      return NULL;
+
+   pdraw->base.destroyDrawable = dri3_destroy_drawable;
+   pdraw->base.xDrawable = xDrawable;
+   pdraw->base.drawable = drawable;
+   pdraw->base.psc = &psc->base;
+//   pdraw->bufferCount = 0;
+   pdraw->swap_interval = 1; /* default may be overridden below */
+   pdraw->have_back = 0;
+   pdraw->have_fake_front = 0;
+
+   if (psc->config)
+      psc->config->configQueryi(psc->driScreen,
+				"vblank_mode", &vblank_mode);
+
+   switch (vblank_mode) {
+   case DRI_CONF_VBLANK_NEVER:
+   case DRI_CONF_VBLANK_DEF_INTERVAL_0:
+      pdraw->swap_interval = 0;
+      break;
+   case DRI_CONF_VBLANK_DEF_INTERVAL_1:
+   case DRI_CONF_VBLANK_ALWAYS_SYNC:
+   default:
+      pdraw->swap_interval = 1;
+      break;
+   }
+
+   (void) __glXInitialize(psc->base.dpy);
+
+   /* Create a new drawable */
+   pdraw->driDrawable =
+      (*psc->image_driver->createNewDrawable) (psc->driScreen,
+                                               config->driConfig, pdraw);
+
+   if (!pdraw->driDrawable) {
+      free(pdraw);
+      return NULL;
+   }
+
+   /*
+    * Make sure server has the same swap interval we do for the new
+    * drawable.
+    */
+   if (psc->vtable.setSwapInterval)
+      psc->vtable.setSwapInterval(&pdraw->base, pdraw->swap_interval);
+
+   return &pdraw->base;
+}
+
+static void
+present_handle_special_event(struct dri3_drawable *priv, xcb_present_generic_event_t *ge)
+{
+   switch (ge->evtype) {
+   case XCB_PRESENT_CONFIGURE_NOTIFY: {
+      xcb_present_configure_notify_event_t *ce = (void *) ge;
+
+      priv->width = ce->width;
+      priv->height = ce->height;
+      break;
+   }
+   case XCB_PRESENT_COMPLETE_NOTIFY: {
+      xcb_present_complete_notify_event_t *ce = (void *) ge;
+
+      if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP)
+         priv->present_event_serial = ce->serial;
+      else
+         priv->present_msc_event_serial = ce->serial;
+      priv->ust = ce->ust;
+      priv->msc = ce->msc;
+      break;
+   }
+   case XCB_PRESENT_EVENT_IDLE_NOTIFY: {
+      xcb_present_idle_notify_event_t *ie = (void *) ge;
+      int b;
+
+      for (b = 0; b < sizeof (priv->buffers) / sizeof (priv->buffers[0]); b++) {
+         struct dri3_buffer        *buf = priv->buffers[b];
+
+         if (buf && buf->pixmap == ie->pixmap) {
+            buf->busy = 0;
+            break;
+         }
+      }
+      break;
+   }
+   }
+   free(ge);
+}
+
+static int
+dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
+                  int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
+{
+   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
+   struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
+   xcb_generic_event_t *ev;
+   xcb_present_generic_event_t *ge;
+
+   /* Ask for the an event for the target MSC */
+   ++priv->present_msc_request_serial;
+   xcb_present_notify_msc(c,
+                          priv->base.xDrawable,
+                          priv->present_msc_request_serial,
+                          target_msc,
+                          divisor,
+                          remainder);
+
+   xcb_flush(c);
+
+   /* Wait for the event */
+   if (priv->special_event) {
+      while (priv->present_msc_request_serial != priv->present_msc_event_serial) {
+         ev = xcb_wait_for_special_event(c, priv->special_event);
+         if (!ev)
+            break;
+         ge = (void *) ev;
+         present_handle_special_event(priv, ge);
+      }
+   }
+
+   *ust = priv->ust;
+   *msc = priv->msc;
+
+   *sbc = priv->sbc;
+
+   return 1;
+}
+
+static int
+dri3_drawable_get_msc(struct glx_screen *psc, __GLXDRIdrawable *pdraw,
+                      int64_t *ust, int64_t *msc, int64_t *sbc)
+{
+   return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc,sbc);
+}
+
+static int
+dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
+                  int64_t *msc, int64_t *sbc)
+{
+   struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
+
+   while (priv->sbc < target_sbc) {
+      sleep(1);
+   }
+   return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc, sbc);
+}
+
+static __DRIcontext *
+dri3_get_current_context(void)
+{
+   struct glx_context *gc = __glXGetCurrentContext();
+   struct dri3_context *dri3Ctx = (struct dri3_context *)gc;
+
+   return dri3Ctx ? dri3Ctx->driContext : NULL;
+}
+
+/**
+ * dri3Throttle - Request driver throttling
+ *
+ * This function uses the DRI2 throttle extension to give the
+ * driver the opportunity to throttle on flush front, copysubbuffer
+ * and swapbuffers.
+ */
+static void
+dri3_throttle(struct dri3_screen *psc,
+              struct dri3_drawable *draw,
+              enum __DRI2throttleReason reason)
+{
+   if (psc->throttle) {
+      __DRIcontext *ctx = dri3_get_current_context();
+
+      psc->throttle->throttle(ctx, draw->driDrawable, reason);
+   }
+}
+
+/**
+ * Asks the driver to flush any queued work necessary for serializing with the
+ * X command stream, and optionally the slightly more strict requirement of
+ * glFlush() equivalence (which would require flushing even if nothing had
+ * been drawn to a window system framebuffer, for example).
+ */
+static void
+dri3_flush(struct dri3_screen *psc,
+           __DRIcontext *ctx,
+           struct dri3_drawable *draw,
+           unsigned flags,
+           enum __DRI2throttleReason throttle_reason)
+{
+   if (ctx && psc->f && psc->f->base.version >= 4) {
+      psc->f->flush_with_flags(ctx, draw->driDrawable, flags, throttle_reason);
+   } else {
+      if (flags & __DRI2_FLUSH_CONTEXT)
+         glFlush();
+
+      if (psc->f)
+         psc->f->flush(draw->driDrawable);
+
+      dri3_throttle(psc, draw, throttle_reason);
+   }
+}
+
+static xcb_gcontext_t
+dri3_drawable_gc(struct dri3_drawable *priv)
+{
+   if (!priv->gc) {
+      uint32_t v;
+      xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
+
+      v = 0;
+      xcb_create_gc(c,
+                    (priv->gc = xcb_generate_id(c)),
+                    priv->base.xDrawable,
+                    XCB_GC_GRAPHICS_EXPOSURES,
+                    &v);
+   }
+   return priv->gc;
+}
+
+static struct dri3_buffer *
+dri3_back_buffer(struct dri3_drawable *priv)
+{
+   return priv->buffers[DRI3_BACK_ID(priv->cur_back)];
+}
+
+static struct dri3_buffer *
+dri3_fake_front_buffer(struct dri3_drawable *priv)
+{
+   return priv->buffers[DRI3_FRONT_ID];
+}
+
+static void
+dri3_copy_area (xcb_connection_t *c  /**< */,
+                xcb_drawable_t    src_drawable  /**< */,
+                xcb_drawable_t    dst_drawable  /**< */,
+                xcb_gcontext_t    gc  /**< */,
+                int16_t           src_x  /**< */,
+                int16_t           src_y  /**< */,
+                int16_t           dst_x  /**< */,
+                int16_t           dst_y  /**< */,
+                uint16_t          width  /**< */,
+                uint16_t          height  /**< */)
+{
+   xcb_void_cookie_t cookie;
+
+   cookie = xcb_copy_area_checked(c,
+                                  src_drawable,
+                                  dst_drawable,
+                                  gc,
+                                  src_x,
+                                  src_y,
+                                  dst_x,
+                                  dst_y,
+                                  width,
+                                  height);
+   xcb_discard_reply(c, cookie.sequence);
+}
+
+static void
+_dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y,
+                       int width, int height,
+                       enum __DRI2throttleReason reason, Bool flush)
+{
+   struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
+   struct dri3_screen *psc = (struct dri3_screen *) pdraw->psc;
+   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+   __DRIcontext *ctx = dri3_get_current_context();
+   struct dri3_buffer *back = dri3_back_buffer(priv);
+
+   unsigned flags;
+
+   /* Check we have the right attachments */
+   if (!priv->have_back || priv->is_pixmap)
+      return;
+
+   flags = __DRI2_FLUSH_DRAWABLE;
+   if (flush)
+      flags |= __DRI2_FLUSH_CONTEXT;
+   dri3_flush(psc, ctx, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
+
+   y = priv->height - y - height;
+
+   dri3_fence_reset(c, back);
+   dri3_copy_area(c,
+                  dri3_back_buffer(priv)->pixmap,
+                  priv->base.xDrawable,
+                  dri3_drawable_gc(priv),
+                  x, y, x, y, width, height);
+   dri3_fence_trigger(c, back);
+   /* Refresh the fake front (if present) after we just damaged the real
+    * front.
+    */
+   if (priv->have_fake_front) {
+      dri3_fence_reset(c, dri3_fake_front_buffer(priv));
+      dri3_copy_area(c,
+                     dri3_back_buffer(priv)->pixmap,
+                     dri3_fake_front_buffer(priv)->pixmap,
+                     dri3_drawable_gc(priv),
+                     x, y, x, y, width, height);
+      dri3_fence_trigger(c, dri3_fake_front_buffer(priv));
+      dri3_fence_await(c, dri3_fake_front_buffer(priv));
+   }
+   dri3_fence_await(c, back);
+}
+
+static void
+dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y,
+		  int width, int height, Bool flush)
+{
+   _dri3_copy_sub_buffer(pdraw, x, y, width, height,
+                         __DRI2_THROTTLE_COPYSUBBUFFER, flush);
+}
+
+
+static void
+dri3_copy_drawable(struct dri3_drawable *priv, Drawable dest, Drawable src)
+{
+   struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
+   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+
+   if (psc->f)
+      (*psc->f->flush) (priv->driDrawable);
+
+   dri3_copy_area(c,
+                  src, dest,
+                  dri3_drawable_gc(priv),
+                  0, 0, 0, 0, priv->width, priv->height);
+}
+
+static void
+dri3_wait_x(struct glx_context *gc)
+{
+   struct dri3_drawable *priv = (struct dri3_drawable *)
+      GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
+
+   if (priv == NULL || !priv->have_fake_front)
+      return;
+
+   dri3_copy_drawable(priv, dri3_fake_front_buffer(priv)->pixmap, priv->base.xDrawable);
+}
+
+static void
+dri3_wait_gl(struct glx_context *gc)
+{
+   struct dri3_drawable *priv = (struct dri3_drawable *)
+      GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
+
+   if (priv == NULL || !priv->have_fake_front)
+      return;
+
+   dri3_copy_drawable(priv, priv->base.xDrawable, dri3_fake_front_buffer(priv)->pixmap);
+}
+
+/**
+ * Called by the driver when it needs to update the real front buffer with the
+ * contents of its fake front buffer.
+ */
+static void
+dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
+{
+   struct glx_context *gc;
+   struct dri3_drawable *pdraw = loaderPrivate;
+   struct dri3_screen *psc;
+
+   if (!pdraw)
+      return;
+
+   if (!pdraw->base.psc)
+      return;
+
+   psc = (struct dri3_screen *) pdraw->base.psc;
+
+   (void) __glXInitialize(psc->base.dpy);
+
+   gc = __glXGetCurrentContext();
+
+   dri3_throttle(psc, pdraw, __DRI2_THROTTLE_FLUSHFRONT);
+
+   dri3_wait_gl(gc);
+}
+
+static struct dri3_buffer *
+dri3_alloc_render_buffer(struct glx_screen *glx_screen, Drawable draw, unsigned int format, int width, int height, int depth)
+{
+   struct dri3_screen *psc = (struct dri3_screen *) glx_screen;
+   Display *dpy = glx_screen->dpy;
+   struct dri3_buffer *buffer;
+   xcb_connection_t *c = XGetXCBConnection(dpy);
+   xcb_pixmap_t pixmap;
+   xcb_sync_fence_t sync_fence;
+   int32_t *shm_fence;
+   int buffer_fd, fence_fd;
+   int stride;
+
+   fence_fd = xshmfence_alloc_shm();
+   if (fence_fd < 0)
+      return NULL;
+   shm_fence = xshmfence_map_shm(fence_fd);
+   if (shm_fence == NULL)
+      goto no_shm_fence;
+
+   buffer = calloc(1, sizeof (struct dri3_buffer));
+   if (!buffer)
+      goto no_buffer;
+
+   buffer->image = (*psc->image->createImage) (psc->driScreen,
+                                               width, height,
+                                               format,
+                                               __DRI_IMAGE_USE_SHARE|__DRI_IMAGE_USE_SCANOUT,
+                                               buffer);
+
+   
+   if (!buffer->image)
+      goto no_image;
+
+   if (!(*psc->image->queryImage)(buffer->image, __DRI_IMAGE_ATTRIB_STRIDE, &stride))
+      goto no_buffer_attrib;
+
+   buffer->pitch = stride;
+
+   if (!(*psc->image->queryImage)(buffer->image, __DRI_IMAGE_ATTRIB_FD, &buffer_fd))
+      goto no_buffer_attrib;
+
+   xcb_dri3_pixmap_from_buffer(c,
+                               (pixmap = xcb_generate_id(c)),
+                               draw,
+                               buffer->size,
+                               width, height, buffer->pitch,
+                               depth, buffer->cpp * 8,
+                               buffer_fd);
+
+   xcb_dri3_fence_from_fd(c,
+                          pixmap,
+                          (sync_fence = xcb_generate_id(c)),
+                          false,
+                          fence_fd);
+
+   buffer->pixmap = pixmap;
+   buffer->sync_fence = sync_fence;
+   buffer->shm_fence = shm_fence;
+   buffer->width = width;
+   buffer->height = height;
+
+   /* Mark the buffer as idle */
+   dri3_fence_set(buffer);
+
+   return buffer;
+   
+no_buffer_attrib:
+   (*psc->image->destroyImage)(buffer->image);
+no_image:
+   free(buffer);
+no_buffer:
+   xshmfence_unmap_shm(shm_fence);
+no_shm_fence:
+   close(fence_fd);
+   return NULL;
+}
+
+static void
+dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer)
+{
+   struct dri3_screen   *psc = (struct dri3_screen *) pdraw->base.psc;
+   xcb_connection_t     *c = XGetXCBConnection(pdraw->base.psc->dpy);
+
+   xcb_free_pixmap(c, buffer->pixmap);
+   xcb_sync_destroy_fence(c, buffer->sync_fence);
+   xshmfence_unmap_shm(buffer->shm_fence);
+   (*psc->image->destroyImage)(buffer->image);
+   free(buffer);
+}
+
+
+
+static void
+present_flush_events(struct dri3_drawable *priv)
+{
+   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+
+   /* Check to see if any configuration changes have occurred
+    * since we were last invoked
+    */
+   if (priv->special_event) {
+      xcb_generic_event_t    *ev;
+
+      while ((ev = xcb_check_for_special_event(c, priv->special_event)) != NULL) {
+         xcb_present_generic_event_t *ge = (void *) ev;
+         present_handle_special_event(priv, ge);
+      }
+   }
+}
+
+static int
+dri3_update_drawable(__DRIdrawable *driDrawable, void *loaderPrivate)
+{
+   struct dri3_drawable *priv = loaderPrivate;
+   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+
+   /* First time through, go get the current drawable geometry
+    */
+   if (priv->width == 0 || priv->height == 0 || priv->depth == 0) {
+      xcb_get_geometry_cookie_t                 geom_cookie;
+      xcb_get_geometry_reply_t                  *geom_reply;
+      xcb_void_cookie_t                         cookie;
+      xcb_generic_error_t                       *error;
+
+      cookie = xcb_present_select_input_checked(c,
+                                                (priv->eid = xcb_generate_id(c)),
+                                                priv->base.xDrawable,
+                                                XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY|
+                                                XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY|
+                                                XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
+         
+      if (!priv->present_extension) {
+         priv->present_extension = xcb_get_extension_data(c, &xcb_present_id);
+         if (!priv->present_extension)
+            return false;
+      }
+
+      priv->special_event = xcb_register_for_special_event(c,
+                                                           priv->present_extension->major_opcode,
+                                                           priv->eid,
+                                                           priv->stamp);
+
+      geom_cookie = xcb_get_geometry(c, priv->base.xDrawable);
+
+      geom_reply = xcb_get_geometry_reply(c, geom_cookie, NULL);
+
+      if (!geom_reply)
+         return false;
+
+      priv->width = geom_reply->width;
+      priv->height = geom_reply->height;
+      priv->depth = geom_reply->depth;
+      priv->is_pixmap = false;
+
+      free(geom_reply);
+
+      error = xcb_request_check(c, cookie);
+
+      if (error) {
+         if (error->error_code != BadWindow) {
+            free(error);
+            return false;
+         }
+         priv->is_pixmap = true;
+         xcb_unregister_for_special_event(c, priv->special_event);
+         priv->special_event = NULL;
+      }
+   }
+   present_flush_events(priv);
+   return true;
+}
+   
+static int
+image_format_to_fourcc(int format)
+{
+
+   /* Convert from __DRI_IMAGE_FORMAT to __DRI_IMAGE_FOURCC (sigh) */
+   switch (format) {
+   case __DRI_IMAGE_FORMAT_RGB565: return __DRI_IMAGE_FOURCC_RGB565;
+   case __DRI_IMAGE_FORMAT_XRGB8888: return __DRI_IMAGE_FOURCC_XRGB8888;
+   case __DRI_IMAGE_FORMAT_ARGB8888: return __DRI_IMAGE_FOURCC_ARGB8888;
+   case __DRI_IMAGE_FORMAT_ABGR8888: return __DRI_IMAGE_FOURCC_ABGR8888;
+   case __DRI_IMAGE_FORMAT_XBGR8888: return __DRI_IMAGE_FOURCC_XBGR8888;
+//   case __DRI_IMAGE_FORMAT_R8: return __DRI_IMAGE_FOURCC_R8;
+//   case __DRI_IMAGE_FORMAT_GR88: return __DRI_IMAGE_FOURCC_GR88;
+//   case __DRI_IMAGE_FORMAT_NONE: return __DRI_IMAGE_FOURCC_NONE;
+//   case __DRI_IMAGE_FORMAT_XRGB2101010: return __DRI_IMAGE_FOURCC_XRGB2101010;
+//   case __DRI_IMAGE_FORMAT_ARGB2101010: return __DRI_IMAGE_FOURCC_ARGB2101010;
+   }
+   return 0;
+}
+
+static struct dri3_buffer *
+dri3_get_pixmap_buffer(__DRIdrawable *driDrawable,
+                       unsigned int format,
+                       enum dri3_buffer_type buffer_type,
+                       void *loaderPrivate)
+{
+   struct dri3_drawable                 *pdraw = loaderPrivate;
+   int                                  buf_id = buffer_type == dri3_pixmap_buf_id(buffer_type);
+   struct dri3_buffer                   *buffer = pdraw->buffers[buf_id];
+   Pixmap                               pixmap;
+   xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
+   xcb_dri3_buffer_from_pixmap_reply_t  *bp_reply;
+   int                                  *fds;
+   int                                  buffer_fd;
+   Display                              *dpy;
+   struct dri3_screen                   *psc;
+   xcb_connection_t                     *c;
+   xcb_sync_fence_t                     sync_fence;
+   int32_t                              *shm_fence;
+   int                                  fence_fd;
+   __DRIimage                           *image_planar;
+   int                                  stride, offset;
+
+   if (buffer)
+      return buffer;
+
+   pixmap = pdraw->base.xDrawable;
+   psc = (struct dri3_screen *) pdraw->base.psc;
+   dpy = psc->base.dpy;
+   c = XGetXCBConnection(dpy);
+
+   buffer = calloc(1, sizeof (struct dri3_buffer));
+   if (!buffer)
+      goto no_buffer;
+
+   fence_fd = xshmfence_alloc_shm();
+   if (fence_fd < 0)
+      goto no_fence;
+   shm_fence = xshmfence_map_shm(fence_fd);
+   if (shm_fence == NULL) {
+      close (fence_fd);
+      goto no_fence;
+   }
+
+   xcb_dri3_fence_from_fd(c,
+                          pixmap,
+                          (sync_fence = xcb_generate_id(c)),
+                          false,
+                          fence_fd);
+
+   bp_cookie = xcb_dri3_buffer_from_pixmap(c, pixmap);
+   bp_reply = xcb_dri3_buffer_from_pixmap_reply(c, bp_cookie, NULL);
+   if (!bp_reply)
+      goto no_image;
+   fds = xcb_dri3_buffer_from_pixmap_reply_fds(c, bp_reply);
+   buffer_fd = fds[0];
+
+   stride = bp_reply->stride;
+   offset = 0;
+
+   image_planar = (*psc->image->createImageFromFds) (psc->driScreen,
+                                                     bp_reply->width,
+                                                     bp_reply->height,
+                                                     image_format_to_fourcc(format),
+                                                     fds, 1,
+                                                     &stride, &offset, buffer);
+   close(buffer_fd);
+   if (!image_planar)
+      goto no_image;
+
+   buffer->image = (*psc->image->fromPlanar)(image_planar, 0, buffer);
+
+   (*psc->image->destroyImage)(image_planar);
+
+   if (!buffer->image)
+      goto no_image;
+
+   buffer->pixmap = pixmap;
+   buffer->width = bp_reply->width;
+   buffer->height = bp_reply->height;
+   buffer->buffer_type = buffer_type;
+   buffer->shm_fence = shm_fence;
+   buffer->sync_fence = sync_fence;
+
+   pdraw->buffers[buf_id] = buffer;
+   return buffer;
+
+no_image:
+   xcb_sync_destroy_fence(c, sync_fence);
+   xshmfence_unmap_shm(shm_fence);
+no_fence:
+   free(buffer);
+no_buffer:
+   return NULL;
+}
+
+static int
+dri3_find_back(xcb_connection_t *c, struct dri3_drawable *priv)
+{
+   int  b;
+   xcb_generic_event_t *ev;
+   xcb_present_generic_event_t *ge;
+
+   for (;;) {
+
+      for (b = 0; b < DRI3_MAX_BACK; b++) {
+         int                    id = DRI3_BACK_ID(b);
+         struct dri3_buffer        *buffer = priv->buffers[id];
+
+         if (!buffer)
+            return b;
+         if (!buffer->busy)
+            return b;
+      }
+      ev = xcb_wait_for_special_event(c, priv->special_event);
+      if (!ev)
+         return -1;
+      ge = (void *) ev;
+      present_handle_special_event(priv, ge);
+   } 
+}
+
+static struct dri3_buffer *
+dri3_get_buffer(__DRIdrawable *driDrawable,
+                unsigned int format,
+                enum dri3_buffer_type buffer_type,
+                void *loaderPrivate)
+{
+   struct dri3_drawable *priv = loaderPrivate;
+   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
+   struct dri3_buffer      *buffer;
+   int                  buf_id;
+
+   if (buffer_type == dri3_buffer_back) {
+      int back = dri3_find_back(c, priv);
+
+      if (back < 0)
+         return NULL;
+
+      priv->cur_back = back;
+      buf_id = DRI3_BACK_ID(priv->cur_back);
+   } else {
+      buf_id = DRI3_FRONT_ID;
+   }
+
+   buffer = priv->buffers[buf_id];
+   if (!buffer || buffer->width != priv->width || buffer->height != priv->height) {
+      struct dri3_buffer   *new_buffer;
+
+      /* Allocate the new buffers
+       */
+      new_buffer = dri3_alloc_render_buffer(priv->base.psc,
+                                            priv->base.xDrawable,
+                                            format, priv->width, priv->height, priv->depth);
+      if (!new_buffer)
+         return NULL;
+      switch (buffer_type) {
+      case dri3_buffer_back:
+         if (buffer) {
+            dri3_fence_reset(c, new_buffer);
+            dri3_fence_await(c, buffer);
+            dri3_copy_area(c,
+                           buffer->pixmap,
+                           new_buffer->pixmap,
+                           dri3_drawable_gc(priv),
+                           0, 0, 0, 0, priv->width, priv->height);
+            dri3_fence_trigger(c, new_buffer);
+            dri3_free_render_buffer(priv, buffer);
+         }
+         break;
+      case dri3_buffer_front:
+         dri3_fence_reset(c, new_buffer);
+         dri3_copy_area(c,
+                        priv->base.xDrawable,
+                        new_buffer->pixmap,
+                        dri3_drawable_gc(priv),
+                        0, 0, 0, 0, priv->width, priv->height);
+         dri3_fence_trigger(c, new_buffer);
+         break;
+      }
+      buffer = new_buffer;
+      buffer->buffer_type = buffer_type;
+      priv->buffers[buf_id] = buffer;
+   } 
+   dri3_fence_await(c, buffer);
+
+   /* Return the requested buffer */
+   return buffer;
+}
+
+static void
+dri3_free_buffers(__DRIdrawable *driDrawable,
+                 enum dri3_buffer_type buffer_type,
+                 void *loaderPrivate)
+{
+   struct dri3_drawable *priv = loaderPrivate;
+   struct dri3_buffer      *buffer;
+   int                  first_id;
+   int                  n_id;
+   int                  buf_id;
+   
+   switch (buffer_type) {
+   case dri3_buffer_back:
+      first_id = DRI3_BACK_ID(0);
+      n_id = DRI3_MAX_BACK;
+      break;
+   case dri3_buffer_front:
+      first_id = DRI3_FRONT_ID;
+      n_id = 1;
+   }
+
+   for (buf_id = first_id; buf_id < first_id + n_id; buf_id++) {
+      buffer = priv->buffers[buf_id];
+      if (buffer) {
+         dri3_free_render_buffer(priv, buffer);
+         priv->buffers[buf_id] = NULL;
+      }
+   }
+}
+
+static int
+dri3_get_buffers(__DRIdrawable *driDrawable,
+                 int *width, int *height,
+                 unsigned int format,
+                 uint32_t *stamp,
+                 void *loaderPrivate,
+                 uint32_t buffer_mask,
+                 struct __DRIimageList *buffers)
+{
+   struct dri3_drawable *priv = loaderPrivate;
+   struct dri3_buffer   *front, *back;
+
+   buffers->front = NULL;
+   buffers->back = NULL;
+
+   front = NULL;
+   back = NULL;
+
+   if (!dri3_update_drawable(driDrawable, loaderPrivate))
+      return false;
+
+   if (priv->is_pixmap)
+      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
+
+   if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
+      if (priv->is_pixmap)
+         front = dri3_get_pixmap_buffer(driDrawable,
+                                        format,
+                                        dri3_buffer_front,
+                                        loaderPrivate);
+      else
+         front = dri3_get_buffer(driDrawable,
+                                 format,
+                                 dri3_buffer_front,
+                                 loaderPrivate);
+
+      if (!front)
+         return false;
+      priv->have_fake_front = !priv->is_pixmap;
+   } else {
+      dri3_free_buffers(driDrawable, dri3_buffer_front, loaderPrivate);
+      priv->have_fake_front = 0;
+   }
+
+   if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
+      back = dri3_get_buffer(driDrawable,
+                             format,
+                             dri3_buffer_back,
+                             loaderPrivate);
+      if (!back)
+         return false;
+      priv->have_back = 1;
+   } else {
+      dri3_free_buffers(driDrawable, dri3_buffer_back, loaderPrivate);
+      priv->have_back = 0;
+   }
+
+   if (front)
+      buffers->front = front->image;
+   
+   if (back)
+      buffers->back = back->image;
+
+   priv->stamp = stamp;
+
+   /* Report back current geometry */
+   *width = priv->width;
+   *height = priv->height;
+   return true;
+}
+
+static int64_t
+dri3_swap_buffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
+                  int64_t remainder, Bool flush)
+{
+   struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
+   struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
+   Display *dpy = priv->base.psc->dpy;
+   xcb_connection_t *c = XGetXCBConnection(dpy);
+   int buf_id = DRI3_BACK_ID(priv->cur_back);
+   int64_t ret = 0;
+
+   __DRIcontext *ctx = dri3_get_current_context();
+   unsigned flags = __DRI2_FLUSH_DRAWABLE;
+   if (flush)
+      flags |= __DRI2_FLUSH_CONTEXT;
+   dri3_flush(psc, ctx, priv, flags, __DRI2_THROTTLE_SWAPBUFFER);
+    
+   present_flush_events(priv);
+
+   if (priv->buffers[buf_id] && !priv->is_pixmap) {
+      dri3_fence_reset(c, priv->buffers[buf_id]);
+
+      /* Compute when we want the frame shown by taking the last known successful
+       * MSC and adding in a swap interval for each outstanding swap request
+       */
+      ++priv->present_request_serial;
+      if (target_msc == 0)
+         target_msc = priv->msc + priv->swap_interval * (priv->present_request_serial - priv->present_event_serial);
+
+      priv->buffers[buf_id]->busy = 1;
+      xcb_present_pixmap(c,
+                         priv->base.xDrawable,
+                         priv->buffers[buf_id]->pixmap,
+                         priv->present_request_serial,
+                         0,                                    /* valid */
+                         0,                                    /* update */
+                         0,                                    /* x_off */
+                         0,                                    /* y_off */
+                         None,                                 /* target_crtc */
+                         None,
+                         priv->buffers[buf_id]->sync_fence,
+                         XCB_PRESENT_OPTION_NONE,
+                         target_msc,
+                         divisor,
+                         remainder, 0, NULL);
+      ret = ++priv->sbc;
+      if (priv->have_fake_front) {
+         dri3_fence_reset(c, priv->buffers[DRI3_FRONT_ID]);
+         dri3_copy_area(c,
+                        priv->buffers[buf_id]->pixmap,
+                        priv->buffers[DRI3_FRONT_ID]->pixmap,
+                        dri3_drawable_gc(priv),
+                        0, 0, 0, 0, priv->width, priv->height);
+         dri3_fence_trigger(c, priv->buffers[DRI3_FRONT_ID]);
+      }
+      xcb_flush(c);
+      if (priv->stamp)
+         ++(*priv->stamp);
+   }
+
+   return ret;
+}
+
+static int
+dri3_query_version(Display *dpy, int *major, int *minor)
+{
+   xcb_dri3_query_version_cookie_t      cookie;
+   xcb_dri3_query_version_reply_t       *reply;       
+   xcb_connection_t                     *c = XGetXCBConnection(dpy);
+   xcb_generic_error_t                  *error;
+
+   cookie = xcb_dri3_query_version(c,
+                                   XCB_DRI3_MAJOR_VERSION,
+                                   XCB_DRI3_MINOR_VERSION);
+   reply = xcb_dri3_query_version_reply(c, cookie, &error);
+   if (!reply) {
+      if (error) {
+         free(error);
+      }
+      return 0;
+   }
+   *major = reply->major_version;
+   *minor = reply->minor_version;
+   free(reply);
+   return 1;
+}
+
+static int
+present_query_version(Display *dpy, int *major, int *minor)
+{
+   xcb_present_query_version_cookie_t   cookie;
+   xcb_present_query_version_reply_t    *reply;       
+   xcb_connection_t                     *c = XGetXCBConnection(dpy);
+   xcb_generic_error_t                  *error;
+
+   cookie = xcb_present_query_version(c,
+                                   XCB_PRESENT_MAJOR_VERSION,
+                                   XCB_PRESENT_MINOR_VERSION);
+   reply = xcb_present_query_version_reply(c, cookie, &error);
+   if (!reply) {
+      if (error) {
+         free(error);
+      }
+      return 0;
+   }
+   *major = reply->major_version;
+   *minor = reply->minor_version;
+   free(reply);
+   return 1;
+}
+
+static int
+dri3_open(Display *dpy,
+          Window root,
+          CARD32 provider)
+{
+   xcb_dri3_open_cookie_t       cookie;
+   xcb_dri3_open_reply_t        *reply;       
+   xcb_connection_t             *c = XGetXCBConnection(dpy);
+   xcb_generic_error_t          *error;
+   int                          fd;
+
+   cookie = xcb_dri3_open(c,
+                          root,
+                          provider);
+
+   reply = xcb_dri3_open_reply(c, cookie, &error);
+   if (!reply)
+      return -1;
+
+   if (reply->nfd != 1) {
+      free(reply);
+      return -1;
+   }
+
+   fd = xcb_dri3_open_reply_fds(c, reply)[0];
+   fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+   return fd;
+}
+
+
+static void
+dri3_destroy_screen(struct glx_screen *base)
+{
+   struct dri3_screen *psc = (struct dri3_screen *) base;
+
+   /* Free the direct rendering per screen data */
+   (*psc->core->destroyScreen) (psc->driScreen);
+   driDestroyConfigs(psc->driver_configs);
+   close(psc->fd);
+   free(psc);
+}
+
+static int
+dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
+{
+   struct dri3_drawable *priv =  (struct dri3_drawable *) pdraw;
+   GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
+   struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
+
+   if (psc->config)
+      psc->config->configQueryi(psc->driScreen,
+				"vblank_mode", &vblank_mode);
+
+   switch (vblank_mode) {
+   case DRI_CONF_VBLANK_NEVER:
+      if (interval != 0)
+         return GLX_BAD_VALUE;
+      break;
+   case DRI_CONF_VBLANK_ALWAYS_SYNC:
+      if (interval <= 0)
+	 return GLX_BAD_VALUE;
+      break;
+   default:
+      break;
+   }
+
+   priv->swap_interval = interval;
+
+   return 0;
+}
+
+static int
+dri3_get_swap_interval(__GLXDRIdrawable *pdraw)
+{
+   struct dri3_drawable *priv =  (struct dri3_drawable *) pdraw;
+
+  return priv->swap_interval;
+}
+
+static const __DRIimageLoaderExtension imageLoaderExtension = {
+   {__DRI_IMAGE_LOADER, __DRI_IMAGE_LOADER_VERSION},
+   .getBuffers = dri3_get_buffers,
+   .flushFrontBuffer = dri3_flush_front_buffer,
+};
+
+static void
+dri3_bind_tex_image(Display * dpy,
+		    GLXDrawable drawable,
+		    int buffer, const int *attrib_list)
+{
+   struct glx_context *gc = __glXGetCurrentContext();
+   struct dri3_context *pcp = (struct dri3_context *) gc;
+   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
+   struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
+   struct dri3_screen *psc;
+
+   if (pdraw != NULL) {
+      psc = (struct dri3_screen *) base->psc;
+
+      if (psc->f &&
+           psc->f->base.version >= 3 && psc->f->invalidate)
+	 psc->f->invalidate(pdraw->driDrawable);
+
+      XSync(dpy, false);
+      if (psc->texBuffer->base.version >= 2 &&
+	  psc->texBuffer->setTexBuffer2 != NULL) {
+	 (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
+					   pdraw->base.textureTarget,
+					   pdraw->base.textureFormat,
+					   pdraw->driDrawable);
+      }
+      else {
+	 (*psc->texBuffer->setTexBuffer) (pcp->driContext,
+					  pdraw->base.textureTarget,
+					  pdraw->driDrawable);
+      }
+   }
+}
+
+static void
+dri3_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
+{
+#if __DRI_TEX_BUFFER_VERSION >= 3
+   struct glx_context *gc = __glXGetCurrentContext();
+   struct dri3_context *pcp = (struct dri3_context *) gc;
+   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
+   struct glx_display *dpyPriv = __glXInitialize(dpy);
+   struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
+   struct dri3_display *pdp =
+      (struct dri3_display *) dpyPriv->dri3Display;
+   struct dri3_screen *psc;
+
+   if (pdraw != NULL) {
+      psc = (struct dri3_screen *) base->psc;
+
+      if (psc->texBuffer->base.version >= 3 &&
+          psc->texBuffer->releaseTexBuffer != NULL) {
+         (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
+                                           pdraw->base.textureTarget,
+                                           pdraw->driDrawable);
+      }
+   }
+#endif
+}
+
+static const struct glx_context_vtable dri3_context_vtable = {
+   dri3_destroy_context,
+   dri3_bind_context,
+   dri3_unbind_context,
+   dri3_wait_gl,
+   dri3_wait_x,
+   DRI_glXUseXFont,
+   dri3_bind_tex_image,
+   dri3_release_tex_image,
+   NULL, /* get_proc_address */
+};
+
+static void
+dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
+                     const char *driverName)
+{
+//   const struct dri3_display *const pdp = (struct dri3_display *) priv->dri3Display;
+   const __DRIextension **extensions;
+   unsigned mask;
+   int i;
+
+   extensions = psc->core->getExtensions(psc->driScreen);
+
+   __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
+   __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
+   __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
+   __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
+
+   /*
+    * GLX_INTEL_swap_event is broken on the server side, where it's
+    * currently unconditionally enabled. This completely breaks
+    * systems running on drivers which don't support that extension.
+    * There's no way to test for its presence on this side, so instead
+    * of disabling it unconditionally, just disable it for drivers
+    * which are known to not support it, or for DDX drivers supporting
+    * only an older (pre-ScheduleSwap) version of DRI2.
+    *
+    * This is a hack which is required until:
+    * http://lists.x.org/archives/xorg-devel/2013-February/035449.html
+    * is merged and updated xserver makes it's way into distros:
+    */
+//   if (pdp->swapAvailable && strcmp(driverName, "vmwgfx") != 0) {
+//      __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
+//   }
+
+   mask = psc->image_driver->getAPIMask(psc->driScreen);
+
+   __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
+   __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
+
+   if ((mask & (1 << __DRI_API_GLES2)) != 0)
+      __glXEnableDirectExtension(&psc->base,
+                                 "GLX_EXT_create_context_es2_profile");
+
+   for (i = 0; extensions[i]; i++) {
+      if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
+	 psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
+	 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
+      }
+
+      if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
+	 psc->f = (__DRI2flushExtension *) extensions[i];
+	 /* internal driver extension, no GL extension exposed */
+      }
+
+      if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
+	 psc->config = (__DRI2configQueryExtension *) extensions[i];
+
+      if (((strcmp(extensions[i]->name, __DRI2_THROTTLE) == 0)))
+	 psc->throttle = (__DRI2throttleExtension *) extensions[i];
+
+      if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
+         __glXEnableDirectExtension(&psc->base,
+                                    "GLX_ARB_create_context_robustness");
+   }
+}
+
+static const struct glx_screen_vtable dri3_screen_vtable = {
+   dri3_create_context,
+   dri3_create_context_attribs
+};
+
+static struct glx_screen *
+dri3_create_screen(int screen, struct glx_display * priv)
+{
+   const __DRIconfig **driver_configs;
+   const __DRIextension **extensions;
+   const struct dri3_display *const pdp = (struct dri3_display *)
+      priv->dri3Display;
+   struct dri3_screen *psc;
+   __GLXDRIscreen *psp;
+   struct glx_config *configs = NULL, *visuals = NULL;
+   char *driverName, *deviceName, *tmp;
+   int i;
+
+   psc = calloc(1, sizeof *psc);
+   if (psc == NULL)
+      return NULL;
+
+   psc->fd = -1;
+
+   if (!glx_screen_init(&psc->base, screen, priv)) {
+      free(psc);
+      return NULL;
+   }
+
+   psc->fd = dri3_open(priv->dpy, RootWindow(priv->dpy, screen), None);
+   if (psc->fd < 0) {
+      glx_screen_cleanup(&psc->base);
+      free(psc);
+      InfoMessageF("screen %d does not appear to be DRI3 capable\n", screen);
+      return NULL;
+   }
+   deviceName = NULL;
+
+   driverName = dri3_get_driver_for_fd(psc->fd);
+   if (!driverName) {
+      ErrorMessageF("No driver found\n");
+      goto handle_error;
+   }
+
+   psc->driver = driOpenDriver(driverName);
+   if (psc->driver == NULL) {
+      ErrorMessageF("driver pointer missing\n");
+      goto handle_error;
+   }
+
+   extensions = driGetDriverExtensions(psc->driver, driverName);
+   if (extensions == NULL)
+      goto handle_error;
+
+   for (i = 0; extensions[i]; i++) {
+      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
+	 psc->core = (__DRIcoreExtension *) extensions[i];
+      if (strcmp(extensions[i]->name, __DRI_IMAGE_DRIVER) == 0)
+	 psc->image_driver = (__DRIimageDriverExtension *) extensions[i];
+   }
+
+
+   if (psc->core == NULL) {
+      ErrorMessageF("core dri driver extension not found\n");
+      goto handle_error;
+   }
+
+   if (psc->image_driver == NULL) {
+      ErrorMessageF("image driver extension not found\n");
+      goto handle_error;
+   }
+
+   psc->driScreen =
+      psc->image_driver->createNewScreen2(screen, psc->fd,
+                                          (const __DRIextension **)
+                                          &pdp->loader_extensions[0],
+                                          extensions,
+                                          &driver_configs, psc);
+
+   if (psc->driScreen == NULL) {
+      ErrorMessageF("failed to create dri screen\n");
+      goto handle_error;
+   }
+
+   extensions = (*psc->core->getExtensions)(psc->driScreen);
+
+   for (i = 0; extensions[i]; i++) {
+      if (strcmp(extensions[i]->name, __DRI_IMAGE) == 0)
+         psc->image = (__DRIimageExtension *) extensions[i];
+   }
+
+   if (psc->image == NULL) {
+      ErrorMessageF("image extension not found\n");
+      goto handle_error;
+   }
+
+   dri3_bind_extensions(psc, priv, driverName);
+
+   configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
+   visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
+
+   if (!configs || !visuals)
+       goto handle_error;
+
+   glx_config_destroy_list(psc->base.configs);
+   psc->base.configs = configs;
+   glx_config_destroy_list(psc->base.visuals);
+   psc->base.visuals = visuals;
+
+   psc->driver_configs = driver_configs;
+
+   psc->base.vtable = &dri3_screen_vtable;
+   psp = &psc->vtable;
+   psc->base.driScreen = psp;
+   psp->destroyScreen = dri3_destroy_screen;
+   psp->createDrawable = dri3_create_drawable;
+   psp->swapBuffers = dri3_swap_buffers;
+
+   psp->getDrawableMSC = dri3_drawable_get_msc;
+   psp->waitForMSC = dri3_wait_for_msc;
+   psp->waitForSBC = dri3_wait_for_sbc;
+   psp->setSwapInterval = dri3_set_swap_interval;
+   psp->getSwapInterval = dri3_get_swap_interval;
+   __glXEnableDirectExtension(&psc->base, "GLX_OML_sync_control");
+
+   psp->copySubBuffer = dri3_copy_sub_buffer;
+   __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
+
+   free(driverName);
+   free(deviceName);
+
+   tmp = getenv("LIBGL_SHOW_FPS");
+   psc->show_fps = tmp && strcmp(tmp, "1") == 0;
+
+   return &psc->base;
+
+handle_error:
+   CriticalErrorMessageF("failed to load driver: %s\n", driverName);
+
+   if (configs)
+       glx_config_destroy_list(configs);
+   if (visuals)
+       glx_config_destroy_list(visuals);
+   if (psc->driScreen)
+       psc->core->destroyScreen(psc->driScreen);
+   psc->driScreen = NULL;
+   if (psc->fd >= 0)
+      close(psc->fd);
+   if (psc->driver)
+      dlclose(psc->driver);
+
+   free(driverName);
+   free(deviceName);
+   glx_screen_cleanup(&psc->base);
+   free(psc);
+
+   return NULL;
+}
+
+/* Called from __glXFreeDisplayPrivate.
+ */
+static void
+dri3_destroy_display(__GLXDRIdisplay * dpy)
+{
+   free(dpy);
+}
+
+/*
+ * Allocate, initialize and return a __DRIdisplayPrivate object.
+ * This is called from __glXInitialize() when we are given a new
+ * display pointer.
+ */
+_X_HIDDEN __GLXDRIdisplay *
+dri3_create_display(Display * dpy)
+{
+   struct dri3_display *pdp;
+   int i;
+
+   pdp = malloc(sizeof *pdp);
+   if (pdp == NULL)
+      return NULL;
+
+   if (!dri3_query_version(dpy, &pdp->dri3Major, &pdp->dri3Minor))
+      goto no_extension;
+
+   if (!present_query_version(dpy, &pdp->presentMajor, &pdp->presentMinor))
+      goto no_extension;
+
+   pdp->base.destroyDisplay = dri3_destroy_display;
+   pdp->base.createScreen = dri3_create_screen;
+
+   i = 0;
+
+   pdp->loader_extensions[i++] = &imageLoaderExtension.base;
+   
+   pdp->loader_extensions[i++] = &systemTimeExtension.base;
+
+   pdp->loader_extensions[i++] = NULL;
+
+   return &pdp->base;
+no_extension:
+   free(pdp);
+   return NULL;
+}
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h
new file mode 100644
index 0000000..2873919
--- /dev/null
+++ b/src/glx/dri3_priv.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/* This file was derived from dri2_priv.h which carries the following
+ * copyright:
+ *
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh@redhat.com)
+ */
+
+#include <xcb/xcb.h>
+#include <xcb/dri3.h>
+#include <xcb/present.h>
+#include <xcb/sync.h>
+
+/* From xmlpool/options.h, user exposed so should be stable */
+#define DRI_CONF_VBLANK_NEVER 0
+#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
+#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
+#define DRI_CONF_VBLANK_ALWAYS_SYNC 3
+
+enum dri3_buffer_type {
+   dri3_buffer_back = 0,
+   dri3_buffer_front = 1
+};
+
+struct dri3_buffer {
+   __DRIimage   *image;
+   uint32_t     pixmap;
+   uint32_t     sync_fence;
+   int32_t      *shm_fence;
+   GLboolean    busy;
+   void         *driverPrivate;
+
+   uint32_t     size;
+   uint32_t     pitch;
+   uint32_t     cpp;
+   uint32_t     flags;
+   uint32_t     width, height;
+
+   enum dri3_buffer_type        buffer_type;
+};
+
+struct dri3_display
+{
+   __GLXDRIdisplay base;
+
+   const __DRIextension *loader_extensions[8];
+
+   /* DRI3 bits */
+   int dri3Major;
+   int dri3Minor;
+
+   /* Present bits */
+   int hasPresent;
+   int presentMajor;
+   int presentMinor;
+};
+
+struct dri3_screen {
+   struct glx_screen base;
+
+   __DRIscreen *driScreen;
+   __GLXDRIscreen vtable;
+
+   const __DRIimageExtension *image;
+   const __DRIimageDriverExtension *image_driver;
+   const __DRIcoreExtension *core;
+   const __DRI2flushExtension *f;
+   const __DRI2configQueryExtension *config;
+   const __DRItexBufferExtension *texBuffer;
+   const __DRI2throttleExtension *throttle;
+   const __DRIconfig **driver_configs;
+
+   void *driver;
+   int fd;
+
+   Bool show_fps;
+};
+
+struct dri3_context
+{
+   struct glx_context base;
+   __DRIcontext *driContext;
+};
+
+#define DRI3_MAX_BACK   2
+#define DRI3_BACK_ID(i) (i)
+#define DRI3_FRONT_ID   (DRI3_MAX_BACK)
+
+static inline int
+dri3_buf_id_next(int buf_id)
+{
+   if (buf_id == DRI3_MAX_BACK - 1)
+      return 0;
+   return buf_id + 1;
+}
+
+static inline int
+dri3_buf_id_prev(int buf_id)
+{
+   if (buf_id == 0)
+      return DRI3_MAX_BACK - 1;
+   return buf_id - 1;
+}
+
+static inline int
+dri3_pixmap_buf_id(enum dri3_buffer_type buffer_type)
+{
+   if (buffer_type == dri3_buffer_back)
+      return DRI3_BACK_ID(0);
+   else
+      return DRI3_FRONT_ID;
+}
+
+struct dri3_drawable
+{
+   __GLXDRIdrawable base;
+   __DRIdrawable *driDrawable;
+   int width, height;
+   int swap_interval;
+   uint8_t have_back;
+   uint8_t have_fake_front;
+   uint8_t is_pixmap;
+
+   uint32_t present_request_serial;
+   uint32_t present_event_serial;
+
+   uint64_t sbc;
+
+   uint64_t ust, msc;
+
+   /* For WaitMSC */
+   uint32_t     present_msc_request_serial;
+   uint32_t     present_msc_event_serial;
+   
+   uint64_t previous_time;
+   unsigned frames;
+
+   struct dri3_buffer *buffers[1 + DRI3_MAX_BACK];
+   int cur_back;
+   int depth;
+
+   uint32_t *stamp;
+
+   xcb_present_event_t eid;
+   xcb_gcontext_t gc;
+   const xcb_query_extension_reply_t *present_extension;
+   xcb_special_event_t *special_event;
+};
+
+char *
+dri3_get_driver_for_fd(int fd);
diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h
index 81ae792..ec168aa 100644
--- a/src/glx/glxclient.h
+++ b/src/glx/glxclient.h
@@ -150,6 +150,7 @@ extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy);
 extern void dri2InvalidateBuffers(Display *dpy, XID drawable);
 extern unsigned dri2GetSwapEventType(Display *dpy, XID drawable);
 
+extern __GLXDRIdisplay *dri3_create_display(Display * dpy);
 
 /*
 ** Functions to obtain driver configuration information from a direct
@@ -582,6 +583,7 @@ struct glx_display
    __GLXDRIdisplay *driswDisplay;
    __GLXDRIdisplay *driDisplay;
    __GLXDRIdisplay *dri2Display;
+   __GLXDRIdisplay *dri3Display;
 #endif
 };
 
diff --git a/src/glx/glxext.c b/src/glx/glxext.c
index bea1ccb..c6e4d9f 100644
--- a/src/glx/glxext.c
+++ b/src/glx/glxext.c
@@ -770,7 +770,9 @@ AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
    for (i = 0; i < screens; i++, psc++) {
       psc = NULL;
 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
-      if (priv->dri2Display)
+      if (priv->dri3Display)
+         psc = (*priv->dri3Display->createScreen) (i, priv);
+      if (psc == NULL && priv->dri2Display)
 	 psc = (*priv->dri2Display->createScreen) (i, priv);
       if (psc == NULL && priv->driDisplay)
 	 psc = (*priv->driDisplay->createScreen) (i, priv);
@@ -863,6 +865,8 @@ __glXInitialize(Display * dpy)
     ** (e.g., those called in AllocAndFetchScreenConfigs).
     */
    if (glx_direct && glx_accel) {
+      if (!getenv("LIBGL_DRI3_DISABLE"))
+         dpyPriv->dri3Display = dri3_create_display(dpy);
       dpyPriv->dri2Display = dri2CreateDisplay(dpy);
       dpyPriv->driDisplay = driCreateDisplay(dpy);
    }
-- 
1.8.4.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_*
  2013-11-05  2:23 ` [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_* Keith Packard
@ 2013-11-05  3:01   ` Jordan Justen
  2013-11-05  4:11     ` Keith Packard
  2013-11-05 22:35   ` Kristian Høgsberg
  1 sibling, 1 reply; 36+ messages in thread
From: Jordan Justen @ 2013-11-05  3:01 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa-dev@lists.freedesktop.org, dri-devel

On Mon, Nov 4, 2013 at 6:23 PM, Keith Packard <keithp@keithp.com> wrote:
> The __DRI_IMAGE_FORMAT codes are used by the image extension, drivers need to
> be able to translate between them. Instead of duplicating this translation in
> each driver, create a shared version.
>
> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
>  src/mesa/drivers/dri/common/dri_util.c | 62 ++++++++++++++++++++++++++++++++++
>  src/mesa/drivers/dri/common/dri_util.h |  6 ++++
>  2 files changed, 68 insertions(+)
>
> diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
> index 95c8b41..76c8ae5 100644
> --- a/src/mesa/drivers/dri/common/dri_util.c
> +++ b/src/mesa/drivers/dri/common/dri_util.c
> @@ -792,3 +792,65 @@ driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv)
>        assert(fb->Height == dPriv->h);
>     }
>  }
> +
> +uint32_t
> +driGLFormatToImageFormat(gl_format format)
> +{
> +   switch (format) {
> +   case MESA_FORMAT_RGB565:
> +      return __DRI_IMAGE_FORMAT_RGB565;
> +   case MESA_FORMAT_XRGB8888:
> +      return __DRI_IMAGE_FORMAT_XRGB8888;
> +   case MESA_FORMAT_ARGB2101010:
> +      return __DRI_IMAGE_FORMAT_ARGB2101010;
> +   case MESA_FORMAT_XRGB2101010_UNORM:
> +      return __DRI_IMAGE_FORMAT_XRGB2101010;
> +   case MESA_FORMAT_ARGB8888:
> +      return __DRI_IMAGE_FORMAT_ARGB8888;
> +   case MESA_FORMAT_RGBA8888_REV:
> +      return __DRI_IMAGE_FORMAT_ABGR8888;
> +   case MESA_FORMAT_RGBX8888_REV:
> +      return __DRI_IMAGE_FORMAT_XBGR8888;
> +   case MESA_FORMAT_R8:
> +      return __DRI_IMAGE_FORMAT_R8;
> +   case MESA_FORMAT_GR88:
> +      return __DRI_IMAGE_FORMAT_GR88;
> +   case MESA_FORMAT_NONE:
> +      return __DRI_IMAGE_FORMAT_NONE;
> +   case MESA_FORMAT_SARGB8:
> +      return __DRI_IMAGE_FORMAT_SARGB8;

After patch 6, this will add SARGB8, right? So, maybe add this to the
commit message, or separate out adding SARGB8 into a separate commit?

Patches 1-6: Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

-Jordan

> +   default:
> +      return 0;
> +   }
> +}
> +
> +gl_format
> +driImageFormatToGLFormat(uint32_t image_format)
> +{
> +   switch (image_format) {
> +   case __DRI_IMAGE_FORMAT_RGB565:
> +      return MESA_FORMAT_RGB565;
> +   case __DRI_IMAGE_FORMAT_XRGB8888:
> +      return MESA_FORMAT_XRGB8888;
> +   case __DRI_IMAGE_FORMAT_ARGB2101010:
> +      return MESA_FORMAT_ARGB2101010;
> +   case __DRI_IMAGE_FORMAT_XRGB2101010:
> +      return MESA_FORMAT_XRGB2101010_UNORM;
> +   case __DRI_IMAGE_FORMAT_ARGB8888:
> +      return MESA_FORMAT_ARGB8888;
> +   case __DRI_IMAGE_FORMAT_ABGR8888:
> +      return MESA_FORMAT_RGBA8888_REV;
> +   case __DRI_IMAGE_FORMAT_XBGR8888:
> +      return MESA_FORMAT_RGBX8888_REV;
> +   case __DRI_IMAGE_FORMAT_R8:
> +      return MESA_FORMAT_R8;
> +   case __DRI_IMAGE_FORMAT_GR88:
> +      return MESA_FORMAT_GR88;
> +   case __DRI_IMAGE_FORMAT_SARGB8:
> +      return MESA_FORMAT_SARGB8;
> +   case __DRI_IMAGE_FORMAT_NONE:
> +      return MESA_FORMAT_NONE;
> +   default:
> +      return MESA_FORMAT_NONE;
> +   }
> +}
> diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
> index 5b56061..fd40769 100644
> --- a/src/mesa/drivers/dri/common/dri_util.h
> +++ b/src/mesa/drivers/dri/common/dri_util.h
> @@ -271,6 +271,12 @@ struct __DRIdrawableRec {
>      } dri2;
>  };
>
> +extern uint32_t
> +driGLFormatToImageFormat(gl_format format);
> +
> +extern gl_format
> +driImageFormatToGLFormat(uint32_t image_format);
> +
>  extern void
>  dri2InvalidateDrawable(__DRIdrawable *drawable);
>
> --
> 1.8.4.2
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_*
  2013-11-05  3:01   ` Jordan Justen
@ 2013-11-05  4:11     ` Keith Packard
  2013-11-05 22:53       ` Jordan Justen
  0 siblings, 1 reply; 36+ messages in thread
From: Keith Packard @ 2013-11-05  4:11 UTC (permalink / raw)
  To: Jordan Justen; +Cc: mesa-dev@lists.freedesktop.org, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 701 bytes --]

Jordan Justen <jljusten@gmail.com> writes:


> After patch 6, this will add SARGB8, right? So, maybe add this to the
> commit message, or separate out adding SARGB8 into a separate commit?

I added the SARGB8 define in patch 4; is there some other separation you
think would be warranted?

Oh, just so everyone knows -- krh and I chatted for a while this morning
and decided that this whole __DRI_IMAGE_FORMAT_* stuff is just a bad
idea and we should remove it all and just use __DRI_IMAGE_FOURCC_*
everywhere. I didn't want to mix that change up with this series though.

> Patches 1-6: Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

Thanks!

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 156 bytes --]

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/8] Add DRIimage-based DRI3/Present loader
  2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
                   ` (7 preceding siblings ...)
  2013-11-05  2:23 ` [PATCH 8/8] Add DRI3+Present loader Keith Packard
@ 2013-11-05 16:40 ` Keith Packard
  2013-11-05 20:04   ` Eric Anholt
  8 siblings, 1 reply; 36+ messages in thread
From: Keith Packard @ 2013-11-05 16:40 UTC (permalink / raw)
  To: mesa-dev; +Cc: dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 2975 bytes --]

Keith Packard <keithp@keithp.com> writes:

> This sequence first adds a a couple of new DRIimage extensions to the
> dri/common, dri/i915 and dri/i965 directories which define a
> loader-independent API for managing window system operations.
>
> The last patch adds a new DRI3000 loader using those new interfaces.

I've figured out that I can also re-use dri2CreateNewScreen2 for the
image driver bits, as long as I change that function to also look up the
image loader. That means there are *no* new dri_util functions needed.

To recap, the changes needed to support using the DRIimageExtension
interfaces for allocating buffers from the driver in the loader are:

    DRIimageDriverExtension

        A proper subset of DRIdri2DriverExtension, which uses
        the same five functions involved in creating new objects:

           /* Common DRI functions, shared with DRI2 */
           __DRIcreateNewScreen2        createNewScreen2;
           __DRIcreateNewDrawable       createNewDrawable;
           __DRIcreateNewContext        createNewContext;
           __DRIcreateContextAttribs    createContextAttribs;
           __DRIgetAPIMask              getAPIMask;
        
    DRIimageLoaderExtension

        Contains just two functions, one to allocate buffers and one to
        copy the fake front to the real front when flushing stuff.

	   /**
	    * Allocate color buffers.
	    *
	    * \param driDrawable
	    * \param width              Width of allocated buffers
	    * \param height             Height of allocated buffers
	    * \param format             one of __DRI_IMAGE_FORMAT_*
	    * \param stamp              Address of variable to be updated when
	    *                           getBuffers must be called again
	    * \param loaderPrivate      The loaderPrivate for driDrawable
	    * \param buffer_mask        Set of buffers to allocate
	    * \param buffers            Returned buffers
	    */
	   int (*getBuffers)(__DRIdrawable *driDrawable,
	                     int *width, int *height,
	                     unsigned int format,
	                     uint32_t *stamp,
	                     void *loaderPrivate,
	                     uint32_t buffer_mask,
	                     struct __DRIimageList *buffers);
	
	    /**
	     * Flush pending front-buffer rendering
	     *
	     * Any rendering that has been performed to the
	     * fake front will be flushed to the front
	     *
	     * \param driDrawable    Drawable whose front-buffer is to be flushed
	     * \param loaderPrivate  Loader's private data that was previously passed
	     *                       into __DRIdri2ExtensionRec::createNewDrawable
	     */
	    void (*flushFrontBuffer)(__DRIdrawable *driDrawable, void *loaderPrivate);

Each driver will need to have a path to use the image loader to get
color buffers using the DRIimageLoaderExtension getBuffers function.

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/8] Add DRIimage-based DRI3/Present loader
  2013-11-05 16:40 ` [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
@ 2013-11-05 20:04   ` Eric Anholt
  2013-11-05 22:09     ` Kristian Høgsberg
  2013-11-05 23:54     ` Keith Packard
  0 siblings, 2 replies; 36+ messages in thread
From: Eric Anholt @ 2013-11-05 20:04 UTC (permalink / raw)
  To: Keith Packard, mesa-dev; +Cc: dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1755 bytes --]

Keith Packard <keithp@keithp.com> writes:

> Keith Packard <keithp@keithp.com> writes:
>
>> This sequence first adds a a couple of new DRIimage extensions to the
>> dri/common, dri/i915 and dri/i965 directories which define a
>> loader-independent API for managing window system operations.
>>
>> The last patch adds a new DRI3000 loader using those new interfaces.
>
> I've figured out that I can also re-use dri2CreateNewScreen2 for the
> image driver bits, as long as I change that function to also look up the
> image loader. That means there are *no* new dri_util functions needed.
>
> To recap, the changes needed to support using the DRIimageExtension
> interfaces for allocating buffers from the driver in the loader are:
>
>     DRIimageDriverExtension
>
>         A proper subset of DRIdri2DriverExtension, which uses
>         the same five functions involved in creating new objects:
>
>            /* Common DRI functions, shared with DRI2 */
>            __DRIcreateNewScreen2        createNewScreen2;
>            __DRIcreateNewDrawable       createNewDrawable;
>            __DRIcreateNewContext        createNewContext;
>            __DRIcreateContextAttribs    createContextAttribs;
>            __DRIgetAPIMask              getAPIMask;

It seems like we could just stick these things in __DRI_CORE as opposed
to having another new extension to look up.  The downside I see there is
bugs in the server, which have patches at xserver-driinterface-versions
of my tree.  (Unfortunately, I'm having a hard time building the server
currently, so no testing yet).  Having a new extension whose name has
nothing to do with the functions in it seems really weird.

Also, apologies for not having done this myself for my CreateNewScreen2
change.

[-- Attachment #1.2: Type: application/pgp-signature, Size: 835 bytes --]

[-- Attachment #2: Type: text/plain, Size: 156 bytes --]

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-05  2:23 ` [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension Keith Packard
@ 2013-11-05 20:05   ` Eric Anholt
  2013-11-05 23:47     ` Keith Packard
  2013-11-05 22:59   ` Kristian Høgsberg
  2013-11-06  6:25   ` Kristian Høgsberg
  2 siblings, 1 reply; 36+ messages in thread
From: Eric Anholt @ 2013-11-05 20:05 UTC (permalink / raw)
  To: Keith Packard, mesa3d-dev; +Cc: dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 12074 bytes --]

Keith Packard <keithp@keithp.com> writes:

> These provide an interface between the driver and the loader to allocate
> color buffers through the DRIimage extension interface rather than through a
> loader-specific extension (as is used by DRI2, for instance).
>
> The driver uses the loader 'getBuffers' interface to allocate color buffers.
>
> The loader uses the createNewScreen2, createNewDrawable, createNewContext,
> getAPIMask and createContextAttribs APIS (mostly shared with DRI2).
>
> This interface will work with the DRI3 loader, and should also work with GBM
> and other loaders so that drivers need not be customized for each new loader
> interface, as long as they provide this image interface.

Most of my review was going to be whining about yet another (broken)
copy of dri2CreateNewScreen2.  Sounds like you've fixed that.

> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
>  include/GL/internal/dri_interface.h           | 112 +++++++++++++++++++++++++
>  src/mesa/drivers/dri/common/dri_util.c        | 113 +++++++++++++++++++++++++
>  src/mesa/drivers/dri/common/dri_util.h        |   6 ++
>  src/mesa/drivers/dri/i915/intel_context.c     | 111 ++++++++++++++++++++++++-
>  src/mesa/drivers/dri/i915/intel_mipmap_tree.c |  33 ++++++++
>  src/mesa/drivers/dri/i915/intel_mipmap_tree.h |   8 ++
>  src/mesa/drivers/dri/i915/intel_screen.c      |   1 +
>  src/mesa/drivers/dri/i965/brw_context.c       | 114 ++++++++++++++++++++++++--
>  src/mesa/drivers/dri/i965/brw_context.h       |  16 ++--
>  src/mesa/drivers/dri/i965/intel_mipmap_tree.c |  61 ++++++++++++++
>  src/mesa/drivers/dri/i965/intel_mipmap_tree.h |   8 ++
>  src/mesa/drivers/dri/i965/intel_screen.c      |   5 +-
>  12 files changed, 568 insertions(+), 20 deletions(-)
>
> diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
> index 907aeca..8fc1fa6 100644
> --- a/include/GL/internal/dri_interface.h
> +++ b/include/GL/internal/dri_interface.h
> @@ -86,6 +86,10 @@ typedef struct __DRIdri2LoaderExtensionRec	__DRIdri2LoaderExtension;
>  typedef struct __DRI2flushExtensionRec	__DRI2flushExtension;
>  typedef struct __DRI2throttleExtensionRec	__DRI2throttleExtension;
>  
> +
> +typedef struct __DRIimageLoaderExtensionRec     __DRIimageLoaderExtension;
> +typedef struct __DRIimageDriverExtensionRec     __DRIimageDriverExtension;
> +
>  /*@}*/
>  
>  
> @@ -1288,4 +1292,112 @@ typedef struct __DRIDriverVtableExtensionRec {
>      const struct __DriverAPIRec *vtable;
>  } __DRIDriverVtableExtension;
>  
> +/**
> + * Image Loader extension. Drivers use this to allocate color buffers
> + */


> +
> +#define __DRI_DRIVER_EXTENSIONS "__driDriverExtensions"

This looks like rebase fail

> +#define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER"
> +#define __DRI_IMAGE_LOADER_VERSION 1
> +
> +struct __DRIimageLoaderExtensionRec {
> +    __DRIextension base;
> +
> +   /**
> +    * Allocate color buffers.
> +    *
> +    * \param driDrawable
> +    * \param width              Width of allocated buffers
> +    * \param height             Height of allocated buffers
> +    * \param format             one of __DRI_IMAGE_FORMAT_*
> +    * \param stamp              Address of variable to be updated when
> +    *                           getBuffers must be called again
> +    * \param loaderPrivate      The loaderPrivate for driDrawable
> +    * \param buffer_mask        Set of buffers to allocate
> +    * \param buffers            Returned buffers
> +    */
> +   int (*getBuffers)(__DRIdrawable *driDrawable,
> +                     int *width, int *height,
> +                     unsigned int format,
> +                     uint32_t *stamp,
> +                     void *loaderPrivate,
> +                     uint32_t buffer_mask,
> +                     struct __DRIimageList *buffers);
> +
> +    /**
> +     * Flush pending front-buffer rendering
> +     *
> +     * Any rendering that has been performed to the
> +     * fake front will be flushed to the front
> +     *
> +     * \param driDrawable    Drawable whose front-buffer is to be flushed
> +     * \param loaderPrivate  Loader's private data that was previously passed
> +     *                       into __DRIdri2ExtensionRec::createNewDrawable
> +     */
> +    void (*flushFrontBuffer)(__DRIdrawable *driDrawable, void *loaderPrivate);
> +};
> +
> +/**
> + * DRI extension.
> + */
> +
> +//struct gl_context;
> +//struct dd_function_table;

Looks like development leftovers.

> +typedef __DRIscreen *
> +(*__DRIcreateNewScreen2)(int screen, int fd,
> +                         const __DRIextension **extensions,
> +                         const __DRIextension **driver_extensions,
> +                         const __DRIconfig ***driver_configs,
> +                         void *loaderPrivate);
> +
> +typedef __DRIdrawable *
> +(*__DRIcreateNewDrawable)(__DRIscreen *screen,
> +                          const __DRIconfig *config,
> +                          void *loaderPrivate);
> +
> +typedef __DRIcontext *
> +(*__DRIcreateNewContext)(__DRIscreen *screen,
> +                         const __DRIconfig *config,
> +                         __DRIcontext *shared,
> +                         void *loaderPrivate);
> +
> +typedef __DRIcontext *
> +(*__DRIcreateContextAttribs)(__DRIscreen *screen,
> +                             int api,
> +                             const __DRIconfig *config,
> +                             __DRIcontext *shared,
> +                             unsigned num_attribs,
> +                             const uint32_t *attribs,
> +                             unsigned *error,
> +                             void *loaderPrivate);
> +typedef unsigned int
> +(*__DRIgetAPIMask)(__DRIscreen *screen);

Maybe append "Func" to the typedefs so they don't look like just another
struct in the declarations?  And since they're supposed to be the same
function pointers as in the __DRIswrastExtensionRec and
__DRIdri2ExtensionRec, change them to this typedef, too?


> +static void
> +intel_update_image_buffers(struct intel_context *intel, __DRIdrawable *drawable)
> +{
> +   struct gl_framebuffer *fb = drawable->driverPrivate;
> +   __DRIscreen *screen = intel->intelScreen->driScrnPriv;
> +   struct intel_renderbuffer *front_rb;
> +   struct intel_renderbuffer *back_rb;
> +   struct __DRIimageList images;
> +   unsigned int format;
> +   uint32_t buffer_mask = 0;
> +
> +   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
> +   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
> +
> +   if (back_rb)
> +      format = intel_rb_format(back_rb);
> +   else if (front_rb)
> +      format = intel_rb_format(front_rb);
> +   else
> +      return;
> +
> +   if ((intel->is_front_buffer_rendering || intel->is_front_buffer_reading || !back_rb) && front_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
> +
> +   if (back_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
> +
> +   (*screen->image.loader->getBuffers) (drawable,
> +                                        &drawable->w,
> +                                        &drawable->h,
> +                                        driGLFormatToImageFormat(format),
> +                                        &drawable->dri2.stamp,
> +                                        drawable->loaderPrivate,
> +                                        buffer_mask,
> +                                        &images);
> +
> +   if (images.front) {
> +      assert(front_rb);
> +      intel_update_image_buffer(intel,
> +                                drawable,
> +                                front_rb,
> +                                images.front,
> +                                __DRI_IMAGE_BUFFER_FRONT);
> +   }
> +   if (images.back)
> +      intel_update_image_buffer(intel,
> +                                drawable,
> +                                back_rb,
> +                                images.back,
> +                                __DRI_IMAGE_BUFFER_BACK);
> +}

It looks like getBuffers could just be two getBuffer calls, except for
the updating of width and height.  Have you looked into doing things
that way at all?

> @@ -549,7 +549,7 @@ brw_process_driconf_options(struct brw_context *brw)
>        driQueryOptionb(options, "disable_glsl_line_continuations");
>  }
>  
> -bool
> +GLboolean
>  brwCreateContext(gl_api api,
>  	         const struct gl_config *mesaVis,
>  		 __DRIcontext *driContextPriv,

Unrelated change?

> +static void
> +intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
> +{
> +   struct gl_framebuffer *fb = drawable->driverPrivate;
> +   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
> +   struct intel_renderbuffer *front_rb;
> +   struct intel_renderbuffer *back_rb;
> +   struct __DRIimageList images;
> +   unsigned int format;
> +   uint32_t buffer_mask = 0;
> +
> +   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
> +   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
> +
> +   if (back_rb)
> +      format = intel_rb_format(back_rb);
> +   else if (front_rb)
> +      format = intel_rb_format(front_rb);
> +   else
> +      return;
> +
> +   if ((brw->is_front_buffer_rendering || brw->is_front_buffer_reading || !back_rb) && front_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
> +
> +   if (back_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
> +
> +   (*screen->image.loader->getBuffers) (drawable,
> +                                        &drawable->w,
> +                                        &drawable->h,
> +                                        driGLFormatToImageFormat(format),
> +                                        &drawable->dri2.stamp,
> +                                        drawable->loaderPrivate,
> +                                        buffer_mask,
> +                                        &images);
> +
> +   if (images.front) {
> +      assert(front_rb);
> +      intel_update_image_buffer(brw,
> +                                drawable,
> +                                front_rb,
> +                                images.front,
> +                                __DRI_IMAGE_BUFFER_FRONT);
> +   }
> +   if (images.back)
> +      intel_update_image_buffer(brw,
> +                                drawable,
> +                                back_rb,
> +                                images.back,
> +                                __DRI_IMAGE_BUFFER_BACK);
> +}

Style nit: we try and put braces around multi-line things like this,
even if they are a single statement.

> diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
> index bec4d6b..1ecbfb7 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.h
> +++ b/src/mesa/drivers/dri/i965/brw_context.h
> @@ -1477,14 +1477,14 @@ void intel_prepare_render(struct brw_context *brw);
>  void intel_resolve_for_dri2_flush(struct brw_context *brw,
>                                    __DRIdrawable *drawable);
>  
> -bool brwCreateContext(gl_api api,
> -		      const struct gl_config *mesaVis,
> -		      __DRIcontext *driContextPriv,
> -                      unsigned major_version,
> -                      unsigned minor_version,
> -                      uint32_t flags,
> -                      unsigned *error,
> -		      void *sharedContextPrivate);
> +GLboolean brwCreateContext(gl_api api,
> +                           const struct gl_config *mesaVis,
> +                           __DRIcontext *driContextPriv,
> +                           unsigned major_version,
> +                           unsigned minor_version,
> +                           uint32_t flags,
> +                           unsigned *error,
> +                           void *sharedContextPrivate);

Unrelated change.


[-- Attachment #1.2: Type: application/pgp-signature, Size: 835 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/8] Add DRIimage-based DRI3/Present loader
  2013-11-05 20:04   ` Eric Anholt
@ 2013-11-05 22:09     ` Kristian Høgsberg
  2013-11-05 23:54     ` Keith Packard
  1 sibling, 0 replies; 36+ messages in thread
From: Kristian Høgsberg @ 2013-11-05 22:09 UTC (permalink / raw)
  To: Eric Anholt; +Cc: mesa-dev, dri-devel

On Tue, Nov 05, 2013 at 12:04:32PM -0800, Eric Anholt wrote:
> Keith Packard <keithp@keithp.com> writes:
> 
> > Keith Packard <keithp@keithp.com> writes:
> >
> >> This sequence first adds a a couple of new DRIimage extensions to the
> >> dri/common, dri/i915 and dri/i965 directories which define a
> >> loader-independent API for managing window system operations.
> >>
> >> The last patch adds a new DRI3000 loader using those new interfaces.
> >
> > I've figured out that I can also re-use dri2CreateNewScreen2 for the
> > image driver bits, as long as I change that function to also look up the
> > image loader. That means there are *no* new dri_util functions needed.
> >
> > To recap, the changes needed to support using the DRIimageExtension
> > interfaces for allocating buffers from the driver in the loader are:
> >
> >     DRIimageDriverExtension
> >
> >         A proper subset of DRIdri2DriverExtension, which uses
> >         the same five functions involved in creating new objects:
> >
> >            /* Common DRI functions, shared with DRI2 */
> >            __DRIcreateNewScreen2        createNewScreen2;
> >            __DRIcreateNewDrawable       createNewDrawable;
> >            __DRIcreateNewContext        createNewContext;
> >            __DRIcreateContextAttribs    createContextAttribs;
> >            __DRIgetAPIMask              getAPIMask;
> 
> It seems like we could just stick these things in __DRI_CORE as opposed
> to having another new extension to look up.  The downside I see there is
> bugs in the server, which have patches at xserver-driinterface-versions
> of my tree.  (Unfortunately, I'm having a hard time building the server
> currently, so no testing yet).  Having a new extension whose name has
> nothing to do with the functions in it seems really weird.

It may make more sense to just extend the existing interfaces, but
when we discussed DRIimageDriverExtension, the idea was that we could
phase out DRIdri2Extension.  I think that still makes sense but
introducing more extensions doesn't make this interface better.

The way this was done originally was that we have DRIcoreExtension
which provided DRI1 support.  The DRIdri2Extension extension replaces
some of the core functions (it has a createNewScreen that doesn't take
a sarea handle, for example...) and allows a loader to implement DRI2,
but you have to use both extensions.  DRIswrastExtension works in a
similar for swrast.

The idea was to share the core functionality, but it's obviously messy
to have to mix two extensions to get things working.  If we're
introducing a new extension, I'd suggest we move the functions from
DRIcoreExtension that we still use into this new extension and make it
completely replace DRIcoreExtension and DRIdri2Extension.  The
functions from the core extension we still use are:

    void (*destroyScreen)(__DRIscreen *screen);

    const __DRIextension **(*getExtensions)(__DRIscreen *screen);

    int (*getConfigAttrib)(const __DRIconfig *config,
                           unsigned int attrib,
                           unsigned int *value);

    int (*indexConfigAttrib)(const __DRIconfig *config, int index,
                             unsigned int *attrib, unsigned int *value);

    void (*destroyDrawable)(__DRIdrawable *drawable);

    int (*copyContext)(__DRIcontext *dest,
                       __DRIcontext *src,
                       unsigned long mask);

    void (*destroyContext)(__DRIcontext *context);

    int (*bindContext)(__DRIcontext *ctx,
                       __DRIdrawable *pdraw,
                       __DRIdrawable *pread);

    int (*unbindContext)(__DRIcontext *ctx);

and if we add those to DRIimageDriverExtension the loader only needs
to look for that and the DRIimage extension.  Of course, the
implementation is already in dri_util.c, we just need to set the
function pointers to the DRIcoreExtension functions we share.

Kristian

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/8] dri/intel: Add explicit size parameter to intel_region_alloc_for_fd
  2013-11-05  2:23 ` [PATCH 3/8] dri/intel: Add explicit size parameter to intel_region_alloc_for_fd Keith Packard
@ 2013-11-05 22:23   ` Kristian Høgsberg
  2013-11-06  0:52     ` Keith Packard
  2013-11-07  5:17     ` Christopher James Halse Rogers
  0 siblings, 2 replies; 36+ messages in thread
From: Kristian Høgsberg @ 2013-11-05 22:23 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa3d-dev, dri-devel

On Mon, Nov 04, 2013 at 06:23:23PM -0800, Keith Packard wrote:
> Instead of assuming that the size will be height * pitch, have the caller pass
> in the size explicitly.
> 
> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
>  src/mesa/drivers/dri/i915/intel_regions.c | 4 ++--
>  src/mesa/drivers/dri/i915/intel_regions.h | 2 +-
>  src/mesa/drivers/dri/i915/intel_screen.c  | 2 +-
>  src/mesa/drivers/dri/i965/intel_regions.c | 4 ++--
>  src/mesa/drivers/dri/i965/intel_regions.h | 1 +
>  src/mesa/drivers/dri/i965/intel_screen.c  | 2 +-
>  6 files changed, 8 insertions(+), 7 deletions(-)
> 
> diff --git a/src/mesa/drivers/dri/i915/intel_regions.c b/src/mesa/drivers/dri/i915/intel_regions.c
> index 44f7030..9f5b89e 100644
> --- a/src/mesa/drivers/dri/i915/intel_regions.c
> +++ b/src/mesa/drivers/dri/i915/intel_regions.c
> @@ -209,6 +209,7 @@ struct intel_region *
>  intel_region_alloc_for_fd(struct intel_screen *screen,
>                            GLuint cpp,
>                            GLuint width, GLuint height, GLuint pitch,
> +                          GLuint size,
>                            int fd, const char *name)
>  {
>     struct intel_region *region;
> @@ -216,8 +217,7 @@ intel_region_alloc_for_fd(struct intel_screen *screen,
>     int ret;
>     uint32_t bit_6_swizzle, tiling;
>  
> -   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr,
> -                                               fd, height * pitch);
> +   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr, fd, size);

The 3.12 kernel let's you get the bo size from lseek on the dma_buf
fd.  I added libdrm support for getting the size that, and if that
works, it overrides the user provided size:

  http://cgit.freedesktop.org/mesa/drm/commit/?id=9c52c3dc4763336884277d8005eac7e6efb77600

3.12 is the first kernel where dma_buf fd passing works reliably
anyway and the first kernel with render-nodes, so it's not worth the
trouble to try to make this work for older kernels.

Regardless, this patchs looks good.

Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>

>     if (buffer == NULL)
>        return NULL;
>     ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
> diff --git a/src/mesa/drivers/dri/i915/intel_regions.h b/src/mesa/drivers/dri/i915/intel_regions.h
> index 5c612a9..6bc4a42 100644
> --- a/src/mesa/drivers/dri/i915/intel_regions.h
> +++ b/src/mesa/drivers/dri/i915/intel_regions.h
> @@ -91,7 +91,7 @@ struct intel_region *
>  intel_region_alloc_for_fd(struct intel_screen *screen,
>                            GLuint cpp,
>                            GLuint width, GLuint height, GLuint pitch,
> -                          int fd, const char *name);
> +                          GLuint size, int fd, const char *name);
>  
>  bool
>  intel_region_flink(struct intel_region *region, uint32_t *name);
> diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
> index 3f54752..085e894 100644
> --- a/src/mesa/drivers/dri/i915/intel_screen.c
> +++ b/src/mesa/drivers/dri/i915/intel_screen.c
> @@ -653,7 +653,7 @@ intel_create_image_from_fds(__DRIscreen *screen,
>        return NULL;
>  
>     image->region = intel_region_alloc_for_fd(intelScreen,
> -                                             1, width, height,
> +                                             1, width, height, height * strides[0],
>                                               strides[0], fds[0], "image");
>     if (image->region == NULL) {
>        free(image);
> diff --git a/src/mesa/drivers/dri/i965/intel_regions.c b/src/mesa/drivers/dri/i965/intel_regions.c
> index a6b80fd..3920f4f 100644
> --- a/src/mesa/drivers/dri/i965/intel_regions.c
> +++ b/src/mesa/drivers/dri/i965/intel_regions.c
> @@ -209,6 +209,7 @@ struct intel_region *
>  intel_region_alloc_for_fd(struct intel_screen *screen,
>                            GLuint cpp,
>                            GLuint width, GLuint height, GLuint pitch,
> +                          GLuint size,
>                            int fd, const char *name)
>  {
>     struct intel_region *region;
> @@ -216,8 +217,7 @@ intel_region_alloc_for_fd(struct intel_screen *screen,
>     int ret;
>     uint32_t bit_6_swizzle, tiling;
>  
> -   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr,
> -                                               fd, height * pitch);
> +   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr, fd, size);
>     if (buffer == NULL)
>        return NULL;
>     ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
> diff --git a/src/mesa/drivers/dri/i965/intel_regions.h b/src/mesa/drivers/dri/i965/intel_regions.h
> index f08a113..05dfef3 100644
> --- a/src/mesa/drivers/dri/i965/intel_regions.h
> +++ b/src/mesa/drivers/dri/i965/intel_regions.h
> @@ -92,6 +92,7 @@ struct intel_region *
>  intel_region_alloc_for_fd(struct intel_screen *screen,
>                            GLuint cpp,
>                            GLuint width, GLuint height, GLuint pitch,
> +                          GLuint size,
>                            int fd, const char *name);
>  
>  bool
> diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
> index ce8124b..b89b1a5 100644
> --- a/src/mesa/drivers/dri/i965/intel_screen.c
> +++ b/src/mesa/drivers/dri/i965/intel_screen.c
> @@ -718,7 +718,7 @@ intel_create_image_from_fds(__DRIscreen *screen,
>        return NULL;
>  
>     image->region = intel_region_alloc_for_fd(intelScreen,
> -                                             1, width, height,
> +                                             1, width, height, height * strides[0],
>                                               strides[0], fds[0], "image");
>     if (image->region == NULL) {
>        free(image);
> -- 
> 1.8.4.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_*
  2013-11-05  2:23 ` [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_* Keith Packard
  2013-11-05  3:01   ` Jordan Justen
@ 2013-11-05 22:35   ` Kristian Høgsberg
  2013-11-06  0:54     ` Keith Packard
  1 sibling, 1 reply; 36+ messages in thread
From: Kristian Høgsberg @ 2013-11-05 22:35 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa3d-dev, dri-devel

On Mon, Nov 04, 2013 at 06:23:25PM -0800, Keith Packard wrote:
> The __DRI_IMAGE_FORMAT codes are used by the image extension, drivers need to
> be able to translate between them. Instead of duplicating this translation in
> each driver, create a shared version.

I'll take the bait... before the i915/i965 split, this code was only
needed in this one place.  All other drivers are gallium drivers which
need to convert to galliums enum pipe_format instead of the gl_format
enum.  Anyway, the code certainly looks more at home in dri_util.c.

Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>

> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
>  src/mesa/drivers/dri/common/dri_util.c | 62 ++++++++++++++++++++++++++++++++++
>  src/mesa/drivers/dri/common/dri_util.h |  6 ++++
>  2 files changed, 68 insertions(+)
> 
> diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
> index 95c8b41..76c8ae5 100644
> --- a/src/mesa/drivers/dri/common/dri_util.c
> +++ b/src/mesa/drivers/dri/common/dri_util.c
> @@ -792,3 +792,65 @@ driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv)
>        assert(fb->Height == dPriv->h);
>     }
>  }
> +
> +uint32_t
> +driGLFormatToImageFormat(gl_format format)
> +{
> +   switch (format) {
> +   case MESA_FORMAT_RGB565:
> +      return __DRI_IMAGE_FORMAT_RGB565;
> +   case MESA_FORMAT_XRGB8888:
> +      return __DRI_IMAGE_FORMAT_XRGB8888;
> +   case MESA_FORMAT_ARGB2101010:
> +      return __DRI_IMAGE_FORMAT_ARGB2101010;
> +   case MESA_FORMAT_XRGB2101010_UNORM:
> +      return __DRI_IMAGE_FORMAT_XRGB2101010;
> +   case MESA_FORMAT_ARGB8888:
> +      return __DRI_IMAGE_FORMAT_ARGB8888;
> +   case MESA_FORMAT_RGBA8888_REV:
> +      return __DRI_IMAGE_FORMAT_ABGR8888;
> +   case MESA_FORMAT_RGBX8888_REV:
> +      return __DRI_IMAGE_FORMAT_XBGR8888;
> +   case MESA_FORMAT_R8:
> +      return __DRI_IMAGE_FORMAT_R8;
> +   case MESA_FORMAT_GR88:
> +      return __DRI_IMAGE_FORMAT_GR88;
> +   case MESA_FORMAT_NONE:
> +      return __DRI_IMAGE_FORMAT_NONE;
> +   case MESA_FORMAT_SARGB8:
> +      return __DRI_IMAGE_FORMAT_SARGB8;
> +   default:
> +      return 0;
> +   }
> +}
> +
> +gl_format
> +driImageFormatToGLFormat(uint32_t image_format)
> +{
> +   switch (image_format) {
> +   case __DRI_IMAGE_FORMAT_RGB565:
> +      return MESA_FORMAT_RGB565;
> +   case __DRI_IMAGE_FORMAT_XRGB8888:
> +      return MESA_FORMAT_XRGB8888;
> +   case __DRI_IMAGE_FORMAT_ARGB2101010:
> +      return MESA_FORMAT_ARGB2101010;
> +   case __DRI_IMAGE_FORMAT_XRGB2101010:
> +      return MESA_FORMAT_XRGB2101010_UNORM;
> +   case __DRI_IMAGE_FORMAT_ARGB8888:
> +      return MESA_FORMAT_ARGB8888;
> +   case __DRI_IMAGE_FORMAT_ABGR8888:
> +      return MESA_FORMAT_RGBA8888_REV;
> +   case __DRI_IMAGE_FORMAT_XBGR8888:
> +      return MESA_FORMAT_RGBX8888_REV;
> +   case __DRI_IMAGE_FORMAT_R8:
> +      return MESA_FORMAT_R8;
> +   case __DRI_IMAGE_FORMAT_GR88:
> +      return MESA_FORMAT_GR88;
> +   case __DRI_IMAGE_FORMAT_SARGB8:
> +      return MESA_FORMAT_SARGB8;
> +   case __DRI_IMAGE_FORMAT_NONE:
> +      return MESA_FORMAT_NONE;
> +   default:
> +      return MESA_FORMAT_NONE;
> +   }
> +}
> diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
> index 5b56061..fd40769 100644
> --- a/src/mesa/drivers/dri/common/dri_util.h
> +++ b/src/mesa/drivers/dri/common/dri_util.h
> @@ -271,6 +271,12 @@ struct __DRIdrawableRec {
>      } dri2;
>  };
>  
> +extern uint32_t
> +driGLFormatToImageFormat(gl_format format);
> +
> +extern gl_format
> +driImageFormatToGLFormat(uint32_t image_format);
> +
>  extern void
>  dri2InvalidateDrawable(__DRIdrawable *drawable);
>  
> -- 
> 1.8.4.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 6/8] dri/i915,dri/i965: Use driGLFormatToImageFormat and driImageFormatToGLFormat
  2013-11-05  2:23 ` [PATCH 6/8] dri/i915, dri/i965: Use driGLFormatToImageFormat and driImageFormatToGLFormat Keith Packard
@ 2013-11-05 22:37   ` Kristian Høgsberg
  0 siblings, 0 replies; 36+ messages in thread
From: Kristian Høgsberg @ 2013-11-05 22:37 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa3d-dev, dri-devel

On Mon, Nov 04, 2013 at 06:23:26PM -0800, Keith Packard wrote:
> Remove private versions of these functions

Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>

> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
>  src/mesa/drivers/dri/i915/intel_screen.c | 53 ++-------------------------
>  src/mesa/drivers/dri/i965/intel_screen.c | 63 ++------------------------------
>  2 files changed, 8 insertions(+), 108 deletions(-)
> 
> diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
> index 085e894..12113c7 100644
> --- a/src/mesa/drivers/dri/i915/intel_screen.c
> +++ b/src/mesa/drivers/dri/i915/intel_screen.c
> @@ -244,32 +244,8 @@ intel_allocate_image(int dri_format, void *loaderPrivate)
>      image->dri_format = dri_format;
>      image->offset = 0;
>  
> -    switch (dri_format) {
> -    case __DRI_IMAGE_FORMAT_RGB565:
> -       image->format = MESA_FORMAT_RGB565;
> -       break;
> -    case __DRI_IMAGE_FORMAT_XRGB8888:
> -       image->format = MESA_FORMAT_XRGB8888;
> -       break;
> -    case __DRI_IMAGE_FORMAT_ARGB8888:
> -       image->format = MESA_FORMAT_ARGB8888;
> -       break;
> -    case __DRI_IMAGE_FORMAT_ABGR8888:
> -       image->format = MESA_FORMAT_RGBA8888_REV;
> -       break;
> -    case __DRI_IMAGE_FORMAT_XBGR8888:
> -       image->format = MESA_FORMAT_RGBX8888_REV;
> -       break;
> -    case __DRI_IMAGE_FORMAT_R8:
> -       image->format = MESA_FORMAT_R8;
> -       break;
> -    case __DRI_IMAGE_FORMAT_GR88:
> -       image->format = MESA_FORMAT_GR88;
> -       break;
> -    case __DRI_IMAGE_FORMAT_NONE:
> -       image->format = MESA_FORMAT_NONE;
> -       break;
> -    default:
> +    image->format = driImageFormatToGLFormat(dri_format);
> +    if (image->format == 0) {
>         free(image);
>         return NULL;
>      }
> @@ -318,27 +294,6 @@ intel_setup_image_from_dimensions(__DRIimage *image)
>     image->tile_y = 0;
>  }
>  
> -static inline uint32_t
> -intel_dri_format(GLuint format)
> -{
> -   switch (format) {
> -   case MESA_FORMAT_RGB565:
> -      return __DRI_IMAGE_FORMAT_RGB565;
> -   case MESA_FORMAT_XRGB8888:
> -      return __DRI_IMAGE_FORMAT_XRGB8888;
> -   case MESA_FORMAT_ARGB8888:
> -      return __DRI_IMAGE_FORMAT_ARGB8888;
> -   case MESA_FORMAT_RGBA8888_REV:
> -      return __DRI_IMAGE_FORMAT_ABGR8888;
> -   case MESA_FORMAT_R8:
> -      return __DRI_IMAGE_FORMAT_R8;
> -   case MESA_FORMAT_RG88:
> -      return __DRI_IMAGE_FORMAT_GR88;
> -   }
> -
> -   return MESA_FORMAT_NONE;
> -}
> -
>  static __DRIimage *
>  intel_create_image_from_name(__DRIscreen *screen,
>  			     int width, int height, int format,
> @@ -396,7 +351,7 @@ intel_create_image_from_renderbuffer(__DRIcontext *context,
>     image->data = loaderPrivate;
>     intel_region_reference(&image->region, irb->mt->region);
>     intel_setup_image_from_dimensions(image);
> -   image->dri_format = intel_dri_format(image->format);
> +   image->dri_format = driGLFormatToImageFormat(image->format);
>  
>     rb->NeedsFinishRenderTexture = true;
>     return image;
> @@ -450,7 +405,7 @@ intel_create_image_from_texture(__DRIcontext *context, int target,
>     image->format = obj->Image[face][level]->TexFormat;
>     image->data = loaderPrivate;
>     intel_setup_image_from_mipmap_tree(intel, image, iobj->mt, level, zoffset);
> -   image->dri_format = intel_dri_format(image->format);
> +   image->dri_format = driGLFormatToImageFormat(image->format);
>     if (image->dri_format == MESA_FORMAT_NONE) {
>        *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
>        free(image);
> diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
> index b89b1a5..f9339c1 100644
> --- a/src/mesa/drivers/dri/i965/intel_screen.c
> +++ b/src/mesa/drivers/dri/i965/intel_screen.c
> @@ -298,38 +298,8 @@ intel_allocate_image(int dri_format, void *loaderPrivate)
>      image->dri_format = dri_format;
>      image->offset = 0;
>  
> -    switch (dri_format) {
> -    case __DRI_IMAGE_FORMAT_RGB565:
> -       image->format = MESA_FORMAT_RGB565;
> -       break;
> -    case __DRI_IMAGE_FORMAT_XRGB8888:
> -       image->format = MESA_FORMAT_XRGB8888;
> -       break;
> -    case __DRI_IMAGE_FORMAT_ARGB2101010:
> -       image->format = MESA_FORMAT_ARGB2101010;
> -       break;
> -    case __DRI_IMAGE_FORMAT_XRGB2101010:
> -       image->format = MESA_FORMAT_XRGB2101010_UNORM;
> -       break;
> -    case __DRI_IMAGE_FORMAT_ARGB8888:
> -       image->format = MESA_FORMAT_ARGB8888;
> -       break;
> -    case __DRI_IMAGE_FORMAT_ABGR8888:
> -       image->format = MESA_FORMAT_RGBA8888_REV;
> -       break;
> -    case __DRI_IMAGE_FORMAT_XBGR8888:
> -       image->format = MESA_FORMAT_RGBX8888_REV;
> -       break;
> -    case __DRI_IMAGE_FORMAT_R8:
> -       image->format = MESA_FORMAT_R8;
> -       break;
> -    case __DRI_IMAGE_FORMAT_GR88:
> -       image->format = MESA_FORMAT_GR88;
> -       break;
> -    case __DRI_IMAGE_FORMAT_NONE:
> -       image->format = MESA_FORMAT_NONE;
> -       break;
> -    default:
> +    image->format = driImageFormatToGLFormat(dri_format);
> +    if (image->format == 0) {
>         free(image);
>         return NULL;
>      }
> @@ -381,31 +351,6 @@ intel_setup_image_from_dimensions(__DRIimage *image)
>     image->has_depthstencil = false;
>  }
>  
> -static inline uint32_t
> -intel_dri_format(GLuint format)
> -{
> -   switch (format) {
> -   case MESA_FORMAT_RGB565:
> -      return __DRI_IMAGE_FORMAT_RGB565;
> -   case MESA_FORMAT_XRGB8888:
> -      return __DRI_IMAGE_FORMAT_XRGB8888;
> -   case MESA_FORMAT_ARGB8888:
> -      return __DRI_IMAGE_FORMAT_ARGB8888;
> -   case MESA_FORMAT_RGBA8888_REV:
> -      return __DRI_IMAGE_FORMAT_ABGR8888;
> -   case MESA_FORMAT_R8:
> -      return __DRI_IMAGE_FORMAT_R8;
> -   case MESA_FORMAT_RG88:
> -      return __DRI_IMAGE_FORMAT_GR88;
> -   case MESA_FORMAT_XRGB2101010_UNORM:
> -      return __DRI_IMAGE_FORMAT_XRGB2101010;
> -   case MESA_FORMAT_ARGB2101010:
> -      return __DRI_IMAGE_FORMAT_ARGB2101010;
> -   }
> -
> -   return MESA_FORMAT_NONE;
> -}
> -
>  static __DRIimage *
>  intel_create_image_from_name(__DRIscreen *screen,
>  			     int width, int height, int format,
> @@ -464,7 +409,7 @@ intel_create_image_from_renderbuffer(__DRIcontext *context,
>     image->data = loaderPrivate;
>     intel_region_reference(&image->region, irb->mt->region);
>     intel_setup_image_from_dimensions(image);
> -   image->dri_format = intel_dri_format(image->format);
> +   image->dri_format = driGLFormatToImageFormat(image->format);
>     image->has_depthstencil = irb->mt->stencil_mt? true : false;
>  
>     rb->NeedsFinishRenderTexture = true;
> @@ -519,7 +464,7 @@ intel_create_image_from_texture(__DRIcontext *context, int target,
>     image->format = obj->Image[face][level]->TexFormat;
>     image->data = loaderPrivate;
>     intel_setup_image_from_mipmap_tree(brw, image, iobj->mt, level, zoffset);
> -   image->dri_format = intel_dri_format(image->format);
> +   image->dri_format = driGLFormatToImageFormat(image->format);
>     image->has_depthstencil = iobj->mt->stencil_mt? true : false;
>     if (image->dri_format == MESA_FORMAT_NONE) {
>        *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
> -- 
> 1.8.4.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_*
  2013-11-05  4:11     ` Keith Packard
@ 2013-11-05 22:53       ` Jordan Justen
  0 siblings, 0 replies; 36+ messages in thread
From: Jordan Justen @ 2013-11-05 22:53 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa-dev@lists.freedesktop.org, dri-devel

On Mon, Nov 4, 2013 at 8:11 PM, Keith Packard <keithp@keithp.com> wrote:
> Jordan Justen <jljusten@gmail.com> writes:
>> After patch 6, this will add SARGB8, right? So, maybe add this to the
>> commit message, or separate out adding SARGB8 into a separate commit?
>
> I added the SARGB8 define in patch 4; is there some other separation you
> think would be warranted?

I was just noting that a side effect of patch five is adding support
for SARGB8. When you remove the code in patch 6, and use these, you've
now added support for this new format.

Not important, but I thought it might be worth noting in the commit
message. Actually probably noting it in the commit message for patch 6
is better since the change happens at that point.

-Jordan

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-05  2:23 ` [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension Keith Packard
  2013-11-05 20:05   ` Eric Anholt
@ 2013-11-05 22:59   ` Kristian Høgsberg
  2013-11-06  0:59     ` Keith Packard
  2013-11-06  6:25   ` Kristian Høgsberg
  2 siblings, 1 reply; 36+ messages in thread
From: Kristian Høgsberg @ 2013-11-05 22:59 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa3d-dev, dri-devel

On Mon, Nov 04, 2013 at 06:23:27PM -0800, Keith Packard wrote:
> These provide an interface between the driver and the loader to allocate
> color buffers through the DRIimage extension interface rather than through a
> loader-specific extension (as is used by DRI2, for instance).
> 
> The driver uses the loader 'getBuffers' interface to allocate color buffers.
> 
> The loader uses the createNewScreen2, createNewDrawable, createNewContext,
> getAPIMask and createContextAttribs APIS (mostly shared with DRI2).
> 
> This interface will work with the DRI3 loader, and should also work with GBM
> and other loaders so that drivers need not be customized for each new loader
> interface, as long as they provide this image interface.
> 
> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
>  include/GL/internal/dri_interface.h           | 112 +++++++++++++++++++++++++
>  src/mesa/drivers/dri/common/dri_util.c        | 113 +++++++++++++++++++++++++
>  src/mesa/drivers/dri/common/dri_util.h        |   6 ++
>  src/mesa/drivers/dri/i915/intel_context.c     | 111 ++++++++++++++++++++++++-
>  src/mesa/drivers/dri/i915/intel_mipmap_tree.c |  33 ++++++++
>  src/mesa/drivers/dri/i915/intel_mipmap_tree.h |   8 ++
>  src/mesa/drivers/dri/i915/intel_screen.c      |   1 +
>  src/mesa/drivers/dri/i965/brw_context.c       | 114 ++++++++++++++++++++++++--
>  src/mesa/drivers/dri/i965/brw_context.h       |  16 ++--
>  src/mesa/drivers/dri/i965/intel_mipmap_tree.c |  61 ++++++++++++++
>  src/mesa/drivers/dri/i965/intel_mipmap_tree.h |   8 ++
>  src/mesa/drivers/dri/i965/intel_screen.c      |   5 +-
>  12 files changed, 568 insertions(+), 20 deletions(-)
> 
> diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
> index 907aeca..8fc1fa6 100644
> --- a/include/GL/internal/dri_interface.h
> +++ b/include/GL/internal/dri_interface.h
> @@ -86,6 +86,10 @@ typedef struct __DRIdri2LoaderExtensionRec	__DRIdri2LoaderExtension;
>  typedef struct __DRI2flushExtensionRec	__DRI2flushExtension;
>  typedef struct __DRI2throttleExtensionRec	__DRI2throttleExtension;
>  
> +
> +typedef struct __DRIimageLoaderExtensionRec     __DRIimageLoaderExtension;
> +typedef struct __DRIimageDriverExtensionRec     __DRIimageDriverExtension;
> +
>  /*@}*/
>  
>  
> @@ -1288,4 +1292,112 @@ typedef struct __DRIDriverVtableExtensionRec {
>      const struct __DriverAPIRec *vtable;
>  } __DRIDriverVtableExtension;
>  
> +/**
> + * Image Loader extension. Drivers use this to allocate color buffers
> + */
> +
> +#define __DRI_DRIVER_EXTENSIONS "__driDriverExtensions"
> +
> +enum __DRIimageBufferMask {
> +   __DRI_IMAGE_BUFFER_BACK = (1 << 0),
> +   __DRI_IMAGE_BUFFER_FRONT = (1 << 1)
> +};
> +
> +struct __DRIimageList {
> +   __DRIimage *back;
> +   __DRIimage *front;
> +};
> +
> +#define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER"
> +#define __DRI_IMAGE_LOADER_VERSION 1
> +
> +struct __DRIimageLoaderExtensionRec {
> +    __DRIextension base;
> +
> +   /**
> +    * Allocate color buffers.
> +    *
> +    * \param driDrawable
> +    * \param width              Width of allocated buffers
> +    * \param height             Height of allocated buffers
> +    * \param format             one of __DRI_IMAGE_FORMAT_*
> +    * \param stamp              Address of variable to be updated when
> +    *                           getBuffers must be called again
> +    * \param loaderPrivate      The loaderPrivate for driDrawable
> +    * \param buffer_mask        Set of buffers to allocate
> +    * \param buffers            Returned buffers
> +    */
> +   int (*getBuffers)(__DRIdrawable *driDrawable,
> +                     int *width, int *height,

We can drop width and height now and just get it from either of the
returned images.  Format is a function of the __DRIconfig and doesn't
change, so we could make that something you can query from the config
in the interest of further reducing the number of arguments.

I'll give this a try with the GBM and Wayland EGL backends now.

Kristian

> +                     unsigned int format,
> +                     uint32_t *stamp,
> +                     void *loaderPrivate,
> +                     uint32_t buffer_mask,
> +                     struct __DRIimageList *buffers);
> +
> +    /**
> +     * Flush pending front-buffer rendering
> +     *
> +     * Any rendering that has been performed to the
> +     * fake front will be flushed to the front
> +     *
> +     * \param driDrawable    Drawable whose front-buffer is to be flushed
> +     * \param loaderPrivate  Loader's private data that was previously passed
> +     *                       into __DRIdri2ExtensionRec::createNewDrawable
> +     */
> +    void (*flushFrontBuffer)(__DRIdrawable *driDrawable, void *loaderPrivate);
> +};
> +
> +/**
> + * DRI extension.
> + */
> +
> +//struct gl_context;
> +//struct dd_function_table;
> +
> +typedef __DRIscreen *
> +(*__DRIcreateNewScreen2)(int screen, int fd,
> +                         const __DRIextension **extensions,
> +                         const __DRIextension **driver_extensions,
> +                         const __DRIconfig ***driver_configs,
> +                         void *loaderPrivate);
> +
> +typedef __DRIdrawable *
> +(*__DRIcreateNewDrawable)(__DRIscreen *screen,
> +                          const __DRIconfig *config,
> +                          void *loaderPrivate);
> +
> +typedef __DRIcontext *
> +(*__DRIcreateNewContext)(__DRIscreen *screen,
> +                         const __DRIconfig *config,
> +                         __DRIcontext *shared,
> +                         void *loaderPrivate);
> +
> +typedef __DRIcontext *
> +(*__DRIcreateContextAttribs)(__DRIscreen *screen,
> +                             int api,
> +                             const __DRIconfig *config,
> +                             __DRIcontext *shared,
> +                             unsigned num_attribs,
> +                             const uint32_t *attribs,
> +                             unsigned *error,
> +                             void *loaderPrivate);
> +
> +typedef unsigned int
> +(*__DRIgetAPIMask)(__DRIscreen *screen);
> +
> +#define __DRI_IMAGE_DRIVER           "DRI_IMAGE_DRIVER"
> +#define __DRI_IMAGE_DRIVER_VERSION   1
> +
> +struct __DRIimageDriverExtensionRec {
> +   __DRIextension               base;
> +
> +   /* Common DRI functions, shared with DRI2 */
> +   __DRIcreateNewScreen2        createNewScreen2;
> +   __DRIcreateNewDrawable       createNewDrawable;
> +   __DRIcreateNewContext        createNewContext;
> +   __DRIcreateContextAttribs    createContextAttribs;
> +   __DRIgetAPIMask              getAPIMask;
> +};
> +
>  #endif
> diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
> index 76c8ae5..d8cb7f6 100644
> --- a/src/mesa/drivers/dri/common/dri_util.c
> +++ b/src/mesa/drivers/dri/common/dri_util.c
> @@ -854,3 +854,116 @@ driImageFormatToGLFormat(uint32_t image_format)
>        return MESA_FORMAT_NONE;
>     }
>  }
> +
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission.  The copyright holders make no representations
> + * about the suitability of this software for any purpose.  It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +PUBLIC const char __imageConfigOptions[] =
> +   DRI_CONF_BEGIN
> +      DRI_CONF_SECTION_PERFORMANCE
> +         DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
> +      DRI_CONF_SECTION_END
> +   DRI_CONF_END;
> +
> +static void
> +setup_image_loader_extensions(__DRIscreen *psp,
> +                              const __DRIextension *const*extensions)
> +{
> +    int i;
> +
> +    for (i = 0; extensions[i]; i++) {
> +        if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0)
> +           psp->image.loader = (__DRIimageLoaderExtension *) extensions[i];
> +    }
> +}
> +
> +static __DRIscreen *
> +image_create_new_screen_2(int scrn, int fd,
> +                          const __DRIextension **extensions,
> +                          const __DRIextension **driver_extensions,
> +                          const __DRIconfig ***driver_configs, void *data)
> +{
> +    static const __DRIextension *emptyExtensionList[] = { NULL };
> +    __DRIscreen *psp;
> +    drmVersionPtr version;
> +
> +    psp = calloc(1, sizeof(*psp));
> +    if (!psp)
> +	return NULL;
> +
> +    /* By default, use the global driDriverAPI symbol (non-megadrivers). */
> +    psp->driver = globalDriverAPI;
> +
> +    /* If the driver exposes its vtable through its extensions list
> +     * (megadrivers), use that instead.
> +     */
> +    if (driver_extensions) {
> +       for (int i = 0; driver_extensions[i]; i++) {
> +          if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) {
> +             psp->driver =
> +                ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable;
> +          }
> +       }
> +    }
> +
> +    setupLoaderExtensions(psp, extensions);
> +    setup_image_loader_extensions(psp, extensions);
> +
> +    version = drmGetVersion(fd);
> +    if (version) {
> +	psp->drm_version.major = version->version_major;
> +	psp->drm_version.minor = version->version_minor;
> +	psp->drm_version.patch = version->version_patchlevel;
> +	drmFreeVersion(version);
> +    }
> +
> +    psp->loaderPrivate = data;
> +
> +    psp->extensions = emptyExtensionList;
> +    psp->fd = fd;
> +    psp->myNum = scrn;
> +
> +    psp->api_mask = (1 << __DRI_API_OPENGL);
> +
> +    *driver_configs = psp->driver->InitScreen(psp);
> +    if (*driver_configs == NULL) {
> +	free(psp);
> +	return NULL;
> +    }
> +
> +    driParseOptionInfo(&psp->optionInfo, __imageConfigOptions);
> +    driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "image");
> +
> +    return psp;
> +}
> +
> +
> +/** Image driver interface */
> +const __DRIimageDriverExtension driImageDriverExtension = {
> +    .base = { __DRI_IMAGE_DRIVER, __DRI_IMAGE_DRIVER_VERSION },
> +
> +    .createNewScreen2           = image_create_new_screen_2,
> +    .createNewDrawable          = driCreateNewDrawable,
> +    .createNewContext           = driCreateNewContext,
> +    .getAPIMask                 = driGetAPIMask,
> +    .createContextAttribs       = driCreateContextAttribs,
> +};
> diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
> index fd40769..6f5cd87 100644
> --- a/src/mesa/drivers/dri/common/dri_util.h
> +++ b/src/mesa/drivers/dri/common/dri_util.h
> @@ -174,6 +174,10 @@ struct __DRIscreenRec {
>  	__DRIuseInvalidateExtension *useInvalidate;
>      } dri2;
>  
> +    struct {
> +        __DRIimageLoaderExtension *loader;
> +    } image;
> +
>      driOptionCache optionInfo;
>      driOptionCache optionCache;
>  
> @@ -283,4 +287,6 @@ dri2InvalidateDrawable(__DRIdrawable *drawable);
>  extern void
>  driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv);
>  
> +extern const __DRIimageDriverExtension driImageDriverExtension;
> +
>  #endif /* _DRI_UTIL_H_ */
> diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
> index 1798bc7..8d369ff 100644
> --- a/src/mesa/drivers/dri/i915/intel_context.c
> +++ b/src/mesa/drivers/dri/i915/intel_context.c
> @@ -91,6 +91,8 @@ intelGetString(struct gl_context * ctx, GLenum name)
>     }
>  }
>  
> +#define flushFront(screen)      ((screen)->image.loader ? (screen)->image.loader->flushFrontBuffer : (screen)->dri2.loader->flushFrontBuffer)
> +
>  static void
>  intel_flush_front(struct gl_context *ctx)
>  {
> @@ -100,11 +102,10 @@ intel_flush_front(struct gl_context *ctx)
>      __DRIscreen *const screen = intel->intelScreen->driScrnPriv;
>  
>      if (intel->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
> -      if (screen->dri2.loader->flushFrontBuffer != NULL &&
> +      if (flushFront(screen) && 
>            driDrawable &&
>            driDrawable->loaderPrivate) {
> -         screen->dri2.loader->flushFrontBuffer(driDrawable,
> -                                               driDrawable->loaderPrivate);
> +         flushFront(screen)(driDrawable, driDrawable->loaderPrivate);
>  
>  	 /* We set the dirty bit in intel_prepare_render() if we're
>  	  * front buffer rendering once we get there.
> @@ -114,6 +115,9 @@ intel_flush_front(struct gl_context *ctx)
>     }
>  }
>  
> +static void
> +intel_update_image_buffers(struct intel_context *intel, __DRIdrawable *drawable);
> +
>  static unsigned
>  intel_bits_per_pixel(const struct intel_renderbuffer *rb)
>  {
> @@ -194,7 +198,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
>     if (unlikely(INTEL_DEBUG & DEBUG_DRI))
>        fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
>  
> -   intel_update_dri2_buffers(intel, drawable);
> +   if (screen->image.loader)
> +      intel_update_image_buffers(intel, drawable);
> +   else
> +      intel_update_dri2_buffers(intel, drawable);
>  
>     driUpdateFramebufferSize(&intel->ctx, drawable);
>  }
> @@ -787,3 +794,99 @@ intel_process_dri2_buffer(struct intel_context *intel,
>                                                   region);
>     intel_region_release(&region);
>  }
> +
> +/**
> + * \brief Query DRI Image loader to obtain a DRIdrawable's buffers.
> + *
> + * To determine which DRI buffers to request, examine the renderbuffers
> + * attached to the drawable's framebuffer. Then request the buffers with
> + * dri3
> + *
> + * This is called from intel_update_renderbuffers().
> + *
> + * \param drawable      Drawable whose buffers are queried.
> + * \param buffers       [out] List of buffers returned by DRI2 query.
> + * \param buffer_count  [out] Number of buffers returned.
> + *
> + * \see intel_update_renderbuffers()
> + */
> +
> +static void
> +intel_update_image_buffer(struct intel_context *intel,
> +                          __DRIdrawable *drawable,
> +                          struct intel_renderbuffer *rb,
> +                          __DRIimage *buffer,
> +                          enum __DRIimageBufferMask buffer_type)
> +{
> +   struct intel_region *region = buffer->region;
> +
> +   if (!rb || !region)
> +      return;
> +
> +   unsigned num_samples = rb->Base.Base.NumSamples;
> +
> +   if (rb->mt &&
> +       rb->mt->region &&
> +       rb->mt->region == region)
> +      return;
> +
> +   intel_miptree_release(&rb->mt);
> +   rb->mt = intel_miptree_create_for_image_buffer(intel,
> +                                                  buffer_type,
> +                                                  intel_rb_format(rb),
> +                                                  num_samples,
> +                                                  region);
> +}
> +
> +
> +static void
> +intel_update_image_buffers(struct intel_context *intel, __DRIdrawable *drawable)
> +{
> +   struct gl_framebuffer *fb = drawable->driverPrivate;
> +   __DRIscreen *screen = intel->intelScreen->driScrnPriv;
> +   struct intel_renderbuffer *front_rb;
> +   struct intel_renderbuffer *back_rb;
> +   struct __DRIimageList images;
> +   unsigned int format;
> +   uint32_t buffer_mask = 0;
> +
> +   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
> +   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
> +
> +   if (back_rb)
> +      format = intel_rb_format(back_rb);
> +   else if (front_rb)
> +      format = intel_rb_format(front_rb);
> +   else
> +      return;
> +
> +   if ((intel->is_front_buffer_rendering || intel->is_front_buffer_reading || !back_rb) && front_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
> +
> +   if (back_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
> +
> +   (*screen->image.loader->getBuffers) (drawable,
> +                                        &drawable->w,
> +                                        &drawable->h,
> +                                        driGLFormatToImageFormat(format),
> +                                        &drawable->dri2.stamp,
> +                                        drawable->loaderPrivate,
> +                                        buffer_mask,
> +                                        &images);
> +
> +   if (images.front) {
> +      assert(front_rb);
> +      intel_update_image_buffer(intel,
> +                                drawable,
> +                                front_rb,
> +                                images.front,
> +                                __DRI_IMAGE_BUFFER_FRONT);
> +   }
> +   if (images.back)
> +      intel_update_image_buffer(intel,
> +                                drawable,
> +                                back_rb,
> +                                images.back,
> +                                __DRI_IMAGE_BUFFER_BACK);
> +}
> diff --git a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
> index 8432b6d..66a7a92 100644
> --- a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
> +++ b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
> @@ -322,6 +322,39 @@ intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
>     return mt;
>  }
>  
> +/**
> + * For a singlesample image buffer, this simply wraps the given region with a miptree.
> + *
> + * For a multisample image buffer, this wraps the given region with
> + * a singlesample miptree, then creates a multisample miptree into which the
> + * singlesample miptree is embedded as a child.
> + */
> +struct intel_mipmap_tree*
> +intel_miptree_create_for_image_buffer(struct intel_context *intel,
> +                                      enum __DRIimageBufferMask buffer_type,
> +                                      gl_format format,
> +                                      uint32_t num_samples,
> +                                      struct intel_region *region)
> +{
> +   struct intel_mipmap_tree *mt = NULL;
> +
> +   /* Only the front and back buffers, which are color buffers, are allocated
> +    * through the image loader.
> +    */
> +   assert(_mesa_get_format_base_format(format) == GL_RGB ||
> +          _mesa_get_format_base_format(format) == GL_RGBA);
> +
> +   mt = intel_miptree_create_for_bo(intel,
> +                                    region->bo,
> +                                    format,
> +                                    0,
> +                                    region->width,
> +                                    region->height,
> +                                    region->pitch,
> +                                    region->tiling);
> +   return mt;
> +}
> +
>  struct intel_mipmap_tree*
>  intel_miptree_create_for_renderbuffer(struct intel_context *intel,
>                                        gl_format format,
> diff --git a/src/mesa/drivers/dri/i915/intel_mipmap_tree.h b/src/mesa/drivers/dri/i915/intel_mipmap_tree.h
> index 1142af6..35cad6d 100644
> --- a/src/mesa/drivers/dri/i915/intel_mipmap_tree.h
> +++ b/src/mesa/drivers/dri/i915/intel_mipmap_tree.h
> @@ -32,6 +32,7 @@
>  
>  #include "intel_screen.h"
>  #include "intel_regions.h"
> +#include "GL/internal/dri_interface.h"
>  
>  #ifdef __cplusplus
>  extern "C" {
> @@ -258,6 +259,13 @@ intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
>                                       gl_format format,
>                                       struct intel_region *region);
>  
> +struct intel_mipmap_tree*
> +intel_miptree_create_for_image_buffer(struct intel_context *intel,
> +                                      enum __DRIimageBufferMask buffer_type,
> +                                      gl_format format,
> +                                      uint32_t num_samples,
> +                                      struct intel_region *region);
> +
>  /**
>   * Create a miptree appropriate as the storage for a non-texture renderbuffer.
>   * The miptree has the following properties:
> diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
> index 12113c7..38badec 100644
> --- a/src/mesa/drivers/dri/i915/intel_screen.c
> +++ b/src/mesa/drivers/dri/i915/intel_screen.c
> @@ -1166,6 +1166,7 @@ static const struct __DRIDriverVtableExtensionRec i915_vtable = {
>  /* This is the table of extensions that the loader will dlsym() for. */
>  static const __DRIextension *i915_driver_extensions[] = {
>      &driCoreExtension.base,
> +    &driImageDriverExtension.base,
>      &driDRI2Extension.base,
>      &i915_vtable.base,
>      &i915_config_options.base,
> diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
> index 2557d10..f3bf67f 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.c
> +++ b/src/mesa/drivers/dri/i965/brw_context.c
> @@ -151,6 +151,8 @@ intelInvalidateState(struct gl_context * ctx, GLuint new_state)
>     brw->NewGLState |= new_state;
>  }
>  
> +#define flushFront(screen)      ((screen)->image.loader ? (screen)->image.loader->flushFrontBuffer : (screen)->dri2.loader->flushFrontBuffer)
> +
>  static void
>  intel_flush_front(struct gl_context *ctx)
>  {
> @@ -160,8 +162,7 @@ intel_flush_front(struct gl_context *ctx)
>     __DRIscreen *const screen = brw->intelScreen->driScrnPriv;
>  
>     if (brw->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
> -      if (screen->dri2.loader->flushFrontBuffer != NULL &&
> -          driDrawable &&
> +      if (flushFront(screen) && driDrawable &&
>            driDrawable->loaderPrivate) {
>  
>           /* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT.
> @@ -174,8 +175,7 @@ intel_flush_front(struct gl_context *ctx)
>           intel_resolve_for_dri2_flush(brw, driDrawable);
>           intel_batchbuffer_flush(brw);
>  
> -         screen->dri2.loader->flushFrontBuffer(driDrawable,
> -                                               driDrawable->loaderPrivate);
> +         flushFront(screen)(driDrawable, driDrawable->loaderPrivate);
>  
>           /* We set the dirty bit in intel_prepare_render() if we're
>            * front buffer rendering once we get there.
> @@ -549,7 +549,7 @@ brw_process_driconf_options(struct brw_context *brw)
>        driQueryOptionb(options, "disable_glsl_line_continuations");
>  }
>  
> -bool
> +GLboolean
>  brwCreateContext(gl_api api,
>  	         const struct gl_config *mesaVis,
>  		 __DRIcontext *driContextPriv,
> @@ -979,6 +979,9 @@ intel_process_dri2_buffer(struct brw_context *brw,
>                            const char *buffer_name);
>  
>  static void
> +intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable);
> +
> +static void
>  intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable)
>  {
>     struct gl_framebuffer *fb = drawable->driverPrivate;
> @@ -1038,6 +1041,7 @@ void
>  intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
>  {
>     struct brw_context *brw = context->driverPrivate;
> +   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
>  
>     /* Set this up front, so that in case our buffers get invalidated
>      * while we're getting new buffers, we don't clobber the stamp and
> @@ -1047,7 +1051,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
>     if (unlikely(INTEL_DEBUG & DEBUG_DRI))
>        fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
>  
> -   intel_update_dri2_buffers(brw, drawable);
> +   if (screen->image.loader)
> +      intel_update_image_buffers(brw, drawable);
> +   else
> +      intel_update_dri2_buffers(brw, drawable);
>  
>     driUpdateFramebufferSize(&brw->ctx, drawable);
>  }
> @@ -1253,3 +1260,98 @@ intel_process_dri2_buffer(struct brw_context *brw,
>                                                   region);
>     intel_region_release(&region);
>  }
> +
> +/**
> + * \brief Query DRI image loader to obtain a DRIdrawable's buffers.
> + *
> + * To determine which DRI buffers to request, examine the renderbuffers
> + * attached to the drawable's framebuffer. Then request the buffers from
> + * the image loader
> + *
> + * This is called from intel_update_renderbuffers().
> + *
> + * \param drawable      Drawable whose buffers are queried.
> + * \param buffers       [out] List of buffers returned by DRI2 query.
> + * \param buffer_count  [out] Number of buffers returned.
> + *
> + * \see intel_update_renderbuffers()
> + */
> +
> +static void
> +intel_update_image_buffer(struct brw_context *intel,
> +                          __DRIdrawable *drawable,
> +                          struct intel_renderbuffer *rb,
> +                          __DRIimage *buffer,
> +                          enum __DRIimageBufferMask buffer_type)
> +{
> +   struct intel_region *region = buffer->region;
> +
> +   if (!rb || !region)
> +      return;
> +
> +   unsigned num_samples = rb->Base.Base.NumSamples;
> +
> +   if (rb->mt &&
> +       rb->mt->region &&
> +       rb->mt->region == region)
> +      return;
> +
> +   intel_miptree_release(&rb->mt);
> +   rb->mt = intel_miptree_create_for_image_buffer(intel,
> +                                                  buffer_type,
> +                                                  intel_rb_format(rb),
> +                                                  num_samples,
> +                                                  region);
> +}
> +
> +static void
> +intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
> +{
> +   struct gl_framebuffer *fb = drawable->driverPrivate;
> +   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
> +   struct intel_renderbuffer *front_rb;
> +   struct intel_renderbuffer *back_rb;
> +   struct __DRIimageList images;
> +   unsigned int format;
> +   uint32_t buffer_mask = 0;
> +
> +   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
> +   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
> +
> +   if (back_rb)
> +      format = intel_rb_format(back_rb);
> +   else if (front_rb)
> +      format = intel_rb_format(front_rb);
> +   else
> +      return;
> +
> +   if ((brw->is_front_buffer_rendering || brw->is_front_buffer_reading || !back_rb) && front_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
> +
> +   if (back_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
> +
> +   (*screen->image.loader->getBuffers) (drawable,
> +                                        &drawable->w,
> +                                        &drawable->h,
> +                                        driGLFormatToImageFormat(format),
> +                                        &drawable->dri2.stamp,
> +                                        drawable->loaderPrivate,
> +                                        buffer_mask,
> +                                        &images);
> +
> +   if (images.front) {
> +      assert(front_rb);
> +      intel_update_image_buffer(brw,
> +                                drawable,
> +                                front_rb,
> +                                images.front,
> +                                __DRI_IMAGE_BUFFER_FRONT);
> +   }
> +   if (images.back)
> +      intel_update_image_buffer(brw,
> +                                drawable,
> +                                back_rb,
> +                                images.back,
> +                                __DRI_IMAGE_BUFFER_BACK);
> +}
> diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
> index bec4d6b..1ecbfb7 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.h
> +++ b/src/mesa/drivers/dri/i965/brw_context.h
> @@ -1477,14 +1477,14 @@ void intel_prepare_render(struct brw_context *brw);
>  void intel_resolve_for_dri2_flush(struct brw_context *brw,
>                                    __DRIdrawable *drawable);
>  
> -bool brwCreateContext(gl_api api,
> -		      const struct gl_config *mesaVis,
> -		      __DRIcontext *driContextPriv,
> -                      unsigned major_version,
> -                      unsigned minor_version,
> -                      uint32_t flags,
> -                      unsigned *error,
> -		      void *sharedContextPrivate);
> +GLboolean brwCreateContext(gl_api api,
> +                           const struct gl_config *mesaVis,
> +                           __DRIcontext *driContextPriv,
> +                           unsigned major_version,
> +                           unsigned minor_version,
> +                           uint32_t flags,
> +                           unsigned *error,
> +                           void *sharedContextPrivate);
>  
>  /*======================================================================
>   * brw_misc_state.c
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> index 2f5e04f..08dbe88 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> @@ -725,6 +725,67 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw,
>     return multisample_mt;
>  }
>  
> +/**
> + * For a singlesample image buffer, this simply wraps the given region with a miptree.
> + *
> + * For a multisample image buffer, this wraps the given region with
> + * a singlesample miptree, then creates a multisample miptree into which the
> + * singlesample miptree is embedded as a child.
> + */
> +struct intel_mipmap_tree*
> +intel_miptree_create_for_image_buffer(struct brw_context *intel,
> +                                      enum __DRIimageBufferMask buffer_type,
> +                                      gl_format format,
> +                                      uint32_t num_samples,
> +                                      struct intel_region *region)
> +{
> +   struct intel_mipmap_tree *singlesample_mt = NULL;
> +   struct intel_mipmap_tree *multisample_mt = NULL;
> +
> +   /* Only the front and back buffers, which are color buffers, are allocated
> +    * through the image loader.
> +    */
> +   assert(_mesa_get_format_base_format(format) == GL_RGB ||
> +          _mesa_get_format_base_format(format) == GL_RGBA);
> +
> +   singlesample_mt = intel_miptree_create_for_bo(intel,
> +                                                 region->bo,
> +                                                 format,
> +                                                 0,
> +                                                 region->width,
> +                                                 region->height,
> +                                                 region->pitch,
> +                                                 region->tiling);
> +   if (!singlesample_mt)
> +      return NULL;
> +
> +   intel_region_reference(&singlesample_mt->region, region);
> +
> +   if (num_samples == 0)
> +      return singlesample_mt;
> +
> +   multisample_mt = intel_miptree_create_for_renderbuffer(intel,
> +                                                          format,
> +                                                          region->width,
> +                                                          region->height,
> +                                                          num_samples);
> +   if (!multisample_mt) {
> +      intel_miptree_release(&singlesample_mt);
> +      return NULL;
> +   }
> +
> +   multisample_mt->singlesample_mt = singlesample_mt;
> +   multisample_mt->need_downsample = false;
> +
> +   intel_region_reference(&multisample_mt->region, region);
> +
> +   if (intel->is_front_buffer_rendering && buffer_type == __DRI_IMAGE_BUFFER_FRONT) {
> +      intel_miptree_upsample(intel, multisample_mt);
> +   }
> +
> +   return multisample_mt;
> +}
> +
>  struct intel_mipmap_tree*
>  intel_miptree_create_for_renderbuffer(struct brw_context *brw,
>                                        gl_format format,
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> index d718125..8777a8c 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> @@ -32,6 +32,7 @@
>  
>  #include "intel_regions.h"
>  #include "intel_resolve_map.h"
> +#include <GL/internal/dri_interface.h>
>  
>  #ifdef __cplusplus
>  extern "C" {
> @@ -529,6 +530,13 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw,
>                                       uint32_t num_samples,
>                                       struct intel_region *region);
>  
> +struct intel_mipmap_tree*
> +intel_miptree_create_for_image_buffer(struct brw_context *intel,
> +                                     enum __DRIimageBufferMask buffer_type,
> +                                     gl_format format,
> +                                     uint32_t num_samples,
> +                                     struct intel_region *region);
> +
>  /**
>   * Create a miptree appropriate as the storage for a non-texture renderbuffer.
>   * The miptree has the following properties:
> diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
> index f9339c1..7571921 100644
> --- a/src/mesa/drivers/dri/i965/intel_screen.c
> +++ b/src/mesa/drivers/dri/i965/intel_screen.c
> @@ -1176,7 +1176,8 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
>  {
>     struct intel_screen *intelScreen;
>  
> -   if (psp->dri2.loader->base.version <= 2 ||
> +   if (psp->image.loader) {
> +   } else if (psp->dri2.loader->base.version <= 2 ||
>         psp->dri2.loader->getBuffersWithFormat == NULL) {
>        fprintf(stderr,
>  	      "\nERROR!  DRI2 loader with getBuffersWithFormat() "
> @@ -1264,7 +1265,6 @@ intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
>     free(intelBuffer);
>  }
>  
> -
>  static const struct __DriverAPIRec brw_driver_api = {
>     .InitScreen		 = intelInitScreen2,
>     .DestroyScreen	 = intelDestroyScreen,
> @@ -1285,6 +1285,7 @@ static const struct __DRIDriverVtableExtensionRec brw_vtable = {
>  
>  static const __DRIextension *brw_driver_extensions[] = {
>      &driCoreExtension.base,
> +    &driImageDriverExtension.base,
>      &driDRI2Extension.base,
>      &brw_vtable.base,
>      &brw_config_options.base,
> -- 
> 1.8.4.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 8/8] Add DRI3+Present loader
  2013-11-05  2:23 ` [PATCH 8/8] Add DRI3+Present loader Keith Packard
@ 2013-11-05 23:10   ` Eric Anholt
  2013-11-06  2:32     ` Keith Packard
  0 siblings, 1 reply; 36+ messages in thread
From: Eric Anholt @ 2013-11-05 23:10 UTC (permalink / raw)
  To: Keith Packard, mesa3d-dev; +Cc: dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 40492 bytes --]

I think I'm going to be griping about code duplication...

Keith Packard <keithp@keithp.com> writes:
> diff --git a/configure.ac b/configure.ac
> index 0a25047..074368c 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -38,6 +38,9 @@ LIBDRM_NVVIEUX_REQUIRED=2.4.33
>  LIBDRM_NOUVEAU_REQUIRED="2.4.33 libdrm >= 2.4.41"
>  LIBDRM_FREEDRENO_REQUIRED=2.4.39
>  DRI2PROTO_REQUIRED=2.6
> +DRI3PROTO_REQUIRED=1.0
> +PRESENTPROTO_REQUIRED=1.0
> +LIBUDEV_REQUIRED=151
>  GLPROTO_REQUIRED=1.4.14
>  LIBDRM_XORG_REQUIRED=2.4.24
>  LIBKMS_XORG_REQUIRED=1.0.0
> @@ -820,10 +823,13 @@ xyesno)
>          fi
>          PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= $DRI2PROTO_REQUIRED])
>          GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV libdrm >= $LIBDRM_REQUIRED"
> +        PKG_CHECK_MODULES([DRI3PROTO], [dri3proto >= $DRI3PROTO_REQUIRED])
> +        PKG_CHECK_MODULES([PRESENTPROTO], [presentproto >= $PRESENTPROTO_REQUIRED])
> +        PKG_CHECK_MODULES([LIBUDEV], [libudev >= $LIBUDEV_REQUIRED])
>      fi
>  
>      # find the DRI deps for libGL
> -    dri_modules="x11 xext xdamage xfixes x11-xcb xcb-glx >= 1.8.1 xcb-dri2 >= 1.8"
> +    dri_modules="x11 xext xdamage xfixes x11-xcb xcb-glx >= 1.8.1 xcb-dri2 >= 1.8 xcb-dri3 xcb-present xcb-sync xshmfence"

Patches need to land in XCB and get released before this can land.  I
don't even see patches on the xcb list yet.

> diff --git a/src/glx/dri3_common.c b/src/glx/dri3_common.c
> new file mode 100644
> index 0000000..c758f96
> --- /dev/null
> +++ b/src/glx/dri3_common.c
> @@ -0,0 +1,146 @@
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission.  The copyright holders make no representations
> + * about the suitability of this software for any purpose.  It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +/*
> + * This code is derived from src/egl/drivers/dri2/common.c which
> + * carries the following copyright:
> + * 
> + * Copyright © 2011 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Authors:
> + *    Kristian Høgsberg <krh@bitplanet.net>
> + *    Benjamin Franzke <benjaminfranzke@googlemail.com>
> + */
> +
> +#include <stdio.h>
> +#include <string.h>
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +#include <GL/gl.h>
> +#include "glapi.h"
> +#include "glxclient.h"
> +#include "xf86dri.h"
> +#include <dlfcn.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <sys/mman.h>
> +#include <sys/time.h>
> +#include "xf86drm.h"
> +#include "dri_common.h"
> +#include "dri3_priv.h"
> +
> +#define DRIVER_MAP_DRI3_ONLY

What does this define do?

> diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
> new file mode 100644
> index 0000000..4021baa
> --- /dev/null
> +++ b/src/glx/dri3_glx.c
> @@ -0,0 +1,1722 @@

> +static inline void
> +dri3_fence_reset(xcb_connection_t *c, struct dri3_buffer *buffer) {
> +   xshmfence_reset(buffer->shm_fence);
> +}
> +
> +static inline void
> +dri3_fence_set(struct dri3_buffer *buffer) {
> +   xshmfence_trigger(buffer->shm_fence);
> +}
> +
> +static inline void
> +dri3_fence_trigger(xcb_connection_t *c, struct dri3_buffer *buffer) {
> +   xcb_sync_trigger_fence(c, buffer->sync_fence);
> +}
> +
> +static inline void
> +dri3_fence_await(xcb_connection_t *c, struct dri3_buffer *buffer) {
> +   xcb_flush(c);
> +   xshmfence_await(buffer->shm_fence);
> +}
> +
> +static inline Bool
> +dri3_fence_triggered(struct dri3_buffer *buffer) {
> +   return xshmfence_query(buffer->shm_fence);
> +}

'{' on a separate line, please.

> +static void
> +dri3_destroy_context(struct glx_context *context)
> +{
> +   struct dri3_context *pcp = (struct dri3_context *) context;
> +   struct dri3_screen *psc = (struct dri3_screen *) context->psc;
> +
> +   driReleaseDrawables(&pcp->base);
> +
> +   free((char *) context->extensions);
> +
> +   (*psc->core->destroyContext) (pcp->driContext);
> +
> +   free(pcp);
> +}
> +
> +static Bool
> +dri3_bind_context(struct glx_context *context, struct glx_context *old,
> +		  GLXDrawable draw, GLXDrawable read)
> +{
> +   struct dri3_context *pcp = (struct dri3_context *) context;
> +   struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
> +   struct dri3_drawable *pdraw, *pread;
> +
> +   pdraw = (struct dri3_drawable *) driFetchDrawable(context, draw);
> +   pread = (struct dri3_drawable *) driFetchDrawable(context, read);
> +
> +   driReleaseDrawables(&pcp->base);
> +
> +   if (pdraw == NULL || pread == NULL)
> +      return GLXBadDrawable;
> +
> +   if (!(*psc->core->bindContext) (pcp->driContext,
> +				   pdraw->driDrawable, pread->driDrawable))
> +      return GLXBadContext;
> +
> +   return Success;
> +}
> +
> +static void
> +dri3_unbind_context(struct glx_context *context, struct glx_context *new)
> +{
> +   struct dri3_context *pcp = (struct dri3_context *) context;
> +   struct dri3_screen *psc = (struct dri3_screen *) pcp->base.psc;
> +
> +   (*psc->core->unbindContext) (pcp->driContext);
> +}
> +
> +static struct glx_context *
> +dri3_create_context(struct glx_screen *base,
> +		    struct glx_config *config_base,
> +		    struct glx_context *shareList, int renderType)
> +{
> +   struct dri3_context *pcp, *pcp_shared;
> +   struct dri3_screen *psc = (struct dri3_screen *) base;
> +   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
> +   __DRIcontext *shared = NULL;
> +
> +   if (shareList) {
> +      /* If the shareList context is not a DRI3 context, we cannot possibly
> +       * create a DRI3 context that shares it.
> +       */
> +      if (shareList->vtable->destroy != dri3_destroy_context) {
> +	 return NULL;
> +      }
> +
> +      pcp_shared = (struct dri3_context *) shareList;
> +      shared = pcp_shared->driContext;
> +   }
> +
> +   pcp = calloc(1, sizeof *pcp);
> +   if (pcp == NULL)
> +      return NULL;
> +
> +   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
> +      free(pcp);
> +      return NULL;
> +   }
> +
> +   pcp->driContext =
> +      (*psc->image_driver->createNewContext) (psc->driScreen,
> +                                              config->driConfig, shared, pcp);
> +
> +   if (pcp->driContext == NULL) {
> +      free(pcp);
> +      return NULL;
> +   }
> +
> +   pcp->base.vtable = &dri3_context_vtable;
> +
> +   return &pcp->base;
> +}

This looks completely like dri2_create_context, except for missing
rendertype validation and a different calloc size.

> +static struct glx_context *
> +dri3_create_context_attribs(struct glx_screen *base,
> +			    struct glx_config *config_base,
> +			    struct glx_context *shareList,
> +			    unsigned num_attribs,
> +			    const uint32_t *attribs,
> +			    unsigned *error)
> +{
> +   struct dri3_context *pcp = NULL;
> +   struct dri3_context *pcp_shared = NULL;
> +   struct dri3_screen *psc = (struct dri3_screen *) base;
> +   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
> +   __DRIcontext *shared = NULL;
> +
> +   uint32_t minor_ver = 1;
> +   uint32_t major_ver = 2;
> +   uint32_t flags = 0;
> +   unsigned api;
> +   int reset = __DRI_CTX_RESET_NO_NOTIFICATION;
> +   uint32_t ctx_attribs[2 * 5];
> +   unsigned num_ctx_attribs = 0;
> +   uint32_t render_type;
> +
> +   /* Remap the GLX tokens to DRI2 tokens.
> +    */
> +   if (!dri2_convert_glx_attribs(num_attribs, attribs,
> +				 &major_ver, &minor_ver,

tabs :(

> +                                 &render_type, &flags, &api,
> +                                 &reset, error))
> +      goto error_exit;
> +
> +   /* Check the renderType value */
> +   if (!validate_renderType_against_config(config_base, render_type))
> +       goto error_exit;
> +
> +   if (shareList) {
> +      pcp_shared = (struct dri3_context *) shareList;
> +      shared = pcp_shared->driContext;
> +   }
> +
> +   pcp = calloc(1, sizeof *pcp);
> +   if (pcp == NULL) {
> +      *error = __DRI_CTX_ERROR_NO_MEMORY;
> +      goto error_exit;
> +   }
> +
> +   if (!glx_context_init(&pcp->base, &psc->base, &config->base))
> +      goto error_exit;
> +
> +   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
> +   ctx_attribs[num_ctx_attribs++] = major_ver;
> +   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
> +   ctx_attribs[num_ctx_attribs++] = minor_ver;
> +
> +   /* Only send a value when the non-default value is requested.  By doing
> +    * this we don't have to check the driver's DRI3 version before sending the
> +    * default value.
> +    */
> +   if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
> +      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
> +      ctx_attribs[num_ctx_attribs++] = reset;
> +   }
> +
> +   if (flags != 0) {
> +      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
> +
> +      /* The current __DRI_CTX_FLAG_* values are identical to the
> +       * GLX_CONTEXT_*_BIT values.
> +       */
> +      ctx_attribs[num_ctx_attribs++] = flags;
> +   }
> +
> +   pcp->driContext =
> +      (*psc->image_driver->createContextAttribs) (psc->driScreen,
> +                                                  api,
> +                                                  config->driConfig,
> +                                                  shared,
> +                                                  num_ctx_attribs / 2,
> +                                                  ctx_attribs,
> +                                                  error,
> +                                                  pcp);
> +
> +   if (pcp->driContext == NULL)
> +      goto error_exit;
> +
> +   pcp->base.vtable = &dri3_context_vtable;
> +
> +   return &pcp->base;
> +
> +error_exit:
> +   free(pcp);
> +
> +   return NULL;
> +}

This looks like an exact copy of dri2_create_context_attribs except for
the vtable, the calloc size being different, the reset initialization,
and the createContextAttribs looking in image_driver instead of dri2.

This sucks.

> +
> +static __GLXDRIdrawable *
> +dri3_create_drawable(struct glx_screen *base, XID xDrawable,
> +                     GLXDrawable drawable, struct glx_config *config_base)
> +{
> +   struct dri3_drawable *pdraw;
> +   struct dri3_screen *psc = (struct dri3_screen *) base;
> +   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
> +   GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
> +
> +   pdraw = calloc(1, sizeof(*pdraw));
> +   if (!pdraw)
> +      return NULL;
> +
> +   pdraw->base.destroyDrawable = dri3_destroy_drawable;
> +   pdraw->base.xDrawable = xDrawable;
> +   pdraw->base.drawable = drawable;
> +   pdraw->base.psc = &psc->base;
> +//   pdraw->bufferCount = 0;

Leftover debug code?

> +   pdraw->swap_interval = 1; /* default may be overridden below */
> +   pdraw->have_back = 0;
> +   pdraw->have_fake_front = 0;
> +
> +   if (psc->config)
> +      psc->config->configQueryi(psc->driScreen,
> +				"vblank_mode", &vblank_mode);
> +
> +   switch (vblank_mode) {
> +   case DRI_CONF_VBLANK_NEVER:
> +   case DRI_CONF_VBLANK_DEF_INTERVAL_0:
> +      pdraw->swap_interval = 0;
> +      break;
> +   case DRI_CONF_VBLANK_DEF_INTERVAL_1:
> +   case DRI_CONF_VBLANK_ALWAYS_SYNC:
> +   default:
> +      pdraw->swap_interval = 1;
> +      break;
> +   }
> +
> +   (void) __glXInitialize(psc->base.dpy);
> +
> +   /* Create a new drawable */
> +   pdraw->driDrawable =
> +      (*psc->image_driver->createNewDrawable) (psc->driScreen,
> +                                               config->driConfig, pdraw);
> +
> +   if (!pdraw->driDrawable) {
> +      free(pdraw);
> +      return NULL;
> +   }
> +
> +   /*
> +    * Make sure server has the same swap interval we do for the new
> +    * drawable.
> +    */
> +   if (psc->vtable.setSwapInterval)
> +      psc->vtable.setSwapInterval(&pdraw->base, pdraw->swap_interval);
> +
> +   return &pdraw->base;
> +}

Finally, a function different enough that I think it merits being a new
implementation :)

> +static int
> +dri3_wait_for_msc(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
> +                  int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
> +{
> +   xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy);
> +   struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
> +   xcb_generic_event_t *ev;
> +   xcb_present_generic_event_t *ge;
> +
> +   /* Ask for the an event for the target MSC */
> +   ++priv->present_msc_request_serial;
> +   xcb_present_notify_msc(c,
> +                          priv->base.xDrawable,
> +                          priv->present_msc_request_serial,
> +                          target_msc,
> +                          divisor,
> +                          remainder);
> +
> +   xcb_flush(c);
> +
> +   /* Wait for the event */
> +   if (priv->special_event) {
> +      while (priv->present_msc_request_serial != priv->present_msc_event_serial) {
> +         ev = xcb_wait_for_special_event(c, priv->special_event);
> +         if (!ev)
> +            break;
> +         ge = (void *) ev;
> +         present_handle_special_event(priv, ge);
> +      }
> +   }
> +
> +   *ust = priv->ust;
> +   *msc = priv->msc;
> +

funny extra newline.

> +   *sbc = priv->sbc;
> +
> +   return 1;
> +}

> +static int
> +dri3_wait_for_sbc(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
> +                  int64_t *msc, int64_t *sbc)
> +{
> +   struct dri3_drawable *priv = (struct dri3_drawable *) pdraw;
> +
> +   while (priv->sbc < target_sbc) {
> +      sleep(1);
> +   }

Some sort of comment about what's going on here?  Seems like sleep(1)
would always be a wrong thing to execute.

> +   return dri3_wait_for_msc(pdraw, 0, 0, 0, ust, msc, sbc);
> +}


> +/**
> + * dri3Throttle - Request driver throttling
> + *
> + * This function uses the DRI2 throttle extension to give the
> + * driver the opportunity to throttle on flush front, copysubbuffer
> + * and swapbuffers.
> + */
> +static void
> +dri3_throttle(struct dri3_screen *psc,
> +              struct dri3_drawable *draw,
> +              enum __DRI2throttleReason reason)
> +{
> +   if (psc->throttle) {
> +      __DRIcontext *ctx = dri3_get_current_context();
> +
> +      psc->throttle->throttle(ctx, draw->driDrawable, reason);
> +   }
> +}

I think we can drop this entirely thanks to flush_with_flags (see
below).  The gallium-only implementation of this driver extension is
just a call to flush_with_flags.

> +
> +/**
> + * Asks the driver to flush any queued work necessary for serializing with the
> + * X command stream, and optionally the slightly more strict requirement of
> + * glFlush() equivalence (which would require flushing even if nothing had
> + * been drawn to a window system framebuffer, for example).
> + */
> +static void
> +dri3_flush(struct dri3_screen *psc,
> +           __DRIcontext *ctx,
> +           struct dri3_drawable *draw,
> +           unsigned flags,
> +           enum __DRI2throttleReason throttle_reason)
> +{
> +   if (ctx && psc->f && psc->f->base.version >= 4) {
> +      psc->f->flush_with_flags(ctx, draw->driDrawable, flags, throttle_reason);
> +   } else {
> +      if (flags & __DRI2_FLUSH_CONTEXT)
> +         glFlush();
> +
> +      if (psc->f)
> +         psc->f->flush(draw->driDrawable);
> +
> +      dri3_throttle(psc, draw, throttle_reason);
> +   }
> +}

I'd rather insist that the driver supports flush_with_flags if you do DRI3.

> +static void
> +dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y,
> +		  int width, int height, Bool flush)
> +{
> +   _dri3_copy_sub_buffer(pdraw, x, y, width, height,
> +                         __DRI2_THROTTLE_COPYSUBBUFFER, flush);
> +}

This appears to be a pointless wrapper.

> +static void
> +dri3_copy_drawable(struct dri3_drawable *priv, Drawable dest, Drawable src)
> +{
> +   struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
> +   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
> +
> +   if (psc->f)
> +      (*psc->f->flush) (priv->driDrawable);

Use flush_with_flags instead.

> +   dri3_copy_area(c,
> +                  src, dest,
> +                  dri3_drawable_gc(priv),
> +                  0, 0, 0, 0, priv->width, priv->height);
> +}

DRI2CopyRegion round-tripped, while this call doesn't.  As a result, I
think dri3_wait_x is broken because it doesn't ensure that the copyarea
actually happens before your driver goes rendering again.  dri3_wait_gl
may be similarly wrong in the other way.

We don't have testing for glXWaitGL() or glXWaitX() at all, and that's
bad.

> +static void
> +dri3_wait_x(struct glx_context *gc)
> +{
> +   struct dri3_drawable *priv = (struct dri3_drawable *)
> +      GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
> +
> +   if (priv == NULL || !priv->have_fake_front)
> +      return;
> +
> +   dri3_copy_drawable(priv, dri3_fake_front_buffer(priv)->pixmap, priv->base.xDrawable);
> +}
> +
> +static void
> +dri3_wait_gl(struct glx_context *gc)
> +{
> +   struct dri3_drawable *priv = (struct dri3_drawable *)
> +      GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable);
> +
> +   if (priv == NULL || !priv->have_fake_front)
> +      return;
> +
> +   dri3_copy_drawable(priv, priv->base.xDrawable, dri3_fake_front_buffer(priv)->pixmap);
> +}

What's going on with fence reset/triggering being present in
copysubbuffer but not these entrypoints?

> +static struct dri3_buffer *
> +dri3_alloc_render_buffer(struct glx_screen *glx_screen, Drawable draw, unsigned int format, int width, int height, int depth)

80-column wrap

> +{
> +   struct dri3_screen *psc = (struct dri3_screen *) glx_screen;
> +   Display *dpy = glx_screen->dpy;
> +   struct dri3_buffer *buffer;
> +   xcb_connection_t *c = XGetXCBConnection(dpy);
> +   xcb_pixmap_t pixmap;
> +   xcb_sync_fence_t sync_fence;
> +   int32_t *shm_fence;
> +   int buffer_fd, fence_fd;
> +   int stride;
> +
> +   fence_fd = xshmfence_alloc_shm();
> +   if (fence_fd < 0)
> +      return NULL;
> +   shm_fence = xshmfence_map_shm(fence_fd);
> +   if (shm_fence == NULL)
> +      goto no_shm_fence;
> +
> +   buffer = calloc(1, sizeof (struct dri3_buffer));
> +   if (!buffer)
> +      goto no_buffer;
> +
> +   buffer->image = (*psc->image->createImage) (psc->driScreen,
> +                                               width, height,
> +                                               format,
> +                                               __DRI_IMAGE_USE_SHARE|__DRI_IMAGE_USE_SCANOUT,
> +                                               buffer);
> +
> +   

trailing whitespace

> +   if (!buffer->image)
> +      goto no_image;
> +
> +   if (!(*psc->image->queryImage)(buffer->image, __DRI_IMAGE_ATTRIB_STRIDE, &stride))
> +      goto no_buffer_attrib;
> +
> +   buffer->pitch = stride;
> +
> +   if (!(*psc->image->queryImage)(buffer->image, __DRI_IMAGE_ATTRIB_FD, &buffer_fd))
> +      goto no_buffer_attrib;


> +
> +   xcb_dri3_pixmap_from_buffer(c,
> +                               (pixmap = xcb_generate_id(c)),
> +                               draw,
> +                               buffer->size,
> +                               width, height, buffer->pitch,
> +                               depth, buffer->cpp * 8,

I don't see buffer->cpp initialized anywhere.

> +   /* Mark the buffer as idle */
> +   dri3_fence_set(buffer);
> +
> +   return buffer;
> +   

trailing whitespace

> +static void
> +dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer)
> +{
> +   struct dri3_screen   *psc = (struct dri3_screen *) pdraw->base.psc;
> +   xcb_connection_t     *c = XGetXCBConnection(pdraw->base.psc->dpy);
> +
> +   xcb_free_pixmap(c, buffer->pixmap);
> +   xcb_sync_destroy_fence(c, buffer->sync_fence);
> +   xshmfence_unmap_shm(buffer->shm_fence);
> +   (*psc->image->destroyImage)(buffer->image);
> +   free(buffer);
> +}
> +
> +
> +
> +static void
> +present_flush_events(struct dri3_drawable *priv)
> +{
> +   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
> +
> +   /* Check to see if any configuration changes have occurred
> +    * since we were last invoked
> +    */
> +   if (priv->special_event) {
> +      xcb_generic_event_t    *ev;
> +
> +      while ((ev = xcb_check_for_special_event(c, priv->special_event)) != NULL) {
> +         xcb_present_generic_event_t *ge = (void *) ev;
> +         present_handle_special_event(priv, ge);
> +      }
> +   }
> +}
> +
> +static int
> +dri3_update_drawable(__DRIdrawable *driDrawable, void *loaderPrivate)
> +{
> +   struct dri3_drawable *priv = loaderPrivate;
> +   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
> +
> +   /* First time through, go get the current drawable geometry
> +    */
> +   if (priv->width == 0 || priv->height == 0 || priv->depth == 0) {
> +      xcb_get_geometry_cookie_t                 geom_cookie;
> +      xcb_get_geometry_reply_t                  *geom_reply;
> +      xcb_void_cookie_t                         cookie;
> +      xcb_generic_error_t                       *error;
> +
> +      cookie = xcb_present_select_input_checked(c,
> +                                                (priv->eid = xcb_generate_id(c)),
> +                                                priv->base.xDrawable,
> +                                                XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY|
> +                                                XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY|
> +                                                XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY);
> +         
> +      if (!priv->present_extension) {
> +         priv->present_extension = xcb_get_extension_data(c, &xcb_present_id);
> +         if (!priv->present_extension)
> +            return false;
> +      }
> +
> +      priv->special_event = xcb_register_for_special_event(c,
> +                                                           priv->present_extension->major_opcode,
> +                                                           priv->eid,
> +                                                           priv->stamp);
> +
> +      geom_cookie = xcb_get_geometry(c, priv->base.xDrawable);
> +
> +      geom_reply = xcb_get_geometry_reply(c, geom_cookie, NULL);
> +
> +      if (!geom_reply)
> +         return false;
> +
> +      priv->width = geom_reply->width;
> +      priv->height = geom_reply->height;
> +      priv->depth = geom_reply->depth;
> +      priv->is_pixmap = false;
> +
> +      free(geom_reply);
> +
> +      error = xcb_request_check(c, cookie);
> +
> +      if (error) {
> +         if (error->error_code != BadWindow) {
> +            free(error);
> +            return false;
> +         }
> +         priv->is_pixmap = true;
> +         xcb_unregister_for_special_event(c, priv->special_event);
> +         priv->special_event = NULL;
> +      }
> +   }

You should probably comment what's going on here.  Is an error going to
be returned iff it's a pixmap?

> +   

trailing whitespace.

> +static int
> +image_format_to_fourcc(int format)
> +{
> +
> +   /* Convert from __DRI_IMAGE_FORMAT to __DRI_IMAGE_FOURCC (sigh) */
> +   switch (format) {
> +   case __DRI_IMAGE_FORMAT_RGB565: return __DRI_IMAGE_FOURCC_RGB565;
> +   case __DRI_IMAGE_FORMAT_XRGB8888: return __DRI_IMAGE_FOURCC_XRGB8888;
> +   case __DRI_IMAGE_FORMAT_ARGB8888: return __DRI_IMAGE_FOURCC_ARGB8888;
> +   case __DRI_IMAGE_FORMAT_ABGR8888: return __DRI_IMAGE_FOURCC_ABGR8888;
> +   case __DRI_IMAGE_FORMAT_XBGR8888: return __DRI_IMAGE_FOURCC_XBGR8888;
> +//   case __DRI_IMAGE_FORMAT_R8: return __DRI_IMAGE_FOURCC_R8;
> +//   case __DRI_IMAGE_FORMAT_GR88: return __DRI_IMAGE_FOURCC_GR88;
> +//   case __DRI_IMAGE_FORMAT_NONE: return __DRI_IMAGE_FOURCC_NONE;
> +//   case __DRI_IMAGE_FORMAT_XRGB2101010: return __DRI_IMAGE_FOURCC_XRGB2101010;
> +//   case __DRI_IMAGE_FORMAT_ARGB2101010: return __DRI_IMAGE_FOURCC_ARGB2101010;

What's up with commented out formats?

> +   }
> +   return 0;
> +}
> +
> +static struct dri3_buffer *
> +dri3_get_pixmap_buffer(__DRIdrawable *driDrawable,
> +                       unsigned int format,
> +                       enum dri3_buffer_type buffer_type,
> +                       void *loaderPrivate)
> +{
> +   struct dri3_drawable                 *pdraw = loaderPrivate;
> +   int                                  buf_id = buffer_type == dri3_pixmap_buf_id(buffer_type);
> +   struct dri3_buffer                   *buffer = pdraw->buffers[buf_id];
> +   Pixmap                               pixmap;
> +   xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie;
> +   xcb_dri3_buffer_from_pixmap_reply_t  *bp_reply;
> +   int                                  *fds;
> +   int                                  buffer_fd;
> +   Display                              *dpy;
> +   struct dri3_screen                   *psc;
> +   xcb_connection_t                     *c;
> +   xcb_sync_fence_t                     sync_fence;
> +   int32_t                              *shm_fence;
> +   int                                  fence_fd;
> +   __DRIimage                           *image_planar;
> +   int                                  stride, offset;
> +
> +   if (buffer)
> +      return buffer;
> +
> +   pixmap = pdraw->base.xDrawable;
> +   psc = (struct dri3_screen *) pdraw->base.psc;
> +   dpy = psc->base.dpy;
> +   c = XGetXCBConnection(dpy);
> +
> +   buffer = calloc(1, sizeof (struct dri3_buffer));
> +   if (!buffer)
> +      goto no_buffer;

> +
> +   image_planar = (*psc->image->createImageFromFds) (psc->driScreen,
> +                                                     bp_reply->width,
> +                                                     bp_reply->height,
> +                                                     image_format_to_fourcc(format),
> +                                                     fds, 1,
> +                                                     &stride, &offset, buffer);
> +   close(buffer_fd);

just drop buffer_fd and reference fds[0] again?

> +   if (!image_planar)
> +      goto no_image;
> +
> +   buffer->image = (*psc->image->fromPlanar)(image_planar, 0, buffer);
> +
> +   (*psc->image->destroyImage)(image_planar);

Is the fromPlanar step here actually needed?  It looks like since
num_fds == 1 you get a functional image from the first step.

> +static int
> +dri3_get_buffers(__DRIdrawable *driDrawable,
> +                 int *width, int *height,
> +                 unsigned int format,
> +                 uint32_t *stamp,
> +                 void *loaderPrivate,
> +                 uint32_t buffer_mask,
> +                 struct __DRIimageList *buffers)
> +{
> +   struct dri3_drawable *priv = loaderPrivate;
> +   struct dri3_buffer   *front, *back;
> +
> +   buffers->front = NULL;
> +   buffers->back = NULL;
> +
> +   front = NULL;
> +   back = NULL;
> +
> +   if (!dri3_update_drawable(driDrawable, loaderPrivate))
> +      return false;
> +
> +   if (priv->is_pixmap)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
> +
> +   if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT) {
> +      if (priv->is_pixmap)
> +         front = dri3_get_pixmap_buffer(driDrawable,
> +                                        format,
> +                                        dri3_buffer_front,
> +                                        loaderPrivate);
> +      else
> +         front = dri3_get_buffer(driDrawable,
> +                                 format,
> +                                 dri3_buffer_front,
> +                                 loaderPrivate);
> +
> +      if (!front)
> +         return false;
> +      priv->have_fake_front = !priv->is_pixmap;
> +   } else {
> +      dri3_free_buffers(driDrawable, dri3_buffer_front, loaderPrivate);
> +      priv->have_fake_front = 0;
> +   }
> +
> +   if (buffer_mask & __DRI_IMAGE_BUFFER_BACK) {
> +      back = dri3_get_buffer(driDrawable,
> +                             format,
> +                             dri3_buffer_back,
> +                             loaderPrivate);
> +      if (!back)
> +         return false;

I think this early return leaks front.  Also have_fake_front's setting
leaked in even though we're not updating priv->front, should it have?

> +      priv->have_back = 1;
> +   } else {
> +      dri3_free_buffers(driDrawable, dri3_buffer_back, loaderPrivate);
> +      priv->have_back = 0;
> +   }
> +
> +   if (front)
> +      buffers->front = front->image;
> +   
> +   if (back)
> +      buffers->back = back->image;
> +
> +   priv->stamp = stamp;
> +
> +   /* Report back current geometry */
> +   *width = priv->width;
> +   *height = priv->height;
> +   return true;
> +}
> +

> +
> +static int
> +dri3_query_version(Display *dpy, int *major, int *minor)
> +{
> +   xcb_dri3_query_version_cookie_t      cookie;
> +   xcb_dri3_query_version_reply_t       *reply;       

trailing whitespace

> +   xcb_connection_t                     *c = XGetXCBConnection(dpy);
> +   xcb_generic_error_t                  *error;
> +
> +   cookie = xcb_dri3_query_version(c,
> +                                   XCB_DRI3_MAJOR_VERSION,
> +                                   XCB_DRI3_MINOR_VERSION);
> +   reply = xcb_dri3_query_version_reply(c, cookie, &error);
> +   if (!reply) {
> +      if (error) {
> +         free(error);
> +      }

No need for NULL-checking free().

Same 2 comments apply to the next 2 functions.

> +      return 0;
> +   }
> +   *major = reply->major_version;
> +   *minor = reply->minor_version;
> +   free(reply);
> +   return 1;
> +}

> +static const __DRIimageLoaderExtension imageLoaderExtension = {
> +   {__DRI_IMAGE_LOADER, __DRI_IMAGE_LOADER_VERSION},
> +   .getBuffers = dri3_get_buffers,
> +   .flushFrontBuffer = dri3_flush_front_buffer,
> +};
> +
> +static void
> +dri3_bind_tex_image(Display * dpy,
> +		    GLXDrawable drawable,
> +		    int buffer, const int *attrib_list)
> +{
> +   struct glx_context *gc = __glXGetCurrentContext();
> +   struct dri3_context *pcp = (struct dri3_context *) gc;
> +   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
> +   struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
> +   struct dri3_screen *psc;
> +
> +   if (pdraw != NULL) {
> +      psc = (struct dri3_screen *) base->psc;
> +
> +      if (psc->f &&
> +           psc->f->base.version >= 3 && psc->f->invalidate)
> +	 psc->f->invalidate(pdraw->driDrawable);
> +
> +      XSync(dpy, false);
> +      if (psc->texBuffer->base.version >= 2 &&
> +	  psc->texBuffer->setTexBuffer2 != NULL) {
> +	 (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
> +					   pdraw->base.textureTarget,
> +					   pdraw->base.textureFormat,
> +					   pdraw->driDrawable);
> +      }
> +      else {
> +	 (*psc->texBuffer->setTexBuffer) (pcp->driContext,
> +					  pdraw->base.textureTarget,
> +					  pdraw->driDrawable);
> +      }
> +   }
> +}

Tab indentation :(

I'd really like to see less loader code duplication.  But if you have
to, at least don't support old setTexBuffer when you know the driver's
new enough that it's got DRI3.

> +static void
> +dri3_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
> +{
> +#if __DRI_TEX_BUFFER_VERSION >= 3
> +   struct glx_context *gc = __glXGetCurrentContext();
> +   struct dri3_context *pcp = (struct dri3_context *) gc;
> +   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
> +   struct glx_display *dpyPriv = __glXInitialize(dpy);
> +   struct dri3_drawable *pdraw = (struct dri3_drawable *) base;
> +   struct dri3_display *pdp =
> +      (struct dri3_display *) dpyPriv->dri3Display;
> +   struct dri3_screen *psc;
> +
> +   if (pdraw != NULL) {
> +      psc = (struct dri3_screen *) base->psc;
> +
> +      if (psc->texBuffer->base.version >= 3 &&
> +          psc->texBuffer->releaseTexBuffer != NULL) {
> +         (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
> +                                           pdraw->base.textureTarget,
> +                                           pdraw->driDrawable);
> +      }
> +   }
> +#endif

Remove the #ifdef.  You're in the tree, you know its value.

> +}
> +
> +static const struct glx_context_vtable dri3_context_vtable = {
> +   dri3_destroy_context,
> +   dri3_bind_context,
> +   dri3_unbind_context,
> +   dri3_wait_gl,
> +   dri3_wait_x,
> +   DRI_glXUseXFont,
> +   dri3_bind_tex_image,
> +   dri3_release_tex_image,
> +   NULL, /* get_proc_address */
> +};
> +
> +static void
> +dri3_bind_extensions(struct dri3_screen *psc, struct glx_display * priv,
> +                     const char *driverName)
> +{
> +//   const struct dri3_display *const pdp = (struct dri3_display *) priv->dri3Display;

more commented leftovers.

> +   const __DRIextension **extensions;
> +   unsigned mask;
> +   int i;
> +
> +   extensions = psc->core->getExtensions(psc->driScreen);
> +
> +   __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
> +   __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
> +   __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
> +   __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
> +
> +   /*
> +    * GLX_INTEL_swap_event is broken on the server side, where it's
> +    * currently unconditionally enabled. This completely breaks
> +    * systems running on drivers which don't support that extension.
> +    * There's no way to test for its presence on this side, so instead
> +    * of disabling it unconditionally, just disable it for drivers
> +    * which are known to not support it, or for DDX drivers supporting
> +    * only an older (pre-ScheduleSwap) version of DRI2.
> +    *
> +    * This is a hack which is required until:
> +    * http://lists.x.org/archives/xorg-devel/2013-February/035449.html
> +    * is merged and updated xserver makes it's way into distros:
> +    */
> +//   if (pdp->swapAvailable && strcmp(driverName, "vmwgfx") != 0) {
> +//      __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
> +//   }

more commented leftovers.  Are you dropping swap_event support?

> +
> +   mask = psc->image_driver->getAPIMask(psc->driScreen);
> +
> +   __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
> +   __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
> +
> +   if ((mask & (1 << __DRI_API_GLES2)) != 0)
> +      __glXEnableDirectExtension(&psc->base,
> +                                 "GLX_EXT_create_context_es2_profile");
> +
> +   for (i = 0; extensions[i]; i++) {
> +      if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
> +	 psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
> +	 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
> +      }
> +
> +      if ((strcmp(extensions[i]->name, __DRI2_FLUSH) == 0)) {
> +	 psc->f = (__DRI2flushExtension *) extensions[i];
> +	 /* internal driver extension, no GL extension exposed */
> +      }
> +
> +      if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0))
> +	 psc->config = (__DRI2configQueryExtension *) extensions[i];
> +
> +      if (((strcmp(extensions[i]->name, __DRI2_THROTTLE) == 0)))
> +	 psc->throttle = (__DRI2throttleExtension *) extensions[i];
> +
> +      if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0)
> +         __glXEnableDirectExtension(&psc->base,
> +                                    "GLX_ARB_create_context_robustness");
> +   }
> +}
> +

This is horribly duplicated with dri2, but that's also horribly
duplicated with EGL's dri3.  I really think we need to do a
dri_loader_common between all of them with a bunch of this crap.

> +   tmp = getenv("LIBGL_SHOW_FPS");
> +   psc->show_fps = tmp && strcmp(tmp, "1") == 0;

Dead code.

> +/*
> + * Allocate, initialize and return a __DRIdisplayPrivate object.
> + * This is called from __glXInitialize() when we are given a new
> + * display pointer.
> + */
> +_X_HIDDEN __GLXDRIdisplay *
> +dri3_create_display(Display * dpy)
> +{
> +   struct dri3_display *pdp;
> +   int i;
> +
> +   pdp = malloc(sizeof *pdp);
> +   if (pdp == NULL)
> +      return NULL;
> +
> +   if (!dri3_query_version(dpy, &pdp->dri3Major, &pdp->dri3Minor))
> +      goto no_extension;
> +
> +   if (!present_query_version(dpy, &pdp->presentMajor, &pdp->presentMinor))
> +      goto no_extension;
> +
> +   pdp->base.destroyDisplay = dri3_destroy_display;
> +   pdp->base.createScreen = dri3_create_screen;
> +
> +   i = 0;
> +
> +   pdp->loader_extensions[i++] = &imageLoaderExtension.base;
> +   

trailing whitespace

> diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h
> new file mode 100644
> index 0000000..2873919
> --- /dev/null
> +++ b/src/glx/dri3_priv.h

> +
> +struct dri3_buffer {
> +   __DRIimage   *image;
> +   uint32_t     pixmap;

> +   uint32_t     sync_fence;
> +   int32_t      *shm_fence;
> +   GLboolean    busy;

Can we get some comments on what these 3 fields do?  These
synchronization details were a huge part of the dri3 discussions, and I
know you've gone several ways about things in the process of
development, but I see just a single comment about what fences do:

 +   /* Mark the buffer as idle */

That's... not enough.

> +struct dri3_drawable
> +{

> +   /* For WaitMSC */
> +   uint32_t     present_msc_request_serial;
> +   uint32_t     present_msc_event_serial;
> +   

whitespace


[-- Attachment #1.2: Type: application/pgp-signature, Size: 835 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-05 20:05   ` Eric Anholt
@ 2013-11-05 23:47     ` Keith Packard
  0 siblings, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-05 23:47 UTC (permalink / raw)
  To: Eric Anholt, mesa3d-dev; +Cc: dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 3123 bytes --]

Eric Anholt <eric@anholt.net> writes:

> Most of my review was going to be whining about yet another (broken)
> copy of dri2CreateNewScreen2.  Sounds like you've fixed that.

Yup, figured that out all on my own after I re-read the code -- the only
difference was that I need to look for the DRIimageLoader hooks, which I
now just do in the shared function.

>> +
>> +#define __DRI_DRIVER_EXTENSIONS "__driDriverExtensions"
>
> This looks like rebase fail

Removed.

>> +//struct gl_context;
>> +//struct dd_function_table;
>
> Looks like development leftovers.

Removed.

> Maybe append "Func" to the typedefs so they don't look like just another
> struct in the declarations?  And since they're supposed to be the same
> function pointers as in the __DRIswrastExtensionRec and
> __DRIdri2ExtensionRec, change them to this typedef, too?

I've moved the typedefs, renamed them and stuck that part of the patch
in the first patch of the series that renames the functions.

> It looks like getBuffers could just be two getBuffer calls, except for
> the updating of width and height.  Have you looked into doing things
> that way at all?

Yes, that was the way I started doing it. There are two reasons for
doing it in a single call:

 1) Pixmaps always need a front buffer, and the driver doesn't know
    which drawables are pixmaps.

 2) Deleting buffers when changing modes. I'd need to add another
    function to let the driver delete unused buffers.
  
Overall, I liked moving more buffer management logic to the loader and
out of the driver, so I followed the DRI2 API here.

> Style nit: we try and put braces around multi-line things like this,
> even if they are a single statement.

Fixed.

>> -bool
>> +GLboolean
>>  brwCreateContext(gl_api api,
>>  	         const struct gl_config *mesaVis,
>>  		 __DRIcontext *driContextPriv,
...
>>                                    __DRIdrawable *drawable);
>>  
>> -bool brwCreateContext(gl_api api,
>> -		      const struct gl_config *mesaVis,
>> -		      __DRIcontext *driContextPriv,
>> -                      unsigned major_version,
>> -                      unsigned minor_version,
>> -                      uint32_t flags,
>> -                      unsigned *error,
>> -		      void *sharedContextPrivate);
>> +GLboolean brwCreateContext(gl_api api,
>> +                           const struct gl_config *mesaVis,
>> +                           __DRIcontext *driContextPriv,
>> +                           unsigned major_version,
>> +                           unsigned minor_version,
>> +                           uint32_t flags,
>> +                           unsigned *error,
>> +                           void *sharedContextPrivate);
...
>
> Unrelated change?

Pulled out to a separate patch -- the return type for createContext is
GLboolean, not bool, and my compiler was whinging.

I've pushed these changes, along with a bunch of new comments in
dri3_glx.c to my dri3 branch. I can send the new series to the list if
that would be helpful.

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 0/8] Add DRIimage-based DRI3/Present loader
  2013-11-05 20:04   ` Eric Anholt
  2013-11-05 22:09     ` Kristian Høgsberg
@ 2013-11-05 23:54     ` Keith Packard
  1 sibling, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-05 23:54 UTC (permalink / raw)
  To: Eric Anholt, mesa-dev; +Cc: dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 969 bytes --]

Eric Anholt <eric@anholt.net> writes:

> It seems like we could just stick these things in __DRI_CORE as opposed
> to having another new extension to look up.

Having the driver expose this new extension is how I tell that the
driver is going to actually call the __DRIimage-based loader; the
alternative to a new extension would be to stick a flag in the
__DRI_CORE structure.

> The downside I see there is
> bugs in the server, which have patches at xserver-driinterface-versions
> of my tree.  (Unfortunately, I'm having a hard time building the server
> currently, so no testing yet).  Having a new extension whose name has
> nothing to do with the functions in it seems really weird.

It defines the interface to a driver which will be using the image
loader to allocate color buffers if available. The fact that the image
loader and DRI2 loader can both share the same driver interface is a
happy coincidence.

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 156 bytes --]

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/8] dri/intel: Add explicit size parameter to intel_region_alloc_for_fd
  2013-11-05 22:23   ` Kristian Høgsberg
@ 2013-11-06  0:52     ` Keith Packard
  2013-11-07  5:17     ` Christopher James Halse Rogers
  1 sibling, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-06  0:52 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: mesa3d-dev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 504 bytes --]

Kristian Høgsberg <hoegsberg@gmail.com> writes:

> The 3.12 kernel let's you get the bo size from lseek on the dma_buf
> fd.  I added libdrm support for getting the size that, and if that
> works, it overrides the user provided size:

Yeah, I'm happy just sending the size and not trusting that the kernel
will have the new API; back-porting happens...

> Regardless, this patchs looks good.
>
> Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>

Thanks!

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_*
  2013-11-05 22:35   ` Kristian Høgsberg
@ 2013-11-06  0:54     ` Keith Packard
  0 siblings, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-06  0:54 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: mesa3d-dev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 550 bytes --]

Kristian Høgsberg <hoegsberg@gmail.com> writes:

> I'll take the bait... before the i915/i965 split, this code was only
> needed in this one place.  All other drivers are gallium drivers which
> need to convert to galliums enum pipe_format instead of the gl_format
> enum.  Anyway, the code certainly looks more at home in dri_util.c.

Yeah, the i915/i965 split wasn't fun to rebase across at all. Oh well,
I'm sure it was for the best :-)

> Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>

Thanks!

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-05 22:59   ` Kristian Høgsberg
@ 2013-11-06  0:59     ` Keith Packard
  2013-11-06  2:48       ` Kristian Høgsberg
  0 siblings, 1 reply; 36+ messages in thread
From: Keith Packard @ 2013-11-06  0:59 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: mesa3d-dev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 762 bytes --]

Kristian Høgsberg <hoegsberg@gmail.com> writes:


> We can drop width and height now and just get it from either of the
> returned images.  Format is a function of the __DRIconfig and doesn't
> change, so we could make that something you can query from the config
> in the interest of further reducing the number of arguments.

Sure would be nice if there were simpler ways than calling the
getAttribs function though; I'm tempted to just leave these params in as
every single driver will need those values and passing them back here
will make the driver code shorter.

> I'll give this a try with the GBM and Wayland EGL backends now.

Cool. Having two backends using this same interface would really help
out.

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 8/8] Add DRI3+Present loader
  2013-11-05 23:10   ` Eric Anholt
@ 2013-11-06  2:32     ` Keith Packard
  0 siblings, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-06  2:32 UTC (permalink / raw)
  To: Eric Anholt, mesa3d-dev; +Cc: dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 11226 bytes --]

Eric Anholt <eric@anholt.net> writes:

I've pushed a patch responding to these comments to my dri3 branch and
will send that out shortly. I will merge those changes with the original
DRI3+Present loader patch so that there is only one commit when the
review process is complete.

> I think I'm going to be griping about code duplication...

Yeah, I'm really not sure what to do about that. The alternative would
be to refactor the DRI2 backend and then land the DRI3 backend on top of
some shared code, but frankly I'm not that excited about breaking DRI2.

Do you want me to actually go ahead and try to do that?

> Patches need to land in XCB and get released before this can land.  I
> don't even see patches on the xcb list yet.

I sent out the patches to the xorg-devel list today after reworking and
cleaning them up. I'd forgotten that there was a separate xcb list.

>> +
>> +#define DRIVER_MAP_DRI3_ONLY
>
> What does this define do?

It is designed to be used in case there are two drivers for a chipset,
one DRI2 one and one DRI3 one. Much like the DRIVER_MAP_GALLIUM_ONLY
flag. It's not currently being used at all, so it should probably just
get removed until necessary.

> '{' on a separate line, please.

Fixed.

> This looks completely like dri2_create_context, except for missing
> rendertype validation and a different calloc size.

Yup. It's cult-n-paste. Note that the license at the top of the file
tries to make it clear that *lots* of the code in this file was copied
From the DRI2 versions. They all take new data structures now, with the
DRI2 stuff replaced with DRI3 stuff, so we can't just shared the same
binaries without a bunch of rework.

> tabs :(

Oh, looks like my xorg emacs settings for using spaces only aren't
applying to mesa. Sorry. And fixed.

> This looks like an exact copy of dri2_create_context_attribs except for
> the vtable, the calloc size being different, the reset initialization,
> and the createContextAttribs looking in image_driver instead of dri2.
>
> This sucks.

As above.

>> +//   pdraw->bufferCount = 0;
>
> Leftover debug code?

Already removed.

>> +
>> +   *ust = priv->ust;
>> +   *msc = priv->msc;
>> +
>
> funny extra newline.

Fixed.

> Some sort of comment about what's going on here?  Seems like sleep(1)
> would always be a wrong thing to execute.

I've added this comment:

/** dri3_wait_for_sbc
 *
 * Wait for the swap buffer count to increase. The only way this
 * can happen is if some other thread is doing swap buffers as
 * we no longer share swap buffer counts with other processes.
 *
 * I'm not sure this is actually useful as such, and so this
 * implementation is a kludge that just polls once a second
 */

I'm not sure what else to do here; presumably there would be locking
preventing multiple threads from getting into this code at the same
time. As none of this code is thread-safe, I'm pretty sure this would
never work anyways.

> I think we can drop this entirely thanks to flush_with_flags (see
> below).  The gallium-only implementation of this driver extension is
> just a call to flush_with_flags.

> I'd rather insist that the driver supports flush_with_flags if you do
> DRI3.

Done.

>
>> +static void
>> +dri3_copy_sub_buffer(__GLXDRIdrawable *pdraw, int x, int y,
>> +		  int width, int height, Bool flush)
>> +{
>> +   _dri3_copy_sub_buffer(pdraw, x, y, width, height,
>> +                         __DRI2_THROTTLE_COPYSUBBUFFER, flush);
>> +}
>
> This appears to be a pointless wrapper.

Removed.

>> +static void
>> +dri3_copy_drawable(struct dri3_drawable *priv, Drawable dest, Drawable src)
>> +{
>> +   struct dri3_screen *psc = (struct dri3_screen *) priv->base.psc;
>> +   xcb_connection_t     *c = XGetXCBConnection(priv->base.psc->dpy);
>> +
>> +   if (psc->f)
>> +      (*psc->f->flush) (priv->driDrawable);
>
> Use flush_with_flags instead.

I call dri3_flush. I've also removed the context argument to dri3_flush
as everyone was passing dri3_current_context, then removed
dri3_current_context and folded that code into dri3_flush.

>> +   dri3_copy_area(c,
>> +                  src, dest,
>> +                  dri3_drawable_gc(priv),
>> +                  0, 0, 0, 0, priv->width, priv->height);
>> +}
>
> DRI2CopyRegion round-tripped, while this call doesn't.  As a result, I
> think dri3_wait_x is broken because it doesn't ensure that the copyarea
> actually happens before your driver goes rendering again.  dri3_wait_gl
> may be similarly wrong in the other way.
>
> We don't have testing for glXWaitGL() or glXWaitX() at all, and that's
> bad.
...
> What's going on with fence reset/triggering being present in
> copysubbuffer but not these entrypoints?

Good catch. I've added fencing around the dri3_copy_area call to
synchronize with the X server.

>> +static struct dri3_buffer *
>> +dri3_alloc_render_buffer(struct glx_screen *glx_screen, Drawable draw, unsigned int format, int width, int height, int depth)
>
> 80-column wrap

Fixed.

> trailing whitespace

Fixed (everywhere)

>
>> +   if (!buffer->image)
>> +      goto no_image;
>> +
>> +   if (!(*psc->image->queryImage)(buffer->image, __DRI_IMAGE_ATTRIB_STRIDE, &stride))
>> +      goto no_buffer_attrib;
>> +
>> +   buffer->pitch = stride;
>> +
>> +   if (!(*psc->image->queryImage)(buffer->image, __DRI_IMAGE_ATTRIB_FD, &buffer_fd))
>> +      goto no_buffer_attrib;
>
>
>> +
>> +   xcb_dri3_pixmap_from_buffer(c,
>> +                               (pixmap = xcb_generate_id(c)),
>> +                               draw,
>> +                               buffer->size,
>> +                               width, height, buffer->pitch,
>> +                               depth, buffer->cpp * 8,
>
> I don't see buffer->cpp initialized anywhere.

Ick. Lost this in the conversion to __DRIimage. I've added a function
that computes cpp from the __DRI_IMAGE_FORMAT_* value and uses that.

> You should probably comment what's going on here.  Is an error going to
> be returned iff it's a pixmap?

Comments added (the select_input request returns a BadWindow error for
pixmaps, which this code interprets as 'that must be a pixmap')

> What's up with commented out formats?

They're just missing from the __DRI_IMAGE_FOURCC definitions. I've just
removed them for now. Krh promises to eliminate all of the
__DRI_IMAGE_FORMAT_* bits and use __DRI_IMAGE_FOURCC everywhere at some
point -- that will eliminate this function entirely.

>> +
>> +   image_planar = (*psc->image->createImageFromFds) (psc->driScreen,
>> +                                                     bp_reply->width,
>> +                                                     bp_reply->height,
>> +                                                     image_format_to_fourcc(format),
>> +                                                     fds, 1,
>> +                                                     &stride, &offset, buffer);
>> +   close(buffer_fd);
>
> just drop buffer_fd and reference fds[0] again?

Done.

>> +   if (!image_planar)
>> +      goto no_image;
>> +
>> +   buffer->image = (*psc->image->fromPlanar)(image_planar, 0, buffer);
>> +
>> +   (*psc->image->destroyImage)(image_planar);
>
> Is the fromPlanar step here actually needed?  It looks like since
> num_fds == 1 you get a functional image from the first step.

Kristian says that it is required -- the upper level __DRIimage might be
a wrapper that points at multiple __DRIimage objects, and in this case
it would point at precisely one of them. I note that the intel driver
doesn't work like that though.

> I think this early return leaks front.  Also have_fake_front's setting
> leaked in even though we're not updating priv->front, should it have?

It isn't "leaked", in that the dri3 code keeps track of the allocated
fake front and will re-use it in future allocations, and free it when
the drawable is destroyed.

However, you're right in asserting that the have_fake_front shouldn't be
set to TRUE until we are going to return success. I've moved that down.

> No need for NULL-checking free().

Fixed

> I'd really like to see less loader code duplication.  But if you have
> to, at least don't support old setTexBuffer when you know the driver's
> new enough that it's got DRI3.

Done. The DRI3 code now requires version 3 of the texBuffer extension
with setTexBuffer2 and releaseTexBuffer defined.

> Remove the #ifdef.  You're in the tree, you know its value.

Removed.

>> +//   if (pdp->swapAvailable && strcmp(driverName, "vmwgfx") != 0) {
>> +//      __glXEnableDirectExtension(&psc->base, "GLX_INTEL_swap_event");
>> +//   }
>
> more commented leftovers.  Are you dropping swap_event support?

Yes, DRI3/Present does not support GLX_INTEL_swap_event. I'd have to add
X server support to deliver that event. Is it useful enough that I
should do this?

> This is horribly duplicated with dri2, but that's also horribly
> duplicated with EGL's dri3.  I really think we need to do a
> dri_loader_common between all of them with a bunch of this crap.

I'm not sure where we would put code to share code between glx and egl,
but it sure would be nice.

>> +   tmp = getenv("LIBGL_SHOW_FPS");
>> +   psc->show_fps = tmp && strcmp(tmp, "1") == 0;
>
> Dead code.

Removed.

>> +
>> +struct dri3_buffer {
>> +   __DRIimage   *image;
>> +   uint32_t     pixmap;
>
>> +   uint32_t     sync_fence;
>> +   int32_t      *shm_fence;
>> +   GLboolean    busy;
>
> Can we get some comments on what these 3 fields do?  These
> synchronization details were a huge part of the dri3 discussions, and I
> know you've gone several ways about things in the process of
> development, but I see just a single comment about what fences do:

   /* Synchronization between the client and X server is done using an
    * xshmfence that is mapped into an X server SyncFence. This lets the
    * client check whether the X server is done using a buffer with a simple
    * xshmfence call, rather than going to read X events from the wire.
    *
    * However, we can only wait for one xshmfence to be triggered at a time,
    * so we need to know *which* buffer is going to be idle next. We do that
    * by waiting for a PresentIdleNotify event. When that event arrives, the
    * 'busy' flag gets cleared and the client knows that the fence has been
    * triggered, and that the wait call will not block.
    */

   uint32_t     sync_fence;     /* XID of X SyncFence object */
   int32_t      *shm_fence;     /* pointer to xshmfence object */
   GLboolean    busy;           /* Set on swap, cleared on IdleNotify */

>  +   /* Mark the buffer as idle */
>
> That's... not enough.

This is at allocation time; we know the buffer is idle. What else would
you like me to do here?

>
>> +struct dri3_drawable
>> +{
>
>> +   /* For WaitMSC */
>> +   uint32_t     present_msc_request_serial;
>> +   uint32_t     present_msc_event_serial;
>> +   
>
> whitespace

Fixed.

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-06  0:59     ` Keith Packard
@ 2013-11-06  2:48       ` Kristian Høgsberg
  0 siblings, 0 replies; 36+ messages in thread
From: Kristian Høgsberg @ 2013-11-06  2:48 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa3d-dev, dri-devel

On Tue, Nov 5, 2013 at 4:59 PM, Keith Packard <keithp@keithp.com> wrote:
> Kristian Høgsberg <hoegsberg@gmail.com> writes:
>
>
>> We can drop width and height now and just get it from either of the
>> returned images.  Format is a function of the __DRIconfig and doesn't
>> change, so we could make that something you can query from the config
>> in the interest of further reducing the number of arguments.
>
> Sure would be nice if there were simpler ways than calling the
> getAttribs function though; I'm tempted to just leave these params in as
> every single driver will need those values and passing them back here
> will make the driver code shorter.

I would say that it's more important to keep the interfaces between
components as simple as possible, even if it incurs a little
inconvenience inside the driver.

But it's a non-issue, since inside the driver you can just access them
as image->width/height.

>> I'll give this a try with the GBM and Wayland EGL backends now.
>
> Cool. Having two backends using this same interface would really help
> out.

I got this running now and I found a few other things.  I'll reply to
the patch again.

Kristian
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-05  2:23 ` [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension Keith Packard
  2013-11-05 20:05   ` Eric Anholt
  2013-11-05 22:59   ` Kristian Høgsberg
@ 2013-11-06  6:25   ` Kristian Høgsberg
  2013-11-06 14:55     ` Keith Packard
  2 siblings, 1 reply; 36+ messages in thread
From: Kristian Høgsberg @ 2013-11-06  6:25 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa3d-dev, dri-devel

On Mon, Nov 04, 2013 at 06:23:27PM -0800, Keith Packard wrote:
> These provide an interface between the driver and the loader to allocate
> color buffers through the DRIimage extension interface rather than through a
> loader-specific extension (as is used by DRI2, for instance).
> 
> The driver uses the loader 'getBuffers' interface to allocate color buffers.
> 
> The loader uses the createNewScreen2, createNewDrawable, createNewContext,
> getAPIMask and createContextAttribs APIS (mostly shared with DRI2).
> 
> This interface will work with the DRI3 loader, and should also work with GBM
> and other loaders so that drivers need not be customized for each new loader
> interface, as long as they provide this image interface.
> 
> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
>  include/GL/internal/dri_interface.h           | 112 +++++++++++++++++++++++++
>  src/mesa/drivers/dri/common/dri_util.c        | 113 +++++++++++++++++++++++++
>  src/mesa/drivers/dri/common/dri_util.h        |   6 ++
>  src/mesa/drivers/dri/i915/intel_context.c     | 111 ++++++++++++++++++++++++-
>  src/mesa/drivers/dri/i915/intel_mipmap_tree.c |  33 ++++++++
>  src/mesa/drivers/dri/i915/intel_mipmap_tree.h |   8 ++
>  src/mesa/drivers/dri/i915/intel_screen.c      |   1 +
>  src/mesa/drivers/dri/i965/brw_context.c       | 114 ++++++++++++++++++++++++--
>  src/mesa/drivers/dri/i965/brw_context.h       |  16 ++--
>  src/mesa/drivers/dri/i965/intel_mipmap_tree.c |  61 ++++++++++++++
>  src/mesa/drivers/dri/i965/intel_mipmap_tree.h |   8 ++
>  src/mesa/drivers/dri/i965/intel_screen.c      |   5 +-
>  12 files changed, 568 insertions(+), 20 deletions(-)
> 
> diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
> index 907aeca..8fc1fa6 100644
> --- a/include/GL/internal/dri_interface.h
> +++ b/include/GL/internal/dri_interface.h
> @@ -86,6 +86,10 @@ typedef struct __DRIdri2LoaderExtensionRec	__DRIdri2LoaderExtension;
>  typedef struct __DRI2flushExtensionRec	__DRI2flushExtension;
>  typedef struct __DRI2throttleExtensionRec	__DRI2throttleExtension;
>  
> +
> +typedef struct __DRIimageLoaderExtensionRec     __DRIimageLoaderExtension;
> +typedef struct __DRIimageDriverExtensionRec     __DRIimageDriverExtension;
> +
>  /*@}*/
>  
>  
> @@ -1288,4 +1292,112 @@ typedef struct __DRIDriverVtableExtensionRec {
>      const struct __DriverAPIRec *vtable;
>  } __DRIDriverVtableExtension;
>  
> +/**
> + * Image Loader extension. Drivers use this to allocate color buffers
> + */
> +
> +#define __DRI_DRIVER_EXTENSIONS "__driDriverExtensions"
> +
> +enum __DRIimageBufferMask {
> +   __DRI_IMAGE_BUFFER_BACK = (1 << 0),
> +   __DRI_IMAGE_BUFFER_FRONT = (1 << 1)
> +};
> +
> +struct __DRIimageList {
> +   __DRIimage *back;
> +   __DRIimage *front;
> +};
> +
> +#define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER"
> +#define __DRI_IMAGE_LOADER_VERSION 1
> +
> +struct __DRIimageLoaderExtensionRec {
> +    __DRIextension base;
> +
> +   /**
> +    * Allocate color buffers.
> +    *
> +    * \param driDrawable
> +    * \param width              Width of allocated buffers
> +    * \param height             Height of allocated buffers
> +    * \param format             one of __DRI_IMAGE_FORMAT_*
> +    * \param stamp              Address of variable to be updated when
> +    *                           getBuffers must be called again
> +    * \param loaderPrivate      The loaderPrivate for driDrawable
> +    * \param buffer_mask        Set of buffers to allocate
> +    * \param buffers            Returned buffers
> +    */
> +   int (*getBuffers)(__DRIdrawable *driDrawable,
> +                     int *width, int *height,
> +                     unsigned int format,
> +                     uint32_t *stamp,
> +                     void *loaderPrivate,
> +                     uint32_t buffer_mask,
> +                     struct __DRIimageList *buffers);
> +
> +    /**
> +     * Flush pending front-buffer rendering
> +     *
> +     * Any rendering that has been performed to the
> +     * fake front will be flushed to the front
> +     *
> +     * \param driDrawable    Drawable whose front-buffer is to be flushed
> +     * \param loaderPrivate  Loader's private data that was previously passed
> +     *                       into __DRIdri2ExtensionRec::createNewDrawable
> +     */
> +    void (*flushFrontBuffer)(__DRIdrawable *driDrawable, void *loaderPrivate);
> +};
> +
> +/**
> + * DRI extension.
> + */
> +
> +//struct gl_context;
> +//struct dd_function_table;
> +
> +typedef __DRIscreen *
> +(*__DRIcreateNewScreen2)(int screen, int fd,
> +                         const __DRIextension **extensions,
> +                         const __DRIextension **driver_extensions,
> +                         const __DRIconfig ***driver_configs,
> +                         void *loaderPrivate);
> +
> +typedef __DRIdrawable *
> +(*__DRIcreateNewDrawable)(__DRIscreen *screen,
> +                          const __DRIconfig *config,
> +                          void *loaderPrivate);
> +
> +typedef __DRIcontext *
> +(*__DRIcreateNewContext)(__DRIscreen *screen,
> +                         const __DRIconfig *config,
> +                         __DRIcontext *shared,
> +                         void *loaderPrivate);
> +
> +typedef __DRIcontext *
> +(*__DRIcreateContextAttribs)(__DRIscreen *screen,
> +                             int api,
> +                             const __DRIconfig *config,
> +                             __DRIcontext *shared,
> +                             unsigned num_attribs,
> +                             const uint32_t *attribs,
> +                             unsigned *error,
> +                             void *loaderPrivate);
> +
> +typedef unsigned int
> +(*__DRIgetAPIMask)(__DRIscreen *screen);
> +
> +#define __DRI_IMAGE_DRIVER           "DRI_IMAGE_DRIVER"
> +#define __DRI_IMAGE_DRIVER_VERSION   1
> +
> +struct __DRIimageDriverExtensionRec {
> +   __DRIextension               base;
> +
> +   /* Common DRI functions, shared with DRI2 */
> +   __DRIcreateNewScreen2        createNewScreen2;
> +   __DRIcreateNewDrawable       createNewDrawable;
> +   __DRIcreateNewContext        createNewContext;
> +   __DRIcreateContextAttribs    createContextAttribs;
> +   __DRIgetAPIMask              getAPIMask;
> +};
> +
>  #endif
> diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
> index 76c8ae5..d8cb7f6 100644
> --- a/src/mesa/drivers/dri/common/dri_util.c
> +++ b/src/mesa/drivers/dri/common/dri_util.c
> @@ -854,3 +854,116 @@ driImageFormatToGLFormat(uint32_t image_format)
>        return MESA_FORMAT_NONE;
>     }
>  }
> +
> +/*
> + * Copyright © 2013 Keith Packard
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission.  The copyright holders make no representations
> + * about the suitability of this software for any purpose.  It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +PUBLIC const char __imageConfigOptions[] =
> +   DRI_CONF_BEGIN
> +      DRI_CONF_SECTION_PERFORMANCE
> +         DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
> +      DRI_CONF_SECTION_END
> +   DRI_CONF_END;
> +
> +static void
> +setup_image_loader_extensions(__DRIscreen *psp,
> +                              const __DRIextension *const*extensions)
> +{
> +    int i;
> +
> +    for (i = 0; extensions[i]; i++) {
> +        if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0)
> +           psp->image.loader = (__DRIimageLoaderExtension *) extensions[i];
> +    }
> +}
> +
> +static __DRIscreen *
> +image_create_new_screen_2(int scrn, int fd,
> +                          const __DRIextension **extensions,
> +                          const __DRIextension **driver_extensions,
> +                          const __DRIconfig ***driver_configs, void *data)
> +{
> +    static const __DRIextension *emptyExtensionList[] = { NULL };
> +    __DRIscreen *psp;
> +    drmVersionPtr version;
> +
> +    psp = calloc(1, sizeof(*psp));
> +    if (!psp)
> +	return NULL;
> +
> +    /* By default, use the global driDriverAPI symbol (non-megadrivers). */
> +    psp->driver = globalDriverAPI;
> +
> +    /* If the driver exposes its vtable through its extensions list
> +     * (megadrivers), use that instead.
> +     */
> +    if (driver_extensions) {
> +       for (int i = 0; driver_extensions[i]; i++) {
> +          if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) {
> +             psp->driver =
> +                ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable;
> +          }
> +       }
> +    }
> +
> +    setupLoaderExtensions(psp, extensions);
> +    setup_image_loader_extensions(psp, extensions);
> +
> +    version = drmGetVersion(fd);
> +    if (version) {
> +	psp->drm_version.major = version->version_major;
> +	psp->drm_version.minor = version->version_minor;
> +	psp->drm_version.patch = version->version_patchlevel;
> +	drmFreeVersion(version);
> +    }
> +
> +    psp->loaderPrivate = data;
> +
> +    psp->extensions = emptyExtensionList;
> +    psp->fd = fd;
> +    psp->myNum = scrn;
> +
> +    psp->api_mask = (1 << __DRI_API_OPENGL);

This is another reason this just needs to be dri2CreateNewScreen2.
The above regresses GLES* support.  I tried with your ~keithp dri3
branch and using dri2CreateNewScreen2 brings back the GLESes.

> +    *driver_configs = psp->driver->InitScreen(psp);
> +    if (*driver_configs == NULL) {
> +	free(psp);
> +	return NULL;
> +    }
> +
> +    driParseOptionInfo(&psp->optionInfo, __imageConfigOptions);
> +    driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "image");
> +
> +    return psp;
> +}
> +
> +
> +/** Image driver interface */
> +const __DRIimageDriverExtension driImageDriverExtension = {
> +    .base = { __DRI_IMAGE_DRIVER, __DRI_IMAGE_DRIVER_VERSION },
> +
> +    .createNewScreen2           = image_create_new_screen_2,
> +    .createNewDrawable          = driCreateNewDrawable,
> +    .createNewContext           = driCreateNewContext,
> +    .getAPIMask                 = driGetAPIMask,
> +    .createContextAttribs       = driCreateContextAttribs,
> +};

Having written the GBM and Wayland suport for this, it's pretty clear
that we just want to use __DRIdri2Extension instead of duplicating
these functions.  Support for the __DRIimage based getBuffers is a
small incremental patch to src/egl/drivers/dri2:

 src/egl/drivers/dri2/egl_dri2.c         |  29 +++++--
 src/egl/drivers/dri2/egl_dri2.h         |   5 +-
 src/egl/drivers/dri2/platform_drm.c     |  50 ++++++++++--
 src/egl/drivers/dri2/platform_wayland.c | 133 ++++++++++++++++++++++----------
 src/gbm/backends/dri/gbm_dri.c          |  32 +++++++-
 src/gbm/backends/dri/gbm_driint.h       |  11 ++-
 6 files changed, 199 insertions(+), 61 deletions(-)

The problem is that technically we would have to do:

      if (dri2_dpy->image_driver) {

         /* use dri2_dpy->image_driver->createContextAttribs

      } else if (dri2_dpy->dri2 &&
	         dri2_dpy->dri2->base.version >= 3) {

         /* use dri2_dpy->dri2->createContextAttribs

all over the place even though they end up calling the same function.
The only real purpose of __DRIimageDriverExtension is to let the
loader know that the DRI driver supports and will use
__DRIimageLoaderExtension if provided, but we can just expose an empty
dummy extension to indicate that.

> diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
> index fd40769..6f5cd87 100644
> --- a/src/mesa/drivers/dri/common/dri_util.h
> +++ b/src/mesa/drivers/dri/common/dri_util.h
> @@ -174,6 +174,10 @@ struct __DRIscreenRec {
>  	__DRIuseInvalidateExtension *useInvalidate;
>      } dri2;
>  
> +    struct {
> +        __DRIimageLoaderExtension *loader;
> +    } image;
> +
>      driOptionCache optionInfo;
>      driOptionCache optionCache;
>  
> @@ -283,4 +287,6 @@ dri2InvalidateDrawable(__DRIdrawable *drawable);
>  extern void
>  driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv);
>  
> +extern const __DRIimageDriverExtension driImageDriverExtension;
> +
>  #endif /* _DRI_UTIL_H_ */
> diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
> index 1798bc7..8d369ff 100644
> --- a/src/mesa/drivers/dri/i915/intel_context.c
> +++ b/src/mesa/drivers/dri/i915/intel_context.c
> @@ -91,6 +91,8 @@ intelGetString(struct gl_context * ctx, GLenum name)
>     }
>  }
>  
> +#define flushFront(screen)      ((screen)->image.loader ? (screen)->image.loader->flushFrontBuffer : (screen)->dri2.loader->flushFrontBuffer)
> +
>  static void
>  intel_flush_front(struct gl_context *ctx)
>  {
> @@ -100,11 +102,10 @@ intel_flush_front(struct gl_context *ctx)
>      __DRIscreen *const screen = intel->intelScreen->driScrnPriv;
>  
>      if (intel->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
> -      if (screen->dri2.loader->flushFrontBuffer != NULL &&
> +      if (flushFront(screen) && 
>            driDrawable &&
>            driDrawable->loaderPrivate) {
> -         screen->dri2.loader->flushFrontBuffer(driDrawable,
> -                                               driDrawable->loaderPrivate);
> +         flushFront(screen)(driDrawable, driDrawable->loaderPrivate);
>  
>  	 /* We set the dirty bit in intel_prepare_render() if we're
>  	  * front buffer rendering once we get there.
> @@ -114,6 +115,9 @@ intel_flush_front(struct gl_context *ctx)
>     }
>  }
>  
> +static void
> +intel_update_image_buffers(struct intel_context *intel, __DRIdrawable *drawable);
> +
>  static unsigned
>  intel_bits_per_pixel(const struct intel_renderbuffer *rb)
>  {
> @@ -194,7 +198,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
>     if (unlikely(INTEL_DEBUG & DEBUG_DRI))
>        fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
>  
> -   intel_update_dri2_buffers(intel, drawable);
> +   if (screen->image.loader)
> +      intel_update_image_buffers(intel, drawable);
> +   else
> +      intel_update_dri2_buffers(intel, drawable);
>  
>     driUpdateFramebufferSize(&intel->ctx, drawable);
>  }
> @@ -787,3 +794,99 @@ intel_process_dri2_buffer(struct intel_context *intel,
>                                                   region);
>     intel_region_release(&region);
>  }
> +
> +/**
> + * \brief Query DRI Image loader to obtain a DRIdrawable's buffers.
> + *
> + * To determine which DRI buffers to request, examine the renderbuffers
> + * attached to the drawable's framebuffer. Then request the buffers with
> + * dri3
> + *
> + * This is called from intel_update_renderbuffers().
> + *
> + * \param drawable      Drawable whose buffers are queried.
> + * \param buffers       [out] List of buffers returned by DRI2 query.
> + * \param buffer_count  [out] Number of buffers returned.
> + *
> + * \see intel_update_renderbuffers()
> + */
> +
> +static void
> +intel_update_image_buffer(struct intel_context *intel,
> +                          __DRIdrawable *drawable,
> +                          struct intel_renderbuffer *rb,
> +                          __DRIimage *buffer,
> +                          enum __DRIimageBufferMask buffer_type)
> +{
> +   struct intel_region *region = buffer->region;
> +
> +   if (!rb || !region)
> +      return;
> +
> +   unsigned num_samples = rb->Base.Base.NumSamples;
> +
> +   if (rb->mt &&
> +       rb->mt->region &&
> +       rb->mt->region == region)
> +      return;
> +
> +   intel_miptree_release(&rb->mt);
> +   rb->mt = intel_miptree_create_for_image_buffer(intel,
> +                                                  buffer_type,
> +                                                  intel_rb_format(rb),
> +                                                  num_samples,
> +                                                  region);
> +}
> +
> +
> +static void
> +intel_update_image_buffers(struct intel_context *intel, __DRIdrawable *drawable)
> +{
> +   struct gl_framebuffer *fb = drawable->driverPrivate;
> +   __DRIscreen *screen = intel->intelScreen->driScrnPriv;
> +   struct intel_renderbuffer *front_rb;
> +   struct intel_renderbuffer *back_rb;
> +   struct __DRIimageList images;
> +   unsigned int format;
> +   uint32_t buffer_mask = 0;
> +
> +   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
> +   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
> +
> +   if (back_rb)
> +      format = intel_rb_format(back_rb);
> +   else if (front_rb)
> +      format = intel_rb_format(front_rb);
> +   else
> +      return;
> +
> +   if ((intel->is_front_buffer_rendering || intel->is_front_buffer_reading || !back_rb) && front_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
> +
> +   if (back_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
> +
> +   (*screen->image.loader->getBuffers) (drawable,
> +                                        &drawable->w,
> +                                        &drawable->h,
> +                                        driGLFormatToImageFormat(format),
> +                                        &drawable->dri2.stamp,
> +                                        drawable->loaderPrivate,
> +                                        buffer_mask,
> +                                        &images);
> +
> +   if (images.front) {

I think we should only look at image.front if the
__DRI_IMAGE_BUFFER_FRONT bit is set.  We never want to set up a front
buffer that we didn't ask for and it seems wrong that the loader has
to clear image.front, if the driver didn't ask for front.

> +      assert(front_rb);
> +      intel_update_image_buffer(intel,
> +                                drawable,
> +                                front_rb,
> +                                images.front,
> +                                __DRI_IMAGE_BUFFER_FRONT);
> +   }
> +   if (images.back)

Same here.

> +      intel_update_image_buffer(intel,
> +                                drawable,
> +                                back_rb,
> +                                images.back,
> +                                __DRI_IMAGE_BUFFER_BACK);
> +}
> diff --git a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
> index 8432b6d..66a7a92 100644
> --- a/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
> +++ b/src/mesa/drivers/dri/i915/intel_mipmap_tree.c
> @@ -322,6 +322,39 @@ intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
>     return mt;
>  }
>  
> +/**
> + * For a singlesample image buffer, this simply wraps the given region with a miptree.
> + *
> + * For a multisample image buffer, this wraps the given region with
> + * a singlesample miptree, then creates a multisample miptree into which the
> + * singlesample miptree is embedded as a child.
> + */
> +struct intel_mipmap_tree*
> +intel_miptree_create_for_image_buffer(struct intel_context *intel,
> +                                      enum __DRIimageBufferMask buffer_type,
> +                                      gl_format format,
> +                                      uint32_t num_samples,
> +                                      struct intel_region *region)
> +{
> +   struct intel_mipmap_tree *mt = NULL;
> +
> +   /* Only the front and back buffers, which are color buffers, are allocated
> +    * through the image loader.
> +    */
> +   assert(_mesa_get_format_base_format(format) == GL_RGB ||
> +          _mesa_get_format_base_format(format) == GL_RGBA);
> +
> +   mt = intel_miptree_create_for_bo(intel,
> +                                    region->bo,
> +                                    format,
> +                                    0,
> +                                    region->width,
> +                                    region->height,
> +                                    region->pitch,
> +                                    region->tiling);
> +   return mt;
> +}
> +
>  struct intel_mipmap_tree*
>  intel_miptree_create_for_renderbuffer(struct intel_context *intel,
>                                        gl_format format,
> diff --git a/src/mesa/drivers/dri/i915/intel_mipmap_tree.h b/src/mesa/drivers/dri/i915/intel_mipmap_tree.h
> index 1142af6..35cad6d 100644
> --- a/src/mesa/drivers/dri/i915/intel_mipmap_tree.h
> +++ b/src/mesa/drivers/dri/i915/intel_mipmap_tree.h
> @@ -32,6 +32,7 @@
>  
>  #include "intel_screen.h"
>  #include "intel_regions.h"
> +#include "GL/internal/dri_interface.h"
>  
>  #ifdef __cplusplus
>  extern "C" {
> @@ -258,6 +259,13 @@ intel_miptree_create_for_dri2_buffer(struct intel_context *intel,
>                                       gl_format format,
>                                       struct intel_region *region);
>  
> +struct intel_mipmap_tree*
> +intel_miptree_create_for_image_buffer(struct intel_context *intel,
> +                                      enum __DRIimageBufferMask buffer_type,
> +                                      gl_format format,
> +                                      uint32_t num_samples,
> +                                      struct intel_region *region);
> +
>  /**
>   * Create a miptree appropriate as the storage for a non-texture renderbuffer.
>   * The miptree has the following properties:
> diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
> index 12113c7..38badec 100644
> --- a/src/mesa/drivers/dri/i915/intel_screen.c
> +++ b/src/mesa/drivers/dri/i915/intel_screen.c
> @@ -1166,6 +1166,7 @@ static const struct __DRIDriverVtableExtensionRec i915_vtable = {
>  /* This is the table of extensions that the loader will dlsym() for. */
>  static const __DRIextension *i915_driver_extensions[] = {
>      &driCoreExtension.base,
> +    &driImageDriverExtension.base,
>      &driDRI2Extension.base,
>      &i915_vtable.base,
>      &i915_config_options.base,
> diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
> index 2557d10..f3bf67f 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.c
> +++ b/src/mesa/drivers/dri/i965/brw_context.c
> @@ -151,6 +151,8 @@ intelInvalidateState(struct gl_context * ctx, GLuint new_state)
>     brw->NewGLState |= new_state;
>  }
>  
> +#define flushFront(screen)      ((screen)->image.loader ? (screen)->image.loader->flushFrontBuffer : (screen)->dri2.loader->flushFrontBuffer)
> +
>  static void
>  intel_flush_front(struct gl_context *ctx)
>  {
> @@ -160,8 +162,7 @@ intel_flush_front(struct gl_context *ctx)
>     __DRIscreen *const screen = brw->intelScreen->driScrnPriv;
>  
>     if (brw->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) {
> -      if (screen->dri2.loader->flushFrontBuffer != NULL &&
> -          driDrawable &&
> +      if (flushFront(screen) && driDrawable &&
>            driDrawable->loaderPrivate) {
>  
>           /* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT.
> @@ -174,8 +175,7 @@ intel_flush_front(struct gl_context *ctx)
>           intel_resolve_for_dri2_flush(brw, driDrawable);
>           intel_batchbuffer_flush(brw);
>  
> -         screen->dri2.loader->flushFrontBuffer(driDrawable,
> -                                               driDrawable->loaderPrivate);
> +         flushFront(screen)(driDrawable, driDrawable->loaderPrivate);
>  
>           /* We set the dirty bit in intel_prepare_render() if we're
>            * front buffer rendering once we get there.
> @@ -549,7 +549,7 @@ brw_process_driconf_options(struct brw_context *brw)
>        driQueryOptionb(options, "disable_glsl_line_continuations");
>  }
>  
> -bool
> +GLboolean
>  brwCreateContext(gl_api api,
>  	         const struct gl_config *mesaVis,
>  		 __DRIcontext *driContextPriv,
> @@ -979,6 +979,9 @@ intel_process_dri2_buffer(struct brw_context *brw,
>                            const char *buffer_name);
>  
>  static void
> +intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable);
> +
> +static void
>  intel_update_dri2_buffers(struct brw_context *brw, __DRIdrawable *drawable)
>  {
>     struct gl_framebuffer *fb = drawable->driverPrivate;
> @@ -1038,6 +1041,7 @@ void
>  intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
>  {
>     struct brw_context *brw = context->driverPrivate;
> +   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
>  
>     /* Set this up front, so that in case our buffers get invalidated
>      * while we're getting new buffers, we don't clobber the stamp and
> @@ -1047,7 +1051,10 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
>     if (unlikely(INTEL_DEBUG & DEBUG_DRI))
>        fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
>  
> -   intel_update_dri2_buffers(brw, drawable);
> +   if (screen->image.loader)
> +      intel_update_image_buffers(brw, drawable);
> +   else
> +      intel_update_dri2_buffers(brw, drawable);
>  
>     driUpdateFramebufferSize(&brw->ctx, drawable);
>  }
> @@ -1253,3 +1260,98 @@ intel_process_dri2_buffer(struct brw_context *brw,
>                                                   region);
>     intel_region_release(&region);
>  }
> +
> +/**
> + * \brief Query DRI image loader to obtain a DRIdrawable's buffers.
> + *
> + * To determine which DRI buffers to request, examine the renderbuffers
> + * attached to the drawable's framebuffer. Then request the buffers from
> + * the image loader
> + *
> + * This is called from intel_update_renderbuffers().
> + *
> + * \param drawable      Drawable whose buffers are queried.
> + * \param buffers       [out] List of buffers returned by DRI2 query.
> + * \param buffer_count  [out] Number of buffers returned.
> + *
> + * \see intel_update_renderbuffers()
> + */
> +
> +static void
> +intel_update_image_buffer(struct brw_context *intel,
> +                          __DRIdrawable *drawable,
> +                          struct intel_renderbuffer *rb,
> +                          __DRIimage *buffer,
> +                          enum __DRIimageBufferMask buffer_type)
> +{
> +   struct intel_region *region = buffer->region;
> +
> +   if (!rb || !region)
> +      return;
> +
> +   unsigned num_samples = rb->Base.Base.NumSamples;
> +
> +   if (rb->mt &&
> +       rb->mt->region &&
> +       rb->mt->region == region)
> +      return;
> +
> +   intel_miptree_release(&rb->mt);
> +   rb->mt = intel_miptree_create_for_image_buffer(intel,
> +                                                  buffer_type,
> +                                                  intel_rb_format(rb),
> +                                                  num_samples,
> +                                                  region);
> +}
> +
> +static void
> +intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
> +{
> +   struct gl_framebuffer *fb = drawable->driverPrivate;
> +   __DRIscreen *screen = brw->intelScreen->driScrnPriv;
> +   struct intel_renderbuffer *front_rb;
> +   struct intel_renderbuffer *back_rb;
> +   struct __DRIimageList images;
> +   unsigned int format;
> +   uint32_t buffer_mask = 0;
> +
> +   front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
> +   back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT);
> +
> +   if (back_rb)
> +      format = intel_rb_format(back_rb);
> +   else if (front_rb)
> +      format = intel_rb_format(front_rb);
> +   else
> +      return;
> +
> +   if ((brw->is_front_buffer_rendering || brw->is_front_buffer_reading || !back_rb) && front_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
> +
> +   if (back_rb)
> +      buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
> +
> +   (*screen->image.loader->getBuffers) (drawable,
> +                                        &drawable->w,
> +                                        &drawable->h,
> +                                        driGLFormatToImageFormat(format),
> +                                        &drawable->dri2.stamp,
> +                                        drawable->loaderPrivate,
> +                                        buffer_mask,
> +                                        &images);
> +
> +   if (images.front) {
> +      assert(front_rb);
> +      intel_update_image_buffer(brw,
> +                                drawable,
> +                                front_rb,
> +                                images.front,
> +                                __DRI_IMAGE_BUFFER_FRONT);
> +   }
> +   if (images.back)
> +      intel_update_image_buffer(brw,
> +                                drawable,
> +                                back_rb,
> +                                images.back,
> +                                __DRI_IMAGE_BUFFER_BACK);
> +}
> diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
> index bec4d6b..1ecbfb7 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.h
> +++ b/src/mesa/drivers/dri/i965/brw_context.h
> @@ -1477,14 +1477,14 @@ void intel_prepare_render(struct brw_context *brw);
>  void intel_resolve_for_dri2_flush(struct brw_context *brw,
>                                    __DRIdrawable *drawable);
>  
> -bool brwCreateContext(gl_api api,
> -		      const struct gl_config *mesaVis,
> -		      __DRIcontext *driContextPriv,
> -                      unsigned major_version,
> -                      unsigned minor_version,
> -                      uint32_t flags,
> -                      unsigned *error,
> -		      void *sharedContextPrivate);
> +GLboolean brwCreateContext(gl_api api,
> +                           const struct gl_config *mesaVis,
> +                           __DRIcontext *driContextPriv,
> +                           unsigned major_version,
> +                           unsigned minor_version,
> +                           uint32_t flags,
> +                           unsigned *error,
> +                           void *sharedContextPrivate);
>  
>  /*======================================================================
>   * brw_misc_state.c
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> index 2f5e04f..08dbe88 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
> @@ -725,6 +725,67 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw,
>     return multisample_mt;
>  }
>  
> +/**
> + * For a singlesample image buffer, this simply wraps the given region with a miptree.
> + *
> + * For a multisample image buffer, this wraps the given region with
> + * a singlesample miptree, then creates a multisample miptree into which the
> + * singlesample miptree is embedded as a child.
> + */
> +struct intel_mipmap_tree*
> +intel_miptree_create_for_image_buffer(struct brw_context *intel,
> +                                      enum __DRIimageBufferMask buffer_type,
> +                                      gl_format format,
> +                                      uint32_t num_samples,
> +                                      struct intel_region *region)
> +{
> +   struct intel_mipmap_tree *singlesample_mt = NULL;
> +   struct intel_mipmap_tree *multisample_mt = NULL;
> +
> +   /* Only the front and back buffers, which are color buffers, are allocated
> +    * through the image loader.
> +    */
> +   assert(_mesa_get_format_base_format(format) == GL_RGB ||
> +          _mesa_get_format_base_format(format) == GL_RGBA);
> +
> +   singlesample_mt = intel_miptree_create_for_bo(intel,
> +                                                 region->bo,
> +                                                 format,
> +                                                 0,
> +                                                 region->width,
> +                                                 region->height,
> +                                                 region->pitch,
> +                                                 region->tiling);
> +   if (!singlesample_mt)
> +      return NULL;
> +
> +   intel_region_reference(&singlesample_mt->region, region);
> +
> +   if (num_samples == 0)
> +      return singlesample_mt;
> +
> +   multisample_mt = intel_miptree_create_for_renderbuffer(intel,
> +                                                          format,
> +                                                          region->width,
> +                                                          region->height,
> +                                                          num_samples);
> +   if (!multisample_mt) {
> +      intel_miptree_release(&singlesample_mt);
> +      return NULL;
> +   }
> +
> +   multisample_mt->singlesample_mt = singlesample_mt;
> +   multisample_mt->need_downsample = false;
> +
> +   intel_region_reference(&multisample_mt->region, region);
> +
> +   if (intel->is_front_buffer_rendering && buffer_type == __DRI_IMAGE_BUFFER_FRONT) {
> +      intel_miptree_upsample(intel, multisample_mt);
> +   }
> +
> +   return multisample_mt;
> +}
> +
>  struct intel_mipmap_tree*
>  intel_miptree_create_for_renderbuffer(struct brw_context *brw,
>                                        gl_format format,
> diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> index d718125..8777a8c 100644
> --- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> +++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
> @@ -32,6 +32,7 @@
>  
>  #include "intel_regions.h"
>  #include "intel_resolve_map.h"
> +#include <GL/internal/dri_interface.h>
>  
>  #ifdef __cplusplus
>  extern "C" {
> @@ -529,6 +530,13 @@ intel_miptree_create_for_dri2_buffer(struct brw_context *brw,
>                                       uint32_t num_samples,
>                                       struct intel_region *region);
>  
> +struct intel_mipmap_tree*
> +intel_miptree_create_for_image_buffer(struct brw_context *intel,
> +                                     enum __DRIimageBufferMask buffer_type,
> +                                     gl_format format,
> +                                     uint32_t num_samples,
> +                                     struct intel_region *region);
> +
>  /**
>   * Create a miptree appropriate as the storage for a non-texture renderbuffer.
>   * The miptree has the following properties:
> diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
> index f9339c1..7571921 100644
> --- a/src/mesa/drivers/dri/i965/intel_screen.c
> +++ b/src/mesa/drivers/dri/i965/intel_screen.c
> @@ -1176,7 +1176,8 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
>  {
>     struct intel_screen *intelScreen;
>  
> -   if (psp->dri2.loader->base.version <= 2 ||
> +   if (psp->image.loader) {
> +   } else if (psp->dri2.loader->base.version <= 2 ||
>         psp->dri2.loader->getBuffersWithFormat == NULL) {
>        fprintf(stderr,
>  	      "\nERROR!  DRI2 loader with getBuffersWithFormat() "
> @@ -1264,7 +1265,6 @@ intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer)
>     free(intelBuffer);
>  }
>  
> -
>  static const struct __DriverAPIRec brw_driver_api = {
>     .InitScreen		 = intelInitScreen2,
>     .DestroyScreen	 = intelDestroyScreen,
> @@ -1285,6 +1285,7 @@ static const struct __DRIDriverVtableExtensionRec brw_vtable = {
>  
>  static const __DRIextension *brw_driver_extensions[] = {
>      &driCoreExtension.base,
> +    &driImageDriverExtension.base,
>      &driDRI2Extension.base,
>      &brw_vtable.base,
>      &brw_config_options.base,
> -- 
> 1.8.4.2
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-06  6:25   ` Kristian Høgsberg
@ 2013-11-06 14:55     ` Keith Packard
  2013-11-06 16:17       ` Kristian Høgsberg
  0 siblings, 1 reply; 36+ messages in thread
From: Keith Packard @ 2013-11-06 14:55 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: mesa3d-dev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 2573 bytes --]

Kristian Høgsberg <hoegsberg@gmail.com> writes:

> Having written the GBM and Wayland suport for this, it's pretty clear
> that we just want to use __DRIdri2Extension instead of duplicating
> these functions.  Support for the __DRIimage based getBuffers is a
> small incremental patch to src/egl/drivers/dri2:

That would require drivers to support all of the DRI2 functions, rather
than just the few needed for Image support though.

> The problem is that technically we would have to do:
>
>       if (dri2_dpy->image_driver) {
>
>          /* use dri2_dpy->image_driver->createContextAttribs
>
>       } else if (dri2_dpy->dri2 &&
> 	         dri2_dpy->dri2->base.version >= 3) {
>
>          /* use dri2_dpy->dri2->createContextAttribs
>
> all over the place even though they end up calling the same function.
> The only real purpose of __DRIimageDriverExtension is to let the
> loader know that the DRI driver supports and will use
> __DRIimageLoaderExtension if provided, but we can just expose an empty
> dummy extension to indicate that.

Alternatively, the loader could simply call through the DRI2 version,
acknowledging that they must be the same function? I'd sure like to be
able to create an ImageLoader-only driver, even if that's not practical
today.

A couple of other options:

 * Move the shared functions into a new structure which is embedded
   in both the DRIdri2ExtensionRec and the DRIimageDriverExtensionRec,
   then the loader could set a pointer to whichever it wanted to use
   in it's own structure.

 * Have the loader pull the functions out of the ExtensionRec and stick
   them directly into its own structure. Then it could use those
   directly and avoid version checks while running.

But, if we just want to use the DRI2 driver interface and create an
extension purely to mark that the driver will use an Image loader,
that's easy too.

> I think we should only look at image.front if the
> __DRI_IMAGE_BUFFER_FRONT bit is set.  We never want to set up a front
> buffer that we didn't ask for and it seems wrong that the loader has
> to clear image.front, if the driver didn't ask for front.

I simply duplicated the logic from the DRI2 path which works exactly the
same way (asks for buffers, then looks to see what it got). I didn't dig
into the details further than this, I'm afraid. The only case where asks
!= received is for pixmap targets where you always get a front buffer. I
assumed there was some deep semantic requirement for that...

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-06 14:55     ` Keith Packard
@ 2013-11-06 16:17       ` Kristian Høgsberg
  2013-11-06 18:09         ` Keith Packard
  0 siblings, 1 reply; 36+ messages in thread
From: Kristian Høgsberg @ 2013-11-06 16:17 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa3d-dev, dri-devel

On Wed, Nov 6, 2013 at 6:55 AM, Keith Packard <keithp@keithp.com> wrote:
> Kristian Høgsberg <hoegsberg@gmail.com> writes:
>
>> Having written the GBM and Wayland suport for this, it's pretty clear
>> that we just want to use __DRIdri2Extension instead of duplicating
>> these functions.  Support for the __DRIimage based getBuffers is a
>> small incremental patch to src/egl/drivers/dri2:
>
> That would require drivers to support all of the DRI2 functions, rather
> than just the few needed for Image support though.

It just the two older create context functions (which fall back to
calling driCreateContextAtribs) and allocateBuffer and releaseBuffer.
The two buffer functions are __DRIbuffer specific of course, but we
can implement them in terms of __DRIimage in dri_util.c now.

>> The problem is that technically we would have to do:
>>
>>       if (dri2_dpy->image_driver) {
>>
>>          /* use dri2_dpy->image_driver->createContextAttribs
>>
>>       } else if (dri2_dpy->dri2 &&
>>                dri2_dpy->dri2->base.version >= 3) {
>>
>>          /* use dri2_dpy->dri2->createContextAttribs
>>
>> all over the place even though they end up calling the same function.
>> The only real purpose of __DRIimageDriverExtension is to let the
>> loader know that the DRI driver supports and will use
>> __DRIimageLoaderExtension if provided, but we can just expose an empty
>> dummy extension to indicate that.
>
> Alternatively, the loader could simply call through the DRI2 version,
> acknowledging that they must be the same function? I'd sure like to be
> able to create an ImageLoader-only driver, even if that's not practical
> today.
>
> A couple of other options:
>
>  * Move the shared functions into a new structure which is embedded
>    in both the DRIdri2ExtensionRec and the DRIimageDriverExtensionRec,
>    then the loader could set a pointer to whichever it wanted to use
>    in it's own structure.
>
>  * Have the loader pull the functions out of the ExtensionRec and stick
>    them directly into its own structure. Then it could use those
>    directly and avoid version checks while running.

There is a third option, which is to pull the functions we need from
__DRIcoreExtension into the __DRIimageDriverExtension, which then is
all you need along with __DRIimageExtension.  This is as painful in
the short term as the current __DRIimageDriverExtension, but it lets
of cut loose of the DRI1 (__DRIcoreExtension has the DRI1
createNewScreen in it) and DRI2 baggage properly later on.  And
pulling out the functions into a loader private struct as you suggest
will make it a lot less painful.  The functions we move from core to
_DRIimageDriverExtension will share the same implementation in
dri_util.c so there's no new code.

> But, if we just want to use the DRI2 driver interface and create an
> extension purely to mark that the driver will use an Image loader,
> that's easy too.

Right - I actually like the clean break idea, but if we're going to
take that pain I want to get rid of all the junk and avoid the awkward
"use some stuff from __DRIcoreExtension and other stuff from
__DRIimageDriverExtension" setup.  So we should either 1) make
__DRIimageDriverExtension completely replace __DRIcoreExtension and
__DRIdri2Extension, or 2) just do a minimal, incremental change (just
the extension to indicate the support for __DRIimage based
getbuffers).

Kristian

>> I think we should only look at image.front if the
>> __DRI_IMAGE_BUFFER_FRONT bit is set.  We never want to set up a front
>> buffer that we didn't ask for and it seems wrong that the loader has
>> to clear image.front, if the driver didn't ask for front.
>
> I simply duplicated the logic from the DRI2 path which works exactly the
> same way (asks for buffers, then looks to see what it got). I didn't dig
> into the details further than this, I'm afraid. The only case where asks
> != received is for pixmap targets where you always get a front buffer. I
> assumed there was some deep semantic requirement for that...

The difference is that there the loader returns a packed array of the
buffers the driver asked for. Now we're using a struct which can be
sparsely populated, so the driver should only look at the fields it
asked for.
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-06 16:17       ` Kristian Høgsberg
@ 2013-11-06 18:09         ` Keith Packard
  2013-11-06 19:06           ` Kristian Høgsberg
  0 siblings, 1 reply; 36+ messages in thread
From: Keith Packard @ 2013-11-06 18:09 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: mesa3d-dev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 5075 bytes --]

Kristian Høgsberg <hoegsberg@gmail.com> writes:

> It just the two older create context functions (which fall back to
> calling driCreateContextAtribs) and allocateBuffer and releaseBuffer.
> The two buffer functions are __DRIbuffer specific of course, but we
> can implement them in terms of __DRIimage in dri_util.c now.

I guess the benefit is that we could remove the DRIdri2Extension
functions from each driver and just use the DRIimage-based wrappers in
dri_util then?

We're still stuck with leaving the DRIdri2Extension as the interface
From the loader though.

> There is a third option, which is to pull the functions we need from
> __DRIcoreExtension into the __DRIimageDriverExtension, which then is
> all you need along with __DRIimageExtension.  This is as painful in
> the short term as the current __DRIimageDriverExtension, but it lets
> of cut loose of the DRI1 (__DRIcoreExtension has the DRI1
> createNewScreen in it) and DRI2 baggage properly later on.  And
> pulling out the functions into a loader private struct as you suggest
> will make it a lot less painful.  The functions we move from core to
> _DRIimageDriverExtension will share the same implementation in
> dri_util.c so there's no new code.

That doesn't seem like a crazy plan; at least Image-based loaders would
be simple then; find the DRIimageDriverExtension and that's it.

> Right - I actually like the clean break idea, but if we're going to
> take that pain I want to get rid of all the junk and avoid the awkward
> "use some stuff from __DRIcoreExtension and other stuff from
> __DRIimageDriverExtension" setup.  So we should either 1) make
> __DRIimageDriverExtension completely replace __DRIcoreExtension and
> __DRIdri2Extension, or 2) just do a minimal, incremental change (just
> the extension to indicate the support for __DRIimage based
> getbuffers).

If we're going to get drivers to add DRIimageExtension to the list of
exported extensions, then it doesn't seem like it matters which way we
go here -- we can move from 2) to 1) in the future without changing any
drivers, only the dri_util bits and the loaders.

However, if we think that 1) is the way to go, we might as well just do
it as that'd avoid having to ever fix the loaders.

> The difference is that there the loader returns a packed array of the
> buffers the driver asked for. Now we're using a struct which can be
> sparsely populated, so the driver should only look at the fields it
> asked for.

My concern is that the DRI2 drivers always return a front buffer for
pixmap drawables, and I think this is actually required for things to
work right (I have vague memories of hacking at this when I started
this).

How about I just stick the set of returned images back into the
DRIimageList struct:

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 2601249..2a873d8 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1319,6 +1319,7 @@ enum __DRIimageBufferMask {
 };
 
 struct __DRIimageList {
+   uint32_t image_mask;
    __DRIimage *back;
    __DRIimage *front;
 };
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index 1bb8241..7de7abd 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -1208,6 +1208,7 @@ dri3_get_buffers(__DRIdrawable *driDrawable,
    struct dri3_drawable *priv = loaderPrivate;
    struct dri3_buffer   *front, *back;
 
+   buffers->image_mask = 0;
    buffers->front = NULL;
    buffers->back = NULL;
 
@@ -1254,12 +1255,15 @@ dri3_get_buffers(__DRIdrawable *driDrawable,
    }
 
    if (front) {
+      buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
       buffers->front = front->image;
       priv->have_fake_front = !priv->is_pixmap;
    }
 
-   if (back)
+   if (back) {
+      buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
       buffers->back = back->image;
+   }
 
    priv->stamp = stamp;
 
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 90bbbfc..273d455 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -1338,7 +1338,7 @@ intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
                                         buffer_mask,
                                         &images);
 
-   if (images.front) {
+   if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
       assert(front_rb);
       drawable->w = images.front->width;
       drawable->h = images.front->height;
@@ -1348,7 +1348,7 @@ intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
                                 images.front,
                                 __DRI_IMAGE_BUFFER_FRONT);
    }
-   if (images.back) {
+   if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
       drawable->w = images.back->width;
       drawable->h = images.back->height;
       intel_update_image_buffer(brw,

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-06 18:09         ` Keith Packard
@ 2013-11-06 19:06           ` Kristian Høgsberg
  2013-11-06 19:29             ` Keith Packard
  0 siblings, 1 reply; 36+ messages in thread
From: Kristian Høgsberg @ 2013-11-06 19:06 UTC (permalink / raw)
  To: Keith Packard; +Cc: mesa3d-dev, dri-devel

On Wed, Nov 6, 2013 at 10:09 AM, Keith Packard <keithp@keithp.com> wrote:
> Kristian Høgsberg <hoegsberg@gmail.com> writes:
>
>> It just the two older create context functions (which fall back to
>> calling driCreateContextAtribs) and allocateBuffer and releaseBuffer.
>> The two buffer functions are __DRIbuffer specific of course, but we
>> can implement them in terms of __DRIimage in dri_util.c now.
>
> I guess the benefit is that we could remove the DRIdri2Extension
> functions from each driver and just use the DRIimage-based wrappers in
> dri_util then?
>
> We're still stuck with leaving the DRIdri2Extension as the interface
> From the loader though.
>
>> There is a third option, which is to pull the functions we need from
>> __DRIcoreExtension into the __DRIimageDriverExtension, which then is
>> all you need along with __DRIimageExtension.  This is as painful in
>> the short term as the current __DRIimageDriverExtension, but it lets
>> of cut loose of the DRI1 (__DRIcoreExtension has the DRI1
>> createNewScreen in it) and DRI2 baggage properly later on.  And
>> pulling out the functions into a loader private struct as you suggest
>> will make it a lot less painful.  The functions we move from core to
>> _DRIimageDriverExtension will share the same implementation in
>> dri_util.c so there's no new code.
>
> That doesn't seem like a crazy plan; at least Image-based loaders would
> be simple then; find the DRIimageDriverExtension and that's it.
>
>> Right - I actually like the clean break idea, but if we're going to
>> take that pain I want to get rid of all the junk and avoid the awkward
>> "use some stuff from __DRIcoreExtension and other stuff from
>> __DRIimageDriverExtension" setup.  So we should either 1) make
>> __DRIimageDriverExtension completely replace __DRIcoreExtension and
>> __DRIdri2Extension, or 2) just do a minimal, incremental change (just
>> the extension to indicate the support for __DRIimage based
>> getbuffers).
>
> If we're going to get drivers to add DRIimageExtension to the list of
> exported extensions, then it doesn't seem like it matters which way we
> go here -- we can move from 2) to 1) in the future without changing any
> drivers, only the dri_util bits and the loaders.
>
> However, if we think that 1) is the way to go, we might as well just do
> it as that'd avoid having to ever fix the loaders.

I'm OK with either approach. It does seem like cleaning up the DRI
driver interface is orthogonal to enabling the __DRIimage based
getBuffer callout though.

>> The difference is that there the loader returns a packed array of the
>> buffers the driver asked for. Now we're using a struct which can be
>> sparsely populated, so the driver should only look at the fields it
>> asked for.
>
> My concern is that the DRI2 drivers always return a front buffer for
> pixmap drawables, and I think this is actually required for things to
> work right (I have vague memories of hacking at this when I started
> this).
>
> How about I just stick the set of returned images back into the
> DRIimageList struct:

I think that's fine.  I was going to say that if we expect the
requested and the returned set of buffers to differ, we might as well
just memset the struct and let non-NULL images indicate returned
images.  But in case of a driver with a newer interface that extends
the struct (stereoscopic buffers), the loader can't memset the entire
struct (it only knows the smaller, previous version), and the driver
will think the non-NULL garbage fields are valid images.  So the
image_mask makes sense.

Kristian

> diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
> index 2601249..2a873d8 100644
> --- a/include/GL/internal/dri_interface.h
> +++ b/include/GL/internal/dri_interface.h
> @@ -1319,6 +1319,7 @@ enum __DRIimageBufferMask {
>  };
>
>  struct __DRIimageList {
> +   uint32_t image_mask;
>     __DRIimage *back;
>     __DRIimage *front;
>  };
> diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
> index 1bb8241..7de7abd 100644
> --- a/src/glx/dri3_glx.c
> +++ b/src/glx/dri3_glx.c
> @@ -1208,6 +1208,7 @@ dri3_get_buffers(__DRIdrawable *driDrawable,
>     struct dri3_drawable *priv = loaderPrivate;
>     struct dri3_buffer   *front, *back;
>
> +   buffers->image_mask = 0;
>     buffers->front = NULL;
>     buffers->back = NULL;
>
> @@ -1254,12 +1255,15 @@ dri3_get_buffers(__DRIdrawable *driDrawable,
>     }
>
>     if (front) {
> +      buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
>        buffers->front = front->image;
>        priv->have_fake_front = !priv->is_pixmap;
>     }
>
> -   if (back)
> +   if (back) {
> +      buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
>        buffers->back = back->image;
> +   }
>
>     priv->stamp = stamp;
>
> diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
> index 90bbbfc..273d455 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.c
> +++ b/src/mesa/drivers/dri/i965/brw_context.c
> @@ -1338,7 +1338,7 @@ intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
>                                          buffer_mask,
>                                          &images);
>
> -   if (images.front) {
> +   if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
>        assert(front_rb);
>        drawable->w = images.front->width;
>        drawable->h = images.front->height;
> @@ -1348,7 +1348,7 @@ intel_update_image_buffers(struct brw_context *brw, __DRIdrawable *drawable)
>                                  images.front,
>                                  __DRI_IMAGE_BUFFER_FRONT);
>     }
> -   if (images.back) {
> +   if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
>        drawable->w = images.back->width;
>        drawable->h = images.back->height;
>        intel_update_image_buffer(brw,
>
> --
> keith.packard@intel.com
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension
  2013-11-06 19:06           ` Kristian Høgsberg
@ 2013-11-06 19:29             ` Keith Packard
  0 siblings, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-06 19:29 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: mesa3d-dev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 1003 bytes --]

Kristian Høgsberg <hoegsberg@gmail.com> writes:

> I'm OK with either approach. It does seem like cleaning up the DRI
> driver interface is orthogonal to enabling the __DRIimage based
> getBuffer callout though.

We should probably not merge what we don't want to maintain though;
let's decide over lunch. I don't think it matters very much to the
current code, it'll only bug us in small ways in the future.

> I think that's fine.  I was going to say that if we expect the
> requested and the returned set of buffers to differ, we might as well
> just memset the struct and let non-NULL images indicate returned
> images.  But in case of a driver with a newer interface that extends
> the struct (stereoscopic buffers), the loader can't memset the entire
> struct (it only knows the smaller, previous version), and the driver
> will think the non-NULL garbage fields are valid images.  So the
> image_mask makes sense.

That's what I was thinking.

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/8] dri/intel: Add explicit size parameter to intel_region_alloc_for_fd
  2013-11-05 22:23   ` Kristian Høgsberg
  2013-11-06  0:52     ` Keith Packard
@ 2013-11-07  5:17     ` Christopher James Halse Rogers
  2013-11-07  5:42       ` Keith Packard
  1 sibling, 1 reply; 36+ messages in thread
From: Christopher James Halse Rogers @ 2013-11-07  5:17 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: mesa3d-dev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 6622 bytes --]

On Tue, 2013-11-05 at 14:23 -0800, Kristian Høgsberg wrote:
> On Mon, Nov 04, 2013 at 06:23:23PM -0800, Keith Packard wrote:
> > Instead of assuming that the size will be height * pitch, have the caller pass
> > in the size explicitly.
> > 
> > Signed-off-by: Keith Packard <keithp@keithp.com>
> > ---
> >  src/mesa/drivers/dri/i915/intel_regions.c | 4 ++--
> >  src/mesa/drivers/dri/i915/intel_regions.h | 2 +-
> >  src/mesa/drivers/dri/i915/intel_screen.c  | 2 +-
> >  src/mesa/drivers/dri/i965/intel_regions.c | 4 ++--
> >  src/mesa/drivers/dri/i965/intel_regions.h | 1 +
> >  src/mesa/drivers/dri/i965/intel_screen.c  | 2 +-
> >  6 files changed, 8 insertions(+), 7 deletions(-)
> > 
> > diff --git a/src/mesa/drivers/dri/i915/intel_regions.c b/src/mesa/drivers/dri/i915/intel_regions.c
> > index 44f7030..9f5b89e 100644
> > --- a/src/mesa/drivers/dri/i915/intel_regions.c
> > +++ b/src/mesa/drivers/dri/i915/intel_regions.c
> > @@ -209,6 +209,7 @@ struct intel_region *
> >  intel_region_alloc_for_fd(struct intel_screen *screen,
> >                            GLuint cpp,
> >                            GLuint width, GLuint height, GLuint pitch,
> > +                          GLuint size,
> >                            int fd, const char *name)
> >  {
> >     struct intel_region *region;
> > @@ -216,8 +217,7 @@ intel_region_alloc_for_fd(struct intel_screen *screen,
> >     int ret;
> >     uint32_t bit_6_swizzle, tiling;
> >  
> > -   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr,
> > -                                               fd, height * pitch);
> > +   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr, fd, size);
> 
> The 3.12 kernel let's you get the bo size from lseek on the dma_buf
> fd.  I added libdrm support for getting the size that, and if that
> works, it overrides the user provided size:
> 
>   http://cgit.freedesktop.org/mesa/drm/commit/?id=9c52c3dc4763336884277d8005eac7e6efb77600
> 
> 3.12 is the first kernel where dma_buf fd passing works reliably
> anyway and the first kernel with render-nodes, so it's not worth the
> trouble to try to make this work for older kernels.
> 
> Regardless, this patchs looks good.
> 
> Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>
> 
> >     if (buffer == NULL)
> >        return NULL;
> >     ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
> > diff --git a/src/mesa/drivers/dri/i915/intel_regions.h b/src/mesa/drivers/dri/i915/intel_regions.h
> > index 5c612a9..6bc4a42 100644
> > --- a/src/mesa/drivers/dri/i915/intel_regions.h
> > +++ b/src/mesa/drivers/dri/i915/intel_regions.h
> > @@ -91,7 +91,7 @@ struct intel_region *
> >  intel_region_alloc_for_fd(struct intel_screen *screen,
> >                            GLuint cpp,
> >                            GLuint width, GLuint height, GLuint pitch,
> > -                          int fd, const char *name);
> > +                          GLuint size, int fd, const char *name);
> >  
> >  bool
> >  intel_region_flink(struct intel_region *region, uint32_t *name);
> > diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
> > index 3f54752..085e894 100644
> > --- a/src/mesa/drivers/dri/i915/intel_screen.c
> > +++ b/src/mesa/drivers/dri/i915/intel_screen.c
> > @@ -653,7 +653,7 @@ intel_create_image_from_fds(__DRIscreen *screen,
> >        return NULL;
> >  
> >     image->region = intel_region_alloc_for_fd(intelScreen,
> > -                                             1, width, height,
> > +                                             1, width, height, height * strides[0],
> >                                               strides[0], fds[0], "image");

You've presumably noticed this already, but this is the wrong way round
- you're passing height * stride as pitch, and stride as size. This
makes for awesome rendering.

> >     if (image->region == NULL) {
> >        free(image);
> > diff --git a/src/mesa/drivers/dri/i965/intel_regions.c b/src/mesa/drivers/dri/i965/intel_regions.c
> > index a6b80fd..3920f4f 100644
> > --- a/src/mesa/drivers/dri/i965/intel_regions.c
> > +++ b/src/mesa/drivers/dri/i965/intel_regions.c
> > @@ -209,6 +209,7 @@ struct intel_region *
> >  intel_region_alloc_for_fd(struct intel_screen *screen,
> >                            GLuint cpp,
> >                            GLuint width, GLuint height, GLuint pitch,
> > +                          GLuint size,
> >                            int fd, const char *name)
> >  {
> >     struct intel_region *region;
> > @@ -216,8 +217,7 @@ intel_region_alloc_for_fd(struct intel_screen *screen,
> >     int ret;
> >     uint32_t bit_6_swizzle, tiling;
> >  
> > -   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr,
> > -                                               fd, height * pitch);
> > +   buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr, fd, size);
> >     if (buffer == NULL)
> >        return NULL;
> >     ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle);
> > diff --git a/src/mesa/drivers/dri/i965/intel_regions.h b/src/mesa/drivers/dri/i965/intel_regions.h
> > index f08a113..05dfef3 100644
> > --- a/src/mesa/drivers/dri/i965/intel_regions.h
> > +++ b/src/mesa/drivers/dri/i965/intel_regions.h
> > @@ -92,6 +92,7 @@ struct intel_region *
> >  intel_region_alloc_for_fd(struct intel_screen *screen,
> >                            GLuint cpp,
> >                            GLuint width, GLuint height, GLuint pitch,
> > +                          GLuint size,
> >                            int fd, const char *name);
> >  
> >  bool
> > diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
> > index ce8124b..b89b1a5 100644
> > --- a/src/mesa/drivers/dri/i965/intel_screen.c
> > +++ b/src/mesa/drivers/dri/i965/intel_screen.c
> > @@ -718,7 +718,7 @@ intel_create_image_from_fds(__DRIscreen *screen,
> >        return NULL;
> >  
> >     image->region = intel_region_alloc_for_fd(intelScreen,
> > -                                             1, width, height,
> > +                                             1, width, height, height * strides[0],
> >                                               strides[0], fds[0], "image");
> >     if (image->region == NULL) {
> >        free(image);
> > -- 
> > 1.8.4.2
> > 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel



[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 3/8] dri/intel: Add explicit size parameter to intel_region_alloc_for_fd
  2013-11-07  5:17     ` Christopher James Halse Rogers
@ 2013-11-07  5:42       ` Keith Packard
  0 siblings, 0 replies; 36+ messages in thread
From: Keith Packard @ 2013-11-07  5:42 UTC (permalink / raw)
  To: Christopher James Halse Rogers, Kristian Høgsberg
  Cc: mesa3d-dev, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 2304 bytes --]

Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
writes:

> You've presumably noticed this already, but this is the wrong way round
> - you're passing height * stride as pitch, and stride as size. This
> makes for awesome rendering.

Thanks for catching this; I've flipped them around, and also fixed the
fact that these calls were passing '1' for cpp, which appears to not
actually matter most of the time, but as the correct value was sitting
there in the image structure for the taking, I added that as well.

You reviewed this on IRC, so I'll be merging it into the commit on my
branch, just putting it here for other people to look at:

diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index 38badec..3ac5aa2 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -608,8 +608,8 @@ intel_create_image_from_fds(__DRIscreen *screen,
       return NULL;
 
    image->region = intel_region_alloc_for_fd(intelScreen,
-                                             1, width, height, height * strides[0],
-                                             strides[0], fds[0], "image");
+                                             f->planes[0].cpp, width, height, strides[0],
+                                             height * strides[0], fds[0], "image");
    if (image->region == NULL) {
       free(image);
       return NULL;
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index 7571921..dcfde97 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -663,8 +663,8 @@ intel_create_image_from_fds(__DRIscreen *screen,
       return NULL;
 
    image->region = intel_region_alloc_for_fd(intelScreen,
-                                             1, width, height, height * strides[0],
-                                             strides[0], fds[0], "image");
+                                             f->planes[0].cpp, width, height, strides[0],
+                                             height * strides[0], fds[0], "image");
    if (image->region == NULL) {
       free(image);
       return NULL;

-- 
keith.packard@intel.com

[-- Attachment #1.2: Type: application/pgp-signature, Size: 827 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2013-11-07  5:42 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-05  2:23 [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
2013-11-05  2:23 ` [PATCH 1/8] drivers/dri/common: A few dri2 functions are not actually DRI2 specific Keith Packard
2013-11-05  2:23 ` [PATCH 2/8] dri/intel: Split out DRI2 buffer update code to separate function Keith Packard
2013-11-05  2:23 ` [PATCH 3/8] dri/intel: Add explicit size parameter to intel_region_alloc_for_fd Keith Packard
2013-11-05 22:23   ` Kristian Høgsberg
2013-11-06  0:52     ` Keith Packard
2013-11-07  5:17     ` Christopher James Halse Rogers
2013-11-07  5:42       ` Keith Packard
2013-11-05  2:23 ` [PATCH 4/8] Define __DRI_IMAGE_FORMAT_SARGB8 Keith Packard
2013-11-05  2:23 ` [PATCH 5/8] dri/common: Add functions mapping MESA_FORMAT_* <-> __DRI_IMAGE_FORMAT_* Keith Packard
2013-11-05  3:01   ` Jordan Justen
2013-11-05  4:11     ` Keith Packard
2013-11-05 22:53       ` Jordan Justen
2013-11-05 22:35   ` Kristian Høgsberg
2013-11-06  0:54     ` Keith Packard
2013-11-05  2:23 ` [PATCH 6/8] dri/i915, dri/i965: Use driGLFormatToImageFormat and driImageFormatToGLFormat Keith Packard
2013-11-05 22:37   ` [PATCH 6/8] dri/i915,dri/i965: " Kristian Høgsberg
2013-11-05  2:23 ` [PATCH 7/8] dri: add __DRIimageLoaderExtension and __DRIimageDriverExtension Keith Packard
2013-11-05 20:05   ` Eric Anholt
2013-11-05 23:47     ` Keith Packard
2013-11-05 22:59   ` Kristian Høgsberg
2013-11-06  0:59     ` Keith Packard
2013-11-06  2:48       ` Kristian Høgsberg
2013-11-06  6:25   ` Kristian Høgsberg
2013-11-06 14:55     ` Keith Packard
2013-11-06 16:17       ` Kristian Høgsberg
2013-11-06 18:09         ` Keith Packard
2013-11-06 19:06           ` Kristian Høgsberg
2013-11-06 19:29             ` Keith Packard
2013-11-05  2:23 ` [PATCH 8/8] Add DRI3+Present loader Keith Packard
2013-11-05 23:10   ` Eric Anholt
2013-11-06  2:32     ` Keith Packard
2013-11-05 16:40 ` [PATCH 0/8] Add DRIimage-based DRI3/Present loader Keith Packard
2013-11-05 20:04   ` Eric Anholt
2013-11-05 22:09     ` Kristian Høgsberg
2013-11-05 23:54     ` Keith Packard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.