#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
#include <X11/extensions/dri2proto.h>
+#ifdef GLX_USE_APPLEGL
+#include "apple_glx.h"
+#include "apple_visual.h"
+#endif
#include "glxextensions.h"
#include "glcontextmodes.h"
/* Extension required boiler plate */
-static char *__glXExtensionName = GLX_EXTENSION_NAME;
-XExtensionInfo *__glXExtensionInfo = NULL;
+static const char __glXExtensionName[] = GLX_EXTENSION_NAME;
+static __GLXdisplayPrivate *glx_displays;
static /* const */ char *error_list[] = {
"GLXBadContext",
"GLXBadWindow",
};
-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 int
+__glXCloseDisplay(Display * dpy, XExtCodes * codes);
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
* our user exposed (via XNextEvent) structure. Instead we use the GLX
static Bool
__glXWireToEvent(Display *dpy, XEvent *event, xEvent *wire)
{
- XExtDisplayInfo *info = __glXFindDisplay(dpy);
+ __GLXdisplayPrivate *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;
static Status
__glXEventToWire(Display *dpy, XEvent *event, xEvent *wire)
{
- XExtDisplayInfo *info = __glXFindDisplay(dpy);
+ __GLXdisplayPrivate *glx_dpy = __glXInitialize(dpy);
- XextCheckExtension(dpy, info, __glXExtensionName, False);
+ if (glx_dpy == NULL)
+ return False;
switch (event->type) {
case GLX_DAMAGED:
break;
case GLX_EXCHANGE_COMPLETE_INTEL:
break;
- case GLX_BLIT_COMPLETE_INTEL:
+ case GLX_COPY_COMPLETE_INTEL:
break;
case GLX_FLIP_COMPLETE_INTEL:
break;
GLint i, screens;
/* Free screen configuration information */
- psc = priv->screenConfigs;
screens = ScreenCount(priv->dpy);
- for (i = 0; i < screens; i++, psc++) {
+ for (i = 0; i < screens; i++) {
+ psc = priv->screenConfigs[i];
if (psc->configs) {
_gl_context_modes_destroy(psc->configs);
if (psc->effectiveGLXexts)
}
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;
- }
+#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 {
+ Xfree(psc);
}
+#else
+ Xfree(psc);
#endif
}
XFree((char *) priv->screenConfigs);
** structure. The caller will free the extension structure.
*/
static int
-__glXFreeDisplayPrivate(XExtData * extension)
+__glXCloseDisplay(Display * dpy, XExtCodes * codes)
{
- __GLXdisplayPrivate *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);
+
+ gc = __glXGetCurrentContext();
+ if (dpy == gc->currentDpy) {
+ gc->vtable->destroy(gc);
+ __glXSetCurrentContextNull();
+ }
- priv = (__GLXdisplayPrivate *) extension->private_data;
FreeScreenConfigs(priv);
- if (priv->serverGLXvendor) {
+ if (priv->serverGLXvendor)
Xfree((char *) priv->serverGLXvendor);
- priv->serverGLXvendor = 0x0; /* to protect against double free's */
- }
- if (priv->serverGLXversion) {
+ if (priv->serverGLXversion)
Xfree((char *) priv->serverGLXversion);
- priv->serverGLXversion = 0x0; /* to protect against double free's */
- }
-#ifdef GLX_DIRECT_RENDERING
+ __glxHashDestroy(priv->drawHash);
+
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
/* Free the direct rendering per display data */
if (priv->driswDisplay)
(*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
#endif
Xfree((char *) priv);
- return 0;
-}
-/************************************************************************/
+ return 1;
+}
/*
** Query the version of the GLX extension. This procedure works even if
#endif /* USE_XCB */
}
+/*
+ * 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
+};
+
+/*
+ * getVisualConfigs uses the !tagged_only path.
+ * getFBConfigs uses the tagged_only path.
+ */
_X_HIDDEN void
__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
const INT32 * bp, Bool tagged_only,
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
}
/*
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;
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_MAX_PBUFFER_PIXELS:
config->maxPbufferPixels = *bp++;
break;
+#ifndef GLX_USE_APPLEGL
case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
config->optimalPbufferWidth = *bp++;
break;
case GLX_SWAP_METHOD_OML:
config->swapMethod = *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;
case GLX_Y_INVERTED_EXT:
config->yInverted = *bp++;
break;
+#endif
+ case GLX_USE_GL:
+ if (fbconfig_style_tags)
+ bp++;
+ break;
case None:
i = count;
break;
default:
+ if(getenv("LIBGL_DIAGNOSTIC")) {
+ 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;
}
}
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
+ __glXInitializeVisualConfigFromTags(m, nprops, props,
tagged_only, GL_TRUE);
m->screen = screen;
m = m->next;
}
static GLboolean
-getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
+getVisualConfigs(__GLXscreenConfigs *psc,
+ __GLXdisplayPrivate *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;
}
static GLboolean
-getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
+getFBConfigs(__GLXscreenConfigs *psc, __GLXdisplayPrivate *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);
return psc->configs != NULL;
}
+_X_HIDDEN Bool
+glx_screen_init(__GLXscreenConfigs *psc,
+ int screen, __GLXdisplayPrivate * 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;
+
+ getVisualConfigs(psc, priv, screen);
+ getFBConfigs(psc, priv, screen);
+
+ return GL_TRUE;
+}
+
/*
** Allocate the memory for the per screen configs for each screen.
** If that works then fetch the per screen configs data.
** First allocate memory for the array of per screen configs.
*/
screens = ScreenCount(dpy);
- psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
- if (!psc) {
+ priv->screenConfigs = Xmalloc(screens * sizeof *priv->screenConfigs);
+ if (!priv->screenConfigs)
return GL_FALSE;
- }
- memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
- priv->screenConfigs = psc;
priv->serverGLXversion =
__glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
}
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;
-
+ psc = NULL;
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
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;
- }
+ 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 (psc == NULL)
+ psc = indirect_create_screen(i, priv);
+ priv->screenConfigs[i] = psc;
}
SyncHandle();
return GL_TRUE;
_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
+#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;
+ dpyPriv = Xcalloc(1, sizeof *dpyPriv);
+ if (!dpyPriv)
+ return NULL;
+
+ dpyPriv->codes = XInitExtension(dpy, __glXExtensionName);
+ if (!dpyPriv->codes) {
+ Xfree(dpyPriv);
+ _XUnlockMutex(_Xglobal_lock);
+ return NULL;
}
+ dpyPriv->dpy = dpy;
+ dpyPriv->majorOpcode = dpyPriv->codes->major_opcode;
+ dpyPriv->serverGLXvendor = 0x0;
+ dpyPriv->serverGLXversion = 0x0;
+
/* 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;
+ if (!QueryVersion(dpy, dpyPriv->majorOpcode,
+ &dpyPriv->majorVersion, &dpyPriv->minorVersion)) {
+ Xfree(dpyPriv);
+ _XUnlockMutex(_Xglobal_lock);
+ return NULL;
}
- /*
- ** Allocate memory for all the pieces needed for this buffer.
- */
- private = (XExtData *) Xmalloc(sizeof(XExtData));
- if (!private) {
- __glXUnlock();
- 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);
}
- 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;
+ XESetCloseDisplay(dpy, dpyPriv->codes->extension, __glXCloseDisplay);
+ XESetErrorString (dpy, dpyPriv->codes->extension,__glXErrorString);
-#ifdef GLX_DIRECT_RENDERING
+#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
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
dpyPriv->driswDisplay = driswCreateDisplay(dpy);
#endif
+#ifdef GLX_USE_APPLEGL
+ if (apple_init_glx(dpy)) {
+ Xfree(dpyPriv);
+ return NULL;
+ }
+#endif
if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
- __glXUnlock();
- Xfree((char *) dpyPriv);
- Xfree((char *) private);
- return 0;
+ Xfree(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) {
+ if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1)
__glXClientInfo(dpy, dpyPriv->majorOpcode);
- }
- __glXUnlock();
+
+ dpyPriv->next = glx_displays;
+ glx_displays = dpyPriv;
+
+ _XUnlockMutex(_Xglobal_lock);
return dpyPriv;
}