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> 427ec681f3Smrg#include <stdarg.h> 4301e04c3fSmrg 44cdc920a0Smrg#include "glxclient.h" 45cdc920a0Smrg#include <X11/extensions/Xext.h> 46cdc920a0Smrg#include <X11/extensions/extutil.h> 47cdc920a0Smrg#ifdef GLX_USE_APPLEGL 48af69d88dSmrg#include "apple/apple_glx.h" 49af69d88dSmrg#include "apple/apple_visual.h" 50cdc920a0Smrg#endif 51cdc920a0Smrg#include "glxextensions.h" 52cdc920a0Smrg 5301e04c3fSmrg#include "util/debug.h" 547ec681f3Smrg#ifndef GLX_USE_APPLEGL 557ec681f3Smrg#include "dri_common.h" 567ec681f3Smrg#endif 5701e04c3fSmrg 58cdc920a0Smrg#include <X11/Xlib-xcb.h> 59cdc920a0Smrg#include <xcb/xcb.h> 60cdc920a0Smrg#include <xcb/glx.h> 61cdc920a0Smrg 627ec681f3Smrg#define __GLX_MIN_CONFIG_PROPS 18 637ec681f3Smrg#define __GLX_EXT_CONFIG_PROPS 32 64cdc920a0Smrg 657ec681f3Smrg/* 667ec681f3Smrg** Since we send all non-core visual properties as token, value pairs, 677ec681f3Smrg** we require 2 words across the wire. In order to maintain backwards 687ec681f3Smrg** compatibility, we need to send the total number of words that the 697ec681f3Smrg** VisualConfigs are sent back in so old libraries can simply "ignore" 707ec681f3Smrg** the new properties. 717ec681f3Smrg*/ 727ec681f3Smrg#define __GLX_TOTAL_CONFIG \ 737ec681f3Smrg (__GLX_MIN_CONFIG_PROPS + 2 * __GLX_EXT_CONFIG_PROPS) 747ec681f3Smrg 757ec681f3Smrg_X_HIDDEN void 767ec681f3Smrgglx_message(int level, const char *f, ...) 777ec681f3Smrg{ 787ec681f3Smrg va_list args; 797ec681f3Smrg int threshold = _LOADER_WARNING; 807ec681f3Smrg const char *libgl_debug; 817ec681f3Smrg 827ec681f3Smrg libgl_debug = getenv("LIBGL_DEBUG"); 837ec681f3Smrg if (libgl_debug) { 847ec681f3Smrg if (strstr(libgl_debug, "quiet")) 857ec681f3Smrg threshold = _LOADER_FATAL; 867ec681f3Smrg else if (strstr(libgl_debug, "verbose")) 877ec681f3Smrg threshold = _LOADER_DEBUG; 887ec681f3Smrg } 897ec681f3Smrg 907ec681f3Smrg /* Note that the _LOADER_* levels are lower numbers for more severe. */ 917ec681f3Smrg if (level <= threshold) { 927ec681f3Smrg fprintf(stderr, "libGL%s: ", level <= _LOADER_WARNING ? " error" : ""); 937ec681f3Smrg va_start(args, f); 947ec681f3Smrg vfprintf(stderr, f, args); 957ec681f3Smrg va_end(args); 967ec681f3Smrg } 977ec681f3Smrg} 98cdc920a0Smrg 99cdc920a0Smrg/* 100cdc920a0Smrg** You can set this cell to 1 to force the gl drawing stuff to be 101cdc920a0Smrg** one command per packet 102cdc920a0Smrg*/ 103cdc920a0Smrg_X_HIDDEN int __glXDebug = 0; 104cdc920a0Smrg 105cdc920a0Smrg/* Extension required boiler plate */ 106cdc920a0Smrg 1073464ebd5Sriastradhstatic const char __glXExtensionName[] = GLX_EXTENSION_NAME; 1087ec681f3Smrgstatic struct glx_display *glx_displays; 109cdc920a0Smrg 110cdc920a0Smrgstatic /* const */ char *error_list[] = { 111cdc920a0Smrg "GLXBadContext", 112cdc920a0Smrg "GLXBadContextState", 113cdc920a0Smrg "GLXBadDrawable", 114cdc920a0Smrg "GLXBadPixmap", 115cdc920a0Smrg "GLXBadContextTag", 116cdc920a0Smrg "GLXBadCurrentWindow", 117cdc920a0Smrg "GLXBadRenderRequest", 118cdc920a0Smrg "GLXBadLargeRequest", 119cdc920a0Smrg "GLXUnsupportedPrivateRequest", 120cdc920a0Smrg "GLXBadFBConfig", 121cdc920a0Smrg "GLXBadPbuffer", 122cdc920a0Smrg "GLXBadCurrentDrawable", 123cdc920a0Smrg "GLXBadWindow", 124af69d88dSmrg "GLXBadProfileARB", 125cdc920a0Smrg}; 126cdc920a0Smrg 127cdc920a0Smrg#ifdef GLX_USE_APPLEGL 128cdc920a0Smrgstatic char *__glXErrorString(Display *dpy, int code, XExtCodes *codes, 129cdc920a0Smrg char *buf, int n); 130cdc920a0Smrg#endif 131cdc920a0Smrg 132cdc920a0Smrgstatic 133cdc920a0SmrgXEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName, 134cdc920a0Smrg __GLX_NUMBER_ERRORS, error_list) 135cdc920a0Smrg 136cdc920a0Smrg/* 137cdc920a0Smrg * GLX events are a bit funky. We don't stuff the X event code into 138cdc920a0Smrg * our user exposed (via XNextEvent) structure. Instead we use the GLX 139cdc920a0Smrg * private event code namespace (and hope it doesn't conflict). Clients 140cdc920a0Smrg * have to know that bit 15 in the event type field means they're getting 141cdc920a0Smrg * a GLX event, and then handle the various sub-event types there, rather 142cdc920a0Smrg * than simply checking the event code and handling it directly. 143cdc920a0Smrg */ 144cdc920a0Smrg 145cdc920a0Smrgstatic Bool 146cdc920a0Smrg__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) 147cdc920a0Smrg{ 1483464ebd5Sriastradh struct glx_display *glx_dpy = __glXInitialize(dpy); 149cdc920a0Smrg 1503464ebd5Sriastradh if (glx_dpy == NULL) 1513464ebd5Sriastradh return False; 152cdc920a0Smrg 1537ec681f3Smrg switch ((wire->u.u.type & 0x7f) - glx_dpy->codes.first_event) { 154cdc920a0Smrg case GLX_PbufferClobber: 155cdc920a0Smrg { 156cdc920a0Smrg GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event; 157cdc920a0Smrg xGLXPbufferClobberEvent *awire = (xGLXPbufferClobberEvent *)wire; 158cdc920a0Smrg aevent->event_type = awire->type; 159cdc920a0Smrg aevent->serial = awire->sequenceNumber; 160cdc920a0Smrg aevent->event_type = awire->event_type; 161cdc920a0Smrg aevent->draw_type = awire->draw_type; 162cdc920a0Smrg aevent->drawable = awire->drawable; 163cdc920a0Smrg aevent->buffer_mask = awire->buffer_mask; 164cdc920a0Smrg aevent->aux_buffer = awire->aux_buffer; 165cdc920a0Smrg aevent->x = awire->x; 166cdc920a0Smrg aevent->y = awire->y; 167cdc920a0Smrg aevent->width = awire->width; 168cdc920a0Smrg aevent->height = awire->height; 169cdc920a0Smrg aevent->count = awire->count; 170cdc920a0Smrg return True; 171cdc920a0Smrg } 172cdc920a0Smrg case GLX_BufferSwapComplete: 173cdc920a0Smrg { 174cdc920a0Smrg GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; 175af69d88dSmrg xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire; 176af69d88dSmrg struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable); 177af69d88dSmrg 178af69d88dSmrg if (!glxDraw) 179af69d88dSmrg return False; 180af69d88dSmrg 18101e04c3fSmrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 18201e04c3fSmrg aevent->send_event = (awire->type & 0x80) != 0; 18301e04c3fSmrg aevent->display = dpy; 184cdc920a0Smrg aevent->event_type = awire->event_type; 185af69d88dSmrg aevent->drawable = glxDraw->xDrawable; 186cdc920a0Smrg aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; 187cdc920a0Smrg aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; 188af69d88dSmrg 18901e04c3fSmrg /* Handle 32-Bit wire sbc wraparound in both directions to cope with out 19001e04c3fSmrg * of sequence 64-Bit sbc's 19101e04c3fSmrg */ 19201e04c3fSmrg if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000)) 19301e04c3fSmrg glxDraw->eventSbcWrap += 0x100000000; 19401e04c3fSmrg if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000)) 19501e04c3fSmrg glxDraw->eventSbcWrap -= 0x100000000; 196af69d88dSmrg glxDraw->lastEventSbc = awire->sbc; 197af69d88dSmrg aevent->sbc = awire->sbc + glxDraw->eventSbcWrap; 198cdc920a0Smrg return True; 199cdc920a0Smrg } 200cdc920a0Smrg default: 201cdc920a0Smrg /* client doesn't support server event */ 202cdc920a0Smrg break; 203cdc920a0Smrg } 204cdc920a0Smrg 205cdc920a0Smrg return False; 206cdc920a0Smrg} 207cdc920a0Smrg 208cdc920a0Smrg/* We don't actually support this. It doesn't make sense for clients to 209cdc920a0Smrg * send each other GLX events. 210cdc920a0Smrg */ 211cdc920a0Smrgstatic Status 212cdc920a0Smrg__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire) 213cdc920a0Smrg{ 2143464ebd5Sriastradh struct glx_display *glx_dpy = __glXInitialize(dpy); 215cdc920a0Smrg 2163464ebd5Sriastradh if (glx_dpy == NULL) 2173464ebd5Sriastradh return False; 218cdc920a0Smrg 219cdc920a0Smrg switch (event->type) { 220cdc920a0Smrg case GLX_DAMAGED: 221cdc920a0Smrg break; 222cdc920a0Smrg case GLX_SAVED: 223cdc920a0Smrg break; 224cdc920a0Smrg case GLX_EXCHANGE_COMPLETE_INTEL: 225cdc920a0Smrg break; 226cdc920a0Smrg case GLX_COPY_COMPLETE_INTEL: 227cdc920a0Smrg break; 228cdc920a0Smrg case GLX_FLIP_COMPLETE_INTEL: 229cdc920a0Smrg break; 230cdc920a0Smrg default: 231cdc920a0Smrg /* client doesn't support server event */ 232cdc920a0Smrg break; 233cdc920a0Smrg } 234cdc920a0Smrg 235cdc920a0Smrg return Success; 236cdc920a0Smrg} 237cdc920a0Smrg 238cdc920a0Smrg/************************************************************************/ 239cdc920a0Smrg/* 240cdc920a0Smrg** Free the per screen configs data as well as the array of 241cdc920a0Smrg** __glXScreenConfigs. 242cdc920a0Smrg*/ 243cdc920a0Smrgstatic void 2443464ebd5SriastradhFreeScreenConfigs(struct glx_display * priv) 245cdc920a0Smrg{ 2463464ebd5Sriastradh struct glx_screen *psc; 247cdc920a0Smrg GLint i, screens; 248cdc920a0Smrg 249cdc920a0Smrg /* Free screen configuration information */ 250cdc920a0Smrg screens = ScreenCount(priv->dpy); 2513464ebd5Sriastradh for (i = 0; i < screens; i++) { 2523464ebd5Sriastradh psc = priv->screens[i]; 2539f464c52Smaya if (!psc) 2549f464c52Smaya continue; 2553464ebd5Sriastradh glx_screen_cleanup(psc); 256cdc920a0Smrg 257cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 258cdc920a0Smrg if (psc->driScreen) { 259cdc920a0Smrg psc->driScreen->destroyScreen(psc); 2603464ebd5Sriastradh } else { 261af69d88dSmrg free(psc); 262cdc920a0Smrg } 2633464ebd5Sriastradh#else 264af69d88dSmrg free(psc); 265cdc920a0Smrg#endif 266cdc920a0Smrg } 267af69d88dSmrg free((char *) priv->screens); 2683464ebd5Sriastradh priv->screens = NULL; 269cdc920a0Smrg} 270cdc920a0Smrg 2713464ebd5Sriastradhstatic void 2723464ebd5Sriastradhglx_display_free(struct glx_display *priv) 273cdc920a0Smrg{ 2743464ebd5Sriastradh struct glx_context *gc; 2753464ebd5Sriastradh 2763464ebd5Sriastradh gc = __glXGetCurrentContext(); 2773464ebd5Sriastradh if (priv->dpy == gc->currentDpy) { 2783464ebd5Sriastradh gc->vtable->destroy(gc); 2793464ebd5Sriastradh __glXSetCurrentContextNull(); 2803464ebd5Sriastradh } 281cdc920a0Smrg 282cdc920a0Smrg FreeScreenConfigs(priv); 283af69d88dSmrg 284af69d88dSmrg __glxHashDestroy(priv->glXDrawHash); 285cdc920a0Smrg 286cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2873464ebd5Sriastradh __glxHashDestroy(priv->drawHash); 2883464ebd5Sriastradh 289cdc920a0Smrg /* Free the direct rendering per display data */ 290cdc920a0Smrg if (priv->driswDisplay) 291cdc920a0Smrg (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay); 292cdc920a0Smrg priv->driswDisplay = NULL; 293cdc920a0Smrg 294af69d88dSmrg#if defined (GLX_USE_DRM) 295cdc920a0Smrg if (priv->dri2Display) 296cdc920a0Smrg (*priv->dri2Display->destroyDisplay) (priv->dri2Display); 297cdc920a0Smrg priv->dri2Display = NULL; 298cdc920a0Smrg 299af69d88dSmrg if (priv->dri3Display) 300af69d88dSmrg (*priv->dri3Display->destroyDisplay) (priv->dri3Display); 301af69d88dSmrg priv->dri3Display = NULL; 302af69d88dSmrg#endif /* GLX_USE_DRM */ 30301e04c3fSmrg 30401e04c3fSmrg#if defined(GLX_USE_WINDOWSGL) 30501e04c3fSmrg if (priv->windowsdriDisplay) 30601e04c3fSmrg (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay); 30701e04c3fSmrg priv->windowsdriDisplay = NULL; 30801e04c3fSmrg#endif /* GLX_USE_WINDOWSGL */ 30901e04c3fSmrg 310af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ 311af69d88dSmrg 312af69d88dSmrg free((char *) priv); 313cdc920a0Smrg} 314cdc920a0Smrg 3153464ebd5Sriastradhstatic int 3163464ebd5Sriastradh__glXCloseDisplay(Display * dpy, XExtCodes * codes) 3173464ebd5Sriastradh{ 3183464ebd5Sriastradh struct glx_display *priv, **prev; 3193464ebd5Sriastradh 3203464ebd5Sriastradh _XLockMutex(_Xglobal_lock); 3213464ebd5Sriastradh prev = &glx_displays; 3223464ebd5Sriastradh for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) { 3233464ebd5Sriastradh if (priv->dpy == dpy) { 3243464ebd5Sriastradh *prev = priv->next; 3253464ebd5Sriastradh break; 3263464ebd5Sriastradh } 3273464ebd5Sriastradh } 3283464ebd5Sriastradh _XUnlockMutex(_Xglobal_lock); 3293464ebd5Sriastradh 330af69d88dSmrg if (priv != NULL) 331af69d88dSmrg glx_display_free(priv); 3323464ebd5Sriastradh 3333464ebd5Sriastradh return 1; 3343464ebd5Sriastradh} 335cdc920a0Smrg 336cdc920a0Smrg/* 337cdc920a0Smrg** Query the version of the GLX extension. This procedure works even if 338cdc920a0Smrg** the client extension is not completely set up. 339cdc920a0Smrg*/ 340cdc920a0Smrgstatic Bool 341cdc920a0SmrgQueryVersion(Display * dpy, int opcode, int *major, int *minor) 342cdc920a0Smrg{ 343cdc920a0Smrg xcb_connection_t *c = XGetXCBConnection(dpy); 344cdc920a0Smrg xcb_glx_query_version_reply_t *reply = xcb_glx_query_version_reply(c, 345cdc920a0Smrg xcb_glx_query_version 346cdc920a0Smrg (c, 347cdc920a0Smrg GLX_MAJOR_VERSION, 348cdc920a0Smrg GLX_MINOR_VERSION), 349cdc920a0Smrg NULL); 350cdc920a0Smrg 351af69d88dSmrg if (!reply) 352af69d88dSmrg return GL_FALSE; 353af69d88dSmrg 354cdc920a0Smrg if (reply->major_version != GLX_MAJOR_VERSION) { 355cdc920a0Smrg free(reply); 356cdc920a0Smrg return GL_FALSE; 357cdc920a0Smrg } 358cdc920a0Smrg *major = reply->major_version; 359cdc920a0Smrg *minor = min(reply->minor_version, GLX_MINOR_VERSION); 360cdc920a0Smrg free(reply); 361cdc920a0Smrg return GL_TRUE; 362cdc920a0Smrg} 363cdc920a0Smrg 364cdc920a0Smrg/* 365cdc920a0Smrg * We don't want to enable this GLX_OML_swap_method in glxext.h, 366cdc920a0Smrg * because we can't support it. The X server writes it out though, 367cdc920a0Smrg * so we should handle it somehow, to avoid false warnings. 368cdc920a0Smrg */ 369cdc920a0Smrgenum { 370cdc920a0Smrg IGNORE_GLX_SWAP_METHOD_OML = 0x8060 371cdc920a0Smrg}; 372cdc920a0Smrg 373cdc920a0Smrg 3743464ebd5Sriastradhstatic GLint 3753464ebd5Sriastradhconvert_from_x_visual_type(int visualType) 3763464ebd5Sriastradh{ 3773464ebd5Sriastradh static const int glx_visual_types[] = { 37801e04c3fSmrg [StaticGray] = GLX_STATIC_GRAY, 37901e04c3fSmrg [GrayScale] = GLX_GRAY_SCALE, 38001e04c3fSmrg [StaticColor] = GLX_STATIC_COLOR, 38101e04c3fSmrg [PseudoColor] = GLX_PSEUDO_COLOR, 38201e04c3fSmrg [TrueColor] = GLX_TRUE_COLOR, 38301e04c3fSmrg [DirectColor] = GLX_DIRECT_COLOR, 3843464ebd5Sriastradh }; 3853464ebd5Sriastradh 3863464ebd5Sriastradh if (visualType < ARRAY_SIZE(glx_visual_types)) 3873464ebd5Sriastradh return glx_visual_types[visualType]; 3883464ebd5Sriastradh 3893464ebd5Sriastradh return GLX_NONE; 3903464ebd5Sriastradh} 3913464ebd5Sriastradh 392cdc920a0Smrg/* 393cdc920a0Smrg * getVisualConfigs uses the !tagged_only path. 394cdc920a0Smrg * getFBConfigs uses the tagged_only path. 395cdc920a0Smrg */ 396cdc920a0Smrg_X_HIDDEN void 3973464ebd5Sriastradh__glXInitializeVisualConfigFromTags(struct glx_config * config, int count, 398cdc920a0Smrg const INT32 * bp, Bool tagged_only, 399cdc920a0Smrg Bool fbconfig_style_tags) 400cdc920a0Smrg{ 401cdc920a0Smrg int i; 402cdc920a0Smrg 403cdc920a0Smrg if (!tagged_only) { 404cdc920a0Smrg /* Copy in the first set of properties */ 405cdc920a0Smrg config->visualID = *bp++; 406cdc920a0Smrg 4073464ebd5Sriastradh config->visualType = convert_from_x_visual_type(*bp++); 408cdc920a0Smrg 4097ec681f3Smrg config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; 410cdc920a0Smrg 411cdc920a0Smrg config->redBits = *bp++; 412cdc920a0Smrg config->greenBits = *bp++; 413cdc920a0Smrg config->blueBits = *bp++; 414cdc920a0Smrg config->alphaBits = *bp++; 415cdc920a0Smrg config->accumRedBits = *bp++; 416cdc920a0Smrg config->accumGreenBits = *bp++; 417cdc920a0Smrg config->accumBlueBits = *bp++; 418cdc920a0Smrg config->accumAlphaBits = *bp++; 419cdc920a0Smrg 420cdc920a0Smrg config->doubleBufferMode = *bp++; 421cdc920a0Smrg config->stereoMode = *bp++; 422cdc920a0Smrg 423cdc920a0Smrg config->rgbBits = *bp++; 424cdc920a0Smrg config->depthBits = *bp++; 425cdc920a0Smrg config->stencilBits = *bp++; 426cdc920a0Smrg config->numAuxBuffers = *bp++; 427cdc920a0Smrg config->level = *bp++; 428cdc920a0Smrg 429cdc920a0Smrg#ifdef GLX_USE_APPLEGL 430cdc920a0Smrg /* AppleSGLX supports pixmap and pbuffers with all config. */ 431cdc920a0Smrg config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 432cdc920a0Smrg /* Unfortunately this can create an ABI compatibility problem. */ 433cdc920a0Smrg count -= 18; 434cdc920a0Smrg#else 435cdc920a0Smrg count -= __GLX_MIN_CONFIG_PROPS; 436cdc920a0Smrg#endif 437cdc920a0Smrg } 438cdc920a0Smrg 439cdc920a0Smrg /* 440cdc920a0Smrg ** Additional properties may be in a list at the end 441cdc920a0Smrg ** of the reply. They are in pairs of property type 442cdc920a0Smrg ** and property value. 443cdc920a0Smrg */ 444cdc920a0Smrg 445cdc920a0Smrg#define FETCH_OR_SET(tag) \ 446cdc920a0Smrg config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1 447cdc920a0Smrg 448cdc920a0Smrg for (i = 0; i < count; i += 2) { 449cdc920a0Smrg long int tag = *bp++; 450cdc920a0Smrg 451cdc920a0Smrg switch (tag) { 452cdc920a0Smrg case GLX_RGBA: 4537ec681f3Smrg if (fbconfig_style_tags) 4547ec681f3Smrg config->renderType = *bp++ ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; 4557ec681f3Smrg else 4567ec681f3Smrg config->renderType = GLX_RGBA_BIT; 457cdc920a0Smrg break; 458cdc920a0Smrg case GLX_BUFFER_SIZE: 459cdc920a0Smrg config->rgbBits = *bp++; 460cdc920a0Smrg break; 461cdc920a0Smrg case GLX_LEVEL: 462cdc920a0Smrg config->level = *bp++; 463cdc920a0Smrg break; 464cdc920a0Smrg case GLX_DOUBLEBUFFER: 465cdc920a0Smrg FETCH_OR_SET(doubleBufferMode); 466cdc920a0Smrg break; 467cdc920a0Smrg case GLX_STEREO: 468cdc920a0Smrg FETCH_OR_SET(stereoMode); 469cdc920a0Smrg break; 470cdc920a0Smrg case GLX_AUX_BUFFERS: 471cdc920a0Smrg config->numAuxBuffers = *bp++; 472cdc920a0Smrg break; 473cdc920a0Smrg case GLX_RED_SIZE: 474cdc920a0Smrg config->redBits = *bp++; 475cdc920a0Smrg break; 476cdc920a0Smrg case GLX_GREEN_SIZE: 477cdc920a0Smrg config->greenBits = *bp++; 478cdc920a0Smrg break; 479cdc920a0Smrg case GLX_BLUE_SIZE: 480cdc920a0Smrg config->blueBits = *bp++; 481cdc920a0Smrg break; 482cdc920a0Smrg case GLX_ALPHA_SIZE: 483cdc920a0Smrg config->alphaBits = *bp++; 484cdc920a0Smrg break; 485cdc920a0Smrg case GLX_DEPTH_SIZE: 486cdc920a0Smrg config->depthBits = *bp++; 487cdc920a0Smrg break; 488cdc920a0Smrg case GLX_STENCIL_SIZE: 489cdc920a0Smrg config->stencilBits = *bp++; 490cdc920a0Smrg break; 491cdc920a0Smrg case GLX_ACCUM_RED_SIZE: 492cdc920a0Smrg config->accumRedBits = *bp++; 493cdc920a0Smrg break; 494cdc920a0Smrg case GLX_ACCUM_GREEN_SIZE: 495cdc920a0Smrg config->accumGreenBits = *bp++; 496cdc920a0Smrg break; 497cdc920a0Smrg case GLX_ACCUM_BLUE_SIZE: 498cdc920a0Smrg config->accumBlueBits = *bp++; 499cdc920a0Smrg break; 500cdc920a0Smrg case GLX_ACCUM_ALPHA_SIZE: 501cdc920a0Smrg config->accumAlphaBits = *bp++; 502cdc920a0Smrg break; 503cdc920a0Smrg case GLX_VISUAL_CAVEAT_EXT: 504cdc920a0Smrg config->visualRating = *bp++; 505cdc920a0Smrg break; 506cdc920a0Smrg case GLX_X_VISUAL_TYPE: 507cdc920a0Smrg config->visualType = *bp++; 508cdc920a0Smrg break; 509cdc920a0Smrg case GLX_TRANSPARENT_TYPE: 510cdc920a0Smrg config->transparentPixel = *bp++; 511cdc920a0Smrg break; 512cdc920a0Smrg case GLX_TRANSPARENT_INDEX_VALUE: 513cdc920a0Smrg config->transparentIndex = *bp++; 514cdc920a0Smrg break; 515cdc920a0Smrg case GLX_TRANSPARENT_RED_VALUE: 516cdc920a0Smrg config->transparentRed = *bp++; 517cdc920a0Smrg break; 518cdc920a0Smrg case GLX_TRANSPARENT_GREEN_VALUE: 519cdc920a0Smrg config->transparentGreen = *bp++; 520cdc920a0Smrg break; 521cdc920a0Smrg case GLX_TRANSPARENT_BLUE_VALUE: 522cdc920a0Smrg config->transparentBlue = *bp++; 523cdc920a0Smrg break; 524cdc920a0Smrg case GLX_TRANSPARENT_ALPHA_VALUE: 525cdc920a0Smrg config->transparentAlpha = *bp++; 526cdc920a0Smrg break; 527cdc920a0Smrg case GLX_VISUAL_ID: 528cdc920a0Smrg config->visualID = *bp++; 529cdc920a0Smrg break; 530cdc920a0Smrg case GLX_DRAWABLE_TYPE: 531cdc920a0Smrg config->drawableType = *bp++; 532cdc920a0Smrg#ifdef GLX_USE_APPLEGL 533cdc920a0Smrg /* AppleSGLX supports pixmap and pbuffers with all config. */ 534cdc920a0Smrg config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 535cdc920a0Smrg#endif 536cdc920a0Smrg break; 537af69d88dSmrg case GLX_RENDER_TYPE: /* fbconfig render type bits */ 5387ec681f3Smrg config->renderType = *bp++; 539cdc920a0Smrg break; 540cdc920a0Smrg case GLX_X_RENDERABLE: 541cdc920a0Smrg config->xRenderable = *bp++; 542cdc920a0Smrg break; 543cdc920a0Smrg case GLX_FBCONFIG_ID: 544cdc920a0Smrg config->fbconfigID = *bp++; 545cdc920a0Smrg break; 546cdc920a0Smrg case GLX_MAX_PBUFFER_WIDTH: 547cdc920a0Smrg config->maxPbufferWidth = *bp++; 548cdc920a0Smrg break; 549cdc920a0Smrg case GLX_MAX_PBUFFER_HEIGHT: 550cdc920a0Smrg config->maxPbufferHeight = *bp++; 551cdc920a0Smrg break; 552cdc920a0Smrg case GLX_MAX_PBUFFER_PIXELS: 553cdc920a0Smrg config->maxPbufferPixels = *bp++; 554cdc920a0Smrg break; 555cdc920a0Smrg#ifndef GLX_USE_APPLEGL 556cdc920a0Smrg case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: 557cdc920a0Smrg config->optimalPbufferWidth = *bp++; 558cdc920a0Smrg break; 559cdc920a0Smrg case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: 560cdc920a0Smrg config->optimalPbufferHeight = *bp++; 561cdc920a0Smrg break; 562cdc920a0Smrg case GLX_VISUAL_SELECT_GROUP_SGIX: 563cdc920a0Smrg config->visualSelectGroup = *bp++; 564cdc920a0Smrg break; 565cdc920a0Smrg case GLX_SWAP_METHOD_OML: 56601e04c3fSmrg if (*bp == GLX_SWAP_UNDEFINED_OML || 56701e04c3fSmrg *bp == GLX_SWAP_COPY_OML || 56801e04c3fSmrg *bp == GLX_SWAP_EXCHANGE_OML) { 56901e04c3fSmrg config->swapMethod = *bp++; 57001e04c3fSmrg } else { 57101e04c3fSmrg /* X servers with old HW drivers may return any value here, so 57201e04c3fSmrg * assume GLX_SWAP_METHOD_UNDEFINED. 57301e04c3fSmrg */ 57401e04c3fSmrg config->swapMethod = GLX_SWAP_UNDEFINED_OML; 57501e04c3fSmrg bp++; 57601e04c3fSmrg } 577cdc920a0Smrg break; 578cdc920a0Smrg#endif 579cdc920a0Smrg case GLX_SAMPLE_BUFFERS_SGIS: 580cdc920a0Smrg config->sampleBuffers = *bp++; 581cdc920a0Smrg break; 582cdc920a0Smrg case GLX_SAMPLES_SGIS: 583cdc920a0Smrg config->samples = *bp++; 584cdc920a0Smrg break; 585cdc920a0Smrg#ifdef GLX_USE_APPLEGL 586cdc920a0Smrg case IGNORE_GLX_SWAP_METHOD_OML: 587cdc920a0Smrg /* We ignore this tag. See the comment above this function. */ 588cdc920a0Smrg ++bp; 589cdc920a0Smrg break; 590cdc920a0Smrg#else 591cdc920a0Smrg case GLX_BIND_TO_TEXTURE_RGB_EXT: 592cdc920a0Smrg config->bindToTextureRgb = *bp++; 593cdc920a0Smrg break; 594cdc920a0Smrg case GLX_BIND_TO_TEXTURE_RGBA_EXT: 595cdc920a0Smrg config->bindToTextureRgba = *bp++; 596cdc920a0Smrg break; 597cdc920a0Smrg case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 598cdc920a0Smrg config->bindToMipmapTexture = *bp++; 599cdc920a0Smrg break; 600cdc920a0Smrg case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 601cdc920a0Smrg config->bindToTextureTargets = *bp++; 602cdc920a0Smrg break; 603cdc920a0Smrg case GLX_Y_INVERTED_EXT: 604cdc920a0Smrg config->yInverted = *bp++; 605cdc920a0Smrg break; 606cdc920a0Smrg#endif 6073464ebd5Sriastradh case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT: 6083464ebd5Sriastradh config->sRGBCapable = *bp++; 6093464ebd5Sriastradh break; 6103464ebd5Sriastradh 611cdc920a0Smrg case GLX_USE_GL: 612cdc920a0Smrg if (fbconfig_style_tags) 613cdc920a0Smrg bp++; 614cdc920a0Smrg break; 615cdc920a0Smrg case None: 616cdc920a0Smrg i = count; 617cdc920a0Smrg break; 6187ec681f3Smrg default: { 6197ec681f3Smrg long int tagvalue = *bp++; 6207ec681f3Smrg DebugMessageF("WARNING: unknown fbconfig attribute from server: " 6217ec681f3Smrg "tag 0x%lx value 0x%lx\n", tag, tagvalue); 6227ec681f3Smrg break; 623cdc920a0Smrg } 624cdc920a0Smrg } 625cdc920a0Smrg } 626cdc920a0Smrg} 627cdc920a0Smrg 6283464ebd5Sriastradhstatic struct glx_config * 629cdc920a0SmrgcreateConfigsFromProperties(Display * dpy, int nvisuals, int nprops, 630cdc920a0Smrg int screen, GLboolean tagged_only) 631cdc920a0Smrg{ 632cdc920a0Smrg INT32 buf[__GLX_TOTAL_CONFIG], *props; 633cdc920a0Smrg unsigned prop_size; 6343464ebd5Sriastradh struct glx_config *modes, *m; 635cdc920a0Smrg int i; 636cdc920a0Smrg 637cdc920a0Smrg if (nprops == 0) 638cdc920a0Smrg return NULL; 639cdc920a0Smrg 640cdc920a0Smrg /* Check number of properties */ 6417ec681f3Smrg if (nprops < __GLX_MIN_CONFIG_PROPS) 642cdc920a0Smrg return NULL; 643cdc920a0Smrg 644cdc920a0Smrg /* Allocate memory for our config structure */ 6453464ebd5Sriastradh modes = glx_config_create_list(nvisuals); 646cdc920a0Smrg if (!modes) 647cdc920a0Smrg return NULL; 648cdc920a0Smrg 649cdc920a0Smrg prop_size = nprops * __GLX_SIZE_INT32; 650cdc920a0Smrg if (prop_size <= sizeof(buf)) 651cdc920a0Smrg props = buf; 652cdc920a0Smrg else 653af69d88dSmrg props = malloc(prop_size); 654cdc920a0Smrg 655cdc920a0Smrg /* Read each config structure and convert it into our format */ 656cdc920a0Smrg m = modes; 657cdc920a0Smrg for (i = 0; i < nvisuals; i++) { 658cdc920a0Smrg _XRead(dpy, (char *) props, prop_size); 659cdc920a0Smrg#ifdef GLX_USE_APPLEGL 660cdc920a0Smrg /* Older X servers don't send this so we default it here. */ 661cdc920a0Smrg m->drawableType = GLX_WINDOW_BIT; 662cdc920a0Smrg#else 663cdc920a0Smrg /* 664cdc920a0Smrg * The XQuartz 2.3.2.1 X server doesn't set this properly, so 665cdc920a0Smrg * set the proper bits here. 666cdc920a0Smrg * AppleSGLX supports windows, pixmaps, and pbuffers with all config. 667cdc920a0Smrg */ 668cdc920a0Smrg m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 669cdc920a0Smrg#endif 670cdc920a0Smrg __glXInitializeVisualConfigFromTags(m, nprops, props, 671cdc920a0Smrg tagged_only, GL_TRUE); 672cdc920a0Smrg m->screen = screen; 673cdc920a0Smrg m = m->next; 674cdc920a0Smrg } 675cdc920a0Smrg 676cdc920a0Smrg if (props != buf) 677af69d88dSmrg free(props); 678cdc920a0Smrg 679cdc920a0Smrg return modes; 680cdc920a0Smrg} 681cdc920a0Smrg 682cdc920a0Smrgstatic GLboolean 6833464ebd5SriastradhgetVisualConfigs(struct glx_screen *psc, 6843464ebd5Sriastradh struct glx_display *priv, int screen) 685cdc920a0Smrg{ 686cdc920a0Smrg xGLXGetVisualConfigsReq *req; 687cdc920a0Smrg xGLXGetVisualConfigsReply reply; 6883464ebd5Sriastradh Display *dpy = priv->dpy; 689cdc920a0Smrg 690cdc920a0Smrg LockDisplay(dpy); 691cdc920a0Smrg 692cdc920a0Smrg psc->visuals = NULL; 693cdc920a0Smrg GetReq(GLXGetVisualConfigs, req); 6947ec681f3Smrg req->reqType = priv->codes.major_opcode; 695cdc920a0Smrg req->glxCode = X_GLXGetVisualConfigs; 696cdc920a0Smrg req->screen = screen; 697cdc920a0Smrg 698cdc920a0Smrg if (!_XReply(dpy, (xReply *) & reply, 0, False)) 699cdc920a0Smrg goto out; 700cdc920a0Smrg 701cdc920a0Smrg psc->visuals = createConfigsFromProperties(dpy, 702cdc920a0Smrg reply.numVisuals, 703cdc920a0Smrg reply.numProps, 704cdc920a0Smrg screen, GL_FALSE); 705cdc920a0Smrg 706cdc920a0Smrg out: 707cdc920a0Smrg UnlockDisplay(dpy); 708cdc920a0Smrg return psc->visuals != NULL; 709cdc920a0Smrg} 710cdc920a0Smrg 711cdc920a0Smrgstatic GLboolean 7127ec681f3SmrggetFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen) 713cdc920a0Smrg{ 714cdc920a0Smrg xGLXGetFBConfigsReq *fb_req; 715cdc920a0Smrg xGLXGetFBConfigsSGIXReq *sgi_req; 716cdc920a0Smrg xGLXVendorPrivateWithReplyReq *vpreq; 717cdc920a0Smrg xGLXGetFBConfigsReply reply; 7183464ebd5Sriastradh Display *dpy = priv->dpy; 719cdc920a0Smrg 7207ec681f3Smrg psc->serverGLXexts = __glXQueryServerString(dpy, screen, GLX_EXTENSIONS); 721cdc920a0Smrg 722af69d88dSmrg if (psc->serverGLXexts == NULL) { 723af69d88dSmrg return GL_FALSE; 724af69d88dSmrg } 725af69d88dSmrg 726cdc920a0Smrg LockDisplay(dpy); 727cdc920a0Smrg 728cdc920a0Smrg psc->configs = NULL; 7297ec681f3Smrg if (priv->minorVersion >= 3) { 730cdc920a0Smrg GetReq(GLXGetFBConfigs, fb_req); 7317ec681f3Smrg fb_req->reqType = priv->codes.major_opcode; 732cdc920a0Smrg fb_req->glxCode = X_GLXGetFBConfigs; 733cdc920a0Smrg fb_req->screen = screen; 734cdc920a0Smrg } 735cdc920a0Smrg else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { 736cdc920a0Smrg GetReqExtra(GLXVendorPrivateWithReply, 7373464ebd5Sriastradh sz_xGLXGetFBConfigsSGIXReq - 738cdc920a0Smrg sz_xGLXVendorPrivateWithReplyReq, vpreq); 739cdc920a0Smrg sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; 7407ec681f3Smrg sgi_req->reqType = priv->codes.major_opcode; 741cdc920a0Smrg sgi_req->glxCode = X_GLXVendorPrivateWithReply; 742cdc920a0Smrg sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; 743cdc920a0Smrg sgi_req->screen = screen; 744cdc920a0Smrg } 745cdc920a0Smrg else 746cdc920a0Smrg goto out; 747cdc920a0Smrg 748cdc920a0Smrg if (!_XReply(dpy, (xReply *) & reply, 0, False)) 749cdc920a0Smrg goto out; 750cdc920a0Smrg 751cdc920a0Smrg psc->configs = createConfigsFromProperties(dpy, 752cdc920a0Smrg reply.numFBConfigs, 753cdc920a0Smrg reply.numAttribs * 2, 754cdc920a0Smrg screen, GL_TRUE); 755cdc920a0Smrg 756cdc920a0Smrg out: 757cdc920a0Smrg UnlockDisplay(dpy); 758cdc920a0Smrg return psc->configs != NULL; 759cdc920a0Smrg} 760cdc920a0Smrg 7613464ebd5Sriastradh_X_HIDDEN Bool 7623464ebd5Sriastradhglx_screen_init(struct glx_screen *psc, 7633464ebd5Sriastradh int screen, struct glx_display * priv) 7643464ebd5Sriastradh{ 7653464ebd5Sriastradh /* Initialize per screen dynamic client GLX extensions */ 7663464ebd5Sriastradh psc->ext_list_first_time = GL_TRUE; 7673464ebd5Sriastradh psc->scr = screen; 7683464ebd5Sriastradh psc->dpy = priv->dpy; 7693464ebd5Sriastradh psc->display = priv; 7703464ebd5Sriastradh 77101e04c3fSmrg if (!getVisualConfigs(psc, priv, screen)) 77201e04c3fSmrg return GL_FALSE; 77301e04c3fSmrg 77401e04c3fSmrg if (!getFBConfigs(psc, priv, screen)) 77501e04c3fSmrg return GL_FALSE; 7763464ebd5Sriastradh 7773464ebd5Sriastradh return GL_TRUE; 7783464ebd5Sriastradh} 7793464ebd5Sriastradh 7803464ebd5Sriastradh_X_HIDDEN void 7813464ebd5Sriastradhglx_screen_cleanup(struct glx_screen *psc) 7823464ebd5Sriastradh{ 7833464ebd5Sriastradh if (psc->configs) { 7843464ebd5Sriastradh glx_config_destroy_list(psc->configs); 785af69d88dSmrg free(psc->effectiveGLXexts); 7863464ebd5Sriastradh psc->configs = NULL; /* NOTE: just for paranoia */ 7873464ebd5Sriastradh } 7883464ebd5Sriastradh if (psc->visuals) { 7893464ebd5Sriastradh glx_config_destroy_list(psc->visuals); 7903464ebd5Sriastradh psc->visuals = NULL; /* NOTE: just for paranoia */ 7913464ebd5Sriastradh } 792af69d88dSmrg free((char *) psc->serverGLXexts); 7937ec681f3Smrg free((char *) psc->serverGLXvendor); 7947ec681f3Smrg free((char *) psc->serverGLXversion); 7953464ebd5Sriastradh} 7963464ebd5Sriastradh 797cdc920a0Smrg/* 798cdc920a0Smrg** Allocate the memory for the per screen configs for each screen. 799cdc920a0Smrg** If that works then fetch the per screen configs data. 800cdc920a0Smrg*/ 801cdc920a0Smrgstatic Bool 8023464ebd5SriastradhAllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv) 803cdc920a0Smrg{ 8043464ebd5Sriastradh struct glx_screen *psc; 805cdc920a0Smrg GLint i, screens; 806cdc920a0Smrg 807cdc920a0Smrg /* 808cdc920a0Smrg ** First allocate memory for the array of per screen configs. 809cdc920a0Smrg */ 810cdc920a0Smrg screens = ScreenCount(dpy); 8119f464c52Smaya priv->screens = calloc(screens, sizeof *priv->screens); 8123464ebd5Sriastradh if (!priv->screens) 813cdc920a0Smrg return GL_FALSE; 814cdc920a0Smrg 815cdc920a0Smrg for (i = 0; i < screens; i++, psc++) { 8163464ebd5Sriastradh psc = NULL; 817cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 818af69d88dSmrg#if defined(GLX_USE_DRM) 819af69d88dSmrg#if defined(HAVE_DRI3) 820af69d88dSmrg if (priv->dri3Display) 821af69d88dSmrg psc = (*priv->dri3Display->createScreen) (i, priv); 822af69d88dSmrg#endif /* HAVE_DRI3 */ 823af69d88dSmrg if (psc == NULL && priv->dri2Display) 8243464ebd5Sriastradh psc = (*priv->dri2Display->createScreen) (i, priv); 825af69d88dSmrg#endif /* GLX_USE_DRM */ 82601e04c3fSmrg 82701e04c3fSmrg#ifdef GLX_USE_WINDOWSGL 82801e04c3fSmrg if (psc == NULL && priv->windowsdriDisplay) 82901e04c3fSmrg psc = (*priv->windowsdriDisplay->createScreen) (i, priv); 83001e04c3fSmrg#endif 83101e04c3fSmrg 8323464ebd5Sriastradh if (psc == NULL && priv->driswDisplay) 8333464ebd5Sriastradh psc = (*priv->driswDisplay->createScreen) (i, priv); 834af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ 835af69d88dSmrg 8363464ebd5Sriastradh#if defined(GLX_USE_APPLEGL) 8373464ebd5Sriastradh if (psc == NULL) 8383464ebd5Sriastradh psc = applegl_create_screen(i, priv); 8393464ebd5Sriastradh#else 8403464ebd5Sriastradh if (psc == NULL) 8413464ebd5Sriastradh psc = indirect_create_screen(i, priv); 8423464ebd5Sriastradh#endif 8433464ebd5Sriastradh priv->screens[i] = psc; 844cdc920a0Smrg } 845cdc920a0Smrg SyncHandle(); 846cdc920a0Smrg return GL_TRUE; 847cdc920a0Smrg} 848cdc920a0Smrg 849cdc920a0Smrg/* 850cdc920a0Smrg** Initialize the client side extension code. 851cdc920a0Smrg*/ 8523464ebd5Sriastradh _X_HIDDEN struct glx_display * 853cdc920a0Smrg__glXInitialize(Display * dpy) 854cdc920a0Smrg{ 8557ec681f3Smrg XExtCodes *codes; 8563464ebd5Sriastradh struct glx_display *dpyPriv, *d; 857cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 858cdc920a0Smrg Bool glx_direct, glx_accel; 859cdc920a0Smrg#endif 8607ec681f3Smrg int i, majorVersion = 0; 861cdc920a0Smrg 8623464ebd5Sriastradh _XLockMutex(_Xglobal_lock); 863cdc920a0Smrg 8643464ebd5Sriastradh for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) { 8653464ebd5Sriastradh if (dpyPriv->dpy == dpy) { 8663464ebd5Sriastradh _XUnlockMutex(_Xglobal_lock); 8673464ebd5Sriastradh return dpyPriv; 8683464ebd5Sriastradh } 869cdc920a0Smrg } 870cdc920a0Smrg 8713464ebd5Sriastradh /* Drop the lock while we create the display private. */ 8723464ebd5Sriastradh _XUnlockMutex(_Xglobal_lock); 873cdc920a0Smrg 874af69d88dSmrg dpyPriv = calloc(1, sizeof *dpyPriv); 8753464ebd5Sriastradh if (!dpyPriv) 8763464ebd5Sriastradh return NULL; 877cdc920a0Smrg 8787ec681f3Smrg codes = XInitExtension(dpy, __glXExtensionName); 8797ec681f3Smrg if (!codes) { 880af69d88dSmrg free(dpyPriv); 8813464ebd5Sriastradh return NULL; 882cdc920a0Smrg } 883cdc920a0Smrg 8847ec681f3Smrg dpyPriv->codes = *codes; 885cdc920a0Smrg dpyPriv->dpy = dpy; 886cdc920a0Smrg 8877ec681f3Smrg /* This GLX implementation requires X_GLXQueryExtensionsString 8887ec681f3Smrg * and X_GLXQueryServerString, which are new in GLX 1.1. 889af69d88dSmrg */ 8907ec681f3Smrg if (!QueryVersion(dpy, dpyPriv->codes.major_opcode, 8917ec681f3Smrg &majorVersion, &dpyPriv->minorVersion) 8927ec681f3Smrg || (majorVersion != 1) 8937ec681f3Smrg || (majorVersion == 1 && dpyPriv->minorVersion < 1)) { 894af69d88dSmrg free(dpyPriv); 8953464ebd5Sriastradh return NULL; 8963464ebd5Sriastradh } 8973464ebd5Sriastradh 8983464ebd5Sriastradh for (i = 0; i < __GLX_NUMBER_EVENTS; i++) { 8997ec681f3Smrg XESetWireToEvent(dpy, dpyPriv->codes.first_event + i, __glXWireToEvent); 9007ec681f3Smrg XESetEventToWire(dpy, dpyPriv->codes.first_event + i, __glXEventToWire); 9013464ebd5Sriastradh } 9023464ebd5Sriastradh 9037ec681f3Smrg XESetCloseDisplay(dpy, dpyPriv->codes.extension, __glXCloseDisplay); 9047ec681f3Smrg XESetErrorString (dpy, dpyPriv->codes.extension, __glXErrorString); 9053464ebd5Sriastradh 906af69d88dSmrg dpyPriv->glXDrawHash = __glxHashCreate(); 907af69d88dSmrg 908cdc920a0Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 90901e04c3fSmrg glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false); 91001e04c3fSmrg glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false); 911cdc920a0Smrg 9123464ebd5Sriastradh dpyPriv->drawHash = __glxHashCreate(); 9133464ebd5Sriastradh 9147ec681f3Smrg#ifndef GLX_USE_APPLEGL 9157ec681f3Smrg /* Set the logger before the *CreateDisplay functions. */ 9167ec681f3Smrg loader_set_logger(glx_message); 9177ec681f3Smrg#endif 9187ec681f3Smrg 919cdc920a0Smrg /* 920cdc920a0Smrg ** Initialize the direct rendering per display data and functions. 921cdc920a0Smrg ** Note: This _must_ be done before calling any other DRI routines 922cdc920a0Smrg ** (e.g., those called in AllocAndFetchScreenConfigs). 923cdc920a0Smrg */ 924af69d88dSmrg#if defined(GLX_USE_DRM) 925cdc920a0Smrg if (glx_direct && glx_accel) { 926af69d88dSmrg#if defined(HAVE_DRI3) 92701e04c3fSmrg if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false)) 928af69d88dSmrg dpyPriv->dri3Display = dri3_create_display(dpy); 929af69d88dSmrg#endif /* HAVE_DRI3 */ 9307ec681f3Smrg if (!env_var_as_boolean("LIBGL_DRI2_DISABLE", false)) 9317ec681f3Smrg dpyPriv->dri2Display = dri2CreateDisplay(dpy); 932cdc920a0Smrg } 933af69d88dSmrg#endif /* GLX_USE_DRM */ 934cdc920a0Smrg if (glx_direct) 935cdc920a0Smrg dpyPriv->driswDisplay = driswCreateDisplay(dpy); 936af69d88dSmrg#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ 9373464ebd5Sriastradh 938cdc920a0Smrg#ifdef GLX_USE_APPLEGL 9393464ebd5Sriastradh if (!applegl_create_display(dpyPriv)) { 940af69d88dSmrg free(dpyPriv); 9413464ebd5Sriastradh return NULL; 9423464ebd5Sriastradh } 943cdc920a0Smrg#endif 94401e04c3fSmrg 94501e04c3fSmrg#ifdef GLX_USE_WINDOWSGL 94601e04c3fSmrg if (glx_direct && glx_accel) 94701e04c3fSmrg dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy); 94801e04c3fSmrg#endif 94901e04c3fSmrg 9503464ebd5Sriastradh if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { 951af69d88dSmrg free(dpyPriv); 9523464ebd5Sriastradh return NULL; 953cdc920a0Smrg } 954cdc920a0Smrg 955af69d88dSmrg __glX_send_client_info(dpyPriv); 9563464ebd5Sriastradh 9573464ebd5Sriastradh /* Grab the lock again and add the dispay private, unless somebody 9583464ebd5Sriastradh * beat us to initializing on this display in the meantime. */ 9593464ebd5Sriastradh _XLockMutex(_Xglobal_lock); 9603464ebd5Sriastradh 9613464ebd5Sriastradh for (d = glx_displays; d; d = d->next) { 9623464ebd5Sriastradh if (d->dpy == dpy) { 9633464ebd5Sriastradh _XUnlockMutex(_Xglobal_lock); 9643464ebd5Sriastradh glx_display_free(dpyPriv); 9653464ebd5Sriastradh return d; 9663464ebd5Sriastradh } 967cdc920a0Smrg } 9683464ebd5Sriastradh 9693464ebd5Sriastradh dpyPriv->next = glx_displays; 9703464ebd5Sriastradh glx_displays = dpyPriv; 9713464ebd5Sriastradh 972af69d88dSmrg _XUnlockMutex(_Xglobal_lock); 973cdc920a0Smrg 974cdc920a0Smrg return dpyPriv; 975cdc920a0Smrg} 976cdc920a0Smrg 977cdc920a0Smrg/* 978cdc920a0Smrg** Setup for sending a GLX command on dpy. Make sure the extension is 979cdc920a0Smrg** initialized. Try to avoid calling __glXInitialize as its kinda slow. 980cdc920a0Smrg*/ 981cdc920a0Smrg_X_HIDDEN CARD8 982cdc920a0Smrg__glXSetupForCommand(Display * dpy) 983cdc920a0Smrg{ 9843464ebd5Sriastradh struct glx_context *gc; 9853464ebd5Sriastradh struct glx_display *priv; 986cdc920a0Smrg 987cdc920a0Smrg /* If this thread has a current context, flush its rendering commands */ 988cdc920a0Smrg gc = __glXGetCurrentContext(); 989cdc920a0Smrg if (gc->currentDpy) { 990cdc920a0Smrg /* Flush rendering buffer of the current context, if any */ 991cdc920a0Smrg (void) __glXFlushRenderBuffer(gc, gc->pc); 992cdc920a0Smrg 993cdc920a0Smrg if (gc->currentDpy == dpy) { 994cdc920a0Smrg /* Use opcode from gc because its right */ 995cdc920a0Smrg return gc->majorOpcode; 996cdc920a0Smrg } 997cdc920a0Smrg else { 998cdc920a0Smrg /* 999cdc920a0Smrg ** Have to get info about argument dpy because it might be to 1000cdc920a0Smrg ** a different server 1001cdc920a0Smrg */ 1002cdc920a0Smrg } 1003cdc920a0Smrg } 1004cdc920a0Smrg 1005cdc920a0Smrg /* Forced to lookup extension via the slow initialize route */ 1006cdc920a0Smrg priv = __glXInitialize(dpy); 1007cdc920a0Smrg if (!priv) { 1008cdc920a0Smrg return 0; 1009cdc920a0Smrg } 10107ec681f3Smrg return priv->codes.major_opcode; 1011cdc920a0Smrg} 1012cdc920a0Smrg 1013cdc920a0Smrg/** 1014cdc920a0Smrg * Flush the drawing command transport buffer. 1015cdc920a0Smrg * 1016cdc920a0Smrg * \param ctx Context whose transport buffer is to be flushed. 1017cdc920a0Smrg * \param pc Pointer to first unused buffer location. 1018cdc920a0Smrg * 1019cdc920a0Smrg * \todo 1020cdc920a0Smrg * Modify this function to use \c ctx->pc instead of the explicit 1021cdc920a0Smrg * \c pc parameter. 1022cdc920a0Smrg */ 1023cdc920a0Smrg_X_HIDDEN GLubyte * 10243464ebd5Sriastradh__glXFlushRenderBuffer(struct glx_context * ctx, GLubyte * pc) 1025cdc920a0Smrg{ 1026cdc920a0Smrg Display *const dpy = ctx->currentDpy; 1027cdc920a0Smrg xcb_connection_t *c = XGetXCBConnection(dpy); 1028cdc920a0Smrg const GLint size = pc - ctx->buf; 1029cdc920a0Smrg 1030cdc920a0Smrg if ((dpy != NULL) && (size > 0)) { 1031cdc920a0Smrg xcb_glx_render(c, ctx->currentContextTag, size, 1032cdc920a0Smrg (const uint8_t *) ctx->buf); 1033cdc920a0Smrg } 1034cdc920a0Smrg 1035cdc920a0Smrg /* Reset pointer and return it */ 1036cdc920a0Smrg ctx->pc = ctx->buf; 1037cdc920a0Smrg return ctx->pc; 1038cdc920a0Smrg} 1039cdc920a0Smrg 1040cdc920a0Smrg 1041cdc920a0Smrg/** 1042cdc920a0Smrg * Send a portion of a GLXRenderLarge command to the server. The advantage of 1043cdc920a0Smrg * this function over \c __glXSendLargeCommand is that callers can use the 1044cdc920a0Smrg * data buffer in the GLX context and may be able to avoid allocating an 1045cdc920a0Smrg * extra buffer. The disadvantage is the clients will have to do more 1046cdc920a0Smrg * GLX protocol work (i.e., calculating \c totalRequests, etc.). 1047cdc920a0Smrg * 1048cdc920a0Smrg * \sa __glXSendLargeCommand 1049cdc920a0Smrg * 1050cdc920a0Smrg * \param gc GLX context 1051cdc920a0Smrg * \param requestNumber Which part of the whole command is this? The first 1052cdc920a0Smrg * request is 1. 1053cdc920a0Smrg * \param totalRequests How many requests will there be? 1054cdc920a0Smrg * \param data Command data. 1055cdc920a0Smrg * \param dataLen Size, in bytes, of the command data. 1056cdc920a0Smrg */ 1057cdc920a0Smrg_X_HIDDEN void 10583464ebd5Sriastradh__glXSendLargeChunk(struct glx_context * gc, GLint requestNumber, 1059cdc920a0Smrg GLint totalRequests, const GLvoid * data, GLint dataLen) 1060cdc920a0Smrg{ 1061cdc920a0Smrg Display *dpy = gc->currentDpy; 1062cdc920a0Smrg xcb_connection_t *c = XGetXCBConnection(dpy); 1063cdc920a0Smrg xcb_glx_render_large(c, gc->currentContextTag, requestNumber, 1064cdc920a0Smrg totalRequests, dataLen, data); 1065cdc920a0Smrg} 1066cdc920a0Smrg 1067cdc920a0Smrg 1068cdc920a0Smrg/** 1069cdc920a0Smrg * Send a command that is too large for the GLXRender protocol request. 1070cdc920a0Smrg * 1071cdc920a0Smrg * Send a large command, one that is too large for some reason to 1072cdc920a0Smrg * send using the GLXRender protocol request. One reason to send 1073cdc920a0Smrg * a large command is to avoid copying the data. 1074cdc920a0Smrg * 1075cdc920a0Smrg * \param ctx GLX context 1076cdc920a0Smrg * \param header Header data. 1077cdc920a0Smrg * \param headerLen Size, in bytes, of the header data. It is assumed that 1078cdc920a0Smrg * the header data will always be small enough to fit in 1079cdc920a0Smrg * a single X protocol packet. 1080cdc920a0Smrg * \param data Command data. 1081cdc920a0Smrg * \param dataLen Size, in bytes, of the command data. 1082cdc920a0Smrg */ 1083cdc920a0Smrg_X_HIDDEN void 10843464ebd5Sriastradh__glXSendLargeCommand(struct glx_context * ctx, 1085cdc920a0Smrg const GLvoid * header, GLint headerLen, 1086cdc920a0Smrg const GLvoid * data, GLint dataLen) 1087cdc920a0Smrg{ 1088cdc920a0Smrg GLint maxSize; 1089cdc920a0Smrg GLint totalRequests, requestNumber; 1090cdc920a0Smrg 1091cdc920a0Smrg /* 1092cdc920a0Smrg ** Calculate the maximum amount of data can be stuffed into a single 1093cdc920a0Smrg ** packet. sz_xGLXRenderReq is added because bufSize is the maximum 1094cdc920a0Smrg ** packet size minus sz_xGLXRenderReq. 1095cdc920a0Smrg */ 1096cdc920a0Smrg maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq; 1097cdc920a0Smrg totalRequests = 1 + (dataLen / maxSize); 1098cdc920a0Smrg if (dataLen % maxSize) 1099cdc920a0Smrg totalRequests++; 1100cdc920a0Smrg 1101cdc920a0Smrg /* 1102cdc920a0Smrg ** Send all of the command, except the large array, as one request. 1103cdc920a0Smrg */ 1104cdc920a0Smrg assert(headerLen <= maxSize); 1105cdc920a0Smrg __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen); 1106cdc920a0Smrg 1107cdc920a0Smrg /* 1108cdc920a0Smrg ** Send enough requests until the whole array is sent. 1109cdc920a0Smrg */ 1110cdc920a0Smrg for (requestNumber = 2; requestNumber <= (totalRequests - 1); 1111cdc920a0Smrg requestNumber++) { 1112cdc920a0Smrg __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize); 1113cdc920a0Smrg data = (const GLvoid *) (((const GLubyte *) data) + maxSize); 1114cdc920a0Smrg dataLen -= maxSize; 1115cdc920a0Smrg assert(dataLen > 0); 1116cdc920a0Smrg } 1117cdc920a0Smrg 1118cdc920a0Smrg assert(dataLen <= maxSize); 1119cdc920a0Smrg __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen); 1120cdc920a0Smrg} 1121