Mesa (master): gallium: Update the dri2 state tracker to support dri1.

Thomas Hellstrom thomash at kemper.freedesktop.org
Tue Apr 28 10:06:11 UTC 2009


Module: Mesa
Branch: master
Commit: ca1f5f7e6c05e34cfe8ef10f29aa19f5547311e6
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ca1f5f7e6c05e34cfe8ef10f29aa19f5547311e6

Author: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
Date:   Tue Apr 28 11:49:39 2009 +0200

gallium: Update the dri2 state tracker to support dri1.

Signed-off-by: Thomas Hellstrom <thellstrom-at-vmware-dot-com>

---

 src/gallium/state_trackers/dri/dri_context.c  |   91 ++++++--
 src/gallium/state_trackers/dri/dri_context.h  |   36 +++-
 src/gallium/state_trackers/dri/dri_drawable.c |  318 +++++++++++++++++++++++--
 src/gallium/state_trackers/dri/dri_drawable.h |   18 ++-
 src/gallium/state_trackers/dri/dri_screen.c   |   87 ++++++-
 src/gallium/state_trackers/dri/dri_screen.h   |   12 +-
 6 files changed, 507 insertions(+), 55 deletions(-)

diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c
index 92c26ac..a45fb54 100644
--- a/src/gallium/state_trackers/dri/dri_context.c
+++ b/src/gallium/state_trackers/dri/dri_context.c
@@ -32,9 +32,8 @@
 #include "dri_screen.h"
 
 #include "dri_drawable.h"
-
-
 #include "state_tracker/drm_api.h"
+#include "state_tracker/dri1_api.h"
 #include "state_tracker/st_public.h"
 #include "state_tracker/st_context.h"
 #include "pipe/p_context.h"
@@ -44,6 +43,7 @@
 #include "util/u_memory.h"
 
 
+
 GLboolean
 dri_create_context(const __GLcontextModes *visual,
                    __DRIcontextPrivate *cPriv,
@@ -65,6 +65,9 @@ dri_create_context(const __GLcontextModes *visual,
    cPriv->driverPrivate = ctx;
    ctx->cPriv = cPriv;
    ctx->sPriv = sPriv;
+   ctx->lock = screen->drmLock;
+   ctx->d_stamp = -1;
+   ctx->r_stamp = -1;
 
    driParseConfigFiles(&ctx->optionCache,
                        &screen->optionCache,
@@ -126,13 +129,22 @@ dri_destroy_context(__DRIcontextPrivate *cPriv)
 GLboolean
 dri_unbind_context(__DRIcontextPrivate *cPriv)
 {
-   struct dri_context *ctx = dri_context(cPriv);
-   st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
-   /* XXX make_current(NULL)? */
+   if (cPriv) {
+      struct dri_context *ctx = dri_context(cPriv);
+
+      if (--ctx->bind_count == 0) {
+	 GET_CURRENT_CONTEXT(curGLCtx);
+
+	 if (ctx->st == curGLCtx->st) {
+	    st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+	    st_make_current(NULL, NULL, NULL);
+	 }
+      }
+   }
+
    return GL_TRUE;
 }
 
-
 GLboolean
 dri_make_current(__DRIcontextPrivate *cPriv,
                  __DRIdrawablePrivate *driDrawPriv,
@@ -143,23 +155,32 @@ dri_make_current(__DRIcontextPrivate *cPriv,
       struct dri_screen *screen = dri_screen(cPriv->driScreenPriv);
       struct dri_drawable *draw = dri_drawable(driDrawPriv);
       struct dri_drawable *read = dri_drawable(driReadPriv);
+      GET_CURRENT_CONTEXT(oldGLCtx);
+
+      if (oldGLCtx && oldGLCtx->st != ctx->st)
+	 st_flush(oldGLCtx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+      ++ctx->bind_count;
 
       /* This is for situations in which we need a rendering context but
        * there may not be any currently bound.
        */
       screen->dummyContext = ctx;
 
-      st_make_current(ctx->st,
-                      draw->stfb,
-                      read->stfb);
-
       /* used in dri_flush_frontbuffer */
       ctx->dPriv = driDrawPriv;
-
-      if (driDrawPriv)
-         dri_get_buffers(driDrawPriv);
-      if (driDrawPriv != driReadPriv && driReadPriv)
-         dri_get_buffers(driReadPriv);
+      ctx->rPriv = driReadPriv;
+
+      st_make_current(ctx->st, draw->stfb, read->stfb);
+
+      if (__dri1_api_hooks) {
+	 dri1_update_drawables(ctx, draw, read);
+      } else {
+	 if (driDrawPriv)
+	    dri_get_buffers(driDrawPriv);
+	 if (driDrawPriv != driReadPriv && driReadPriv)
+	    dri_get_buffers(driReadPriv);
+      }
    } else {
       st_make_current(NULL, NULL, NULL);
    }
@@ -167,4 +188,44 @@ dri_make_current(__DRIcontextPrivate *cPriv,
    return GL_TRUE;
 }
 
+static void
+st_dri_lock(struct pipe_context *pipe)
+{
+   dri_lock((struct dri_context *) pipe->priv);
+}
+
+static void
+st_dri_unlock(struct pipe_context *pipe)
+{
+   dri_unlock((struct dri_context *) pipe->priv);
+}
+
+static boolean
+st_dri_is_locked(struct pipe_context *pipe)
+{
+   return ((struct dri_context *) pipe->priv)->isLocked;
+}
+
+static boolean
+st_dri_lost_lock(struct pipe_context *pipe)
+{
+   return ((struct dri_context *) pipe->priv)->wsLostLock;
+}
+
+static void
+st_dri_clear_lost_lock(struct pipe_context *pipe)
+{
+   ((struct dri_context *) pipe->priv)->wsLostLock = FALSE;
+}
+
+struct dri1_api_lock_funcs dri1_lf =
+{
+   .lock = st_dri_lock,
+   .unlock = st_dri_unlock,
+   .is_locked = st_dri_is_locked,
+   .is_lock_lost = st_dri_lost_lock,
+   .clear_lost_lock = st_dri_clear_lost_lock
+};
+
+
 /* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_context.h b/src/gallium/state_trackers/dri/dri_context.h
index e910472..82a5916 100644
--- a/src/gallium/state_trackers/dri/dri_context.h
+++ b/src/gallium/state_trackers/dri/dri_context.h
@@ -42,32 +42,64 @@ struct pipe_fence;
 struct st_context;
 struct dri_drawable;
 
-
 struct dri_context
 {
    /* dri */
    __DRIscreenPrivate *sPriv;
    __DRIcontextPrivate *cPriv;
    __DRIdrawablePrivate *dPriv;
+   __DRIdrawablePrivate *rPriv;
 
    driOptionCache optionCache;
 
+   unsigned int d_stamp;
+   unsigned int r_stamp;
+
+   drmLock *lock;
+   boolean isLocked;
+   boolean stLostLock;
+   boolean wsLostLock;
+
+   unsigned int bind_count;
+
    /* gallium */
    struct st_context *st;
    struct pipe_context *pipe;
 };
 
-
 static INLINE struct dri_context *
 dri_context(__DRIcontextPrivate *driContextPriv)
 {
    return (struct dri_context *) driContextPriv->driverPrivate;
 }
 
+static INLINE void
+dri_lock(struct dri_context *ctx)
+{
+   drm_context_t hw_context = ctx->cPriv->hHWContext;
+   char ret = 0;
+
+   DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret);
+   if (ret) {
+      drmGetLock(ctx->sPriv->fd, hw_context, 0);
+      ctx->stLostLock = TRUE;
+      ctx->wsLostLock = TRUE;
+   }
+   ctx->isLocked = TRUE;
+}
+
+static INLINE void
+dri_unlock(struct dri_context *ctx)
+{
+   ctx->isLocked = FALSE;
+   DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext);
+}
 
 /***********************************************************************
  * dri_context.c
  */
+extern struct dri1_api_lock_funcs dri1_lf;
+
 void
 dri_destroy_context(__DRIcontextPrivate * driContextPriv);
 
diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c
index 2e3f409..287617e 100644
--- a/src/gallium/state_trackers/dri/dri_drawable.c
+++ b/src/gallium/state_trackers/dri/dri_drawable.c
@@ -37,6 +37,7 @@
 #include "pipe/p_screen.h"
 #include "pipe/p_inlines.h"
 #include "state_tracker/drm_api.h"
+#include "state_tracker/dri1_api.h"
 #include "state_tracker/st_public.h"
 #include "state_tracker/st_context.h"
 #include "state_tracker/st_cb_fbo.h"
@@ -207,22 +208,6 @@ dri_flush_frontbuffer(struct pipe_screen *screen,
 }
 
 
-void
-dri_swap_buffers(__DRIdrawablePrivate * dPriv)
-{
-   /* not needed for dri2 */
-   assert(0);
-}
-
-
-void
-dri_copy_sub_buffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
-{
-   /* not needed for dri2 */
-   assert(0);
-}
-
-
 /**
  * This is called when we need to set up GL rendering to a new X window.
  */
@@ -305,21 +290,322 @@ dri_create_buffer(__DRIscreenPrivate *sPriv,
       drawable->attachments[i++] = __DRI_BUFFER_STENCIL;
    drawable->num_attachments = i;
 
+   drawable->desired_fences = 2;
+
    return GL_TRUE;
 fail:
    FREE(drawable);
    return GL_FALSE;
 }
 
+static struct pipe_fence_handle *
+dri_swap_fences_pop_front(struct dri_drawable *draw)
+{
+   struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
+   struct pipe_fence_handle *fence = NULL;
+
+   if (draw->cur_fences >= draw->desired_fences) {
+      screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]);
+      screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL);
+      --draw->cur_fences;
+      draw->tail &= DRI_SWAP_FENCES_MASK;
+   }
+   return fence;
+}
+
+static void
+dri_swap_fences_push_back(struct dri_drawable *draw,
+			  struct pipe_fence_handle *fence)
+{
+   struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
+
+   if (!fence)
+      return;
+
+   if (draw->cur_fences < DRI_SWAP_FENCES_MAX) {
+      draw->cur_fences++;
+      screen->fence_reference(screen, &draw->swap_fences[draw->head++], fence);
+      draw->head &= DRI_SWAP_FENCES_MASK;
+   }
+}
 
 void
 dri_destroy_buffer(__DRIdrawablePrivate *dPriv)
 {
    struct dri_drawable *drawable = dri_drawable(dPriv);
+   struct pipe_fence_handle *fence;
+   struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen;
 
    st_unreference_framebuffer(drawable->stfb);
+   drawable->desired_fences = 0;
+   while(drawable->cur_fences) {
+      fence = dri_swap_fences_pop_front(drawable);
+      screen->fence_reference(screen, &fence, NULL);
+   }
 
    FREE(drawable);
 }
 
+static void
+dri1_update_drawables_locked(struct dri_context *ctx,
+			     __DRIdrawablePrivate *driDrawPriv,
+			     __DRIdrawablePrivate *driReadPriv)
+{
+   if (ctx->stLostLock) {
+      ctx->stLostLock = FALSE;
+      if (driDrawPriv == driReadPriv)
+	 DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv);
+      else
+	 DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv, driReadPriv);
+   }
+}
+
+/**
+ * This ensures all contexts which binds to a drawable picks up the
+ * drawable change and signals new buffer state.
+ * Calling st_resize_framebuffer for each context may seem like overkill,
+ * but no new buffers will actually be allocated if the dimensions doesn't
+ * change.
+ */
+
+static void
+dri1_propagate_drawable_change(struct dri_context *ctx)
+{
+   __DRIdrawablePrivate *dPriv = ctx->dPriv;
+   __DRIdrawablePrivate *rPriv = ctx->rPriv;
+   boolean flushed = FALSE;
+
+   if (dPriv && ctx->d_stamp != dPriv->lastStamp) {
+
+      st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+      flushed = TRUE;
+      ctx->d_stamp = dPriv->lastStamp;
+      st_resize_framebuffer(dri_drawable(dPriv)->stfb, dPriv->w, dPriv->h);
+
+   }
+
+   if (rPriv && dPriv != rPriv && ctx->r_stamp != rPriv->lastStamp) {
+
+      if (!flushed)
+	       st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+      ctx->r_stamp = rPriv->lastStamp;
+      st_resize_framebuffer(dri_drawable(rPriv)->stfb, rPriv->w, rPriv->h);
+
+   } else if (rPriv && dPriv == rPriv) {
+
+      ctx->r_stamp = ctx->d_stamp;
+
+   }
+}
+
+void
+dri1_update_drawables(struct dri_context *ctx,
+		      struct dri_drawable *draw,
+		      struct dri_drawable *read)
+{
+   dri_lock(ctx);
+   dri1_update_drawables_locked(ctx, draw->dPriv, read->dPriv);
+   dri_unlock(ctx);
+
+   dri1_propagate_drawable_change(ctx);
+}
+
+static INLINE boolean
+dri1_intersect_src_bbox(struct drm_clip_rect *dst,
+			int dst_x,
+			int dst_y,
+			const struct drm_clip_rect *src,
+			const struct drm_clip_rect *bbox)
+{
+   int xy1;
+   int xy2;
+
+   xy1 = ((int) src->x1 > (int) bbox->x1 + dst_x) ? src->x1 :
+      (int) bbox->x1 + dst_x;
+   xy2 = ((int) src->x2 < (int) bbox->x2 + dst_x) ? src->x2 :
+      (int) bbox->x2 + dst_x;
+   if (xy1 >= xy2 || xy1 < 0)
+      return FALSE;
+
+   dst->x1 = xy1;
+   dst->x2 = xy2;
+
+   xy1 = ((int) src->y1 > (int) bbox->y1 + dst_x) ? src->y1 :
+      (int) bbox->y1 + dst_x;
+   xy2 = ((int) src->y2 < (int) bbox->y2 + dst_x) ? src->y2 :
+      (int) bbox->y2 + dst_x;
+   if (xy1 >= xy2 || xy1 < 0)
+      return FALSE;
+
+   dst->y1 = xy1;
+   dst->y2 = xy2;
+   return TRUE;
+}
+
+
+static void
+dri1_swap_copy(struct dri_context *ctx,
+	       struct pipe_surface *dst,
+	       struct pipe_surface *src,
+	       __DRIdrawablePrivate *dPriv,
+	       const struct drm_clip_rect *bbox)
+{
+   struct pipe_context *pipe = ctx->pipe;
+   struct drm_clip_rect clip;
+   struct drm_clip_rect *cur;
+   int i;
+
+   cur = dPriv->pClipRects;
+
+   for (i=0; i<dPriv->numClipRects; ++i) {
+      if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox))
+	 pipe->surface_copy(pipe, dst, clip.x1, clip.y1,
+			    src,
+			    (int) clip.x1 - dPriv->x,
+			    (int) clip.y1 - dPriv->y,
+			    clip.x2 - clip.x1,
+			    clip.y2 - clip.y1);
+   }
+}
+
+static void
+dri1_copy_to_front(struct dri_context *ctx,
+		   struct pipe_surface *surf,
+		   __DRIdrawablePrivate *dPriv,
+		   const struct drm_clip_rect *sub_box,
+		   struct pipe_fence_handle **fence)
+{
+   struct pipe_context *pipe = ctx->pipe;
+   boolean save_lost_lock;
+   uint cur_w;
+   uint cur_h;
+   struct drm_clip_rect bbox;
+   boolean visible = TRUE;
+
+   *fence = NULL;
+
+   dri_lock(ctx);
+   save_lost_lock = ctx->stLostLock;
+   dri1_update_drawables_locked(ctx, dPriv, dPriv);
+   st_get_framebuffer_dimensions(dri_drawable(dPriv)->stfb, &cur_w, &cur_h);
+
+   bbox.x1 = 0;
+   bbox.x2 = cur_w;
+   bbox.y1 = 0;
+   bbox.y2 = cur_h;
+
+   if (sub_box)
+      visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box);
+
+   if (visible && __dri1_api_hooks->present_locked) {
+
+      __dri1_api_hooks->present_locked(pipe,
+				       surf,
+				       dPriv->pClipRects,
+				       dPriv->numClipRects,
+				       dPriv->x,
+				       dPriv->y,
+				       &bbox,
+				       fence);
+
+   } else if (visible && __dri1_api_hooks->front_srf_locked) {
+
+      struct pipe_surface *front =
+	 __dri1_api_hooks->front_srf_locked(pipe);
+
+      if (front)
+	 dri1_swap_copy(ctx, front, surf, dPriv, &bbox);
+
+      st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence);
+   }
+
+   ctx->stLostLock = save_lost_lock;
+
+   /**
+    * FIXME: Revisit this: Update drawables on copy_sub_buffer ?
+    */
+
+   if (!sub_box)
+      dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv);
+
+   dri_unlock(ctx);
+   dri1_propagate_drawable_change(ctx);
+}
+
+void
+dri1_flush_frontbuffer(struct pipe_screen *screen,
+		       struct pipe_surface *surf,
+		       void *context_private)
+{
+   struct dri_context *ctx = (struct dri_context *)context_private;
+   struct pipe_fence_handle *dummy_fence;
+
+   dri1_copy_to_front(ctx, surf, ctx->dPriv, NULL, &dummy_fence);
+
+   /**
+    * FIXME: Do we need swap throttling here?
+    */
+}
+
+void
+dri_swap_buffers(__DRIdrawablePrivate * dPriv)
+{
+   struct dri_context *ctx;
+   struct pipe_surface *back_surf;
+   struct dri_drawable *draw = dri_drawable(dPriv);
+   struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen;
+   struct pipe_fence_handle *fence;
+   GET_CURRENT_CONTEXT(glCtx);
+
+   assert(__dri1_api_hooks != NULL);
+
+   if (!glCtx)
+      return; /* For now */
+
+   ctx = (struct dri_context *) glCtx->st->pipe->priv;
+
+   st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
+   if (back_surf) {
+      st_notify_swapbuffers(draw->stfb);
+      st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+      fence = dri_swap_fences_pop_front(draw);
+      if (fence) {
+	 (void) screen->fence_finish(screen, fence, 0);
+	 screen->fence_reference(screen, &fence, NULL);
+      }
+      dri1_copy_to_front(ctx, back_surf, dPriv, NULL, &fence);
+      dri_swap_fences_push_back(draw, fence);
+      screen->fence_reference(screen, &fence, NULL);
+   }
+}
+
+void
+dri_copy_sub_buffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
+{
+   struct drm_clip_rect sub_bbox;
+   struct dri_context *ctx;
+   struct pipe_surface *back_surf;
+   struct dri_drawable *draw = dri_drawable(dPriv);
+   struct pipe_fence_handle *dummy_fence;
+   GET_CURRENT_CONTEXT(glCtx);
+
+   assert(__dri1_api_hooks != NULL);
+
+   if (!glCtx)
+      return;
+
+   ctx = (struct dri_context *) glCtx->st->pipe->priv;
+
+   sub_bbox.x1 = x;
+   sub_bbox.x2 = x + w;
+   sub_bbox.y1 = y;
+   sub_bbox.y2 = y + h;
+
+   st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf);
+   if (back_surf) {
+      st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
+      dri1_copy_to_front(ctx, back_surf, dPriv, &sub_bbox, &dummy_fence);
+   }
+}
+
 /* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h
index 185c657..c1341de 100644
--- a/src/gallium/state_trackers/dri/dri_drawable.h
+++ b/src/gallium/state_trackers/dri/dri_drawable.h
@@ -31,9 +31,11 @@
 #include "pipe/p_compiler.h"
 
 struct pipe_surface;
-struct pipe_fence;
+struct pipe_fence_handle;
 struct st_framebuffer;
 
+#define DRI_SWAP_FENCES_MAX  8
+#define DRI_SWAP_FENCES_MASK 7
 
 struct dri_drawable
 {
@@ -46,6 +48,11 @@ struct dri_drawable
 
    /* gallium */
    struct st_framebuffer *stfb;
+   struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX];
+   unsigned int head;
+   unsigned int tail;
+   unsigned int desired_fences;
+   unsigned int cur_fences;
 };
 
 
@@ -84,6 +91,15 @@ dri_get_buffers(__DRIdrawablePrivate * dPriv);
 void
 dri_destroy_buffer(__DRIdrawablePrivate *dPriv);
 
+void
+dri1_update_drawables(struct dri_context *ctx,
+		      struct dri_drawable *draw,
+		      struct dri_drawable *read);
+
+void
+dri1_flush_frontbuffer(struct pipe_screen *screen,
+		       struct pipe_surface *surf,
+		       void *context_private);
 #endif
 
 /* vim: set sw=3 ts=8 sts=3 expandtab: */
diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c
index ab33003..418bb90 100644
--- a/src/gallium/state_trackers/dri/dri_screen.c
+++ b/src/gallium/state_trackers/dri/dri_screen.c
@@ -40,7 +40,9 @@
 #include "pipe/p_context.h"
 #include "pipe/p_screen.h"
 #include "pipe/p_inlines.h"
+#include "pipe/p_format.h"
 #include "state_tracker/drm_api.h"
+#include "state_tracker/dri1_api.h"
 #include "state_tracker/st_public.h"
 #include "state_tracker/st_cb_fbo.h"
 
@@ -57,7 +59,6 @@ PUBLIC const char __driConfigOptions[] =
 
 const uint __driNConfigOptions = 3;
 
-
 static const __DRIextension *dri_screen_extensions[] = {
     &driReadDrawableExtension,
     &driCopySubBufferExtension.base,
@@ -67,6 +68,8 @@ static const __DRIextension *dri_screen_extensions[] = {
     NULL
 };
 
+struct dri1_api *__dri1_api_hooks = NULL;
+
 static const __DRIconfig **
 dri_fill_in_modes(__DRIscreenPrivate *psp,
                   unsigned pixel_bits, unsigned depth_bits,
@@ -139,7 +142,7 @@ dri_fill_in_modes(__DRIscreenPrivate *psp,
 /**
  * Get information about previous buffer swaps.
  */
-int
+static int
 dri_get_swap_info(__DRIdrawablePrivate * dPriv,
                   __DRIswapInfo * sInfo)
 {
@@ -151,13 +154,69 @@ dri_get_swap_info(__DRIdrawablePrivate * dPriv,
       return 0;
 }
 
+static INLINE void
+dri_copy_version(struct dri1_api_version *dst,
+		 const struct __DRIversionRec *src)
+{
+   dst->major = src->major;
+   dst->minor = src->minor;
+   dst->patch_level = src->patch;
+}
 
-/**
- * NULL stub for old dri loaders
- */
-const __DRIconfig **
+static const __DRIconfig **
 dri_init_screen(__DRIscreenPrivate *sPriv)
 {
+    struct dri_screen *screen;
+    const __DRIconfig **configs;
+    struct dri1_create_screen_arg arg;
+
+    dri_init_extensions(NULL);
+
+    screen = CALLOC_STRUCT(dri_screen);
+    if (!screen)
+       return NULL;
+
+    screen->sPriv = sPriv;
+    screen->fd = sPriv->fd;
+    screen->drmLock = (drmLock *) &sPriv->pSAREA->lock;
+
+    sPriv->private = (void *) screen;
+    sPriv->extensions = dri_screen_extensions;
+
+    arg.base.mode = DRM_CREATE_DRI1;
+    arg.lf = &dri1_lf;
+    arg.ddx_info = sPriv->pDevPriv;
+    arg.ddx_info_size = sPriv->devPrivSize;
+    arg.sarea = sPriv->pSAREA;
+    dri_copy_version(&arg.ddx_version, &sPriv->ddx_version);
+    dri_copy_version(&arg.dri_version, &sPriv->dri_version);
+    dri_copy_version(&arg.drm_version, &sPriv->drm_version);
+    arg.api = NULL;
+
+    screen->pipe_screen = drm_api_hooks.create_screen
+      (screen->fd, &arg.base);
+
+   if (!screen->pipe_screen || !arg.api) {
+      debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__);
+      goto out_no_screen;
+   }
+
+   __dri1_api_hooks = arg.api;
+
+   screen->pipe_screen->flush_frontbuffer = dri1_flush_frontbuffer;
+   driParseOptionInfo(&screen->optionCache,
+                      __driConfigOptions,
+                      __driNConfigOptions);
+
+   configs = dri_fill_in_modes(sPriv, sPriv->fbBPP, 24, 8, 1);
+   if (!configs)
+      goto out_no_configs;
+
+   return configs;
+ out_no_configs:
+   screen->pipe_screen->destroy(screen->pipe_screen);
+ out_no_screen:
+   FREE(screen);
    return NULL;
 }
 
@@ -167,10 +226,11 @@ dri_init_screen(__DRIscreenPrivate *sPriv)
  *
  * Returns the __GLcontextModes supported by this driver.
  */
-const __DRIconfig **
+static const __DRIconfig **
 dri_init_screen2(__DRIscreenPrivate *sPriv)
 {
    struct dri_screen *screen;
+   struct drm_create_screen_arg arg;
 
    /* Set up dispatch table to cope with all known extensions */
    dri_init_extensions(NULL);
@@ -183,9 +243,9 @@ dri_init_screen2(__DRIscreenPrivate *sPriv)
    screen->fd = sPriv->fd;
    sPriv->private = (void *) screen;
    sPriv->extensions = dri_screen_extensions;
+   arg.mode = DRM_CREATE_NORMAL;
 
-
-   screen->pipe_screen = drm_api_hooks.create_screen(screen->fd, NULL);
+   screen->pipe_screen = drm_api_hooks.create_screen(screen->fd, &arg);
    if (!screen->pipe_screen) {
       debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__);
       goto fail;
@@ -208,7 +268,7 @@ fail:
 }
 
 
-void
+static void
 dri_destroy_screen(__DRIscreenPrivate * sPriv)
 {
    struct dri_screen *screen = dri_screen(sPriv);
@@ -220,19 +280,20 @@ dri_destroy_screen(__DRIscreenPrivate * sPriv)
 
 
 PUBLIC const struct __DriverAPIRec driDriverAPI = {
-   .InitScreen          = dri_init_screen, /* not supported but exported */
+   .InitScreen          = dri_init_screen,
    .DestroyScreen       = dri_destroy_screen,
    .CreateContext       = dri_create_context,
    .DestroyContext      = dri_destroy_context,
    .CreateBuffer        = dri_create_buffer,
    .DestroyBuffer       = dri_destroy_buffer,
-   .SwapBuffers         = dri_swap_buffers, /* not supported but exported */
+   .SwapBuffers         = dri_swap_buffers,
    .MakeCurrent         = dri_make_current,
    .UnbindContext       = dri_unbind_context,
    .GetSwapInfo         = dri_get_swap_info,
    .GetDrawableMSC      = driDrawableGetMSC32,
    .WaitForMSC          = driWaitForMSC32,
-   .CopySubBuffer       = dri_copy_sub_buffer, /* not supported but exported */
+   .CopySubBuffer       = dri_copy_sub_buffer,
+   .InitScreen          = dri_init_screen,
    .InitScreen2         = dri_init_screen2,
 };
 
diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h
index 3751ec6..c358c35 100644
--- a/src/gallium/state_trackers/dri/dri_screen.h
+++ b/src/gallium/state_trackers/dri/dri_screen.h
@@ -37,6 +37,8 @@
 
 #include "pipe/p_compiler.h"
 
+#include "state_tracker/dri1_api.h"
+
 struct dri_screen
 {
    /* dri */
@@ -55,6 +57,7 @@ struct dri_screen
 
    /* drm */
    int fd;
+   drmLock *drmLock;
 
    /* gallium */
    struct pipe_winsys *pipe_winsys;
@@ -73,15 +76,8 @@ dri_screen(__DRIscreenPrivate *sPriv)
 /***********************************************************************
  * dri_screen.c
  */
-const __DRIconfig **
-dri_init_screen2(__DRIscreenPrivate *sPriv);
-
-void
-dri_destroy_screen(__DRIscreenPrivate * sPriv);
 
-int
-dri_get_swap_info(__DRIdrawablePrivate * dPriv,
-                  __DRIswapInfo * sInfo);
+extern struct dri1_api *__dri1_api_hooks;
 
 #endif
 




More information about the mesa-commit mailing list