X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fglx%2Fglxext.c;h=cef81920356e8a69f7a27ef9239fb915611cbe42;hp=6d6f89e79a274c66eaad034c4a1479d74f374cec;hb=5bc509363b6dbc42af72668fe500b6aec988dbf0;hpb=ad7d36e91933a49ce3f6ed2c14ae585a8a84fdf5 diff --git a/src/glx/glxext.c b/src/glx/glxext.c index 6d6f89e79a2..cef81920356 100644 --- a/src/glx/glxext.c +++ b/src/glx/glxext.c @@ -38,22 +38,26 @@ */ #include +#include + #include "glxclient.h" #include #include -#include +#ifdef GLX_USE_APPLEGL +#include "apple/apple_glx.h" +#include "apple/apple_visual.h" +#endif #include "glxextensions.h" -#include "glcontextmodes.h" -#ifdef USE_XCB +#include "util/debug.h" + #include #include #include -#endif #ifdef DEBUG -void __glXDumpDrawBuffer(__GLXcontext * ctx); +void __glXDumpDrawBuffer(struct glx_context * ctx); #endif /* @@ -64,8 +68,8 @@ _X_HIDDEN int __glXDebug = 0; /* Extension required boiler plate */ -static char *__glXExtensionName = GLX_EXTENSION_NAME; -XExtensionInfo *__glXExtensionInfo = NULL; +static const char __glXExtensionName[] = GLX_EXTENSION_NAME; + static struct glx_display *glx_displays; static /* const */ char *error_list[] = { "GLXBadContext", @@ -81,48 +85,17 @@ static /* const */ char *error_list[] = { "GLXBadPbuffer", "GLXBadCurrentDrawable", "GLXBadWindow", + "GLXBadProfileARB", }; -static int -__glXCloseDisplay(Display * dpy, XExtCodes * codes) -{ - GLXContext gc; - - gc = __glXGetCurrentContext(); - if (dpy == gc->currentDpy) { - __glXSetCurrentContextNull(); - __glXFreeContext(gc); - } - - return XextRemoveDisplay(__glXExtensionInfo, dpy); -} - +#ifdef GLX_USE_APPLEGL +static char *__glXErrorString(Display *dpy, int code, XExtCodes *codes, + char *buf, int n); +#endif static XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName, __GLX_NUMBER_ERRORS, error_list) -static Bool -__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire); -static Status -__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire); - -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 */ - __glXWireToEvent, /* wire_to_event */ - __glXEventToWire, /* event_to_wire */ - NULL, /* error */ - __glXErrorString, /* error_string */ -}; - -XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, - __glXExtensionName, &__glXExtensionHooks, - __GLX_NUMBER_EVENTS, NULL) /* * GLX events are a bit funky. We don't stuff the X event code into @@ -136,11 +109,12 @@ XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, static Bool __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) { - XExtDisplayInfo *info = __glXFindDisplay(dpy); + struct glx_display *glx_dpy = __glXInitialize(dpy); - XextCheckExtension(dpy, info, __glXExtensionName, False); + if (glx_dpy == NULL) + return False; - switch ((wire->u.u.type & 0x7f) - info->codes->first_event) { + switch ((wire->u.u.type & 0x7f) - glx_dpy->codes->first_event) { case GLX_PbufferClobber: { GLXPbufferClobberEvent *aevent = (GLXPbufferClobberEvent *)event; @@ -159,28 +133,34 @@ __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); + + if (!glxDraw) + return False; + + aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); + aevent->send_event = (awire->type & 0x80) != 0; + aevent->display = dpy; aevent->event_type = awire->event_type; - aevent->drawable = awire->drawable; + aevent->drawable = glxDraw->xDrawable; 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; + + /* Handle 32-Bit wire sbc wraparound in both directions to cope with out + * of sequence 64-Bit sbc's + */ + if ((int64_t) awire->sbc < ((int64_t) glxDraw->lastEventSbc - 0x40000000)) + glxDraw->eventSbcWrap += 0x100000000; + if ((int64_t) awire->sbc > ((int64_t) glxDraw->lastEventSbc + 0x40000000)) + glxDraw->eventSbcWrap -= 0x100000000; + glxDraw->lastEventSbc = awire->sbc; + aevent->sbc = awire->sbc + glxDraw->eventSbcWrap; return True; } -#endif default: /* client doesn't support server event */ break; @@ -195,9 +175,10 @@ __glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire) static Status __glXEventToWire(Display *dpy, XEvent *event, xEvent *wire) { - XExtDisplayInfo *info = __glXFindDisplay(dpy); + struct glx_display *glx_dpy = __glXInitialize(dpy); - XextCheckExtension(dpy, info, __glXExtensionName, False); + if (glx_dpy == NULL) + return False; switch (event->type) { case GLX_DAMAGED: @@ -224,73 +205,57 @@ __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 */ - 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) { - unsigned int j; - for (j = 0; psc->driver_configs[j]; j++) - free((__DRIconfig *) psc->driver_configs[j]); - free(psc->driver_configs); - psc->driver_configs = NULL; - } + for (i = 0; i < screens; i++) { + psc = priv->screens[i]; + glx_screen_cleanup(psc); + +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) if (psc->driScreen) { psc->driScreen->destroyScreen(psc); - __glxHashDestroy(psc->drawHash); - XFree(psc->driScreen); - psc->driScreen = NULL; + } else { + free(psc); } +#else + 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 -__glXFreeDisplayPrivate(XExtData * extension) +static void +glx_display_free(struct glx_display *priv) { - __GLXdisplayPrivate *priv; + struct glx_context *gc; - 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 */ + gc = __glXGetCurrentContext(); + if (priv->dpy == gc->currentDpy) { + gc->vtable->destroy(gc); + __glXSetCurrentContextNull(); } -#ifdef GLX_DIRECT_RENDERING + FreeScreenConfigs(priv); + free((char *) priv->serverGLXvendor); + free((char *) priv->serverGLXversion); + + __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); priv->driswDisplay = NULL; +#if defined (GLX_USE_DRM) if (priv->driDisplay) (*priv->driDisplay->destroyDisplay) (priv->driDisplay); priv->driDisplay = NULL; @@ -298,13 +263,43 @@ __glXFreeDisplayPrivate(XExtData * extension) if (priv->dri2Display) (*priv->dri2Display->destroyDisplay) (priv->dri2Display); priv->dri2Display = NULL; -#endif - Xfree((char *) priv); - return 0; + if (priv->dri3Display) + (*priv->dri3Display->destroyDisplay) (priv->dri3Display); + priv->dri3Display = NULL; +#endif /* GLX_USE_DRM */ + +#if defined(GLX_USE_WINDOWSGL) + if (priv->windowsdriDisplay) + (*priv->windowsdriDisplay->destroyDisplay) (priv->windowsdriDisplay); + priv->windowsdriDisplay = NULL; +#endif /* GLX_USE_WINDOWSGL */ + +#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ + + 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; +} /* ** Query the version of the GLX extension. This procedure works even if @@ -313,7 +308,6 @@ __glXFreeDisplayPrivate(XExtData * extension) 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 @@ -322,6 +316,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; @@ -330,47 +327,53 @@ 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(); +/* + * We don't want to enable this GLX_OML_swap_method in glxext.h, + * because we can't support it. The X server writes it out though, + * so we should handle it somehow, to avoid false warnings. + */ +enum { + IGNORE_GLX_SWAP_METHOD_OML = 0x8060 +}; - 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 */ -} +static GLint +convert_from_x_visual_type(int visualType) +{ + static const int glx_visual_types[] = { + [StaticGray] = GLX_STATIC_GRAY, + [GrayScale] = GLX_GRAY_SCALE, + [StaticColor] = GLX_STATIC_COLOR, + [PseudoColor] = GLX_PSEUDO_COLOR, + [TrueColor] = GLX_TRUE_COLOR, + [DirectColor] = GLX_DIRECT_COLOR, + }; + + if (visualType < ARRAY_SIZE(glx_visual_types)) + return glx_visual_types[visualType]; + + return GLX_NONE; +} +/* + * getVisualConfigs uses the !tagged_only path. + * getFBConfigs uses the tagged_only path. + */ _X_HIDDEN void -__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, +__glXInitializeVisualConfigFromTags(struct glx_config * config, int count, const INT32 * bp, Bool tagged_only, Bool fbconfig_style_tags) { int i; + GLint renderType = 0; if (!tagged_only) { /* Copy in the first set of properties */ config->visualID = *bp++; - config->visualType = _gl_convert_from_x_visual_type(*bp++); + config->visualType = convert_from_x_visual_type(*bp++); config->rgbMode = *bp++; @@ -392,7 +395,14 @@ __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, config->numAuxBuffers = *bp++; config->level = *bp++; +#ifdef GLX_USE_APPLEGL + /* AppleSGLX supports pixmap and pbuffers with all config. */ + config->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; + /* Unfortunately this can create an ABI compatibility problem. */ + count -= 18; +#else count -= __GLX_MIN_CONFIG_PROPS; +#endif } /* @@ -405,7 +415,9 @@ __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1 for (i = 0; i < count; i += 2) { - switch (*bp++) { + long int tag = *bp++; + + switch (tag) { case GLX_RGBA: FETCH_OR_SET(rgbMode); break; @@ -483,9 +495,13 @@ __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, break; case GLX_DRAWABLE_TYPE: config->drawableType = *bp++; +#ifdef GLX_USE_APPLEGL + /* AppleSGLX supports pixmap and pbuffers with all config. */ + 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++; @@ -502,6 +518,7 @@ __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, case GLX_MAX_PBUFFER_PIXELS: config->maxPbufferPixels = *bp++; break; +#ifndef GLX_USE_APPLEGL case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: config->optimalPbufferWidth = *bp++; break; @@ -512,14 +529,31 @@ __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, config->visualSelectGroup = *bp++; break; case GLX_SWAP_METHOD_OML: - config->swapMethod = *bp++; + if (*bp == GLX_SWAP_UNDEFINED_OML || + *bp == GLX_SWAP_COPY_OML || + *bp == GLX_SWAP_EXCHANGE_OML) { + config->swapMethod = *bp++; + } else { + /* X servers with old HW drivers may return any value here, so + * assume GLX_SWAP_METHOD_UNDEFINED. + */ + config->swapMethod = GLX_SWAP_UNDEFINED_OML; + bp++; + } break; +#endif case GLX_SAMPLE_BUFFERS_SGIS: config->sampleBuffers = *bp++; break; case GLX_SAMPLES_SGIS: config->samples = *bp++; break; +#ifdef GLX_USE_APPLEGL + case IGNORE_GLX_SWAP_METHOD_OML: + /* We ignore this tag. See the comment above this function. */ + ++bp; + break; +#else case GLX_BIND_TO_TEXTURE_RGB_EXT: config->bindToTextureRgb = *bp++; break; @@ -535,34 +569,61 @@ __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, case GLX_Y_INVERTED_EXT: config->yInverted = *bp++; break; +#endif + case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT: + config->sRGBCapable = *bp++; + break; + + case GLX_USE_GL: + if (fbconfig_style_tags) + bp++; + break; case None: i = count; break; default: - /* Ignore the unrecognized tag's value */ - bp++; + if(env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) { + long int tagvalue = *bp++; + fprintf(stderr, "WARNING: unknown GLX tag from server: " + "tag 0x%lx value 0x%lx\n", tag, tagvalue); + } else { + /* Ignore the unrecognized tag's value */ + bp++; + } break; } } - 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; + } - config->haveAccumBuffer = ((config->accumRedBits + - config->accumGreenBits + - config->accumBlueBits + - config->accumAlphaBits) > 0); - config->haveDepthBuffer = (config->depthBits > 0); - config->haveStencilBuffer = (config->stencilBits > 0); + /* The GLX_ARB_fbconfig_float spec says: + * + * "Note that floating point rendering is only supported for + * GLXPbuffer drawables." + */ + if (config->floatMode) + config->drawableType &= GLX_PBUFFER_BIT; } -static __GLcontextModes * +static struct glx_config * createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, int screen, GLboolean tagged_only) { INT32 buf[__GLX_TOTAL_CONFIG], *props; unsigned prop_size; - __GLcontextModes *modes, *m; + struct glx_config *modes, *m; int i; if (nprops == 0) @@ -575,7 +636,7 @@ createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, return NULL; /* Allocate memory for our config structure */ - modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes)); + modes = glx_config_create_list(nvisuals); if (!modes) return NULL; @@ -583,36 +644,47 @@ 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; for (i = 0; i < nvisuals; i++) { _XRead(dpy, (char *) props, prop_size); - /* Older X servers don't send this so we default it here. */ +#ifdef GLX_USE_APPLEGL + /* Older X servers don't send this so we default it here. */ m->drawableType = GLX_WINDOW_BIT; - __glXInitializeVisualConfigFromTags(m, nprops, props, +#else + /* + * The XQuartz 2.3.2.1 X server doesn't set this properly, so + * set the proper bits here. + * AppleSGLX supports windows, pixmaps, and pbuffers with all config. + */ + m->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; +#endif + /* Older X servers don't send this so we default it here. */ + m->sRGBCapable = GL_FALSE; + __glXInitializeVisualConfigFromTags(m, nprops, props, tagged_only, GL_TRUE); m->screen = screen; m = m->next; } if (props != buf) - Xfree(props); + free(props); return modes; } static GLboolean -getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) +getVisualConfigs(struct glx_screen *psc, + struct glx_display *priv, int screen) { xGLXGetVisualConfigsReq *req; - __GLXscreenConfigs *psc; xGLXGetVisualConfigsReply reply; + Display *dpy = priv->dpy; LockDisplay(dpy); - psc = priv->screenConfigs + screen; psc->visuals = NULL; GetReq(GLXGetVisualConfigs, req); req->reqType = priv->majorOpcode; @@ -633,18 +705,21 @@ getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) } static GLboolean -getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) + getFBConfigs(struct glx_screen *psc, struct glx_display *priv, int screen) { xGLXGetFBConfigsReq *fb_req; xGLXGetFBConfigsSGIXReq *sgi_req; xGLXVendorPrivateWithReplyReq *vpreq; xGLXGetFBConfigsReply reply; - __GLXscreenConfigs *psc; + Display *dpy = priv->dpy; - psc = priv->screenConfigs + screen; psc->serverGLXexts = __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); + if (psc->serverGLXexts == NULL) { + return GL_FALSE; + } + LockDisplay(dpy); psc->configs = NULL; @@ -656,7 +731,7 @@ getFBConfigs(Display * dpy, __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; @@ -680,26 +755,57 @@ getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) return psc->configs != NULL; } +_X_HIDDEN Bool +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; + psc->scr = screen; + psc->dpy = priv->dpy; + psc->display = priv; + + if (!getVisualConfigs(psc, priv, screen)) + return GL_FALSE; + + if (!getFBConfigs(psc, priv, screen)) + return GL_FALSE; + + 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); - psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs)); - if (!psc) { + priv->screens = malloc(screens * sizeof *priv->screens); + if (!priv->screens) return GL_FALSE; - } - memset(psc, 0, screens * sizeof(__GLXscreenConfigs)); - priv->screenConfigs = psc; priv->serverGLXversion = __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); @@ -709,33 +815,36 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) } 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; - - /* Initialize per screen dynamic client GLX extensions */ - psc->ext_list_first_time = GL_TRUE; - - 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); + psc = NULL; +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) +#if defined(GLX_USE_DRM) +#if defined(HAVE_DRI3) + if (priv->dri3Display) + psc = (*priv->dri3Display->createScreen) (i, priv); +#endif /* HAVE_DRI3 */ + if (psc == NULL && priv->dri2Display) + psc = (*priv->dri2Display->createScreen) (i, priv); + if (psc == NULL && priv->driDisplay) + psc = (*priv->driDisplay->createScreen) (i, priv); +#endif /* GLX_USE_DRM */ + +#ifdef GLX_USE_WINDOWSGL + if (psc == NULL && priv->windowsdriDisplay) + psc = (*priv->windowsdriDisplay->createScreen) (i, priv); +#endif - if (psc->driScreen == NULL && priv->driswDisplay) - psc->driScreen = (*priv->driswDisplay->createScreen) (psc, i, priv); + if (psc == NULL && priv->driswDisplay) + psc = (*priv->driswDisplay->createScreen) (i, priv); +#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ - if (psc->driScreen == NULL) { - __glxHashDestroy(psc->drawHash); - psc->drawHash = NULL; - } +#if defined(GLX_USE_APPLEGL) + if (psc == NULL) + psc = applegl_create_screen(i, priv); +#else + if (psc == NULL) + psc = indirect_create_screen(i, priv); #endif + priv->screens[i] = psc; } SyncHandle(); return GL_TRUE; @@ -744,110 +853,122 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) /* ** Initialize the client side extension code. */ -_X_HIDDEN __GLXdisplayPrivate * + _X_HIDDEN struct glx_display * __glXInitialize(Display * dpy) { - XExtDisplayInfo *info = __glXFindDisplay(dpy); - XExtData **privList, *private, *found; - __GLXdisplayPrivate *dpyPriv; - XEDataObject dataObj; - int major, minor; -#ifdef GLX_DIRECT_RENDERING + struct glx_display *dpyPriv, *d; +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) Bool glx_direct, glx_accel; #endif + int i; - /* The one and only long long lock */ - __glXLock(); + _XLockMutex(_Xglobal_lock); - if (!XextHasExtension(info)) { - /* No GLX extension supported by this server. Oh well. */ - __glXUnlock(); - XMissingExtension(dpy, __glXExtensionName); - return 0; + for (dpyPriv = glx_displays; dpyPriv; dpyPriv = dpyPriv->next) { + if (dpyPriv->dpy == dpy) { + _XUnlockMutex(_Xglobal_lock); + return dpyPriv; + } } - /* 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; - } + /* Drop the lock while we create the display private. */ + _XUnlockMutex(_Xglobal_lock); - /* 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; + dpyPriv = calloc(1, sizeof *dpyPriv); + if (!dpyPriv) + return NULL; + + dpyPriv->codes = XInitExtension(dpy, __glXExtensionName); + if (!dpyPriv->codes) { + free(dpyPriv); + return NULL; } - /* - ** Allocate memory for all the pieces needed for this buffer. + dpyPriv->dpy = dpy; + dpyPriv->majorOpcode = dpyPriv->codes->major_opcode; + dpyPriv->serverGLXvendor = 0x0; + dpyPriv->serverGLXversion = 0x0; + + /* See if the versions are compatible. This GLX implementation does not + * work with servers that only support GLX 1.0. */ - private = (XExtData *) Xmalloc(sizeof(XExtData)); - if (!private) { - __glXUnlock(); - return 0; + if (!QueryVersion(dpy, dpyPriv->majorOpcode, + &dpyPriv->majorVersion, &dpyPriv->minorVersion) + || (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion < 1)) { + free(dpyPriv); + return NULL; } - dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate)); - if (!dpyPriv) { - __glXUnlock(); - Xfree((char *) private); - return 0; + + for (i = 0; i < __GLX_NUMBER_EVENTS; i++) { + XESetWireToEvent(dpy, dpyPriv->codes->first_event + i, __glXWireToEvent); + XESetEventToWire(dpy, dpyPriv->codes->first_event + i, __glXEventToWire); } - /* - ** 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; + XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay); + XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString); - dpyPriv->serverGLXvendor = 0x0; - dpyPriv->serverGLXversion = 0x0; + dpyPriv->glXDrawHash = __glxHashCreate(); + +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false); + glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false); -#ifdef GLX_DIRECT_RENDERING - glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL); - glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL); + dpyPriv->drawHash = __glxHashCreate(); /* ** 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 defined(GLX_USE_DRM) if (glx_direct && glx_accel) { +#if defined(HAVE_DRI3) + if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false)) + dpyPriv->dri3Display = dri3_create_display(dpy); +#endif /* HAVE_DRI3 */ dpyPriv->dri2Display = dri2CreateDisplay(dpy); dpyPriv->driDisplay = driCreateDisplay(dpy); } +#endif /* GLX_USE_DRM */ if (glx_direct) dpyPriv->driswDisplay = driswCreateDisplay(dpy); +#endif /* GLX_DIRECT_RENDERING && !GLX_USE_APPLEGL */ + +#ifdef GLX_USE_APPLEGL + if (!applegl_create_display(dpyPriv)) { + free(dpyPriv); + return NULL; + } +#endif + +#ifdef GLX_USE_WINDOWSGL + if (glx_direct && glx_accel) + dpyPriv->windowsdriDisplay = driwindowsCreateDisplay(dpy); #endif if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { - __glXUnlock(); - Xfree((char *) dpyPriv); - Xfree((char *) private); - return 0; + free(dpyPriv); + return NULL; } - /* - ** 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); + __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; + } } - __glXUnlock(); + + dpyPriv->next = glx_displays; + glx_displays = dpyPriv; + + _XUnlockMutex(_Xglobal_lock); return dpyPriv; } @@ -859,8 +980,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(); @@ -899,32 +1020,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 */ @@ -950,36 +1054,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 */ } @@ -999,7 +1080,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) { @@ -1041,7 +1122,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;