123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972 |
- /*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-
- /**
- * \file glxext.c
- * GLX protocol interface boot-strap code.
- *
- * Direct rendering support added by Precision Insight, Inc.
- *
- * \author Kevin E. Martin <kevin@precisioninsight.com>
- */
-
- #include <assert.h>
- #include "glxclient.h"
- #include <X11/extensions/Xext.h>
- #include <X11/extensions/extutil.h>
- #include "glapi.h"
- #include "glxextensions.h"
- #include "glcontextmodes.h"
-
- #ifdef USE_XCB
- #include <X11/Xlib-xcb.h>
- #include <xcb/xcb.h>
- #include <xcb/glx.h>
- #endif
-
-
- #ifdef DEBUG
- void __glXDumpDrawBuffer(__GLXcontext * ctx);
- #endif
-
- /*
- ** You can set this cell to 1 to force the gl drawing stuff to be
- ** one command per packet
- */
- _X_HIDDEN int __glXDebug = 0;
-
- /* Extension required boiler plate */
-
- static char *__glXExtensionName = GLX_EXTENSION_NAME;
- XExtensionInfo *__glXExtensionInfo = NULL;
-
- static /* const */ char *error_list[] = {
- "GLXBadContext",
- "GLXBadContextState",
- "GLXBadDrawable",
- "GLXBadPixmap",
- "GLXBadContextTag",
- "GLXBadCurrentWindow",
- "GLXBadRenderRequest",
- "GLXBadLargeRequest",
- "GLXUnsupportedPrivateRequest",
- "GLXBadFBConfig",
- "GLXBadPbuffer",
- "GLXBadCurrentDrawable",
- "GLXBadWindow",
- };
-
- static int
- __glXCloseDisplay(Display * dpy, XExtCodes * codes)
- {
- GLXContext gc;
-
- gc = __glXGetCurrentContext();
- if (dpy == gc->currentDpy) {
- __glXSetCurrentContextNull();
- __glXFreeContext(gc);
- }
-
- return XextRemoveDisplay(__glXExtensionInfo, dpy);
- }
-
-
- static
- XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
- __GLX_NUMBER_ERRORS, error_list)
-
- static /* const */ XExtensionHooks __glXExtensionHooks = {
- NULL, /* create_gc */
- NULL, /* copy_gc */
- NULL, /* flush_gc */
- NULL, /* free_gc */
- NULL, /* create_font */
- NULL, /* free_font */
- __glXCloseDisplay, /* close_display */
- NULL, /* wire_to_event */
- NULL, /* event_to_wire */
- NULL, /* error */
- __glXErrorString, /* error_string */
- };
-
- static
- XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
- __glXExtensionName, &__glXExtensionHooks,
- __GLX_NUMBER_EVENTS, NULL)
-
- /************************************************************************/
- /*
- ** Free the per screen configs data as well as the array of
- ** __glXScreenConfigs.
- */
- static void
- FreeScreenConfigs(__GLXdisplayPrivate * priv)
- {
- __GLXscreenConfigs *psc;
- GLint i, screens;
-
- /* Free screen configuration information */
- psc = priv->screenConfigs;
- screens = ScreenCount(priv->dpy);
- for (i = 0; i < screens; i++, psc++) {
- if (psc->configs) {
- _gl_context_modes_destroy(psc->configs);
- if (psc->effectiveGLXexts)
- Xfree(psc->effectiveGLXexts);
- psc->configs = NULL; /* NOTE: just for paranoia */
- }
- if (psc->visuals) {
- _gl_context_modes_destroy(psc->visuals);
- psc->visuals = NULL; /* NOTE: just for paranoia */
- }
- Xfree((char *) psc->serverGLXexts);
-
- #ifdef GLX_DIRECT_RENDERING
- if (psc->driver_configs) {
- for(unsigned int i = 0; psc->driver_configs[i]; i++)
- free((__DRIconfig*)psc->driver_configs[i]);
- free(psc->driver_configs);
- psc->driver_configs = NULL;
- }
- if (psc->driScreen) {
- psc->driScreen->destroyScreen(psc);
- __glxHashDestroy(psc->drawHash);
- XFree(psc->driScreen);
- psc->driScreen = NULL;
- }
- #endif
- }
- XFree((char *) priv->screenConfigs);
- priv->screenConfigs = NULL;
- }
-
- /*
- ** Release the private memory referred to in a display private
- ** structure. The caller will free the extension structure.
- */
- static int
- __glXFreeDisplayPrivate(XExtData * extension)
- {
- __GLXdisplayPrivate *priv;
-
- priv = (__GLXdisplayPrivate *) extension->private_data;
- FreeScreenConfigs(priv);
- if (priv->serverGLXvendor) {
- Xfree((char *) priv->serverGLXvendor);
- priv->serverGLXvendor = 0x0; /* to protect against double free's */
- }
- if (priv->serverGLXversion) {
- Xfree((char *) priv->serverGLXversion);
- priv->serverGLXversion = 0x0; /* to protect against double free's */
- }
-
- #ifdef GLX_DIRECT_RENDERING
- /* Free the direct rendering per display data */
- if (priv->driswDisplay)
- (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
- priv->driswDisplay = NULL;
-
- if (priv->driDisplay)
- (*priv->driDisplay->destroyDisplay) (priv->driDisplay);
- priv->driDisplay = NULL;
-
- if (priv->dri2Display)
- (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
- priv->dri2Display = NULL;
- #endif
-
- Xfree((char *) priv);
- return 0;
- }
-
- /************************************************************************/
-
- /*
- ** Query the version of the GLX extension. This procedure works even if
- ** the client extension is not completely set up.
- */
- static Bool
- QueryVersion(Display * dpy, int opcode, int *major, int *minor)
- {
- #ifdef USE_XCB
- xcb_connection_t *c = XGetXCBConnection(dpy);
- xcb_glx_query_version_reply_t* reply =
- xcb_glx_query_version_reply(c,
- xcb_glx_query_version(c,
- GLX_MAJOR_VERSION,
- GLX_MINOR_VERSION),
- NULL);
-
- if(reply->major_version != GLX_MAJOR_VERSION)
- {
- free(reply);
- return GL_FALSE;
- }
- *major = reply->major_version;
- *minor = min(reply->minor_version, GLX_MINOR_VERSION);
- free(reply);
- return GL_TRUE;
- #else
- xGLXQueryVersionReq *req;
- xGLXQueryVersionReply reply;
-
- /* Send the glXQueryVersion request */
- LockDisplay(dpy);
- GetReq(GLXQueryVersion, req);
- req->reqType = opcode;
- req->glxCode = X_GLXQueryVersion;
- req->majorVersion = GLX_MAJOR_VERSION;
- req->minorVersion = GLX_MINOR_VERSION;
- _XReply(dpy, (xReply *) & reply, 0, False);
- UnlockDisplay(dpy);
- SyncHandle();
-
- if (reply.majorVersion != GLX_MAJOR_VERSION) {
- /*
- ** The server does not support the same major release as this
- ** client.
- */
- return GL_FALSE;
- }
- *major = reply.majorVersion;
- *minor = min(reply.minorVersion, GLX_MINOR_VERSION);
- return GL_TRUE;
- #endif /* USE_XCB */
- }
-
-
- _X_HIDDEN void
- __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
- const INT32 * bp, Bool tagged_only,
- Bool fbconfig_style_tags)
- {
- int i;
-
- if (!tagged_only) {
- /* Copy in the first set of properties */
- config->visualID = *bp++;
-
- config->visualType = _gl_convert_from_x_visual_type(*bp++);
-
- config->rgbMode = *bp++;
-
- config->redBits = *bp++;
- config->greenBits = *bp++;
- config->blueBits = *bp++;
- config->alphaBits = *bp++;
- config->accumRedBits = *bp++;
- config->accumGreenBits = *bp++;
- config->accumBlueBits = *bp++;
- config->accumAlphaBits = *bp++;
-
- config->doubleBufferMode = *bp++;
- config->stereoMode = *bp++;
-
- config->rgbBits = *bp++;
- config->depthBits = *bp++;
- config->stencilBits = *bp++;
- config->numAuxBuffers = *bp++;
- config->level = *bp++;
-
- count -= __GLX_MIN_CONFIG_PROPS;
- }
-
- /*
- ** Additional properties may be in a list at the end
- ** of the reply. They are in pairs of property type
- ** and property value.
- */
-
- #define FETCH_OR_SET(tag) \
- config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
-
- for (i = 0; i < count; i += 2) {
- switch (*bp++) {
- case GLX_RGBA:
- FETCH_OR_SET(rgbMode);
- break;
- case GLX_BUFFER_SIZE:
- config->rgbBits = *bp++;
- break;
- case GLX_LEVEL:
- config->level = *bp++;
- break;
- case GLX_DOUBLEBUFFER:
- FETCH_OR_SET(doubleBufferMode);
- break;
- case GLX_STEREO:
- FETCH_OR_SET(stereoMode);
- break;
- case GLX_AUX_BUFFERS:
- config->numAuxBuffers = *bp++;
- break;
- case GLX_RED_SIZE:
- config->redBits = *bp++;
- break;
- case GLX_GREEN_SIZE:
- config->greenBits = *bp++;
- break;
- case GLX_BLUE_SIZE:
- config->blueBits = *bp++;
- break;
- case GLX_ALPHA_SIZE:
- config->alphaBits = *bp++;
- break;
- case GLX_DEPTH_SIZE:
- config->depthBits = *bp++;
- break;
- case GLX_STENCIL_SIZE:
- config->stencilBits = *bp++;
- break;
- case GLX_ACCUM_RED_SIZE:
- config->accumRedBits = *bp++;
- break;
- case GLX_ACCUM_GREEN_SIZE:
- config->accumGreenBits = *bp++;
- break;
- case GLX_ACCUM_BLUE_SIZE:
- config->accumBlueBits = *bp++;
- break;
- case GLX_ACCUM_ALPHA_SIZE:
- config->accumAlphaBits = *bp++;
- break;
- case GLX_VISUAL_CAVEAT_EXT:
- config->visualRating = *bp++;
- break;
- case GLX_X_VISUAL_TYPE:
- config->visualType = *bp++;
- break;
- case GLX_TRANSPARENT_TYPE:
- config->transparentPixel = *bp++;
- break;
- case GLX_TRANSPARENT_INDEX_VALUE:
- config->transparentIndex = *bp++;
- break;
- case GLX_TRANSPARENT_RED_VALUE:
- config->transparentRed = *bp++;
- break;
- case GLX_TRANSPARENT_GREEN_VALUE:
- config->transparentGreen = *bp++;
- break;
- case GLX_TRANSPARENT_BLUE_VALUE:
- config->transparentBlue = *bp++;
- break;
- case GLX_TRANSPARENT_ALPHA_VALUE:
- config->transparentAlpha = *bp++;
- break;
- case GLX_VISUAL_ID:
- config->visualID = *bp++;
- break;
- case GLX_DRAWABLE_TYPE:
- config->drawableType = *bp++;
- break;
- case GLX_RENDER_TYPE:
- config->renderType = *bp++;
- break;
- case GLX_X_RENDERABLE:
- config->xRenderable = *bp++;
- break;
- case GLX_FBCONFIG_ID:
- config->fbconfigID = *bp++;
- break;
- case GLX_MAX_PBUFFER_WIDTH:
- config->maxPbufferWidth = *bp++;
- break;
- case GLX_MAX_PBUFFER_HEIGHT:
- config->maxPbufferHeight = *bp++;
- break;
- case GLX_MAX_PBUFFER_PIXELS:
- config->maxPbufferPixels = *bp++;
- break;
- case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
- config->optimalPbufferWidth = *bp++;
- break;
- case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
- config->optimalPbufferHeight = *bp++;
- break;
- case GLX_VISUAL_SELECT_GROUP_SGIX:
- config->visualSelectGroup = *bp++;
- break;
- case GLX_SWAP_METHOD_OML:
- config->swapMethod = *bp++;
- break;
- case GLX_SAMPLE_BUFFERS_SGIS:
- config->sampleBuffers = *bp++;
- break;
- case GLX_SAMPLES_SGIS:
- config->samples = *bp++;
- break;
- case GLX_BIND_TO_TEXTURE_RGB_EXT:
- config->bindToTextureRgb = *bp++;
- break;
- case GLX_BIND_TO_TEXTURE_RGBA_EXT:
- config->bindToTextureRgba = *bp++;
- break;
- case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
- config->bindToMipmapTexture = *bp++;
- break;
- case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
- config->bindToTextureTargets = *bp++;
- break;
- case GLX_Y_INVERTED_EXT:
- config->yInverted = *bp++;
- break;
- case None:
- i = count;
- break;
- default:
- break;
- }
- }
-
- config->renderType =
- (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
-
- config->haveAccumBuffer = ((config->accumRedBits +
- config->accumGreenBits +
- config->accumBlueBits +
- config->accumAlphaBits) > 0);
- config->haveDepthBuffer = (config->depthBits > 0);
- config->haveStencilBuffer = (config->stencilBits > 0);
- }
-
- static __GLcontextModes *
- createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
- int screen, GLboolean tagged_only)
- {
- INT32 buf[__GLX_TOTAL_CONFIG], *props;
- unsigned prop_size;
- __GLcontextModes *modes, *m;
- int i;
-
- if (nprops == 0)
- return NULL;
-
- /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
-
- /* Check number of properties */
- if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
- return NULL;
-
- /* Allocate memory for our config structure */
- modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes));
- if (!modes)
- return NULL;
-
- prop_size = nprops * __GLX_SIZE_INT32;
- if (prop_size <= sizeof(buf))
- props = buf;
- else
- props = Xmalloc(prop_size);
-
- /* Read each config structure and convert it into our format */
- m = modes;
- for (i = 0; i < nvisuals; i++) {
- _XRead(dpy, (char *) props, prop_size);
- /* Older X servers don't send this so we default it here. */
- m->drawableType = GLX_WINDOW_BIT;
- __glXInitializeVisualConfigFromTags(m, nprops, props,
- tagged_only, GL_TRUE);
- m->screen = screen;
- m = m->next;
- }
-
- if (props != buf)
- Xfree(props);
-
- return modes;
- }
-
- static GLboolean
- getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
- {
- xGLXGetVisualConfigsReq *req;
- __GLXscreenConfigs *psc;
- xGLXGetVisualConfigsReply reply;
-
- LockDisplay(dpy);
-
- psc = priv->screenConfigs + screen;
- psc->visuals = NULL;
- GetReq(GLXGetVisualConfigs, req);
- req->reqType = priv->majorOpcode;
- req->glxCode = X_GLXGetVisualConfigs;
- req->screen = screen;
-
- if (!_XReply(dpy, (xReply *) & reply, 0, False))
- goto out;
-
- psc->visuals = createConfigsFromProperties(dpy,
- reply.numVisuals,
- reply.numProps,
- screen, GL_FALSE);
-
- out:
- UnlockDisplay(dpy);
- return psc->visuals != NULL;
- }
-
- static GLboolean
- getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
- {
- xGLXGetFBConfigsReq *fb_req;
- xGLXGetFBConfigsSGIXReq *sgi_req;
- xGLXVendorPrivateWithReplyReq *vpreq;
- xGLXGetFBConfigsReply reply;
- __GLXscreenConfigs *psc;
-
- psc = priv->screenConfigs + screen;
- psc->serverGLXexts = __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
-
- LockDisplay(dpy);
-
- psc->configs = NULL;
- if (atof(priv->serverGLXversion) >= 1.3) {
- GetReq(GLXGetFBConfigs, fb_req);
- fb_req->reqType = priv->majorOpcode;
- fb_req->glxCode = X_GLXGetFBConfigs;
- fb_req->screen = screen;
- }
- else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
- GetReqExtra(GLXVendorPrivateWithReply,
- sz_xGLXGetFBConfigsSGIXReq +
- sz_xGLXVendorPrivateWithReplyReq, vpreq);
- sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
- sgi_req->reqType = priv->majorOpcode;
- sgi_req->glxCode = X_GLXVendorPrivateWithReply;
- sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
- sgi_req->screen = screen;
- }
- else
- goto out;
-
- if (!_XReply(dpy, (xReply *) & reply, 0, False))
- goto out;
-
- psc->configs = createConfigsFromProperties(dpy,
- reply.numFBConfigs,
- reply.numAttribs * 2,
- screen, GL_TRUE);
-
- out:
- UnlockDisplay(dpy);
- return psc->configs != NULL;
- }
-
- /*
- ** Allocate the memory for the per screen configs for each screen.
- ** If that works then fetch the per screen configs data.
- */
- static Bool
- AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
- {
- __GLXscreenConfigs *psc;
- GLint i, screens;
-
- /*
- ** First allocate memory for the array of per screen configs.
- */
- screens = ScreenCount(dpy);
- psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
- if (!psc) {
- return GL_FALSE;
- }
- memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
- priv->screenConfigs = psc;
-
- priv->serverGLXversion = __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
- if (priv->serverGLXversion == NULL) {
- FreeScreenConfigs(priv);
- return GL_FALSE;
- }
-
- for (i = 0; i < screens; i++, psc++) {
- getVisualConfigs(dpy, priv, i);
- getFBConfigs(dpy, priv, i);
-
- #ifdef GLX_DIRECT_RENDERING
- psc->scr = i;
- psc->dpy = dpy;
- psc->drawHash = __glxHashCreate();
- if (psc->drawHash == NULL)
- continue;
-
- if (priv->dri2Display)
- psc->driScreen = (*priv->dri2Display->createScreen) (psc, i, priv);
-
- if (psc->driScreen == NULL && priv->driDisplay)
- psc->driScreen = (*priv->driDisplay->createScreen) (psc, i, priv);
-
- if (psc->driScreen == NULL && priv->driswDisplay)
- psc->driScreen = (*priv->driswDisplay->createScreen) (psc, i, priv);
-
- if (psc->driScreen == NULL) {
- __glxHashDestroy(psc->drawHash);
- psc->drawHash = NULL;
- }
- #endif
- }
- SyncHandle();
- return GL_TRUE;
- }
-
- /*
- ** Initialize the client side extension code.
- */
- _X_HIDDEN __GLXdisplayPrivate *
- __glXInitialize(Display * dpy)
- {
- XExtDisplayInfo *info = __glXFindDisplay(dpy);
- XExtData **privList, *private, *found;
- __GLXdisplayPrivate *dpyPriv;
- XEDataObject dataObj;
- int major, minor;
- #ifdef GLX_DIRECT_RENDERING
- Bool glx_direct, glx_accel;
- #endif
-
- #if defined(USE_XTHREADS)
- {
- static int firstCall = 1;
- if (firstCall) {
- /* initialize the GLX mutexes */
- xmutex_init(&__glXmutex);
- firstCall = 0;
- }
- }
- #endif
-
- /* The one and only long long lock */
- __glXLock();
-
- if (!XextHasExtension(info)) {
- /* No GLX extension supported by this server. Oh well. */
- __glXUnlock();
- XMissingExtension(dpy, __glXExtensionName);
- return 0;
- }
-
- /* See if a display private already exists. If so, return it */
- dataObj.display = dpy;
- privList = XEHeadOfExtensionList(dataObj);
- found = XFindOnExtensionList(privList, info->codes->extension);
- if (found) {
- __glXUnlock();
- return (__GLXdisplayPrivate *) found->private_data;
- }
-
- /* See if the versions are compatible */
- if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) {
- /* The client and server do not agree on versions. Punt. */
- __glXUnlock();
- return 0;
- }
-
- /*
- ** Allocate memory for all the pieces needed for this buffer.
- */
- private = (XExtData *) Xmalloc(sizeof(XExtData));
- if (!private) {
- __glXUnlock();
- return 0;
- }
- dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate));
- if (!dpyPriv) {
- __glXUnlock();
- Xfree((char *) private);
- return 0;
- }
-
- /*
- ** Init the display private and then read in the screen config
- ** structures from the server.
- */
- dpyPriv->majorOpcode = info->codes->major_opcode;
- dpyPriv->majorVersion = major;
- dpyPriv->minorVersion = minor;
- dpyPriv->dpy = dpy;
-
- dpyPriv->serverGLXvendor = 0x0;
- dpyPriv->serverGLXversion = 0x0;
-
- #ifdef GLX_DIRECT_RENDERING
- glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL);
- glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
-
- /*
- ** Initialize the direct rendering per display data and functions.
- ** Note: This _must_ be done before calling any other DRI routines
- ** (e.g., those called in AllocAndFetchScreenConfigs).
- */
- if (glx_direct && glx_accel) {
- dpyPriv->dri2Display = dri2CreateDisplay(dpy);
- dpyPriv->driDisplay = driCreateDisplay(dpy);
- }
- if (glx_direct)
- dpyPriv->driswDisplay = driswCreateDisplay(dpy);
- #endif
-
- if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
- __glXUnlock();
- Xfree((char *) dpyPriv);
- Xfree((char *) private);
- return 0;
- }
-
- /*
- ** Fill in the private structure. This is the actual structure that
- ** hangs off of the Display structure. Our private structure is
- ** referred to by this structure. Got that?
- */
- private->number = info->codes->extension;
- private->next = 0;
- private->free_private = __glXFreeDisplayPrivate;
- private->private_data = (char *) dpyPriv;
- XAddToExtensionList(privList, private);
-
- if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) {
- __glXClientInfo(dpy, dpyPriv->majorOpcode);
- }
- __glXUnlock();
-
- return dpyPriv;
- }
-
- /*
- ** Setup for sending a GLX command on dpy. Make sure the extension is
- ** initialized. Try to avoid calling __glXInitialize as its kinda slow.
- */
- _X_HIDDEN CARD8
- __glXSetupForCommand(Display * dpy)
- {
- GLXContext gc;
- __GLXdisplayPrivate *priv;
-
- /* If this thread has a current context, flush its rendering commands */
- gc = __glXGetCurrentContext();
- if (gc->currentDpy) {
- /* Flush rendering buffer of the current context, if any */
- (void) __glXFlushRenderBuffer(gc, gc->pc);
-
- if (gc->currentDpy == dpy) {
- /* Use opcode from gc because its right */
- return gc->majorOpcode;
- }
- else {
- /*
- ** Have to get info about argument dpy because it might be to
- ** a different server
- */
- }
- }
-
- /* Forced to lookup extension via the slow initialize route */
- priv = __glXInitialize(dpy);
- if (!priv) {
- return 0;
- }
- return priv->majorOpcode;
- }
-
- /**
- * Flush the drawing command transport buffer.
- *
- * \param ctx Context whose transport buffer is to be flushed.
- * \param pc Pointer to first unused buffer location.
- *
- * \todo
- * Modify this function to use \c ctx->pc instead of the explicit
- * \c pc parameter.
- */
- _X_HIDDEN GLubyte *
- __glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc)
- {
- Display *const dpy = ctx->currentDpy;
- #ifdef USE_XCB
- xcb_connection_t *c = XGetXCBConnection(dpy);
- #else
- xGLXRenderReq *req;
- #endif /* USE_XCB */
- const GLint size = pc - ctx->buf;
-
- if ((dpy != NULL) && (size > 0)) {
- #ifdef USE_XCB
- xcb_glx_render(c, ctx->currentContextTag, size,
- (const uint8_t *) ctx->buf);
- #else
- /* Send the entire buffer as an X request */
- LockDisplay(dpy);
- GetReq(GLXRender, req);
- req->reqType = ctx->majorOpcode;
- req->glxCode = X_GLXRender;
- req->contextTag = ctx->currentContextTag;
- req->length += (size + 3) >> 2;
- _XSend(dpy, (char *) ctx->buf, size);
- UnlockDisplay(dpy);
- SyncHandle();
- #endif
- }
-
- /* Reset pointer and return it */
- ctx->pc = ctx->buf;
- return ctx->pc;
- }
-
-
- /**
- * Send a portion of a GLXRenderLarge command to the server. The advantage of
- * this function over \c __glXSendLargeCommand is that callers can use the
- * data buffer in the GLX context and may be able to avoid allocating an
- * extra buffer. The disadvantage is the clients will have to do more
- * GLX protocol work (i.e., calculating \c totalRequests, etc.).
- *
- * \sa __glXSendLargeCommand
- *
- * \param gc GLX context
- * \param requestNumber Which part of the whole command is this? The first
- * request is 1.
- * \param totalRequests How many requests will there be?
- * \param data Command data.
- * \param dataLen Size, in bytes, of the command data.
- */
- _X_HIDDEN void
- __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber,
- GLint totalRequests, const GLvoid * data, GLint dataLen)
- {
- Display *dpy = gc->currentDpy;
- #ifdef USE_XCB
- xcb_connection_t *c = XGetXCBConnection(dpy);
- xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
- totalRequests, dataLen, data);
- #else
- xGLXRenderLargeReq *req;
-
- if (requestNumber == 1) {
- LockDisplay(dpy);
- }
-
- GetReq(GLXRenderLarge, req);
- req->reqType = gc->majorOpcode;
- req->glxCode = X_GLXRenderLarge;
- req->contextTag = gc->currentContextTag;
- req->length += (dataLen + 3) >> 2;
- req->requestNumber = requestNumber;
- req->requestTotal = totalRequests;
- req->dataBytes = dataLen;
- Data(dpy, data, dataLen);
-
- if (requestNumber == totalRequests) {
- UnlockDisplay(dpy);
- SyncHandle();
- }
- #endif /* USE_XCB */
- }
-
-
- /**
- * Send a command that is too large for the GLXRender protocol request.
- *
- * Send a large command, one that is too large for some reason to
- * send using the GLXRender protocol request. One reason to send
- * a large command is to avoid copying the data.
- *
- * \param ctx GLX context
- * \param header Header data.
- * \param headerLen Size, in bytes, of the header data. It is assumed that
- * the header data will always be small enough to fit in
- * a single X protocol packet.
- * \param data Command data.
- * \param dataLen Size, in bytes, of the command data.
- */
- _X_HIDDEN void
- __glXSendLargeCommand(__GLXcontext * ctx,
- const GLvoid * header, GLint headerLen,
- const GLvoid * data, GLint dataLen)
- {
- GLint maxSize;
- GLint totalRequests, requestNumber;
-
- /*
- ** Calculate the maximum amount of data can be stuffed into a single
- ** packet. sz_xGLXRenderReq is added because bufSize is the maximum
- ** packet size minus sz_xGLXRenderReq.
- */
- maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
- totalRequests = 1 + (dataLen / maxSize);
- if (dataLen % maxSize)
- totalRequests++;
-
- /*
- ** Send all of the command, except the large array, as one request.
- */
- assert(headerLen <= maxSize);
- __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
-
- /*
- ** Send enough requests until the whole array is sent.
- */
- for (requestNumber = 2; requestNumber <= (totalRequests - 1);
- requestNumber++) {
- __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
- data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
- dataLen -= maxSize;
- assert(dataLen > 0);
- }
-
- assert(dataLen <= maxSize);
- __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
- }
-
- /************************************************************************/
-
- #ifdef DEBUG
- _X_HIDDEN void
- __glXDumpDrawBuffer(__GLXcontext * ctx)
- {
- GLubyte *p = ctx->buf;
- GLubyte *end = ctx->pc;
- GLushort opcode, length;
-
- while (p < end) {
- /* Fetch opcode */
- opcode = *((GLushort *) p);
- length = *((GLushort *) (p + 2));
- printf("%2x: %5d: ", opcode, length);
- length -= 4;
- p += 4;
- while (length > 0) {
- printf("%08x ", *((unsigned *) p));
- p += 4;
- length -= 4;
- }
- printf("\n");
- }
- }
- #endif
|