Home | History | Annotate | Download | only in xlib
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 /**
     26  * \file xm_api.c
     27  *
     28  * All the XMesa* API functions.
     29  *
     30  *
     31  * NOTES:
     32  *
     33  * The window coordinate system origin (0,0) is in the lower-left corner
     34  * of the window.  X11's window coordinate origin is in the upper-left
     35  * corner of the window.  Therefore, most drawing functions in this
     36  * file have to flip Y coordinates.
     37  *
     38  *
     39  * Byte swapping:  If the Mesa host and the X display use a different
     40  * byte order then there's some trickiness to be aware of when using
     41  * XImages.  The byte ordering used for the XImage is that of the X
     42  * display, not the Mesa host.
     43  * The color-to-pixel encoding for True/DirectColor must be done
     44  * according to the display's visual red_mask, green_mask, and blue_mask.
     45  * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
     46  * do byte swapping if needed.  If one wants to directly "poke" the pixel
     47  * into the XImage's buffer then the pixel must be byte swapped first.
     48  *
     49  */
     50 
     51 #ifdef __CYGWIN__
     52 #undef WIN32
     53 #undef __WIN32__
     54 #endif
     55 
     56 #include <stdio.h>
     57 #include "xm_api.h"
     58 #include "xm_st.h"
     59 
     60 #include "pipe/p_context.h"
     61 #include "pipe/p_defines.h"
     62 #include "pipe/p_screen.h"
     63 #include "pipe/p_state.h"
     64 
     65 #include "util/u_atomic.h"
     66 #include "util/u_inlines.h"
     67 
     68 #include "hud/hud_context.h"
     69 
     70 #include "xm_public.h"
     71 #include <GL/glx.h>
     72 
     73 
     74 /* Driver interface routines, set up by xlib backend on library
     75  * _init().  These are global in the same way that function names are
     76  * global.
     77  */
     78 static struct xm_driver driver;
     79 static struct st_api *stapi;
     80 
     81 /* Default strict invalidate to false.  This means we will not call
     82  * XGetGeometry after every swapbuffers, which allows swapbuffers to
     83  * remain asynchronous.  For apps running at 100fps with synchronous
     84  * swapping, a 10% boost is typical.  For gears, I see closer to 20%
     85  * speedup.
     86  *
     87  * Note that the work of copying data on swapbuffers doesn't disappear
     88  * - this change just allows the X server to execute the PutImage
     89  * asynchronously without us effectively blocked until its completion.
     90  *
     91  * This speeds up even llvmpipe's threaded rasterization as the
     92  * swapbuffers operation was a large part of the serial component of
     93  * an llvmpipe frame.
     94  *
     95  * The downside of this is correctness - applications which don't call
     96  * glViewport on window resizes will get incorrect rendering.  A
     97  * better solution would be to have per-frame but asynchronous
     98  * invalidation.  Xcb almost looks as if it could provide this, but
     99  * the API doesn't seem to quite be there.
    100  */
    101 boolean xmesa_strict_invalidate = FALSE;
    102 
    103 void xmesa_set_driver( const struct xm_driver *templ )
    104 {
    105    driver = *templ;
    106    stapi = driver.create_st_api();
    107 
    108    xmesa_strict_invalidate =
    109       debug_get_bool_option("XMESA_STRICT_INVALIDATE", FALSE);
    110 }
    111 
    112 
    113 static int
    114 xmesa_get_param(struct st_manager *smapi,
    115                 enum st_manager_param param)
    116 {
    117    switch(param) {
    118    case ST_MANAGER_BROKEN_INVALIDATE:
    119       return !xmesa_strict_invalidate;
    120    default:
    121       return 0;
    122    }
    123 }
    124 
    125 /* linked list of XMesaDisplay hooks per display */
    126 typedef struct _XMesaExtDisplayInfo {
    127    struct _XMesaExtDisplayInfo *next;
    128    Display *display;
    129    struct xmesa_display mesaDisplay;
    130 } XMesaExtDisplayInfo;
    131 
    132 typedef struct _XMesaExtInfo {
    133    XMesaExtDisplayInfo *head;
    134    int ndisplays;
    135 } XMesaExtInfo;
    136 
    137 static XMesaExtInfo MesaExtInfo;
    138 
    139 /* hook to delete XMesaDisplay on XDestroyDisplay */
    140 extern void
    141 xmesa_close_display(Display *display)
    142 {
    143    XMesaExtDisplayInfo *info, *prev;
    144 
    145    assert(MesaExtInfo.ndisplays > 0);
    146    assert(MesaExtInfo.head);
    147 
    148    _XLockMutex(_Xglobal_lock);
    149    /* first find display */
    150    prev = NULL;
    151    for (info = MesaExtInfo.head; info; info = info->next) {
    152       if (info->display == display) {
    153          prev = info;
    154          break;
    155       }
    156    }
    157 
    158    if (info == NULL) {
    159       /* no display found */
    160       _XUnlockMutex(_Xglobal_lock);
    161       return;
    162    }
    163 
    164    /* remove display entry from list */
    165    if (prev != MesaExtInfo.head) {
    166       prev->next = info->next;
    167    } else {
    168       MesaExtInfo.head = info->next;
    169    }
    170    MesaExtInfo.ndisplays--;
    171 
    172    _XUnlockMutex(_Xglobal_lock);
    173 
    174    /* don't forget to clean up mesaDisplay */
    175    XMesaDisplay xmdpy = &info->mesaDisplay;
    176 
    177    /**
    178     * XXX: Don't destroy the screens here, since there may still
    179     * be some dangling screen pointers that are used after this point
    180     * if (xmdpy->screen) {
    181     *    xmdpy->screen->destroy(xmdpy->screen);
    182     * }
    183     */
    184    free(xmdpy->smapi);
    185 
    186    XFree((char *) info);
    187 }
    188 
    189 static XMesaDisplay
    190 xmesa_init_display( Display *display )
    191 {
    192    pipe_static_mutex(init_mutex);
    193    XMesaDisplay xmdpy;
    194    XMesaExtDisplayInfo *info;
    195 
    196    if (display == NULL) {
    197       return NULL;
    198    }
    199 
    200    pipe_mutex_lock(init_mutex);
    201 
    202    /* Look for XMesaDisplay which corresponds to this display */
    203    info = MesaExtInfo.head;
    204    while(info) {
    205       if (info->display == display) {
    206          /* Found it */
    207          pipe_mutex_unlock(init_mutex);
    208          return  &info->mesaDisplay;
    209       }
    210       info = info->next;
    211    }
    212 
    213    /* Not found.  Create new XMesaDisplay */
    214    /* first allocate X-related resources and hook destroy callback */
    215 
    216    /* allocate mesa display info */
    217    info = (XMesaExtDisplayInfo *) Xmalloc(sizeof(XMesaExtDisplayInfo));
    218    if (info == NULL) {
    219       pipe_mutex_unlock(init_mutex);
    220       return NULL;
    221    }
    222    info->display = display;
    223    xmdpy = &info->mesaDisplay; /* to be filled out below */
    224 
    225    /* chain to the list of displays */
    226    _XLockMutex(_Xglobal_lock);
    227    info->next = MesaExtInfo.head;
    228    MesaExtInfo.head = info;
    229    MesaExtInfo.ndisplays++;
    230    _XUnlockMutex(_Xglobal_lock);
    231 
    232    /* now create the new XMesaDisplay info */
    233    assert(display);
    234 
    235    xmdpy->display = display;
    236    xmdpy->screen = driver.create_pipe_screen(display);
    237    xmdpy->smapi = CALLOC_STRUCT(st_manager);
    238    xmdpy->pipe = NULL;
    239    if (xmdpy->smapi) {
    240       xmdpy->smapi->screen = xmdpy->screen;
    241       xmdpy->smapi->get_param = xmesa_get_param;
    242    }
    243 
    244    if (xmdpy->screen && xmdpy->smapi) {
    245       pipe_mutex_init(xmdpy->mutex);
    246    }
    247    else {
    248       if (xmdpy->screen) {
    249          xmdpy->screen->destroy(xmdpy->screen);
    250          xmdpy->screen = NULL;
    251       }
    252       free(xmdpy->smapi);
    253       xmdpy->smapi = NULL;
    254 
    255       xmdpy->display = NULL;
    256    }
    257 
    258    pipe_mutex_unlock(init_mutex);
    259 
    260    return xmdpy;
    261 }
    262 
    263 
    264 /**********************************************************************/
    265 /*****                     X Utility Functions                    *****/
    266 /**********************************************************************/
    267 
    268 
    269 /**
    270  * Return the host's byte order as LSBFirst or MSBFirst ala X.
    271  */
    272 static int host_byte_order( void )
    273 {
    274    int i = 1;
    275    char *cptr = (char *) &i;
    276    return (*cptr==1) ? LSBFirst : MSBFirst;
    277 }
    278 
    279 
    280 
    281 
    282 /**
    283  * Return the true number of bits per pixel for XImages.
    284  * For example, if we request a 24-bit deep visual we may actually need/get
    285  * 32bpp XImages.  This function returns the appropriate bpp.
    286  * Input:  dpy - the X display
    287  *         visinfo - desribes the visual to be used for XImages
    288  * Return:  true number of bits per pixel for XImages
    289  */
    290 static int
    291 bits_per_pixel( XMesaVisual xmv )
    292 {
    293    Display *dpy = xmv->display;
    294    XVisualInfo * visinfo = xmv->visinfo;
    295    XImage *img;
    296    int bitsPerPixel;
    297    /* Create a temporary XImage */
    298    img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
    299 		       ZPixmap, 0,           /*format, offset*/
    300 		       malloc(8),    /*data*/
    301 		       1, 1,                 /*width, height*/
    302 		       32,                   /*bitmap_pad*/
    303 		       0                     /*bytes_per_line*/
    304                      );
    305    assert(img);
    306    /* grab the bits/pixel value */
    307    bitsPerPixel = img->bits_per_pixel;
    308    /* free the XImage */
    309    free( img->data );
    310    img->data = NULL;
    311    XDestroyImage( img );
    312    return bitsPerPixel;
    313 }
    314 
    315 
    316 
    317 /*
    318  * Determine if a given X window ID is valid (window exists).
    319  * Do this by calling XGetWindowAttributes() for the window and
    320  * checking if we catch an X error.
    321  * Input:  dpy - the display
    322  *         win - the window to check for existence
    323  * Return:  GL_TRUE - window exists
    324  *          GL_FALSE - window doesn't exist
    325  */
    326 static GLboolean WindowExistsFlag;
    327 
    328 static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr )
    329 {
    330    (void) dpy;
    331    if (xerr->error_code == BadWindow) {
    332       WindowExistsFlag = GL_FALSE;
    333    }
    334    return 0;
    335 }
    336 
    337 static GLboolean window_exists( Display *dpy, Window win )
    338 {
    339    XWindowAttributes wa;
    340    int (*old_handler)( Display*, XErrorEvent* );
    341    WindowExistsFlag = GL_TRUE;
    342    old_handler = XSetErrorHandler(window_exists_err_handler);
    343    XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
    344    XSetErrorHandler(old_handler);
    345    return WindowExistsFlag;
    346 }
    347 
    348 static Status
    349 get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height )
    350 {
    351    Window root;
    352    Status stat;
    353    int xpos, ypos;
    354    unsigned int w, h, bw, depth;
    355    stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
    356    *width = w;
    357    *height = h;
    358    return stat;
    359 }
    360 
    361 
    362 /**
    363  * Return the size of the window (or pixmap) that corresponds to the
    364  * given XMesaBuffer.
    365  * \param width  returns width in pixels
    366  * \param height  returns height in pixels
    367  */
    368 void
    369 xmesa_get_window_size(Display *dpy, XMesaBuffer b,
    370                       GLuint *width, GLuint *height)
    371 {
    372    XMesaDisplay xmdpy = xmesa_init_display(dpy);
    373    Status stat;
    374 
    375    pipe_mutex_lock(xmdpy->mutex);
    376    stat = get_drawable_size(dpy, b->ws.drawable, width, height);
    377    pipe_mutex_unlock(xmdpy->mutex);
    378 
    379    if (!stat) {
    380       /* probably querying a window that's recently been destroyed */
    381       _mesa_warning(NULL, "XGetGeometry failed!\n");
    382       *width = *height = 1;
    383    }
    384 }
    385 
    386 #define GET_REDMASK(__v)        __v->mesa_visual.redMask
    387 #define GET_GREENMASK(__v)      __v->mesa_visual.greenMask
    388 #define GET_BLUEMASK(__v)       __v->mesa_visual.blueMask
    389 
    390 
    391 /**
    392  * Choose the pixel format for the given visual.
    393  * This will tell the gallium driver how to pack pixel data into
    394  * drawing surfaces.
    395  */
    396 static GLuint
    397 choose_pixel_format(XMesaVisual v)
    398 {
    399    boolean native_byte_order = (host_byte_order() ==
    400                                 ImageByteOrder(v->display));
    401 
    402    if (   GET_REDMASK(v)   == 0x0000ff
    403        && GET_GREENMASK(v) == 0x00ff00
    404        && GET_BLUEMASK(v)  == 0xff0000
    405        && v->BitsPerPixel == 32) {
    406       if (native_byte_order) {
    407          /* no byteswapping needed */
    408          return PIPE_FORMAT_RGBA8888_UNORM;
    409       }
    410       else {
    411          return PIPE_FORMAT_ABGR8888_UNORM;
    412       }
    413    }
    414    else if (   GET_REDMASK(v)   == 0xff0000
    415             && GET_GREENMASK(v) == 0x00ff00
    416             && GET_BLUEMASK(v)  == 0x0000ff
    417             && v->BitsPerPixel == 32) {
    418       if (native_byte_order) {
    419          /* no byteswapping needed */
    420          return PIPE_FORMAT_BGRA8888_UNORM;
    421       }
    422       else {
    423          return PIPE_FORMAT_ARGB8888_UNORM;
    424       }
    425    }
    426    else if (   GET_REDMASK(v)   == 0x0000ff00
    427             && GET_GREENMASK(v) == 0x00ff0000
    428             && GET_BLUEMASK(v)  == 0xff000000
    429             && v->BitsPerPixel == 32) {
    430       if (native_byte_order) {
    431          /* no byteswapping needed */
    432          return PIPE_FORMAT_ARGB8888_UNORM;
    433       }
    434       else {
    435          return PIPE_FORMAT_BGRA8888_UNORM;
    436       }
    437    }
    438    else if (   GET_REDMASK(v)   == 0xf800
    439             && GET_GREENMASK(v) == 0x07e0
    440             && GET_BLUEMASK(v)  == 0x001f
    441             && native_byte_order
    442             && v->BitsPerPixel == 16) {
    443       /* 5-6-5 RGB */
    444       return PIPE_FORMAT_B5G6R5_UNORM;
    445    }
    446 
    447    return PIPE_FORMAT_NONE;
    448 }
    449 
    450 
    451 /**
    452  * Choose a depth/stencil format that satisfies the given depth and
    453  * stencil sizes.
    454  */
    455 static enum pipe_format
    456 choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil)
    457 {
    458    const enum pipe_texture_target target = PIPE_TEXTURE_2D;
    459    const unsigned tex_usage = PIPE_BIND_DEPTH_STENCIL;
    460    const unsigned sample_count = 0;
    461    enum pipe_format formats[8], fmt;
    462    int count, i;
    463 
    464    count = 0;
    465 
    466    if (depth <= 16 && stencil == 0) {
    467       formats[count++] = PIPE_FORMAT_Z16_UNORM;
    468    }
    469    if (depth <= 24 && stencil == 0) {
    470       formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
    471       formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
    472    }
    473    if (depth <= 24 && stencil <= 8) {
    474       formats[count++] = PIPE_FORMAT_S8_UINT_Z24_UNORM;
    475       formats[count++] = PIPE_FORMAT_Z24_UNORM_S8_UINT;
    476    }
    477    if (depth <= 32 && stencil == 0) {
    478       formats[count++] = PIPE_FORMAT_Z32_UNORM;
    479    }
    480 
    481    fmt = PIPE_FORMAT_NONE;
    482    for (i = 0; i < count; i++) {
    483       if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i],
    484                                              target, sample_count,
    485                                              tex_usage)) {
    486          fmt = formats[i];
    487          break;
    488       }
    489    }
    490 
    491    return fmt;
    492 }
    493 
    494 
    495 
    496 /**********************************************************************/
    497 /*****                Linked list of XMesaBuffers                 *****/
    498 /**********************************************************************/
    499 
    500 static XMesaBuffer XMesaBufferList = NULL;
    501 
    502 
    503 /**
    504  * Allocate a new XMesaBuffer object which corresponds to the given drawable.
    505  * Note that XMesaBuffer is derived from struct gl_framebuffer.
    506  * The new XMesaBuffer will not have any size (Width=Height=0).
    507  *
    508  * \param d  the corresponding X drawable (window or pixmap)
    509  * \param type  either WINDOW, PIXMAP or PBUFFER, describing d
    510  * \param vis  the buffer's visual
    511  * \param cmap  the window's colormap, if known.
    512  * \return new XMesaBuffer or NULL if any problem
    513  */
    514 static XMesaBuffer
    515 create_xmesa_buffer(Drawable d, BufferType type,
    516                     XMesaVisual vis, Colormap cmap)
    517 {
    518    XMesaDisplay xmdpy = xmesa_init_display(vis->display);
    519    XMesaBuffer b;
    520 
    521    assert(type == WINDOW || type == PIXMAP || type == PBUFFER);
    522 
    523    if (!xmdpy)
    524       return NULL;
    525 
    526    b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
    527    if (!b)
    528       return NULL;
    529 
    530    b->ws.drawable = d;
    531    b->ws.visual = vis->visinfo->visual;
    532    b->ws.depth = vis->visinfo->depth;
    533 
    534    b->xm_visual = vis;
    535    b->type = type;
    536    b->cmap = cmap;
    537 
    538    get_drawable_size(vis->display, d, &b->width, &b->height);
    539 
    540    /*
    541     * Create framebuffer, but we'll plug in our own renderbuffers below.
    542     */
    543    b->stfb = xmesa_create_st_framebuffer(xmdpy, b);
    544 
    545    /* GLX_EXT_texture_from_pixmap */
    546    b->TextureTarget = 0;
    547    b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
    548    b->TextureMipmap = 0;
    549 
    550    /* insert buffer into linked list */
    551    b->Next = XMesaBufferList;
    552    XMesaBufferList = b;
    553 
    554    return b;
    555 }
    556 
    557 
    558 /**
    559  * Find an XMesaBuffer by matching X display and colormap but NOT matching
    560  * the notThis buffer.
    561  */
    562 XMesaBuffer
    563 xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis)
    564 {
    565    XMesaBuffer b;
    566    for (b = XMesaBufferList; b; b = b->Next) {
    567       if (b->xm_visual->display == dpy &&
    568           b->cmap == cmap &&
    569           b != notThis) {
    570          return b;
    571       }
    572    }
    573    return NULL;
    574 }
    575 
    576 
    577 /**
    578  * Remove buffer from linked list, delete if no longer referenced.
    579  */
    580 static void
    581 xmesa_free_buffer(XMesaBuffer buffer)
    582 {
    583    XMesaBuffer prev = NULL, b;
    584 
    585    for (b = XMesaBufferList; b; b = b->Next) {
    586       if (b == buffer) {
    587          /* unlink buffer from list */
    588          if (prev)
    589             prev->Next = buffer->Next;
    590          else
    591             XMesaBufferList = buffer->Next;
    592 
    593          /* Since the X window for the XMesaBuffer is going away, we don't
    594           * want to dereference this pointer in the future.
    595           */
    596          b->ws.drawable = 0;
    597 
    598          /* XXX we should move the buffer to a delete-pending list and destroy
    599           * the buffer until it is no longer current.
    600           */
    601          xmesa_destroy_st_framebuffer(buffer->stfb);
    602 
    603          free(buffer);
    604 
    605          return;
    606       }
    607       /* continue search */
    608       prev = b;
    609    }
    610    /* buffer not found in XMesaBufferList */
    611    _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
    612 }
    613 
    614 
    615 
    616 /**********************************************************************/
    617 /*****                   Misc Private Functions                   *****/
    618 /**********************************************************************/
    619 
    620 
    621 /**
    622  * When a context is bound for the first time, we can finally finish
    623  * initializing the context's visual and buffer information.
    624  * \param v  the XMesaVisual to initialize
    625  * \param b  the XMesaBuffer to initialize (may be NULL)
    626  * \param rgb_flag  TRUE = RGBA mode, FALSE = color index mode
    627  * \param window  the window/pixmap we're rendering into
    628  * \param cmap  the colormap associated with the window/pixmap
    629  * \return GL_TRUE=success, GL_FALSE=failure
    630  */
    631 static GLboolean
    632 initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
    633                              GLboolean rgb_flag, Drawable window,
    634                              Colormap cmap)
    635 {
    636    assert(!b || b->xm_visual == v);
    637 
    638    /* Save true bits/pixel */
    639    v->BitsPerPixel = bits_per_pixel(v);
    640    assert(v->BitsPerPixel > 0);
    641 
    642    if (rgb_flag == GL_FALSE) {
    643       /* COLOR-INDEXED WINDOW: not supported*/
    644       return GL_FALSE;
    645    }
    646    else {
    647       /* RGB WINDOW:
    648        * We support RGB rendering into almost any kind of visual.
    649        */
    650       const int xclass = v->visualType;
    651       if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
    652 	 _mesa_warning(NULL,
    653             "XMesa: RGB mode rendering not supported in given visual.\n");
    654 	 return GL_FALSE;
    655       }
    656       v->mesa_visual.indexBits = 0;
    657 
    658       if (v->BitsPerPixel == 32) {
    659          /* We use XImages for all front/back buffers.  If an X Window or
    660           * X Pixmap is 32bpp, there's no guarantee that the alpha channel
    661           * will be preserved.  For XImages we're in luck.
    662           */
    663          v->mesa_visual.alphaBits = 8;
    664       }
    665    }
    666 
    667    /*
    668     * If MESA_INFO env var is set print out some debugging info
    669     * which can help Brian figure out what's going on when a user
    670     * reports bugs.
    671     */
    672    if (getenv("MESA_INFO")) {
    673       printf("X/Mesa visual = %p\n", (void *) v);
    674       printf("X/Mesa level = %d\n", v->mesa_visual.level);
    675       printf("X/Mesa depth = %d\n", v->visinfo->depth);
    676       printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
    677    }
    678 
    679    return GL_TRUE;
    680 }
    681 
    682 
    683 
    684 #define NUM_VISUAL_TYPES   6
    685 
    686 /**
    687  * Convert an X visual type to a GLX visual type.
    688  *
    689  * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
    690  *        to be converted.
    691  * \return If \c visualType is a valid X visual type, a GLX visual type will
    692  *         be returned.  Otherwise \c GLX_NONE will be returned.
    693  *
    694  * \note
    695  * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
    696  * DRI CVS tree.
    697  */
    698 static GLint
    699 xmesa_convert_from_x_visual_type( int visualType )
    700 {
    701     static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
    702 	GLX_STATIC_GRAY,  GLX_GRAY_SCALE,
    703 	GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
    704 	GLX_TRUE_COLOR,   GLX_DIRECT_COLOR
    705     };
    706 
    707     return ( (unsigned) visualType < NUM_VISUAL_TYPES )
    708 	? glx_visual_types[ visualType ] : GLX_NONE;
    709 }
    710 
    711 
    712 /**********************************************************************/
    713 /*****                       Public Functions                     *****/
    714 /**********************************************************************/
    715 
    716 
    717 /*
    718  * Create a new X/Mesa visual.
    719  * Input:  display - X11 display
    720  *         visinfo - an XVisualInfo pointer
    721  *         rgb_flag - GL_TRUE = RGB mode,
    722  *                    GL_FALSE = color index mode
    723  *         alpha_flag - alpha buffer requested?
    724  *         db_flag - GL_TRUE = double-buffered,
    725  *                   GL_FALSE = single buffered
    726  *         stereo_flag - stereo visual?
    727  *         ximage_flag - GL_TRUE = use an XImage for back buffer,
    728  *                       GL_FALSE = use an off-screen pixmap for back buffer
    729  *         depth_size - requested bits/depth values, or zero
    730  *         stencil_size - requested bits/stencil values, or zero
    731  *         accum_red_size - requested bits/red accum values, or zero
    732  *         accum_green_size - requested bits/green accum values, or zero
    733  *         accum_blue_size - requested bits/blue accum values, or zero
    734  *         accum_alpha_size - requested bits/alpha accum values, or zero
    735  *         num_samples - number of samples/pixel if multisampling, or zero
    736  *         level - visual level, usually 0
    737  *         visualCaveat - ala the GLX extension, usually GLX_NONE
    738  * Return;  a new XMesaVisual or 0 if error.
    739  */
    740 PUBLIC
    741 XMesaVisual XMesaCreateVisual( Display *display,
    742                                XVisualInfo * visinfo,
    743                                GLboolean rgb_flag,
    744                                GLboolean alpha_flag,
    745                                GLboolean db_flag,
    746                                GLboolean stereo_flag,
    747                                GLboolean ximage_flag,
    748                                GLint depth_size,
    749                                GLint stencil_size,
    750                                GLint accum_red_size,
    751                                GLint accum_green_size,
    752                                GLint accum_blue_size,
    753                                GLint accum_alpha_size,
    754                                GLint num_samples,
    755                                GLint level,
    756                                GLint visualCaveat )
    757 {
    758    XMesaDisplay xmdpy = xmesa_init_display(display);
    759    XMesaVisual v;
    760    GLint red_bits, green_bits, blue_bits, alpha_bits;
    761 
    762    if (!xmdpy)
    763       return NULL;
    764 
    765    /* For debugging only */
    766    if (getenv("MESA_XSYNC")) {
    767       /* This makes debugging X easier.
    768        * In your debugger, set a breakpoint on _XError to stop when an
    769        * X protocol error is generated.
    770        */
    771       XSynchronize( display, 1 );
    772    }
    773 
    774    v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
    775    if (!v) {
    776       return NULL;
    777    }
    778 
    779    v->display = display;
    780 
    781    /* Save a copy of the XVisualInfo struct because the user may Xfree()
    782     * the struct but we may need some of the information contained in it
    783     * at a later time.
    784     */
    785    v->visinfo = malloc(sizeof(*visinfo));
    786    if (!v->visinfo) {
    787       free(v);
    788       return NULL;
    789    }
    790    memcpy(v->visinfo, visinfo, sizeof(*visinfo));
    791 
    792    v->ximage_flag = ximage_flag;
    793 
    794    v->mesa_visual.redMask = visinfo->red_mask;
    795    v->mesa_visual.greenMask = visinfo->green_mask;
    796    v->mesa_visual.blueMask = visinfo->blue_mask;
    797    v->visualID = visinfo->visualid;
    798    v->screen = visinfo->screen;
    799 
    800 #if !(defined(__cplusplus) || defined(c_plusplus))
    801    v->visualType = xmesa_convert_from_x_visual_type(visinfo->class);
    802 #else
    803    v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
    804 #endif
    805 
    806    v->mesa_visual.visualRating = visualCaveat;
    807 
    808    if (alpha_flag)
    809       v->mesa_visual.alphaBits = 8;
    810 
    811    (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
    812 
    813    {
    814       const int xclass = v->visualType;
    815       if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
    816          red_bits   = _mesa_bitcount(GET_REDMASK(v));
    817          green_bits = _mesa_bitcount(GET_GREENMASK(v));
    818          blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
    819       }
    820       else {
    821          /* this is an approximation */
    822          int depth;
    823          depth = v->visinfo->depth;
    824          red_bits = depth / 3;
    825          depth -= red_bits;
    826          green_bits = depth / 2;
    827          depth -= green_bits;
    828          blue_bits = depth;
    829          alpha_bits = 0;
    830          assert( red_bits + green_bits + blue_bits == v->visinfo->depth );
    831       }
    832       alpha_bits = v->mesa_visual.alphaBits;
    833    }
    834 
    835    /* initialize visual */
    836    {
    837       struct gl_config *vis = &v->mesa_visual;
    838 
    839       vis->rgbMode          = GL_TRUE;
    840       vis->doubleBufferMode = db_flag;
    841       vis->stereoMode       = stereo_flag;
    842 
    843       vis->redBits          = red_bits;
    844       vis->greenBits        = green_bits;
    845       vis->blueBits         = blue_bits;
    846       vis->alphaBits        = alpha_bits;
    847       vis->rgbBits          = red_bits + green_bits + blue_bits;
    848 
    849       vis->indexBits      = 0;
    850       vis->depthBits      = depth_size;
    851       vis->stencilBits    = stencil_size;
    852 
    853       vis->accumRedBits   = accum_red_size;
    854       vis->accumGreenBits = accum_green_size;
    855       vis->accumBlueBits  = accum_blue_size;
    856       vis->accumAlphaBits = accum_alpha_size;
    857 
    858       vis->haveAccumBuffer   = accum_red_size > 0;
    859       vis->haveDepthBuffer   = depth_size > 0;
    860       vis->haveStencilBuffer = stencil_size > 0;
    861 
    862       vis->numAuxBuffers = 0;
    863       vis->level = 0;
    864       vis->sampleBuffers = 0;
    865       vis->samples = 0;
    866    }
    867 
    868    v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
    869    if (db_flag)
    870       v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
    871    if (stereo_flag) {
    872       v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
    873       if (db_flag)
    874          v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
    875    }
    876 
    877    v->stvis.color_format = choose_pixel_format(v);
    878    if (v->stvis.color_format == PIPE_FORMAT_NONE) {
    879       free(v->visinfo);
    880       free(v);
    881       return NULL;
    882    }
    883 
    884    v->stvis.depth_stencil_format =
    885       choose_depth_stencil_format(xmdpy, depth_size, stencil_size);
    886 
    887    v->stvis.accum_format = (accum_red_size +
    888          accum_green_size + accum_blue_size + accum_alpha_size) ?
    889       PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
    890 
    891    v->stvis.samples = num_samples;
    892    v->stvis.render_buffer = ST_ATTACHMENT_INVALID;
    893 
    894    /* XXX minor hack */
    895    v->mesa_visual.level = level;
    896    return v;
    897 }
    898 
    899 
    900 PUBLIC
    901 void XMesaDestroyVisual( XMesaVisual v )
    902 {
    903    free(v->visinfo);
    904    free(v);
    905 }
    906 
    907 
    908 /**
    909  * Return the informative name.
    910  */
    911 const char *
    912 xmesa_get_name(void)
    913 {
    914    return stapi->name;
    915 }
    916 
    917 
    918 /**
    919  * Do per-display initializations.
    920  */
    921 void
    922 xmesa_init( Display *display )
    923 {
    924    xmesa_init_display(display);
    925 }
    926 
    927 
    928 /**
    929  * Create a new XMesaContext.
    930  * \param v  the XMesaVisual
    931  * \param share_list  another XMesaContext with which to share display
    932  *                    lists or NULL if no sharing is wanted.
    933  * \return an XMesaContext or NULL if error.
    934  */
    935 PUBLIC
    936 XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list,
    937                                  GLuint major, GLuint minor,
    938                                  GLuint profileMask, GLuint contextFlags)
    939 {
    940    XMesaDisplay xmdpy = xmesa_init_display(v->display);
    941    struct st_context_attribs attribs;
    942    enum st_context_error ctx_err = 0;
    943    XMesaContext c;
    944 
    945    if (!xmdpy)
    946       goto no_xmesa_context;
    947 
    948    /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */
    949    c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
    950    if (!c)
    951       goto no_xmesa_context;
    952 
    953    c->xm_visual = v;
    954    c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
    955    c->xm_read_buffer = NULL;
    956 
    957    memset(&attribs, 0, sizeof(attribs));
    958    attribs.visual = v->stvis;
    959    attribs.major = major;
    960    attribs.minor = minor;
    961    if (contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
    962       attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
    963    if (contextFlags & GLX_CONTEXT_DEBUG_BIT_ARB)
    964       attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
    965    if (contextFlags & GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
    966       attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS;
    967 
    968    switch (profileMask) {
    969    case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
    970       /* There are no profiles before OpenGL 3.2.  The
    971        * GLX_ARB_create_context_profile spec says:
    972        *
    973        *     "If the requested OpenGL version is less than 3.2,
    974        *     GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
    975        *     of the context is determined solely by the requested version."
    976        */
    977       if (major > 3 || (major == 3 && minor >= 2)) {
    978          attribs.profile = ST_PROFILE_OPENGL_CORE;
    979          break;
    980       }
    981       /* fall-through */
    982    case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
    983       /*
    984        * The spec also says:
    985        *
    986        *     "If version 3.1 is requested, the context returned may implement
    987        *     any of the following versions:
    988        *
    989        *       * Version 3.1. The GL_ARB_compatibility extension may or may not
    990        *         be implemented, as determined by the implementation.
    991        *       * The core profile of version 3.2 or greater."
    992        *
    993        * and because Mesa doesn't support GL_ARB_compatibility, the only chance to
    994        * honour a 3.1 context is through core profile.
    995        */
    996       if (major == 3 && minor == 1) {
    997          attribs.profile = ST_PROFILE_OPENGL_CORE;
    998       } else {
    999          attribs.profile = ST_PROFILE_DEFAULT;
   1000       }
   1001       break;
   1002    case GLX_CONTEXT_ES_PROFILE_BIT_EXT:
   1003       if (major >= 2) {
   1004          attribs.profile = ST_PROFILE_OPENGL_ES2;
   1005       } else {
   1006          attribs.profile = ST_PROFILE_OPENGL_ES1;
   1007       }
   1008       break;
   1009    default:
   1010       assert(0);
   1011       goto no_st;
   1012    }
   1013 
   1014    c->st = stapi->create_context(stapi, xmdpy->smapi, &attribs,
   1015          &ctx_err, (share_list) ? share_list->st : NULL);
   1016    if (c->st == NULL)
   1017       goto no_st;
   1018 
   1019    c->st->st_manager_private = (void *) c;
   1020 
   1021    c->hud = hud_create(c->st->pipe, c->st->cso_context);
   1022 
   1023    return c;
   1024 
   1025 no_st:
   1026    free(c);
   1027 no_xmesa_context:
   1028    return NULL;
   1029 }
   1030 
   1031 
   1032 
   1033 PUBLIC
   1034 void XMesaDestroyContext( XMesaContext c )
   1035 {
   1036    if (c->hud) {
   1037       hud_destroy(c->hud);
   1038    }
   1039 
   1040    c->st->destroy(c->st);
   1041 
   1042    /* FIXME: We should destroy the screen here, but if we do so, surfaces may
   1043     * outlive it, causing segfaults
   1044    struct pipe_screen *screen = c->st->pipe->screen;
   1045    screen->destroy(screen);
   1046    */
   1047 
   1048    free(c);
   1049 }
   1050 
   1051 
   1052 
   1053 /**
   1054  * Private function for creating an XMesaBuffer which corresponds to an
   1055  * X window or pixmap.
   1056  * \param v  the window's XMesaVisual
   1057  * \param w  the window we're wrapping
   1058  * \return  new XMesaBuffer or NULL if error
   1059  */
   1060 PUBLIC XMesaBuffer
   1061 XMesaCreateWindowBuffer(XMesaVisual v, Window w)
   1062 {
   1063    XWindowAttributes attr;
   1064    XMesaBuffer b;
   1065    Colormap cmap;
   1066    int depth;
   1067 
   1068    assert(v);
   1069    assert(w);
   1070 
   1071    /* Check that window depth matches visual depth */
   1072    XGetWindowAttributes( v->display, w, &attr );
   1073    depth = attr.depth;
   1074    if (v->visinfo->depth != depth) {
   1075       _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
   1076                     v->visinfo->depth, depth);
   1077       return NULL;
   1078    }
   1079 
   1080    /* Find colormap */
   1081    if (attr.colormap) {
   1082       cmap = attr.colormap;
   1083    }
   1084    else {
   1085       _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
   1086       /* this is weird, a window w/out a colormap!? */
   1087       /* OK, let's just allocate a new one and hope for the best */
   1088       cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
   1089    }
   1090 
   1091    b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap);
   1092    if (!b)
   1093       return NULL;
   1094 
   1095    if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
   1096                                       (Drawable) w, cmap )) {
   1097       xmesa_free_buffer(b);
   1098       return NULL;
   1099    }
   1100 
   1101    return b;
   1102 }
   1103 
   1104 
   1105 
   1106 /**
   1107  * Create a new XMesaBuffer from an X pixmap.
   1108  *
   1109  * \param v    the XMesaVisual
   1110  * \param p    the pixmap
   1111  * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
   1112  *             \c GLX_DIRECT_COLOR visual for the pixmap
   1113  * \returns new XMesaBuffer or NULL if error
   1114  */
   1115 PUBLIC XMesaBuffer
   1116 XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap)
   1117 {
   1118    XMesaBuffer b;
   1119 
   1120    assert(v);
   1121 
   1122    b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
   1123    if (!b)
   1124       return NULL;
   1125 
   1126    if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
   1127 				     (Drawable) p, cmap)) {
   1128       xmesa_free_buffer(b);
   1129       return NULL;
   1130    }
   1131 
   1132    return b;
   1133 }
   1134 
   1135 
   1136 /**
   1137  * For GLX_EXT_texture_from_pixmap
   1138  */
   1139 XMesaBuffer
   1140 XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
   1141                                Colormap cmap,
   1142                                int format, int target, int mipmap)
   1143 {
   1144    GET_CURRENT_CONTEXT(ctx);
   1145    XMesaBuffer b;
   1146 
   1147    assert(v);
   1148 
   1149    b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
   1150    if (!b)
   1151       return NULL;
   1152 
   1153    /* get pixmap size */
   1154    xmesa_get_window_size(v->display, b, &b->width, &b->height);
   1155 
   1156    if (target == 0) {
   1157       /* examine dims */
   1158       if (ctx->Extensions.ARB_texture_non_power_of_two) {
   1159          target = GLX_TEXTURE_2D_EXT;
   1160       }
   1161       else if (   _mesa_bitcount(b->width)  == 1
   1162                && _mesa_bitcount(b->height) == 1) {
   1163          /* power of two size */
   1164          if (b->height == 1) {
   1165             target = GLX_TEXTURE_1D_EXT;
   1166          }
   1167          else {
   1168             target = GLX_TEXTURE_2D_EXT;
   1169          }
   1170       }
   1171       else if (ctx->Extensions.NV_texture_rectangle) {
   1172          target = GLX_TEXTURE_RECTANGLE_EXT;
   1173       }
   1174       else {
   1175          /* non power of two textures not supported */
   1176          XMesaDestroyBuffer(b);
   1177          return 0;
   1178       }
   1179    }
   1180 
   1181    b->TextureTarget = target;
   1182    b->TextureFormat = format;
   1183    b->TextureMipmap = mipmap;
   1184 
   1185    if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
   1186 				     (Drawable) p, cmap)) {
   1187       xmesa_free_buffer(b);
   1188       return NULL;
   1189    }
   1190 
   1191    return b;
   1192 }
   1193 
   1194 
   1195 
   1196 XMesaBuffer
   1197 XMesaCreatePBuffer(XMesaVisual v, Colormap cmap,
   1198                    unsigned int width, unsigned int height)
   1199 {
   1200    Window root;
   1201    Drawable drawable;  /* X Pixmap Drawable */
   1202    XMesaBuffer b;
   1203 
   1204    /* allocate pixmap for front buffer */
   1205    root = RootWindow( v->display, v->visinfo->screen );
   1206    drawable = XCreatePixmap(v->display, root, width, height,
   1207                             v->visinfo->depth);
   1208    if (!drawable)
   1209       return NULL;
   1210 
   1211    b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
   1212    if (!b)
   1213       return NULL;
   1214 
   1215    if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
   1216 				     drawable, cmap)) {
   1217       xmesa_free_buffer(b);
   1218       return NULL;
   1219    }
   1220 
   1221    return b;
   1222 }
   1223 
   1224 
   1225 
   1226 /*
   1227  * Deallocate an XMesaBuffer structure and all related info.
   1228  */
   1229 PUBLIC void
   1230 XMesaDestroyBuffer(XMesaBuffer b)
   1231 {
   1232    xmesa_free_buffer(b);
   1233 }
   1234 
   1235 
   1236 /**
   1237  * Notify the binding context to validate the buffer.
   1238  */
   1239 void
   1240 xmesa_notify_invalid_buffer(XMesaBuffer b)
   1241 {
   1242    p_atomic_inc(&b->stfb->stamp);
   1243 }
   1244 
   1245 
   1246 /**
   1247  * Query the current drawable size and notify the binding context.
   1248  */
   1249 void
   1250 xmesa_check_buffer_size(XMesaBuffer b)
   1251 {
   1252    GLuint old_width, old_height;
   1253 
   1254    if (b->type == PBUFFER)
   1255       return;
   1256 
   1257    old_width = b->width;
   1258    old_height = b->height;
   1259 
   1260    xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height);
   1261 
   1262    if (b->width != old_width || b->height != old_height)
   1263       xmesa_notify_invalid_buffer(b);
   1264 }
   1265 
   1266 
   1267 /*
   1268  * Bind buffer b to context c and make c the current rendering context.
   1269  */
   1270 PUBLIC
   1271 GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
   1272                              XMesaBuffer readBuffer )
   1273 {
   1274    XMesaContext old_ctx = XMesaGetCurrentContext();
   1275 
   1276    if (old_ctx && old_ctx != c) {
   1277       XMesaFlush(old_ctx);
   1278       old_ctx->xm_buffer = NULL;
   1279       old_ctx->xm_read_buffer = NULL;
   1280    }
   1281 
   1282    if (c) {
   1283       if (!drawBuffer || !readBuffer)
   1284          return GL_FALSE;  /* must specify buffers! */
   1285 
   1286       if (c == old_ctx &&
   1287 	  c->xm_buffer == drawBuffer &&
   1288 	  c->xm_read_buffer == readBuffer)
   1289 	 return GL_TRUE;
   1290 
   1291       xmesa_check_buffer_size(drawBuffer);
   1292       if (readBuffer != drawBuffer)
   1293          xmesa_check_buffer_size(readBuffer);
   1294 
   1295       c->xm_buffer = drawBuffer;
   1296       c->xm_read_buffer = readBuffer;
   1297 
   1298       stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb);
   1299 
   1300       /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
   1301       drawBuffer->wasCurrent = GL_TRUE;
   1302    }
   1303    else {
   1304       /* Detach */
   1305       stapi->make_current(stapi, NULL, NULL, NULL);
   1306 
   1307    }
   1308    return GL_TRUE;
   1309 }
   1310 
   1311 
   1312 /*
   1313  * Unbind the context c from its buffer.
   1314  */
   1315 GLboolean XMesaUnbindContext( XMesaContext c )
   1316 {
   1317    /* A no-op for XFree86 integration purposes */
   1318    return GL_TRUE;
   1319 }
   1320 
   1321 
   1322 XMesaContext XMesaGetCurrentContext( void )
   1323 {
   1324    struct st_context_iface *st = stapi->get_current(stapi);
   1325    return (XMesaContext) (st) ? st->st_manager_private : NULL;
   1326 }
   1327 
   1328 
   1329 
   1330 /**
   1331  * Swap front and back color buffers and have winsys display front buffer.
   1332  * If there's no front color buffer no swap actually occurs.
   1333  */
   1334 PUBLIC
   1335 void XMesaSwapBuffers( XMesaBuffer b )
   1336 {
   1337    XMesaContext xmctx = XMesaGetCurrentContext();
   1338 
   1339    /* Need to draw HUD before flushing */
   1340    if (xmctx && xmctx->hud) {
   1341       struct pipe_resource *back =
   1342          xmesa_get_framebuffer_resource(b->stfb, ST_ATTACHMENT_BACK_LEFT);
   1343       hud_draw(xmctx->hud, back);
   1344    }
   1345 
   1346    if (xmctx && xmctx->xm_buffer == b) {
   1347       xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL);
   1348    }
   1349 
   1350    xmesa_swap_st_framebuffer(b->stfb);
   1351 }
   1352 
   1353 
   1354 
   1355 /*
   1356  * Copy sub-region of back buffer to front buffer
   1357  */
   1358 void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
   1359 {
   1360    XMesaContext xmctx = XMesaGetCurrentContext();
   1361 
   1362    xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL);
   1363 
   1364    xmesa_copy_st_framebuffer(b->stfb,
   1365          ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT,
   1366          x, b->height - y - height, width, height);
   1367 }
   1368 
   1369 
   1370 
   1371 void XMesaFlush( XMesaContext c )
   1372 {
   1373    if (c && c->xm_visual->display) {
   1374       XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display);
   1375       struct pipe_fence_handle *fence = NULL;
   1376 
   1377       c->st->flush(c->st, ST_FLUSH_FRONT, &fence);
   1378       if (fence) {
   1379          xmdpy->screen->fence_finish(xmdpy->screen, NULL, fence,
   1380                                      PIPE_TIMEOUT_INFINITE);
   1381          xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL);
   1382       }
   1383       XFlush( c->xm_visual->display );
   1384    }
   1385 }
   1386 
   1387 
   1388 
   1389 
   1390 
   1391 XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d )
   1392 {
   1393    XMesaBuffer b;
   1394    for (b = XMesaBufferList; b; b = b->Next) {
   1395       if (b->ws.drawable == d && b->xm_visual->display == dpy) {
   1396          return b;
   1397       }
   1398    }
   1399    return NULL;
   1400 }
   1401 
   1402 
   1403 /**
   1404  * Free/destroy all XMesaBuffers associated with given display.
   1405  */
   1406 void xmesa_destroy_buffers_on_display(Display *dpy)
   1407 {
   1408    XMesaBuffer b, next;
   1409    for (b = XMesaBufferList; b; b = next) {
   1410       next = b->Next;
   1411       if (b->xm_visual->display == dpy) {
   1412          xmesa_free_buffer(b);
   1413          /* delete head of list? */
   1414          if (XMesaBufferList == b) {
   1415             XMesaBufferList = next;
   1416          }
   1417       }
   1418    }
   1419 }
   1420 
   1421 
   1422 /*
   1423  * Look for XMesaBuffers whose X window has been destroyed.
   1424  * Deallocate any such XMesaBuffers.
   1425  */
   1426 void XMesaGarbageCollect( void )
   1427 {
   1428    XMesaBuffer b, next;
   1429    for (b=XMesaBufferList; b; b=next) {
   1430       next = b->Next;
   1431       if (b->xm_visual &&
   1432           b->xm_visual->display &&
   1433           b->ws.drawable &&
   1434           b->type == WINDOW) {
   1435          XSync(b->xm_visual->display, False);
   1436          if (!window_exists( b->xm_visual->display, b->ws.drawable )) {
   1437             /* found a dead window, free the ancillary info */
   1438             XMesaDestroyBuffer( b );
   1439          }
   1440       }
   1441    }
   1442 }
   1443 
   1444 
   1445 static enum st_attachment_type xmesa_attachment_type(int glx_attachment)
   1446 {
   1447    switch(glx_attachment) {
   1448       case GLX_FRONT_LEFT_EXT:
   1449          return ST_ATTACHMENT_FRONT_LEFT;
   1450       case GLX_FRONT_RIGHT_EXT:
   1451          return ST_ATTACHMENT_FRONT_RIGHT;
   1452       case GLX_BACK_LEFT_EXT:
   1453          return ST_ATTACHMENT_BACK_LEFT;
   1454       case GLX_BACK_RIGHT_EXT:
   1455          return ST_ATTACHMENT_BACK_RIGHT;
   1456       default:
   1457          assert(0);
   1458          return ST_ATTACHMENT_FRONT_LEFT;
   1459    }
   1460 }
   1461 
   1462 
   1463 PUBLIC void
   1464 XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
   1465                   const int *attrib_list)
   1466 {
   1467    struct st_context_iface *st = stapi->get_current(stapi);
   1468    struct st_framebuffer_iface* stfbi = drawable->stfb;
   1469    struct pipe_resource *res;
   1470    int x, y, w, h;
   1471    enum st_attachment_type st_attachment = xmesa_attachment_type(buffer);
   1472 
   1473    x = 0;
   1474    y = 0;
   1475    w = drawable->width;
   1476    h = drawable->height;
   1477 
   1478    /* We need to validate our attachments before using them,
   1479     * in case the texture doesn't exist yet. */
   1480    xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment);
   1481    res = xmesa_get_attachment(stfbi, st_attachment);
   1482 
   1483    if (res) {
   1484       struct pipe_context* pipe = xmesa_get_context(stfbi);
   1485       enum pipe_format internal_format = res->format;
   1486       struct pipe_transfer *tex_xfer;
   1487       char *map;
   1488       int line, byte_width;
   1489       XImage *img;
   1490 
   1491       internal_format = choose_pixel_format(drawable->xm_visual);
   1492 
   1493       map = pipe_transfer_map(pipe, res,
   1494                               0, 0,    /* level, layer */
   1495                               PIPE_TRANSFER_WRITE,
   1496                               x, y,
   1497                               w, h, &tex_xfer);
   1498       if (!map)
   1499          return;
   1500 
   1501       /* Grab the XImage that we want to turn into a texture. */
   1502       img = XGetImage(dpy,
   1503                       drawable->ws.drawable,
   1504                       x, y,
   1505                       w, h,
   1506                       AllPlanes,
   1507                       ZPixmap);
   1508 
   1509       if (!img) {
   1510          pipe_transfer_unmap(pipe, tex_xfer);
   1511          return;
   1512       }
   1513 
   1514       /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. */
   1515       byte_width = w * ((img->bits_per_pixel + 7) / 8);
   1516 
   1517       for (line = 0; line < h; line++)
   1518          memcpy(&map[line * tex_xfer->stride],
   1519                 &img->data[line * img->bytes_per_line],
   1520                 byte_width);
   1521 
   1522       pipe_transfer_unmap(pipe, tex_xfer);
   1523 
   1524       st->teximage(st,
   1525                    ST_TEXTURE_2D,
   1526                    0,    /* level */
   1527                    internal_format,
   1528                    res,
   1529                    FALSE /* no mipmap */);
   1530 
   1531    }
   1532 }
   1533 
   1534 
   1535 
   1536 PUBLIC void
   1537 XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer)
   1538 {
   1539 }
   1540 
   1541 
   1542 void
   1543 XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask)
   1544 {
   1545    if (dst->st->copy)
   1546       dst->st->copy(dst->st, src->st, mask);
   1547 }
   1548