Home | History | Annotate | Download | only in glx
      1 /*
      2  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
      3  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice including the dates of first publication and
     13  * either this permission notice or a reference to
     14  * http://oss.sgi.com/projects/FreeB/
     15  * shall be included in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     20  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     22  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * Except as contained in this notice, the name of Silicon Graphics, Inc.
     26  * shall not be used in advertising or otherwise to promote the sale, use or
     27  * other dealings in this Software without prior written authorization from
     28  * Silicon Graphics, Inc.
     29  */
     30 
     31 /**
     32  * \file glxext.c
     33  * GLX protocol interface boot-strap code.
     34  *
     35  * Direct rendering support added by Precision Insight, Inc.
     36  *
     37  * \author Kevin E. Martin <kevin (at) precisioninsight.com>
     38  */
     39 
     40 #include <assert.h>
     41 #include <stdbool.h>
     42 
     43 #include "glxclient.h"
     44 #include <X11/extensions/Xext.h>
     45 #include <X11/extensions/extutil.h>
     46 #ifdef GLX_USE_APPLEGL
     47 #include "apple/apple_glx.h"
     48 #include "apple/apple_visual.h"
     49 #endif
     50 #include "glxextensions.h"
     51 
     52 #include "util/debug.h"
     53 
     54 #include <X11/Xlib-xcb.h>
     55 #include <xcb/xcb.h>
     56 #include <xcb/glx.h>
     57 
     58 
     59 #ifdef DEBUG
     60 void __glXDumpDrawBuffer(struct glx_context * ctx);
     61 #endif
     62 
     63 /*
     64 ** You can set this cell to 1 to force the gl drawing stuff to be
     65 ** one command per packet
     66 */
     67 _X_HIDDEN int __glXDebug = 0;
     68 
     69 /* Extension required boiler plate */
     70 
     71 static const char __glXExtensionName[] = GLX_EXTENSION_NAME;
     72   static struct glx_display *glx_displays;
     73 
     74 static /* const */ char *error_list[] = {
     75    "GLXBadContext",
     76    "GLXBadContextState",
     77    "GLXBadDrawable",
     78    "GLXBadPixmap",
     79    "GLXBadContextTag",
     80    "GLXBadCurrentWindow",
     81    "GLXBadRenderRequest",
     82    "GLXBadLargeRequest",
     83    "GLXUnsupportedPrivateRequest",
     84    "GLXBadFBConfig",
     85    "GLXBadPbuffer",
     86    "GLXBadCurrentDrawable",
     87    "GLXBadWindow",
     88    "GLXBadProfileARB",
     89 };
     90 
     91 #ifdef GLX_USE_APPLEGL
     92 static char *__glXErrorString(Display *dpy, int code, XExtCodes *codes,
     93                               char *buf, int n);
     94 #endif
     95 
     96 static
     97 XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
     98                            __GLX_NUMBER_ERRORS, error_list)
     99 
    100 /*
    101  * GLX events are a bit funky.  We don't stuff the X event code into
    102  * our user exposed (via XNextEvent) structure.  Instead we use the GLX
    103  * private event code namespace (and hope it doesn't conflict).  Clients
    104  * have to know that bit 15 in the event type field means they're getting
    105  * a GLX event, and then handle the various sub-event types there, rather
    106  * than simply checking the event code and handling it directly.
    107  */
    108 
    109 static Bool
    110 __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
    111 {
    112      struct glx_display *glx_dpy = __glXInitialize(dpy);
    113 
    114    if (glx_dpy == NULL)
    115       return False;
    116 
    117    switch ((wire->u.u.type & 0x7f) - glx_dpy->codes->first_event) {
    118    case GLX_PbufferClobber:
    119    {
    120       GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event;
    121       xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire;
    122       aevent->event_type = awire->type;
    123       aevent->serial = awire->sequenceNumber;
    124       aevent->event_type = awire->event_type;
    125       aevent->draw_type = awire->draw_type;
    126       aevent->drawable = awire->drawable;
    127       aevent->buffer_mask = awire->buffer_mask;
    128       aevent->aux_buffer = awire->aux_buffer;
    129       aevent->x = awire->x;
    130       aevent->y = awire->y;
    131       aevent->width = awire->width;
    132       aevent->height = awire->height;
    133       aevent->count = awire->count;
    134       return True;
    135    }
    136    case GLX_BufferSwapComplete:
    137    {
    138       GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
    139       xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire;
    140       struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable);
    141 
    142       if (!glxDraw)
    143 	 return False;
    144 
    145       aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
    146       aevent->send_event = (awire->type & 0x80) != 0;
    147       aevent->display = dpy;
    148       aevent->event_type = awire->event_type;
    149       aevent->drawable = glxDraw->xDrawable;
    150       aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
    151       aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
    152 
    153       /* Handle 32-Bit wire sbc wraparound in both directions to cope with out
    154        * of sequence 64-Bit sbc's
    155        */
    156       if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000))
    157          glxDraw->eventSbcWrap += 0x100000000;
    158       if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000))
    159          glxDraw->eventSbcWrap -= 0x100000000;
    160       glxDraw->lastEventSbc = awire->sbc;
    161       aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
    162       return True;
    163    }
    164    default:
    165       /* client doesn't support server event */
    166       break;
    167    }
    168 
    169    return False;
    170 }
    171 
    172 /* We don't actually support this.  It doesn't make sense for clients to
    173  * send each other GLX events.
    174  */
    175 static Status
    176 __glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
    177 {
    178      struct glx_display *glx_dpy = __glXInitialize(dpy);
    179 
    180    if (glx_dpy == NULL)
    181       return False;
    182 
    183    switch (event->type) {
    184    case GLX_DAMAGED:
    185       break;
    186    case GLX_SAVED:
    187       break;
    188    case GLX_EXCHANGE_COMPLETE_INTEL:
    189       break;
    190    case GLX_COPY_COMPLETE_INTEL:
    191       break;
    192    case GLX_FLIP_COMPLETE_INTEL:
    193       break;
    194    default:
    195       /* client doesn't support server event */
    196       break;
    197    }
    198 
    199    return Success;
    200 }
    201 
    202 /************************************************************************/
    203 /*
    204 ** Free the per screen configs data as well as the array of
    205 ** __glXScreenConfigs.
    206 */
    207 static void
    208 FreeScreenConfigs(struct glx_display * priv)
    209 {
    210    struct glx_screen *psc;
    211    GLint i, screens;
    212 
    213    /* Free screen configuration information */
    214    screens = ScreenCount(priv->dpy);
    215    for (i = 0; i < screens; i++) {
    216       psc = priv->screens[i];
    217       glx_screen_cleanup(psc);
    218 
    219 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    220       if (psc->driScreen) {
    221          psc->driScreen->destroyScreen(psc);
    222       } else {
    223 	 free(psc);
    224       }
    225 #else
    226       free(psc);
    227 #endif
    228    }
    229    free((char *) priv->screens);
    230    priv->screens = NULL;
    231 }
    232 
    233 static void
    234 glx_display_free(struct glx_display *priv)
    235 {
    236    struct glx_context *gc;
    237 
    238    gc = __glXGetCurrentContext();
    239    if (priv->dpy == gc->currentDpy) {
    240       gc->vtable->destroy(gc);
    241       __glXSetCurrentContextNull();
    242    }
    243 
    244    FreeScreenConfigs(priv);
    245    free((char *) priv->serverGLXvendor);
    246    free((char *) priv->serverGLXversion);
    247 
    248    __glxHashDestroy(priv->glXDrawHash);
    249 
    250 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    251    __glxHashDestroy(priv->drawHash);
    252 
    253    /* Free the direct rendering per display data */
    254    if (priv->driswDisplay)
    255       (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
    256    priv->driswDisplay = NULL;
    257 
    258 #if defined (GLX_USE_DRM)
    259    if (priv->driDisplay)
    260       (*priv->driDisplay->destroyDisplay) (priv->driDisplay);
    261    priv->driDisplay = NULL;
    262 
    263    if (priv->dri2Display)
    264       (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
    265    priv->dri2Display = NULL;
    266 
    267    if (priv->dri3Display)
    268       (*priv->dri3Display->destroyDisplay) (priv->dri3Display);
    269    priv->dri3Display = NULL;
    270 #endif /* GLX_USE_DRM */
    271 
    272 #if defined(GLX_USE_WINDOWSGL)
    273    if (priv->windowsdriDisplay)
    274       (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay);
    275    priv->windowsdriDisplay = NULL;
    276 #endif /* GLX_USE_WINDOWSGL */
    277 
    278 #endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
    279 
    280    free((char *) priv);
    281 }
    282 
    283 static int
    284 __glXCloseDisplay(Display * dpy, XExtCodes * codes)
    285 {
    286    struct glx_display *priv, **prev;
    287 
    288    _XLockMutex(_Xglobal_lock);
    289    prev = &glx_displays;
    290    for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) {
    291       if (priv->dpy == dpy) {
    292          *prev = priv->next;
    293 	 break;
    294       }
    295    }
    296    _XUnlockMutex(_Xglobal_lock);
    297 
    298    if (priv != NULL)
    299       glx_display_free(priv);
    300 
    301    return 1;
    302 }
    303 
    304 /*
    305 ** Query the version of the GLX extension.  This procedure works even if
    306 ** the client extension is not completely set up.
    307 */
    308 static Bool
    309 QueryVersion(Display * dpy, int opcode, int *major, int *minor)
    310 {
    311    xcb_connection_t *c = XGetXCBConnection(dpy);
    312    xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c,
    313                                                                       xcb_glx_query_version
    314                                                                       (c,
    315                                                                        GLX_MAJOR_VERSION,
    316                                                                        GLX_MINOR_VERSION),
    317                                                                       NULL);
    318 
    319    if (!reply)
    320      return GL_FALSE;
    321 
    322    if (reply->major_version != GLX_MAJOR_VERSION) {
    323       free(reply);
    324       return GL_FALSE;
    325    }
    326    *major = reply->major_version;
    327    *minor = min(reply->minor_version, GLX_MINOR_VERSION);
    328    free(reply);
    329    return GL_TRUE;
    330 }
    331 
    332 /*
    333  * We don't want to enable this GLX_OML_swap_method in glxext.h,
    334  * because we can't support it.  The X server writes it out though,
    335  * so we should handle it somehow, to avoid false warnings.
    336  */
    337 enum {
    338     IGNORE_GLX_SWAP_METHOD_OML = 0x8060
    339 };
    340 
    341 
    342 static GLint
    343 convert_from_x_visual_type(int visualType)
    344 {
    345    static const int glx_visual_types[] = {
    346       GLX_STATIC_GRAY, GLX_GRAY_SCALE,
    347       GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
    348       GLX_TRUE_COLOR, GLX_DIRECT_COLOR
    349    };
    350 
    351    if (visualType < ARRAY_SIZE(glx_visual_types))
    352       return glx_visual_types[visualType];
    353 
    354    return GLX_NONE;
    355 }
    356 
    357 /*
    358  * getVisualConfigs uses the !tagged_only path.
    359  * getFBConfigs uses the tagged_only path.
    360  */
    361 _X_HIDDEN void
    362 __glXInitializeVisualConfigFromTags(struct glx_config * config, int count,
    363                                     const INT32 * bp, Bool tagged_only,
    364                                     Bool fbconfig_style_tags)
    365 {
    366    int i;
    367    GLint renderType = 0;
    368 
    369    if (!tagged_only) {
    370       /* Copy in the first set of properties */
    371       config->visualID = *bp++;
    372 
    373       config->visualType = convert_from_x_visual_type(*bp++);
    374 
    375       config->rgbMode = *bp++;
    376 
    377       config->redBits = *bp++;
    378       config->greenBits = *bp++;
    379       config->blueBits = *bp++;
    380       config->alphaBits = *bp++;
    381       config->accumRedBits = *bp++;
    382       config->accumGreenBits = *bp++;
    383       config->accumBlueBits = *bp++;
    384       config->accumAlphaBits = *bp++;
    385 
    386       config->doubleBufferMode = *bp++;
    387       config->stereoMode = *bp++;
    388 
    389       config->rgbBits = *bp++;
    390       config->depthBits = *bp++;
    391       config->stencilBits = *bp++;
    392       config->numAuxBuffers = *bp++;
    393       config->level = *bp++;
    394 
    395 #ifdef GLX_USE_APPLEGL
    396        /* AppleSGLX supports pixmap and pbuffers with all config. */
    397        config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
    398        /* Unfortunately this can create an ABI compatibility problem. */
    399        count -= 18;
    400 #else
    401       count -= __GLX_MIN_CONFIG_PROPS;
    402 #endif
    403    }
    404 
    405    config->sRGBCapable = GL_FALSE;
    406 
    407    /*
    408     ** Additional properties may be in a list at the end
    409     ** of the reply.  They are in pairs of property type
    410     ** and property value.
    411     */
    412 
    413 #define FETCH_OR_SET(tag) \
    414     config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
    415 
    416    for (i = 0; i < count; i += 2) {
    417       long int tag = *bp++;
    418 
    419       switch (tag) {
    420       case GLX_RGBA:
    421          FETCH_OR_SET(rgbMode);
    422          break;
    423       case GLX_BUFFER_SIZE:
    424          config->rgbBits = *bp++;
    425          break;
    426       case GLX_LEVEL:
    427          config->level = *bp++;
    428          break;
    429       case GLX_DOUBLEBUFFER:
    430          FETCH_OR_SET(doubleBufferMode);
    431          break;
    432       case GLX_STEREO:
    433          FETCH_OR_SET(stereoMode);
    434          break;
    435       case GLX_AUX_BUFFERS:
    436          config->numAuxBuffers = *bp++;
    437          break;
    438       case GLX_RED_SIZE:
    439          config->redBits = *bp++;
    440          break;
    441       case GLX_GREEN_SIZE:
    442          config->greenBits = *bp++;
    443          break;
    444       case GLX_BLUE_SIZE:
    445          config->blueBits = *bp++;
    446          break;
    447       case GLX_ALPHA_SIZE:
    448          config->alphaBits = *bp++;
    449          break;
    450       case GLX_DEPTH_SIZE:
    451          config->depthBits = *bp++;
    452          break;
    453       case GLX_STENCIL_SIZE:
    454          config->stencilBits = *bp++;
    455          break;
    456       case GLX_ACCUM_RED_SIZE:
    457          config->accumRedBits = *bp++;
    458          break;
    459       case GLX_ACCUM_GREEN_SIZE:
    460          config->accumGreenBits = *bp++;
    461          break;
    462       case GLX_ACCUM_BLUE_SIZE:
    463          config->accumBlueBits = *bp++;
    464          break;
    465       case GLX_ACCUM_ALPHA_SIZE:
    466          config->accumAlphaBits = *bp++;
    467          break;
    468       case GLX_VISUAL_CAVEAT_EXT:
    469          config->visualRating = *bp++;
    470          break;
    471       case GLX_X_VISUAL_TYPE:
    472          config->visualType = *bp++;
    473          break;
    474       case GLX_TRANSPARENT_TYPE:
    475          config->transparentPixel = *bp++;
    476          break;
    477       case GLX_TRANSPARENT_INDEX_VALUE:
    478          config->transparentIndex = *bp++;
    479          break;
    480       case GLX_TRANSPARENT_RED_VALUE:
    481          config->transparentRed = *bp++;
    482          break;
    483       case GLX_TRANSPARENT_GREEN_VALUE:
    484          config->transparentGreen = *bp++;
    485          break;
    486       case GLX_TRANSPARENT_BLUE_VALUE:
    487          config->transparentBlue = *bp++;
    488          break;
    489       case GLX_TRANSPARENT_ALPHA_VALUE:
    490          config->transparentAlpha = *bp++;
    491          break;
    492       case GLX_VISUAL_ID:
    493          config->visualID = *bp++;
    494          break;
    495       case GLX_DRAWABLE_TYPE:
    496          config->drawableType = *bp++;
    497 #ifdef GLX_USE_APPLEGL
    498          /* AppleSGLX supports pixmap and pbuffers with all config. */
    499          config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
    500 #endif
    501          break;
    502       case GLX_RENDER_TYPE: /* fbconfig render type bits */
    503          renderType = *bp++;
    504          break;
    505       case GLX_X_RENDERABLE:
    506          config->xRenderable = *bp++;
    507          break;
    508       case GLX_FBCONFIG_ID:
    509          config->fbconfigID = *bp++;
    510          break;
    511       case GLX_MAX_PBUFFER_WIDTH:
    512          config->maxPbufferWidth = *bp++;
    513          break;
    514       case GLX_MAX_PBUFFER_HEIGHT:
    515          config->maxPbufferHeight = *bp++;
    516          break;
    517       case GLX_MAX_PBUFFER_PIXELS:
    518          config->maxPbufferPixels = *bp++;
    519          break;
    520 #ifndef GLX_USE_APPLEGL
    521       case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
    522          config->optimalPbufferWidth = *bp++;
    523          break;
    524       case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
    525          config->optimalPbufferHeight = *bp++;
    526          break;
    527       case GLX_VISUAL_SELECT_GROUP_SGIX:
    528          config->visualSelectGroup = *bp++;
    529          break;
    530       case GLX_SWAP_METHOD_OML:
    531          if (*bp == GLX_SWAP_UNDEFINED_OML ||
    532              *bp == GLX_SWAP_COPY_OML ||
    533              *bp == GLX_SWAP_EXCHANGE_OML) {
    534             config->swapMethod = *bp++;
    535          } else {
    536             /* X servers with old HW drivers may return any value here, so
    537              * assume GLX_SWAP_METHOD_UNDEFINED.
    538              */
    539             config->swapMethod = GLX_SWAP_UNDEFINED_OML;
    540             bp++;
    541          }
    542          break;
    543 #endif
    544       case GLX_SAMPLE_BUFFERS_SGIS:
    545          config->sampleBuffers = *bp++;
    546          break;
    547       case GLX_SAMPLES_SGIS:
    548          config->samples = *bp++;
    549          break;
    550 #ifdef GLX_USE_APPLEGL
    551       case IGNORE_GLX_SWAP_METHOD_OML:
    552          /* We ignore this tag.  See the comment above this function. */
    553          ++bp;
    554          break;
    555 #else
    556       case GLX_BIND_TO_TEXTURE_RGB_EXT:
    557          config->bindToTextureRgb = *bp++;
    558          break;
    559       case GLX_BIND_TO_TEXTURE_RGBA_EXT:
    560          config->bindToTextureRgba = *bp++;
    561          break;
    562       case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
    563          config->bindToMipmapTexture = *bp++;
    564          break;
    565       case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
    566          config->bindToTextureTargets = *bp++;
    567          break;
    568       case GLX_Y_INVERTED_EXT:
    569          config->yInverted = *bp++;
    570          break;
    571 #endif
    572       case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
    573          config->sRGBCapable = *bp++;
    574          break;
    575 
    576       case GLX_USE_GL:
    577          if (fbconfig_style_tags)
    578             bp++;
    579          break;
    580       case None:
    581          i = count;
    582          break;
    583       default:
    584          if(env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) {
    585              long int tagvalue = *bp++;
    586              fprintf(stderr, "WARNING: unknown GLX tag from server: "
    587                      "tag 0x%lx value 0x%lx\n", tag, tagvalue);
    588          } else {
    589              /* Ignore the unrecognized tag's value */
    590              bp++;
    591          }
    592          break;
    593       }
    594    }
    595 
    596    if (renderType != 0 && renderType != GLX_DONT_CARE) {
    597       config->renderType = renderType;
    598       config->floatMode = (renderType &
    599          (GLX_RGBA_FLOAT_BIT_ARB|GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) != 0;
    600    } else {
    601       /* If there wasn't GLX_RENDER_TYPE property, set it based on
    602        * config->rgbMode.  The only way to communicate that the config is
    603        * floating-point is via GLX_RENDER_TYPE, so this cannot be a float
    604        * config.
    605        */
    606       config->renderType =
    607          (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
    608    }
    609 
    610    /* The GLX_ARB_fbconfig_float spec says:
    611     *
    612     *     "Note that floating point rendering is only supported for
    613     *     GLXPbuffer drawables."
    614     */
    615    if (config->floatMode)
    616       config->drawableType &= GLX_PBUFFER_BIT;
    617 }
    618 
    619 static struct glx_config *
    620 createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
    621                             int screen, GLboolean tagged_only)
    622 {
    623    INT32 buf[__GLX_TOTAL_CONFIG], *props;
    624    unsigned prop_size;
    625    struct glx_config *modes, *m;
    626    int i;
    627 
    628    if (nprops == 0)
    629       return NULL;
    630 
    631    /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
    632 
    633    /* Check number of properties */
    634    if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
    635       return NULL;
    636 
    637    /* Allocate memory for our config structure */
    638    modes = glx_config_create_list(nvisuals);
    639    if (!modes)
    640       return NULL;
    641 
    642    prop_size = nprops * __GLX_SIZE_INT32;
    643    if (prop_size <= sizeof(buf))
    644       props = buf;
    645    else
    646       props = malloc(prop_size);
    647 
    648    /* Read each config structure and convert it into our format */
    649    m = modes;
    650    for (i = 0; i < nvisuals; i++) {
    651       _XRead(dpy, (char *) props, prop_size);
    652 #ifdef GLX_USE_APPLEGL
    653        /* Older X servers don't send this so we default it here. */
    654       m->drawableType = GLX_WINDOW_BIT;
    655 #else
    656       /*
    657        * The XQuartz 2.3.2.1 X server doesn't set this properly, so
    658        * set the proper bits here.
    659        * AppleSGLX supports windows, pixmaps, and pbuffers with all config.
    660        */
    661       m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
    662 #endif
    663        __glXInitializeVisualConfigFromTags(m, nprops, props,
    664                                           tagged_only, GL_TRUE);
    665       m->screen = screen;
    666       m = m->next;
    667    }
    668 
    669    if (props != buf)
    670       free(props);
    671 
    672    return modes;
    673 }
    674 
    675 static GLboolean
    676 getVisualConfigs(struct glx_screen *psc,
    677 		  struct glx_display *priv, int screen)
    678 {
    679    xGLXGetVisualConfigsReq *req;
    680    xGLXGetVisualConfigsReply reply;
    681    Display *dpy = priv->dpy;
    682 
    683    LockDisplay(dpy);
    684 
    685    psc->visuals = NULL;
    686    GetReq(GLXGetVisualConfigs, req);
    687    req->reqType = priv->majorOpcode;
    688    req->glxCode = X_GLXGetVisualConfigs;
    689    req->screen = screen;
    690 
    691    if (!_XReply(dpy, (xReply *) & reply, 0, False))
    692       goto out;
    693 
    694    psc->visuals = createConfigsFromProperties(dpy,
    695                                               reply.numVisuals,
    696                                               reply.numProps,
    697                                               screen, GL_FALSE);
    698 
    699  out:
    700    UnlockDisplay(dpy);
    701    return psc->visuals != NULL;
    702 }
    703 
    704 static GLboolean
    705  getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen)
    706 {
    707    xGLXGetFBConfigsReq *fb_req;
    708    xGLXGetFBConfigsSGIXReq *sgi_req;
    709    xGLXVendorPrivateWithReplyReq *vpreq;
    710    xGLXGetFBConfigsReply reply;
    711    Display *dpy = priv->dpy;
    712 
    713    psc->serverGLXexts =
    714       __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
    715 
    716    if (psc->serverGLXexts == NULL) {
    717       return GL_FALSE;
    718    }
    719 
    720    LockDisplay(dpy);
    721 
    722    psc->configs = NULL;
    723    if (atof(priv->serverGLXversion) >= 1.3) {
    724       GetReq(GLXGetFBConfigs, fb_req);
    725       fb_req->reqType = priv->majorOpcode;
    726       fb_req->glxCode = X_GLXGetFBConfigs;
    727       fb_req->screen = screen;
    728    }
    729    else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
    730       GetReqExtra(GLXVendorPrivateWithReply,
    731                   sz_xGLXGetFBConfigsSGIXReq -
    732                   sz_xGLXVendorPrivateWithReplyReq, vpreq);
    733       sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
    734       sgi_req->reqType = priv->majorOpcode;
    735       sgi_req->glxCode = X_GLXVendorPrivateWithReply;
    736       sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
    737       sgi_req->screen = screen;
    738    }
    739    else
    740       goto out;
    741 
    742    if (!_XReply(dpy, (xReply *) & reply, 0, False))
    743       goto out;
    744 
    745    psc->configs = createConfigsFromProperties(dpy,
    746                                               reply.numFBConfigs,
    747                                               reply.numAttribs * 2,
    748                                               screen, GL_TRUE);
    749 
    750  out:
    751    UnlockDisplay(dpy);
    752    return psc->configs != NULL;
    753 }
    754 
    755 _X_HIDDEN Bool
    756 glx_screen_init(struct glx_screen *psc,
    757 		 int screen, struct glx_display * priv)
    758 {
    759    /* Initialize per screen dynamic client GLX extensions */
    760    psc->ext_list_first_time = GL_TRUE;
    761    psc->scr = screen;
    762    psc->dpy = priv->dpy;
    763    psc->display = priv;
    764 
    765    if (!getVisualConfigs(psc, priv, screen))
    766       return GL_FALSE;
    767 
    768    if (!getFBConfigs(psc, priv, screen))
    769       return GL_FALSE;
    770 
    771    return GL_TRUE;
    772 }
    773 
    774 _X_HIDDEN void
    775 glx_screen_cleanup(struct glx_screen *psc)
    776 {
    777    if (psc->configs) {
    778       glx_config_destroy_list(psc->configs);
    779       free(psc->effectiveGLXexts);
    780       psc->configs = NULL;   /* NOTE: just for paranoia */
    781    }
    782    if (psc->visuals) {
    783       glx_config_destroy_list(psc->visuals);
    784       psc->visuals = NULL;   /* NOTE: just for paranoia */
    785    }
    786    free((char *) psc->serverGLXexts);
    787 }
    788 
    789 /*
    790 ** Allocate the memory for the per screen configs for each screen.
    791 ** If that works then fetch the per screen configs data.
    792 */
    793 static Bool
    794 AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv)
    795 {
    796    struct glx_screen *psc;
    797    GLint i, screens;
    798 
    799    /*
    800     ** First allocate memory for the array of per screen configs.
    801     */
    802    screens = ScreenCount(dpy);
    803    priv->screens = malloc(screens * sizeof *priv->screens);
    804    if (!priv->screens)
    805       return GL_FALSE;
    806 
    807    priv->serverGLXversion =
    808       __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
    809    if (priv->serverGLXversion == NULL) {
    810       FreeScreenConfigs(priv);
    811       return GL_FALSE;
    812    }
    813 
    814    for (i = 0; i < screens; i++, psc++) {
    815       psc = NULL;
    816 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    817 #if defined(GLX_USE_DRM)
    818 #if defined(HAVE_DRI3)
    819       if (priv->dri3Display)
    820          psc = (*priv->dri3Display->createScreen) (i, priv);
    821 #endif /* HAVE_DRI3 */
    822       if (psc == NULL && priv->dri2Display)
    823 	 psc = (*priv->dri2Display->createScreen) (i, priv);
    824       if (psc == NULL && priv->driDisplay)
    825 	 psc = (*priv->driDisplay->createScreen) (i, priv);
    826 #endif /* GLX_USE_DRM */
    827 
    828 #ifdef GLX_USE_WINDOWSGL
    829       if (psc == NULL && priv->windowsdriDisplay)
    830 	 psc = (*priv->windowsdriDisplay->createScreen) (i, priv);
    831 #endif
    832 
    833       if (psc == NULL && priv->driswDisplay)
    834 	 psc = (*priv->driswDisplay->createScreen) (i, priv);
    835 #endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
    836 
    837 #if defined(GLX_USE_APPLEGL)
    838       if (psc == NULL)
    839          psc = applegl_create_screen(i, priv);
    840 #else
    841       if (psc == NULL)
    842 	 psc = indirect_create_screen(i, priv);
    843 #endif
    844       priv->screens[i] = psc;
    845    }
    846    SyncHandle();
    847    return GL_TRUE;
    848 }
    849 
    850 /*
    851 ** Initialize the client side extension code.
    852 */
    853  _X_HIDDEN struct glx_display *
    854 __glXInitialize(Display * dpy)
    855 {
    856    struct glx_display *dpyPriv, *d;
    857 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    858    Bool glx_direct, glx_accel;
    859 #endif
    860    int i;
    861 
    862    _XLockMutex(_Xglobal_lock);
    863 
    864    for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) {
    865       if (dpyPriv->dpy == dpy) {
    866 	 _XUnlockMutex(_Xglobal_lock);
    867 	 return dpyPriv;
    868       }
    869    }
    870 
    871    /* Drop the lock while we create the display private. */
    872    _XUnlockMutex(_Xglobal_lock);
    873 
    874    dpyPriv = calloc(1, sizeof *dpyPriv);
    875    if (!dpyPriv)
    876       return NULL;
    877 
    878    dpyPriv->codes = XInitExtension(dpy, __glXExtensionName);
    879    if (!dpyPriv->codes) {
    880       free(dpyPriv);
    881       return NULL;
    882    }
    883 
    884    dpyPriv->dpy = dpy;
    885    dpyPriv->majorOpcode = dpyPriv->codes->major_opcode;
    886    dpyPriv->serverGLXvendor = 0x0;
    887    dpyPriv->serverGLXversion = 0x0;
    888 
    889    /* See if the versions are compatible.  This GLX implementation does not
    890     * work with servers that only support GLX 1.0.
    891     */
    892    if (!QueryVersion(dpy, dpyPriv->majorOpcode,
    893 		     &dpyPriv->majorVersion, &dpyPriv->minorVersion)
    894        || (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion < 1)) {
    895       free(dpyPriv);
    896       return NULL;
    897    }
    898 
    899    for (i = 0; i < __GLX_NUMBER_EVENTS; i++) {
    900       XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent);
    901       XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire);
    902    }
    903 
    904    XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay);
    905    XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString);
    906 
    907    dpyPriv->glXDrawHash = __glxHashCreate();
    908 
    909 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
    910    glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false);
    911    glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
    912 
    913    dpyPriv->drawHash = __glxHashCreate();
    914 
    915    /*
    916     ** Initialize the direct rendering per display data and functions.
    917     ** Note: This _must_ be done before calling any other DRI routines
    918     ** (e.g., those called in AllocAndFetchScreenConfigs).
    919     */
    920 #if defined(GLX_USE_DRM)
    921    if (glx_direct && glx_accel) {
    922 #if defined(HAVE_DRI3)
    923       if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false))
    924          dpyPriv->dri3Display = dri3_create_display(dpy);
    925 #endif /* HAVE_DRI3 */
    926       dpyPriv->dri2Display = dri2CreateDisplay(dpy);
    927       dpyPriv->driDisplay = driCreateDisplay(dpy);
    928    }
    929 #endif /* GLX_USE_DRM */
    930    if (glx_direct)
    931       dpyPriv->driswDisplay = driswCreateDisplay(dpy);
    932 #endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */
    933 
    934 #ifdef GLX_USE_APPLEGL
    935    if (!applegl_create_display(dpyPriv)) {
    936       free(dpyPriv);
    937       return NULL;
    938    }
    939 #endif
    940 
    941 #ifdef GLX_USE_WINDOWSGL
    942    if (glx_direct && glx_accel)
    943       dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy);
    944 #endif
    945 
    946    if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
    947       free(dpyPriv);
    948       return NULL;
    949    }
    950 
    951    __glX_send_client_info(dpyPriv);
    952 
    953    /* Grab the lock again and add the dispay private, unless somebody
    954     * beat us to initializing on this display in the meantime. */
    955    _XLockMutex(_Xglobal_lock);
    956 
    957    for (d = glx_displays; d; d = d->next) {
    958       if (d->dpy == dpy) {
    959 	 _XUnlockMutex(_Xglobal_lock);
    960 	 glx_display_free(dpyPriv);
    961 	 return d;
    962       }
    963    }
    964 
    965    dpyPriv->next = glx_displays;
    966    glx_displays = dpyPriv;
    967 
    968    _XUnlockMutex(_Xglobal_lock);
    969 
    970    return dpyPriv;
    971 }
    972 
    973 /*
    974 ** Setup for sending a GLX command on dpy.  Make sure the extension is
    975 ** initialized.  Try to avoid calling __glXInitialize as its kinda slow.
    976 */
    977 _X_HIDDEN CARD8
    978 __glXSetupForCommand(Display * dpy)
    979 {
    980     struct glx_context *gc;
    981     struct glx_display *priv;
    982 
    983    /* If this thread has a current context, flush its rendering commands */
    984    gc = __glXGetCurrentContext();
    985    if (gc->currentDpy) {
    986       /* Flush rendering buffer of the current context, if any */
    987       (void) __glXFlushRenderBuffer(gc, gc->pc);
    988 
    989       if (gc->currentDpy == dpy) {
    990          /* Use opcode from gc because its right */
    991          return gc->majorOpcode;
    992       }
    993       else {
    994          /*
    995           ** Have to get info about argument dpy because it might be to
    996           ** a different server
    997           */
    998       }
    999    }
   1000 
   1001    /* Forced to lookup extension via the slow initialize route */
   1002    priv = __glXInitialize(dpy);
   1003    if (!priv) {
   1004       return 0;
   1005    }
   1006    return priv->majorOpcode;
   1007 }
   1008 
   1009 /**
   1010  * Flush the drawing command transport buffer.
   1011  *
   1012  * \param ctx  Context whose transport buffer is to be flushed.
   1013  * \param pc   Pointer to first unused buffer location.
   1014  *
   1015  * \todo
   1016  * Modify this function to use \c ctx->pc instead of the explicit
   1017  * \c pc parameter.
   1018  */
   1019 _X_HIDDEN GLubyte *
   1020 __glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc)
   1021 {
   1022    Display *const dpy = ctx->currentDpy;
   1023    xcb_connection_t *c = XGetXCBConnection(dpy);
   1024    const GLint size = pc - ctx->buf;
   1025 
   1026    if ((dpy != NULL) && (size > 0)) {
   1027       xcb_glx_render(c, ctx->currentContextTag, size,
   1028                      (const uint8_t *) ctx->buf);
   1029    }
   1030 
   1031    /* Reset pointer and return it */
   1032    ctx->pc = ctx->buf;
   1033    return ctx->pc;
   1034 }
   1035 
   1036 
   1037 /**
   1038  * Send a portion of a GLXRenderLarge command to the server.  The advantage of
   1039  * this function over \c __glXSendLargeCommand is that callers can use the
   1040  * data buffer in the GLX context and may be able to avoid allocating an
   1041  * extra buffer.  The disadvantage is the clients will have to do more
   1042  * GLX protocol work (i.e., calculating \c totalRequests, etc.).
   1043  *
   1044  * \sa __glXSendLargeCommand
   1045  *
   1046  * \param gc             GLX context
   1047  * \param requestNumber  Which part of the whole command is this?  The first
   1048  *                       request is 1.
   1049  * \param totalRequests  How many requests will there be?
   1050  * \param data           Command data.
   1051  * \param dataLen        Size, in bytes, of the command data.
   1052  */
   1053 _X_HIDDEN void
   1054 __glXSendLargeChunk(struct glx_context * gc, GLint requestNumber,
   1055                     GLint totalRequests, const GLvoid * data, GLint dataLen)
   1056 {
   1057    Display *dpy = gc->currentDpy;
   1058    xcb_connection_t *c = XGetXCBConnection(dpy);
   1059    xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
   1060                         totalRequests, dataLen, data);
   1061 }
   1062 
   1063 
   1064 /**
   1065  * Send a command that is too large for the GLXRender protocol request.
   1066  *
   1067  * Send a large command, one that is too large for some reason to
   1068  * send using the GLXRender protocol request.  One reason to send
   1069  * a large command is to avoid copying the data.
   1070  *
   1071  * \param ctx        GLX context
   1072  * \param header     Header data.
   1073  * \param headerLen  Size, in bytes, of the header data.  It is assumed that
   1074  *                   the header data will always be small enough to fit in
   1075  *                   a single X protocol packet.
   1076  * \param data       Command data.
   1077  * \param dataLen    Size, in bytes, of the command data.
   1078  */
   1079 _X_HIDDEN void
   1080 __glXSendLargeCommand(struct glx_context * ctx,
   1081                       const GLvoid * header, GLint headerLen,
   1082                       const GLvoid * data, GLint dataLen)
   1083 {
   1084    GLint maxSize;
   1085    GLint totalRequests, requestNumber;
   1086 
   1087    /*
   1088     ** Calculate the maximum amount of data can be stuffed into a single
   1089     ** packet.  sz_xGLXRenderReq is added because bufSize is the maximum
   1090     ** packet size minus sz_xGLXRenderReq.
   1091     */
   1092    maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
   1093    totalRequests = 1 + (dataLen / maxSize);
   1094    if (dataLen % maxSize)
   1095       totalRequests++;
   1096 
   1097    /*
   1098     ** Send all of the command, except the large array, as one request.
   1099     */
   1100    assert(headerLen <= maxSize);
   1101    __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
   1102 
   1103    /*
   1104     ** Send enough requests until the whole array is sent.
   1105     */
   1106    for (requestNumber = 2; requestNumber <= (totalRequests - 1);
   1107         requestNumber++) {
   1108       __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
   1109       data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
   1110       dataLen -= maxSize;
   1111       assert(dataLen > 0);
   1112    }
   1113 
   1114    assert(dataLen <= maxSize);
   1115    __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
   1116 }
   1117 
   1118 /************************************************************************/
   1119 
   1120 #ifdef DEBUG
   1121 _X_HIDDEN void
   1122 __glXDumpDrawBuffer(struct glx_context * ctx)
   1123 {
   1124    GLubyte *p = ctx->buf;
   1125    GLubyte *end = ctx->pc;
   1126    GLushort opcode, length;
   1127 
   1128    while (p < end) {
   1129       /* Fetch opcode */
   1130       opcode = *((GLushort *) p);
   1131       length = *((GLushort *) (p + 2));
   1132       printf("%2x: %5d: ", opcode, length);
   1133       length -= 4;
   1134       p += 4;
   1135       while (length > 0) {
   1136          printf("%08x ", *((unsigned *) p));
   1137          p += 4;
   1138          length -= 4;
   1139       }
   1140       printf("\n");
   1141    }
   1142 }
   1143 #endif
   1144