1848b8605Smrg/* 2848b8605Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3848b8605Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. 4848b8605Smrg * 5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6848b8605Smrg * copy of this software and associated documentation files (the "Software"), 7848b8605Smrg * to deal in the Software without restriction, including without limitation 8848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 10848b8605Smrg * Software is furnished to do so, subject to the following conditions: 11848b8605Smrg * 12848b8605Smrg * The above copyright notice including the dates of first publication and 13848b8605Smrg * either this permission notice or a reference to 14848b8605Smrg * http://oss.sgi.com/projects/FreeB/ 15848b8605Smrg * shall be included in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21848b8605Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22848b8605Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23848b8605Smrg * SOFTWARE. 24848b8605Smrg * 25848b8605Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc. 26848b8605Smrg * shall not be used in advertising or otherwise to promote the sale, use or 27848b8605Smrg * other dealings in this Software without prior written authorization from 28848b8605Smrg * Silicon Graphics, Inc. 29848b8605Smrg */ 30848b8605Smrg 31848b8605Smrg/** 32848b8605Smrg * \file glxext.c 33848b8605Smrg * GLX protocol interface boot-strap code. 34848b8605Smrg * 35848b8605Smrg * Direct rendering support added by Precision Insight, Inc. 36848b8605Smrg * 37848b8605Smrg * \author Kevin E. Martin <kevin@precisioninsight.com> 38848b8605Smrg */ 39848b8605Smrg 40848b8605Smrg#include <assert.h> 41b8e80941Smrg#include <stdbool.h> 42b8e80941Smrg 43848b8605Smrg#include "glxclient.h" 44848b8605Smrg#include <X11/extensions/Xext.h> 45848b8605Smrg#include <X11/extensions/extutil.h> 46848b8605Smrg#ifdef GLX_USE_APPLEGL 47848b8605Smrg#include "apple/apple_glx.h" 48848b8605Smrg#include "apple/apple_visual.h" 49848b8605Smrg#endif 50848b8605Smrg#include "glxextensions.h" 51848b8605Smrg 52b8e80941Smrg#include "util/debug.h" 53b8e80941Smrg 54848b8605Smrg#include <X11/Xlib-xcb.h> 55848b8605Smrg#include <xcb/xcb.h> 56848b8605Smrg#include <xcb/glx.h> 57848b8605Smrg 58848b8605Smrg 59848b8605Smrg#ifdef DEBUG 60848b8605Smrgvoid __glXDumpDrawBuffer(struct glx_context * ctx); 61848b8605Smrg#endif 62848b8605Smrg 63848b8605Smrg/* 64848b8605Smrg** You can set this cell to 1 to force the gl drawing stuff to be 65848b8605Smrg** one command per packet 66848b8605Smrg*/ 67848b8605Smrg_X_HIDDEN int __glXDebug = 0; 68848b8605Smrg 69848b8605Smrg/* Extension required boiler plate */ 70848b8605Smrg 71848b8605Smrgstatic const char __glXExtensionName[] = GLX_EXTENSION_NAME; 72848b8605Smrg static struct glx_display *glx_displays; 73848b8605Smrg 74848b8605Smrgstatic /* const */ char *error_list[] = { 75848b8605Smrg "GLXBadContext", 76848b8605Smrg "GLXBadContextState", 77848b8605Smrg "GLXBadDrawable", 78848b8605Smrg "GLXBadPixmap", 79848b8605Smrg "GLXBadContextTag", 80848b8605Smrg "GLXBadCurrentWindow", 81848b8605Smrg "GLXBadRenderRequest", 82848b8605Smrg "GLXBadLargeRequest", 83848b8605Smrg "GLXUnsupportedPrivateRequest", 84848b8605Smrg "GLXBadFBConfig", 85848b8605Smrg "GLXBadPbuffer", 86848b8605Smrg "GLXBadCurrentDrawable", 87848b8605Smrg "GLXBadWindow", 88848b8605Smrg "GLXBadProfileARB", 89848b8605Smrg}; 90848b8605Smrg 91848b8605Smrg#ifdef GLX_USE_APPLEGL 92848b8605Smrgstatic char *__glXErrorString(Display *dpy, int code, XExtCodes *codes, 93848b8605Smrg char *buf, int n); 94848b8605Smrg#endif 95848b8605Smrg 96848b8605Smrgstatic 97848b8605SmrgXEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName, 98848b8605Smrg __GLX_NUMBER_ERRORS, error_list) 99848b8605Smrg 100848b8605Smrg/* 101848b8605Smrg * GLX events are a bit funky. We don't stuff the X event code into 102848b8605Smrg * our user exposed (via XNextEvent) structure. Instead we use the GLX 103848b8605Smrg * private event code namespace (and hope it doesn't conflict). Clients 104848b8605Smrg * have to know that bit 15 in the event type field means they're getting 105848b8605Smrg * a GLX event, and then handle the various sub-event types there, rather 106848b8605Smrg * than simply checking the event code and handling it directly. 107848b8605Smrg */ 108848b8605Smrg 109848b8605Smrgstatic Bool 110848b8605Smrg__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) 111848b8605Smrg{ 112848b8605Smrg struct glx_display *glx_dpy = __glXInitialize(dpy); 113848b8605Smrg 114848b8605Smrg if (glx_dpy == NULL) 115848b8605Smrg return False; 116848b8605Smrg 117848b8605Smrg switch ((wire->u.u.type & 0x7f) - glx_dpy->codes->first_event) { 118848b8605Smrg case GLX_PbufferClobber: 119848b8605Smrg { 120848b8605Smrg GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event; 121848b8605Smrg xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire; 122848b8605Smrg aevent->event_type = awire->type; 123848b8605Smrg aevent->serial = awire->sequenceNumber; 124848b8605Smrg aevent->event_type = awire->event_type; 125848b8605Smrg aevent->draw_type = awire->draw_type; 126848b8605Smrg aevent->drawable = awire->drawable; 127848b8605Smrg aevent->buffer_mask = awire->buffer_mask; 128848b8605Smrg aevent->aux_buffer = awire->aux_buffer; 129848b8605Smrg aevent->x = awire->x; 130848b8605Smrg aevent->y = awire->y; 131848b8605Smrg aevent->width = awire->width; 132848b8605Smrg aevent->height = awire->height; 133848b8605Smrg aevent->count = awire->count; 134848b8605Smrg return True; 135848b8605Smrg } 136848b8605Smrg case GLX_BufferSwapComplete: 137848b8605Smrg { 138848b8605Smrg GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; 139848b8605Smrg xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire; 140848b8605Smrg struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable); 141848b8605Smrg 142848b8605Smrg if (!glxDraw) 143848b8605Smrg return False; 144848b8605Smrg 145b8e80941Smrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 146b8e80941Smrg aevent->send_event = (awire->type & 0x80) != 0; 147b8e80941Smrg aevent->display = dpy; 148848b8605Smrg aevent->event_type = awire->event_type; 149848b8605Smrg aevent->drawable = glxDraw->xDrawable; 150848b8605Smrg aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; 151848b8605Smrg aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; 152848b8605Smrg 153b8e80941Smrg /* Handle 32-Bit wire sbc wraparound in both directions to cope with out 154b8e80941Smrg * of sequence 64-Bit sbc's 155b8e80941Smrg */ 156b8e80941Smrg if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000)) 157b8e80941Smrg glxDraw->eventSbcWrap += 0x100000000; 158b8e80941Smrg if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000)) 159b8e80941Smrg glxDraw->eventSbcWrap -= 0x100000000; 160848b8605Smrg glxDraw->lastEventSbc = awire->sbc; 161848b8605Smrg aevent->sbc = awire->sbc + glxDraw->eventSbcWrap; 162848b8605Smrg return True; 163848b8605Smrg } 164848b8605Smrg default: 165848b8605Smrg /* client doesn't support server event */ 166848b8605Smrg break; 167848b8605Smrg } 168848b8605Smrg 169848b8605Smrg return False; 170848b8605Smrg} 171848b8605Smrg 172848b8605Smrg/* We don't actually support this. It doesn't make sense for clients to 173848b8605Smrg * send each other GLX events. 174848b8605Smrg */ 175848b8605Smrgstatic Status 176848b8605Smrg__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire) 177848b8605Smrg{ 178848b8605Smrg struct glx_display *glx_dpy = __glXInitialize(dpy); 179848b8605Smrg 180848b8605Smrg if (glx_dpy == NULL) 181848b8605Smrg return False; 182848b8605Smrg 183848b8605Smrg switch (event->type) { 184848b8605Smrg case GLX_DAMAGED: 185848b8605Smrg break; 186848b8605Smrg case GLX_SAVED: 187848b8605Smrg break; 188848b8605Smrg case GLX_EXCHANGE_COMPLETE_INTEL: 189848b8605Smrg break; 190848b8605Smrg case GLX_COPY_COMPLETE_INTEL: 191848b8605Smrg break; 192848b8605Smrg case GLX_FLIP_COMPLETE_INTEL: 193848b8605Smrg break; 194848b8605Smrg default: 195848b8605Smrg /* client doesn't support server event */ 196848b8605Smrg break; 197848b8605Smrg } 198848b8605Smrg 199848b8605Smrg return Success; 200848b8605Smrg} 201848b8605Smrg 202848b8605Smrg/************************************************************************/ 203848b8605Smrg/* 204848b8605Smrg** Free the per screen configs data as well as the array of 205848b8605Smrg** __glXScreenConfigs. 206848b8605Smrg*/ 207848b8605Smrgstatic void 208848b8605SmrgFreeScreenConfigs(struct glx_display * priv) 209848b8605Smrg{ 210848b8605Smrg struct glx_screen *psc; 211848b8605Smrg GLint i, screens; 212848b8605Smrg 213848b8605Smrg /* Free screen configuration information */ 214848b8605Smrg screens = ScreenCount(priv->dpy); 215848b8605Smrg for (i = 0; i < screens; i++) { 216848b8605Smrg psc = priv->screens[i]; 217b8e80941Smrg if (!psc) 218b8e80941Smrg continue; 219848b8605Smrg glx_screen_cleanup(psc); 220848b8605Smrg 221848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 222848b8605Smrg if (psc->driScreen) { 223848b8605Smrg psc->driScreen->destroyScreen(psc); 224848b8605Smrg } else { 225848b8605Smrg free(psc); 226848b8605Smrg } 227848b8605Smrg#else 228848b8605Smrg free(psc); 229848b8605Smrg#endif 230848b8605Smrg } 231848b8605Smrg free((char *) priv->screens); 232848b8605Smrg priv->screens = NULL; 233848b8605Smrg} 234848b8605Smrg 235848b8605Smrgstatic void 236848b8605Smrgglx_display_free(struct glx_display *priv) 237848b8605Smrg{ 238848b8605Smrg struct glx_context *gc; 239848b8605Smrg 240848b8605Smrg gc = __glXGetCurrentContext(); 241848b8605Smrg if (priv->dpy == gc->currentDpy) { 242848b8605Smrg gc->vtable->destroy(gc); 243848b8605Smrg __glXSetCurrentContextNull(); 244848b8605Smrg } 245848b8605Smrg 246848b8605Smrg FreeScreenConfigs(priv); 247848b8605Smrg free((char *) priv->serverGLXvendor); 248848b8605Smrg free((char *) priv->serverGLXversion); 249848b8605Smrg 250848b8605Smrg __glxHashDestroy(priv->glXDrawHash); 251848b8605Smrg 252848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 253848b8605Smrg __glxHashDestroy(priv->drawHash); 254848b8605Smrg 255848b8605Smrg /* Free the direct rendering per display data */ 256848b8605Smrg if (priv->driswDisplay) 257848b8605Smrg (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay); 258848b8605Smrg priv->driswDisplay = NULL; 259848b8605Smrg 260848b8605Smrg#if defined (GLX_USE_DRM) 261848b8605Smrg if (priv->driDisplay) 262848b8605Smrg (*priv->driDisplay->destroyDisplay) (priv->driDisplay); 263848b8605Smrg priv->driDisplay = NULL; 264848b8605Smrg 265848b8605Smrg if (priv->dri2Display) 266848b8605Smrg (*priv->dri2Display->destroyDisplay) (priv->dri2Display); 267848b8605Smrg priv->dri2Display = NULL; 268848b8605Smrg 269848b8605Smrg if (priv->dri3Display) 270848b8605Smrg (*priv->dri3Display->destroyDisplay) (priv->dri3Display); 271848b8605Smrg priv->dri3Display = NULL; 272848b8605Smrg#endif /* GLX_USE_DRM */ 273b8e80941Smrg 274b8e80941Smrg#if defined(GLX_USE_WINDOWSGL) 275b8e80941Smrg if (priv->windowsdriDisplay) 276b8e80941Smrg (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay); 277b8e80941Smrg priv->windowsdriDisplay = NULL; 278b8e80941Smrg#endif /* GLX_USE_WINDOWSGL */ 279b8e80941Smrg 280848b8605Smrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ 281848b8605Smrg 282848b8605Smrg free((char *) priv); 283848b8605Smrg} 284848b8605Smrg 285848b8605Smrgstatic int 286848b8605Smrg__glXCloseDisplay(Display * dpy, XExtCodes * codes) 287848b8605Smrg{ 288848b8605Smrg struct glx_display *priv, **prev; 289848b8605Smrg 290848b8605Smrg _XLockMutex(_Xglobal_lock); 291848b8605Smrg prev = &glx_displays; 292848b8605Smrg for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) { 293848b8605Smrg if (priv->dpy == dpy) { 294848b8605Smrg *prev = priv->next; 295848b8605Smrg break; 296848b8605Smrg } 297848b8605Smrg } 298848b8605Smrg _XUnlockMutex(_Xglobal_lock); 299848b8605Smrg 300848b8605Smrg if (priv != NULL) 301848b8605Smrg glx_display_free(priv); 302848b8605Smrg 303848b8605Smrg return 1; 304848b8605Smrg} 305848b8605Smrg 306848b8605Smrg/* 307848b8605Smrg** Query the version of the GLX extension. This procedure works even if 308848b8605Smrg** the client extension is not completely set up. 309848b8605Smrg*/ 310848b8605Smrgstatic Bool 311848b8605SmrgQueryVersion(Display * dpy, int opcode, int *major, int *minor) 312848b8605Smrg{ 313848b8605Smrg xcb_connection_t *c = XGetXCBConnection(dpy); 314848b8605Smrg xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c, 315848b8605Smrg xcb_glx_query_version 316848b8605Smrg (c, 317848b8605Smrg GLX_MAJOR_VERSION, 318848b8605Smrg GLX_MINOR_VERSION), 319848b8605Smrg NULL); 320848b8605Smrg 321848b8605Smrg if (!reply) 322848b8605Smrg return GL_FALSE; 323848b8605Smrg 324848b8605Smrg if (reply->major_version != GLX_MAJOR_VERSION) { 325848b8605Smrg free(reply); 326848b8605Smrg return GL_FALSE; 327848b8605Smrg } 328848b8605Smrg *major = reply->major_version; 329848b8605Smrg *minor = min(reply->minor_version, GLX_MINOR_VERSION); 330848b8605Smrg free(reply); 331848b8605Smrg return GL_TRUE; 332848b8605Smrg} 333848b8605Smrg 334848b8605Smrg/* 335848b8605Smrg * We don't want to enable this GLX_OML_swap_method in glxext.h, 336848b8605Smrg * because we can't support it. The X server writes it out though, 337848b8605Smrg * so we should handle it somehow, to avoid false warnings. 338848b8605Smrg */ 339848b8605Smrgenum { 340848b8605Smrg IGNORE_GLX_SWAP_METHOD_OML = 0x8060 341848b8605Smrg}; 342848b8605Smrg 343848b8605Smrg 344848b8605Smrgstatic GLint 345848b8605Smrgconvert_from_x_visual_type(int visualType) 346848b8605Smrg{ 347848b8605Smrg static const int glx_visual_types[] = { 348b8e80941Smrg [StaticGray] = GLX_STATIC_GRAY, 349b8e80941Smrg [GrayScale] = GLX_GRAY_SCALE, 350b8e80941Smrg [StaticColor] = GLX_STATIC_COLOR, 351b8e80941Smrg [PseudoColor] = GLX_PSEUDO_COLOR, 352b8e80941Smrg [TrueColor] = GLX_TRUE_COLOR, 353b8e80941Smrg [DirectColor] = GLX_DIRECT_COLOR, 354848b8605Smrg }; 355848b8605Smrg 356848b8605Smrg if (visualType < ARRAY_SIZE(glx_visual_types)) 357848b8605Smrg return glx_visual_types[visualType]; 358848b8605Smrg 359848b8605Smrg return GLX_NONE; 360848b8605Smrg} 361848b8605Smrg 362848b8605Smrg/* 363848b8605Smrg * getVisualConfigs uses the !tagged_only path. 364848b8605Smrg * getFBConfigs uses the tagged_only path. 365848b8605Smrg */ 366848b8605Smrg_X_HIDDEN void 367848b8605Smrg__glXInitializeVisualConfigFromTags(struct glx_config * config, int count, 368848b8605Smrg const INT32 * bp, Bool tagged_only, 369848b8605Smrg Bool fbconfig_style_tags) 370848b8605Smrg{ 371848b8605Smrg int i; 372848b8605Smrg GLint renderType = 0; 373848b8605Smrg 374848b8605Smrg if (!tagged_only) { 375848b8605Smrg /* Copy in the first set of properties */ 376848b8605Smrg config->visualID = *bp++; 377848b8605Smrg 378848b8605Smrg config->visualType = convert_from_x_visual_type(*bp++); 379848b8605Smrg 380848b8605Smrg config->rgbMode = *bp++; 381848b8605Smrg 382848b8605Smrg config->redBits = *bp++; 383848b8605Smrg config->greenBits = *bp++; 384848b8605Smrg config->blueBits = *bp++; 385848b8605Smrg config->alphaBits = *bp++; 386848b8605Smrg config->accumRedBits = *bp++; 387848b8605Smrg config->accumGreenBits = *bp++; 388848b8605Smrg config->accumBlueBits = *bp++; 389848b8605Smrg config->accumAlphaBits = *bp++; 390848b8605Smrg 391848b8605Smrg config->doubleBufferMode = *bp++; 392848b8605Smrg config->stereoMode = *bp++; 393848b8605Smrg 394848b8605Smrg config->rgbBits = *bp++; 395848b8605Smrg config->depthBits = *bp++; 396848b8605Smrg config->stencilBits = *bp++; 397848b8605Smrg config->numAuxBuffers = *bp++; 398848b8605Smrg config->level = *bp++; 399848b8605Smrg 400848b8605Smrg#ifdef GLX_USE_APPLEGL 401848b8605Smrg /* AppleSGLX supports pixmap and pbuffers with all config. */ 402848b8605Smrg config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 403848b8605Smrg /* Unfortunately this can create an ABI compatibility problem. */ 404848b8605Smrg count -= 18; 405848b8605Smrg#else 406848b8605Smrg count -= __GLX_MIN_CONFIG_PROPS; 407848b8605Smrg#endif 408848b8605Smrg } 409848b8605Smrg 410848b8605Smrg /* 411848b8605Smrg ** Additional properties may be in a list at the end 412848b8605Smrg ** of the reply. They are in pairs of property type 413848b8605Smrg ** and property value. 414848b8605Smrg */ 415848b8605Smrg 416848b8605Smrg#define FETCH_OR_SET(tag) \ 417848b8605Smrg config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1 418848b8605Smrg 419848b8605Smrg for (i = 0; i < count; i += 2) { 420848b8605Smrg long int tag = *bp++; 421848b8605Smrg 422848b8605Smrg switch (tag) { 423848b8605Smrg case GLX_RGBA: 424848b8605Smrg FETCH_OR_SET(rgbMode); 425848b8605Smrg break; 426848b8605Smrg case GLX_BUFFER_SIZE: 427848b8605Smrg config->rgbBits = *bp++; 428848b8605Smrg break; 429848b8605Smrg case GLX_LEVEL: 430848b8605Smrg config->level = *bp++; 431848b8605Smrg break; 432848b8605Smrg case GLX_DOUBLEBUFFER: 433848b8605Smrg FETCH_OR_SET(doubleBufferMode); 434848b8605Smrg break; 435848b8605Smrg case GLX_STEREO: 436848b8605Smrg FETCH_OR_SET(stereoMode); 437848b8605Smrg break; 438848b8605Smrg case GLX_AUX_BUFFERS: 439848b8605Smrg config->numAuxBuffers = *bp++; 440848b8605Smrg break; 441848b8605Smrg case GLX_RED_SIZE: 442848b8605Smrg config->redBits = *bp++; 443848b8605Smrg break; 444848b8605Smrg case GLX_GREEN_SIZE: 445848b8605Smrg config->greenBits = *bp++; 446848b8605Smrg break; 447848b8605Smrg case GLX_BLUE_SIZE: 448848b8605Smrg config->blueBits = *bp++; 449848b8605Smrg break; 450848b8605Smrg case GLX_ALPHA_SIZE: 451848b8605Smrg config->alphaBits = *bp++; 452848b8605Smrg break; 453848b8605Smrg case GLX_DEPTH_SIZE: 454848b8605Smrg config->depthBits = *bp++; 455848b8605Smrg break; 456848b8605Smrg case GLX_STENCIL_SIZE: 457848b8605Smrg config->stencilBits = *bp++; 458848b8605Smrg break; 459848b8605Smrg case GLX_ACCUM_RED_SIZE: 460848b8605Smrg config->accumRedBits = *bp++; 461848b8605Smrg break; 462848b8605Smrg case GLX_ACCUM_GREEN_SIZE: 463848b8605Smrg config->accumGreenBits = *bp++; 464848b8605Smrg break; 465848b8605Smrg case GLX_ACCUM_BLUE_SIZE: 466848b8605Smrg config->accumBlueBits = *bp++; 467848b8605Smrg break; 468848b8605Smrg case GLX_ACCUM_ALPHA_SIZE: 469848b8605Smrg config->accumAlphaBits = *bp++; 470848b8605Smrg break; 471848b8605Smrg case GLX_VISUAL_CAVEAT_EXT: 472848b8605Smrg config->visualRating = *bp++; 473848b8605Smrg break; 474848b8605Smrg case GLX_X_VISUAL_TYPE: 475848b8605Smrg config->visualType = *bp++; 476848b8605Smrg break; 477848b8605Smrg case GLX_TRANSPARENT_TYPE: 478848b8605Smrg config->transparentPixel = *bp++; 479848b8605Smrg break; 480848b8605Smrg case GLX_TRANSPARENT_INDEX_VALUE: 481848b8605Smrg config->transparentIndex = *bp++; 482848b8605Smrg break; 483848b8605Smrg case GLX_TRANSPARENT_RED_VALUE: 484848b8605Smrg config->transparentRed = *bp++; 485848b8605Smrg break; 486848b8605Smrg case GLX_TRANSPARENT_GREEN_VALUE: 487848b8605Smrg config->transparentGreen = *bp++; 488848b8605Smrg break; 489848b8605Smrg case GLX_TRANSPARENT_BLUE_VALUE: 490848b8605Smrg config->transparentBlue = *bp++; 491848b8605Smrg break; 492848b8605Smrg case GLX_TRANSPARENT_ALPHA_VALUE: 493848b8605Smrg config->transparentAlpha = *bp++; 494848b8605Smrg break; 495848b8605Smrg case GLX_VISUAL_ID: 496848b8605Smrg config->visualID = *bp++; 497848b8605Smrg break; 498848b8605Smrg case GLX_DRAWABLE_TYPE: 499848b8605Smrg config->drawableType = *bp++; 500848b8605Smrg#ifdef GLX_USE_APPLEGL 501848b8605Smrg /* AppleSGLX supports pixmap and pbuffers with all config. */ 502848b8605Smrg config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 503848b8605Smrg#endif 504848b8605Smrg break; 505848b8605Smrg case GLX_RENDER_TYPE: /* fbconfig render type bits */ 506848b8605Smrg renderType = *bp++; 507848b8605Smrg break; 508848b8605Smrg case GLX_X_RENDERABLE: 509848b8605Smrg config->xRenderable = *bp++; 510848b8605Smrg break; 511848b8605Smrg case GLX_FBCONFIG_ID: 512848b8605Smrg config->fbconfigID = *bp++; 513848b8605Smrg break; 514848b8605Smrg case GLX_MAX_PBUFFER_WIDTH: 515848b8605Smrg config->maxPbufferWidth = *bp++; 516848b8605Smrg break; 517848b8605Smrg case GLX_MAX_PBUFFER_HEIGHT: 518848b8605Smrg config->maxPbufferHeight = *bp++; 519848b8605Smrg break; 520848b8605Smrg case GLX_MAX_PBUFFER_PIXELS: 521848b8605Smrg config->maxPbufferPixels = *bp++; 522848b8605Smrg break; 523848b8605Smrg#ifndef GLX_USE_APPLEGL 524848b8605Smrg case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: 525848b8605Smrg config->optimalPbufferWidth = *bp++; 526848b8605Smrg break; 527848b8605Smrg case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: 528848b8605Smrg config->optimalPbufferHeight = *bp++; 529848b8605Smrg break; 530848b8605Smrg case GLX_VISUAL_SELECT_GROUP_SGIX: 531848b8605Smrg config->visualSelectGroup = *bp++; 532848b8605Smrg break; 533848b8605Smrg case GLX_SWAP_METHOD_OML: 534b8e80941Smrg if (*bp == GLX_SWAP_UNDEFINED_OML || 535b8e80941Smrg *bp == GLX_SWAP_COPY_OML || 536b8e80941Smrg *bp == GLX_SWAP_EXCHANGE_OML) { 537b8e80941Smrg config->swapMethod = *bp++; 538b8e80941Smrg } else { 539b8e80941Smrg /* X servers with old HW drivers may return any value here, so 540b8e80941Smrg * assume GLX_SWAP_METHOD_UNDEFINED. 541b8e80941Smrg */ 542b8e80941Smrg config->swapMethod = GLX_SWAP_UNDEFINED_OML; 543b8e80941Smrg bp++; 544b8e80941Smrg } 545848b8605Smrg break; 546848b8605Smrg#endif 547848b8605Smrg case GLX_SAMPLE_BUFFERS_SGIS: 548848b8605Smrg config->sampleBuffers = *bp++; 549848b8605Smrg break; 550848b8605Smrg case GLX_SAMPLES_SGIS: 551848b8605Smrg config->samples = *bp++; 552848b8605Smrg break; 553848b8605Smrg#ifdef GLX_USE_APPLEGL 554848b8605Smrg case IGNORE_GLX_SWAP_METHOD_OML: 555848b8605Smrg /* We ignore this tag. See the comment above this function. */ 556848b8605Smrg ++bp; 557848b8605Smrg break; 558848b8605Smrg#else 559848b8605Smrg case GLX_BIND_TO_TEXTURE_RGB_EXT: 560848b8605Smrg config->bindToTextureRgb = *bp++; 561848b8605Smrg break; 562848b8605Smrg case GLX_BIND_TO_TEXTURE_RGBA_EXT: 563848b8605Smrg config->bindToTextureRgba = *bp++; 564848b8605Smrg break; 565848b8605Smrg case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 566848b8605Smrg config->bindToMipmapTexture = *bp++; 567848b8605Smrg break; 568848b8605Smrg case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 569848b8605Smrg config->bindToTextureTargets = *bp++; 570848b8605Smrg break; 571848b8605Smrg case GLX_Y_INVERTED_EXT: 572848b8605Smrg config->yInverted = *bp++; 573848b8605Smrg break; 574848b8605Smrg#endif 575848b8605Smrg case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT: 576848b8605Smrg config->sRGBCapable = *bp++; 577848b8605Smrg break; 578848b8605Smrg 579848b8605Smrg case GLX_USE_GL: 580848b8605Smrg if (fbconfig_style_tags) 581848b8605Smrg bp++; 582848b8605Smrg break; 583848b8605Smrg case None: 584848b8605Smrg i = count; 585848b8605Smrg break; 586848b8605Smrg default: 587b8e80941Smrg if(env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) { 588848b8605Smrg long int tagvalue = *bp++; 589848b8605Smrg fprintf(stderr, "WARNING: unknown GLX tag from server: " 590848b8605Smrg "tag 0x%lx value 0x%lx\n", tag, tagvalue); 591848b8605Smrg } else { 592848b8605Smrg /* Ignore the unrecognized tag's value */ 593848b8605Smrg bp++; 594848b8605Smrg } 595848b8605Smrg break; 596848b8605Smrg } 597848b8605Smrg } 598848b8605Smrg 599848b8605Smrg if (renderType != 0 && renderType != GLX_DONT_CARE) { 600848b8605Smrg config->renderType = renderType; 601848b8605Smrg config->floatMode = (renderType & 602848b8605Smrg (GLX_RGBA_FLOAT_BIT_ARB|GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) != 0; 603848b8605Smrg } else { 604848b8605Smrg /* If there wasn't GLX_RENDER_TYPE property, set it based on 605848b8605Smrg * config->rgbMode. The only way to communicate that the config is 606848b8605Smrg * floating-point is via GLX_RENDER_TYPE, so this cannot be a float 607848b8605Smrg * config. 608848b8605Smrg */ 609848b8605Smrg config->renderType = 610848b8605Smrg (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; 611848b8605Smrg } 612848b8605Smrg 613848b8605Smrg /* The GLX_ARB_fbconfig_float spec says: 614848b8605Smrg * 615848b8605Smrg * "Note that floating point rendering is only supported for 616848b8605Smrg * GLXPbuffer drawables." 617848b8605Smrg */ 618848b8605Smrg if (config->floatMode) 619b8e80941Smrg config->drawableType &= GLX_PBUFFER_BIT; 620848b8605Smrg} 621848b8605Smrg 622848b8605Smrgstatic struct glx_config * 623848b8605SmrgcreateConfigsFromProperties(Display * dpy, int nvisuals, int nprops, 624848b8605Smrg int screen, GLboolean tagged_only) 625848b8605Smrg{ 626848b8605Smrg INT32 buf[__GLX_TOTAL_CONFIG], *props; 627848b8605Smrg unsigned prop_size; 628848b8605Smrg struct glx_config *modes, *m; 629848b8605Smrg int i; 630848b8605Smrg 631848b8605Smrg if (nprops == 0) 632848b8605Smrg return NULL; 633848b8605Smrg 634848b8605Smrg /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */ 635848b8605Smrg 636848b8605Smrg /* Check number of properties */ 637848b8605Smrg if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS) 638848b8605Smrg return NULL; 639848b8605Smrg 640848b8605Smrg /* Allocate memory for our config structure */ 641848b8605Smrg modes = glx_config_create_list(nvisuals); 642848b8605Smrg if (!modes) 643848b8605Smrg return NULL; 644848b8605Smrg 645848b8605Smrg prop_size = nprops * __GLX_SIZE_INT32; 646848b8605Smrg if (prop_size <= sizeof(buf)) 647848b8605Smrg props = buf; 648848b8605Smrg else 649848b8605Smrg props = malloc(prop_size); 650848b8605Smrg 651848b8605Smrg /* Read each config structure and convert it into our format */ 652848b8605Smrg m = modes; 653848b8605Smrg for (i = 0; i < nvisuals; i++) { 654848b8605Smrg _XRead(dpy, (char *) props, prop_size); 655848b8605Smrg#ifdef GLX_USE_APPLEGL 656848b8605Smrg /* Older X servers don't send this so we default it here. */ 657848b8605Smrg m->drawableType = GLX_WINDOW_BIT; 658848b8605Smrg#else 659848b8605Smrg /* 660848b8605Smrg * The XQuartz 2.3.2.1 X server doesn't set this properly, so 661848b8605Smrg * set the proper bits here. 662848b8605Smrg * AppleSGLX supports windows, pixmaps, and pbuffers with all config. 663848b8605Smrg */ 664848b8605Smrg m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 665848b8605Smrg#endif 666b8e80941Smrg /* Older X servers don't send this so we default it here. */ 667b8e80941Smrg m->sRGBCapable = GL_FALSE; 668848b8605Smrg __glXInitializeVisualConfigFromTags(m, nprops, props, 669848b8605Smrg tagged_only, GL_TRUE); 670848b8605Smrg m->screen = screen; 671848b8605Smrg m = m->next; 672848b8605Smrg } 673848b8605Smrg 674848b8605Smrg if (props != buf) 675848b8605Smrg free(props); 676848b8605Smrg 677848b8605Smrg return modes; 678848b8605Smrg} 679848b8605Smrg 680848b8605Smrgstatic GLboolean 681848b8605SmrggetVisualConfigs(struct glx_screen *psc, 682848b8605Smrg struct glx_display *priv, int screen) 683848b8605Smrg{ 684848b8605Smrg xGLXGetVisualConfigsReq *req; 685848b8605Smrg xGLXGetVisualConfigsReply reply; 686848b8605Smrg Display *dpy = priv->dpy; 687848b8605Smrg 688848b8605Smrg LockDisplay(dpy); 689848b8605Smrg 690848b8605Smrg psc->visuals = NULL; 691848b8605Smrg GetReq(GLXGetVisualConfigs, req); 692848b8605Smrg req->reqType = priv->majorOpcode; 693848b8605Smrg req->glxCode = X_GLXGetVisualConfigs; 694848b8605Smrg req->screen = screen; 695848b8605Smrg 696848b8605Smrg if (!_XReply(dpy, (xReply *) & reply, 0, False)) 697848b8605Smrg goto out; 698848b8605Smrg 699848b8605Smrg psc->visuals = createConfigsFromProperties(dpy, 700848b8605Smrg reply.numVisuals, 701848b8605Smrg reply.numProps, 702848b8605Smrg screen, GL_FALSE); 703848b8605Smrg 704848b8605Smrg out: 705848b8605Smrg UnlockDisplay(dpy); 706848b8605Smrg return psc->visuals != NULL; 707848b8605Smrg} 708848b8605Smrg 709848b8605Smrgstatic GLboolean 710848b8605Smrg getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen) 711848b8605Smrg{ 712848b8605Smrg xGLXGetFBConfigsReq *fb_req; 713848b8605Smrg xGLXGetFBConfigsSGIXReq *sgi_req; 714848b8605Smrg xGLXVendorPrivateWithReplyReq *vpreq; 715848b8605Smrg xGLXGetFBConfigsReply reply; 716848b8605Smrg Display *dpy = priv->dpy; 717848b8605Smrg 718848b8605Smrg psc->serverGLXexts = 719848b8605Smrg __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); 720848b8605Smrg 721848b8605Smrg if (psc->serverGLXexts == NULL) { 722848b8605Smrg return GL_FALSE; 723848b8605Smrg } 724848b8605Smrg 725848b8605Smrg LockDisplay(dpy); 726848b8605Smrg 727848b8605Smrg psc->configs = NULL; 728848b8605Smrg if (atof(priv->serverGLXversion) >= 1.3) { 729848b8605Smrg GetReq(GLXGetFBConfigs, fb_req); 730848b8605Smrg fb_req->reqType = priv->majorOpcode; 731848b8605Smrg fb_req->glxCode = X_GLXGetFBConfigs; 732848b8605Smrg fb_req->screen = screen; 733848b8605Smrg } 734848b8605Smrg else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { 735848b8605Smrg GetReqExtra(GLXVendorPrivateWithReply, 736848b8605Smrg sz_xGLXGetFBConfigsSGIXReq - 737848b8605Smrg sz_xGLXVendorPrivateWithReplyReq, vpreq); 738848b8605Smrg sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; 739848b8605Smrg sgi_req->reqType = priv->majorOpcode; 740848b8605Smrg sgi_req->glxCode = X_GLXVendorPrivateWithReply; 741848b8605Smrg sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; 742848b8605Smrg sgi_req->screen = screen; 743848b8605Smrg } 744848b8605Smrg else 745848b8605Smrg goto out; 746848b8605Smrg 747848b8605Smrg if (!_XReply(dpy, (xReply *) & reply, 0, False)) 748848b8605Smrg goto out; 749848b8605Smrg 750848b8605Smrg psc->configs = createConfigsFromProperties(dpy, 751848b8605Smrg reply.numFBConfigs, 752848b8605Smrg reply.numAttribs * 2, 753848b8605Smrg screen, GL_TRUE); 754848b8605Smrg 755848b8605Smrg out: 756848b8605Smrg UnlockDisplay(dpy); 757848b8605Smrg return psc->configs != NULL; 758848b8605Smrg} 759848b8605Smrg 760848b8605Smrg_X_HIDDEN Bool 761848b8605Smrgglx_screen_init(struct glx_screen *psc, 762848b8605Smrg int screen, struct glx_display * priv) 763848b8605Smrg{ 764848b8605Smrg /* Initialize per screen dynamic client GLX extensions */ 765848b8605Smrg psc->ext_list_first_time = GL_TRUE; 766848b8605Smrg psc->scr = screen; 767848b8605Smrg psc->dpy = priv->dpy; 768848b8605Smrg psc->display = priv; 769848b8605Smrg 770b8e80941Smrg if (!getVisualConfigs(psc, priv, screen)) 771b8e80941Smrg return GL_FALSE; 772b8e80941Smrg 773b8e80941Smrg if (!getFBConfigs(psc, priv, screen)) 774b8e80941Smrg return GL_FALSE; 775848b8605Smrg 776848b8605Smrg return GL_TRUE; 777848b8605Smrg} 778848b8605Smrg 779848b8605Smrg_X_HIDDEN void 780848b8605Smrgglx_screen_cleanup(struct glx_screen *psc) 781848b8605Smrg{ 782848b8605Smrg if (psc->configs) { 783848b8605Smrg glx_config_destroy_list(psc->configs); 784848b8605Smrg free(psc->effectiveGLXexts); 785848b8605Smrg psc->configs = NULL; /* NOTE: just for paranoia */ 786848b8605Smrg } 787848b8605Smrg if (psc->visuals) { 788848b8605Smrg glx_config_destroy_list(psc->visuals); 789848b8605Smrg psc->visuals = NULL; /* NOTE: just for paranoia */ 790848b8605Smrg } 791848b8605Smrg free((char *) psc->serverGLXexts); 792848b8605Smrg} 793848b8605Smrg 794848b8605Smrg/* 795848b8605Smrg** Allocate the memory for the per screen configs for each screen. 796848b8605Smrg** If that works then fetch the per screen configs data. 797848b8605Smrg*/ 798848b8605Smrgstatic Bool 799848b8605SmrgAllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv) 800848b8605Smrg{ 801848b8605Smrg struct glx_screen *psc; 802848b8605Smrg GLint i, screens; 803848b8605Smrg 804848b8605Smrg /* 805848b8605Smrg ** First allocate memory for the array of per screen configs. 806848b8605Smrg */ 807848b8605Smrg screens = ScreenCount(dpy); 808b8e80941Smrg priv->screens = calloc(screens, sizeof *priv->screens); 809848b8605Smrg if (!priv->screens) 810848b8605Smrg return GL_FALSE; 811848b8605Smrg 812848b8605Smrg priv->serverGLXversion = 813848b8605Smrg __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); 814848b8605Smrg if (priv->serverGLXversion == NULL) { 815848b8605Smrg FreeScreenConfigs(priv); 816848b8605Smrg return GL_FALSE; 817848b8605Smrg } 818848b8605Smrg 819848b8605Smrg for (i = 0; i < screens; i++, psc++) { 820848b8605Smrg psc = NULL; 821848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 822848b8605Smrg#if defined(GLX_USE_DRM) 823848b8605Smrg#if defined(HAVE_DRI3) 824848b8605Smrg if (priv->dri3Display) 825848b8605Smrg psc = (*priv->dri3Display->createScreen) (i, priv); 826848b8605Smrg#endif /* HAVE_DRI3 */ 827848b8605Smrg if (psc == NULL && priv->dri2Display) 828848b8605Smrg psc = (*priv->dri2Display->createScreen) (i, priv); 829848b8605Smrg if (psc == NULL && priv->driDisplay) 830848b8605Smrg psc = (*priv->driDisplay->createScreen) (i, priv); 831848b8605Smrg#endif /* GLX_USE_DRM */ 832b8e80941Smrg 833b8e80941Smrg#ifdef GLX_USE_WINDOWSGL 834b8e80941Smrg if (psc == NULL && priv->windowsdriDisplay) 835b8e80941Smrg psc = (*priv->windowsdriDisplay->createScreen) (i, priv); 836b8e80941Smrg#endif 837b8e80941Smrg 838848b8605Smrg if (psc == NULL && priv->driswDisplay) 839848b8605Smrg psc = (*priv->driswDisplay->createScreen) (i, priv); 840848b8605Smrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ 841848b8605Smrg 842848b8605Smrg#if defined(GLX_USE_APPLEGL) 843848b8605Smrg if (psc == NULL) 844848b8605Smrg psc = applegl_create_screen(i, priv); 845848b8605Smrg#else 846848b8605Smrg if (psc == NULL) 847848b8605Smrg psc = indirect_create_screen(i, priv); 848848b8605Smrg#endif 849848b8605Smrg priv->screens[i] = psc; 850848b8605Smrg } 851848b8605Smrg SyncHandle(); 852848b8605Smrg return GL_TRUE; 853848b8605Smrg} 854848b8605Smrg 855848b8605Smrg/* 856848b8605Smrg** Initialize the client side extension code. 857848b8605Smrg*/ 858848b8605Smrg _X_HIDDEN struct glx_display * 859848b8605Smrg__glXInitialize(Display * dpy) 860848b8605Smrg{ 861848b8605Smrg struct glx_display *dpyPriv, *d; 862848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 863848b8605Smrg Bool glx_direct, glx_accel; 864848b8605Smrg#endif 865848b8605Smrg int i; 866848b8605Smrg 867848b8605Smrg _XLockMutex(_Xglobal_lock); 868848b8605Smrg 869848b8605Smrg for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) { 870848b8605Smrg if (dpyPriv->dpy == dpy) { 871848b8605Smrg _XUnlockMutex(_Xglobal_lock); 872848b8605Smrg return dpyPriv; 873848b8605Smrg } 874848b8605Smrg } 875848b8605Smrg 876848b8605Smrg /* Drop the lock while we create the display private. */ 877848b8605Smrg _XUnlockMutex(_Xglobal_lock); 878848b8605Smrg 879848b8605Smrg dpyPriv = calloc(1, sizeof *dpyPriv); 880848b8605Smrg if (!dpyPriv) 881848b8605Smrg return NULL; 882848b8605Smrg 883848b8605Smrg dpyPriv->codes = XInitExtension(dpy, __glXExtensionName); 884848b8605Smrg if (!dpyPriv->codes) { 885848b8605Smrg free(dpyPriv); 886848b8605Smrg return NULL; 887848b8605Smrg } 888848b8605Smrg 889848b8605Smrg dpyPriv->dpy = dpy; 890848b8605Smrg dpyPriv->majorOpcode = dpyPriv->codes->major_opcode; 891848b8605Smrg dpyPriv->serverGLXvendor = 0x0; 892848b8605Smrg dpyPriv->serverGLXversion = 0x0; 893848b8605Smrg 894848b8605Smrg /* See if the versions are compatible. This GLX implementation does not 895848b8605Smrg * work with servers that only support GLX 1.0. 896848b8605Smrg */ 897848b8605Smrg if (!QueryVersion(dpy, dpyPriv->majorOpcode, 898848b8605Smrg &dpyPriv->majorVersion, &dpyPriv->minorVersion) 899848b8605Smrg || (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion < 1)) { 900848b8605Smrg free(dpyPriv); 901848b8605Smrg return NULL; 902848b8605Smrg } 903848b8605Smrg 904848b8605Smrg for (i = 0; i < __GLX_NUMBER_EVENTS; i++) { 905848b8605Smrg XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent); 906848b8605Smrg XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire); 907848b8605Smrg } 908848b8605Smrg 909848b8605Smrg XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay); 910848b8605Smrg XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString); 911848b8605Smrg 912848b8605Smrg dpyPriv->glXDrawHash = __glxHashCreate(); 913848b8605Smrg 914848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 915b8e80941Smrg glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false); 916b8e80941Smrg glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false); 917848b8605Smrg 918848b8605Smrg dpyPriv->drawHash = __glxHashCreate(); 919848b8605Smrg 920848b8605Smrg /* 921848b8605Smrg ** Initialize the direct rendering per display data and functions. 922848b8605Smrg ** Note: This _must_ be done before calling any other DRI routines 923848b8605Smrg ** (e.g., those called in AllocAndFetchScreenConfigs). 924848b8605Smrg */ 925848b8605Smrg#if defined(GLX_USE_DRM) 926848b8605Smrg if (glx_direct && glx_accel) { 927848b8605Smrg#if defined(HAVE_DRI3) 928b8e80941Smrg if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false)) 929848b8605Smrg dpyPriv->dri3Display = dri3_create_display(dpy); 930848b8605Smrg#endif /* HAVE_DRI3 */ 931848b8605Smrg dpyPriv->dri2Display = dri2CreateDisplay(dpy); 932848b8605Smrg dpyPriv->driDisplay = driCreateDisplay(dpy); 933848b8605Smrg } 934848b8605Smrg#endif /* GLX_USE_DRM */ 935848b8605Smrg if (glx_direct) 936848b8605Smrg dpyPriv->driswDisplay = driswCreateDisplay(dpy); 937848b8605Smrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ 938848b8605Smrg 939848b8605Smrg#ifdef GLX_USE_APPLEGL 940848b8605Smrg if (!applegl_create_display(dpyPriv)) { 941848b8605Smrg free(dpyPriv); 942848b8605Smrg return NULL; 943848b8605Smrg } 944848b8605Smrg#endif 945b8e80941Smrg 946b8e80941Smrg#ifdef GLX_USE_WINDOWSGL 947b8e80941Smrg if (glx_direct && glx_accel) 948b8e80941Smrg dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy); 949b8e80941Smrg#endif 950b8e80941Smrg 951848b8605Smrg if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { 952848b8605Smrg free(dpyPriv); 953848b8605Smrg return NULL; 954848b8605Smrg } 955848b8605Smrg 956848b8605Smrg __glX_send_client_info(dpyPriv); 957848b8605Smrg 958848b8605Smrg /* Grab the lock again and add the dispay private, unless somebody 959848b8605Smrg * beat us to initializing on this display in the meantime. */ 960848b8605Smrg _XLockMutex(_Xglobal_lock); 961848b8605Smrg 962848b8605Smrg for (d = glx_displays; d; d = d->next) { 963848b8605Smrg if (d->dpy == dpy) { 964848b8605Smrg _XUnlockMutex(_Xglobal_lock); 965848b8605Smrg glx_display_free(dpyPriv); 966848b8605Smrg return d; 967848b8605Smrg } 968848b8605Smrg } 969848b8605Smrg 970848b8605Smrg dpyPriv->next = glx_displays; 971848b8605Smrg glx_displays = dpyPriv; 972848b8605Smrg 973848b8605Smrg _XUnlockMutex(_Xglobal_lock); 974848b8605Smrg 975848b8605Smrg return dpyPriv; 976848b8605Smrg} 977848b8605Smrg 978848b8605Smrg/* 979848b8605Smrg** Setup for sending a GLX command on dpy. Make sure the extension is 980848b8605Smrg** initialized. Try to avoid calling __glXInitialize as its kinda slow. 981848b8605Smrg*/ 982848b8605Smrg_X_HIDDEN CARD8 983848b8605Smrg__glXSetupForCommand(Display * dpy) 984848b8605Smrg{ 985848b8605Smrg struct glx_context *gc; 986848b8605Smrg struct glx_display *priv; 987848b8605Smrg 988848b8605Smrg /* If this thread has a current context, flush its rendering commands */ 989848b8605Smrg gc = __glXGetCurrentContext(); 990848b8605Smrg if (gc->currentDpy) { 991848b8605Smrg /* Flush rendering buffer of the current context, if any */ 992848b8605Smrg (void) __glXFlushRenderBuffer(gc, gc->pc); 993848b8605Smrg 994848b8605Smrg if (gc->currentDpy == dpy) { 995848b8605Smrg /* Use opcode from gc because its right */ 996848b8605Smrg return gc->majorOpcode; 997848b8605Smrg } 998848b8605Smrg else { 999848b8605Smrg /* 1000848b8605Smrg ** Have to get info about argument dpy because it might be to 1001848b8605Smrg ** a different server 1002848b8605Smrg */ 1003848b8605Smrg } 1004848b8605Smrg } 1005848b8605Smrg 1006848b8605Smrg /* Forced to lookup extension via the slow initialize route */ 1007848b8605Smrg priv = __glXInitialize(dpy); 1008848b8605Smrg if (!priv) { 1009848b8605Smrg return 0; 1010848b8605Smrg } 1011848b8605Smrg return priv->majorOpcode; 1012848b8605Smrg} 1013848b8605Smrg 1014848b8605Smrg/** 1015848b8605Smrg * Flush the drawing command transport buffer. 1016848b8605Smrg * 1017848b8605Smrg * \param ctx Context whose transport buffer is to be flushed. 1018848b8605Smrg * \param pc Pointer to first unused buffer location. 1019848b8605Smrg * 1020848b8605Smrg * \todo 1021848b8605Smrg * Modify this function to use \c ctx->pc instead of the explicit 1022848b8605Smrg * \c pc parameter. 1023848b8605Smrg */ 1024848b8605Smrg_X_HIDDEN GLubyte * 1025848b8605Smrg__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc) 1026848b8605Smrg{ 1027848b8605Smrg Display *const dpy = ctx->currentDpy; 1028848b8605Smrg xcb_connection_t *c = XGetXCBConnection(dpy); 1029848b8605Smrg const GLint size = pc - ctx->buf; 1030848b8605Smrg 1031848b8605Smrg if ((dpy != NULL) && (size > 0)) { 1032848b8605Smrg xcb_glx_render(c, ctx->currentContextTag, size, 1033848b8605Smrg (const uint8_t *) ctx->buf); 1034848b8605Smrg } 1035848b8605Smrg 1036848b8605Smrg /* Reset pointer and return it */ 1037848b8605Smrg ctx->pc = ctx->buf; 1038848b8605Smrg return ctx->pc; 1039848b8605Smrg} 1040848b8605Smrg 1041848b8605Smrg 1042848b8605Smrg/** 1043848b8605Smrg * Send a portion of a GLXRenderLarge command to the server. The advantage of 1044848b8605Smrg * this function over \c __glXSendLargeCommand is that callers can use the 1045848b8605Smrg * data buffer in the GLX context and may be able to avoid allocating an 1046848b8605Smrg * extra buffer. The disadvantage is the clients will have to do more 1047848b8605Smrg * GLX protocol work (i.e., calculating \c totalRequests, etc.). 1048848b8605Smrg * 1049848b8605Smrg * \sa __glXSendLargeCommand 1050848b8605Smrg * 1051848b8605Smrg * \param gc GLX context 1052848b8605Smrg * \param requestNumber Which part of the whole command is this? The first 1053848b8605Smrg * request is 1. 1054848b8605Smrg * \param totalRequests How many requests will there be? 1055848b8605Smrg * \param data Command data. 1056848b8605Smrg * \param dataLen Size, in bytes, of the command data. 1057848b8605Smrg */ 1058848b8605Smrg_X_HIDDEN void 1059848b8605Smrg__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber, 1060848b8605Smrg GLint totalRequests, const GLvoid * data, GLint dataLen) 1061848b8605Smrg{ 1062848b8605Smrg Display *dpy = gc->currentDpy; 1063848b8605Smrg xcb_connection_t *c = XGetXCBConnection(dpy); 1064848b8605Smrg xcb_glx_render_large(c, gc->currentContextTag, requestNumber, 1065848b8605Smrg totalRequests, dataLen, data); 1066848b8605Smrg} 1067848b8605Smrg 1068848b8605Smrg 1069848b8605Smrg/** 1070848b8605Smrg * Send a command that is too large for the GLXRender protocol request. 1071848b8605Smrg * 1072848b8605Smrg * Send a large command, one that is too large for some reason to 1073848b8605Smrg * send using the GLXRender protocol request. One reason to send 1074848b8605Smrg * a large command is to avoid copying the data. 1075848b8605Smrg * 1076848b8605Smrg * \param ctx GLX context 1077848b8605Smrg * \param header Header data. 1078848b8605Smrg * \param headerLen Size, in bytes, of the header data. It is assumed that 1079848b8605Smrg * the header data will always be small enough to fit in 1080848b8605Smrg * a single X protocol packet. 1081848b8605Smrg * \param data Command data. 1082848b8605Smrg * \param dataLen Size, in bytes, of the command data. 1083848b8605Smrg */ 1084848b8605Smrg_X_HIDDEN void 1085848b8605Smrg__glXSendLargeCommand(struct glx_context * ctx, 1086848b8605Smrg const GLvoid * header, GLint headerLen, 1087848b8605Smrg const GLvoid * data, GLint dataLen) 1088848b8605Smrg{ 1089848b8605Smrg GLint maxSize; 1090848b8605Smrg GLint totalRequests, requestNumber; 1091848b8605Smrg 1092848b8605Smrg /* 1093848b8605Smrg ** Calculate the maximum amount of data can be stuffed into a single 1094848b8605Smrg ** packet. sz_xGLXRenderReq is added because bufSize is the maximum 1095848b8605Smrg ** packet size minus sz_xGLXRenderReq. 1096848b8605Smrg */ 1097848b8605Smrg maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq; 1098848b8605Smrg totalRequests = 1 + (dataLen / maxSize); 1099848b8605Smrg if (dataLen % maxSize) 1100848b8605Smrg totalRequests++; 1101848b8605Smrg 1102848b8605Smrg /* 1103848b8605Smrg ** Send all of the command, except the large array, as one request. 1104848b8605Smrg */ 1105848b8605Smrg assert(headerLen <= maxSize); 1106848b8605Smrg __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen); 1107848b8605Smrg 1108848b8605Smrg /* 1109848b8605Smrg ** Send enough requests until the whole array is sent. 1110848b8605Smrg */ 1111848b8605Smrg for (requestNumber = 2; requestNumber <= (totalRequests - 1); 1112848b8605Smrg requestNumber++) { 1113848b8605Smrg __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize); 1114848b8605Smrg data = (const GLvoid *) (((const GLubyte *) data) + maxSize); 1115848b8605Smrg dataLen -= maxSize; 1116848b8605Smrg assert(dataLen > 0); 1117848b8605Smrg } 1118848b8605Smrg 1119848b8605Smrg assert(dataLen <= maxSize); 1120848b8605Smrg __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen); 1121848b8605Smrg} 1122848b8605Smrg 1123848b8605Smrg/************************************************************************/ 1124848b8605Smrg 1125848b8605Smrg#ifdef DEBUG 1126848b8605Smrg_X_HIDDEN void 1127848b8605Smrg__glXDumpDrawBuffer(struct glx_context * ctx) 1128848b8605Smrg{ 1129848b8605Smrg GLubyte *p = ctx->buf; 1130848b8605Smrg GLubyte *end = ctx->pc; 1131848b8605Smrg GLushort opcode, length; 1132848b8605Smrg 1133848b8605Smrg while (p < end) { 1134848b8605Smrg /* Fetch opcode */ 1135848b8605Smrg opcode = *((GLushort *) p); 1136848b8605Smrg length = *((GLushort *) (p + 2)); 1137848b8605Smrg printf("%2x: %5d: ", opcode, length); 1138848b8605Smrg length -= 4; 1139848b8605Smrg p += 4; 1140848b8605Smrg while (length > 0) { 1141848b8605Smrg printf("%08x ", *((unsigned *) p)); 1142848b8605Smrg p += 4; 1143848b8605Smrg length -= 4; 1144848b8605Smrg } 1145848b8605Smrg printf("\n"); 1146848b8605Smrg } 1147848b8605Smrg} 1148848b8605Smrg#endif 1149