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