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