X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglx%2Fglxext.c;h=4a195bd40ba272da5125d22a037e52826b434e37;hb=bb0d6db974ea920491aca2eb011064fd3c2fb676;hp=8e8b362d10dc67b6b4361050b63466ddbf858b2c;hpb=6ddf66e9230ee862ac341c4767cf6b3b2dd2552b;p=mesa.git diff --git a/src/glx/glxext.c b/src/glx/glxext.c index 8e8b362d10d..4a195bd40ba 100644 --- a/src/glx/glxext.c +++ b/src/glx/glxext.c @@ -41,23 +41,19 @@ #include "glxclient.h" #include #include -#include #ifdef GLX_USE_APPLEGL #include "apple_glx.h" #include "apple_visual.h" #endif #include "glxextensions.h" -#include "glcontextmodes.h" -#ifdef USE_XCB #include #include #include -#endif #ifdef DEBUG -void __glXDumpDrawBuffer(__GLXcontext * ctx); +void __glXDumpDrawBuffer(struct glx_context * ctx); #endif /* @@ -69,7 +65,7 @@ _X_HIDDEN int __glXDebug = 0; /* Extension required boiler plate */ static const char __glXExtensionName[] = GLX_EXTENSION_NAME; -static __GLXdisplayPrivate *glx_displays; + static struct glx_display *glx_displays; static /* const */ char *error_list[] = { "GLXBadContext", @@ -85,6 +81,7 @@ static /* const */ char *error_list[] = { "GLXBadPbuffer", "GLXBadCurrentDrawable", "GLXBadWindow", + "GLXBadProfileARB", }; #ifdef GLX_USE_APPLEGL @@ -108,7 +105,7 @@ XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName, static Bool __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) { - __GLXdisplayPrivate *glx_dpy = __glXInitialize(dpy); + struct glx_display *glx_dpy = __glXInitialize(dpy); if (glx_dpy == NULL) return False; @@ -132,28 +129,25 @@ __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) aevent->count = awire->count; return True; } - /* No easy symbol to test for this, as GLX_BufferSwapComplete is - * defined in the local glx.h header, but the - * xGLXBufferSwapComplete typedef is only available in new versions - * of the external glxproto.h header, which doesn't have any - * testable versioning define. - * - * I'll use the related DRI2 define, in the hope that we won't - * receive these events unless we know how to ask for them: - */ -#ifdef X_DRI2SwapBuffers case GLX_BufferSwapComplete: { GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; - xGLXBufferSwapComplete *awire = (xGLXBufferSwapComplete *)wire; + xGLXBufferSwapComplete2 *awire = (xGLXBufferSwapComplete2 *)wire; + struct glx_drawable *glxDraw = GetGLXDrawable(dpy, awire->drawable); aevent->event_type = awire->event_type; aevent->drawable = awire->drawable; aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; - aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo; + + if (!glxDraw) + return False; + + if (awire->sbc < glxDraw->lastEventSbc) + glxDraw->eventSbcWrap += 0x100000000; + glxDraw->lastEventSbc = awire->sbc; + aevent->sbc = awire->sbc + glxDraw->eventSbcWrap; return True; } -#endif default: /* client doesn't support server event */ break; @@ -168,7 +162,7 @@ __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) static Status __glXEventToWire(Display *dpy, XEvent *event, xEvent *wire) { - __GLXdisplayPrivate *glx_dpy = __glXInitialize(dpy); + struct glx_display *glx_dpy = __glXInitialize(dpy); if (glx_dpy == NULL) return False; @@ -198,76 +192,51 @@ __glXEventToWire(Display *dpy, XEvent *event, xEvent *wire) ** __glXScreenConfigs. */ static void -FreeScreenConfigs(__GLXdisplayPrivate * priv) +FreeScreenConfigs(struct glx_display * priv) { - __GLXscreenConfigs *psc; + struct glx_screen *psc; GLint i, screens; /* Free screen configuration information */ screens = ScreenCount(priv->dpy); for (i = 0; i < screens; i++) { - psc = priv->screenConfigs[i]; - if (psc->configs) { - glx_config_destroy_list(psc->configs); - if (psc->effectiveGLXexts) - Xfree(psc->effectiveGLXexts); - psc->configs = NULL; /* NOTE: just for paranoia */ - } - if (psc->visuals) { - glx_config_destroy_list(psc->visuals); - psc->visuals = NULL; /* NOTE: just for paranoia */ - } - Xfree((char *) psc->serverGLXexts); + psc = priv->screens[i]; + glx_screen_cleanup(psc); #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) if (psc->driScreen) { psc->driScreen->destroyScreen(psc); } else { - Xfree(psc); + free(psc); } #else - Xfree(psc); + free(psc); #endif } - XFree((char *) priv->screenConfigs); - priv->screenConfigs = NULL; + free((char *) priv->screens); + priv->screens = NULL; } -/* -** Release the private memory referred to in a display private -** structure. The caller will free the extension structure. -*/ -static int -__glXCloseDisplay(Display * dpy, XExtCodes * codes) +static void +glx_display_free(struct glx_display *priv) { - __GLXdisplayPrivate *priv, **prev; - GLXContext gc; - - _XLockMutex(_Xglobal_lock); - prev = &glx_displays; - for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) { - if (priv->dpy == dpy) { - (*prev)->next = priv->next; - break; - } - } - _XUnlockMutex(_Xglobal_lock); + struct glx_context *gc; gc = __glXGetCurrentContext(); - if (dpy == gc->currentDpy) { + if (priv->dpy == gc->currentDpy) { gc->vtable->destroy(gc); __glXSetCurrentContextNull(); } FreeScreenConfigs(priv); - if (priv->serverGLXvendor) - Xfree((char *) priv->serverGLXvendor); - if (priv->serverGLXversion) - Xfree((char *) priv->serverGLXversion); + free((char *) priv->serverGLXvendor); + free((char *) priv->serverGLXversion); - __glxHashDestroy(priv->drawHash); + __glxHashDestroy(priv->glXDrawHash); #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + __glxHashDestroy(priv->drawHash); + /* Free the direct rendering per display data */ if (priv->driswDisplay) (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay); @@ -282,7 +251,26 @@ __glXCloseDisplay(Display * dpy, XExtCodes * codes) priv->dri2Display = NULL; #endif - Xfree((char *) priv); + free((char *) priv); +} + +static int +__glXCloseDisplay(Display * dpy, XExtCodes * codes) +{ + struct glx_display *priv, **prev; + + _XLockMutex(_Xglobal_lock); + prev = &glx_displays; + for (priv = glx_displays; priv; prev = &priv->next, priv = priv->next) { + if (priv->dpy == dpy) { + *prev = priv->next; + break; + } + } + _XUnlockMutex(_Xglobal_lock); + + if (priv != NULL) + glx_display_free(priv); return 1; } @@ -294,7 +282,6 @@ __glXCloseDisplay(Display * dpy, XExtCodes * codes) 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 @@ -303,6 +290,9 @@ QueryVersion(Display * dpy, int opcode, int *major, int *minor) GLX_MINOR_VERSION), NULL); + if (!reply) + return GL_FALSE; + if (reply->major_version != GLX_MAJOR_VERSION) { free(reply); return GL_FALSE; @@ -311,32 +301,6 @@ QueryVersion(Display * dpy, int opcode, int *major, int *minor) *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 */ } /* @@ -374,6 +338,7 @@ __glXInitializeVisualConfigFromTags(struct glx_config * config, int count, Bool fbconfig_style_tags) { int i; + GLint renderType = 0; if (!tagged_only) { /* Copy in the first set of properties */ @@ -411,6 +376,8 @@ __glXInitializeVisualConfigFromTags(struct glx_config * config, int count, #endif } + config->sRGBCapable = GL_FALSE; + /* ** Additional properties may be in a list at the end ** of the reply. They are in pairs of property type @@ -506,8 +473,8 @@ __glXInitializeVisualConfigFromTags(struct glx_config * config, int count, config->drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; #endif break; - case GLX_RENDER_TYPE: - config->renderType = *bp++; + case GLX_RENDER_TYPE: /* fbconfig render type bits */ + renderType = *bp++; break; case GLX_X_RENDERABLE: config->xRenderable = *bp++; @@ -566,6 +533,10 @@ __glXInitializeVisualConfigFromTags(struct glx_config * config, int count, config->yInverted = *bp++; break; #endif + case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT: + config->sRGBCapable = *bp++; + break; + case GLX_USE_GL: if (fbconfig_style_tags) bp++; @@ -586,8 +557,27 @@ __glXInitializeVisualConfigFromTags(struct glx_config * config, int count, } } - config->renderType = - (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; + if (renderType != 0 && renderType != GLX_DONT_CARE) { + config->renderType = renderType; + config->floatMode = (renderType & + (GLX_RGBA_FLOAT_BIT_ARB|GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) != 0; + } else { + /* If there wasn't GLX_RENDER_TYPE property, set it based on + * config->rgbMode. The only way to communicate that the config is + * floating-point is via GLX_RENDER_TYPE, so this cannot be a float + * config. + */ + config->renderType = + (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; + } + + /* The GLX_ARB_fbconfig_float spec says: + * + * "Note that floating point rendering is only supported for + * GLXPbuffer drawables." + */ + if (config->floatMode) + config->drawableType &= ~(GLX_WINDOW_BIT|GLX_PIXMAP_BIT); } static struct glx_config * @@ -617,7 +607,7 @@ createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, if (prop_size <= sizeof(buf)) props = buf; else - props = Xmalloc(prop_size); + props = malloc(prop_size); /* Read each config structure and convert it into our format */ m = modes; @@ -641,14 +631,14 @@ createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, } if (props != buf) - Xfree(props); + free(props); return modes; } static GLboolean -getVisualConfigs(__GLXscreenConfigs *psc, - __GLXdisplayPrivate *priv, int screen) +getVisualConfigs(struct glx_screen *psc, + struct glx_display *priv, int screen) { xGLXGetVisualConfigsReq *req; xGLXGetVisualConfigsReply reply; @@ -676,7 +666,7 @@ getVisualConfigs(__GLXscreenConfigs *psc, } static GLboolean -getFBConfigs(__GLXscreenConfigs *psc, __GLXdisplayPrivate *priv, int screen) + getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen) { xGLXGetFBConfigsReq *fb_req; xGLXGetFBConfigsSGIXReq *sgi_req; @@ -698,7 +688,7 @@ getFBConfigs(__GLXscreenConfigs *psc, __GLXdisplayPrivate *priv, int screen) } else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { GetReqExtra(GLXVendorPrivateWithReply, - sz_xGLXGetFBConfigsSGIXReq + + sz_xGLXGetFBConfigsSGIXReq - sz_xGLXVendorPrivateWithReplyReq, vpreq); sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; sgi_req->reqType = priv->majorOpcode; @@ -723,8 +713,8 @@ getFBConfigs(__GLXscreenConfigs *psc, __GLXdisplayPrivate *priv, int screen) } _X_HIDDEN Bool -glx_screen_init(__GLXscreenConfigs *psc, - int screen, __GLXdisplayPrivate * priv) +glx_screen_init(struct glx_screen *psc, + int screen, struct glx_display * priv) { /* Initialize per screen dynamic client GLX extensions */ psc->ext_list_first_time = GL_TRUE; @@ -738,22 +728,37 @@ glx_screen_init(__GLXscreenConfigs *psc, return GL_TRUE; } +_X_HIDDEN void +glx_screen_cleanup(struct glx_screen *psc) +{ + if (psc->configs) { + glx_config_destroy_list(psc->configs); + free(psc->effectiveGLXexts); + psc->configs = NULL; /* NOTE: just for paranoia */ + } + if (psc->visuals) { + glx_config_destroy_list(psc->visuals); + psc->visuals = NULL; /* NOTE: just for paranoia */ + } + free((char *) psc->serverGLXexts); +} + /* ** 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) +AllocAndFetchScreenConfigs(Display * dpy, struct glx_display * priv) { - __GLXscreenConfigs *psc; + struct glx_screen *psc; GLint i, screens; /* ** First allocate memory for the array of per screen configs. */ screens = ScreenCount(dpy); - priv->screenConfigs = Xmalloc(screens * sizeof *priv->screenConfigs); - if (!priv->screenConfigs) + priv->screens = malloc(screens * sizeof *priv->screens); + if (!priv->screens) return GL_FALSE; priv->serverGLXversion = @@ -766,16 +771,25 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) for (i = 0; i < screens; i++, psc++) { psc = NULL; #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) - if (priv->dri2Display) +#if defined(HAVE_DRI3) + if (priv->dri3Display) + psc = (*priv->dri3Display->createScreen) (i, priv); +#endif + if (psc == NULL && priv->dri2Display) psc = (*priv->dri2Display->createScreen) (i, priv); if (psc == NULL && priv->driDisplay) psc = (*priv->driDisplay->createScreen) (i, priv); if (psc == NULL && priv->driswDisplay) psc = (*priv->driswDisplay->createScreen) (i, priv); #endif +#if defined(GLX_USE_APPLEGL) + if (psc == NULL) + psc = applegl_create_screen(i, priv); +#else if (psc == NULL) psc = indirect_create_screen(i, priv); - priv->screenConfigs[i] = psc; +#endif + priv->screens[i] = psc; } SyncHandle(); return GL_TRUE; @@ -784,10 +798,10 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) /* ** Initialize the client side extension code. */ -_X_HIDDEN __GLXdisplayPrivate * + _X_HIDDEN struct glx_display * __glXInitialize(Display * dpy) { - __GLXdisplayPrivate *dpyPriv; + struct glx_display *dpyPriv, *d; #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) Bool glx_direct, glx_accel; #endif @@ -802,13 +816,16 @@ __glXInitialize(Display * dpy) } } - dpyPriv = Xcalloc(1, sizeof *dpyPriv); + /* Drop the lock while we create the display private. */ + _XUnlockMutex(_Xglobal_lock); + + dpyPriv = calloc(1, sizeof *dpyPriv); if (!dpyPriv) return NULL; dpyPriv->codes = XInitExtension(dpy, __glXExtensionName); if (!dpyPriv->codes) { - Xfree(dpyPriv); + free(dpyPriv); _XUnlockMutex(_Xglobal_lock); return NULL; } @@ -818,10 +835,13 @@ __glXInitialize(Display * dpy) dpyPriv->serverGLXvendor = 0x0; dpyPriv->serverGLXversion = 0x0; - /* See if the versions are compatible */ + /* See if the versions are compatible. This GLX implementation does not + * work with servers that only support GLX 1.0. + */ if (!QueryVersion(dpy, dpyPriv->majorOpcode, - &dpyPriv->majorVersion, &dpyPriv->minorVersion)) { - Xfree(dpyPriv); + &dpyPriv->majorVersion, &dpyPriv->minorVersion) + || (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion < 1)) { + free(dpyPriv); _XUnlockMutex(_Xglobal_lock); return NULL; } @@ -834,6 +854,8 @@ __glXInitialize(Display * dpy) XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay); XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString); + dpyPriv->glXDrawHash = __glxHashCreate(); + #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL); glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL); @@ -846,6 +868,10 @@ __glXInitialize(Display * dpy) ** (e.g., those called in AllocAndFetchScreenConfigs). */ if (glx_direct && glx_accel) { +#if defined(HAVE_DRI3) + if (!getenv("LIBGL_DRI3_DISABLE")) + dpyPriv->dri3Display = dri3_create_display(dpy); +#endif dpyPriv->dri2Display = dri2CreateDisplay(dpy); dpyPriv->driDisplay = driCreateDisplay(dpy); } @@ -854,18 +880,29 @@ __glXInitialize(Display * dpy) #endif #ifdef GLX_USE_APPLEGL - if (apple_init_glx(dpy)) { - Xfree(dpyPriv); + if (!applegl_create_display(dpyPriv)) { + free(dpyPriv); return NULL; } #endif if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { - Xfree(dpyPriv); + free(dpyPriv); return NULL; } - if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) - __glXClientInfo(dpy, dpyPriv->majorOpcode); + __glX_send_client_info(dpyPriv); + + /* Grab the lock again and add the dispay private, unless somebody + * beat us to initializing on this display in the meantime. */ + _XLockMutex(_Xglobal_lock); + + for (d = glx_displays; d; d = d->next) { + if (d->dpy == dpy) { + _XUnlockMutex(_Xglobal_lock); + glx_display_free(dpyPriv); + return d; + } + } dpyPriv->next = glx_displays; glx_displays = dpyPriv; @@ -882,8 +919,8 @@ __glXInitialize(Display * dpy) _X_HIDDEN CARD8 __glXSetupForCommand(Display * dpy) { - GLXContext gc; - __GLXdisplayPrivate *priv; + struct glx_context *gc; + struct glx_display *priv; /* If this thread has a current context, flush its rendering commands */ gc = __glXGetCurrentContext(); @@ -922,32 +959,15 @@ __glXSetupForCommand(Display * dpy) * \c pc parameter. */ _X_HIDDEN GLubyte * -__glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc) +__glXFlushRenderBuffer(struct glx_context * 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 */ @@ -973,36 +993,13 @@ __glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc) * \param dataLen Size, in bytes, of the command data. */ _X_HIDDEN void -__glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber, +__glXSendLargeChunk(struct glx_context * 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 */ } @@ -1022,7 +1019,7 @@ __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber, * \param dataLen Size, in bytes, of the command data. */ _X_HIDDEN void -__glXSendLargeCommand(__GLXcontext * ctx, +__glXSendLargeCommand(struct glx_context * ctx, const GLvoid * header, GLint headerLen, const GLvoid * data, GLint dataLen) { @@ -1064,7 +1061,7 @@ __glXSendLargeCommand(__GLXcontext * ctx, #ifdef DEBUG _X_HIDDEN void -__glXDumpDrawBuffer(__GLXcontext * ctx) +__glXDumpDrawBuffer(struct glx_context * ctx) { GLubyte *p = ctx->buf; GLubyte *end = ctx->pc;