st/glx: Use st_api.h instead of st_public.h.
authorChia-I Wu <olv@lunarg.com>
Wed, 10 Mar 2010 09:22:56 +0000 (17:22 +0800)
committerChia-I Wu <olv@lunarg.com>
Fri, 12 Mar 2010 01:57:11 +0000 (09:57 +0800)
src/gallium/state_trackers/glx/xlib/Makefile
src/gallium/state_trackers/glx/xlib/glx_api.c
src/gallium/state_trackers/glx/xlib/xm_api.c
src/gallium/state_trackers/glx/xlib/xm_api.h
src/gallium/state_trackers/glx/xlib/xm_st.c [new file with mode: 0644]
src/gallium/state_trackers/glx/xlib/xm_st.h [new file with mode: 0644]

index 7b2adc62c34d87fcbdde1886a0f6f680a739c82b..ddffdb162c7586575bd77a5fbc4efa8b2962f7bd 100644 (file)
@@ -11,6 +11,7 @@ C_SOURCES = \
        glx_api.c \
        glx_getproc.c \
        glx_usefont.c \
-       xm_api.c
+       xm_api.c \
+       xm_st.c
 
 include ../../../Makefile.template
index 2454585850008fc23e8a4e4e1c532eab97af3052..4930cd6cd505c5d800af591eeaa92cb1a9031aea 100644 (file)
 
 #include "xm_api.h"
 #include "main/context.h"
-#include "main/config.h"
 #include "main/macros.h"
 #include "main/imports.h"
 #include "main/version.h"
-#include "state_tracker/st_context.h"
-#include "state_tracker/st_public.h"
 
 
 /* This indicates the client-side GLX API and GLX encoder version. */
@@ -1304,7 +1301,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
    if (MakeCurrent_PrevContext == src) {
       _mesa_Flush();
    }
-   st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask );
+   XMesaCopyContext(xm_src, xm_dst, mask);
 }
 
 
index f4d7133d2ff1ed5ada9efeb4ef8ebb0fc7019124..6a0f3146dbf96f4a4a7eb8fb6f6f3676ff237728 100644 (file)
 #endif
 
 #include "xm_api.h"
-#include "main/context.h"
-#include "main/framebuffer.h"
+#include "xm_st.h"
 
-#include "state_tracker/st_public.h"
-#include "state_tracker/st_context.h"
+#include "main/context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_screen.h"
 #include "pipe/p_context.h"
@@ -84,6 +82,8 @@ void xmesa_set_driver( const struct xm_driver *templ )
 pipe_mutex _xmesa_lock;
 
 static struct pipe_screen *screen = NULL;
+static struct st_api *stapi = NULL;
+static struct st_manager *smapi = NULL;
 
 
 /**********************************************************************/
@@ -273,49 +273,49 @@ choose_pixel_format(XMesaVisual v)
    return 0;
 }
 
-
-
 /**
- * Query the default gallium screen for a Z/Stencil format that
- * at least matches the given depthBits and stencilBits.
+ * Choose a depth/stencil format for the given depth and stencil sizes.
  */
-static void
-xmesa_choose_z_stencil_format(int depthBits, int stencilBits,
-                              enum pipe_format *depthFormat,
-                              enum pipe_format *stencilFormat)
+static enum pipe_format
+choose_depth_stencil_format(int depth, int stencil)
 {
    const enum pipe_texture_target target = PIPE_TEXTURE_2D;
    const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
    const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE |
                                 PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO);
-   static enum pipe_format formats[] = {
-      PIPE_FORMAT_S8Z24_UNORM,
-      PIPE_FORMAT_Z24S8_UNORM,
-      PIPE_FORMAT_Z16_UNORM,
-      PIPE_FORMAT_Z32_UNORM
-   };
-   int i;
+   enum pipe_format formats[8], fmt;
+   int count, i;
 
    assert(screen);
 
-   *depthFormat = *stencilFormat = PIPE_FORMAT_NONE;
+   count = 0;
+   switch (depth) {
+   case 16:
+      if (!stencil)
+         formats[count++] = PIPE_FORMAT_Z16_UNORM;
+      break;
+   case 24:
+      formats[count++] = PIPE_FORMAT_S8Z24_UNORM;
+      formats[count++] = PIPE_FORMAT_Z24S8_UNORM;
+      break;
+   case 32:
+      if (!stencil)
+         formats[count++] = PIPE_FORMAT_Z32_UNORM;
+      break;
+   default:
+      break;
+   }
 
-   /* search for supported format */
-   for (i = 0; i < Elements(formats); i++) {
+   fmt = PIPE_FORMAT_NONE;
+   for (i = 0; i < count; i++) {
       if (screen->is_format_supported(screen, formats[i],
                                       target, tex_usage, geom_flags)) {
-         *depthFormat = formats[i];
+         fmt = formats[i];
          break;
       }
    }
 
-   if (stencilBits) {
-      *stencilFormat = *depthFormat;
-   }
-
-   /* XXX we should check that he chosen format has at least as many bits
-    * as what was requested.
-    */
+   return fmt;
 }
 
 
@@ -343,12 +343,14 @@ create_xmesa_buffer(Drawable d, BufferType type,
                     XMesaVisual vis, Colormap cmap)
 {
    XMesaBuffer b;
-   GLframebuffer *fb;
-   enum pipe_format colorFormat, depthFormat, stencilFormat;
    uint width, height;
 
    ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
 
+   xmesa_init(vis->display);
+   if (!screen)
+      return NULL;
+
    b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
    if (!b)
       return NULL;
@@ -361,24 +363,12 @@ create_xmesa_buffer(Drawable d, BufferType type,
    b->type = type;
    b->cmap = cmap;
 
-   /* determine PIPE_FORMATs for buffers */
-   colorFormat = choose_pixel_format(vis);
-
-   xmesa_choose_z_stencil_format(vis->mesa_visual.depthBits,
-                                 vis->mesa_visual.stencilBits,
-                                 &depthFormat, &stencilFormat);
-
-
    get_drawable_size(vis->display, d, &width, &height);
 
    /*
     * Create framebuffer, but we'll plug in our own renderbuffers below.
     */
-   b->stfb = st_create_framebuffer(&vis->mesa_visual,
-                                   colorFormat, depthFormat, stencilFormat,
-                                   width, height,
-                                   (void *) b);
-   fb = &b->stfb->Base;
+   b->stfb = xmesa_create_st_framebuffer(screen, b);
 
    /* GLX_EXT_texture_from_pixmap */
    b->TextureTarget = 0;
@@ -422,24 +412,21 @@ xmesa_free_buffer(XMesaBuffer buffer)
 
    for (b = XMesaBufferList; b; b = b->Next) {
       if (b == buffer) {
-         struct gl_framebuffer *fb = &buffer->stfb->Base;
-
          /* unlink buffer from list */
          if (prev)
             prev->Next = buffer->Next;
          else
             XMesaBufferList = buffer->Next;
 
-         /* mark as delete pending */
-         fb->DeletePending = GL_TRUE;
-
          /* Since the X window for the XMesaBuffer is going away, we don't
           * want to dereference this pointer in the future.
           */
          b->ws.drawable = 0;
 
-         /* Unreference.  If count = zero we'll really delete the buffer */
-         _mesa_reference_framebuffer(&fb, NULL);
+         /* XXX we should move the buffer to a delete-pending list and destroy
+          * the buffer until it is no longer current.
+          */
+         xmesa_destroy_st_framebuffer(buffer->stfb);
 
          free(buffer);
 
@@ -681,6 +668,26 @@ XMesaVisual XMesaCreateVisual( Display *display,
                             accum_blue_size, accum_alpha_size,
                             0 );
 
+   v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
+   if (db_flag)
+      v->stvis.buffer_mask = ST_ATTACHMENT_BACK_LEFT_MASK;
+   if (stereo_flag) {
+      v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_RIGHT_MASK;
+      if (db_flag)
+         v->stvis.buffer_mask = ST_ATTACHMENT_BACK_RIGHT_MASK;
+   }
+
+   v->stvis.color_format = choose_pixel_format(v);
+   v->stvis.depth_stencil_format =
+      choose_depth_stencil_format(depth_size, stencil_size);
+
+   v->stvis.accum_format = (accum_red_size +
+         accum_green_size + accum_blue_size + accum_alpha_size) ?
+      PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
+
+   v->stvis.samples = num_samples;
+   v->stvis.render_buffer = ST_ATTACHMENT_INVALID;
+
    /* XXX minor hack */
    v->mesa_visual.level = level;
    return v;
@@ -705,6 +712,26 @@ xmesa_init( Display *display )
    if (firstTime) {
       pipe_mutex_init(_xmesa_lock);
       screen = driver.create_pipe_screen( display );
+      stapi = xmesa_create_st_api();
+      smapi = CALLOC_STRUCT(st_manager);
+      if (smapi)
+         smapi->screen = screen;
+
+      if (!screen || !stapi || !smapi) {
+         if (screen) {
+            screen->destroy(screen);
+            screen = NULL;
+         }
+         if (stapi) {
+            stapi->destroy(stapi);
+            stapi = NULL;
+         }
+         if (smapi) {
+            FREE(smapi);
+            smapi = NULL;
+         }
+      }
+
       firstTime = GL_FALSE;
    }
 }
@@ -720,10 +747,7 @@ xmesa_init( Display *display )
 PUBLIC
 XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
 {
-   struct pipe_context *pipe = NULL;
    XMesaContext c;
-   GLcontext *mesaCtx;
-   uint pf;
 
    xmesa_init( v->display );
 
@@ -732,9 +756,6 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
    if (!c)
       return NULL;
 
-   pf = choose_pixel_format(v);
-   assert(pf);
-
    c->xm_visual = v;
    c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
    c->xm_read_buffer = NULL;
@@ -742,29 +763,18 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
    if (screen == NULL)
       goto fail;
 
-   /* Trace screen knows how to properly wrap context creation in the
-    * wrapped screen, so nothing special to do here:
-    */
-   pipe = screen->context_create(screen, (void *) c);
-   if (pipe == NULL)
-      goto fail;
-
-   c->st = st_create_context(pipe, 
-                             &v->mesa_visual,
-                             share_list ? share_list->st : NULL);
+   c->st = stapi->create_context(stapi, smapi,
+         &v->stvis, (share_list) ? share_list->st : NULL);
    if (c->st == NULL)
       goto fail;
 
-   mesaCtx = c->st->ctx;
-   c->st->ctx->DriverCtx = c;
+   c->st->st_manager_private = (void *) c;
 
    return c;
 
 fail:
    if (c->st)
-      st_destroy_context(c->st);
-   else if (pipe)
-      pipe->destroy(pipe);
+      c->st->destroy(c->st);
 
    free(c);
    return NULL;
@@ -775,7 +785,7 @@ fail:
 PUBLIC
 void XMesaDestroyContext( XMesaContext c )
 {
-   st_destroy_context(c->st);
+   c->st->destroy(c->st);
 
    /* FIXME: We should destroy the screen here, but if we do so, surfaces may 
     * outlive it, causing segfaults
@@ -881,7 +891,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
 {
    GET_CURRENT_CONTEXT(ctx);
    XMesaBuffer b;
-   GLuint width, height;
 
    assert(v);
 
@@ -889,19 +898,18 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
    if (!b)
       return NULL;
 
-   /* get pixmap size, update framebuffer/renderbuffer dims */
-   xmesa_get_window_size(v->display, b, &width, &height);
-   _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
+   /* get pixmap size */
+   xmesa_get_window_size(v->display, b, &b->width, &b->height);
 
    if (target == 0) {
       /* examine dims */
       if (ctx->Extensions.ARB_texture_non_power_of_two) {
          target = GLX_TEXTURE_2D_EXT;
       }
-      else if (   _mesa_bitcount(width)  == 1
-               && _mesa_bitcount(height) == 1) {
+      else if (   _mesa_bitcount(b->width)  == 1
+               && _mesa_bitcount(b->height) == 1) {
          /* power of two size */
-         if (height == 1) {
+         if (b->height == 1) {
             target = GLX_TEXTURE_1D_EXT;
          }
          else {
@@ -974,23 +982,20 @@ XMesaDestroyBuffer(XMesaBuffer b)
 
 
 /**
- * Query the current window size and update the corresponding GLframebuffer
- * and all attached renderbuffers.
- * Called when:
- *  1. the first time a buffer is bound to a context.
- *  2. SwapBuffers.  XXX probabaly from xm_flush_frontbuffer() too...
- * Note: it's possible (and legal) for xmctx to be NULL.  That can happen
- * when resizing a buffer when no rendering context is bound.
+ * Query the current drawable size and notify the binding context.
  */
 void
-xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
+xmesa_check_buffer_size(XMesaBuffer b)
 {
-   GLuint width, height;
-   xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
-   st_resize_framebuffer(drawBuffer->stfb, width, height);
-}
+   XMesaContext xmctx = XMesaGetCurrentContext();
 
+   if (b->type == PBUFFER)
+      return;
 
+   xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height);
+   if (xmctx && xmctx->xm_buffer == b)
+      xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb);
+}
 
 
 /*
@@ -1017,22 +1022,21 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
          c->xm_read_buffer == readBuffer)
         return GL_TRUE;
 
+      xmesa_check_buffer_size(drawBuffer);
+      if (readBuffer != drawBuffer)
+         xmesa_check_buffer_size(readBuffer);
+
       c->xm_buffer = drawBuffer;
       c->xm_read_buffer = readBuffer;
 
-      st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb, 
-                      &drawBuffer->ws);
-
-      xmesa_check_and_update_buffer_size(c, drawBuffer);
-      if (readBuffer != drawBuffer)
-         xmesa_check_and_update_buffer_size(c, readBuffer);
+      stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb);
 
       /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
       drawBuffer->wasCurrent = GL_TRUE;
    }
    else {
       /* Detach */
-      st_make_current( NULL, NULL, NULL, NULL );
+      stapi->make_current(stapi, NULL, NULL, NULL);
 
    }
    return GL_TRUE;
@@ -1051,14 +1055,8 @@ GLboolean XMesaUnbindContext( XMesaContext c )
 
 XMesaContext XMesaGetCurrentContext( void )
 {
-   GET_CURRENT_CONTEXT(ctx);
-   if (ctx) {
-      XMesaContext xmesa = xmesa_context(ctx);
-      return xmesa;
-   }
-   else {
-      return 0;
-   }
+   struct st_context_iface *st = stapi->get_current(stapi);
+   return (XMesaContext) (st) ? st->st_manager_private : NULL;
 }
 
 
@@ -1070,17 +1068,17 @@ XMesaContext XMesaGetCurrentContext( void )
 PUBLIC
 void XMesaSwapBuffers( XMesaBuffer b )
 {
-   struct pipe_surface *frontLeftSurf;
-
-   st_swapbuffers(b->stfb, &frontLeftSurf, NULL);
-
-   if (frontLeftSurf) {
-      screen->flush_frontbuffer( screen,
-                                 frontLeftSurf, 
-                                 &b->ws );
+   XMesaContext xmctx = XMesaGetCurrentContext();
+
+   if (xmctx && xmctx->xm_buffer == b) {
+      xmctx->st->flush( xmctx->st,
+            PIPE_FLUSH_RENDER_CACHE | 
+            PIPE_FLUSH_SWAPBUFFERS |
+            PIPE_FLUSH_FRAME,
+            NULL);
    }
 
-   xmesa_check_and_update_buffer_size(NULL, b);
+   xmesa_swap_st_framebuffer(b->stfb);
 }
 
 
@@ -1090,21 +1088,9 @@ void XMesaSwapBuffers( XMesaBuffer b )
  */
 void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
 {
-   struct pipe_surface *surf_front;
-   struct pipe_surface *surf_back;
-   struct pipe_context *pipe = NULL; /* XXX fix */
-
-   st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front);
-   st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back);
-
-   if (!surf_front || !surf_back)
-      return;
-
-   assert(pipe);
-   pipe->surface_copy(pipe,
-                      surf_front, x, y,  /* dest */
-                      surf_back, x, y,   /* src */
-                      width, height);
+   xmesa_copy_st_framebuffer(b->stfb,
+         ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT,
+         x, y, width, height);
 }
 
 
@@ -1112,7 +1098,13 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
 void XMesaFlush( XMesaContext c )
 {
    if (c && c->xm_visual->display) {
-      st_finish(c->st);
+      struct pipe_fence_handle *fence = NULL;
+
+      c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
+      if (fence) {
+         screen->fence_finish(screen, fence, 0);
+         screen->fence_reference(screen, &fence, NULL);
+      }
       XSync( c->xm_visual->display, False );
    }
 }
@@ -1186,3 +1178,10 @@ XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer)
 {
 }
 
+
+void
+XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask)
+{
+   if (dst->st->copy)
+      dst->st->copy(dst->st, src->st, mask);
+}
index de47064b410a5e3238bf261aa9830a0be10adb40..258abf92554bda53a11d35d39cc151ed5463f5a0 100644 (file)
@@ -58,8 +58,7 @@ and create a window, you must do the following to use the X/Mesa interface:
 
 
 #include "main/mtypes.h"
-#include "state_tracker/st_context.h"
-#include "state_tracker/st_public.h"
+#include "state_tracker/st_api.h"
 #include "os/os_thread.h"
 
 #include "state_tracker/xlib_sw_winsys.h"
@@ -258,6 +257,8 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
                                int format, int target, int mipmap);
 
 
+extern void
+XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask);
 
 
 /***********************************************************************
@@ -280,6 +281,8 @@ struct xmesa_visual {
    GLint BitsPerPixel;         /* True bits per pixel for XImages */
 
    GLboolean ximage_flag;      /* Use XImage for back buffer (not pixmap)? */
+
+   struct st_visual stvis;
 };
 
 
@@ -288,7 +291,7 @@ struct xmesa_visual {
  * Basically corresponds to a GLXContext.
  */
 struct xmesa_context {
-   struct st_context *st;
+   struct st_context_iface *st;
    XMesaVisual xm_visual;      /** pixel format info */
    XMesaBuffer xm_buffer;      /** current drawbuffer */
    XMesaBuffer xm_read_buffer;  /** current readbuffer */
@@ -311,7 +314,7 @@ typedef enum {
  * Basically corresponds to a GLXDrawable.
  */
 struct xmesa_buffer {
-   struct st_framebuffer *stfb;
+   struct st_framebuffer_iface *stfb;
    struct xlib_drawable ws;
 
    GLboolean wasCurrent;       /* was ever the current buffer? */
@@ -335,33 +338,15 @@ struct xmesa_buffer {
    GLint TextureMipmap; /** 0 or 1 */
 
    struct xmesa_buffer *Next;  /* Linked list pointer: */
-};
-
-
-
-/** cast wrapper */
-static INLINE XMesaContext
-xmesa_context(GLcontext *ctx)
-{
-   return (XMesaContext) ctx->DriverCtx;
-}
 
+   unsigned width, height;
+};
 
-/** cast wrapper */
-static INLINE XMesaBuffer
-xmesa_buffer(GLframebuffer *fb)
-{
-   struct st_framebuffer *stfb = (struct st_framebuffer *) fb;
-   return (XMesaBuffer) st_framebuffer_private(stfb);
-}
 
 
 extern void
 xmesa_init(Display *dpy);
 
-extern void
-xmesa_delete_framebuffer(struct gl_framebuffer *fb);
-
 extern XMesaBuffer
 xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis);
 
@@ -370,7 +355,7 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b,
                       GLuint *width, GLuint *height);
 
 extern void
-xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer);
+xmesa_check_buffer_size(XMesaBuffer b);
 
 extern void
 xmesa_destroy_buffers_on_display(Display *dpy);
@@ -378,13 +363,13 @@ xmesa_destroy_buffers_on_display(Display *dpy);
 static INLINE GLuint
 xmesa_buffer_width(XMesaBuffer b)
 {
-   return b->stfb->Base.Width;
+   return b->width;
 }
 
 static INLINE GLuint
 xmesa_buffer_height(XMesaBuffer b)
 {
-   return b->stfb->Base.Height;
+   return b->height;
 }
 
 
diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c
new file mode 100644 (file)
index 0000000..c5ea5c1
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * 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 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
+ * BRIAN PAUL 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:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include "util/u_memory.h"
+#include "util/u_inlines.h"
+
+#include "xm_api.h"
+#include "xm_st.h"
+
+/* support OpenGL by default */
+#ifndef XMESA_ST_MODULE
+#define XMESA_ST_MODULE st_module_OpenGL
+#endif
+
+struct xmesa_st_framebuffer {
+   struct pipe_screen *screen;
+   XMesaBuffer buffer;
+
+   struct st_visual stvis;
+
+   unsigned texture_width, texture_height;
+   struct pipe_texture *textures[ST_ATTACHMENT_COUNT];
+
+   struct pipe_surface *display_surface;
+};
+
+static INLINE struct xmesa_st_framebuffer *
+xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi)
+{
+   return (struct xmesa_st_framebuffer *) stfbi->st_manager_private;
+}
+
+/**
+ * Display an attachment to the xlib_drawable of the framebuffer.
+ */
+static boolean
+xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi,
+                             enum st_attachment_type statt)
+{
+   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
+   struct pipe_texture *ptex = xstfb->textures[statt];
+   struct pipe_surface *psurf;
+
+   if (!ptex)
+      return TRUE;
+
+   psurf = xstfb->display_surface;
+   /* (re)allocate the surface for the texture to be displayed */
+   if (!psurf || psurf->texture != ptex) {
+      pipe_surface_reference(&xstfb->display_surface, NULL);
+
+      psurf = xstfb->screen->get_tex_surface(xstfb->screen,
+            ptex, 0, 0, 0, PIPE_BUFFER_USAGE_CPU_READ);
+      if (!psurf)
+         return FALSE;
+
+      xstfb->display_surface = psurf;
+   }
+
+   xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws);
+
+   return TRUE;
+}
+
+/**
+ * Remove outdated textures and create the requested ones.
+ */
+static void
+xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi,
+                                       const enum st_attachment_type *statts,
+                                       unsigned count)
+{
+   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
+   struct pipe_texture templ;
+   unsigned request_mask, i;
+
+   request_mask = 0;
+   for (i = 0; i < count; i++)
+      request_mask |= 1 << statts[i];
+
+   memset(&templ, 0, sizeof(templ));
+   templ.target = PIPE_TEXTURE_2D;
+   templ.width0 = xstfb->texture_width;
+   templ.height0 = xstfb->texture_height;
+   templ.depth0 = 1;
+   templ.last_level = 0;
+
+   for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
+      struct pipe_texture *ptex = xstfb->textures[i];
+      enum pipe_format format;
+      unsigned tex_usage;
+
+      /* remove outdated textures */
+      if (ptex && (ptex->width0 != xstfb->texture_width ||
+                   ptex->height0 != xstfb->texture_height)) {
+         pipe_texture_reference(&xstfb->textures[i], NULL);
+         ptex = NULL;
+      }
+
+      /* the texture already exists or not requested */
+      if (ptex || !(request_mask & (1 << i)))
+         continue;
+
+      switch (i) {
+      case ST_ATTACHMENT_FRONT_LEFT:
+      case ST_ATTACHMENT_BACK_LEFT:
+      case ST_ATTACHMENT_FRONT_RIGHT:
+      case ST_ATTACHMENT_BACK_RIGHT:
+         format = xstfb->stvis.color_format;
+         tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
+                     PIPE_TEXTURE_USAGE_RENDER_TARGET;
+         break;
+      case ST_ATTACHMENT_DEPTH_STENCIL:
+         format = xstfb->stvis.depth_stencil_format;
+         tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
+         break;
+      default:
+         format = PIPE_FORMAT_NONE;
+         break;
+      }
+
+      if (format != PIPE_FORMAT_NONE) {
+         templ.format = format;
+         templ.tex_usage = tex_usage;
+
+         xstfb->textures[i] =
+            xstfb->screen->texture_create(xstfb->screen, &templ);
+      }
+   }
+}
+
+static boolean 
+xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
+                              const enum st_attachment_type *statts,
+                              unsigned count,
+                              struct pipe_texture **out)
+{
+   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
+   unsigned i;
+
+   /* revalidate textures */
+   if (xstfb->buffer->width != xstfb->texture_width ||
+       xstfb->buffer->height != xstfb->texture_height) {
+      xstfb->texture_width = xstfb->buffer->width;
+      xstfb->texture_height = xstfb->buffer->height;
+
+      xmesa_st_framebuffer_validate_textures(stfbi, statts, count);
+   }
+
+   for (i = 0; i < count; i++) {
+      out[i] = NULL;
+      pipe_texture_reference(&out[i], xstfb->textures[statts[i]]);
+   }
+
+   return TRUE;
+}
+
+static boolean
+xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
+                                 enum st_attachment_type statt)
+{
+   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
+   boolean ret;
+
+   ret = xmesa_st_framebuffer_flush_front(stfbi, statt);
+   if (ret)
+      xmesa_check_buffer_size(xstfb->buffer);
+
+   return ret;
+}
+
+struct st_framebuffer_iface *
+xmesa_create_st_framebuffer(struct pipe_screen *screen, XMesaBuffer b)
+{
+   struct st_framebuffer_iface *stfbi;
+   struct xmesa_st_framebuffer *xstfb;
+
+   stfbi = CALLOC_STRUCT(st_framebuffer_iface);
+   xstfb = CALLOC_STRUCT(xmesa_st_framebuffer);
+   if (!stfbi || !xstfb) {
+      if (stfbi)
+         FREE(stfbi);
+      if (xstfb)
+         FREE(xstfb);
+      return NULL;
+   }
+
+   xstfb->screen = screen;
+   xstfb->buffer = b;
+   xstfb->stvis = b->xm_visual->stvis;
+
+   stfbi->visual = &xstfb->stvis;
+   stfbi->flush_front = xmesa_st_framebuffer_flush_front;
+   stfbi->validate = xmesa_st_framebuffer_validate;
+   stfbi->st_manager_private = (void *) xstfb;
+
+   return stfbi;
+}
+
+void
+xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi)
+{
+   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
+
+   FREE(xstfb);
+   FREE(stfbi);
+}
+
+void
+xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi)
+{
+   struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi);
+   boolean ret;
+
+   ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT);
+   if (ret) {
+      struct pipe_texture **front, **back, *tmp;
+
+      front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT];
+      back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT];
+      /* swap textures only if the front texture has been allocated */
+      if (*front) {
+         tmp = *front;
+         *front = *back;
+         *back = tmp;
+      }
+
+      xmesa_check_buffer_size(xstfb->buffer);
+   }
+}
+
+void
+xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi,
+                          enum st_attachment_type src,
+                          enum st_attachment_type dst,
+                          int x, int y, int w, int h)
+{
+   /* TODO */
+}
+
+struct st_api *
+xmesa_create_st_api(void)
+{
+   return XMESA_ST_MODULE.create_api();
+}
diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.h b/src/gallium/state_trackers/glx/xlib/xm_st.h
new file mode 100644 (file)
index 0000000..7ca7afe
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * 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 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
+ * BRIAN PAUL 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:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef _XM_ST_H_
+#define _XM_ST_H_
+
+#include "pipe/p_compiler.h"
+#include "state_tracker/st_api.h"
+
+#include "xm_api.h"
+
+struct st_api *
+xmesa_create_st_api(void);
+
+struct st_framebuffer_iface *
+xmesa_create_st_framebuffer(struct pipe_screen *screen, XMesaBuffer b);
+
+void
+xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi);
+
+void
+xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi);
+
+void
+xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi,
+                          enum st_attachment_type src,
+                          enum st_attachment_type dst,
+                          int x, int y, int w, int h);
+
+#endif /* _XM_ST_H_ */