st/glx: Set the drawable attribute on xmesa_buffer creation.
[mesa.git] / src / gallium / state_trackers / glx / xlib / xm_api.c
index 217bdeff75e8deb87736b7d89a7b68eba0277f5d..faaa5a7501057a031ae391b5710a4325ecce4a65 100644 (file)
  * corner of the window.  Therefore, most drawing functions in this
  * file have to flip Y coordinates.
  *
- * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
- * in support for the MIT Shared Memory extension.  If enabled, when you
- * use an Ximage for the back buffer in double buffered mode, the "swap"
- * operation will be faster.  You must also link with -lXext.
  *
  * Byte swapping:  If the Mesa host and the X display use a different
  * byte order then there's some trickiness to be aware of when using
 #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 "pipe/p_defines.h"
 #include "pipe/p_screen.h"
 #include "pipe/p_context.h"
+#include "util/u_atomic.h"
 
-#include "trace/tr_screen.h"
-#include "trace/tr_context.h"
-#include "trace/tr_texture.h"
-
-#include "xm_winsys.h"
+#include "xm_public.h"
 #include <GL/glx.h>
 
 
  * global.
  */
 static struct xm_driver driver;
+static struct st_api *stapi;
+
+/* Default strict invalidate to false.  This means we will not call
+ * XGetGeometry after every swapbuffers, which allows swapbuffers to
+ * remain asynchronous.  For apps running at 100fps with synchronous
+ * swapping, a 10% boost is typical.  For gears, I see closer to 20%
+ * speedup.
+ *
+ * Note that the work of copying data on swapbuffers doesn't disappear
+ * - this change just allows the X server to execute the PutImage
+ * asynchronously without us effectively blocked until its completion.
+ *
+ * This speeds up even llvmpipe's threaded rasterization as the
+ * swapbuffers operation was a large part of the serial component of
+ * an llvmpipe frame.
+ *
+ * The downside of this is correctness - applications which don't call
+ * glViewport on window resizes will get incorrect rendering.  A
+ * better solution would be to have per-frame but asynchronous
+ * invalidation.  Xcb almost looks as if it could provide this, but
+ * the API doesn't seem to quite be there.
+ */
+boolean xmesa_strict_invalidate = FALSE;
 
 void xmesa_set_driver( const struct xm_driver *templ )
 {
    driver = *templ;
+   stapi = driver.create_st_api();
+
+   xmesa_strict_invalidate =
+      debug_get_bool_option("XMESA_STRICT_INVALIDATE", FALSE);
 }
 
-/**
- * Global X driver lock
+
+/*
+ * XXX replace this with a linked list, or better yet, try to attach the
+ * gallium/mesa extra bits to the X Display object with XAddExtension().
  */
-pipe_mutex _xmesa_lock;
+#define MAX_DISPLAYS 10
+static struct xmesa_display Displays[MAX_DISPLAYS];
+static int NumDisplays = 0;
+
+static int
+xmesa_get_param(struct st_manager *smapi,
+                enum st_manager_param param)
+{
+   switch(param) {
+   case ST_MANAGER_BROKEN_INVALIDATE:
+      return !xmesa_strict_invalidate;
+   default:
+      return 0;
+   }
+}
+
+static XMesaDisplay
+xmesa_init_display( Display *display )
+{
+   pipe_static_mutex(init_mutex);
+   XMesaDisplay xmdpy;
+   int i;
+
+   pipe_mutex_lock(init_mutex);
+
+   /* Look for XMesaDisplay which corresponds to 'display' */
+   for (i = 0; i < NumDisplays; i++) {
+      if (Displays[i].display == display) {
+         /* Found it */
+         pipe_mutex_unlock(init_mutex);
+         return &Displays[i];
+      }
+   }
+
+   /* Create new XMesaDisplay */
+
+   assert(NumDisplays < MAX_DISPLAYS);
+   xmdpy = &Displays[NumDisplays];
+   NumDisplays++;
+
+   if (!xmdpy->display && display) {
+      xmdpy->display = display;
+      xmdpy->screen = driver.create_pipe_screen(display);
+      xmdpy->smapi = CALLOC_STRUCT(st_manager);
+      if (xmdpy->smapi) {
+         xmdpy->smapi->screen = xmdpy->screen;
+         xmdpy->smapi->get_param = xmesa_get_param;
+      }
 
-static struct pipe_screen *_screen = NULL;
-static struct pipe_screen *screen = NULL;
+      if (xmdpy->screen && xmdpy->smapi) {
+         pipe_mutex_init(xmdpy->mutex);
+      }
+      else {
+         if (xmdpy->screen) {
+            xmdpy->screen->destroy(xmdpy->screen);
+            xmdpy->screen = NULL;
+         }
+         if (xmdpy->smapi) {
+            FREE(xmdpy->smapi);
+            xmdpy->smapi = NULL;
+         }
 
+         xmdpy->display = NULL;
+      }
+   }
+   if (!xmdpy->display || xmdpy->display != display)
+      xmdpy = NULL;
+
+   pipe_mutex_unlock(init_mutex);
+
+   return xmdpy;
+}
 
 /**********************************************************************/
 /*****                     X Utility Functions                    *****/
@@ -111,41 +197,6 @@ static int host_byte_order( void )
 }
 
 
-/**
- * Check if the X Shared Memory extension is available.
- * Return:  0 = not available
- *          1 = shared XImage support available
- *          2 = shared Pixmap support available also
- */
-int xmesa_check_for_xshm( Display *display )
-{
-#if defined(USE_XSHM)
-   int major, minor, ignore;
-   Bool pixmaps;
-
-   if (getenv("SP_NO_RAST")) 
-      return 0;
-
-   if (getenv("MESA_NOSHM")) {
-      return 0;
-   }
-
-   if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
-      if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
-        return (pixmaps==True) ? 2 : 1;
-      }
-      else {
-        return 0;
-      }
-   }
-   else {
-      return 0;
-   }
-#else
-   /* No  XSHM support */
-   return 0;
-#endif
-}
 
 
 /**
@@ -238,12 +289,12 @@ void
 xmesa_get_window_size(Display *dpy, XMesaBuffer b,
                       GLuint *width, GLuint *height)
 {
+   XMesaDisplay xmdpy = xmesa_init_display(dpy);
    Status stat;
 
-   pipe_mutex_lock(_xmesa_lock);
-   XSync(b->xm_visual->display, 0); /* added for Chromium */
-   stat = get_drawable_size(dpy, b->drawable, width, height);
-   pipe_mutex_unlock(_xmesa_lock);
+   pipe_mutex_lock(xmdpy->mutex);
+   stat = get_drawable_size(dpy, b->ws.drawable, width, height);
+   pipe_mutex_unlock(xmdpy->mutex);
 
    if (!stat) {
       /* probably querying a window that's recently been destroyed */
@@ -313,53 +364,51 @@ choose_pixel_format(XMesaVisual v)
       return PIPE_FORMAT_B5G6R5_UNORM;
    }
 
-   assert(0);
-   return 0;
+   return PIPE_FORMAT_NONE;
 }
 
 
-
 /**
- * Query the default gallium screen for a Z/Stencil format that
- * at least matches the given depthBits and stencilBits.
+ * Choose a depth/stencil format that satisfies 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(XMesaDisplay xmdpy, 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;
+   const unsigned tex_usage = PIPE_BIND_DEPTH_STENCIL;
+   const unsigned sample_count = 0;
+   enum pipe_format formats[8], fmt;
+   int count, i;
 
-   assert(screen);
+   count = 0;
 
-   *depthFormat = *stencilFormat = PIPE_FORMAT_NONE;
+   if (depth <= 16 && stencil == 0) {
+      formats[count++] = PIPE_FORMAT_Z16_UNORM;
+   }
+   if (depth <= 24 && stencil == 0) {
+      formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
+      formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
+   }
+   if (depth <= 24 && stencil <= 8) {
+      formats[count++] = PIPE_FORMAT_S8_USCALED_Z24_UNORM;
+      formats[count++] = PIPE_FORMAT_Z24_UNORM_S8_USCALED;
+   }
+   if (depth <= 32 && stencil == 0) {
+      formats[count++] = PIPE_FORMAT_Z32_UNORM;
+   }
 
-   /* search for supported format */
-   for (i = 0; i < Elements(formats); i++) {
-      if (screen->is_format_supported(screen, formats[i],
-                                      target, tex_usage, geom_flags)) {
-         *depthFormat = formats[i];
+   fmt = PIPE_FORMAT_NONE;
+   for (i = 0; i < count; i++) {
+      if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i],
+                                             target, sample_count,
+                                             tex_usage)) {
+         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;
 }
 
 
@@ -368,12 +417,12 @@ xmesa_choose_z_stencil_format(int depthBits, int stencilBits,
 /*****                Linked list of XMesaBuffers                 *****/
 /**********************************************************************/
 
-XMesaBuffer XMesaBufferList = NULL;
+static XMesaBuffer XMesaBufferList = NULL;
 
 
 /**
  * Allocate a new XMesaBuffer object which corresponds to the given drawable.
- * Note that XMesaBuffer is derived from GLframebuffer.
+ * Note that XMesaBuffer is derived from struct gl_framebuffer.
  * The new XMesaBuffer will not have any size (Width=Height=0).
  *
  * \param d  the corresponding X drawable (window or pixmap)
@@ -386,53 +435,33 @@ static XMesaBuffer
 create_xmesa_buffer(Drawable d, BufferType type,
                     XMesaVisual vis, Colormap cmap)
 {
+   XMesaDisplay xmdpy = xmesa_init_display(vis->display);
    XMesaBuffer b;
-   GLframebuffer *fb;
-   enum pipe_format colorFormat, depthFormat, stencilFormat;
    uint width, height;
 
    ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
 
+   if (!xmdpy)
+      return NULL;
+
    b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
    if (!b)
       return NULL;
 
-   b->drawable = d;
+   b->ws.drawable = b->drawable = d;
+   b->ws.visual = vis->visinfo->visual;
+   b->ws.depth = vis->visinfo->depth;
 
    b->xm_visual = vis;
    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;
-
-   /*
-    * Create scratch XImage for xmesa_display_surface()
-    */
-   b->tempImage = XCreateImage(vis->display,
-                               vis->visinfo->visual,
-                               vis->visinfo->depth,
-                               ZPixmap, 0,   /* format, offset */
-                               NULL,         /* data */
-                               0, 0,         /* size */
-                               32,           /* bitmap_pad */
-                               0);           /* bytes_per_line */
+   b->stfb = xmesa_create_st_framebuffer(xmdpy, b);
 
    /* GLX_EXT_texture_from_pixmap */
    b->TextureTarget = 0;
@@ -476,29 +505,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->drawable = 0;
-
-         buffer->tempImage->data = NULL;
-         XDestroyImage(buffer->tempImage);
+         b->ws.drawable = 0;
 
-         /* Unreference.  If count = zero we'll really delete the buffer */
-         _mesa_reference_framebuffer(&fb, NULL);
-
-         XFreeGC(b->xm_visual->display, b->gc);
+         /* 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);
 
@@ -547,7 +568,7 @@ initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
       /* RGB WINDOW:
        * We support RGB rendering into almost any kind of visual.
        */
-      const int xclass = v->mesa_visual.visualType;
+      const int xclass = v->visualType;
       if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
         _mesa_warning(NULL,
             "XMesa: RGB mode rendering not supported in given visual.\n");
@@ -576,21 +597,6 @@ initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
       printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
    }
 
-   if (b && window) {
-      /* these should have been set in create_xmesa_buffer */
-      ASSERT(b->drawable == window);
-
-      /* Setup for single/double buffering */
-      if (v->mesa_visual.doubleBufferMode) {
-         /* Double buffered */
-         b->shm = xmesa_check_for_xshm( v->display );
-      }
-
-      /* X11 graphics context */
-      b->gc = XCreateGC( v->display, window, 0, NULL );
-      XSetFunction( v->display, b->gc, GXcopy );
-   }
-
    return GL_TRUE;
 }
 
@@ -670,10 +676,12 @@ XMesaVisual XMesaCreateVisual( Display *display,
                                GLint level,
                                GLint visualCaveat )
 {
+   XMesaDisplay xmdpy = xmesa_init_display(display);
    XMesaVisual v;
    GLint red_bits, green_bits, blue_bits, alpha_bits;
 
-   xmesa_init();
+   if (!xmdpy)
+      return NULL;
 
    /* For debugging only */
    if (_mesa_getenv("MESA_XSYNC")) {
@@ -707,13 +715,13 @@ XMesaVisual XMesaCreateVisual( Display *display,
    v->mesa_visual.redMask = visinfo->red_mask;
    v->mesa_visual.greenMask = visinfo->green_mask;
    v->mesa_visual.blueMask = visinfo->blue_mask;
-   v->mesa_visual.visualID = visinfo->visualid;
-   v->mesa_visual.screen = visinfo->screen;
+   v->visualID = visinfo->visualid;
+   v->screen = visinfo->screen;
 
 #if !(defined(__cplusplus) || defined(c_plusplus))
-   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
+   v->visualType = xmesa_convert_from_x_visual_type(visinfo->class);
 #else
-   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
+   v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
 #endif
 
    v->mesa_visual.visualRating = visualCaveat;
@@ -724,7 +732,7 @@ XMesaVisual XMesaCreateVisual( Display *display,
    (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
 
    {
-      const int xclass = v->mesa_visual.visualType;
+      const int xclass = v->visualType;
       if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
          red_bits   = _mesa_bitcount(GET_REDMASK(v));
          green_bits = _mesa_bitcount(GET_GREENMASK(v));
@@ -745,15 +753,64 @@ XMesaVisual XMesaCreateVisual( Display *display,
       alpha_bits = v->mesa_visual.alphaBits;
    }
 
-   _mesa_initialize_visual( &v->mesa_visual,
-                            db_flag, stereo_flag,
-                            red_bits, green_bits,
-                            blue_bits, alpha_bits,
-                            depth_size,
-                            stencil_size,
-                            accum_red_size, accum_green_size,
-                            accum_blue_size, accum_alpha_size,
-                            0 );
+   /* initialize visual */
+   {
+      struct gl_config *vis = &v->mesa_visual;
+
+      vis->rgbMode          = GL_TRUE;
+      vis->doubleBufferMode = db_flag;
+      vis->stereoMode       = stereo_flag;
+
+      vis->redBits          = red_bits;
+      vis->greenBits        = green_bits;
+      vis->blueBits         = blue_bits;
+      vis->alphaBits        = alpha_bits;
+      vis->rgbBits          = red_bits + green_bits + blue_bits;
+
+      vis->indexBits      = 0;
+      vis->depthBits      = depth_size;
+      vis->stencilBits    = stencil_size;
+
+      vis->accumRedBits   = accum_red_size;
+      vis->accumGreenBits = accum_green_size;
+      vis->accumBlueBits  = accum_blue_size;
+      vis->accumAlphaBits = accum_alpha_size;
+
+      vis->haveAccumBuffer   = accum_red_size > 0;
+      vis->haveDepthBuffer   = depth_size > 0;
+      vis->haveStencilBuffer = stencil_size > 0;
+
+      vis->numAuxBuffers = 0;
+      vis->level = 0;
+      vis->sampleBuffers = 0;
+      vis->samples = 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);
+   if (v->stvis.color_format == PIPE_FORMAT_NONE) {
+      FREE(v->visinfo);
+      FREE(v);
+      return NULL;
+   }
+
+   v->stvis.depth_stencil_format =
+      choose_depth_stencil_format(xmdpy, 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;
@@ -770,18 +827,22 @@ void XMesaDestroyVisual( XMesaVisual v )
 
 
 /**
- * Do one-time initializations.
+ * Return the informative name.
+ */
+const char *
+xmesa_get_name(void)
+{
+   return stapi->name;
+}
+
+
+/**
+ * Do per-display initializations.
  */
 void
-xmesa_init(void)
+xmesa_init( Display *display )
 {
-   static GLboolean firstTime = GL_TRUE;
-   if (firstTime) {
-      pipe_mutex_init(_xmesa_lock);
-      _screen = driver.create_pipe_screen();
-      screen = trace_screen_create( _screen );
-      firstTime = GL_FALSE;
-   }
+   xmesa_init_display(display);
 }
 
 
@@ -793,53 +854,54 @@ xmesa_init(void)
  * \return an XMesaContext or NULL if error.
  */
 PUBLIC
-XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
+XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list,
+                                 GLuint major, GLuint minor,
+                                 GLuint profileMask, GLuint contextFlags)
 {
-   struct pipe_context *pipe = NULL;
+   XMesaDisplay xmdpy = xmesa_init_display(v->display);
+   struct st_context_attribs attribs;
    XMesaContext c;
-   GLcontext *mesaCtx;
-   uint pf;
 
-   xmesa_init();
+   if (!xmdpy)
+      return NULL;
 
-   /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
+   /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */
    c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
    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;
 
-   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);
+   memset(&attribs, 0, sizeof(attribs));
+   attribs.profile = ST_PROFILE_DEFAULT;
+   attribs.visual = v->stvis;
+   attribs.major = major;
+   attribs.minor = minor;
+   if (contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
+      attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
+   if (contextFlags & GLX_CONTEXT_DEBUG_BIT_ARB)
+      attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
+   if (contextFlags & GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
+      attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS;
+   if (profileMask & GLX_CONTEXT_CORE_PROFILE_BIT_ARB)
+      attribs.flags |= ST_CONTEXT_FLAG_CORE_PROFILE;
+   if (profileMask & GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
+      attribs.flags |= ST_CONTEXT_FLAG_COMPATIBLE_PROFILE;
+
+   c->st = stapi->create_context(stapi, xmdpy->smapi,
+         &attribs, (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;
@@ -850,7 +912,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
@@ -956,7 +1018,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
 {
    GET_CURRENT_CONTEXT(ctx);
    XMesaBuffer b;
-   GLuint width, height;
 
    assert(v);
 
@@ -964,19 +1025,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 {
@@ -1049,23 +1109,34 @@ 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.
+ * Notify the binding context to validate the buffer.
  */
 void
-xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
+xmesa_notify_invalid_buffer(XMesaBuffer b)
 {
-   GLuint width, height;
-   xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
-   st_resize_framebuffer(drawBuffer->stfb, width, height);
+   p_atomic_inc(&b->stfb->stamp);
 }
 
 
+/**
+ * Query the current drawable size and notify the binding context.
+ */
+void
+xmesa_check_buffer_size(XMesaBuffer b)
+{
+   GLuint old_width, old_height;
+
+   if (b->type == PBUFFER)
+      return;
+
+   old_width = b->width;
+   old_height = b->height;
+
+   xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height);
+
+   if (b->width != old_width || b->height != old_height)
+      xmesa_notify_invalid_buffer(b);
+}
 
 
 /*
@@ -1092,21 +1163,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);
-
-      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 );
+      stapi->make_current(stapi, NULL, NULL, NULL);
 
    }
    return GL_TRUE;
@@ -1125,14 +1196,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;
 }
 
 
@@ -1144,21 +1209,13 @@ XMesaContext XMesaGetCurrentContext( void )
 PUBLIC
 void XMesaSwapBuffers( XMesaBuffer b )
 {
-   struct pipe_surface *frontLeftSurf;
-
-   st_swapbuffers(b->stfb, &frontLeftSurf, NULL);
+   XMesaContext xmctx = XMesaGetCurrentContext();
 
-   if (frontLeftSurf) {
-      if (_screen != screen) {
-         struct trace_surface *tr_surf = trace_surface( frontLeftSurf );
-         struct pipe_surface *surf = tr_surf->surface;
-         frontLeftSurf = surf;
-      }
-
-      driver.display_surface(b, frontLeftSurf);
+   if (xmctx && xmctx->xm_buffer == b) {
+      xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL);
    }
 
-   xmesa_check_and_update_buffer_size(NULL, b);
+   xmesa_swap_st_framebuffer(b->stfb);
 }
 
 
@@ -1168,21 +1225,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);
 }
 
 
@@ -1190,8 +1235,16 @@ 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);
-      XSync( c->xm_visual->display, False );
+      XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display);
+      struct pipe_fence_handle *fence = NULL;
+
+      c->st->flush(c->st, ST_FLUSH_FRONT, &fence);
+      if (fence) {
+         xmdpy->screen->fence_finish(xmdpy->screen, fence,
+                                     PIPE_TIMEOUT_INFINITE);
+         xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL);
+      }
+      XFlush( c->xm_visual->display );
    }
 }
 
@@ -1203,7 +1256,7 @@ XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d )
 {
    XMesaBuffer b;
    for (b = XMesaBufferList; b; b = b->Next) {
-      if (b->drawable == d && b->xm_visual->display == dpy) {
+      if (b->ws.drawable == d && b->xm_visual->display == dpy) {
          return b;
       }
    }
@@ -1221,6 +1274,10 @@ void xmesa_destroy_buffers_on_display(Display *dpy)
       next = b->Next;
       if (b->xm_visual->display == dpy) {
          xmesa_free_buffer(b);
+         /* delete head of list? */
+         if (XMesaBufferList == b) {
+            XMesaBufferList = next;
+         }
       }
    }
 }
@@ -1237,10 +1294,10 @@ void XMesaGarbageCollect( void )
       next = b->Next;
       if (b->xm_visual &&
           b->xm_visual->display &&
-          b->drawable &&
+          b->ws.drawable &&
           b->type == WINDOW) {
          XSync(b->xm_visual->display, False);
-         if (!window_exists( b->xm_visual->display, b->drawable )) {
+         if (!window_exists( b->xm_visual->display, b->ws.drawable )) {
             /* found a dead window, free the ancillary info */
             XMesaDestroyBuffer( b );
          }
@@ -1264,3 +1321,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);
+}