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