📄 glxcmds.c
字号:
/* * 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 glxcmds.c * Client-side GLX interface. */#include "glxclient.h"#include "glapi.h"#include "glxextensions.h"#include "glcontextmodes.h"#include "glheader.h"#ifdef GLX_DIRECT_RENDERING#include <sys/time.h>#include <X11/extensions/xf86vmode.h>#include "xf86dri.h"#endifstatic const char __glXGLXClientVendorName[] = "SGI";static const char __glXGLXClientVersion[] = "1.4";/****************************************************************************/#ifdef GLX_DIRECT_RENDERINGstatic Bool windowExistsFlag;static int windowExistsErrorHandler(Display *dpy, XErrorEvent *xerr){ if (xerr->error_code == BadWindow) { windowExistsFlag = GL_FALSE; } return 0;}/** * Find drawables in the local hash that have been destroyed on the * server. * * \param dpy Display to destroy drawables for * \param screen Screen number to destroy drawables for */static void GarbageCollectDRIDrawables(Display *dpy, __GLXscreenConfigs *sc){ XID draw; __GLXDRIdrawable *pdraw; XWindowAttributes xwa; int (*oldXErrorHandler)(Display *, XErrorEvent *); /* Set no-op error handler so Xlib doesn't bail out if the windows * has alreay been destroyed on the server. */ XSync(dpy, GL_FALSE); oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler); if (__glxHashFirst(sc->drawHash, &draw, (void *)&pdraw) == 1) { do { windowExistsFlag = GL_TRUE; XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */ if (!windowExistsFlag) { /* Destroy the local drawable data, if the drawable no longer exists in the Xserver */ (*pdraw->destroyDrawable)(pdraw); __glxHashDelete(sc->drawHash, draw); } } while (__glxHashNext(sc->drawHash, &draw, (void *)&pdraw) == 1); } XSync(dpy, GL_FALSE); XSetErrorHandler(oldXErrorHandler);}extern __GLXDRIdrawable *GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num);/** * Get the __DRIdrawable for the drawable associated with a GLXContext * * \param dpy The display associated with \c drawable. * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved. * \param scrn_num If non-NULL, the drawables screen is stored there * \returns A pointer to the context's __DRIdrawable on success, or NULL if * the drawable is not associated with a direct-rendering context. */_X_HIDDEN __GLXDRIdrawable *GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int * const scrn_num){ __GLXdisplayPrivate *priv = __glXInitialize(dpy); __GLXDRIdrawable *pdraw; const unsigned screen_count = ScreenCount(dpy); unsigned i; __GLXscreenConfigs *psc; if (priv == NULL) return NULL; for (i = 0; i < screen_count; i++) { psc = &priv->screenConfigs[i]; if (psc->drawHash == NULL) continue; if (__glxHashLookup(psc->drawHash, drawable, (void *) &pdraw) == 0) { if (scrn_num != NULL) *scrn_num = i; return pdraw; } } return NULL;}#endif/** * Get the GLX per-screen data structure associated with a GLX context. * * \param dpy Display for which the GLX per-screen information is to be * retrieved. * \param scrn Screen on \c dpy for which the GLX per-screen information is * to be retrieved. * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn * specify a valid GLX screen, or NULL otherwise. * * \todo Should this function validate that \c scrn is within the screen * number range for \c dpy? */static __GLXscreenConfigs *GetGLXScreenConfigs(Display *dpy, int scrn){ __GLXdisplayPrivate * const priv = __glXInitialize(dpy); return (priv->screenConfigs != NULL) ? &priv->screenConfigs[scrn] : NULL;}static intGetGLXPrivScreenConfig( Display *dpy, int scrn, __GLXdisplayPrivate ** ppriv, __GLXscreenConfigs ** ppsc ){ /* Initialize the extension, if needed . This has the added value * of initializing/allocating the display private */ if ( dpy == NULL ) { return GLX_NO_EXTENSION; } *ppriv = __glXInitialize(dpy); if ( *ppriv == NULL ) { return GLX_NO_EXTENSION; } /* Check screen number to see if its valid */ if ((scrn < 0) || (scrn >= ScreenCount(dpy))) { return GLX_BAD_SCREEN; } /* Check to see if the GL is supported on this screen */ *ppsc = &((*ppriv)->screenConfigs[scrn]); if ( (*ppsc)->configs == NULL ) { /* No support for GL on this screen regardless of visual */ return GLX_BAD_VISUAL; } return Success;}/** * Determine if a \c GLXFBConfig supplied by the application is valid. * * \param dpy Application supplied \c Display pointer. * \param config Application supplied \c GLXFBConfig. * * \returns If the \c GLXFBConfig is valid, the a pointer to the matching * \c __GLcontextModes structure is returned. Otherwise, \c NULL * is returned. */static __GLcontextModes *ValidateGLXFBConfig( Display * dpy, GLXFBConfig config ){ __GLXdisplayPrivate * const priv = __glXInitialize(dpy); const unsigned num_screens = ScreenCount(dpy); unsigned i; const __GLcontextModes * modes; if ( priv != NULL ) { for ( i = 0 ; i < num_screens ; i++ ) { for ( modes = priv->screenConfigs[i].configs ; modes != NULL ; modes = modes->next ) { if ( modes == (__GLcontextModes *) config ) { return (__GLcontextModes *) config; } } } } return NULL;}/** * \todo It should be possible to move the allocate of \c client_state_private * later in the function for direct-rendering contexts. Direct-rendering * contexts don't need to track client state, so they don't need that memory * at all. * * \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new * function called \c __glXAllocateClientState that allocates the memory and * does all the initialization (including the pixel pack / unpack). */staticGLXContext AllocateGLXContext( Display *dpy ){ GLXContext gc; int bufSize; CARD8 opcode; __GLXattribute *state; if (!dpy) return NULL; opcode = __glXSetupForCommand(dpy); if (!opcode) { return NULL; } /* Allocate our context record */ gc = (GLXContext) Xmalloc(sizeof(struct __GLXcontextRec)); if (!gc) { /* Out of memory */ return NULL; } memset(gc, 0, sizeof(struct __GLXcontextRec)); state = Xmalloc(sizeof(struct __GLXattributeRec)); if (state == NULL) { /* Out of memory */ Xfree(gc); return NULL; } gc->client_state_private = state; memset(gc->client_state_private, 0, sizeof(struct __GLXattributeRec)); state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL); /* ** Create a temporary buffer to hold GLX rendering commands. The size ** of the buffer is selected so that the maximum number of GLX rendering ** commands can fit in a single X packet and still have room in the X ** packet for the GLXRenderReq header. */ bufSize = (XMaxRequestSize(dpy) * 4) - sz_xGLXRenderReq; gc->buf = (GLubyte *) Xmalloc(bufSize); if (!gc->buf) { Xfree(gc->client_state_private); Xfree(gc); return NULL; } gc->bufSize = bufSize; /* Fill in the new context */ gc->renderMode = GL_RENDER; state->storePack.alignment = 4; state->storeUnpack.alignment = 4; gc->attributes.stackPointer = &gc->attributes.stack[0]; /* ** PERFORMANCE NOTE: A mode dependent fill image can speed things up. ** Other code uses the fastImageUnpack bit, but it is never set ** to GL_TRUE. */ gc->fastImageUnpack = GL_FALSE; gc->fillImage = __glFillImage; gc->pc = gc->buf; gc->bufEnd = gc->buf + bufSize; gc->isDirect = GL_FALSE; if (__glXDebug) { /* ** Set limit register so that there will be one command per packet */ gc->limit = gc->buf; } else { gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE; } gc->createDpy = dpy; gc->majorOpcode = opcode; /* ** Constrain the maximum drawing command size allowed to be ** transfered using the X_GLXRender protocol request. First ** constrain by a software limit, then constrain by the protocl ** limit. */ if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) { bufSize = __GLX_RENDER_CMD_SIZE_LIMIT; } if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) { bufSize = __GLX_MAX_RENDER_CMD_SIZE; } gc->maxSmallRenderCommandSize = bufSize; return gc;}/** * Create a new context. Exactly one of \c vis and \c fbconfig should be * non-NULL. * * \param use_glx_1_3 For FBConfigs, should GLX 1.3 protocol or * SGIX_fbconfig protocol be used? * \param renderType For FBConfigs, what is the rendering type? */static GLXContextCreateContext(Display *dpy, XVisualInfo *vis, const __GLcontextModes * const fbconfig, GLXContext shareList, Bool allowDirect, GLXContextID contextID, Bool use_glx_1_3, int renderType){ GLXContext gc;#ifdef GLX_DIRECT_RENDERING int screen = (fbconfig == NULL) ? vis->screen : fbconfig->screen; __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);#endif if ( dpy == NULL ) return NULL; gc = AllocateGLXContext(dpy); if (!gc) return NULL; if (None == contextID) { if ( (vis == NULL) && (fbconfig == NULL) ) return NULL;#ifdef GLX_DIRECT_RENDERING if (allowDirect && psc->driScreen) { const __GLcontextModes * mode; if (fbconfig == NULL) { mode = _gl_context_modes_find_visual(psc->visuals, vis->visualid); if (mode == NULL) { xError error; error.errorCode = BadValue; error.resourceID = vis->visualid; error.sequenceNumber = dpy->request; error.type = X_Error; error.majorCode = gc->majorOpcode; error.minorCode = X_GLXCreateContext; _XError(dpy, &error); return None; } } else { mode = fbconfig; } gc->driContext = psc->driScreen->createContext(psc, mode, gc, shareList, renderType); if (gc->driContext != NULL) { gc->screen = mode->screen; gc->psc = psc; gc->mode = mode; gc->isDirect = GL_TRUE; } }#endif LockDisplay(dpy); if ( fbconfig == NULL ) { xGLXCreateContextReq *req; /* Send the glXCreateContext request */ GetReq(GLXCreateContext,req); req->reqType = gc->majorOpcode; req->glxCode = X_GLXCreateContext; req->context = gc->xid = XAllocID(dpy); req->visual = vis->visualid; req->screen = vis->screen; req->shareList = shareList ? shareList->xid : None;#ifdef GLX_DIRECT_RENDERING req->isDirect = gc->driContext != NULL;#else req->isDirect = 0;#endif } else if ( use_glx_1_3 ) { xGLXCreateNewContextReq *req; /* Send the glXCreateNewContext request */ GetReq(GLXCreateNewContext,req); req->reqType = gc->majorOpcode; req->glxCode = X_GLXCreateNewContext; req->context = gc->xid = XAllocID(dpy); req->fbconfig = fbconfig->fbconfigID; req->screen = fbconfig->screen; req->renderType = renderType; req->shareList = shareList ? shareList->xid : None;#ifdef GLX_DIRECT_RENDERING req->isDirect = gc->driContext != NULL;#else req->isDirect = 0;#endif } else { xGLXVendorPrivateWithReplyReq *vpreq; xGLXCreateContextWithConfigSGIXReq *req; /* Send the glXCreateNewContext request */ GetReqExtra(GLXVendorPrivateWithReply, sz_xGLXCreateContextWithConfigSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq); req = (xGLXCreateContextWithConfigSGIXReq *)vpreq; req->reqType = gc->majorOpcode; req->glxCode = X_GLXVendorPrivateWithReply; req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX; req->context = gc->xid = XAllocID(dpy); req->fbconfig = fbconfig->fbconfigID; req->screen = fbconfig->screen; req->renderType = renderType; req->shareList = shareList ? shareList->xid : None;#ifdef GLX_DIRECT_RENDERING req->isDirect = gc->driContext != NULL;#else req->isDirect = 0;#endif } UnlockDisplay(dpy); SyncHandle(); gc->imported = GL_FALSE; } else { gc->xid = contextID; gc->imported = GL_TRUE; } return gc;}PUBLIC GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool allowDirect){ return CreateContext(dpy, vis, NULL, shareList, allowDirect, None, False, 0);}_X_HIDDEN void __glXFreeContext(__GLXcontext *gc){ if (gc->vendor) XFree((char *) gc->vendor); if (gc->renderer) XFree((char *) gc->renderer); if (gc->version) XFree((char *) gc->version); if (gc->extensions) XFree((char *) gc->extensions); __glFreeAttributeState(gc); XFree((char *) gc->buf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -