📄 glxext.c
字号:
out: UnlockDisplay(dpy); return psc->visuals != NULL;}static GLbooleangetFBConfigs(Display *dpy, __GLXdisplayPrivate *priv, int screen){ xGLXGetFBConfigsReq *fb_req; xGLXGetFBConfigsSGIXReq *sgi_req; xGLXVendorPrivateWithReplyReq *vpreq; xGLXGetFBConfigsReply reply; __GLXscreenConfigs *psc; psc = priv->screenConfigs + screen; psc->serverGLXexts = __glXGetStringFromServer(dpy, priv->majorOpcode, X_GLXQueryServerString, 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 = __glXGetStringFromServer(dpy, priv->majorOpcode, X_GLXQueryServerString, 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 (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 INIT_MESA_SPARC /* 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->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 */ INIT_MESA_SPARC 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#ifdef USE_SPARC_ASM/* * This is where our dispatch table's bounds are. * And the static mesa_init is taken directly from * Mesa's 'sparc.c' initializer. * * We need something like this here, because this version * of openGL/glx never initializes a Mesa context, and so * the address of the dispatch table pointer never gets stuffed * into the dispatch jump table otherwise. * * It matters only on SPARC, and only if you are using assembler * code instead of C-code indirect dispatch. * * -- FEM, 04.xii.03 */extern unsigned int _mesa_sparc_glapi_begin;extern unsigned int _mesa_sparc_glapi_end;extern void __glapi_sparc_icache_flush(unsigned int *);static void_glx_mesa_init_sparc_glapi_relocs(void){ unsigned int *insn_ptr, *end_ptr; unsigned long disp_addr; insn_ptr = &_mesa_sparc_glapi_begin; end_ptr = &_mesa_sparc_glapi_end; disp_addr = (unsigned long) &_glapi_Dispatch; /* * Verbatim from Mesa sparc.c. It's needed because there doesn't * seem to be a better way to do this: * * UNCONDITIONAL_JUMP ( (*_glapi_Dispatch) + entry_offset ) * * This code is patching in the ADDRESS of the pointer to the * dispatch table. Hence, it must be called exactly once, because * that address is not going to change. * * What it points to can change, but Mesa (and hence, we) assume * that there is only one pointer. * */ while (insn_ptr < end_ptr) {#if ( defined(__sparc_v9__) && ( !defined(__linux__) || defined(__linux_64__) ) ) /* This code patches for 64-bit addresses. This had better not happen for Sparc/Linux, no matter what architecture we are building for. So, don't do this. The 'defined(__linux_64__)' is used here as a placeholder for when we do do 64-bit usermode on sparc linux. */ insn_ptr[0] |= (disp_addr >> (32 + 10)); insn_ptr[1] |= ((disp_addr & 0xffffffff) >> 10); __glapi_sparc_icache_flush(&insn_ptr[0]); insn_ptr[2] |= ((disp_addr >> 32) & ((1 << 10) - 1)); insn_ptr[3] |= (disp_addr & ((1 << 10) - 1)); __glapi_sparc_icache_flush(&insn_ptr[2]); insn_ptr += 11;#else insn_ptr[0] |= (disp_addr >> 10); insn_ptr[1] |= (disp_addr & ((1 << 10) - 1)); __glapi_sparc_icache_flush(&insn_ptr[0]); insn_ptr += 5;#endif }}#endif /* sparc ASM in use */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -