#include "glxclient.h"
#include "glapi.h"
#include "glxextensions.h"
+#include "indirect.h"
+#include "glx_error.h"
#ifdef GLX_DIRECT_RENDERING
#ifdef GLX_USE_APPLEGL
#include "apple_glx_context.h"
#include "apple_glx.h"
-#include "glx_error.h"
#else
#include <sys/time.h>
#ifdef XF86VIDMODE
#else
#endif
-#if defined(USE_XCB)
#include <X11/Xlib-xcb.h>
#include <xcb/xcb.h>
#include <xcb/glx.h>
-#endif
static const char __glXGLXClientVendorName[] = "Mesa Project and SGI";
static const char __glXGLXClientVersion[] = "1.4";
#endif
+_X_HIDDEN struct glx_drawable *
+GetGLXDrawable(Display *dpy, GLXDrawable drawable)
+{
+ struct glx_display *priv = __glXInitialize(dpy);
+ struct glx_drawable *glxDraw;
+
+ if (priv == NULL)
+ return NULL;
+
+ if (__glxHashLookup(priv->glXDrawHash, drawable, (void *) &glxDraw) == 0)
+ return glxDraw;
+
+ return NULL;
+}
+
+_X_HIDDEN int
+InitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw, XID xDrawable,
+ GLXDrawable drawable)
+{
+ struct glx_display *priv = __glXInitialize(dpy);
+
+ if (!priv)
+ return -1;
+
+ glxDraw->xDrawable = xDrawable;
+ glxDraw->drawable = drawable;
+ glxDraw->lastEventSbc = 0;
+ glxDraw->eventSbcWrap = 0;
+
+ return __glxHashInsert(priv->glXDrawHash, drawable, glxDraw);
+}
+
+_X_HIDDEN void
+DestroyGLXDrawable(Display *dpy, GLXDrawable drawable)
+{
+ struct glx_display *priv = __glXInitialize(dpy);
+ struct glx_drawable *glxDraw;
+
+ if (!priv)
+ return;
+
+ glxDraw = GetGLXDrawable(dpy, drawable);
+ __glxHashDelete(priv->glXDrawHash, drawable);
+ free(glxDraw);
+}
/**
* Get the GLX per-screen data structure associated with a GLX context.
* number range for \c dpy?
*/
-static struct glx_screen *
+_X_HIDDEN struct glx_screen *
GetGLXScreenConfigs(Display * dpy, int scrn)
{
struct glx_display *const priv = __glXInitialize(dpy);
/**
- * Create a new context. Exactly one of \c vis and \c fbconfig should be
- * non-NULL.
+ * Create a new context.
*
- * \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 GLXContext
-CreateContext(Display * dpy, int generic_id,
- struct glx_config *config,
- GLXContext shareList_user,
- Bool allowDirect,
+CreateContext(Display *dpy, int generic_id, struct glx_config *config,
+ GLXContext shareList_user, Bool allowDirect,
unsigned code, int renderType, int screen)
{
- struct glx_context *gc = NULL;
- struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen);
+ struct glx_context *gc;
+ struct glx_screen *psc;
struct glx_context *shareList = (struct glx_context *) shareList_user;
if (dpy == NULL)
return NULL;
+ psc = GetGLXScreenConfigs(dpy, screen);
+ if (psc == NULL)
+ return NULL;
+
if (generic_id == None)
return NULL;
gc = NULL;
+#ifdef GLX_USE_APPLEGL
+ gc = applegl_create_context(psc, config, shareList, renderType);
+#else
if (allowDirect && psc->vtable->create_context)
gc = psc->vtable->create_context(psc, config, shareList, renderType);
if (!gc)
gc = indirect_create_context(psc, config, shareList, renderType);
+#endif
if (!gc)
return NULL;
UnlockDisplay(dpy);
SyncHandle();
+ gc->share_xid = shareList ? shareList->xid : None;
gc->imported = GL_FALSE;
gc->renderType = renderType;
X_GLXCreateContext, renderType, vis->screen);
}
-_X_HIDDEN void
+static void
glx_send_destroy_context(Display *dpy, XID xid)
{
CARD8 opcode = __glXSetupForCommand(dpy);
/*
** Destroy the named context
*/
-static void
-DestroyContext(Display * dpy, GLXContext ctx)
+
+_X_EXPORT void
+glXDestroyContext(Display * dpy, GLXContext ctx)
{
struct glx_context *gc = (struct glx_context *) ctx;
- if (!gc)
+ if (gc == NULL || gc->xid == None)
return;
__glXLock();
+ if (!gc->imported)
+ glx_send_destroy_context(dpy, gc->xid);
+
if (gc->currentDpy) {
/* This context is bound to some thread. According to the man page,
* we should not actually delete the context until it's unbound.
* Note that we set gc->xid = None above. In MakeContextCurrent()
* we check for that and delete the context there.
*/
- if (!gc->imported)
- glx_send_destroy_context(dpy, gc->xid);
gc->xid = None;
- __glXUnlock();
- return;
+ } else {
+ gc->vtable->destroy(gc);
}
__glXUnlock();
-
- if (gc->vtable->destroy)
- gc->vtable->destroy(gc);
-}
-
-_X_EXPORT void
-glXDestroyContext(Display * dpy, GLXContext gc)
-{
- DestroyContext(dpy, gc);
}
/*
static Bool
__glXIsDirect(Display * dpy, GLXContextID contextID)
{
-#if !defined(USE_XCB)
- xGLXIsDirectReq *req;
- xGLXIsDirectReply reply;
-#endif
CARD8 opcode;
opcode = __glXSetupForCommand(dpy);
return GL_FALSE;
}
-#ifdef USE_XCB
xcb_connection_t *c = XGetXCBConnection(dpy);
+ xcb_generic_error_t *err;
xcb_glx_is_direct_reply_t *reply = xcb_glx_is_direct_reply(c,
xcb_glx_is_direct
(c, contextID),
- NULL);
+ &err);
+
+ const Bool is_direct = (reply != NULL && reply->is_direct) ? True : False;
+
+ if (err != NULL) {
+ __glXSendErrorForXcb(dpy, err);
+ free(err);
+ }
- const Bool is_direct = reply->is_direct ? True : False;
free(reply);
return is_direct;
-#else
- /* Send the glXIsDirect request */
- LockDisplay(dpy);
- GetReq(GLXIsDirect, req);
- req->reqType = opcode;
- req->glxCode = X_GLXIsDirect;
- req->context = contextID;
- _XReply(dpy, (xReply *) & reply, 0, False);
- UnlockDisplay(dpy);
- SyncHandle();
-
- return reply.isDirect;
-#endif /* USE_XCB */
}
/**
struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen);
const struct glx_config *config;
- config = _gl_context_modes_find_visual(psc->visuals, vis->visualid);
+ config = glx_config_find_visual(psc->visuals, vis->visualid);
if(apple_glx_pixmap_create(dpy, vis->screen, pixmap, config))
return None;
return pixmap;
#else
xGLXCreateGLXPixmapReq *req;
+ struct glx_drawable *glxDraw;
GLXPixmap xid;
CARD8 opcode;
return None;
}
+ glxDraw = malloc(sizeof(*glxDraw));
+ if (!glxDraw)
+ return None;
+
/* Send the glXCreateGLXPixmap request */
LockDisplay(dpy);
GetReq(GLXCreateGLXPixmap, req);
UnlockDisplay(dpy);
SyncHandle();
+ if (InitGLXDrawable(dpy, glxDraw, pixmap, req->glxpixmap)) {
+ free(glxDraw);
+ return None;
+ }
+
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
do {
/* FIXME: Maybe delay __DRIdrawable creation until the drawable
psc = priv->screens[vis->screen];
if (psc->driScreen == NULL)
- break;
+ return xid;
+
config = glx_config_find_visual(psc->visuals, vis->visualid);
- pdraw = psc->driScreen->createDrawable(psc, pixmap, req->glxpixmap, config);
+ pdraw = psc->driScreen->createDrawable(psc, pixmap, xid, config);
if (pdraw == NULL) {
fprintf(stderr, "failed to create pixmap\n");
+ xid = None;
break;
}
- if (__glxHashInsert(priv->drawHash, req->glxpixmap, pdraw)) {
+ if (__glxHashInsert(priv->drawHash, xid, pdraw)) {
(*pdraw->destroyDrawable) (pdraw);
- return None; /* FIXME: Check what we're supposed to do here... */
+ xid = None;
+ break;
}
} while (0);
+
+ if (xid == None) {
+ xGLXDestroyGLXPixmapReq *dreq;
+ LockDisplay(dpy);
+ GetReq(GLXDestroyGLXPixmap, dreq);
+ dreq->reqType = opcode;
+ dreq->glxCode = X_GLXDestroyGLXPixmap;
+ dreq->glxpixmap = xid;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ }
#endif
return xid;
UnlockDisplay(dpy);
SyncHandle();
+ DestroyGLXDrawable(dpy, glxpixmap);
+
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
{
struct glx_display *const priv = __glXInitialize(dpy);
glXSwapBuffers(Display * dpy, GLXDrawable drawable)
{
#ifdef GLX_USE_APPLEGL
- GLXContext gc = glXGetCurrentContext();
+ struct glx_context * gc = __glXGetCurrentContext();
if(gc && apple_glx_is_current_drawable(dpy, gc->driContext, drawable)) {
apple_glx_swap_buffers(gc->driContext);
} else {
struct glx_context *gc;
GLXContextTag tag;
CARD8 opcode;
-#ifdef USE_XCB
xcb_connection_t *c;
-#else
- xGLXSwapBuffersReq *req;
-#endif
+
+ gc = __glXGetCurrentContext();
#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
- __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
+ {
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
- if (pdraw != NULL) {
- glFlush();
- (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0);
- return;
+ if (pdraw != NULL) {
+ Bool flush = gc && drawable == gc->currentDrawable;
+
+ (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0, flush);
+ return;
+ }
}
#endif
** The calling thread may or may not have a current context. If it
** does, send the context tag so the server can do a flush.
*/
- gc = __glXGetCurrentContext();
if ((gc != NULL) && (dpy == gc->currentDpy) &&
((drawable == gc->currentDrawable)
|| (drawable == gc->currentReadable))) {
tag = 0;
}
-#ifdef USE_XCB
c = XGetXCBConnection(dpy);
xcb_glx_swap_buffers(c, tag, drawable);
xcb_flush(c);
-#else
- /* Send the glXSwapBuffers request */
- LockDisplay(dpy);
- GetReq(GLXSwapBuffers, req);
- req->reqType = opcode;
- req->glxCode = X_GLXSwapBuffers;
- req->drawable = drawable;
- req->contextTag = tag;
- UnlockDisplay(dpy);
- SyncHandle();
- XFlush(dpy);
-#endif /* USE_XCB */
#endif /* GLX_USE_APPLEGL */
}
/* Test that all bits from a are contained in b */
#define MATCH_MASK(param) \
do { \
- if ((a->param & ~b->param) != 0) \
+ if ( ((int) a-> param != (int) GLX_DONT_CARE) \
+ && ((a->param & ~b->param) != 0) ) { \
return False; \
+ } \
} while (0);
/**
&visualTemplate, &i);
if (newList) {
- Xfree(visualList);
+ free(visualList);
visualList = newList;
best_config = config;
}
char *ext_str = __glXGetClientGLExtensionString();
int size = strlen(ext_str) + 1;
-#ifdef USE_XCB
xcb_connection_t *c = XGetXCBConnection(dpy);
xcb_glx_client_info(c,
GLX_MAJOR_VERSION, GLX_MINOR_VERSION, size, ext_str);
-#else
- xGLXClientInfoReq *req;
- /* Send the glXClientInfo request */
- LockDisplay(dpy);
- GetReq(GLXClientInfo, req);
- req->reqType = opcode;
- req->glxCode = X_GLXClientInfo;
- req->major = GLX_MAJOR_VERSION;
- req->minor = GLX_MINOR_VERSION;
-
- req->length += (size + 3) >> 2;
- req->numbytes = size;
- Data(dpy, ext_str, size);
-
- UnlockDisplay(dpy);
- SyncHandle();
-#endif /* USE_XCB */
-
- Xfree(ext_str);
+ free(ext_str);
}
glXImportContextEXT(Display *dpy, GLXContextID contextID)
{
struct glx_display *priv = __glXInitialize(dpy);
- struct glx_screen *psc;
+ struct glx_screen *psc = NULL;
xGLXQueryContextReply reply;
CARD8 opcode;
struct glx_context *ctx;
- int propList[__GLX_MAX_CONTEXT_PROPS * 2], *pProp, nPropListBytes;
+
+ /* This GLX implementation knows about 5 different properties, so
+ * allow the server to send us one of each.
+ */
+ int propList[5 * 2], *pProp, nPropListBytes;
+ int numProps;
int i, renderType;
XID share;
struct glx_config *mode;
+ uint32_t fbconfigID = 0;
+ uint32_t visualID = 0;
+ uint32_t screen = 0;
+ Bool got_screen = False;
+
+ /* The GLX_EXT_import_context spec says:
+ *
+ * "If <contextID> does not refer to a valid context, then a BadContext
+ * error is generated; if <contextID> refers to direct rendering
+ * context then no error is generated but glXImportContextEXT returns
+ * NULL."
+ *
+ * If contextID is None, generate BadContext on the client-side. Other
+ * sorts of invalid contexts will be detected by the server in the
+ * __glXIsDirect call.
+ */
+ if (contextID == None) {
+ __glXSendError(dpy, GLXBadContext, contextID, X_GLXIsDirect, false);
+ return NULL;
+ }
- if (contextID == None || __glXIsDirect(dpy, contextID))
+ if (__glXIsDirect(dpy, contextID))
return NULL;
opcode = __glXSetupForCommand(dpy);
UnlockDisplay(dpy);
SyncHandle();
- /* Look up screen first so we can look up visuals/fbconfigs later */
- psc = NULL;
- for (i = 0, pProp = propList; i < reply.n; i++, pProp += 2)
- if (pProp[0] == GLX_SCREEN)
- psc = GetGLXScreenConfigs(dpy, pProp[1]);
- if (psc == NULL)
- return NULL;
-
+ numProps = nPropListBytes / (2 * sizeof(propList[0]));
share = None;
mode = NULL;
renderType = 0;
pProp = propList;
- for (i = 0, pProp = propList; i < reply.n; i++, pProp += 2)
+ for (i = 0, pProp = propList; i < numProps; i++, pProp += 2)
switch (pProp[0]) {
+ case GLX_SCREEN:
+ screen = pProp[1];
+ got_screen = True;
+ break;
case GLX_SHARE_CONTEXT_EXT:
share = pProp[1];
break;
case GLX_VISUAL_ID_EXT:
- mode = glx_config_find_visual(psc->visuals, pProp[1]);
+ visualID = pProp[1];
break;
case GLX_FBCONFIG_ID:
- mode = glx_config_find_fbconfig(psc->configs, pProp[1]);
+ fbconfigID = pProp[1];
break;
case GLX_RENDER_TYPE:
renderType = pProp[1];
break;
}
+ if (!got_screen)
+ return NULL;
+
+ psc = GetGLXScreenConfigs(dpy, screen);
+ if (psc == NULL)
+ return NULL;
+
+ if (fbconfigID != 0) {
+ mode = glx_config_find_fbconfig(psc->configs, fbconfigID);
+ } else if (visualID != 0) {
+ mode = glx_config_find_visual(psc->visuals, visualID);
+ }
+
if (mode == NULL)
return NULL;
{
struct glx_context *ctx = (struct glx_context *) ctx_user;
- return ctx->xid;
+ return (ctx == NULL) ? None : ctx->xid;
}
_X_EXPORT void
-glXFreeContextEXT(Display * dpy, GLXContext ctx)
+glXFreeContextEXT(Display *dpy, GLXContext ctx)
{
- DestroyContext(dpy, ctx);
-}
+ struct glx_context *gc = (struct glx_context *) ctx;
+ if (gc == NULL || gc->xid == None)
+ return;
+
+ /* The GLX_EXT_import_context spec says:
+ *
+ * "glXFreeContext does not free the server-side context information or
+ * the XID associated with the server-side context."
+ *
+ * Don't send any protocol. Just destroy the client-side tracking of the
+ * context. Also, only release the context structure if it's not current.
+ */
+ __glXLock();
+ if (gc->currentDpy) {
+ gc->xid = None;
+ } else {
+ gc->vtable->destroy(gc);
+ }
+ __glXUnlock();
+}
_X_EXPORT GLXFBConfig *
glXChooseFBConfig(Display * dpy, int screen,
if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) {
list_size = choose_visual(config_list, list_size, attribList, GL_TRUE);
if (list_size == 0) {
- XFree(config_list);
+ free(config_list);
config_list = NULL;
}
}
}
}
- config_list = Xmalloc(num_configs * sizeof *config_list);
+ config_list = malloc(num_configs * sizeof *config_list);
if (config_list != NULL) {
*nelements = num_configs;
i = 0;
struct glx_display *priv;
struct glx_screen *psc = NULL;
- if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) != Success)
+ if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) == Success)
&& __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)
&& (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) {
return (GLXFBConfigSGIX) glx_config_find_visual(psc->configs,
#ifdef GLX_DIRECT_RENDERING
if (psc->driScreen && psc->driScreen->swapBuffers)
return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor,
- remainder);
+ remainder, False);
#endif
return -1;
if (pdraw != NULL) {
struct glx_screen *psc = pdraw->psc;
if (psc->driScreen->copySubBuffer != NULL) {
- glFlush();
- (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height);
+ (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height, True);
}
return;
__glXstrdup(const char *str)
{
char *copy;
- copy = (char *) Xmalloc(strlen(str) + 1);
+ copy = malloc(strlen(str) + 1);
if (!copy)
return NULL;
strcpy(copy, str);
GLX_FUNCTION(glXGetDriverConfig),
#endif
+ /*** GLX_ARB_create_context and GLX_ARB_create_context_profile ***/
+ GLX_FUNCTION(glXCreateContextAttribsARB),
+
{NULL, NULL} /* end of list */
};
-#ifndef GLX_USE_APPLEGL
static const GLvoid *
get_glx_proc_address(const char *funcName)
{
return NULL;
}
-#endif
/**
* Get the address of a named GL function. This is the pre-GLX 1.4 name for
* DRI based drivers from searching the core GL function table for
* internal API functions.
*/
-#ifdef GLX_USE_APPLEGL
- f = (gl_function) apple_glx_get_proc_address(procName);
-#else
f = (gl_function) get_glx_proc_address((const char *) procName);
if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l')
&& (procName[2] != 'X')) {
- f = (gl_function) _glapi_get_proc_address((const char *) procName);
- }
+#ifdef GLX_SHARED_GLAPI
+ f = (gl_function) __indirect_get_proc_address((const char *) procName);
#endif
+ if (!f)
+ f = (gl_function) _glapi_get_proc_address((const char *) procName);
+ if (!f) {
+ struct glx_context *gc = __glXGetCurrentContext();
+
+ if (gc != NULL && gc->vtable->get_proc_address != NULL)
+ f = gc->vtable->get_proc_address((const char *) procName);
+ }
+ }
return f;
}