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 glxcmds.c 33848b8605Smrg * Client-side GLX interface. 34848b8605Smrg */ 35848b8605Smrg 36848b8605Smrg#include "glxclient.h" 37848b8605Smrg#include "glapi.h" 38848b8605Smrg#include "glxextensions.h" 39848b8605Smrg#include "indirect.h" 40848b8605Smrg#include "glx_error.h" 41848b8605Smrg 42848b8605Smrg#ifdef GLX_DIRECT_RENDERING 43848b8605Smrg#ifdef GLX_USE_APPLEGL 44848b8605Smrg#include "apple/apple_glx_context.h" 45848b8605Smrg#include "apple/apple_glx.h" 46b8e80941Smrg#include "util/debug.h" 47848b8605Smrg#else 48848b8605Smrg#include <sys/time.h> 49b8e80941Smrg#ifndef GLX_USE_WINDOWSGL 50848b8605Smrg#include <X11/extensions/xf86vmode.h> 51b8e80941Smrg#endif /* GLX_USE_WINDOWSGL */ 52848b8605Smrg#endif 53848b8605Smrg#endif 54848b8605Smrg 55848b8605Smrg#include <X11/Xlib-xcb.h> 56848b8605Smrg#include <xcb/xcb.h> 57848b8605Smrg#include <xcb/glx.h> 58b8e80941Smrg#include "GL/mesa_glinterop.h" 59848b8605Smrg 60848b8605Smrgstatic const char __glXGLXClientVendorName[] = "Mesa Project and SGI"; 61848b8605Smrgstatic const char __glXGLXClientVersion[] = "1.4"; 62848b8605Smrg 63848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 64848b8605Smrg 65848b8605Smrg/** 66848b8605Smrg * Get the __DRIdrawable for the drawable associated with a GLXContext 67848b8605Smrg * 68848b8605Smrg * \param dpy The display associated with \c drawable. 69848b8605Smrg * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved. 70848b8605Smrg * \param scrn_num If non-NULL, the drawables screen is stored there 71848b8605Smrg * \returns A pointer to the context's __DRIdrawable on success, or NULL if 72848b8605Smrg * the drawable is not associated with a direct-rendering context. 73848b8605Smrg */ 74848b8605Smrg_X_HIDDEN __GLXDRIdrawable * 75848b8605SmrgGetGLXDRIDrawable(Display * dpy, GLXDrawable drawable) 76848b8605Smrg{ 77848b8605Smrg struct glx_display *priv = __glXInitialize(dpy); 78848b8605Smrg __GLXDRIdrawable *pdraw; 79848b8605Smrg 80848b8605Smrg if (priv == NULL) 81848b8605Smrg return NULL; 82848b8605Smrg 83848b8605Smrg if (__glxHashLookup(priv->drawHash, drawable, (void *) &pdraw) == 0) 84848b8605Smrg return pdraw; 85848b8605Smrg 86848b8605Smrg return NULL; 87848b8605Smrg} 88848b8605Smrg 89848b8605Smrg#endif 90848b8605Smrg 91848b8605Smrg_X_HIDDEN struct glx_drawable * 92848b8605SmrgGetGLXDrawable(Display *dpy, GLXDrawable drawable) 93848b8605Smrg{ 94848b8605Smrg struct glx_display *priv = __glXInitialize(dpy); 95848b8605Smrg struct glx_drawable *glxDraw; 96848b8605Smrg 97848b8605Smrg if (priv == NULL) 98848b8605Smrg return NULL; 99848b8605Smrg 100848b8605Smrg if (__glxHashLookup(priv->glXDrawHash, drawable, (void *) &glxDraw) == 0) 101848b8605Smrg return glxDraw; 102848b8605Smrg 103848b8605Smrg return NULL; 104848b8605Smrg} 105848b8605Smrg 106848b8605Smrg_X_HIDDEN int 107848b8605SmrgInitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw, XID xDrawable, 108848b8605Smrg GLXDrawable drawable) 109848b8605Smrg{ 110848b8605Smrg struct glx_display *priv = __glXInitialize(dpy); 111848b8605Smrg 112848b8605Smrg if (!priv) 113848b8605Smrg return -1; 114848b8605Smrg 115848b8605Smrg glxDraw->xDrawable = xDrawable; 116848b8605Smrg glxDraw->drawable = drawable; 117848b8605Smrg glxDraw->lastEventSbc = 0; 118848b8605Smrg glxDraw->eventSbcWrap = 0; 119848b8605Smrg 120848b8605Smrg return __glxHashInsert(priv->glXDrawHash, drawable, glxDraw); 121848b8605Smrg} 122848b8605Smrg 123848b8605Smrg_X_HIDDEN void 124848b8605SmrgDestroyGLXDrawable(Display *dpy, GLXDrawable drawable) 125848b8605Smrg{ 126848b8605Smrg struct glx_display *priv = __glXInitialize(dpy); 127848b8605Smrg struct glx_drawable *glxDraw; 128848b8605Smrg 129848b8605Smrg if (!priv) 130848b8605Smrg return; 131848b8605Smrg 132848b8605Smrg glxDraw = GetGLXDrawable(dpy, drawable); 133848b8605Smrg __glxHashDelete(priv->glXDrawHash, drawable); 134848b8605Smrg free(glxDraw); 135848b8605Smrg} 136848b8605Smrg 137848b8605Smrg/** 138848b8605Smrg * Get the GLX per-screen data structure associated with a GLX context. 139848b8605Smrg * 140848b8605Smrg * \param dpy Display for which the GLX per-screen information is to be 141848b8605Smrg * retrieved. 142848b8605Smrg * \param scrn Screen on \c dpy for which the GLX per-screen information is 143848b8605Smrg * to be retrieved. 144848b8605Smrg * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn 145848b8605Smrg * specify a valid GLX screen, or NULL otherwise. 146848b8605Smrg * 147848b8605Smrg * \todo Should this function validate that \c scrn is within the screen 148848b8605Smrg * number range for \c dpy? 149848b8605Smrg */ 150848b8605Smrg 151848b8605Smrg_X_HIDDEN struct glx_screen * 152848b8605SmrgGetGLXScreenConfigs(Display * dpy, int scrn) 153848b8605Smrg{ 154848b8605Smrg struct glx_display *const priv = __glXInitialize(dpy); 155848b8605Smrg 156848b8605Smrg return (priv 157848b8605Smrg && priv->screens != 158848b8605Smrg NULL) ? priv->screens[scrn] : NULL; 159848b8605Smrg} 160848b8605Smrg 161848b8605Smrg 162848b8605Smrgstatic int 163848b8605SmrgGetGLXPrivScreenConfig(Display * dpy, int scrn, struct glx_display ** ppriv, 164848b8605Smrg struct glx_screen ** ppsc) 165848b8605Smrg{ 166848b8605Smrg /* Initialize the extension, if needed . This has the added value 167848b8605Smrg * of initializing/allocating the display private 168848b8605Smrg */ 169848b8605Smrg 170848b8605Smrg if (dpy == NULL) { 171848b8605Smrg return GLX_NO_EXTENSION; 172848b8605Smrg } 173848b8605Smrg 174848b8605Smrg *ppriv = __glXInitialize(dpy); 175848b8605Smrg if (*ppriv == NULL) { 176848b8605Smrg return GLX_NO_EXTENSION; 177848b8605Smrg } 178848b8605Smrg 179848b8605Smrg /* Check screen number to see if its valid */ 180848b8605Smrg if ((scrn < 0) || (scrn >= ScreenCount(dpy))) { 181848b8605Smrg return GLX_BAD_SCREEN; 182848b8605Smrg } 183848b8605Smrg 184848b8605Smrg /* Check to see if the GL is supported on this screen */ 185848b8605Smrg *ppsc = (*ppriv)->screens[scrn]; 186848b8605Smrg if ((*ppsc)->configs == NULL && (*ppsc)->visuals == NULL) { 187848b8605Smrg /* No support for GL on this screen regardless of visual */ 188848b8605Smrg return GLX_BAD_VISUAL; 189848b8605Smrg } 190848b8605Smrg 191848b8605Smrg return Success; 192848b8605Smrg} 193848b8605Smrg 194848b8605Smrg 195848b8605Smrg/** 196848b8605Smrg * Determine if a \c GLXFBConfig supplied by the application is valid. 197848b8605Smrg * 198848b8605Smrg * \param dpy Application supplied \c Display pointer. 199848b8605Smrg * \param config Application supplied \c GLXFBConfig. 200848b8605Smrg * 201848b8605Smrg * \returns If the \c GLXFBConfig is valid, the a pointer to the matching 202848b8605Smrg * \c struct glx_config structure is returned. Otherwise, \c NULL 203848b8605Smrg * is returned. 204848b8605Smrg */ 205848b8605Smrgstatic struct glx_config * 206848b8605SmrgValidateGLXFBConfig(Display * dpy, GLXFBConfig fbconfig) 207848b8605Smrg{ 208848b8605Smrg struct glx_display *const priv = __glXInitialize(dpy); 209848b8605Smrg int num_screens = ScreenCount(dpy); 210848b8605Smrg unsigned i; 211848b8605Smrg struct glx_config *config; 212848b8605Smrg 213848b8605Smrg if (priv != NULL) { 214848b8605Smrg for (i = 0; i < num_screens; i++) { 215848b8605Smrg for (config = priv->screens[i]->configs; config != NULL; 216848b8605Smrg config = config->next) { 217848b8605Smrg if (config == (struct glx_config *) fbconfig) { 218848b8605Smrg return config; 219848b8605Smrg } 220848b8605Smrg } 221848b8605Smrg } 222848b8605Smrg } 223848b8605Smrg 224848b8605Smrg return NULL; 225848b8605Smrg} 226848b8605Smrg 227848b8605Smrg/** 228848b8605Smrg * Verifies context's GLX_RENDER_TYPE value with config. 229848b8605Smrg * 230848b8605Smrg * \param config GLX FBConfig which will support the returned renderType. 231848b8605Smrg * \param renderType The context render type to be verified. 232848b8605Smrg * \return True if the value of context renderType was approved, or 0 if no 233848b8605Smrg * valid value was found. 234848b8605Smrg */ 235848b8605SmrgBool 236848b8605Smrgvalidate_renderType_against_config(const struct glx_config *config, 237848b8605Smrg int renderType) 238848b8605Smrg{ 239b8e80941Smrg /* GLX_EXT_no_config_context supports any render type */ 240b8e80941Smrg if (!config) 241b8e80941Smrg return True; 242b8e80941Smrg 243b8e80941Smrg switch (renderType) { 244b8e80941Smrg case GLX_RGBA_TYPE: 245b8e80941Smrg return (config->renderType & GLX_RGBA_BIT) != 0; 246b8e80941Smrg case GLX_COLOR_INDEX_TYPE: 247b8e80941Smrg return (config->renderType & GLX_COLOR_INDEX_BIT) != 0; 248b8e80941Smrg case GLX_RGBA_FLOAT_TYPE_ARB: 249b8e80941Smrg return (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) != 0; 250b8e80941Smrg case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT: 251b8e80941Smrg return (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) != 0; 252b8e80941Smrg default: 253b8e80941Smrg break; 254b8e80941Smrg } 255b8e80941Smrg return 0; 256848b8605Smrg} 257848b8605Smrg 258848b8605Smrg_X_HIDDEN Bool 259848b8605Smrgglx_context_init(struct glx_context *gc, 260848b8605Smrg struct glx_screen *psc, struct glx_config *config) 261848b8605Smrg{ 262848b8605Smrg gc->majorOpcode = __glXSetupForCommand(psc->display->dpy); 263848b8605Smrg if (!gc->majorOpcode) 264848b8605Smrg return False; 265848b8605Smrg 266848b8605Smrg gc->screen = psc->scr; 267848b8605Smrg gc->psc = psc; 268848b8605Smrg gc->config = config; 269848b8605Smrg gc->isDirect = GL_TRUE; 270848b8605Smrg gc->currentContextTag = -1; 271848b8605Smrg 272848b8605Smrg return True; 273848b8605Smrg} 274848b8605Smrg 275b8e80941Smrg/** 276b8e80941Smrg * Determine if a context uses direct rendering. 277b8e80941Smrg * 278b8e80941Smrg * \param dpy Display where the context was created. 279b8e80941Smrg * \param contextID ID of the context to be tested. 280b8e80941Smrg * \param error Out parameter, set to True on error if not NULL 281b8e80941Smrg * 282b8e80941Smrg * \returns \c True if the context is direct rendering or not. 283b8e80941Smrg */ 284b8e80941Smrgstatic Bool 285b8e80941Smrg__glXIsDirect(Display * dpy, GLXContextID contextID, Bool *error) 286b8e80941Smrg{ 287b8e80941Smrg CARD8 opcode; 288b8e80941Smrg xcb_connection_t *c; 289b8e80941Smrg xcb_generic_error_t *err; 290b8e80941Smrg xcb_glx_is_direct_reply_t *reply; 291b8e80941Smrg Bool is_direct; 292b8e80941Smrg 293b8e80941Smrg opcode = __glXSetupForCommand(dpy); 294b8e80941Smrg if (!opcode) { 295b8e80941Smrg return False; 296b8e80941Smrg } 297b8e80941Smrg 298b8e80941Smrg c = XGetXCBConnection(dpy); 299b8e80941Smrg reply = xcb_glx_is_direct_reply(c, xcb_glx_is_direct(c, contextID), &err); 300b8e80941Smrg is_direct = (reply != NULL && reply->is_direct) ? True : False; 301b8e80941Smrg 302b8e80941Smrg if (err != NULL) { 303b8e80941Smrg if (error) 304b8e80941Smrg *error = True; 305b8e80941Smrg __glXSendErrorForXcb(dpy, err); 306b8e80941Smrg free(err); 307b8e80941Smrg } 308b8e80941Smrg 309b8e80941Smrg free(reply); 310b8e80941Smrg 311b8e80941Smrg return is_direct; 312b8e80941Smrg} 313848b8605Smrg 314848b8605Smrg/** 315848b8605Smrg * Create a new context. 316848b8605Smrg * 317848b8605Smrg * \param renderType For FBConfigs, what is the rendering type? 318848b8605Smrg */ 319848b8605Smrg 320848b8605Smrgstatic GLXContext 321848b8605SmrgCreateContext(Display *dpy, int generic_id, struct glx_config *config, 322848b8605Smrg GLXContext shareList_user, Bool allowDirect, 323848b8605Smrg unsigned code, int renderType, int screen) 324848b8605Smrg{ 325848b8605Smrg struct glx_context *gc; 326848b8605Smrg struct glx_screen *psc; 327848b8605Smrg struct glx_context *shareList = (struct glx_context *) shareList_user; 328848b8605Smrg if (dpy == NULL) 329848b8605Smrg return NULL; 330848b8605Smrg 331848b8605Smrg psc = GetGLXScreenConfigs(dpy, screen); 332848b8605Smrg if (psc == NULL) 333848b8605Smrg return NULL; 334848b8605Smrg 335848b8605Smrg if (generic_id == None) 336848b8605Smrg return NULL; 337848b8605Smrg 338848b8605Smrg gc = NULL; 339848b8605Smrg#ifdef GLX_USE_APPLEGL 340848b8605Smrg gc = applegl_create_context(psc, config, shareList, renderType); 341848b8605Smrg#else 342848b8605Smrg if (allowDirect && psc->vtable->create_context) 343848b8605Smrg gc = psc->vtable->create_context(psc, config, shareList, renderType); 344848b8605Smrg if (!gc) 345848b8605Smrg gc = indirect_create_context(psc, config, shareList, renderType); 346848b8605Smrg#endif 347848b8605Smrg if (!gc) 348848b8605Smrg return NULL; 349848b8605Smrg 350848b8605Smrg LockDisplay(dpy); 351848b8605Smrg switch (code) { 352848b8605Smrg case X_GLXCreateContext: { 353848b8605Smrg xGLXCreateContextReq *req; 354848b8605Smrg 355848b8605Smrg /* Send the glXCreateContext request */ 356848b8605Smrg GetReq(GLXCreateContext, req); 357848b8605Smrg req->reqType = gc->majorOpcode; 358848b8605Smrg req->glxCode = X_GLXCreateContext; 359848b8605Smrg req->context = gc->xid = XAllocID(dpy); 360848b8605Smrg req->visual = generic_id; 361848b8605Smrg req->screen = screen; 362848b8605Smrg req->shareList = shareList ? shareList->xid : None; 363848b8605Smrg req->isDirect = gc->isDirect; 364848b8605Smrg break; 365848b8605Smrg } 366848b8605Smrg 367848b8605Smrg case X_GLXCreateNewContext: { 368848b8605Smrg xGLXCreateNewContextReq *req; 369848b8605Smrg 370848b8605Smrg /* Send the glXCreateNewContext request */ 371848b8605Smrg GetReq(GLXCreateNewContext, req); 372848b8605Smrg req->reqType = gc->majorOpcode; 373848b8605Smrg req->glxCode = X_GLXCreateNewContext; 374848b8605Smrg req->context = gc->xid = XAllocID(dpy); 375848b8605Smrg req->fbconfig = generic_id; 376848b8605Smrg req->screen = screen; 377848b8605Smrg req->renderType = renderType; 378848b8605Smrg req->shareList = shareList ? shareList->xid : None; 379848b8605Smrg req->isDirect = gc->isDirect; 380848b8605Smrg break; 381848b8605Smrg } 382848b8605Smrg 383848b8605Smrg case X_GLXvop_CreateContextWithConfigSGIX: { 384848b8605Smrg xGLXVendorPrivateWithReplyReq *vpreq; 385848b8605Smrg xGLXCreateContextWithConfigSGIXReq *req; 386848b8605Smrg 387848b8605Smrg /* Send the glXCreateNewContext request */ 388848b8605Smrg GetReqExtra(GLXVendorPrivateWithReply, 389848b8605Smrg sz_xGLXCreateContextWithConfigSGIXReq - 390848b8605Smrg sz_xGLXVendorPrivateWithReplyReq, vpreq); 391848b8605Smrg req = (xGLXCreateContextWithConfigSGIXReq *) vpreq; 392848b8605Smrg req->reqType = gc->majorOpcode; 393848b8605Smrg req->glxCode = X_GLXVendorPrivateWithReply; 394848b8605Smrg req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX; 395848b8605Smrg req->context = gc->xid = XAllocID(dpy); 396848b8605Smrg req->fbconfig = generic_id; 397848b8605Smrg req->screen = screen; 398848b8605Smrg req->renderType = renderType; 399848b8605Smrg req->shareList = shareList ? shareList->xid : None; 400848b8605Smrg req->isDirect = gc->isDirect; 401848b8605Smrg break; 402848b8605Smrg } 403848b8605Smrg 404848b8605Smrg default: 405848b8605Smrg /* What to do here? This case is the sign of an internal error. It 406848b8605Smrg * should never be reachable. 407848b8605Smrg */ 408848b8605Smrg break; 409848b8605Smrg } 410848b8605Smrg 411848b8605Smrg UnlockDisplay(dpy); 412848b8605Smrg SyncHandle(); 413848b8605Smrg 414848b8605Smrg gc->share_xid = shareList ? shareList->xid : None; 415848b8605Smrg gc->imported = GL_FALSE; 416848b8605Smrg 417b8e80941Smrg /* Unlike most X resource creation requests, we're about to return a handle 418b8e80941Smrg * with client-side state, not just an XID. To simplify error handling 419b8e80941Smrg * elsewhere in libGL, force a round-trip here to ensure the CreateContext 420b8e80941Smrg * request above succeeded. 421b8e80941Smrg */ 422b8e80941Smrg { 423b8e80941Smrg Bool error = False; 424b8e80941Smrg int isDirect = __glXIsDirect(dpy, gc->xid, &error); 425b8e80941Smrg 426b8e80941Smrg if (error != False || isDirect != gc->isDirect) { 427b8e80941Smrg gc->vtable->destroy(gc); 428b8e80941Smrg gc = NULL; 429b8e80941Smrg } 430b8e80941Smrg } 431b8e80941Smrg 432848b8605Smrg return (GLXContext) gc; 433848b8605Smrg} 434848b8605Smrg 435b8e80941Smrg_GLX_PUBLIC GLXContext 436848b8605SmrgglXCreateContext(Display * dpy, XVisualInfo * vis, 437848b8605Smrg GLXContext shareList, Bool allowDirect) 438848b8605Smrg{ 439848b8605Smrg struct glx_config *config = NULL; 440848b8605Smrg int renderType = GLX_RGBA_TYPE; 441848b8605Smrg 442848b8605Smrg#if defined(GLX_DIRECT_RENDERING) || defined(GLX_USE_APPLEGL) 443848b8605Smrg struct glx_screen *const psc = GetGLXScreenConfigs(dpy, vis->screen); 444848b8605Smrg 445848b8605Smrg if (psc) 446848b8605Smrg config = glx_config_find_visual(psc->visuals, vis->visualid); 447848b8605Smrg 448848b8605Smrg if (config == NULL) { 449b8e80941Smrg __glXSendError(dpy, BadValue, vis->visualid, X_GLXCreateContext, True); 450848b8605Smrg return None; 451848b8605Smrg } 452848b8605Smrg 453848b8605Smrg /* Choose the context render type based on DRI config values. It is 454848b8605Smrg * unusual to set this type from config, but we have no other choice, as 455848b8605Smrg * this old API does not provide renderType parameter. 456848b8605Smrg */ 457848b8605Smrg if (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) { 458848b8605Smrg renderType = GLX_RGBA_FLOAT_TYPE_ARB; 459848b8605Smrg } else if (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) { 460848b8605Smrg renderType = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT; 461848b8605Smrg } else if (config->renderType & GLX_RGBA_BIT) { 462848b8605Smrg renderType = GLX_RGBA_TYPE; 463848b8605Smrg } else if (config->renderType & GLX_COLOR_INDEX_BIT) { 464848b8605Smrg renderType = GLX_COLOR_INDEX_TYPE; 465848b8605Smrg } else if (config->rgbMode) { 466848b8605Smrg /* If we're here, then renderType is not set correctly. Let's use a 467848b8605Smrg * safeguard - any TrueColor or DirectColor mode is RGB mode. Such 468848b8605Smrg * default value is needed by old DRI drivers, which didn't set 469848b8605Smrg * renderType correctly as the value was just ignored. 470848b8605Smrg */ 471848b8605Smrg renderType = GLX_RGBA_TYPE; 472848b8605Smrg } else { 473848b8605Smrg /* Safeguard - only one option left, all non-RGB modes are indexed 474848b8605Smrg * modes. Again, this allows drivers with invalid renderType to work 475848b8605Smrg * properly. 476848b8605Smrg */ 477848b8605Smrg renderType = GLX_COLOR_INDEX_TYPE; 478848b8605Smrg } 479848b8605Smrg#endif 480848b8605Smrg 481848b8605Smrg return CreateContext(dpy, vis->visualid, config, shareList, allowDirect, 482848b8605Smrg X_GLXCreateContext, renderType, vis->screen); 483848b8605Smrg} 484848b8605Smrg 485848b8605Smrgstatic void 486848b8605Smrgglx_send_destroy_context(Display *dpy, XID xid) 487848b8605Smrg{ 488848b8605Smrg CARD8 opcode = __glXSetupForCommand(dpy); 489848b8605Smrg xGLXDestroyContextReq *req; 490848b8605Smrg 491848b8605Smrg LockDisplay(dpy); 492848b8605Smrg GetReq(GLXDestroyContext, req); 493848b8605Smrg req->reqType = opcode; 494848b8605Smrg req->glxCode = X_GLXDestroyContext; 495848b8605Smrg req->context = xid; 496848b8605Smrg UnlockDisplay(dpy); 497848b8605Smrg SyncHandle(); 498848b8605Smrg} 499848b8605Smrg 500848b8605Smrg/* 501848b8605Smrg** Destroy the named context 502848b8605Smrg*/ 503848b8605Smrg 504b8e80941Smrg_GLX_PUBLIC void 505848b8605SmrgglXDestroyContext(Display * dpy, GLXContext ctx) 506848b8605Smrg{ 507848b8605Smrg struct glx_context *gc = (struct glx_context *) ctx; 508848b8605Smrg 509848b8605Smrg if (gc == NULL || gc->xid == None) 510848b8605Smrg return; 511848b8605Smrg 512848b8605Smrg __glXLock(); 513848b8605Smrg if (!gc->imported) 514848b8605Smrg glx_send_destroy_context(dpy, gc->xid); 515848b8605Smrg 516848b8605Smrg if (gc->currentDpy) { 517848b8605Smrg /* This context is bound to some thread. According to the man page, 518848b8605Smrg * we should not actually delete the context until it's unbound. 519848b8605Smrg * Note that we set gc->xid = None above. In MakeContextCurrent() 520848b8605Smrg * we check for that and delete the context there. 521848b8605Smrg */ 522848b8605Smrg gc->xid = None; 523848b8605Smrg } else { 524848b8605Smrg gc->vtable->destroy(gc); 525848b8605Smrg } 526848b8605Smrg __glXUnlock(); 527848b8605Smrg} 528848b8605Smrg 529848b8605Smrg/* 530848b8605Smrg** Return the major and minor version #s for the GLX extension 531848b8605Smrg*/ 532b8e80941Smrg_GLX_PUBLIC Bool 533848b8605SmrgglXQueryVersion(Display * dpy, int *major, int *minor) 534848b8605Smrg{ 535848b8605Smrg struct glx_display *priv; 536848b8605Smrg 537848b8605Smrg /* Init the extension. This fetches the major and minor version. */ 538848b8605Smrg priv = __glXInitialize(dpy); 539848b8605Smrg if (!priv) 540848b8605Smrg return False; 541848b8605Smrg 542848b8605Smrg if (major) 543848b8605Smrg *major = priv->majorVersion; 544848b8605Smrg if (minor) 545848b8605Smrg *minor = priv->minorVersion; 546848b8605Smrg return True; 547848b8605Smrg} 548848b8605Smrg 549848b8605Smrg/* 550b8e80941Smrg** Query the existence of the GLX extension 551848b8605Smrg*/ 552b8e80941Smrg_GLX_PUBLIC Bool 553848b8605SmrgglXQueryExtension(Display * dpy, int *errorBase, int *eventBase) 554848b8605Smrg{ 555848b8605Smrg int major_op, erb, evb; 556848b8605Smrg Bool rv; 557848b8605Smrg 558848b8605Smrg rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb); 559848b8605Smrg if (rv) { 560848b8605Smrg if (errorBase) 561848b8605Smrg *errorBase = erb; 562848b8605Smrg if (eventBase) 563848b8605Smrg *eventBase = evb; 564848b8605Smrg } 565848b8605Smrg return rv; 566848b8605Smrg} 567848b8605Smrg 568848b8605Smrg/* 569848b8605Smrg** Put a barrier in the token stream that forces the GL to finish its 570848b8605Smrg** work before X can proceed. 571848b8605Smrg*/ 572b8e80941Smrg_GLX_PUBLIC void 573848b8605SmrgglXWaitGL(void) 574848b8605Smrg{ 575848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 576848b8605Smrg 577b8e80941Smrg if (gc->vtable->wait_gl) 578848b8605Smrg gc->vtable->wait_gl(gc); 579848b8605Smrg} 580848b8605Smrg 581848b8605Smrg/* 582848b8605Smrg** Put a barrier in the token stream that forces X to finish its 583848b8605Smrg** work before GL can proceed. 584848b8605Smrg*/ 585b8e80941Smrg_GLX_PUBLIC void 586848b8605SmrgglXWaitX(void) 587848b8605Smrg{ 588848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 589848b8605Smrg 590b8e80941Smrg if (gc->vtable->wait_x) 591848b8605Smrg gc->vtable->wait_x(gc); 592848b8605Smrg} 593848b8605Smrg 594b8e80941Smrg_GLX_PUBLIC void 595848b8605SmrgglXUseXFont(Font font, int first, int count, int listBase) 596848b8605Smrg{ 597848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 598848b8605Smrg 599b8e80941Smrg if (gc->vtable->use_x_font) 600848b8605Smrg gc->vtable->use_x_font(gc, font, first, count, listBase); 601848b8605Smrg} 602848b8605Smrg 603848b8605Smrg/************************************************************************/ 604848b8605Smrg 605848b8605Smrg/* 606848b8605Smrg** Copy the source context to the destination context using the 607848b8605Smrg** attribute "mask". 608848b8605Smrg*/ 609b8e80941Smrg_GLX_PUBLIC void 610848b8605SmrgglXCopyContext(Display * dpy, GLXContext source_user, 611848b8605Smrg GLXContext dest_user, unsigned long mask) 612848b8605Smrg{ 613848b8605Smrg struct glx_context *source = (struct glx_context *) source_user; 614848b8605Smrg struct glx_context *dest = (struct glx_context *) dest_user; 615848b8605Smrg#ifdef GLX_USE_APPLEGL 616848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 617848b8605Smrg int errorcode; 618848b8605Smrg bool x11error; 619848b8605Smrg 620848b8605Smrg if(apple_glx_copy_context(gc->driContext, source->driContext, dest->driContext, 621848b8605Smrg mask, &errorcode, &x11error)) { 622848b8605Smrg __glXSendError(dpy, errorcode, 0, X_GLXCopyContext, x11error); 623848b8605Smrg } 624848b8605Smrg 625848b8605Smrg#else 626848b8605Smrg xGLXCopyContextReq *req; 627848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 628848b8605Smrg GLXContextTag tag; 629848b8605Smrg CARD8 opcode; 630848b8605Smrg 631848b8605Smrg opcode = __glXSetupForCommand(dpy); 632848b8605Smrg if (!opcode) { 633848b8605Smrg return; 634848b8605Smrg } 635848b8605Smrg 636848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 637848b8605Smrg if (gc->isDirect) { 638848b8605Smrg /* NOT_DONE: This does not work yet */ 639848b8605Smrg } 640848b8605Smrg#endif 641848b8605Smrg 642848b8605Smrg /* 643848b8605Smrg ** If the source is the current context, send its tag so that the context 644848b8605Smrg ** can be flushed before the copy. 645848b8605Smrg */ 646848b8605Smrg if (source == gc && dpy == gc->currentDpy) { 647848b8605Smrg tag = gc->currentContextTag; 648848b8605Smrg } 649848b8605Smrg else { 650848b8605Smrg tag = 0; 651848b8605Smrg } 652848b8605Smrg 653848b8605Smrg /* Send the glXCopyContext request */ 654848b8605Smrg LockDisplay(dpy); 655848b8605Smrg GetReq(GLXCopyContext, req); 656848b8605Smrg req->reqType = opcode; 657848b8605Smrg req->glxCode = X_GLXCopyContext; 658848b8605Smrg req->source = source ? source->xid : None; 659848b8605Smrg req->dest = dest ? dest->xid : None; 660848b8605Smrg req->mask = mask; 661848b8605Smrg req->contextTag = tag; 662848b8605Smrg UnlockDisplay(dpy); 663848b8605Smrg SyncHandle(); 664848b8605Smrg#endif /* GLX_USE_APPLEGL */ 665848b8605Smrg} 666848b8605Smrg 667848b8605Smrg 668848b8605Smrg/** 669848b8605Smrg * \todo 670848b8605Smrg * Shouldn't this function \b always return \c False when 671848b8605Smrg * \c GLX_DIRECT_RENDERING is not defined? Do we really need to bother with 672848b8605Smrg * the GLX protocol here at all? 673848b8605Smrg */ 674b8e80941Smrg_GLX_PUBLIC Bool 675848b8605SmrgglXIsDirect(Display * dpy, GLXContext gc_user) 676848b8605Smrg{ 677848b8605Smrg struct glx_context *gc = (struct glx_context *) gc_user; 678848b8605Smrg 679848b8605Smrg if (!gc) { 680848b8605Smrg return False; 681848b8605Smrg } 682848b8605Smrg else if (gc->isDirect) { 683848b8605Smrg return True; 684848b8605Smrg } 685848b8605Smrg#ifdef GLX_USE_APPLEGL /* TODO: indirect on darwin */ 686848b8605Smrg return False; 687848b8605Smrg#else 688b8e80941Smrg return __glXIsDirect(dpy, gc->xid, NULL); 689848b8605Smrg#endif 690848b8605Smrg} 691848b8605Smrg 692b8e80941Smrg_GLX_PUBLIC GLXPixmap 693848b8605SmrgglXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap) 694848b8605Smrg{ 695848b8605Smrg#ifdef GLX_USE_APPLEGL 696848b8605Smrg int screen = vis->screen; 697848b8605Smrg struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen); 698848b8605Smrg const struct glx_config *config; 699848b8605Smrg 700848b8605Smrg config = glx_config_find_visual(psc->visuals, vis->visualid); 701848b8605Smrg 702848b8605Smrg if(apple_glx_pixmap_create(dpy, vis->screen, pixmap, config)) 703848b8605Smrg return None; 704848b8605Smrg 705848b8605Smrg return pixmap; 706848b8605Smrg#else 707848b8605Smrg xGLXCreateGLXPixmapReq *req; 708848b8605Smrg struct glx_drawable *glxDraw; 709848b8605Smrg GLXPixmap xid; 710848b8605Smrg CARD8 opcode; 711848b8605Smrg 712848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 713848b8605Smrg struct glx_display *const priv = __glXInitialize(dpy); 714848b8605Smrg 715848b8605Smrg if (priv == NULL) 716848b8605Smrg return None; 717848b8605Smrg#endif 718848b8605Smrg 719848b8605Smrg opcode = __glXSetupForCommand(dpy); 720848b8605Smrg if (!opcode) { 721848b8605Smrg return None; 722848b8605Smrg } 723848b8605Smrg 724848b8605Smrg glxDraw = malloc(sizeof(*glxDraw)); 725848b8605Smrg if (!glxDraw) 726848b8605Smrg return None; 727848b8605Smrg 728848b8605Smrg /* Send the glXCreateGLXPixmap request */ 729848b8605Smrg LockDisplay(dpy); 730848b8605Smrg GetReq(GLXCreateGLXPixmap, req); 731848b8605Smrg req->reqType = opcode; 732848b8605Smrg req->glxCode = X_GLXCreateGLXPixmap; 733848b8605Smrg req->screen = vis->screen; 734848b8605Smrg req->visual = vis->visualid; 735848b8605Smrg req->pixmap = pixmap; 736848b8605Smrg req->glxpixmap = xid = XAllocID(dpy); 737848b8605Smrg UnlockDisplay(dpy); 738848b8605Smrg SyncHandle(); 739848b8605Smrg 740848b8605Smrg if (InitGLXDrawable(dpy, glxDraw, pixmap, req->glxpixmap)) { 741848b8605Smrg free(glxDraw); 742848b8605Smrg return None; 743848b8605Smrg } 744848b8605Smrg 745848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 746848b8605Smrg do { 747848b8605Smrg /* FIXME: Maybe delay __DRIdrawable creation until the drawable 748848b8605Smrg * is actually bound to a context... */ 749848b8605Smrg 750848b8605Smrg __GLXDRIdrawable *pdraw; 751848b8605Smrg struct glx_screen *psc; 752848b8605Smrg struct glx_config *config; 753848b8605Smrg 754848b8605Smrg psc = priv->screens[vis->screen]; 755848b8605Smrg if (psc->driScreen == NULL) 756848b8605Smrg return xid; 757848b8605Smrg 758848b8605Smrg config = glx_config_find_visual(psc->visuals, vis->visualid); 759848b8605Smrg pdraw = psc->driScreen->createDrawable(psc, pixmap, xid, config); 760848b8605Smrg if (pdraw == NULL) { 761848b8605Smrg fprintf(stderr, "failed to create pixmap\n"); 762848b8605Smrg xid = None; 763848b8605Smrg break; 764848b8605Smrg } 765848b8605Smrg 766848b8605Smrg if (__glxHashInsert(priv->drawHash, xid, pdraw)) { 767848b8605Smrg (*pdraw->destroyDrawable) (pdraw); 768848b8605Smrg xid = None; 769848b8605Smrg break; 770848b8605Smrg } 771848b8605Smrg } while (0); 772848b8605Smrg 773848b8605Smrg if (xid == None) { 774848b8605Smrg xGLXDestroyGLXPixmapReq *dreq; 775848b8605Smrg LockDisplay(dpy); 776848b8605Smrg GetReq(GLXDestroyGLXPixmap, dreq); 777848b8605Smrg dreq->reqType = opcode; 778848b8605Smrg dreq->glxCode = X_GLXDestroyGLXPixmap; 779848b8605Smrg dreq->glxpixmap = xid; 780848b8605Smrg UnlockDisplay(dpy); 781848b8605Smrg SyncHandle(); 782848b8605Smrg } 783848b8605Smrg#endif 784848b8605Smrg 785848b8605Smrg return xid; 786848b8605Smrg#endif 787848b8605Smrg} 788848b8605Smrg 789848b8605Smrg/* 790848b8605Smrg** Destroy the named pixmap 791848b8605Smrg*/ 792b8e80941Smrg_GLX_PUBLIC void 793848b8605SmrgglXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap) 794848b8605Smrg{ 795848b8605Smrg#ifdef GLX_USE_APPLEGL 796848b8605Smrg if(apple_glx_pixmap_destroy(dpy, glxpixmap)) 797848b8605Smrg __glXSendError(dpy, GLXBadPixmap, glxpixmap, X_GLXDestroyPixmap, false); 798848b8605Smrg#else 799848b8605Smrg xGLXDestroyGLXPixmapReq *req; 800848b8605Smrg CARD8 opcode; 801848b8605Smrg 802848b8605Smrg opcode = __glXSetupForCommand(dpy); 803848b8605Smrg if (!opcode) { 804848b8605Smrg return; 805848b8605Smrg } 806848b8605Smrg 807848b8605Smrg /* Send the glXDestroyGLXPixmap request */ 808848b8605Smrg LockDisplay(dpy); 809848b8605Smrg GetReq(GLXDestroyGLXPixmap, req); 810848b8605Smrg req->reqType = opcode; 811848b8605Smrg req->glxCode = X_GLXDestroyGLXPixmap; 812848b8605Smrg req->glxpixmap = glxpixmap; 813848b8605Smrg UnlockDisplay(dpy); 814848b8605Smrg SyncHandle(); 815848b8605Smrg 816848b8605Smrg DestroyGLXDrawable(dpy, glxpixmap); 817848b8605Smrg 818848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 819848b8605Smrg { 820848b8605Smrg struct glx_display *const priv = __glXInitialize(dpy); 821848b8605Smrg __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap); 822848b8605Smrg 823848b8605Smrg if (priv != NULL && pdraw != NULL) { 824848b8605Smrg (*pdraw->destroyDrawable) (pdraw); 825848b8605Smrg __glxHashDelete(priv->drawHash, glxpixmap); 826848b8605Smrg } 827848b8605Smrg } 828848b8605Smrg#endif 829848b8605Smrg#endif /* GLX_USE_APPLEGL */ 830848b8605Smrg} 831848b8605Smrg 832b8e80941Smrg_GLX_PUBLIC void 833848b8605SmrgglXSwapBuffers(Display * dpy, GLXDrawable drawable) 834848b8605Smrg{ 835848b8605Smrg#ifdef GLX_USE_APPLEGL 836848b8605Smrg struct glx_context * gc = __glXGetCurrentContext(); 837b8e80941Smrg if(gc != &dummyContext && apple_glx_is_current_drawable(dpy, gc->driContext, drawable)) { 838848b8605Smrg apple_glx_swap_buffers(gc->driContext); 839848b8605Smrg } else { 840848b8605Smrg __glXSendError(dpy, GLXBadCurrentWindow, 0, X_GLXSwapBuffers, false); 841848b8605Smrg } 842848b8605Smrg#else 843848b8605Smrg struct glx_context *gc; 844848b8605Smrg GLXContextTag tag; 845848b8605Smrg CARD8 opcode; 846848b8605Smrg xcb_connection_t *c; 847848b8605Smrg 848848b8605Smrg gc = __glXGetCurrentContext(); 849848b8605Smrg 850848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 851848b8605Smrg { 852848b8605Smrg __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 853848b8605Smrg 854848b8605Smrg if (pdraw != NULL) { 855b8e80941Smrg Bool flush = gc != &dummyContext && drawable == gc->currentDrawable; 856848b8605Smrg 857848b8605Smrg (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0, flush); 858848b8605Smrg return; 859848b8605Smrg } 860848b8605Smrg } 861848b8605Smrg#endif 862848b8605Smrg 863848b8605Smrg opcode = __glXSetupForCommand(dpy); 864848b8605Smrg if (!opcode) { 865848b8605Smrg return; 866848b8605Smrg } 867848b8605Smrg 868848b8605Smrg /* 869848b8605Smrg ** The calling thread may or may not have a current context. If it 870848b8605Smrg ** does, send the context tag so the server can do a flush. 871848b8605Smrg */ 872b8e80941Smrg if ((gc != &dummyContext) && (dpy == gc->currentDpy) && 873848b8605Smrg ((drawable == gc->currentDrawable) 874848b8605Smrg || (drawable == gc->currentReadable))) { 875848b8605Smrg tag = gc->currentContextTag; 876848b8605Smrg } 877848b8605Smrg else { 878848b8605Smrg tag = 0; 879848b8605Smrg } 880848b8605Smrg 881848b8605Smrg c = XGetXCBConnection(dpy); 882848b8605Smrg xcb_glx_swap_buffers(c, tag, drawable); 883848b8605Smrg xcb_flush(c); 884848b8605Smrg#endif /* GLX_USE_APPLEGL */ 885848b8605Smrg} 886848b8605Smrg 887848b8605Smrg 888848b8605Smrg/* 889848b8605Smrg** Return configuration information for the given display, screen and 890848b8605Smrg** visual combination. 891848b8605Smrg*/ 892b8e80941Smrg_GLX_PUBLIC int 893848b8605SmrgglXGetConfig(Display * dpy, XVisualInfo * vis, int attribute, 894848b8605Smrg int *value_return) 895848b8605Smrg{ 896848b8605Smrg struct glx_display *priv; 897848b8605Smrg struct glx_screen *psc; 898848b8605Smrg struct glx_config *config; 899848b8605Smrg int status; 900848b8605Smrg 901848b8605Smrg status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc); 902848b8605Smrg if (status == Success) { 903848b8605Smrg config = glx_config_find_visual(psc->visuals, vis->visualid); 904848b8605Smrg 905848b8605Smrg /* Lookup attribute after first finding a match on the visual */ 906848b8605Smrg if (config != NULL) { 907848b8605Smrg return glx_config_get(config, attribute, value_return); 908848b8605Smrg } 909848b8605Smrg 910848b8605Smrg status = GLX_BAD_VISUAL; 911848b8605Smrg } 912848b8605Smrg 913848b8605Smrg /* 914848b8605Smrg ** If we can't find the config for this visual, this visual is not 915848b8605Smrg ** supported by the OpenGL implementation on the server. 916848b8605Smrg */ 917848b8605Smrg if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) { 918848b8605Smrg *value_return = False; 919848b8605Smrg status = Success; 920848b8605Smrg } 921848b8605Smrg 922848b8605Smrg return status; 923848b8605Smrg} 924848b8605Smrg 925848b8605Smrg/************************************************************************/ 926848b8605Smrg 927848b8605Smrgstatic void 928848b8605Smrginit_fbconfig_for_chooser(struct glx_config * config, 929848b8605Smrg GLboolean fbconfig_style_tags) 930848b8605Smrg{ 931848b8605Smrg memset(config, 0, sizeof(struct glx_config)); 932848b8605Smrg config->visualID = (XID) GLX_DONT_CARE; 933848b8605Smrg config->visualType = GLX_DONT_CARE; 934848b8605Smrg 935848b8605Smrg /* glXChooseFBConfig specifies different defaults for these properties than 936848b8605Smrg * glXChooseVisual. 937848b8605Smrg */ 938848b8605Smrg if (fbconfig_style_tags) { 939848b8605Smrg config->rgbMode = GL_TRUE; 940848b8605Smrg config->doubleBufferMode = GLX_DONT_CARE; 941848b8605Smrg config->renderType = GLX_RGBA_BIT; 942848b8605Smrg } 943848b8605Smrg 944848b8605Smrg config->drawableType = GLX_WINDOW_BIT; 945848b8605Smrg config->visualRating = GLX_DONT_CARE; 946848b8605Smrg config->transparentPixel = GLX_NONE; 947848b8605Smrg config->transparentRed = GLX_DONT_CARE; 948848b8605Smrg config->transparentGreen = GLX_DONT_CARE; 949848b8605Smrg config->transparentBlue = GLX_DONT_CARE; 950848b8605Smrg config->transparentAlpha = GLX_DONT_CARE; 951848b8605Smrg config->transparentIndex = GLX_DONT_CARE; 952848b8605Smrg 953848b8605Smrg config->xRenderable = GLX_DONT_CARE; 954848b8605Smrg config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE); 955848b8605Smrg 956848b8605Smrg config->swapMethod = GLX_DONT_CARE; 957b8e80941Smrg config->sRGBCapable = GLX_DONT_CARE; 958848b8605Smrg} 959848b8605Smrg 960848b8605Smrg#define MATCH_DONT_CARE( param ) \ 961848b8605Smrg do { \ 962848b8605Smrg if ( ((int) a-> param != (int) GLX_DONT_CARE) \ 963848b8605Smrg && (a-> param != b-> param) ) { \ 964848b8605Smrg return False; \ 965848b8605Smrg } \ 966848b8605Smrg } while ( 0 ) 967848b8605Smrg 968848b8605Smrg#define MATCH_MINIMUM( param ) \ 969848b8605Smrg do { \ 970848b8605Smrg if ( ((int) a-> param != (int) GLX_DONT_CARE) \ 971848b8605Smrg && (a-> param > b-> param) ) { \ 972848b8605Smrg return False; \ 973848b8605Smrg } \ 974848b8605Smrg } while ( 0 ) 975848b8605Smrg 976848b8605Smrg#define MATCH_EXACT( param ) \ 977848b8605Smrg do { \ 978848b8605Smrg if ( a-> param != b-> param) { \ 979848b8605Smrg return False; \ 980848b8605Smrg } \ 981848b8605Smrg } while ( 0 ) 982848b8605Smrg 983848b8605Smrg/* Test that all bits from a are contained in b */ 984848b8605Smrg#define MATCH_MASK(param) \ 985848b8605Smrg do { \ 986848b8605Smrg if ( ((int) a-> param != (int) GLX_DONT_CARE) \ 987848b8605Smrg && ((a->param & ~b->param) != 0) ) { \ 988848b8605Smrg return False; \ 989848b8605Smrg } \ 990848b8605Smrg } while (0); 991848b8605Smrg 992848b8605Smrg/** 993848b8605Smrg * Determine if two GLXFBConfigs are compatible. 994848b8605Smrg * 995848b8605Smrg * \param a Application specified config to test. 996848b8605Smrg * \param b Server specified config to test against \c a. 997848b8605Smrg */ 998848b8605Smrgstatic Bool 999848b8605Smrgfbconfigs_compatible(const struct glx_config * const a, 1000848b8605Smrg const struct glx_config * const b) 1001848b8605Smrg{ 1002848b8605Smrg MATCH_DONT_CARE(doubleBufferMode); 1003848b8605Smrg MATCH_DONT_CARE(visualType); 1004848b8605Smrg MATCH_DONT_CARE(visualRating); 1005848b8605Smrg MATCH_DONT_CARE(xRenderable); 1006848b8605Smrg MATCH_DONT_CARE(fbconfigID); 1007848b8605Smrg MATCH_DONT_CARE(swapMethod); 1008848b8605Smrg 1009848b8605Smrg MATCH_MINIMUM(rgbBits); 1010848b8605Smrg MATCH_MINIMUM(numAuxBuffers); 1011848b8605Smrg MATCH_MINIMUM(redBits); 1012848b8605Smrg MATCH_MINIMUM(greenBits); 1013848b8605Smrg MATCH_MINIMUM(blueBits); 1014848b8605Smrg MATCH_MINIMUM(alphaBits); 1015848b8605Smrg MATCH_MINIMUM(depthBits); 1016848b8605Smrg MATCH_MINIMUM(stencilBits); 1017848b8605Smrg MATCH_MINIMUM(accumRedBits); 1018848b8605Smrg MATCH_MINIMUM(accumGreenBits); 1019848b8605Smrg MATCH_MINIMUM(accumBlueBits); 1020848b8605Smrg MATCH_MINIMUM(accumAlphaBits); 1021848b8605Smrg MATCH_MINIMUM(sampleBuffers); 1022848b8605Smrg MATCH_MINIMUM(maxPbufferWidth); 1023848b8605Smrg MATCH_MINIMUM(maxPbufferHeight); 1024848b8605Smrg MATCH_MINIMUM(maxPbufferPixels); 1025848b8605Smrg MATCH_MINIMUM(samples); 1026848b8605Smrg 1027848b8605Smrg MATCH_DONT_CARE(stereoMode); 1028848b8605Smrg MATCH_EXACT(level); 1029848b8605Smrg 1030848b8605Smrg MATCH_MASK(drawableType); 1031848b8605Smrg MATCH_MASK(renderType); 1032b8e80941Smrg MATCH_DONT_CARE(sRGBCapable); 1033848b8605Smrg 1034848b8605Smrg /* There is a bug in a few of the XFree86 DDX drivers. They contain 1035848b8605Smrg * visuals with a "transparent type" of 0 when they really mean GLX_NONE. 1036848b8605Smrg * Technically speaking, it is a bug in the DDX driver, but there is 1037848b8605Smrg * enough of an installed base to work around the problem here. In any 1038848b8605Smrg * case, 0 is not a valid value of the transparent type, so we'll treat 0 1039848b8605Smrg * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and 1040848b8605Smrg * 0 from the server to be a match to maintain backward compatibility with 1041848b8605Smrg * the (broken) drivers. 1042848b8605Smrg */ 1043848b8605Smrg 1044848b8605Smrg if (a->transparentPixel != (int) GLX_DONT_CARE && a->transparentPixel != 0) { 1045848b8605Smrg if (a->transparentPixel == GLX_NONE) { 1046848b8605Smrg if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0) 1047848b8605Smrg return False; 1048848b8605Smrg } 1049848b8605Smrg else { 1050848b8605Smrg MATCH_EXACT(transparentPixel); 1051848b8605Smrg } 1052848b8605Smrg 1053848b8605Smrg switch (a->transparentPixel) { 1054848b8605Smrg case GLX_TRANSPARENT_RGB: 1055848b8605Smrg MATCH_DONT_CARE(transparentRed); 1056848b8605Smrg MATCH_DONT_CARE(transparentGreen); 1057848b8605Smrg MATCH_DONT_CARE(transparentBlue); 1058848b8605Smrg MATCH_DONT_CARE(transparentAlpha); 1059848b8605Smrg break; 1060848b8605Smrg 1061848b8605Smrg case GLX_TRANSPARENT_INDEX: 1062848b8605Smrg MATCH_DONT_CARE(transparentIndex); 1063848b8605Smrg break; 1064848b8605Smrg 1065848b8605Smrg default: 1066848b8605Smrg break; 1067848b8605Smrg } 1068848b8605Smrg } 1069848b8605Smrg 1070848b8605Smrg return True; 1071848b8605Smrg} 1072848b8605Smrg 1073848b8605Smrg 1074848b8605Smrg/* There's some trickly language in the GLX spec about how this is supposed 1075848b8605Smrg * to work. Basically, if a given component size is either not specified 1076848b8605Smrg * or the requested size is zero, it is supposed to act like PERFER_SMALLER. 1077848b8605Smrg * Well, that's really hard to do with the code as-is. This behavior is 1078848b8605Smrg * closer to correct, but still not technically right. 1079848b8605Smrg */ 1080848b8605Smrg#define PREFER_LARGER_OR_ZERO(comp) \ 1081848b8605Smrg do { \ 1082848b8605Smrg if ( ((*a)-> comp) != ((*b)-> comp) ) { \ 1083848b8605Smrg if ( ((*a)-> comp) == 0 ) { \ 1084848b8605Smrg return -1; \ 1085848b8605Smrg } \ 1086848b8605Smrg else if ( ((*b)-> comp) == 0 ) { \ 1087848b8605Smrg return 1; \ 1088848b8605Smrg } \ 1089848b8605Smrg else { \ 1090848b8605Smrg return ((*b)-> comp) - ((*a)-> comp) ; \ 1091848b8605Smrg } \ 1092848b8605Smrg } \ 1093848b8605Smrg } while( 0 ) 1094848b8605Smrg 1095848b8605Smrg#define PREFER_LARGER(comp) \ 1096848b8605Smrg do { \ 1097848b8605Smrg if ( ((*a)-> comp) != ((*b)-> comp) ) { \ 1098848b8605Smrg return ((*b)-> comp) - ((*a)-> comp) ; \ 1099848b8605Smrg } \ 1100848b8605Smrg } while( 0 ) 1101848b8605Smrg 1102848b8605Smrg#define PREFER_SMALLER(comp) \ 1103848b8605Smrg do { \ 1104848b8605Smrg if ( ((*a)-> comp) != ((*b)-> comp) ) { \ 1105848b8605Smrg return ((*a)-> comp) - ((*b)-> comp) ; \ 1106848b8605Smrg } \ 1107848b8605Smrg } while( 0 ) 1108848b8605Smrg 1109848b8605Smrg/** 1110848b8605Smrg * Compare two GLXFBConfigs. This function is intended to be used as the 1111848b8605Smrg * compare function passed in to qsort. 1112848b8605Smrg * 1113848b8605Smrg * \returns If \c a is a "better" config, according to the specification of 1114848b8605Smrg * SGIX_fbconfig, a number less than zero is returned. If \c b is 1115848b8605Smrg * better, then a number greater than zero is return. If both are 1116848b8605Smrg * equal, zero is returned. 1117848b8605Smrg * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX 1118848b8605Smrg */ 1119848b8605Smrgstatic int 1120848b8605Smrgfbconfig_compare(struct glx_config **a, struct glx_config **b) 1121848b8605Smrg{ 1122848b8605Smrg /* The order of these comparisons must NOT change. It is defined by 1123848b8605Smrg * the GLX 1.4 specification. 1124848b8605Smrg */ 1125848b8605Smrg 1126848b8605Smrg PREFER_SMALLER(visualSelectGroup); 1127848b8605Smrg 1128848b8605Smrg /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and 1129848b8605Smrg * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the 1130848b8605Smrg * numerical sort order of the enums (0x8000, 0x8001, and 0x800D). 1131848b8605Smrg */ 1132848b8605Smrg PREFER_SMALLER(visualRating); 1133848b8605Smrg 1134848b8605Smrg /* This isn't quite right. It is supposed to compare the sum of the 1135848b8605Smrg * components the user specifically set minimums for. 1136848b8605Smrg */ 1137848b8605Smrg PREFER_LARGER_OR_ZERO(redBits); 1138848b8605Smrg PREFER_LARGER_OR_ZERO(greenBits); 1139848b8605Smrg PREFER_LARGER_OR_ZERO(blueBits); 1140848b8605Smrg PREFER_LARGER_OR_ZERO(alphaBits); 1141848b8605Smrg 1142848b8605Smrg PREFER_SMALLER(rgbBits); 1143848b8605Smrg 1144848b8605Smrg if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) { 1145848b8605Smrg /* Prefer single-buffer. 1146848b8605Smrg */ 1147848b8605Smrg return (!(*a)->doubleBufferMode) ? -1 : 1; 1148848b8605Smrg } 1149848b8605Smrg 1150848b8605Smrg PREFER_SMALLER(numAuxBuffers); 1151848b8605Smrg 1152848b8605Smrg PREFER_SMALLER(sampleBuffers); 1153848b8605Smrg PREFER_SMALLER(samples); 1154848b8605Smrg 1155848b8605Smrg PREFER_LARGER_OR_ZERO(depthBits); 1156848b8605Smrg PREFER_SMALLER(stencilBits); 1157848b8605Smrg 1158848b8605Smrg /* This isn't quite right. It is supposed to compare the sum of the 1159848b8605Smrg * components the user specifically set minimums for. 1160848b8605Smrg */ 1161848b8605Smrg PREFER_LARGER_OR_ZERO(accumRedBits); 1162848b8605Smrg PREFER_LARGER_OR_ZERO(accumGreenBits); 1163848b8605Smrg PREFER_LARGER_OR_ZERO(accumBlueBits); 1164848b8605Smrg PREFER_LARGER_OR_ZERO(accumAlphaBits); 1165848b8605Smrg 1166848b8605Smrg PREFER_SMALLER(visualType); 1167848b8605Smrg 1168848b8605Smrg /* None of the pbuffer or fbconfig specs say that this comparison needs 1169848b8605Smrg * to happen at all, but it seems like it should. 1170848b8605Smrg */ 1171848b8605Smrg PREFER_LARGER(maxPbufferWidth); 1172848b8605Smrg PREFER_LARGER(maxPbufferHeight); 1173848b8605Smrg PREFER_LARGER(maxPbufferPixels); 1174848b8605Smrg 1175848b8605Smrg return 0; 1176848b8605Smrg} 1177848b8605Smrg 1178848b8605Smrg 1179848b8605Smrg/** 1180848b8605Smrg * Selects and sorts a subset of the supplied configs based on the attributes. 1181b8e80941Smrg * This function forms to basis of \c glXChooseFBConfig and 1182b8e80941Smrg * \c glXChooseFBConfigSGIX. 1183848b8605Smrg * 1184848b8605Smrg * \param configs Array of pointers to possible configs. The elements of 1185848b8605Smrg * this array that do not meet the criteria will be set to 1186848b8605Smrg * NULL. The remaining elements will be sorted according to 1187848b8605Smrg * the various visual / FBConfig selection rules. 1188848b8605Smrg * \param num_configs Number of elements in the \c configs array. 1189848b8605Smrg * \param attribList Attributes used select from \c configs. This array is 1190b8e80941Smrg * terminated by a \c None tag. The array is of the form 1191b8e80941Smrg * expected by \c glXChooseFBConfig (where every tag has a 1192b8e80941Smrg * value). 1193848b8605Smrg * \returns The number of valid elements left in \c configs. 1194848b8605Smrg * 1195b8e80941Smrg * \sa glXChooseFBConfig, glXChooseFBConfigSGIX 1196848b8605Smrg */ 1197848b8605Smrgstatic int 1198b8e80941Smrgchoose_fbconfig(struct glx_config ** configs, int num_configs, 1199b8e80941Smrg const int *attribList) 1200848b8605Smrg{ 1201848b8605Smrg struct glx_config test_config; 1202848b8605Smrg int base; 1203848b8605Smrg int i; 1204848b8605Smrg 1205848b8605Smrg /* This is a fairly direct implementation of the selection method 1206848b8605Smrg * described by GLX_SGIX_fbconfig. Start by culling out all the 1207848b8605Smrg * configs that are not compatible with the selected parameter 1208848b8605Smrg * list. 1209848b8605Smrg */ 1210848b8605Smrg 1211b8e80941Smrg init_fbconfig_for_chooser(&test_config, GL_TRUE); 1212848b8605Smrg __glXInitializeVisualConfigFromTags(&test_config, 512, 1213848b8605Smrg (const INT32 *) attribList, 1214b8e80941Smrg GL_TRUE, GL_TRUE); 1215848b8605Smrg 1216848b8605Smrg base = 0; 1217848b8605Smrg for (i = 0; i < num_configs; i++) { 1218848b8605Smrg if (fbconfigs_compatible(&test_config, configs[i])) { 1219848b8605Smrg configs[base] = configs[i]; 1220848b8605Smrg base++; 1221848b8605Smrg } 1222848b8605Smrg } 1223848b8605Smrg 1224848b8605Smrg if (base == 0) { 1225848b8605Smrg return 0; 1226848b8605Smrg } 1227848b8605Smrg 1228848b8605Smrg if (base < num_configs) { 1229848b8605Smrg (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base)); 1230848b8605Smrg } 1231848b8605Smrg 1232848b8605Smrg /* After the incompatible configs are removed, the resulting 1233848b8605Smrg * list is sorted according to the rules set out in the various 1234848b8605Smrg * specifications. 1235848b8605Smrg */ 1236848b8605Smrg 1237848b8605Smrg qsort(configs, base, sizeof(struct glx_config *), 1238848b8605Smrg (int (*)(const void *, const void *)) fbconfig_compare); 1239848b8605Smrg return base; 1240848b8605Smrg} 1241848b8605Smrg 1242848b8605Smrg 1243848b8605Smrg 1244848b8605Smrg 1245848b8605Smrg/* 1246848b8605Smrg** Return the visual that best matches the template. Return None if no 1247848b8605Smrg** visual matches the template. 1248848b8605Smrg*/ 1249b8e80941Smrg_GLX_PUBLIC XVisualInfo * 1250848b8605SmrgglXChooseVisual(Display * dpy, int screen, int *attribList) 1251848b8605Smrg{ 1252848b8605Smrg XVisualInfo *visualList = NULL; 1253848b8605Smrg struct glx_display *priv; 1254848b8605Smrg struct glx_screen *psc; 1255848b8605Smrg struct glx_config test_config; 1256848b8605Smrg struct glx_config *config; 1257848b8605Smrg struct glx_config *best_config = NULL; 1258848b8605Smrg 1259848b8605Smrg /* 1260848b8605Smrg ** Get a list of all visuals, return if list is empty 1261848b8605Smrg */ 1262848b8605Smrg if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { 1263848b8605Smrg return None; 1264848b8605Smrg } 1265848b8605Smrg 1266848b8605Smrg 1267848b8605Smrg /* 1268848b8605Smrg ** Build a template from the defaults and the attribute list 1269848b8605Smrg ** Free visual list and return if an unexpected token is encountered 1270848b8605Smrg */ 1271848b8605Smrg init_fbconfig_for_chooser(&test_config, GL_FALSE); 1272848b8605Smrg __glXInitializeVisualConfigFromTags(&test_config, 512, 1273848b8605Smrg (const INT32 *) attribList, 1274848b8605Smrg GL_TRUE, GL_FALSE); 1275848b8605Smrg 1276848b8605Smrg /* 1277848b8605Smrg ** Eliminate visuals that don't meet minimum requirements 1278848b8605Smrg ** Compute a score for those that do 1279848b8605Smrg ** Remember which visual, if any, got the highest score 1280848b8605Smrg ** If no visual is acceptable, return None 1281848b8605Smrg ** Otherwise, create an XVisualInfo list with just the selected X visual 1282848b8605Smrg ** and return this. 1283848b8605Smrg */ 1284848b8605Smrg for (config = psc->visuals; config != NULL; config = config->next) { 1285848b8605Smrg if (fbconfigs_compatible(&test_config, config) 1286848b8605Smrg && ((best_config == NULL) || 1287848b8605Smrg (fbconfig_compare (&config, &best_config) < 0))) { 1288848b8605Smrg XVisualInfo visualTemplate; 1289848b8605Smrg XVisualInfo *newList; 1290848b8605Smrg int i; 1291848b8605Smrg 1292848b8605Smrg visualTemplate.screen = screen; 1293848b8605Smrg visualTemplate.visualid = config->visualID; 1294848b8605Smrg newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, 1295848b8605Smrg &visualTemplate, &i); 1296848b8605Smrg 1297848b8605Smrg if (newList) { 1298848b8605Smrg free(visualList); 1299848b8605Smrg visualList = newList; 1300848b8605Smrg best_config = config; 1301848b8605Smrg } 1302848b8605Smrg } 1303848b8605Smrg } 1304848b8605Smrg 1305848b8605Smrg#ifdef GLX_USE_APPLEGL 1306b8e80941Smrg if(visualList && env_var_as_boolean("LIBGL_DUMP_VISUALID", false)) { 1307848b8605Smrg printf("visualid 0x%lx\n", visualList[0].visualid); 1308848b8605Smrg } 1309848b8605Smrg#endif 1310848b8605Smrg 1311848b8605Smrg return visualList; 1312848b8605Smrg} 1313848b8605Smrg 1314848b8605Smrg 1315b8e80941Smrg_GLX_PUBLIC const char * 1316848b8605SmrgglXQueryExtensionsString(Display * dpy, int screen) 1317848b8605Smrg{ 1318848b8605Smrg struct glx_screen *psc; 1319848b8605Smrg struct glx_display *priv; 1320848b8605Smrg 1321848b8605Smrg if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { 1322848b8605Smrg return NULL; 1323848b8605Smrg } 1324848b8605Smrg 1325848b8605Smrg if (!psc->effectiveGLXexts) { 1326848b8605Smrg if (!psc->serverGLXexts) { 1327848b8605Smrg psc->serverGLXexts = 1328848b8605Smrg __glXQueryServerString(dpy, priv->majorOpcode, screen, 1329848b8605Smrg GLX_EXTENSIONS); 1330848b8605Smrg } 1331848b8605Smrg 1332848b8605Smrg __glXCalculateUsableExtensions(psc, 1333848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 1334848b8605Smrg (psc->driScreen != NULL), 1335848b8605Smrg#else 1336848b8605Smrg GL_FALSE, 1337848b8605Smrg#endif 1338848b8605Smrg priv->minorVersion); 1339848b8605Smrg } 1340848b8605Smrg 1341848b8605Smrg return psc->effectiveGLXexts; 1342848b8605Smrg} 1343848b8605Smrg 1344b8e80941Smrg_GLX_PUBLIC const char * 1345848b8605SmrgglXGetClientString(Display * dpy, int name) 1346848b8605Smrg{ 1347848b8605Smrg (void) dpy; 1348848b8605Smrg 1349848b8605Smrg switch (name) { 1350848b8605Smrg case GLX_VENDOR: 1351848b8605Smrg return (__glXGLXClientVendorName); 1352848b8605Smrg case GLX_VERSION: 1353848b8605Smrg return (__glXGLXClientVersion); 1354848b8605Smrg case GLX_EXTENSIONS: 1355848b8605Smrg return (__glXGetClientExtensions()); 1356848b8605Smrg default: 1357848b8605Smrg return NULL; 1358848b8605Smrg } 1359848b8605Smrg} 1360848b8605Smrg 1361b8e80941Smrg_GLX_PUBLIC const char * 1362848b8605SmrgglXQueryServerString(Display * dpy, int screen, int name) 1363848b8605Smrg{ 1364848b8605Smrg struct glx_screen *psc; 1365848b8605Smrg struct glx_display *priv; 1366848b8605Smrg const char **str; 1367848b8605Smrg 1368848b8605Smrg 1369848b8605Smrg if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { 1370848b8605Smrg return NULL; 1371848b8605Smrg } 1372848b8605Smrg 1373848b8605Smrg switch (name) { 1374848b8605Smrg case GLX_VENDOR: 1375848b8605Smrg str = &priv->serverGLXvendor; 1376848b8605Smrg break; 1377848b8605Smrg case GLX_VERSION: 1378848b8605Smrg str = &priv->serverGLXversion; 1379848b8605Smrg break; 1380848b8605Smrg case GLX_EXTENSIONS: 1381848b8605Smrg str = &psc->serverGLXexts; 1382848b8605Smrg break; 1383848b8605Smrg default: 1384848b8605Smrg return NULL; 1385848b8605Smrg } 1386848b8605Smrg 1387848b8605Smrg if (*str == NULL) { 1388848b8605Smrg *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name); 1389848b8605Smrg } 1390848b8605Smrg 1391848b8605Smrg return *str; 1392848b8605Smrg} 1393848b8605Smrg 1394848b8605Smrg 1395848b8605Smrg/* 1396848b8605Smrg** EXT_import_context 1397848b8605Smrg*/ 1398848b8605Smrg 1399b8e80941Smrg_GLX_PUBLIC Display * 1400848b8605SmrgglXGetCurrentDisplay(void) 1401848b8605Smrg{ 1402848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 1403b8e80941Smrg if (gc == &dummyContext) 1404848b8605Smrg return NULL; 1405848b8605Smrg return gc->currentDpy; 1406848b8605Smrg} 1407848b8605Smrg 1408b8e80941Smrg_GLX_PUBLIC 1409848b8605SmrgGLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (), 1410848b8605Smrg glXGetCurrentDisplay) 1411848b8605Smrg 1412848b8605Smrg#ifndef GLX_USE_APPLEGL 1413b8e80941Smrg_GLX_PUBLIC GLXContext 1414848b8605SmrgglXImportContextEXT(Display *dpy, GLXContextID contextID) 1415848b8605Smrg{ 1416848b8605Smrg struct glx_display *priv = __glXInitialize(dpy); 1417848b8605Smrg struct glx_screen *psc = NULL; 1418848b8605Smrg xGLXQueryContextReply reply; 1419848b8605Smrg CARD8 opcode; 1420848b8605Smrg struct glx_context *ctx; 1421b8e80941Smrg int i, renderType = GLX_RGBA_TYPE; /* By default, assume RGBA context */ 1422b8e80941Smrg XID share = None; 1423b8e80941Smrg struct glx_config *mode = NULL; 1424848b8605Smrg uint32_t fbconfigID = 0; 1425848b8605Smrg uint32_t visualID = 0; 1426848b8605Smrg uint32_t screen = 0; 1427848b8605Smrg Bool got_screen = False; 1428848b8605Smrg 1429848b8605Smrg if (priv == NULL) 1430848b8605Smrg return NULL; 1431848b8605Smrg 1432848b8605Smrg /* The GLX_EXT_import_context spec says: 1433848b8605Smrg * 1434848b8605Smrg * "If <contextID> does not refer to a valid context, then a BadContext 1435848b8605Smrg * error is generated; if <contextID> refers to direct rendering 1436848b8605Smrg * context then no error is generated but glXImportContextEXT returns 1437848b8605Smrg * NULL." 1438848b8605Smrg * 1439848b8605Smrg * If contextID is None, generate BadContext on the client-side. Other 1440848b8605Smrg * sorts of invalid contexts will be detected by the server in the 1441848b8605Smrg * __glXIsDirect call. 1442848b8605Smrg */ 1443848b8605Smrg if (contextID == None) { 1444848b8605Smrg __glXSendError(dpy, GLXBadContext, contextID, X_GLXIsDirect, false); 1445848b8605Smrg return NULL; 1446848b8605Smrg } 1447848b8605Smrg 1448b8e80941Smrg if (__glXIsDirect(dpy, contextID, NULL)) 1449848b8605Smrg return NULL; 1450848b8605Smrg 1451848b8605Smrg opcode = __glXSetupForCommand(dpy); 1452848b8605Smrg if (!opcode) 1453848b8605Smrg return 0; 1454848b8605Smrg 1455848b8605Smrg /* Send the glXQueryContextInfoEXT request */ 1456848b8605Smrg LockDisplay(dpy); 1457848b8605Smrg 1458848b8605Smrg if (priv->majorVersion > 1 || priv->minorVersion >= 3) { 1459848b8605Smrg xGLXQueryContextReq *req; 1460848b8605Smrg 1461848b8605Smrg GetReq(GLXQueryContext, req); 1462848b8605Smrg 1463848b8605Smrg req->reqType = opcode; 1464848b8605Smrg req->glxCode = X_GLXQueryContext; 1465848b8605Smrg req->context = contextID; 1466848b8605Smrg } 1467848b8605Smrg else { 1468848b8605Smrg xGLXVendorPrivateReq *vpreq; 1469848b8605Smrg xGLXQueryContextInfoEXTReq *req; 1470848b8605Smrg 1471848b8605Smrg GetReqExtra(GLXVendorPrivate, 1472848b8605Smrg sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq, 1473848b8605Smrg vpreq); 1474848b8605Smrg req = (xGLXQueryContextInfoEXTReq *) vpreq; 1475848b8605Smrg req->reqType = opcode; 1476848b8605Smrg req->glxCode = X_GLXVendorPrivateWithReply; 1477848b8605Smrg req->vendorCode = X_GLXvop_QueryContextInfoEXT; 1478848b8605Smrg req->context = contextID; 1479848b8605Smrg } 1480848b8605Smrg 1481b8e80941Smrg if (_XReply(dpy, (xReply *) & reply, 0, False) && 1482b8e80941Smrg reply.n < (INT32_MAX / 2)) { 1483b8e80941Smrg 1484b8e80941Smrg for (i = 0; i < reply.n; i++) { 1485b8e80941Smrg int prop[2]; 1486b8e80941Smrg 1487b8e80941Smrg _XRead(dpy, (char *)prop, sizeof(prop)); 1488b8e80941Smrg switch (prop[0]) { 1489b8e80941Smrg case GLX_SCREEN: 1490b8e80941Smrg screen = prop[1]; 1491b8e80941Smrg got_screen = True; 1492b8e80941Smrg break; 1493b8e80941Smrg case GLX_SHARE_CONTEXT_EXT: 1494b8e80941Smrg share = prop[1]; 1495b8e80941Smrg break; 1496b8e80941Smrg case GLX_VISUAL_ID_EXT: 1497b8e80941Smrg visualID = prop[1]; 1498b8e80941Smrg break; 1499b8e80941Smrg case GLX_FBCONFIG_ID: 1500b8e80941Smrg fbconfigID = prop[1]; 1501b8e80941Smrg break; 1502b8e80941Smrg case GLX_RENDER_TYPE: 1503b8e80941Smrg renderType = prop[1]; 1504b8e80941Smrg break; 1505b8e80941Smrg } 1506b8e80941Smrg } 1507b8e80941Smrg } 1508848b8605Smrg UnlockDisplay(dpy); 1509848b8605Smrg SyncHandle(); 1510848b8605Smrg 1511848b8605Smrg if (!got_screen) 1512848b8605Smrg return NULL; 1513848b8605Smrg 1514848b8605Smrg psc = GetGLXScreenConfigs(dpy, screen); 1515848b8605Smrg if (psc == NULL) 1516848b8605Smrg return NULL; 1517848b8605Smrg 1518848b8605Smrg if (fbconfigID != 0) { 1519848b8605Smrg mode = glx_config_find_fbconfig(psc->configs, fbconfigID); 1520848b8605Smrg } else if (visualID != 0) { 1521848b8605Smrg mode = glx_config_find_visual(psc->visuals, visualID); 1522848b8605Smrg } 1523848b8605Smrg 1524848b8605Smrg if (mode == NULL) 1525848b8605Smrg return NULL; 1526848b8605Smrg 1527848b8605Smrg ctx = indirect_create_context(psc, mode, NULL, renderType); 1528848b8605Smrg if (ctx == NULL) 1529848b8605Smrg return NULL; 1530848b8605Smrg 1531848b8605Smrg ctx->xid = contextID; 1532848b8605Smrg ctx->imported = GL_TRUE; 1533848b8605Smrg ctx->share_xid = share; 1534848b8605Smrg 1535848b8605Smrg return (GLXContext) ctx; 1536848b8605Smrg} 1537848b8605Smrg 1538848b8605Smrg#endif 1539848b8605Smrg 1540b8e80941Smrg_GLX_PUBLIC int 1541848b8605SmrgglXQueryContext(Display * dpy, GLXContext ctx_user, int attribute, int *value) 1542848b8605Smrg{ 1543848b8605Smrg struct glx_context *ctx = (struct glx_context *) ctx_user; 1544848b8605Smrg 1545848b8605Smrg switch (attribute) { 1546848b8605Smrg case GLX_SHARE_CONTEXT_EXT: 1547848b8605Smrg *value = ctx->share_xid; 1548848b8605Smrg break; 1549848b8605Smrg case GLX_VISUAL_ID_EXT: 1550848b8605Smrg *value = ctx->config ? ctx->config->visualID : None; 1551848b8605Smrg break; 1552848b8605Smrg case GLX_SCREEN: 1553848b8605Smrg *value = ctx->screen; 1554848b8605Smrg break; 1555848b8605Smrg case GLX_FBCONFIG_ID: 1556848b8605Smrg *value = ctx->config ? ctx->config->fbconfigID : None; 1557848b8605Smrg break; 1558848b8605Smrg case GLX_RENDER_TYPE: 1559848b8605Smrg *value = ctx->renderType; 1560848b8605Smrg break; 1561848b8605Smrg default: 1562848b8605Smrg return GLX_BAD_ATTRIBUTE; 1563848b8605Smrg } 1564848b8605Smrg return Success; 1565848b8605Smrg} 1566848b8605Smrg 1567b8e80941Smrg_GLX_PUBLIC 1568848b8605SmrgGLX_ALIAS(int, glXQueryContextInfoEXT, 1569848b8605Smrg (Display * dpy, GLXContext ctx, int attribute, int *value), 1570848b8605Smrg (dpy, ctx, attribute, value), glXQueryContext) 1571848b8605Smrg 1572b8e80941Smrg_GLX_PUBLIC GLXContextID glXGetContextIDEXT(const GLXContext ctx_user) 1573848b8605Smrg{ 1574848b8605Smrg struct glx_context *ctx = (struct glx_context *) ctx_user; 1575848b8605Smrg 1576848b8605Smrg return (ctx == NULL) ? None : ctx->xid; 1577848b8605Smrg} 1578848b8605Smrg 1579b8e80941Smrg_GLX_PUBLIC void 1580848b8605SmrgglXFreeContextEXT(Display *dpy, GLXContext ctx) 1581848b8605Smrg{ 1582848b8605Smrg struct glx_context *gc = (struct glx_context *) ctx; 1583848b8605Smrg 1584848b8605Smrg if (gc == NULL || gc->xid == None) 1585848b8605Smrg return; 1586848b8605Smrg 1587848b8605Smrg /* The GLX_EXT_import_context spec says: 1588848b8605Smrg * 1589848b8605Smrg * "glXFreeContext does not free the server-side context information or 1590848b8605Smrg * the XID associated with the server-side context." 1591848b8605Smrg * 1592848b8605Smrg * Don't send any protocol. Just destroy the client-side tracking of the 1593848b8605Smrg * context. Also, only release the context structure if it's not current. 1594848b8605Smrg */ 1595848b8605Smrg __glXLock(); 1596848b8605Smrg if (gc->currentDpy) { 1597848b8605Smrg gc->xid = None; 1598848b8605Smrg } else { 1599848b8605Smrg gc->vtable->destroy(gc); 1600848b8605Smrg } 1601848b8605Smrg __glXUnlock(); 1602848b8605Smrg} 1603848b8605Smrg 1604b8e80941Smrg_GLX_PUBLIC GLXFBConfig * 1605848b8605SmrgglXChooseFBConfig(Display * dpy, int screen, 1606848b8605Smrg const int *attribList, int *nitems) 1607848b8605Smrg{ 1608848b8605Smrg struct glx_config **config_list; 1609848b8605Smrg int list_size; 1610848b8605Smrg 1611848b8605Smrg 1612848b8605Smrg config_list = (struct glx_config **) 1613848b8605Smrg glXGetFBConfigs(dpy, screen, &list_size); 1614848b8605Smrg 1615848b8605Smrg if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) { 1616b8e80941Smrg list_size = choose_fbconfig(config_list, list_size, attribList); 1617848b8605Smrg if (list_size == 0) { 1618848b8605Smrg free(config_list); 1619848b8605Smrg config_list = NULL; 1620848b8605Smrg } 1621848b8605Smrg } 1622848b8605Smrg 1623848b8605Smrg *nitems = list_size; 1624848b8605Smrg return (GLXFBConfig *) config_list; 1625848b8605Smrg} 1626848b8605Smrg 1627848b8605Smrg 1628b8e80941Smrg_GLX_PUBLIC GLXContext 1629848b8605SmrgglXCreateNewContext(Display * dpy, GLXFBConfig fbconfig, 1630848b8605Smrg int renderType, GLXContext shareList, Bool allowDirect) 1631848b8605Smrg{ 1632848b8605Smrg struct glx_config *config = (struct glx_config *) fbconfig; 1633b8e80941Smrg struct glx_config **config_list; 1634b8e80941Smrg int list_size; 1635b8e80941Smrg unsigned i; 1636b8e80941Smrg 1637b8e80941Smrg if (!config) { 1638b8e80941Smrg __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateNewContext, false); 1639b8e80941Smrg return NULL; 1640b8e80941Smrg } 1641b8e80941Smrg 1642b8e80941Smrg config_list = (struct glx_config **) 1643b8e80941Smrg glXGetFBConfigs(dpy, config->screen, &list_size); 1644b8e80941Smrg 1645b8e80941Smrg for (i = 0; i < list_size; i++) { 1646b8e80941Smrg if (config_list[i] == config) 1647b8e80941Smrg break; 1648b8e80941Smrg } 1649b8e80941Smrg free(config_list); 1650b8e80941Smrg 1651b8e80941Smrg if (i == list_size) { 1652b8e80941Smrg __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateNewContext, false); 1653b8e80941Smrg return NULL; 1654b8e80941Smrg } 1655848b8605Smrg 1656848b8605Smrg return CreateContext(dpy, config->fbconfigID, config, shareList, 1657848b8605Smrg allowDirect, X_GLXCreateNewContext, renderType, 1658848b8605Smrg config->screen); 1659848b8605Smrg} 1660848b8605Smrg 1661848b8605Smrg 1662b8e80941Smrg_GLX_PUBLIC GLXDrawable 1663848b8605SmrgglXGetCurrentReadDrawable(void) 1664848b8605Smrg{ 1665848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 1666848b8605Smrg 1667848b8605Smrg return gc->currentReadable; 1668848b8605Smrg} 1669848b8605Smrg 1670848b8605Smrg 1671b8e80941Smrg_GLX_PUBLIC GLXFBConfig * 1672848b8605SmrgglXGetFBConfigs(Display * dpy, int screen, int *nelements) 1673848b8605Smrg{ 1674848b8605Smrg struct glx_display *priv = __glXInitialize(dpy); 1675848b8605Smrg struct glx_config **config_list = NULL; 1676848b8605Smrg struct glx_config *config; 1677848b8605Smrg unsigned num_configs = 0; 1678848b8605Smrg int i; 1679848b8605Smrg 1680848b8605Smrg *nelements = 0; 1681848b8605Smrg if (priv && (priv->screens != NULL) 1682b8e80941Smrg && (screen >= 0) && (screen < ScreenCount(dpy)) 1683848b8605Smrg && (priv->screens[screen]->configs != NULL) 1684848b8605Smrg && (priv->screens[screen]->configs->fbconfigID 1685848b8605Smrg != (int) GLX_DONT_CARE)) { 1686848b8605Smrg 1687848b8605Smrg for (config = priv->screens[screen]->configs; config != NULL; 1688848b8605Smrg config = config->next) { 1689848b8605Smrg if (config->fbconfigID != (int) GLX_DONT_CARE) { 1690848b8605Smrg num_configs++; 1691848b8605Smrg } 1692848b8605Smrg } 1693848b8605Smrg 1694848b8605Smrg config_list = malloc(num_configs * sizeof *config_list); 1695848b8605Smrg if (config_list != NULL) { 1696848b8605Smrg *nelements = num_configs; 1697848b8605Smrg i = 0; 1698848b8605Smrg for (config = priv->screens[screen]->configs; config != NULL; 1699848b8605Smrg config = config->next) { 1700848b8605Smrg if (config->fbconfigID != (int) GLX_DONT_CARE) { 1701848b8605Smrg config_list[i] = config; 1702848b8605Smrg i++; 1703848b8605Smrg } 1704848b8605Smrg } 1705848b8605Smrg } 1706848b8605Smrg } 1707848b8605Smrg 1708848b8605Smrg return (GLXFBConfig *) config_list; 1709848b8605Smrg} 1710848b8605Smrg 1711848b8605Smrg 1712b8e80941Smrg_GLX_PUBLIC int 1713848b8605SmrgglXGetFBConfigAttrib(Display * dpy, GLXFBConfig fbconfig, 1714848b8605Smrg int attribute, int *value) 1715848b8605Smrg{ 1716848b8605Smrg struct glx_config *config = ValidateGLXFBConfig(dpy, fbconfig); 1717848b8605Smrg 1718848b8605Smrg if (config == NULL) 1719848b8605Smrg return GLXBadFBConfig; 1720848b8605Smrg 1721848b8605Smrg return glx_config_get(config, attribute, value); 1722848b8605Smrg} 1723848b8605Smrg 1724848b8605Smrg 1725b8e80941Smrg_GLX_PUBLIC XVisualInfo * 1726848b8605SmrgglXGetVisualFromFBConfig(Display * dpy, GLXFBConfig fbconfig) 1727848b8605Smrg{ 1728848b8605Smrg XVisualInfo visualTemplate; 1729848b8605Smrg struct glx_config *config = (struct glx_config *) fbconfig; 1730848b8605Smrg int count; 1731848b8605Smrg 1732848b8605Smrg /* 1733848b8605Smrg ** Get a list of all visuals, return if list is empty 1734848b8605Smrg */ 1735848b8605Smrg visualTemplate.visualid = config->visualID; 1736848b8605Smrg return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count); 1737848b8605Smrg} 1738848b8605Smrg 1739848b8605Smrg#ifndef GLX_USE_APPLEGL 1740848b8605Smrg/* 1741848b8605Smrg** GLX_SGI_swap_control 1742848b8605Smrg*/ 1743848b8605Smrgstatic int 1744848b8605Smrg__glXSwapIntervalSGI(int interval) 1745848b8605Smrg{ 1746848b8605Smrg xGLXVendorPrivateReq *req; 1747848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 1748848b8605Smrg struct glx_screen *psc; 1749848b8605Smrg Display *dpy; 1750848b8605Smrg CARD32 *interval_ptr; 1751848b8605Smrg CARD8 opcode; 1752848b8605Smrg 1753b8e80941Smrg if (gc == &dummyContext) { 1754848b8605Smrg return GLX_BAD_CONTEXT; 1755848b8605Smrg } 1756848b8605Smrg 1757848b8605Smrg if (interval <= 0) { 1758848b8605Smrg return GLX_BAD_VALUE; 1759848b8605Smrg } 1760848b8605Smrg 1761848b8605Smrg psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1762848b8605Smrg 1763848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1764848b8605Smrg if (gc->isDirect && psc && psc->driScreen && 1765848b8605Smrg psc->driScreen->setSwapInterval) { 1766848b8605Smrg __GLXDRIdrawable *pdraw = 1767848b8605Smrg GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1768b8e80941Smrg /* Simply ignore the command if the GLX drawable has been destroyed but 1769b8e80941Smrg * the context is still bound. 1770b8e80941Smrg */ 1771b8e80941Smrg if (pdraw) 1772b8e80941Smrg psc->driScreen->setSwapInterval(pdraw, interval); 1773848b8605Smrg return 0; 1774848b8605Smrg } 1775848b8605Smrg#endif 1776848b8605Smrg 1777848b8605Smrg dpy = gc->currentDpy; 1778848b8605Smrg opcode = __glXSetupForCommand(dpy); 1779848b8605Smrg if (!opcode) { 1780848b8605Smrg return 0; 1781848b8605Smrg } 1782848b8605Smrg 1783848b8605Smrg /* Send the glXSwapIntervalSGI request */ 1784848b8605Smrg LockDisplay(dpy); 1785848b8605Smrg GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req); 1786848b8605Smrg req->reqType = opcode; 1787848b8605Smrg req->glxCode = X_GLXVendorPrivate; 1788848b8605Smrg req->vendorCode = X_GLXvop_SwapIntervalSGI; 1789848b8605Smrg req->contextTag = gc->currentContextTag; 1790848b8605Smrg 1791848b8605Smrg interval_ptr = (CARD32 *) (req + 1); 1792848b8605Smrg *interval_ptr = interval; 1793848b8605Smrg 1794848b8605Smrg UnlockDisplay(dpy); 1795848b8605Smrg SyncHandle(); 1796848b8605Smrg XFlush(dpy); 1797848b8605Smrg 1798848b8605Smrg return 0; 1799848b8605Smrg} 1800848b8605Smrg 1801848b8605Smrg 1802848b8605Smrg/* 1803848b8605Smrg** GLX_MESA_swap_control 1804848b8605Smrg*/ 1805848b8605Smrgstatic int 1806848b8605Smrg__glXSwapIntervalMESA(unsigned int interval) 1807848b8605Smrg{ 1808848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1809848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 1810848b8605Smrg 1811b8e80941Smrg if (gc != &dummyContext && gc->isDirect) { 1812848b8605Smrg struct glx_screen *psc; 1813848b8605Smrg 1814848b8605Smrg psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1815848b8605Smrg if (psc && psc->driScreen && psc->driScreen->setSwapInterval) { 1816848b8605Smrg __GLXDRIdrawable *pdraw = 1817848b8605Smrg GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1818b8e80941Smrg 1819b8e80941Smrg /* Simply ignore the command if the GLX drawable has been destroyed but 1820b8e80941Smrg * the context is still bound. 1821b8e80941Smrg */ 1822b8e80941Smrg if (!pdraw) 1823b8e80941Smrg return 0; 1824b8e80941Smrg 1825b8e80941Smrg return psc->driScreen->setSwapInterval(pdraw, interval); 1826848b8605Smrg } 1827848b8605Smrg } 1828848b8605Smrg#endif 1829848b8605Smrg 1830848b8605Smrg return GLX_BAD_CONTEXT; 1831848b8605Smrg} 1832848b8605Smrg 1833848b8605Smrg 1834848b8605Smrgstatic int 1835848b8605Smrg__glXGetSwapIntervalMESA(void) 1836848b8605Smrg{ 1837848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1838848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 1839848b8605Smrg 1840b8e80941Smrg if (gc != &dummyContext && gc->isDirect) { 1841848b8605Smrg struct glx_screen *psc; 1842848b8605Smrg 1843848b8605Smrg psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1844848b8605Smrg if (psc && psc->driScreen && psc->driScreen->getSwapInterval) { 1845848b8605Smrg __GLXDRIdrawable *pdraw = 1846848b8605Smrg GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1847b8e80941Smrg if (pdraw) 1848b8e80941Smrg return psc->driScreen->getSwapInterval(pdraw); 1849848b8605Smrg } 1850848b8605Smrg } 1851848b8605Smrg#endif 1852848b8605Smrg 1853848b8605Smrg return 0; 1854848b8605Smrg} 1855848b8605Smrg 1856848b8605Smrg 1857848b8605Smrg/* 1858848b8605Smrg** GLX_SGI_video_sync 1859848b8605Smrg*/ 1860848b8605Smrgstatic int 1861848b8605Smrg__glXGetVideoSyncSGI(unsigned int *count) 1862848b8605Smrg{ 1863848b8605Smrg int64_t ust, msc, sbc; 1864848b8605Smrg int ret; 1865848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 1866848b8605Smrg struct glx_screen *psc; 1867848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1868848b8605Smrg __GLXDRIdrawable *pdraw; 1869848b8605Smrg#endif 1870848b8605Smrg 1871b8e80941Smrg if (gc == &dummyContext) 1872848b8605Smrg return GLX_BAD_CONTEXT; 1873848b8605Smrg 1874848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1875848b8605Smrg if (!gc->isDirect) 1876848b8605Smrg return GLX_BAD_CONTEXT; 1877848b8605Smrg#endif 1878848b8605Smrg 1879848b8605Smrg psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen); 1880848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1881848b8605Smrg pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1882848b8605Smrg#endif 1883848b8605Smrg 1884848b8605Smrg /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry, 1885848b8605Smrg * FIXME: there should be a GLX encoding for this call. I can find no 1886848b8605Smrg * FIXME: documentation for the GLX encoding. 1887848b8605Smrg */ 1888848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1889848b8605Smrg if (psc && psc->driScreen && psc->driScreen->getDrawableMSC) { 1890848b8605Smrg ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc); 1891848b8605Smrg *count = (unsigned) msc; 1892848b8605Smrg return (ret == True) ? 0 : GLX_BAD_CONTEXT; 1893848b8605Smrg } 1894848b8605Smrg#endif 1895848b8605Smrg 1896848b8605Smrg return GLX_BAD_CONTEXT; 1897848b8605Smrg} 1898848b8605Smrg 1899848b8605Smrgstatic int 1900848b8605Smrg__glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 1901848b8605Smrg{ 1902848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 1903848b8605Smrg struct glx_screen *psc; 1904848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1905848b8605Smrg __GLXDRIdrawable *pdraw; 1906848b8605Smrg#endif 1907848b8605Smrg int64_t ust, msc, sbc; 1908848b8605Smrg int ret; 1909848b8605Smrg 1910848b8605Smrg if (divisor <= 0 || remainder < 0) 1911848b8605Smrg return GLX_BAD_VALUE; 1912848b8605Smrg 1913b8e80941Smrg if (gc == &dummyContext) 1914848b8605Smrg return GLX_BAD_CONTEXT; 1915848b8605Smrg 1916848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1917848b8605Smrg if (!gc->isDirect) 1918848b8605Smrg return GLX_BAD_CONTEXT; 1919848b8605Smrg#endif 1920848b8605Smrg 1921848b8605Smrg psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); 1922848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1923848b8605Smrg pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); 1924848b8605Smrg#endif 1925848b8605Smrg 1926848b8605Smrg#ifdef GLX_DIRECT_RENDERING 1927848b8605Smrg if (psc && psc->driScreen && psc->driScreen->waitForMSC) { 1928848b8605Smrg ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc, 1929848b8605Smrg &sbc); 1930848b8605Smrg *count = (unsigned) msc; 1931848b8605Smrg return (ret == True) ? 0 : GLX_BAD_CONTEXT; 1932848b8605Smrg } 1933848b8605Smrg#endif 1934848b8605Smrg 1935848b8605Smrg return GLX_BAD_CONTEXT; 1936848b8605Smrg} 1937848b8605Smrg 1938848b8605Smrg#endif /* GLX_USE_APPLEGL */ 1939848b8605Smrg 1940848b8605Smrg/* 1941848b8605Smrg** GLX_SGIX_fbconfig 1942848b8605Smrg** Many of these functions are aliased to GLX 1.3 entry points in the 1943848b8605Smrg** GLX_functions table. 1944848b8605Smrg*/ 1945848b8605Smrg 1946b8e80941Smrg_GLX_PUBLIC 1947848b8605SmrgGLX_ALIAS(int, glXGetFBConfigAttribSGIX, 1948848b8605Smrg (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value), 1949848b8605Smrg (dpy, config, attribute, value), glXGetFBConfigAttrib) 1950848b8605Smrg 1951b8e80941Smrg_GLX_PUBLIC GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX, 1952848b8605Smrg (Display * dpy, int screen, int *attrib_list, 1953848b8605Smrg int *nelements), (dpy, screen, attrib_list, nelements), 1954848b8605Smrg glXChooseFBConfig) 1955848b8605Smrg 1956b8e80941Smrg_GLX_PUBLIC GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX, 1957848b8605Smrg (Display * dpy, GLXFBConfigSGIX config), 1958848b8605Smrg (dpy, config), glXGetVisualFromFBConfig) 1959848b8605Smrg 1960b8e80941Smrg_GLX_PUBLIC GLXPixmap 1961848b8605SmrgglXCreateGLXPixmapWithConfigSGIX(Display * dpy, 1962848b8605Smrg GLXFBConfigSGIX fbconfig, 1963848b8605Smrg Pixmap pixmap) 1964848b8605Smrg{ 1965848b8605Smrg#ifndef GLX_USE_APPLEGL 1966848b8605Smrg xGLXVendorPrivateWithReplyReq *vpreq; 1967848b8605Smrg xGLXCreateGLXPixmapWithConfigSGIXReq *req; 1968848b8605Smrg GLXPixmap xid = None; 1969848b8605Smrg CARD8 opcode; 1970848b8605Smrg struct glx_screen *psc; 1971848b8605Smrg#endif 1972848b8605Smrg struct glx_config *config = (struct glx_config *) fbconfig; 1973848b8605Smrg 1974848b8605Smrg 1975848b8605Smrg if ((dpy == NULL) || (config == NULL)) { 1976848b8605Smrg return None; 1977848b8605Smrg } 1978848b8605Smrg#ifdef GLX_USE_APPLEGL 1979848b8605Smrg if(apple_glx_pixmap_create(dpy, config->screen, pixmap, config)) 1980848b8605Smrg return None; 1981848b8605Smrg return pixmap; 1982848b8605Smrg#else 1983848b8605Smrg 1984848b8605Smrg psc = GetGLXScreenConfigs(dpy, config->screen); 1985848b8605Smrg if ((psc != NULL) 1986848b8605Smrg && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 1987848b8605Smrg opcode = __glXSetupForCommand(dpy); 1988848b8605Smrg if (!opcode) { 1989848b8605Smrg return None; 1990848b8605Smrg } 1991848b8605Smrg 1992848b8605Smrg /* Send the glXCreateGLXPixmapWithConfigSGIX request */ 1993848b8605Smrg LockDisplay(dpy); 1994848b8605Smrg GetReqExtra(GLXVendorPrivateWithReply, 1995848b8605Smrg sz_xGLXCreateGLXPixmapWithConfigSGIXReq - 1996848b8605Smrg sz_xGLXVendorPrivateWithReplyReq, vpreq); 1997848b8605Smrg req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq; 1998848b8605Smrg req->reqType = opcode; 1999848b8605Smrg req->glxCode = X_GLXVendorPrivateWithReply; 2000848b8605Smrg req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; 2001848b8605Smrg req->screen = config->screen; 2002848b8605Smrg req->fbconfig = config->fbconfigID; 2003848b8605Smrg req->pixmap = pixmap; 2004848b8605Smrg req->glxpixmap = xid = XAllocID(dpy); 2005848b8605Smrg UnlockDisplay(dpy); 2006848b8605Smrg SyncHandle(); 2007848b8605Smrg } 2008848b8605Smrg 2009848b8605Smrg return xid; 2010848b8605Smrg#endif 2011848b8605Smrg} 2012848b8605Smrg 2013b8e80941Smrg_GLX_PUBLIC GLXContext 2014848b8605SmrgglXCreateContextWithConfigSGIX(Display * dpy, 2015848b8605Smrg GLXFBConfigSGIX fbconfig, int renderType, 2016848b8605Smrg GLXContext shareList, Bool allowDirect) 2017848b8605Smrg{ 2018848b8605Smrg GLXContext gc = NULL; 2019848b8605Smrg struct glx_config *config = (struct glx_config *) fbconfig; 2020848b8605Smrg struct glx_screen *psc; 2021848b8605Smrg 2022848b8605Smrg 2023848b8605Smrg if ((dpy == NULL) || (config == NULL)) { 2024848b8605Smrg return None; 2025848b8605Smrg } 2026848b8605Smrg 2027848b8605Smrg psc = GetGLXScreenConfigs(dpy, config->screen); 2028848b8605Smrg if ((psc != NULL) 2029848b8605Smrg && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { 2030848b8605Smrg gc = CreateContext(dpy, config->fbconfigID, config, shareList, 2031848b8605Smrg allowDirect, 2032848b8605Smrg X_GLXvop_CreateContextWithConfigSGIX, renderType, 2033848b8605Smrg config->screen); 2034848b8605Smrg } 2035848b8605Smrg 2036848b8605Smrg return gc; 2037848b8605Smrg} 2038848b8605Smrg 2039848b8605Smrg 2040b8e80941Smrg_GLX_PUBLIC GLXFBConfigSGIX 2041848b8605SmrgglXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis) 2042848b8605Smrg{ 2043848b8605Smrg struct glx_display *priv; 2044848b8605Smrg struct glx_screen *psc = NULL; 2045848b8605Smrg 2046848b8605Smrg if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) == Success) 2047848b8605Smrg && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit) 2048848b8605Smrg && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) { 2049848b8605Smrg return (GLXFBConfigSGIX) glx_config_find_visual(psc->configs, 2050848b8605Smrg vis->visualid); 2051848b8605Smrg } 2052848b8605Smrg 2053848b8605Smrg return NULL; 2054848b8605Smrg} 2055848b8605Smrg 2056848b8605Smrg#ifndef GLX_USE_APPLEGL 2057848b8605Smrg/* 2058848b8605Smrg** GLX_OML_sync_control 2059848b8605Smrg*/ 2060848b8605Smrgstatic Bool 2061848b8605Smrg__glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, 2062848b8605Smrg int64_t * ust, int64_t * msc, int64_t * sbc) 2063848b8605Smrg{ 2064848b8605Smrg struct glx_display * const priv = __glXInitialize(dpy); 2065848b8605Smrg int ret; 2066848b8605Smrg#ifdef GLX_DIRECT_RENDERING 2067848b8605Smrg __GLXDRIdrawable *pdraw; 2068848b8605Smrg#endif 2069848b8605Smrg struct glx_screen *psc; 2070848b8605Smrg 2071848b8605Smrg if (!priv) 2072848b8605Smrg return False; 2073848b8605Smrg 2074848b8605Smrg#ifdef GLX_DIRECT_RENDERING 2075848b8605Smrg pdraw = GetGLXDRIDrawable(dpy, drawable); 2076848b8605Smrg psc = pdraw ? pdraw->psc : NULL; 2077848b8605Smrg if (pdraw && psc->driScreen->getDrawableMSC) { 2078848b8605Smrg ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc); 2079848b8605Smrg return ret; 2080848b8605Smrg } 2081848b8605Smrg#endif 2082848b8605Smrg 2083848b8605Smrg return False; 2084848b8605Smrg} 2085848b8605Smrg 2086848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2087848b8605Smrg_X_HIDDEN GLboolean 2088848b8605Smrg__glxGetMscRate(struct glx_screen *psc, 2089848b8605Smrg int32_t * numerator, int32_t * denominator) 2090848b8605Smrg{ 2091b8e80941Smrg#if !defined(GLX_USE_WINDOWSGL) 2092848b8605Smrg XF86VidModeModeLine mode_line; 2093848b8605Smrg int dot_clock; 2094848b8605Smrg int i; 2095848b8605Smrg 2096848b8605Smrg if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && 2097848b8605Smrg XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) { 2098848b8605Smrg unsigned n = dot_clock * 1000; 2099848b8605Smrg unsigned d = mode_line.vtotal * mode_line.htotal; 2100848b8605Smrg 2101848b8605Smrg# define V_INTERLACE 0x010 2102848b8605Smrg# define V_DBLSCAN 0x020 2103848b8605Smrg 2104848b8605Smrg if (mode_line.flags & V_INTERLACE) 2105848b8605Smrg n *= 2; 2106848b8605Smrg else if (mode_line.flags & V_DBLSCAN) 2107848b8605Smrg d *= 2; 2108848b8605Smrg 2109848b8605Smrg /* The OML_sync_control spec requires that if the refresh rate is a 2110848b8605Smrg * whole number, that the returned numerator be equal to the refresh 2111848b8605Smrg * rate and the denominator be 1. 2112848b8605Smrg */ 2113848b8605Smrg 2114848b8605Smrg if (n % d == 0) { 2115848b8605Smrg n /= d; 2116848b8605Smrg d = 1; 2117848b8605Smrg } 2118848b8605Smrg else { 2119848b8605Smrg static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 }; 2120848b8605Smrg 2121848b8605Smrg /* This is a poor man's way to reduce a fraction. It's far from 2122848b8605Smrg * perfect, but it will work well enough for this situation. 2123848b8605Smrg */ 2124848b8605Smrg 2125848b8605Smrg for (i = 0; f[i] != 0; i++) { 2126848b8605Smrg while (n % f[i] == 0 && d % f[i] == 0) { 2127848b8605Smrg d /= f[i]; 2128848b8605Smrg n /= f[i]; 2129848b8605Smrg } 2130848b8605Smrg } 2131848b8605Smrg } 2132848b8605Smrg 2133848b8605Smrg *numerator = n; 2134848b8605Smrg *denominator = d; 2135848b8605Smrg 2136848b8605Smrg return True; 2137848b8605Smrg } 2138848b8605Smrg#endif 2139848b8605Smrg 2140848b8605Smrg return False; 2141848b8605Smrg} 2142848b8605Smrg#endif 2143848b8605Smrg 2144848b8605Smrg/** 2145848b8605Smrg * Determine the refresh rate of the specified drawable and display. 2146848b8605Smrg * 2147848b8605Smrg * \param dpy Display whose refresh rate is to be determined. 2148848b8605Smrg * \param drawable Drawable whose refresh rate is to be determined. 2149848b8605Smrg * \param numerator Numerator of the refresh rate. 2150848b8605Smrg * \param demoninator Denominator of the refresh rate. 2151848b8605Smrg * \return If the refresh rate for the specified display and drawable could 2152848b8605Smrg * be calculated, True is returned. Otherwise False is returned. 2153848b8605Smrg * 2154848b8605Smrg * \note This function is implemented entirely client-side. A lot of other 2155848b8605Smrg * functionality is required to export GLX_OML_sync_control, so on 2156848b8605Smrg * XFree86 this function can be called for direct-rendering contexts 2157848b8605Smrg * when GLX_OML_sync_control appears in the client extension string. 2158848b8605Smrg */ 2159848b8605Smrg 2160848b8605Smrg_X_HIDDEN GLboolean 2161848b8605Smrg__glXGetMscRateOML(Display * dpy, GLXDrawable drawable, 2162848b8605Smrg int32_t * numerator, int32_t * denominator) 2163848b8605Smrg{ 2164b8e80941Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) && !defined(GLX_USE_WINDOWSGL) 2165848b8605Smrg __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable); 2166848b8605Smrg 2167848b8605Smrg if (draw == NULL) 2168848b8605Smrg return False; 2169848b8605Smrg 2170848b8605Smrg return __glxGetMscRate(draw->psc, numerator, denominator); 2171848b8605Smrg#else 2172848b8605Smrg (void) dpy; 2173848b8605Smrg (void) drawable; 2174848b8605Smrg (void) numerator; 2175848b8605Smrg (void) denominator; 2176848b8605Smrg#endif 2177848b8605Smrg return False; 2178848b8605Smrg} 2179848b8605Smrg 2180848b8605Smrg 2181848b8605Smrgstatic int64_t 2182848b8605Smrg__glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, 2183848b8605Smrg int64_t target_msc, int64_t divisor, int64_t remainder) 2184848b8605Smrg{ 2185848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 2186848b8605Smrg#ifdef GLX_DIRECT_RENDERING 2187848b8605Smrg __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 2188848b8605Smrg struct glx_screen *psc = pdraw ? pdraw->psc : NULL; 2189848b8605Smrg#endif 2190848b8605Smrg 2191b8e80941Smrg if (gc == &dummyContext) /* no GLX for this */ 2192848b8605Smrg return -1; 2193848b8605Smrg 2194848b8605Smrg#ifdef GLX_DIRECT_RENDERING 2195848b8605Smrg if (!pdraw || !gc->isDirect) 2196848b8605Smrg return -1; 2197848b8605Smrg#endif 2198848b8605Smrg 2199848b8605Smrg /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2200848b8605Smrg * error", but it also says "It [glXSwapBuffersMscOML] will return a value 2201848b8605Smrg * of -1 if the function failed because of errors detected in the input 2202848b8605Smrg * parameters" 2203848b8605Smrg */ 2204848b8605Smrg if (divisor < 0 || remainder < 0 || target_msc < 0) 2205848b8605Smrg return -1; 2206848b8605Smrg if (divisor > 0 && remainder >= divisor) 2207848b8605Smrg return -1; 2208848b8605Smrg 2209848b8605Smrg if (target_msc == 0 && divisor == 0 && remainder == 0) 2210848b8605Smrg remainder = 1; 2211848b8605Smrg 2212848b8605Smrg#ifdef GLX_DIRECT_RENDERING 2213848b8605Smrg if (psc->driScreen && psc->driScreen->swapBuffers) 2214848b8605Smrg return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor, 2215848b8605Smrg remainder, False); 2216848b8605Smrg#endif 2217848b8605Smrg 2218848b8605Smrg return -1; 2219848b8605Smrg} 2220848b8605Smrg 2221848b8605Smrg 2222848b8605Smrgstatic Bool 2223848b8605Smrg__glXWaitForMscOML(Display * dpy, GLXDrawable drawable, 2224848b8605Smrg int64_t target_msc, int64_t divisor, 2225848b8605Smrg int64_t remainder, int64_t * ust, 2226848b8605Smrg int64_t * msc, int64_t * sbc) 2227848b8605Smrg{ 2228848b8605Smrg#ifdef GLX_DIRECT_RENDERING 2229848b8605Smrg __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 2230848b8605Smrg struct glx_screen *psc = pdraw ? pdraw->psc : NULL; 2231848b8605Smrg int ret; 2232848b8605Smrg#endif 2233848b8605Smrg 2234848b8605Smrg 2235848b8605Smrg /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE 2236848b8605Smrg * error", but the return type in the spec is Bool. 2237848b8605Smrg */ 2238848b8605Smrg if (divisor < 0 || remainder < 0 || target_msc < 0) 2239848b8605Smrg return False; 2240848b8605Smrg if (divisor > 0 && remainder >= divisor) 2241848b8605Smrg return False; 2242848b8605Smrg 2243848b8605Smrg#ifdef GLX_DIRECT_RENDERING 2244848b8605Smrg if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { 2245848b8605Smrg ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder, 2246848b8605Smrg ust, msc, sbc); 2247848b8605Smrg return ret; 2248848b8605Smrg } 2249848b8605Smrg#endif 2250848b8605Smrg 2251848b8605Smrg return False; 2252848b8605Smrg} 2253848b8605Smrg 2254848b8605Smrg 2255848b8605Smrgstatic Bool 2256848b8605Smrg__glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, 2257848b8605Smrg int64_t target_sbc, int64_t * ust, 2258848b8605Smrg int64_t * msc, int64_t * sbc) 2259848b8605Smrg{ 2260848b8605Smrg#ifdef GLX_DIRECT_RENDERING 2261848b8605Smrg __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 2262848b8605Smrg struct glx_screen *psc = pdraw ? pdraw->psc : NULL; 2263848b8605Smrg int ret; 2264848b8605Smrg#endif 2265848b8605Smrg 2266848b8605Smrg /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE 2267848b8605Smrg * error", but the return type in the spec is Bool. 2268848b8605Smrg */ 2269848b8605Smrg if (target_sbc < 0) 2270848b8605Smrg return False; 2271848b8605Smrg 2272848b8605Smrg#ifdef GLX_DIRECT_RENDERING 2273848b8605Smrg if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) { 2274848b8605Smrg ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc); 2275848b8605Smrg return ret; 2276848b8605Smrg } 2277848b8605Smrg#endif 2278848b8605Smrg 2279848b8605Smrg return False; 2280848b8605Smrg} 2281848b8605Smrg 2282848b8605Smrg/*@}*/ 2283848b8605Smrg 2284848b8605Smrg 2285848b8605Smrg/** 2286848b8605Smrg * Mesa extension stubs. These will help reduce portability problems. 2287848b8605Smrg */ 2288848b8605Smrg/*@{*/ 2289848b8605Smrg 2290848b8605Smrg/** 2291848b8605Smrg * Release all buffers associated with the specified GLX drawable. 2292848b8605Smrg * 2293848b8605Smrg * \todo 2294848b8605Smrg * This function was intended for stand-alone Mesa. The issue there is that 2295848b8605Smrg * the library doesn't get any notification when a window is closed. In 2296848b8605Smrg * DRI there is a similar but slightly different issue. When GLX 1.3 is 2297848b8605Smrg * supported, there are 3 different functions to destroy a drawable. It 2298848b8605Smrg * should be possible to create GLX protocol (or have it determine which 2299848b8605Smrg * protocol to use based on the type of the drawable) to have one function 2300848b8605Smrg * do the work of 3. For the direct-rendering case, this function could 2301848b8605Smrg * just call the driver's \c __DRIdrawableRec::destroyDrawable function. 2302848b8605Smrg * This would reduce the frequency with which \c __driGarbageCollectDrawables 2303848b8605Smrg * would need to be used. This really should be done as part of the new DRI 2304848b8605Smrg * interface work. 2305848b8605Smrg * 2306848b8605Smrg * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt 2307848b8605Smrg * __driGarbageCollectDrawables 2308848b8605Smrg * glXDestroyGLXPixmap 2309848b8605Smrg * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow 2310848b8605Smrg * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX 2311848b8605Smrg */ 2312848b8605Smrgstatic Bool 2313848b8605Smrg__glXReleaseBuffersMESA(Display * dpy, GLXDrawable d) 2314848b8605Smrg{ 2315848b8605Smrg (void) dpy; 2316848b8605Smrg (void) d; 2317848b8605Smrg return False; 2318848b8605Smrg} 2319848b8605Smrg 2320848b8605Smrg 2321b8e80941Smrg_GLX_PUBLIC GLXPixmap 2322848b8605SmrgglXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual, 2323848b8605Smrg Pixmap pixmap, Colormap cmap) 2324848b8605Smrg{ 2325848b8605Smrg (void) dpy; 2326848b8605Smrg (void) visual; 2327848b8605Smrg (void) pixmap; 2328848b8605Smrg (void) cmap; 2329848b8605Smrg return 0; 2330848b8605Smrg} 2331848b8605Smrg 2332848b8605Smrg/*@}*/ 2333848b8605Smrg 2334848b8605Smrg 2335848b8605Smrg/** 2336848b8605Smrg * GLX_MESA_copy_sub_buffer 2337848b8605Smrg */ 2338848b8605Smrg#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ 2339848b8605Smrgstatic void 2340848b8605Smrg__glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable, 2341848b8605Smrg int x, int y, int width, int height) 2342848b8605Smrg{ 2343848b8605Smrg xGLXVendorPrivateReq *req; 2344848b8605Smrg struct glx_context *gc; 2345848b8605Smrg GLXContextTag tag; 2346848b8605Smrg CARD32 *drawable_ptr; 2347848b8605Smrg INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr; 2348848b8605Smrg CARD8 opcode; 2349848b8605Smrg 2350848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2351848b8605Smrg __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 2352848b8605Smrg if (pdraw != NULL) { 2353848b8605Smrg struct glx_screen *psc = pdraw->psc; 2354848b8605Smrg if (psc->driScreen->copySubBuffer != NULL) { 2355848b8605Smrg (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height, True); 2356848b8605Smrg } 2357848b8605Smrg 2358848b8605Smrg return; 2359848b8605Smrg } 2360848b8605Smrg#endif 2361848b8605Smrg 2362848b8605Smrg opcode = __glXSetupForCommand(dpy); 2363848b8605Smrg if (!opcode) 2364848b8605Smrg return; 2365848b8605Smrg 2366848b8605Smrg /* 2367848b8605Smrg ** The calling thread may or may not have a current context. If it 2368848b8605Smrg ** does, send the context tag so the server can do a flush. 2369848b8605Smrg */ 2370848b8605Smrg gc = __glXGetCurrentContext(); 2371b8e80941Smrg if ((gc != &dummyContext) && (dpy == gc->currentDpy) && 2372848b8605Smrg ((drawable == gc->currentDrawable) || 2373848b8605Smrg (drawable == gc->currentReadable))) { 2374848b8605Smrg tag = gc->currentContextTag; 2375848b8605Smrg } 2376848b8605Smrg else { 2377848b8605Smrg tag = 0; 2378848b8605Smrg } 2379848b8605Smrg 2380848b8605Smrg LockDisplay(dpy); 2381848b8605Smrg GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req); 2382848b8605Smrg req->reqType = opcode; 2383848b8605Smrg req->glxCode = X_GLXVendorPrivate; 2384848b8605Smrg req->vendorCode = X_GLXvop_CopySubBufferMESA; 2385848b8605Smrg req->contextTag = tag; 2386848b8605Smrg 2387848b8605Smrg drawable_ptr = (CARD32 *) (req + 1); 2388848b8605Smrg x_ptr = (INT32 *) (drawable_ptr + 1); 2389848b8605Smrg y_ptr = (INT32 *) (drawable_ptr + 2); 2390848b8605Smrg w_ptr = (INT32 *) (drawable_ptr + 3); 2391848b8605Smrg h_ptr = (INT32 *) (drawable_ptr + 4); 2392848b8605Smrg 2393848b8605Smrg *drawable_ptr = drawable; 2394848b8605Smrg *x_ptr = x; 2395848b8605Smrg *y_ptr = y; 2396848b8605Smrg *w_ptr = width; 2397848b8605Smrg *h_ptr = height; 2398848b8605Smrg 2399848b8605Smrg UnlockDisplay(dpy); 2400848b8605Smrg SyncHandle(); 2401848b8605Smrg} 2402848b8605Smrg 2403848b8605Smrg/*@{*/ 2404848b8605Smrgstatic void 2405848b8605Smrg__glXBindTexImageEXT(Display * dpy, 2406848b8605Smrg GLXDrawable drawable, int buffer, const int *attrib_list) 2407848b8605Smrg{ 2408848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 2409848b8605Smrg 2410b8e80941Smrg if (gc->vtable->bind_tex_image == NULL) 2411848b8605Smrg return; 2412848b8605Smrg 2413848b8605Smrg gc->vtable->bind_tex_image(dpy, drawable, buffer, attrib_list); 2414848b8605Smrg} 2415848b8605Smrg 2416848b8605Smrgstatic void 2417848b8605Smrg__glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer) 2418848b8605Smrg{ 2419848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 2420848b8605Smrg 2421b8e80941Smrg if (gc->vtable->release_tex_image == NULL) 2422848b8605Smrg return; 2423848b8605Smrg 2424848b8605Smrg gc->vtable->release_tex_image(dpy, drawable, buffer); 2425848b8605Smrg} 2426848b8605Smrg 2427848b8605Smrg/*@}*/ 2428848b8605Smrg 2429848b8605Smrg#endif /* GLX_USE_APPLEGL */ 2430848b8605Smrg 2431848b8605Smrg/* 2432848b8605Smrg** glXGetProcAddress support 2433848b8605Smrg*/ 2434848b8605Smrg 2435848b8605Smrgstruct name_address_pair 2436848b8605Smrg{ 2437848b8605Smrg const char *Name; 2438848b8605Smrg GLvoid *Address; 2439848b8605Smrg}; 2440848b8605Smrg 2441848b8605Smrg#define GLX_FUNCTION(f) { # f, (GLvoid *) f } 2442848b8605Smrg#define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f } 2443848b8605Smrg 2444848b8605Smrgstatic const struct name_address_pair GLX_functions[] = { 2445848b8605Smrg /*** GLX_VERSION_1_0 ***/ 2446848b8605Smrg GLX_FUNCTION(glXChooseVisual), 2447848b8605Smrg GLX_FUNCTION(glXCopyContext), 2448848b8605Smrg GLX_FUNCTION(glXCreateContext), 2449848b8605Smrg GLX_FUNCTION(glXCreateGLXPixmap), 2450848b8605Smrg GLX_FUNCTION(glXDestroyContext), 2451848b8605Smrg GLX_FUNCTION(glXDestroyGLXPixmap), 2452848b8605Smrg GLX_FUNCTION(glXGetConfig), 2453848b8605Smrg GLX_FUNCTION(glXGetCurrentContext), 2454848b8605Smrg GLX_FUNCTION(glXGetCurrentDrawable), 2455848b8605Smrg GLX_FUNCTION(glXIsDirect), 2456848b8605Smrg GLX_FUNCTION(glXMakeCurrent), 2457848b8605Smrg GLX_FUNCTION(glXQueryExtension), 2458848b8605Smrg GLX_FUNCTION(glXQueryVersion), 2459848b8605Smrg GLX_FUNCTION(glXSwapBuffers), 2460848b8605Smrg GLX_FUNCTION(glXUseXFont), 2461848b8605Smrg GLX_FUNCTION(glXWaitGL), 2462848b8605Smrg GLX_FUNCTION(glXWaitX), 2463848b8605Smrg 2464848b8605Smrg /*** GLX_VERSION_1_1 ***/ 2465848b8605Smrg GLX_FUNCTION(glXGetClientString), 2466848b8605Smrg GLX_FUNCTION(glXQueryExtensionsString), 2467848b8605Smrg GLX_FUNCTION(glXQueryServerString), 2468848b8605Smrg 2469848b8605Smrg /*** GLX_VERSION_1_2 ***/ 2470848b8605Smrg GLX_FUNCTION(glXGetCurrentDisplay), 2471848b8605Smrg 2472848b8605Smrg /*** GLX_VERSION_1_3 ***/ 2473848b8605Smrg GLX_FUNCTION(glXChooseFBConfig), 2474848b8605Smrg GLX_FUNCTION(glXCreateNewContext), 2475848b8605Smrg GLX_FUNCTION(glXCreatePbuffer), 2476848b8605Smrg GLX_FUNCTION(glXCreatePixmap), 2477848b8605Smrg GLX_FUNCTION(glXCreateWindow), 2478848b8605Smrg GLX_FUNCTION(glXDestroyPbuffer), 2479848b8605Smrg GLX_FUNCTION(glXDestroyPixmap), 2480848b8605Smrg GLX_FUNCTION(glXDestroyWindow), 2481848b8605Smrg GLX_FUNCTION(glXGetCurrentReadDrawable), 2482848b8605Smrg GLX_FUNCTION(glXGetFBConfigAttrib), 2483848b8605Smrg GLX_FUNCTION(glXGetFBConfigs), 2484848b8605Smrg GLX_FUNCTION(glXGetSelectedEvent), 2485848b8605Smrg GLX_FUNCTION(glXGetVisualFromFBConfig), 2486848b8605Smrg GLX_FUNCTION(glXMakeContextCurrent), 2487848b8605Smrg GLX_FUNCTION(glXQueryContext), 2488848b8605Smrg GLX_FUNCTION(glXQueryDrawable), 2489848b8605Smrg GLX_FUNCTION(glXSelectEvent), 2490848b8605Smrg 2491848b8605Smrg#ifndef GLX_USE_APPLEGL 2492848b8605Smrg /*** GLX_SGI_swap_control ***/ 2493848b8605Smrg GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI), 2494848b8605Smrg 2495848b8605Smrg /*** GLX_SGI_video_sync ***/ 2496848b8605Smrg GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI), 2497848b8605Smrg GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI), 2498848b8605Smrg 2499848b8605Smrg /*** GLX_SGI_make_current_read ***/ 2500848b8605Smrg GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent), 2501848b8605Smrg GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable), 2502848b8605Smrg 2503848b8605Smrg /*** GLX_EXT_import_context ***/ 2504848b8605Smrg GLX_FUNCTION(glXFreeContextEXT), 2505848b8605Smrg GLX_FUNCTION(glXGetContextIDEXT), 2506848b8605Smrg GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay), 2507848b8605Smrg GLX_FUNCTION(glXImportContextEXT), 2508848b8605Smrg GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext), 2509848b8605Smrg#endif 2510848b8605Smrg 2511848b8605Smrg /*** GLX_SGIX_fbconfig ***/ 2512848b8605Smrg GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib), 2513848b8605Smrg GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig), 2514848b8605Smrg GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX), 2515848b8605Smrg GLX_FUNCTION(glXCreateContextWithConfigSGIX), 2516848b8605Smrg GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig), 2517848b8605Smrg GLX_FUNCTION(glXGetFBConfigFromVisualSGIX), 2518848b8605Smrg 2519848b8605Smrg#ifndef GLX_USE_APPLEGL 2520848b8605Smrg /*** GLX_SGIX_pbuffer ***/ 2521848b8605Smrg GLX_FUNCTION(glXCreateGLXPbufferSGIX), 2522848b8605Smrg GLX_FUNCTION(glXDestroyGLXPbufferSGIX), 2523848b8605Smrg GLX_FUNCTION(glXQueryGLXPbufferSGIX), 2524848b8605Smrg GLX_FUNCTION(glXSelectEventSGIX), 2525848b8605Smrg GLX_FUNCTION(glXGetSelectedEventSGIX), 2526848b8605Smrg 2527848b8605Smrg /*** GLX_MESA_copy_sub_buffer ***/ 2528848b8605Smrg GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA), 2529848b8605Smrg 2530848b8605Smrg /*** GLX_MESA_pixmap_colormap ***/ 2531848b8605Smrg GLX_FUNCTION(glXCreateGLXPixmapMESA), 2532848b8605Smrg 2533848b8605Smrg /*** GLX_MESA_release_buffers ***/ 2534848b8605Smrg GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA), 2535848b8605Smrg 2536848b8605Smrg /*** GLX_MESA_swap_control ***/ 2537848b8605Smrg GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA), 2538848b8605Smrg GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA), 2539848b8605Smrg#endif 2540848b8605Smrg 2541848b8605Smrg /*** GLX_ARB_get_proc_address ***/ 2542848b8605Smrg GLX_FUNCTION(glXGetProcAddressARB), 2543848b8605Smrg 2544848b8605Smrg /*** GLX 1.4 ***/ 2545848b8605Smrg GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB), 2546848b8605Smrg 2547848b8605Smrg#ifndef GLX_USE_APPLEGL 2548848b8605Smrg /*** GLX_OML_sync_control ***/ 2549848b8605Smrg GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML), 2550848b8605Smrg GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML), 2551848b8605Smrg GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML), 2552848b8605Smrg GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML), 2553848b8605Smrg GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML), 2554848b8605Smrg 2555848b8605Smrg /*** GLX_EXT_texture_from_pixmap ***/ 2556848b8605Smrg GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT), 2557848b8605Smrg GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT), 2558848b8605Smrg#endif 2559848b8605Smrg 2560848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && defined(GLX_USE_DRM) 2561848b8605Smrg /*** DRI configuration ***/ 2562848b8605Smrg GLX_FUNCTION(glXGetScreenDriver), 2563848b8605Smrg GLX_FUNCTION(glXGetDriverConfig), 2564848b8605Smrg#endif 2565848b8605Smrg 2566848b8605Smrg /*** GLX_ARB_create_context and GLX_ARB_create_context_profile ***/ 2567848b8605Smrg GLX_FUNCTION(glXCreateContextAttribsARB), 2568848b8605Smrg 2569848b8605Smrg /*** GLX_MESA_query_renderer ***/ 2570848b8605Smrg GLX_FUNCTION(glXQueryRendererIntegerMESA), 2571848b8605Smrg GLX_FUNCTION(glXQueryRendererStringMESA), 2572848b8605Smrg GLX_FUNCTION(glXQueryCurrentRendererIntegerMESA), 2573848b8605Smrg GLX_FUNCTION(glXQueryCurrentRendererStringMESA), 2574848b8605Smrg 2575848b8605Smrg {NULL, NULL} /* end of list */ 2576848b8605Smrg}; 2577848b8605Smrg 2578848b8605Smrgstatic const GLvoid * 2579848b8605Smrgget_glx_proc_address(const char *funcName) 2580848b8605Smrg{ 2581848b8605Smrg GLuint i; 2582848b8605Smrg 2583848b8605Smrg /* try static functions */ 2584848b8605Smrg for (i = 0; GLX_functions[i].Name; i++) { 2585848b8605Smrg if (strcmp(GLX_functions[i].Name, funcName) == 0) 2586848b8605Smrg return GLX_functions[i].Address; 2587848b8605Smrg } 2588848b8605Smrg 2589848b8605Smrg return NULL; 2590848b8605Smrg} 2591848b8605Smrg 2592848b8605Smrg/** 2593848b8605Smrg * Get the address of a named GL function. This is the pre-GLX 1.4 name for 2594848b8605Smrg * \c glXGetProcAddress. 2595848b8605Smrg * 2596848b8605Smrg * \param procName Name of a GL or GLX function. 2597848b8605Smrg * \returns A pointer to the named function 2598848b8605Smrg * 2599848b8605Smrg * \sa glXGetProcAddress 2600848b8605Smrg */ 2601b8e80941Smrg_GLX_PUBLIC void (*glXGetProcAddressARB(const GLubyte * procName)) (void) 2602848b8605Smrg{ 2603848b8605Smrg typedef void (*gl_function) (void); 2604848b8605Smrg gl_function f; 2605848b8605Smrg 2606848b8605Smrg 2607848b8605Smrg /* Search the table of GLX and internal functions first. If that 2608848b8605Smrg * fails and the supplied name could be a valid core GL name, try 2609848b8605Smrg * searching the core GL function table. This check is done to prevent 2610848b8605Smrg * DRI based drivers from searching the core GL function table for 2611848b8605Smrg * internal API functions. 2612848b8605Smrg */ 2613848b8605Smrg f = (gl_function) get_glx_proc_address((const char *) procName); 2614848b8605Smrg if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l') 2615848b8605Smrg && (procName[2] != 'X')) { 2616b8e80941Smrg#ifdef GLX_INDIRECT_RENDERING 2617848b8605Smrg f = (gl_function) __indirect_get_proc_address((const char *) procName); 2618848b8605Smrg#endif 2619848b8605Smrg if (!f) 2620848b8605Smrg f = (gl_function) _glapi_get_proc_address((const char *) procName); 2621848b8605Smrg if (!f) { 2622848b8605Smrg struct glx_context *gc = __glXGetCurrentContext(); 2623848b8605Smrg 2624848b8605Smrg if (gc != NULL && gc->vtable->get_proc_address != NULL) 2625848b8605Smrg f = gc->vtable->get_proc_address((const char *) procName); 2626848b8605Smrg } 2627848b8605Smrg } 2628848b8605Smrg return f; 2629848b8605Smrg} 2630848b8605Smrg 2631848b8605Smrg/** 2632848b8605Smrg * Get the address of a named GL function. This is the GLX 1.4 name for 2633848b8605Smrg * \c glXGetProcAddressARB. 2634848b8605Smrg * 2635848b8605Smrg * \param procName Name of a GL or GLX function. 2636848b8605Smrg * \returns A pointer to the named function 2637848b8605Smrg * 2638848b8605Smrg * \sa glXGetProcAddressARB 2639848b8605Smrg */ 2640b8e80941Smrg_GLX_PUBLIC 2641b8e80941SmrgGLX_ALIAS(__GLXextFuncPtr, glXGetProcAddress, 2642b8e80941Smrg (const GLubyte * procName), 2643b8e80941Smrg (procName), glXGetProcAddressARB) 2644848b8605Smrg 2645848b8605Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2646848b8605Smrg/** 2647848b8605Smrg * Get the unadjusted system time (UST). Currently, the UST is measured in 2648848b8605Smrg * microseconds since Epoc. The actual resolution of the UST may vary from 2649848b8605Smrg * system to system, and the units may vary from release to release. 2650848b8605Smrg * Drivers should not call this function directly. They should instead use 2651848b8605Smrg * \c glXGetProcAddress to obtain a pointer to the function. 2652848b8605Smrg * 2653848b8605Smrg * \param ust Location to store the 64-bit UST 2654848b8605Smrg * \returns Zero on success or a negative errno value on failure. 2655848b8605Smrg * 2656848b8605Smrg * \sa glXGetProcAddress, PFNGLXGETUSTPROC 2657848b8605Smrg * 2658848b8605Smrg * \since Internal API version 20030317. 2659848b8605Smrg */ 2660848b8605Smrg_X_HIDDEN int 2661848b8605Smrg__glXGetUST(int64_t * ust) 2662848b8605Smrg{ 2663848b8605Smrg struct timeval tv; 2664848b8605Smrg 2665848b8605Smrg if (ust == NULL) { 2666848b8605Smrg return -EFAULT; 2667848b8605Smrg } 2668848b8605Smrg 2669848b8605Smrg if (gettimeofday(&tv, NULL) == 0) { 2670848b8605Smrg ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; 2671848b8605Smrg return 0; 2672848b8605Smrg } 2673848b8605Smrg else { 2674848b8605Smrg return -errno; 2675848b8605Smrg } 2676848b8605Smrg} 2677848b8605Smrg#endif /* GLX_DIRECT_RENDERING */ 2678b8e80941Smrg 2679b8e80941Smrg#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 2680b8e80941Smrg 2681b8e80941SmrgPUBLIC int 2682b8e80941SmrgMesaGLInteropGLXQueryDeviceInfo(Display *dpy, GLXContext context, 2683b8e80941Smrg struct mesa_glinterop_device_info *out) 2684b8e80941Smrg{ 2685b8e80941Smrg struct glx_context *gc = (struct glx_context*)context; 2686b8e80941Smrg int ret; 2687b8e80941Smrg 2688b8e80941Smrg __glXLock(); 2689b8e80941Smrg 2690b8e80941Smrg if (!gc || gc->xid == None || !gc->isDirect) { 2691b8e80941Smrg __glXUnlock(); 2692b8e80941Smrg return MESA_GLINTEROP_INVALID_CONTEXT; 2693b8e80941Smrg } 2694b8e80941Smrg 2695b8e80941Smrg if (!gc->vtable->interop_query_device_info) { 2696b8e80941Smrg __glXUnlock(); 2697b8e80941Smrg return MESA_GLINTEROP_UNSUPPORTED; 2698b8e80941Smrg } 2699b8e80941Smrg 2700b8e80941Smrg ret = gc->vtable->interop_query_device_info(gc, out); 2701b8e80941Smrg __glXUnlock(); 2702b8e80941Smrg return ret; 2703b8e80941Smrg} 2704b8e80941Smrg 2705b8e80941SmrgPUBLIC int 2706b8e80941SmrgMesaGLInteropGLXExportObject(Display *dpy, GLXContext context, 2707b8e80941Smrg struct mesa_glinterop_export_in *in, 2708b8e80941Smrg struct mesa_glinterop_export_out *out) 2709b8e80941Smrg{ 2710b8e80941Smrg struct glx_context *gc = (struct glx_context*)context; 2711b8e80941Smrg int ret; 2712b8e80941Smrg 2713b8e80941Smrg __glXLock(); 2714b8e80941Smrg 2715b8e80941Smrg if (!gc || gc->xid == None || !gc->isDirect) { 2716b8e80941Smrg __glXUnlock(); 2717b8e80941Smrg return MESA_GLINTEROP_INVALID_CONTEXT; 2718b8e80941Smrg } 2719b8e80941Smrg 2720b8e80941Smrg if (!gc->vtable->interop_export_object) { 2721b8e80941Smrg __glXUnlock(); 2722b8e80941Smrg return MESA_GLINTEROP_UNSUPPORTED; 2723b8e80941Smrg } 2724b8e80941Smrg 2725b8e80941Smrg ret = gc->vtable->interop_export_object(gc, in, out); 2726b8e80941Smrg __glXUnlock(); 2727b8e80941Smrg return ret; 2728b8e80941Smrg} 2729b8e80941Smrg 2730b8e80941Smrg#endif /* defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) */ 2731