glxext.c revision 01e04c3f
1cdc920a0Smrg/* 2cdc920a0Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3cdc920a0Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. 4cdc920a0Smrg * 5cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6cdc920a0Smrg * copy of this software and associated documentation files (the "Software"), 7cdc920a0Smrg * to deal in the Software without restriction, including without limitation 8cdc920a0Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9cdc920a0Smrg * and/or sell copies of the Software, and to permit persons to whom the 10cdc920a0Smrg * Software is furnished to do so, subject to the following conditions: 11cdc920a0Smrg * 12cdc920a0Smrg * The above copyright notice including the dates of first publication and 13cdc920a0Smrg * either this permission notice or a reference to 14cdc920a0Smrg * http://oss.sgi.com/projects/FreeB/ 15cdc920a0Smrg * shall be included in all copies or substantial portions of the Software. 16cdc920a0Smrg * 17cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18cdc920a0Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19cdc920a0Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20cdc920a0Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21cdc920a0Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22cdc920a0Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23cdc920a0Smrg * SOFTWARE. 24cdc920a0Smrg * 25cdc920a0Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc. 26cdc920a0Smrg * shall not be used in advertising or otherwise to promote the sale, use or 27cdc920a0Smrg * other dealings in this Software without prior written authorization from 28cdc920a0Smrg * Silicon Graphics, Inc. 29cdc920a0Smrg */ 30cdc920a0Smrg 31cdc920a0Smrg/** 32cdc920a0Smrg * \file glxext.c 33cdc920a0Smrg * GLX protocol interface boot-strap code. 34cdc920a0Smrg * 35cdc920a0Smrg * Direct rendering support added by Precision Insight, Inc. 36cdc920a0Smrg * 37cdc920a0Smrg * \author Kevin E. Martin <kevin@precisioninsight.com> 38cdc920a0Smrg */ 39cdc920a0Smrg 40cdc920a0Smrg#include <assert.h> 4101e04c3fSmrg#include <stdbool.h> 4201e04c3fSmrg 43cdc920a0Smrg#include "glxclient.h" 44cdc920a0Smrg#include <X11/extensions/Xext.h> 45cdc920a0Smrg#include <X11/extensions/extutil.h> 46cdc920a0Smrg#ifdef GLX_USE_APPLEGL 47af69d88dSmrg#include "apple/apple_glx.h" 48af69d88dSmrg#include "apple/apple_visual.h" 49cdc920a0Smrg#endif 50cdc920a0Smrg#include "glxextensions.h" 51cdc920a0Smrg 5201e04c3fSmrg#include "util/debug.h" 5301e04c3fSmrg 54cdc920a0Smrg#include <X11/Xlib-xcb.h> 55cdc920a0Smrg#include <xcb/xcb.h> 56cdc920a0Smrg#include <xcb/glx.h> 57cdc920a0Smrg 58cdc920a0Smrg 59cdc920a0Smrg#ifdef DEBUG 603464ebd5Sriastradhvoid __glXDumpDrawBuffer(struct glx_context * ctx); 61cdc920a0Smrg#endif 62cdc920a0Smrg 63cdc920a0Smrg/* 64cdc920a0Smrg** You can set this cell to 1 to force the gl drawing stuff to be 65cdc920a0Smrg** one command per packet 66cdc920a0Smrg*/ 67cdc920a0Smrg_X_HIDDEN int __glXDebug = 0; 68cdc920a0Smrg 69cdc920a0Smrg/* Extension required boiler plate */ 70cdc920a0Smrg 713464ebd5Sriastradhstatic const char __glXExtensionName[] = GLX_EXTENSION_NAME; 723464ebd5Sriastradh static struct glx_display *glx_displays; 73cdc920a0Smrg 74cdc920a0Smrgstatic /* const */ char *error_list[] = { 75cdc920a0Smrg "GLXBadContext", 76cdc920a0Smrg "GLXBadContextState", 77cdc920a0Smrg "GLXBadDrawable", 78cdc920a0Smrg "GLXBadPixmap", 79cdc920a0Smrg "GLXBadContextTag", 80cdc920a0Smrg "GLXBadCurrentWindow", 81cdc920a0Smrg "GLXBadRenderRequest", 82cdc920a0Smrg "GLXBadLargeRequest", 83cdc920a0Smrg "GLXUnsupportedPrivateRequest", 84cdc920a0Smrg "GLXBadFBConfig", 85cdc920a0Smrg "GLXBadPbuffer", 86cdc920a0Smrg "GLXBadCurrentDrawable", 87cdc920a0Smrg "GLXBadWindow", 88af69d88dSmrg "GLXBadProfileARB", 89cdc920a0Smrg}; 90cdc920a0Smrg 91cdc920a0Smrg#ifdef GLX_USE_APPLEGL 92cdc920a0Smrgstatic char *__glXErrorString(Display *dpy, int code, XExtCodes *codes, 93cdc920a0Smrg char *buf, int n); 94cdc920a0Smrg#endif 95cdc920a0Smrg 96cdc920a0Smrgstatic 97cdc920a0SmrgXEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName, 98cdc920a0Smrg __GLX_NUMBER_ERRORS, error_list) 99cdc920a0Smrg 100cdc920a0Smrg/* 101cdc920a0Smrg * GLX events are a bit funky. We don't stuff the X event code into 102cdc920a0Smrg * our user exposed (via XNextEvent) structure. Instead we use the GLX 103cdc920a0Smrg * private event code namespace (and hope it doesn't conflict). Clients 104cdc920a0Smrg * have to know that bit 15 in the event type field means they're getting 105cdc920a0Smrg * a GLX event, and then handle the various sub-event types there, rather 106cdc920a0Smrg * than simply checking the event code and handling it directly. 107cdc920a0Smrg */ 108cdc920a0Smrg 109cdc920a0Smrgstatic Bool 110cdc920a0Smrg__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) 111cdc920a0Smrg{ 1123464ebd5Sriastradh struct glx_display *glx_dpy = __glXInitialize(dpy); 113cdc920a0Smrg 1143464ebd5Sriastradh if (glx_dpy == NULL) 1153464ebd5Sriastradh return False; 116cdc920a0Smrg 1173464ebd5Sriastradh switch ((wire->u.u.type & 0x7f) - glx_dpy->codes->first_event) { 118cdc920a0Smrg case GLX_PbufferClobber: 119cdc920a0Smrg { 120cdc920a0Smrg GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event; 121cdc920a0Smrg xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire; 122cdc920a0Smrg aevent->event_type = awire->type; 123cdc920a0Smrg aevent->serial = awire->sequenceNumber; 124cdc920a0Smrg aevent->event_type = awire->event_type; 125cdc920a0Smrg aevent->draw_type = awire->draw_type; 126cdc920a0Smrg aevent->drawable = awire->drawable; 127cdc920a0Smrg aevent->buffer_mask = awire->buffer_mask; 128cdc920a0Smrg aevent->aux_buffer = awire->aux_buffer; 129cdc920a0Smrg aevent->x = awire->x; 130cdc920a0Smrg aevent->y = awire->y; 131cdc920a0Smrg aevent->width = awire->width; 132cdc920a0Smrg aevent->height = awire->height; 133cdc920a0Smrg aevent->count = awire->count; 134cdc920a0Smrg return True; 135cdc920a0Smrg } 136cdc920a0Smrg case GLX_BufferSwapComplete: 137cdc920a0Smrg { 138cdc920a0Smrg GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; 139af69d88dSmrg xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire; 140af69d88dSmrg struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable); 141af69d88dSmrg 142af69d88dSmrg if (!glxDraw) 143af69d88dSmrg return False; 144af69d88dSmrg 14501e04c3fSmrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 14601e04c3fSmrg aevent->send_event = (awire->type & 0x80) != 0; 14701e04c3fSmrg aevent->display = dpy; 148cdc920a0Smrg aevent->event_type = awire->event_type; 149af69d88dSmrg aevent->drawable = glxDraw->xDrawable; 150cdc920a0Smrg aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; 151cdc920a0Smrg aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; 152af69d88dSmrg 15301e04c3fSmrg /* Handle 32-Bit wire sbc wraparound in both directions to cope with out 15401e04c3fSmrg * of sequence 64-Bit sbc's 15501e04c3fSmrg */ 15601e04c3fSmrg if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000)) 15701e04c3fSmrg glxDraw->eventSbcWrap += 0x100000000; 15801e04c3fSmrg if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000)) 15901e04c3fSmrg glxDraw->eventSbcWrap -= 0x100000000; 160af69d88dSmrg glxDraw->lastEventSbc = awire->sbc; 161af69d88dSmrg aevent->sbc = awire->sbc + glxDraw->eventSbcWrap; 162cdc920a0Smrg return True; 163cdc920a0Smrg } 164cdc920a0Smrg default: 165cdc920a0Smrg /* client doesn't support server event */ 166cdc920a0Smrg break; 167cdc920a0Smrg } 168cdc920a0Smrg 169cdc920a0Smrg return False; 170cdc920a0Smrg} 171cdc920a0Smrg 172cdc920a0Smrg/* We don't actually support this. It doesn't make sense for clients to 173cdc920a0Smrg * send each other GLX events. 174cdc920a0Smrg */ 175cdc920a0Smrgstatic Status 176cdc920a0Smrg__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire) 177cdc920a0Smrg{ 1783464ebd5Sriastradh struct glx_display *glx_dpy = __glXInitialize(dpy); 179cdc920a0Smrg 1803464ebd5Sriastradh if (glx_dpy == NULL) 1813464ebd5Sriastradh return False; 182cdc920a0Smrg 183cdc920a0Smrg switch (event->type) { 184cdc920a0Smrg case GLX_DAMAGED: 185cdc920a0Smrg break; 186cdc920a0Smrg case GLX_SAVED: 187cdc920a0Smrg break; 188cdc920a0Smrg case GLX_EXCHANGE_COMPLETE_INTEL: 189cdc920a0Smrg break; 190cdc920a0Smrg case GLX_COPY_COMPLETE_INTEL: 191cdc920a0Smrg break; 192cdc920a0Smrg case GLX_FLIP_COMPLETE_INTEL: 193cdc920a0Smrg break; 194cdc920a0Smrg default: 195cdc920a0Smrg /* client doesn't support server event */ 196cdc920a0Smrg break; 197cdc920a0Smrg } 198cdc920a0Smrg 199cdc920a0Smrg return Success; 200cdc920a0Smrg} 201cdc920a0Smrg 202cdc920a0Smrg/************************************************************************/ 203cdc920a0Smrg/* 204cdc920a0Smrg** Free the per screen configs data as well as the array of 205cdc920a0Smrg** __glXScreenConfigs. 206cdc920a0Smrg*/ 207cdc920a0Smrgstatic void 2083464ebd5SriastradhFreeScreenConfigs(struct glx_display * priv) 209cdc920a0Smrg{ 2103464ebd5Sriastradh struct glx_screen *psc; 211cdc920a0Smrg GLint i, screens; 212cdc920a0Smrg 213cdc920a0Smrg /* Free screen configuration information */ 214cdc920a0Smrg screens = ScreenCount(priv->dpy); 2153464ebd5Sriastradh for (i = 0; i < screens; i++) { 2163464ebd5Sriastradh psc = priv->screens[i]; 2173464ebd5Sriastradh glx_screen_cleanup(psc); 218cdc920a0Smrg 219cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 220cdc920a0Smrg if (psc->driScreen) { 221cdc920a0Smrg psc->driScreen->destroyScreen(psc); 2223464ebd5Sriastradh } else { 223af69d88dSmrg free(psc); 224cdc920a0Smrg } 2253464ebd5Sriastradh#else 226af69d88dSmrg free(psc); 227cdc920a0Smrg#endif 228cdc920a0Smrg } 229af69d88dSmrg free((char *) priv->screens); 2303464ebd5Sriastradh priv->screens = NULL; 231cdc920a0Smrg} 232cdc920a0Smrg 2333464ebd5Sriastradhstatic void 2343464ebd5Sriastradhglx_display_free(struct glx_display *priv) 235cdc920a0Smrg{ 2363464ebd5Sriastradh struct glx_context *gc; 2373464ebd5Sriastradh 2383464ebd5Sriastradh gc = __glXGetCurrentContext(); 2393464ebd5Sriastradh if (priv->dpy == gc->currentDpy) { 2403464ebd5Sriastradh gc->vtable->destroy(gc); 2413464ebd5Sriastradh __glXSetCurrentContextNull(); 2423464ebd5Sriastradh } 243cdc920a0Smrg 244cdc920a0Smrg FreeScreenConfigs(priv); 245af69d88dSmrg free((char *) priv->serverGLXvendor); 246af69d88dSmrg free((char *) priv->serverGLXversion); 247af69d88dSmrg 248af69d88dSmrg __glxHashDestroy(priv->glXDrawHash); 249cdc920a0Smrg 250cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2513464ebd5Sriastradh __glxHashDestroy(priv->drawHash); 2523464ebd5Sriastradh 253cdc920a0Smrg /* Free the direct rendering per display data */ 254cdc920a0Smrg if (priv->driswDisplay) 255cdc920a0Smrg (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay); 256cdc920a0Smrg priv->driswDisplay = NULL; 257cdc920a0Smrg 258af69d88dSmrg#if defined (GLX_USE_DRM) 259cdc920a0Smrg if (priv->driDisplay) 260cdc920a0Smrg (*priv->driDisplay->destroyDisplay) (priv->driDisplay); 261cdc920a0Smrg priv->driDisplay = NULL; 262cdc920a0Smrg 263cdc920a0Smrg if (priv->dri2Display) 264cdc920a0Smrg (*priv->dri2Display->destroyDisplay) (priv->dri2Display); 265cdc920a0Smrg priv->dri2Display = NULL; 266cdc920a0Smrg 267af69d88dSmrg if (priv->dri3Display) 268af69d88dSmrg (*priv->dri3Display->destroyDisplay) (priv->dri3Display); 269af69d88dSmrg priv->dri3Display = NULL; 270af69d88dSmrg#endif /* GLX_USE_DRM */ 27101e04c3fSmrg 27201e04c3fSmrg#if defined(GLX_USE_WINDOWSGL) 27301e04c3fSmrg if (priv->windowsdriDisplay) 27401e04c3fSmrg (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay); 27501e04c3fSmrg priv->windowsdriDisplay = NULL; 27601e04c3fSmrg#endif /* GLX_USE_WINDOWSGL */ 27701e04c3fSmrg 278af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ 279af69d88dSmrg 280af69d88dSmrg free((char *) priv); 281cdc920a0Smrg} 282cdc920a0Smrg 2833464ebd5Sriastradhstatic int 2843464ebd5Sriastradh__glXCloseDisplay(Display * dpy, XExtCodes * codes) 2853464ebd5Sriastradh{ 2863464ebd5Sriastradh struct glx_display *priv, **prev; 2873464ebd5Sriastradh 2883464ebd5Sriastradh _XLockMutex(_Xglobal_lock); 2893464ebd5Sriastradh prev = &glx_displays; 2903464ebd5Sriastradh for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) { 2913464ebd5Sriastradh if (priv->dpy == dpy) { 2923464ebd5Sriastradh *prev = priv->next; 2933464ebd5Sriastradh break; 2943464ebd5Sriastradh } 2953464ebd5Sriastradh } 2963464ebd5Sriastradh _XUnlockMutex(_Xglobal_lock); 2973464ebd5Sriastradh 298af69d88dSmrg if (priv != NULL) 299af69d88dSmrg glx_display_free(priv); 3003464ebd5Sriastradh 3013464ebd5Sriastradh return 1; 3023464ebd5Sriastradh} 303cdc920a0Smrg 304cdc920a0Smrg/* 305cdc920a0Smrg** Query the version of the GLX extension. This procedure works even if 306cdc920a0Smrg** the client extension is not completely set up. 307cdc920a0Smrg*/ 308cdc920a0Smrgstatic Bool 309cdc920a0SmrgQueryVersion(Display * dpy, int opcode, int *major, int *minor) 310cdc920a0Smrg{ 311cdc920a0Smrg xcb_connection_t *c = XGetXCBConnection(dpy); 312cdc920a0Smrg xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c, 313cdc920a0Smrg xcb_glx_query_version 314cdc920a0Smrg (c, 315cdc920a0Smrg GLX_MAJOR_VERSION, 316cdc920a0Smrg GLX_MINOR_VERSION), 317cdc920a0Smrg NULL); 318cdc920a0Smrg 319af69d88dSmrg if (!reply) 320af69d88dSmrg return GL_FALSE; 321af69d88dSmrg 322cdc920a0Smrg if (reply->major_version != GLX_MAJOR_VERSION) { 323cdc920a0Smrg free(reply); 324cdc920a0Smrg return GL_FALSE; 325cdc920a0Smrg } 326cdc920a0Smrg *major = reply->major_version; 327cdc920a0Smrg *minor = min(reply->minor_version, GLX_MINOR_VERSION); 328cdc920a0Smrg free(reply); 329cdc920a0Smrg return GL_TRUE; 330cdc920a0Smrg} 331cdc920a0Smrg 332cdc920a0Smrg/* 333cdc920a0Smrg * We don't want to enable this GLX_OML_swap_method in glxext.h, 334cdc920a0Smrg * because we can't support it. The X server writes it out though, 335cdc920a0Smrg * so we should handle it somehow, to avoid false warnings. 336cdc920a0Smrg */ 337cdc920a0Smrgenum { 338cdc920a0Smrg IGNORE_GLX_SWAP_METHOD_OML = 0x8060 339cdc920a0Smrg}; 340cdc920a0Smrg 341cdc920a0Smrg 3423464ebd5Sriastradhstatic GLint 3433464ebd5Sriastradhconvert_from_x_visual_type(int visualType) 3443464ebd5Sriastradh{ 3453464ebd5Sriastradh static const int glx_visual_types[] = { 34601e04c3fSmrg [StaticGray] = GLX_STATIC_GRAY, 34701e04c3fSmrg [GrayScale] = GLX_GRAY_SCALE, 34801e04c3fSmrg [StaticColor] = GLX_STATIC_COLOR, 34901e04c3fSmrg [PseudoColor] = GLX_PSEUDO_COLOR, 35001e04c3fSmrg [TrueColor] = GLX_TRUE_COLOR, 35101e04c3fSmrg [DirectColor] = GLX_DIRECT_COLOR, 3523464ebd5Sriastradh }; 3533464ebd5Sriastradh 3543464ebd5Sriastradh if (visualType < ARRAY_SIZE(glx_visual_types)) 3553464ebd5Sriastradh return glx_visual_types[visualType]; 3563464ebd5Sriastradh 3573464ebd5Sriastradh return GLX_NONE; 3583464ebd5Sriastradh} 3593464ebd5Sriastradh 360cdc920a0Smrg/* 361cdc920a0Smrg * getVisualConfigs uses the !tagged_only path. 362cdc920a0Smrg * getFBConfigs uses the tagged_only path. 363cdc920a0Smrg */ 364cdc920a0Smrg_X_HIDDEN void 3653464ebd5Sriastradh__glXInitializeVisualConfigFromTags(struct glx_config * config, int count, 366cdc920a0Smrg const INT32 * bp, Bool tagged_only, 367cdc920a0Smrg Bool fbconfig_style_tags) 368cdc920a0Smrg{ 369cdc920a0Smrg int i; 370af69d88dSmrg GLint renderType = 0; 371cdc920a0Smrg 372cdc920a0Smrg if (!tagged_only) { 373cdc920a0Smrg /* Copy in the first set of properties */ 374cdc920a0Smrg config->visualID = *bp++; 375cdc920a0Smrg 3763464ebd5Sriastradh config->visualType = convert_from_x_visual_type(*bp++); 377cdc920a0Smrg 378cdc920a0Smrg config->rgbMode = *bp++; 379cdc920a0Smrg 380cdc920a0Smrg config->redBits = *bp++; 381cdc920a0Smrg config->greenBits = *bp++; 382cdc920a0Smrg config->blueBits = *bp++; 383cdc920a0Smrg config->alphaBits = *bp++; 384cdc920a0Smrg config->accumRedBits = *bp++; 385cdc920a0Smrg config->accumGreenBits = *bp++; 386cdc920a0Smrg config->accumBlueBits = *bp++; 387cdc920a0Smrg config->accumAlphaBits = *bp++; 388cdc920a0Smrg 389cdc920a0Smrg config->doubleBufferMode = *bp++; 390cdc920a0Smrg config->stereoMode = *bp++; 391cdc920a0Smrg 392cdc920a0Smrg config->rgbBits = *bp++; 393cdc920a0Smrg config->depthBits = *bp++; 394cdc920a0Smrg config->stencilBits = *bp++; 395cdc920a0Smrg config->numAuxBuffers = *bp++; 396cdc920a0Smrg config->level = *bp++; 397cdc920a0Smrg 398cdc920a0Smrg#ifdef GLX_USE_APPLEGL 399cdc920a0Smrg /* AppleSGLX supports pixmap and pbuffers with all config. */ 400cdc920a0Smrg config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 401cdc920a0Smrg /* Unfortunately this can create an ABI compatibility problem. */ 402cdc920a0Smrg count -= 18; 403cdc920a0Smrg#else 404cdc920a0Smrg count -= __GLX_MIN_CONFIG_PROPS; 405cdc920a0Smrg#endif 406cdc920a0Smrg } 407cdc920a0Smrg 408cdc920a0Smrg /* 409cdc920a0Smrg ** Additional properties may be in a list at the end 410cdc920a0Smrg ** of the reply. They are in pairs of property type 411cdc920a0Smrg ** and property value. 412cdc920a0Smrg */ 413cdc920a0Smrg 414cdc920a0Smrg#define FETCH_OR_SET(tag) \ 415cdc920a0Smrg config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1 416cdc920a0Smrg 417cdc920a0Smrg for (i = 0; i < count; i += 2) { 418cdc920a0Smrg long int tag = *bp++; 419cdc920a0Smrg 420cdc920a0Smrg switch (tag) { 421cdc920a0Smrg case GLX_RGBA: 422cdc920a0Smrg FETCH_OR_SET(rgbMode); 423cdc920a0Smrg break; 424cdc920a0Smrg case GLX_BUFFER_SIZE: 425cdc920a0Smrg config->rgbBits = *bp++; 426cdc920a0Smrg break; 427cdc920a0Smrg case GLX_LEVEL: 428cdc920a0Smrg config->level = *bp++; 429cdc920a0Smrg break; 430cdc920a0Smrg case GLX_DOUBLEBUFFER: 431cdc920a0Smrg FETCH_OR_SET(doubleBufferMode); 432cdc920a0Smrg break; 433cdc920a0Smrg case GLX_STEREO: 434cdc920a0Smrg FETCH_OR_SET(stereoMode); 435cdc920a0Smrg break; 436cdc920a0Smrg case GLX_AUX_BUFFERS: 437cdc920a0Smrg config->numAuxBuffers = *bp++; 438cdc920a0Smrg break; 439cdc920a0Smrg case GLX_RED_SIZE: 440cdc920a0Smrg config->redBits = *bp++; 441cdc920a0Smrg break; 442cdc920a0Smrg case GLX_GREEN_SIZE: 443cdc920a0Smrg config->greenBits = *bp++; 444cdc920a0Smrg break; 445cdc920a0Smrg case GLX_BLUE_SIZE: 446cdc920a0Smrg config->blueBits = *bp++; 447cdc920a0Smrg break; 448cdc920a0Smrg case GLX_ALPHA_SIZE: 449cdc920a0Smrg config->alphaBits = *bp++; 450cdc920a0Smrg break; 451cdc920a0Smrg case GLX_DEPTH_SIZE: 452cdc920a0Smrg config->depthBits = *bp++; 453cdc920a0Smrg break; 454cdc920a0Smrg case GLX_STENCIL_SIZE: 455cdc920a0Smrg config->stencilBits = *bp++; 456cdc920a0Smrg break; 457cdc920a0Smrg case GLX_ACCUM_RED_SIZE: 458cdc920a0Smrg config->accumRedBits = *bp++; 459cdc920a0Smrg break; 460cdc920a0Smrg case GLX_ACCUM_GREEN_SIZE: 461cdc920a0Smrg config->accumGreenBits = *bp++; 462cdc920a0Smrg break; 463cdc920a0Smrg case GLX_ACCUM_BLUE_SIZE: 464cdc920a0Smrg config->accumBlueBits = *bp++; 465cdc920a0Smrg break; 466cdc920a0Smrg case GLX_ACCUM_ALPHA_SIZE: 467cdc920a0Smrg config->accumAlphaBits = *bp++; 468cdc920a0Smrg break; 469cdc920a0Smrg case GLX_VISUAL_CAVEAT_EXT: 470cdc920a0Smrg config->visualRating = *bp++; 471cdc920a0Smrg break; 472cdc920a0Smrg case GLX_X_VISUAL_TYPE: 473cdc920a0Smrg config->visualType = *bp++; 474cdc920a0Smrg break; 475cdc920a0Smrg case GLX_TRANSPARENT_TYPE: 476cdc920a0Smrg config->transparentPixel = *bp++; 477cdc920a0Smrg break; 478cdc920a0Smrg case GLX_TRANSPARENT_INDEX_VALUE: 479cdc920a0Smrg config->transparentIndex = *bp++; 480cdc920a0Smrg break; 481cdc920a0Smrg case GLX_TRANSPARENT_RED_VALUE: 482cdc920a0Smrg config->transparentRed = *bp++; 483cdc920a0Smrg break; 484cdc920a0Smrg case GLX_TRANSPARENT_GREEN_VALUE: 485cdc920a0Smrg config->transparentGreen = *bp++; 486cdc920a0Smrg break; 487cdc920a0Smrg case GLX_TRANSPARENT_BLUE_VALUE: 488cdc920a0Smrg config->transparentBlue = *bp++; 489cdc920a0Smrg break; 490cdc920a0Smrg case GLX_TRANSPARENT_ALPHA_VALUE: 491cdc920a0Smrg config->transparentAlpha = *bp++; 492cdc920a0Smrg break; 493cdc920a0Smrg case GLX_VISUAL_ID: 494cdc920a0Smrg config->visualID = *bp++; 495cdc920a0Smrg break; 496cdc920a0Smrg case GLX_DRAWABLE_TYPE: 497cdc920a0Smrg config->drawableType = *bp++; 498cdc920a0Smrg#ifdef GLX_USE_APPLEGL 499cdc920a0Smrg /* AppleSGLX supports pixmap and pbuffers with all config. */ 500cdc920a0Smrg config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 501cdc920a0Smrg#endif 502cdc920a0Smrg break; 503af69d88dSmrg case GLX_RENDER_TYPE: /* fbconfig render type bits */ 504af69d88dSmrg renderType = *bp++; 505cdc920a0Smrg break; 506cdc920a0Smrg case GLX_X_RENDERABLE: 507cdc920a0Smrg config->xRenderable = *bp++; 508cdc920a0Smrg break; 509cdc920a0Smrg case GLX_FBCONFIG_ID: 510cdc920a0Smrg config->fbconfigID = *bp++; 511cdc920a0Smrg break; 512cdc920a0Smrg case GLX_MAX_PBUFFER_WIDTH: 513cdc920a0Smrg config->maxPbufferWidth = *bp++; 514cdc920a0Smrg break; 515cdc920a0Smrg case GLX_MAX_PBUFFER_HEIGHT: 516cdc920a0Smrg config->maxPbufferHeight = *bp++; 517cdc920a0Smrg break; 518cdc920a0Smrg case GLX_MAX_PBUFFER_PIXELS: 519cdc920a0Smrg config->maxPbufferPixels = *bp++; 520cdc920a0Smrg break; 521cdc920a0Smrg#ifndef GLX_USE_APPLEGL 522cdc920a0Smrg case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: 523cdc920a0Smrg config->optimalPbufferWidth = *bp++; 524cdc920a0Smrg break; 525cdc920a0Smrg case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: 526cdc920a0Smrg config->optimalPbufferHeight = *bp++; 527cdc920a0Smrg break; 528cdc920a0Smrg case GLX_VISUAL_SELECT_GROUP_SGIX: 529cdc920a0Smrg config->visualSelectGroup = *bp++; 530cdc920a0Smrg break; 531cdc920a0Smrg case GLX_SWAP_METHOD_OML: 53201e04c3fSmrg if (*bp == GLX_SWAP_UNDEFINED_OML || 53301e04c3fSmrg *bp == GLX_SWAP_COPY_OML || 53401e04c3fSmrg *bp == GLX_SWAP_EXCHANGE_OML) { 53501e04c3fSmrg config->swapMethod = *bp++; 53601e04c3fSmrg } else { 53701e04c3fSmrg /* X servers with old HW drivers may return any value here, so 53801e04c3fSmrg * assume GLX_SWAP_METHOD_UNDEFINED. 53901e04c3fSmrg */ 54001e04c3fSmrg config->swapMethod = GLX_SWAP_UNDEFINED_OML; 54101e04c3fSmrg bp++; 54201e04c3fSmrg } 543cdc920a0Smrg break; 544cdc920a0Smrg#endif 545cdc920a0Smrg case GLX_SAMPLE_BUFFERS_SGIS: 546cdc920a0Smrg config->sampleBuffers = *bp++; 547cdc920a0Smrg break; 548cdc920a0Smrg case GLX_SAMPLES_SGIS: 549cdc920a0Smrg config->samples = *bp++; 550cdc920a0Smrg break; 551cdc920a0Smrg#ifdef GLX_USE_APPLEGL 552cdc920a0Smrg case IGNORE_GLX_SWAP_METHOD_OML: 553cdc920a0Smrg /* We ignore this tag. See the comment above this function. */ 554cdc920a0Smrg ++bp; 555cdc920a0Smrg break; 556cdc920a0Smrg#else 557cdc920a0Smrg case GLX_BIND_TO_TEXTURE_RGB_EXT: 558cdc920a0Smrg config->bindToTextureRgb = *bp++; 559cdc920a0Smrg break; 560cdc920a0Smrg case GLX_BIND_TO_TEXTURE_RGBA_EXT: 561cdc920a0Smrg config->bindToTextureRgba = *bp++; 562cdc920a0Smrg break; 563cdc920a0Smrg case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 564cdc920a0Smrg config->bindToMipmapTexture = *bp++; 565cdc920a0Smrg break; 566cdc920a0Smrg case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 567cdc920a0Smrg config->bindToTextureTargets = *bp++; 568cdc920a0Smrg break; 569cdc920a0Smrg case GLX_Y_INVERTED_EXT: 570cdc920a0Smrg config->yInverted = *bp++; 571cdc920a0Smrg break; 572cdc920a0Smrg#endif 5733464ebd5Sriastradh case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT: 5743464ebd5Sriastradh config->sRGBCapable = *bp++; 5753464ebd5Sriastradh break; 5763464ebd5Sriastradh 577cdc920a0Smrg case GLX_USE_GL: 578cdc920a0Smrg if (fbconfig_style_tags) 579cdc920a0Smrg bp++; 580cdc920a0Smrg break; 581cdc920a0Smrg case None: 582cdc920a0Smrg i = count; 583cdc920a0Smrg break; 584cdc920a0Smrg default: 58501e04c3fSmrg if(env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) { 586cdc920a0Smrg long int tagvalue = *bp++; 587cdc920a0Smrg fprintf(stderr, "WARNING: unknown GLX tag from server: " 588cdc920a0Smrg "tag 0x%lx value 0x%lx\n", tag, tagvalue); 589cdc920a0Smrg } else { 590cdc920a0Smrg /* Ignore the unrecognized tag's value */ 591cdc920a0Smrg bp++; 592cdc920a0Smrg } 5933464ebd5Sriastradh break; 594cdc920a0Smrg } 595cdc920a0Smrg } 596cdc920a0Smrg 597af69d88dSmrg if (renderType != 0 && renderType != GLX_DONT_CARE) { 598af69d88dSmrg config->renderType = renderType; 599af69d88dSmrg config->floatMode = (renderType & 600af69d88dSmrg (GLX_RGBA_FLOAT_BIT_ARB|GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) != 0; 601af69d88dSmrg } else { 602af69d88dSmrg /* If there wasn't GLX_RENDER_TYPE property, set it based on 603af69d88dSmrg * config->rgbMode. The only way to communicate that the config is 604af69d88dSmrg * floating-point is via GLX_RENDER_TYPE, so this cannot be a float 605af69d88dSmrg * config. 606af69d88dSmrg */ 607af69d88dSmrg config->renderType = 608af69d88dSmrg (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; 609af69d88dSmrg } 610af69d88dSmrg 611af69d88dSmrg /* The GLX_ARB_fbconfig_float spec says: 612af69d88dSmrg * 613af69d88dSmrg * "Note that floating point rendering is only supported for 614af69d88dSmrg * GLXPbuffer drawables." 615af69d88dSmrg */ 616af69d88dSmrg if (config->floatMode) 61701e04c3fSmrg config->drawableType &= GLX_PBUFFER_BIT; 618cdc920a0Smrg} 619cdc920a0Smrg 6203464ebd5Sriastradhstatic struct glx_config * 621cdc920a0SmrgcreateConfigsFromProperties(Display * dpy, int nvisuals, int nprops, 622cdc920a0Smrg int screen, GLboolean tagged_only) 623cdc920a0Smrg{ 624cdc920a0Smrg INT32 buf[__GLX_TOTAL_CONFIG], *props; 625cdc920a0Smrg unsigned prop_size; 6263464ebd5Sriastradh struct glx_config *modes, *m; 627cdc920a0Smrg int i; 628cdc920a0Smrg 629cdc920a0Smrg if (nprops == 0) 630cdc920a0Smrg return NULL; 631cdc920a0Smrg 632cdc920a0Smrg /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */ 633cdc920a0Smrg 634cdc920a0Smrg /* Check number of properties */ 635cdc920a0Smrg if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS) 636cdc920a0Smrg return NULL; 637cdc920a0Smrg 638cdc920a0Smrg /* Allocate memory for our config structure */ 6393464ebd5Sriastradh modes = glx_config_create_list(nvisuals); 640cdc920a0Smrg if (!modes) 641cdc920a0Smrg return NULL; 642cdc920a0Smrg 643cdc920a0Smrg prop_size = nprops * __GLX_SIZE_INT32; 644cdc920a0Smrg if (prop_size <= sizeof(buf)) 645cdc920a0Smrg props = buf; 646cdc920a0Smrg else 647af69d88dSmrg props = malloc(prop_size); 648cdc920a0Smrg 649cdc920a0Smrg /* Read each config structure and convert it into our format */ 650cdc920a0Smrg m = modes; 651cdc920a0Smrg for (i = 0; i < nvisuals; i++) { 652cdc920a0Smrg _XRead(dpy, (char *) props, prop_size); 653cdc920a0Smrg#ifdef GLX_USE_APPLEGL 654cdc920a0Smrg /* Older X servers don't send this so we default it here. */ 655cdc920a0Smrg m->drawableType = GLX_WINDOW_BIT; 656cdc920a0Smrg#else 657cdc920a0Smrg /* 658cdc920a0Smrg * The XQuartz 2.3.2.1 X server doesn't set this properly, so 659cdc920a0Smrg * set the proper bits here. 660cdc920a0Smrg * AppleSGLX supports windows, pixmaps, and pbuffers with all config. 661cdc920a0Smrg */ 662cdc920a0Smrg m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 663cdc920a0Smrg#endif 66401e04c3fSmrg /* Older X servers don't send this so we default it here. */ 66501e04c3fSmrg m->sRGBCapable = GL_FALSE; 666cdc920a0Smrg __glXInitializeVisualConfigFromTags(m, nprops, props, 667cdc920a0Smrg tagged_only, GL_TRUE); 668cdc920a0Smrg m->screen = screen; 669cdc920a0Smrg m = m->next; 670cdc920a0Smrg } 671cdc920a0Smrg 672cdc920a0Smrg if (props != buf) 673af69d88dSmrg free(props); 674cdc920a0Smrg 675cdc920a0Smrg return modes; 676cdc920a0Smrg} 677cdc920a0Smrg 678cdc920a0Smrgstatic GLboolean 6793464ebd5SriastradhgetVisualConfigs(struct glx_screen *psc, 6803464ebd5Sriastradh struct glx_display *priv, int screen) 681cdc920a0Smrg{ 682cdc920a0Smrg xGLXGetVisualConfigsReq *req; 683cdc920a0Smrg xGLXGetVisualConfigsReply reply; 6843464ebd5Sriastradh Display *dpy = priv->dpy; 685cdc920a0Smrg 686cdc920a0Smrg LockDisplay(dpy); 687cdc920a0Smrg 688cdc920a0Smrg psc->visuals = NULL; 689cdc920a0Smrg GetReq(GLXGetVisualConfigs, req); 690cdc920a0Smrg req->reqType = priv->majorOpcode; 691cdc920a0Smrg req->glxCode = X_GLXGetVisualConfigs; 692cdc920a0Smrg req->screen = screen; 693cdc920a0Smrg 694cdc920a0Smrg if (!_XReply(dpy, (xReply *) & reply, 0, False)) 695cdc920a0Smrg goto out; 696cdc920a0Smrg 697cdc920a0Smrg psc->visuals = createConfigsFromProperties(dpy, 698cdc920a0Smrg reply.numVisuals, 699cdc920a0Smrg reply.numProps, 700cdc920a0Smrg screen, GL_FALSE); 701cdc920a0Smrg 702cdc920a0Smrg out: 703cdc920a0Smrg UnlockDisplay(dpy); 704cdc920a0Smrg return psc->visuals != NULL; 705cdc920a0Smrg} 706cdc920a0Smrg 707cdc920a0Smrgstatic GLboolean 7083464ebd5Sriastradh getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen) 709cdc920a0Smrg{ 710cdc920a0Smrg xGLXGetFBConfigsReq *fb_req; 711cdc920a0Smrg xGLXGetFBConfigsSGIXReq *sgi_req; 712cdc920a0Smrg xGLXVendorPrivateWithReplyReq *vpreq; 713cdc920a0Smrg xGLXGetFBConfigsReply reply; 7143464ebd5Sriastradh Display *dpy = priv->dpy; 715cdc920a0Smrg 716cdc920a0Smrg psc->serverGLXexts = 717cdc920a0Smrg __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); 718cdc920a0Smrg 719af69d88dSmrg if (psc->serverGLXexts == NULL) { 720af69d88dSmrg return GL_FALSE; 721af69d88dSmrg } 722af69d88dSmrg 723cdc920a0Smrg LockDisplay(dpy); 724cdc920a0Smrg 725cdc920a0Smrg psc->configs = NULL; 726cdc920a0Smrg if (atof(priv->serverGLXversion) >= 1.3) { 727cdc920a0Smrg GetReq(GLXGetFBConfigs, fb_req); 728cdc920a0Smrg fb_req->reqType = priv->majorOpcode; 729cdc920a0Smrg fb_req->glxCode = X_GLXGetFBConfigs; 730cdc920a0Smrg fb_req->screen = screen; 731cdc920a0Smrg } 732cdc920a0Smrg else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { 733cdc920a0Smrg GetReqExtra(GLXVendorPrivateWithReply, 7343464ebd5Sriastradh sz_xGLXGetFBConfigsSGIXReq - 735cdc920a0Smrg sz_xGLXVendorPrivateWithReplyReq, vpreq); 736cdc920a0Smrg sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; 737cdc920a0Smrg sgi_req->reqType = priv->majorOpcode; 738cdc920a0Smrg sgi_req->glxCode = X_GLXVendorPrivateWithReply; 739cdc920a0Smrg sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; 740cdc920a0Smrg sgi_req->screen = screen; 741cdc920a0Smrg } 742cdc920a0Smrg else 743cdc920a0Smrg goto out; 744cdc920a0Smrg 745cdc920a0Smrg if (!_XReply(dpy, (xReply *) & reply, 0, False)) 746cdc920a0Smrg goto out; 747cdc920a0Smrg 748cdc920a0Smrg psc->configs = createConfigsFromProperties(dpy, 749cdc920a0Smrg reply.numFBConfigs, 750cdc920a0Smrg reply.numAttribs * 2, 751cdc920a0Smrg screen, GL_TRUE); 752cdc920a0Smrg 753cdc920a0Smrg out: 754cdc920a0Smrg UnlockDisplay(dpy); 755cdc920a0Smrg return psc->configs != NULL; 756cdc920a0Smrg} 757cdc920a0Smrg 7583464ebd5Sriastradh_X_HIDDEN Bool 7593464ebd5Sriastradhglx_screen_init(struct glx_screen *psc, 7603464ebd5Sriastradh int screen, struct glx_display * priv) 7613464ebd5Sriastradh{ 7623464ebd5Sriastradh /* Initialize per screen dynamic client GLX extensions */ 7633464ebd5Sriastradh psc->ext_list_first_time = GL_TRUE; 7643464ebd5Sriastradh psc->scr = screen; 7653464ebd5Sriastradh psc->dpy = priv->dpy; 7663464ebd5Sriastradh psc->display = priv; 7673464ebd5Sriastradh 76801e04c3fSmrg if (!getVisualConfigs(psc, priv, screen)) 76901e04c3fSmrg return GL_FALSE; 77001e04c3fSmrg 77101e04c3fSmrg if (!getFBConfigs(psc, priv, screen)) 77201e04c3fSmrg return GL_FALSE; 7733464ebd5Sriastradh 7743464ebd5Sriastradh return GL_TRUE; 7753464ebd5Sriastradh} 7763464ebd5Sriastradh 7773464ebd5Sriastradh_X_HIDDEN void 7783464ebd5Sriastradhglx_screen_cleanup(struct glx_screen *psc) 7793464ebd5Sriastradh{ 7803464ebd5Sriastradh if (psc->configs) { 7813464ebd5Sriastradh glx_config_destroy_list(psc->configs); 782af69d88dSmrg free(psc->effectiveGLXexts); 7833464ebd5Sriastradh psc->configs = NULL; /* NOTE: just for paranoia */ 7843464ebd5Sriastradh } 7853464ebd5Sriastradh if (psc->visuals) { 7863464ebd5Sriastradh glx_config_destroy_list(psc->visuals); 7873464ebd5Sriastradh psc->visuals = NULL; /* NOTE: just for paranoia */ 7883464ebd5Sriastradh } 789af69d88dSmrg free((char *) psc->serverGLXexts); 7903464ebd5Sriastradh} 7913464ebd5Sriastradh 792cdc920a0Smrg/* 793cdc920a0Smrg** Allocate the memory for the per screen configs for each screen. 794cdc920a0Smrg** If that works then fetch the per screen configs data. 795cdc920a0Smrg*/ 796cdc920a0Smrgstatic Bool 7973464ebd5SriastradhAllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv) 798cdc920a0Smrg{ 7993464ebd5Sriastradh struct glx_screen *psc; 800cdc920a0Smrg GLint i, screens; 801cdc920a0Smrg 802cdc920a0Smrg /* 803cdc920a0Smrg ** First allocate memory for the array of per screen configs. 804cdc920a0Smrg */ 805cdc920a0Smrg screens = ScreenCount(dpy); 806af69d88dSmrg priv->screens = malloc(screens * sizeof *priv->screens); 8073464ebd5Sriastradh if (!priv->screens) 808cdc920a0Smrg return GL_FALSE; 809cdc920a0Smrg 810cdc920a0Smrg priv->serverGLXversion = 811cdc920a0Smrg __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); 812cdc920a0Smrg if (priv->serverGLXversion == NULL) { 813cdc920a0Smrg FreeScreenConfigs(priv); 814cdc920a0Smrg return GL_FALSE; 815cdc920a0Smrg } 816cdc920a0Smrg 817cdc920a0Smrg for (i = 0; i < screens; i++, psc++) { 8183464ebd5Sriastradh psc = NULL; 819cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 820af69d88dSmrg#if defined(GLX_USE_DRM) 821af69d88dSmrg#if defined(HAVE_DRI3) 822af69d88dSmrg if (priv->dri3Display) 823af69d88dSmrg psc = (*priv->dri3Display->createScreen) (i, priv); 824af69d88dSmrg#endif /* HAVE_DRI3 */ 825af69d88dSmrg if (psc == NULL && priv->dri2Display) 8263464ebd5Sriastradh psc = (*priv->dri2Display->createScreen) (i, priv); 8273464ebd5Sriastradh if (psc == NULL && priv->driDisplay) 8283464ebd5Sriastradh psc = (*priv->driDisplay->createScreen) (i, priv); 829af69d88dSmrg#endif /* GLX_USE_DRM */ 83001e04c3fSmrg 83101e04c3fSmrg#ifdef GLX_USE_WINDOWSGL 83201e04c3fSmrg if (psc == NULL && priv->windowsdriDisplay) 83301e04c3fSmrg psc = (*priv->windowsdriDisplay->createScreen) (i, priv); 83401e04c3fSmrg#endif 83501e04c3fSmrg 8363464ebd5Sriastradh if (psc == NULL && priv->driswDisplay) 8373464ebd5Sriastradh psc = (*priv->driswDisplay->createScreen) (i, priv); 838af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ 839af69d88dSmrg 8403464ebd5Sriastradh#if defined(GLX_USE_APPLEGL) 8413464ebd5Sriastradh if (psc == NULL) 8423464ebd5Sriastradh psc = applegl_create_screen(i, priv); 8433464ebd5Sriastradh#else 8443464ebd5Sriastradh if (psc == NULL) 8453464ebd5Sriastradh psc = indirect_create_screen(i, priv); 8463464ebd5Sriastradh#endif 8473464ebd5Sriastradh priv->screens[i] = psc; 848cdc920a0Smrg } 849cdc920a0Smrg SyncHandle(); 850cdc920a0Smrg return GL_TRUE; 851cdc920a0Smrg} 852cdc920a0Smrg 853cdc920a0Smrg/* 854cdc920a0Smrg** Initialize the client side extension code. 855cdc920a0Smrg*/ 8563464ebd5Sriastradh _X_HIDDEN struct glx_display * 857cdc920a0Smrg__glXInitialize(Display * dpy) 858cdc920a0Smrg{ 8593464ebd5Sriastradh struct glx_display *dpyPriv, *d; 860cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 861cdc920a0Smrg Bool glx_direct, glx_accel; 862cdc920a0Smrg#endif 8633464ebd5Sriastradh int i; 864cdc920a0Smrg 8653464ebd5Sriastradh _XLockMutex(_Xglobal_lock); 866cdc920a0Smrg 8673464ebd5Sriastradh for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) { 8683464ebd5Sriastradh if (dpyPriv->dpy == dpy) { 8693464ebd5Sriastradh _XUnlockMutex(_Xglobal_lock); 8703464ebd5Sriastradh return dpyPriv; 8713464ebd5Sriastradh } 872cdc920a0Smrg } 873cdc920a0Smrg 8743464ebd5Sriastradh /* Drop the lock while we create the display private. */ 8753464ebd5Sriastradh _XUnlockMutex(_Xglobal_lock); 876cdc920a0Smrg 877af69d88dSmrg dpyPriv = calloc(1, sizeof *dpyPriv); 8783464ebd5Sriastradh if (!dpyPriv) 8793464ebd5Sriastradh return NULL; 880cdc920a0Smrg 8813464ebd5Sriastradh dpyPriv->codes = XInitExtension(dpy, __glXExtensionName); 8823464ebd5Sriastradh if (!dpyPriv->codes) { 883af69d88dSmrg free(dpyPriv); 8843464ebd5Sriastradh return NULL; 885cdc920a0Smrg } 886cdc920a0Smrg 887cdc920a0Smrg dpyPriv->dpy = dpy; 8883464ebd5Sriastradh dpyPriv->majorOpcode = dpyPriv->codes->major_opcode; 889cdc920a0Smrg dpyPriv->serverGLXvendor = 0x0; 890cdc920a0Smrg dpyPriv->serverGLXversion = 0x0; 891cdc920a0Smrg 892af69d88dSmrg /* See if the versions are compatible. This GLX implementation does not 893af69d88dSmrg * work with servers that only support GLX 1.0. 894af69d88dSmrg */ 8953464ebd5Sriastradh if (!QueryVersion(dpy, dpyPriv->majorOpcode, 896af69d88dSmrg &dpyPriv->majorVersion, &dpyPriv->minorVersion) 897af69d88dSmrg || (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion < 1)) { 898af69d88dSmrg free(dpyPriv); 8993464ebd5Sriastradh return NULL; 9003464ebd5Sriastradh } 9013464ebd5Sriastradh 9023464ebd5Sriastradh for (i = 0; i < __GLX_NUMBER_EVENTS; i++) { 9033464ebd5Sriastradh XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent); 9043464ebd5Sriastradh XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire); 9053464ebd5Sriastradh } 9063464ebd5Sriastradh 9073464ebd5Sriastradh XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay); 9083464ebd5Sriastradh XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString); 9093464ebd5Sriastradh 910af69d88dSmrg dpyPriv->glXDrawHash = __glxHashCreate(); 911af69d88dSmrg 912cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 91301e04c3fSmrg glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false); 91401e04c3fSmrg glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false); 915cdc920a0Smrg 9163464ebd5Sriastradh dpyPriv->drawHash = __glxHashCreate(); 9173464ebd5Sriastradh 918cdc920a0Smrg /* 919cdc920a0Smrg ** Initialize the direct rendering per display data and functions. 920cdc920a0Smrg ** Note: This _must_ be done before calling any other DRI routines 921cdc920a0Smrg ** (e.g., those called in AllocAndFetchScreenConfigs). 922cdc920a0Smrg */ 923af69d88dSmrg#if defined(GLX_USE_DRM) 924cdc920a0Smrg if (glx_direct && glx_accel) { 925af69d88dSmrg#if defined(HAVE_DRI3) 92601e04c3fSmrg if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false)) 927af69d88dSmrg dpyPriv->dri3Display = dri3_create_display(dpy); 928af69d88dSmrg#endif /* HAVE_DRI3 */ 929cdc920a0Smrg dpyPriv->dri2Display = dri2CreateDisplay(dpy); 930cdc920a0Smrg dpyPriv->driDisplay = driCreateDisplay(dpy); 931cdc920a0Smrg } 932af69d88dSmrg#endif /* GLX_USE_DRM */ 933cdc920a0Smrg if (glx_direct) 934cdc920a0Smrg dpyPriv->driswDisplay = driswCreateDisplay(dpy); 935af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ 9363464ebd5Sriastradh 937cdc920a0Smrg#ifdef GLX_USE_APPLEGL 9383464ebd5Sriastradh if (!applegl_create_display(dpyPriv)) { 939af69d88dSmrg free(dpyPriv); 9403464ebd5Sriastradh return NULL; 9413464ebd5Sriastradh } 942cdc920a0Smrg#endif 94301e04c3fSmrg 94401e04c3fSmrg#ifdef GLX_USE_WINDOWSGL 94501e04c3fSmrg if (glx_direct && glx_accel) 94601e04c3fSmrg dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy); 94701e04c3fSmrg#endif 94801e04c3fSmrg 9493464ebd5Sriastradh if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { 950af69d88dSmrg free(dpyPriv); 9513464ebd5Sriastradh return NULL; 952cdc920a0Smrg } 953cdc920a0Smrg 954af69d88dSmrg __glX_send_client_info(dpyPriv); 9553464ebd5Sriastradh 9563464ebd5Sriastradh /* Grab the lock again and add the dispay private, unless somebody 9573464ebd5Sriastradh * beat us to initializing on this display in the meantime. */ 9583464ebd5Sriastradh _XLockMutex(_Xglobal_lock); 9593464ebd5Sriastradh 9603464ebd5Sriastradh for (d = glx_displays; d; d = d->next) { 9613464ebd5Sriastradh if (d->dpy == dpy) { 9623464ebd5Sriastradh _XUnlockMutex(_Xglobal_lock); 9633464ebd5Sriastradh glx_display_free(dpyPriv); 9643464ebd5Sriastradh return d; 9653464ebd5Sriastradh } 966cdc920a0Smrg } 9673464ebd5Sriastradh 9683464ebd5Sriastradh dpyPriv->next = glx_displays; 9693464ebd5Sriastradh glx_displays = dpyPriv; 9703464ebd5Sriastradh 971af69d88dSmrg _XUnlockMutex(_Xglobal_lock); 972cdc920a0Smrg 973cdc920a0Smrg return dpyPriv; 974cdc920a0Smrg} 975cdc920a0Smrg 976cdc920a0Smrg/* 977cdc920a0Smrg** Setup for sending a GLX command on dpy. Make sure the extension is 978cdc920a0Smrg** initialized. Try to avoid calling __glXInitialize as its kinda slow. 979cdc920a0Smrg*/ 980cdc920a0Smrg_X_HIDDEN CARD8 981cdc920a0Smrg__glXSetupForCommand(Display * dpy) 982cdc920a0Smrg{ 9833464ebd5Sriastradh struct glx_context *gc; 9843464ebd5Sriastradh struct glx_display *priv; 985cdc920a0Smrg 986cdc920a0Smrg /* If this thread has a current context, flush its rendering commands */ 987cdc920a0Smrg gc = __glXGetCurrentContext(); 988cdc920a0Smrg if (gc->currentDpy) { 989cdc920a0Smrg /* Flush rendering buffer of the current context, if any */ 990cdc920a0Smrg (void) __glXFlushRenderBuffer(gc, gc->pc); 991cdc920a0Smrg 992cdc920a0Smrg if (gc->currentDpy == dpy) { 993cdc920a0Smrg /* Use opcode from gc because its right */ 994cdc920a0Smrg return gc->majorOpcode; 995cdc920a0Smrg } 996cdc920a0Smrg else { 997cdc920a0Smrg /* 998cdc920a0Smrg ** Have to get info about argument dpy because it might be to 999cdc920a0Smrg ** a different server 1000cdc920a0Smrg */ 1001cdc920a0Smrg } 1002cdc920a0Smrg } 1003cdc920a0Smrg 1004cdc920a0Smrg /* Forced to lookup extension via the slow initialize route */ 1005cdc920a0Smrg priv = __glXInitialize(dpy); 1006cdc920a0Smrg if (!priv) { 1007cdc920a0Smrg return 0; 1008cdc920a0Smrg } 1009cdc920a0Smrg return priv->majorOpcode; 1010cdc920a0Smrg} 1011cdc920a0Smrg 1012cdc920a0Smrg/** 1013cdc920a0Smrg * Flush the drawing command transport buffer. 1014cdc920a0Smrg * 1015cdc920a0Smrg * \param ctx Context whose transport buffer is to be flushed. 1016cdc920a0Smrg * \param pc Pointer to first unused buffer location. 1017cdc920a0Smrg * 1018cdc920a0Smrg * \todo 1019cdc920a0Smrg * Modify this function to use \c ctx->pc instead of the explicit 1020cdc920a0Smrg * \c pc parameter. 1021cdc920a0Smrg */ 1022cdc920a0Smrg_X_HIDDEN GLubyte * 10233464ebd5Sriastradh__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc) 1024cdc920a0Smrg{ 1025cdc920a0Smrg Display *const dpy = ctx->currentDpy; 1026cdc920a0Smrg xcb_connection_t *c = XGetXCBConnection(dpy); 1027cdc920a0Smrg const GLint size = pc - ctx->buf; 1028cdc920a0Smrg 1029cdc920a0Smrg if ((dpy != NULL) && (size > 0)) { 1030cdc920a0Smrg xcb_glx_render(c, ctx->currentContextTag, size, 1031cdc920a0Smrg (const uint8_t *) ctx->buf); 1032cdc920a0Smrg } 1033cdc920a0Smrg 1034cdc920a0Smrg /* Reset pointer and return it */ 1035cdc920a0Smrg ctx->pc = ctx->buf; 1036cdc920a0Smrg return ctx->pc; 1037cdc920a0Smrg} 1038cdc920a0Smrg 1039cdc920a0Smrg 1040cdc920a0Smrg/** 1041cdc920a0Smrg * Send a portion of a GLXRenderLarge command to the server. The advantage of 1042cdc920a0Smrg * this function over \c __glXSendLargeCommand is that callers can use the 1043cdc920a0Smrg * data buffer in the GLX context and may be able to avoid allocating an 1044cdc920a0Smrg * extra buffer. The disadvantage is the clients will have to do more 1045cdc920a0Smrg * GLX protocol work (i.e., calculating \c totalRequests, etc.). 1046cdc920a0Smrg * 1047cdc920a0Smrg * \sa __glXSendLargeCommand 1048cdc920a0Smrg * 1049cdc920a0Smrg * \param gc GLX context 1050cdc920a0Smrg * \param requestNumber Which part of the whole command is this? The first 1051cdc920a0Smrg * request is 1. 1052cdc920a0Smrg * \param totalRequests How many requests will there be? 1053cdc920a0Smrg * \param data Command data. 1054cdc920a0Smrg * \param dataLen Size, in bytes, of the command data. 1055cdc920a0Smrg */ 1056cdc920a0Smrg_X_HIDDEN void 10573464ebd5Sriastradh__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber, 1058cdc920a0Smrg GLint totalRequests, const GLvoid * data, GLint dataLen) 1059cdc920a0Smrg{ 1060cdc920a0Smrg Display *dpy = gc->currentDpy; 1061cdc920a0Smrg xcb_connection_t *c = XGetXCBConnection(dpy); 1062cdc920a0Smrg xcb_glx_render_large(c, gc->currentContextTag, requestNumber, 1063cdc920a0Smrg totalRequests, dataLen, data); 1064cdc920a0Smrg} 1065cdc920a0Smrg 1066cdc920a0Smrg 1067cdc920a0Smrg/** 1068cdc920a0Smrg * Send a command that is too large for the GLXRender protocol request. 1069cdc920a0Smrg * 1070cdc920a0Smrg * Send a large command, one that is too large for some reason to 1071cdc920a0Smrg * send using the GLXRender protocol request. One reason to send 1072cdc920a0Smrg * a large command is to avoid copying the data. 1073cdc920a0Smrg * 1074cdc920a0Smrg * \param ctx GLX context 1075cdc920a0Smrg * \param header Header data. 1076cdc920a0Smrg * \param headerLen Size, in bytes, of the header data. It is assumed that 1077cdc920a0Smrg * the header data will always be small enough to fit in 1078cdc920a0Smrg * a single X protocol packet. 1079cdc920a0Smrg * \param data Command data. 1080cdc920a0Smrg * \param dataLen Size, in bytes, of the command data. 1081cdc920a0Smrg */ 1082cdc920a0Smrg_X_HIDDEN void 10833464ebd5Sriastradh__glXSendLargeCommand(struct glx_context * ctx, 1084cdc920a0Smrg const GLvoid * header, GLint headerLen, 1085cdc920a0Smrg const GLvoid * data, GLint dataLen) 1086cdc920a0Smrg{ 1087cdc920a0Smrg GLint maxSize; 1088cdc920a0Smrg GLint totalRequests, requestNumber; 1089cdc920a0Smrg 1090cdc920a0Smrg /* 1091cdc920a0Smrg ** Calculate the maximum amount of data can be stuffed into a single 1092cdc920a0Smrg ** packet. sz_xGLXRenderReq is added because bufSize is the maximum 1093cdc920a0Smrg ** packet size minus sz_xGLXRenderReq. 1094cdc920a0Smrg */ 1095cdc920a0Smrg maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq; 1096cdc920a0Smrg totalRequests = 1 + (dataLen / maxSize); 1097cdc920a0Smrg if (dataLen % maxSize) 1098cdc920a0Smrg totalRequests++; 1099cdc920a0Smrg 1100cdc920a0Smrg /* 1101cdc920a0Smrg ** Send all of the command, except the large array, as one request. 1102cdc920a0Smrg */ 1103cdc920a0Smrg assert(headerLen <= maxSize); 1104cdc920a0Smrg __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen); 1105cdc920a0Smrg 1106cdc920a0Smrg /* 1107cdc920a0Smrg ** Send enough requests until the whole array is sent. 1108cdc920a0Smrg */ 1109cdc920a0Smrg for (requestNumber = 2; requestNumber <= (totalRequests - 1); 1110cdc920a0Smrg requestNumber++) { 1111cdc920a0Smrg __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize); 1112cdc920a0Smrg data = (const GLvoid *) (((const GLubyte *) data) + maxSize); 1113cdc920a0Smrg dataLen -= maxSize; 1114cdc920a0Smrg assert(dataLen > 0); 1115cdc920a0Smrg } 1116cdc920a0Smrg 1117cdc920a0Smrg assert(dataLen <= maxSize); 1118cdc920a0Smrg __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen); 1119cdc920a0Smrg} 1120cdc920a0Smrg 1121cdc920a0Smrg/************************************************************************/ 1122cdc920a0Smrg 1123cdc920a0Smrg#ifdef DEBUG 1124cdc920a0Smrg_X_HIDDEN void 11253464ebd5Sriastradh__glXDumpDrawBuffer(struct glx_context * ctx) 1126cdc920a0Smrg{ 1127cdc920a0Smrg GLubyte *p = ctx->buf; 1128cdc920a0Smrg GLubyte *end = ctx->pc; 1129cdc920a0Smrg GLushort opcode, length; 1130cdc920a0Smrg 1131cdc920a0Smrg while (p < end) { 1132cdc920a0Smrg /* Fetch opcode */ 1133cdc920a0Smrg opcode = *((GLushort *) p); 1134cdc920a0Smrg length = *((GLushort *) (p + 2)); 1135cdc920a0Smrg printf("%2x: %5d: ", opcode, length); 1136cdc920a0Smrg length -= 4; 1137cdc920a0Smrg p += 4; 1138cdc920a0Smrg while (length > 0) { 1139cdc920a0Smrg printf("%08x ", *((unsigned *) p)); 1140cdc920a0Smrg p += 4; 1141cdc920a0Smrg length -= 4; 1142cdc920a0Smrg } 1143cdc920a0Smrg printf("\n"); 1144cdc920a0Smrg } 1145cdc920a0Smrg} 1146cdc920a0Smrg#endif 1147