#ifdef GLX_DIRECT_RENDERING
#include <OpenGL/OpenGL.h>
#include <OpenGL/CGLContext.h>
#include <unistd.h>
#include <Xlibint.h>
#include <extensions/Xext.h>
#include <extensions/extutil.h>
#include "glxclient.h"
#include "appledri.h"
#include "dri_driver.h"
#include "x-list.h"
#include "x-hash.h"
static Bool driMesaBindContext(Display *dpy, int scrn,
GLXDrawable draw, GLXContext gc);
static Bool driMesaUnbindContext(Display *dpy, int scrn,
GLXDrawable draw, GLXContext gc,
int will_rebind);
static void *driMesaCreateDrawable(Display *dpy, int scrn, GLXDrawable draw,
VisualID vid, __DRIdrawable *pdraw);
static __DRIdrawable *driMesaGetDrawable(Display *dpy, GLXDrawable draw,
void *screenPrivate);
static void driMesaSwapBuffers(Display *dpy, void *drawPrivate);
static void driMesaDestroyDrawable(Display *dpy, void *drawPrivate);
static void *driMesaCreateContext(Display *dpy, XVisualInfo *vis, void *shared,
__DRIcontext *pctx);
static void driMesaDestroyContext(Display *dpy, int scrn, void *screenPrivate);
static void *driMesaCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config);
static void driMesaDestroyScreen(Display *dpy, int scrn, void *screenPrivate);
static void driMesaCreateSurface(Display *dpy, int scrn,
__DRIdrawablePrivate *pdp);
static void unwrap_context (__DRIcontextPrivate *pcp);
static void wrap_context (__DRIcontextPrivate *pcp);
extern CGLContextObj XAppleDRIGetIndirectContext (void);
static inline Bool
__driMesaAddDrawable(x_hash_table *drawHash, __DRIdrawable *pdraw)
{
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
assert (drawHash != NULL);
x_hash_table_insert (drawHash, (void *) pdp->draw, pdraw);
return GL_TRUE;
}
static inline __DRIdrawable *
__driMesaFindDrawable(x_hash_table *drawHash, GLXDrawable draw)
{
if (drawHash == NULL)
return NULL;
return x_hash_table_lookup (drawHash, (void *) draw, NULL);
}
struct find_by_uid_closure {
unsigned int uid;
__DRIdrawable *ret;
};
static void
find_by_uid_cb (void *k, void *v, void *data)
{
__DRIdrawable *pdraw = v;
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
struct find_by_uid_closure *c = data;
if (pdp->uid == c->uid)
c->ret = pdraw;
}
static __DRIdrawable *
__driMesaFindDrawableByUID (x_hash_table *drawHash, unsigned int uid)
{
struct find_by_uid_closure c;
c.uid = uid;
c.ret = NULL;
x_hash_table_foreach (drawHash, find_by_uid_cb, &c);
return c.ret;
}
static inline void
__driMesaRemoveDrawable(x_hash_table *drawHash, __DRIdrawable *pdraw)
{
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
if (drawHash == NULL)
return;
x_hash_table_remove (drawHash, (void *) pdp->draw);
}
static Bool __driMesaWindowExistsFlag;
static int __driMesaWindowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
{
if (xerr->error_code == BadWindow) {
__driMesaWindowExistsFlag = GL_FALSE;
}
return 0;
}
static Bool __driMesaWindowExists(Display *dpy, GLXDrawable draw)
{
XWindowAttributes xwa;
int (*oldXErrorHandler)(Display *, XErrorEvent *);
__driMesaWindowExistsFlag = GL_TRUE;
oldXErrorHandler = XSetErrorHandler(__driMesaWindowExistsErrorHandler);
XGetWindowAttributes(dpy, draw, &xwa);
XSetErrorHandler(oldXErrorHandler);
return __driMesaWindowExistsFlag;
}
static void __driMesaCollectCallback (void *k, void *v, void *data)
{
GLXDrawable draw = (GLXDrawable) k;
__DRIdrawable *pdraw = v;
x_list **todelete = data;
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
Display *dpy;
dpy = pdp->driScreenPriv->display;
XSync(dpy, GL_FALSE);
if (!pdp->destroyed && !__driMesaWindowExists(dpy, draw)) {
pdp->destroyed = TRUE;
*todelete = x_list_prepend (*todelete, pdraw);
}
}
static void __driMesaGarbageCollectDrawables(void *drawHash)
{
__DRIdrawable *pdraw;
__DRIdrawablePrivate *pdp;
Display *dpy;
x_list *todelete = NULL, *node;
x_hash_table_foreach (drawHash, __driMesaCollectCallback, &todelete);
for (node = todelete; node != NULL; node = node->next)
{
pdraw = node->data;
pdp = (__DRIdrawablePrivate *)pdraw->private;
dpy = pdp->driScreenPriv->display;
__driMesaRemoveDrawable(drawHash, pdraw);
(*pdraw->destroyDrawable)(dpy, pdraw->private);
Xfree(pdraw);
}
x_list_free (todelete);
}
static Bool
driMesaFindDrawableByUID (Display *dpy,unsigned int uid,
__DRIscreenPrivate **psp_ret,
__DRIdrawablePrivate **pdp_ret)
{
__DRIscreen *pDRIScreen;
__DRIscreenPrivate *psp;
__DRIdrawable *pdraw;
int scrn;
for (scrn = 0; scrn < ScreenCount (dpy); scrn++)
{
if (!(pDRIScreen = __glXFindDRIScreen(dpy, scrn))) {
return FALSE;
} else if (!(psp = (__DRIscreenPrivate *)pDRIScreen->private)) {
return FALSE;
}
pthread_mutex_lock (&psp->mutex);
pdraw = __driMesaFindDrawableByUID (psp->drawHash, uid);
if (pdraw != NULL) {
*psp_ret = psp;
*pdp_ret = pdraw->private;
return TRUE;
};
pthread_mutex_unlock (&psp->mutex);
}
return FALSE;
}
static void
unbind_context (__DRIcontextPrivate *pcp)
{
if (pcp->driDrawablePriv != NULL)
{
if (pcp->next != NULL)
pcp->next->prev = pcp->prev;
if (pcp->prev != NULL)
pcp->prev->next = pcp->next;
if (pcp->driDrawablePriv->driContextPriv == pcp)
pcp->driDrawablePriv->driContextPriv = pcp->next;
pcp->driDrawablePriv = NULL;
pcp->prev = pcp->next = NULL;
}
if (pcp->surface_id != 0)
{
pcp->surface_id = 0;
pcp->pending_clear = TRUE;
}
}
static void
unbind_drawable (__DRIdrawablePrivate *pdp)
{
__DRIcontextPrivate *pcp, *next;
for (pcp = pdp->driContextPriv; pcp != NULL; pcp = next)
{
next = pcp->next;
unbind_context (pcp);
}
}
static void
update_context (__DRIcontextPrivate *pcp)
{
if (pcp->pending_clear)
{
CGLClearDrawable (pcp->ctx);
pcp->pending_clear = FALSE;
}
if (pcp->pending_update && pcp->surface_id != 0)
{
xp_update_gl_context (pcp->ctx);
pcp->pending_update = FALSE;
}
}
static Bool driMesaUnbindContext(Display *dpy, int scrn,
GLXDrawable draw, GLXContext gc,
int will_rebind)
{
__DRIscreen *pDRIScreen;
__DRIcontextPrivate *pcp;
__DRIscreenPrivate *psp;
__DRIdrawablePrivate *pdp;
if (gc == NULL || draw == None) {
return GL_FALSE;
}
if (!(pDRIScreen = __glXFindDRIScreen(dpy, scrn))) {
return GL_FALSE;
} else if (!(psp = (__DRIscreenPrivate *)pDRIScreen->private)) {
return GL_FALSE;
}
pthread_mutex_lock (&psp->mutex);
pcp = (__DRIcontextPrivate *)gc->driContext.private;
pdp = pcp->driDrawablePriv;
if (pdp == NULL) {
pthread_mutex_unlock (&psp->mutex);
return GL_FALSE;
}
CGLSetCurrentContext (XAppleDRIGetIndirectContext ());
pcp->thread_id = 0;
unbind_context (pcp);
if (pdp->refcount == 0) {
pthread_mutex_unlock (&psp->mutex);
return GL_FALSE;
} else if (--pdp->refcount == 0) {
#if 0
__driMesaRemoveDrawable(psp->drawHash, pdraw);
(*pdraw->destroyDrawable)(dpy, pdraw->private);
Xfree(pdraw);
#endif
}
pthread_mutex_unlock (&psp->mutex);
return GL_TRUE;
}
static Bool driMesaBindContext(Display *dpy, int scrn,
GLXDrawable draw, GLXContext gc)
{
__DRIscreen *pDRIScreen;
__DRIdrawable *pdraw;
__DRIdrawablePrivate *pdp;
__DRIscreenPrivate *psp;
__DRIcontextPrivate *pcp;
if (gc == NULL || draw == None) {
return GL_FALSE;
}
if (!(pDRIScreen = __glXFindDRIScreen(dpy, scrn))) {
return GL_FALSE;
} else if (!(psp = (__DRIscreenPrivate *)pDRIScreen->private)) {
return GL_FALSE;
}
pthread_mutex_lock (&psp->mutex);
pdraw = __driMesaFindDrawable(psp->drawHash, draw);
if (!pdraw) {
pdraw = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
if (!pdraw) {
pthread_mutex_unlock (&psp->mutex);
return GL_FALSE;
}
pdraw->private = driMesaCreateDrawable(dpy, scrn, draw, gc->vid,
pdraw);
if (!pdraw->private) {
Xfree(pdraw);
pthread_mutex_unlock (&psp->mutex);
return GL_FALSE;
}
if (!__driMesaAddDrawable(psp->drawHash, pdraw)) {
(*pdraw->destroyDrawable)(dpy, pdraw->private);
Xfree(pdraw);
pthread_mutex_unlock (&psp->mutex);
return GL_FALSE;
}
}
pdp = (__DRIdrawablePrivate *)pdraw->private;
pcp = (__DRIcontextPrivate *)gc->driContext.private;
if (pdp->surface_id == 0)
{
driMesaCreateSurface (dpy, scrn, pdp);
}
unbind_context (pcp);
pcp->driDrawablePriv = pdp;
pcp->prev = NULL;
pcp->next = pdp->driContextPriv;
pdp->driContextPriv = pcp;
pdp->refcount++;
if (pcp->surface_id != pdp->surface_id)
{
pcp->surface_id = 0;
unwrap_context (pcp);
if (pdp->surface_id == 0)
CGLClearDrawable (pcp->ctx);
else if (xp_attach_gl_context (pcp->ctx, pdp->surface_id) == Success)
pcp->surface_id = pdp->surface_id;
else
fprintf (stderr, "failed to bind to surface\n");
wrap_context (pcp);
pcp->pending_clear = FALSE;
pcp->pending_update = FALSE;
}
else if (pcp->pending_clear)
{
CGLClearDrawable (pcp->ctx);
pcp->pending_clear = FALSE;
}
CGLSetCurrentContext (pcp->ctx);
pcp->thread_id = xthread_self ();
pthread_mutex_unlock (&psp->mutex);
return GL_TRUE;
}
static xp_client_id
get_client_id (void)
{
static xp_client_id id;
if (id == 0)
{
if (xp_init (XP_IN_BACKGROUND) != Success
|| xp_get_client_id (&id) != Success)
{
return 0;
}
}
return id;
}
static void driMesaCreateSurface(Display *dpy, int scrn,
__DRIdrawablePrivate *pdp)
{
xp_client_id client_id;
unsigned int key[2];
pdp->surface_id = 0;
pdp->uid = 0;
client_id = get_client_id ();
if (client_id == 0)
return;
if (XAppleDRICreateSurface (dpy, scrn, pdp->draw,
client_id, key, &pdp->uid))
{
xp_import_surface (key, &pdp->surface_id);
}
}
static void *driMesaCreateDrawable(Display *dpy, int scrn, GLXDrawable draw,
VisualID vid, __DRIdrawable *pdraw)
{
__DRIscreen *pDRIScreen;
__DRIscreenPrivate *psp;
__DRIdrawablePrivate *pdp;
pdp = (__DRIdrawablePrivate *)Xmalloc(sizeof(__DRIdrawablePrivate));
if (!pdp) {
return NULL;
}
pdp->draw = draw;
pdp->refcount = 0;
pdp->surface_id = 0;
pdp->uid = 0;
pdp->destroyed = FALSE;
if (!(pDRIScreen = __glXFindDRIScreen(dpy, scrn))) {
Xfree(pdp);
return NULL;
} else if (!(psp = (__DRIscreenPrivate *)pDRIScreen->private)) {
Xfree(pdp);
return NULL;
}
pdp->driScreenPriv = psp;
pdp->driContextPriv = NULL;
driMesaCreateSurface (dpy, scrn, pdp);
if (pdp->surface_id == 0) {
Xfree (pdp);
return NULL;
}
pdraw->destroyDrawable = driMesaDestroyDrawable;
pdraw->swapBuffers = driMesaSwapBuffers;
return (void *)pdp;
}
static __DRIdrawable *driMesaGetDrawable(Display *dpy, GLXDrawable draw,
void *screenPrivate)
{
__DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
__DRIdrawable *dri_draw;
pthread_mutex_lock (&psp->mutex);
dri_draw = __driMesaFindDrawable(psp->drawHash, draw);
pthread_mutex_unlock (&psp->mutex);
return dri_draw;
}
static void driMesaSwapBuffers(Display *dpy, void *drawPrivate)
{
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawPrivate;
__DRIcontextPrivate *pcp;
xthread_t self = xthread_self ();
static Bool warned;
pthread_mutex_lock (&pdp->driScreenPriv->mutex);
for (pcp = pdp->driContextPriv; pcp != NULL; pcp = pcp->next)
{
if (pcp->thread_id == self || pcp->thread_id == 0)
break;
}
if (pcp != NULL)
{
CGLFlushDrawable (pcp->ctx);
}
else
{
if (!warned) {
fprintf (stderr, "glXSwapBuffers: no context for this drawable\n");
warned = TRUE;
}
}
pthread_mutex_unlock (&pdp->driScreenPriv->mutex);
}
static void driMesaDestroyDrawable(Display *dpy, void *drawPrivate)
{
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawPrivate;
if (pdp) {
unbind_drawable (pdp);
if (pdp->surface_id != 0) {
xp_destroy_surface (pdp->surface_id);
pdp->surface_id = 0;
}
if (!pdp->destroyed) {
XAppleDRIDestroySurface(dpy, pdp->driScreenPriv->myNum, pdp->draw);
}
Xfree(pdp);
}
}
static CGLPixelFormatObj
driCreatePixelFormat (Display *dpy, __DRIscreenPrivate *psp,
XVisualInfo *visinfo, __GLXvisualConfig *config)
{
int i;
CGLPixelFormatAttribute attr[64]; CGLPixelFormatObj result;
GLint n_formats;
i = 0;
if (!config->rgba)
return NULL;
if (config->stereo)
attr[i++] = kCGLPFAStereo;
if (config->doubleBuffer)
attr[i++] = kCGLPFADoubleBuffer;
attr[i++] = kCGLPFAColorSize;
attr[i++] = config->redSize + config->greenSize + config->blueSize;
attr[i++] = kCGLPFAAlphaSize;
attr[i++] = 1;
if (config->accumRedSize + config->accumGreenSize
+ config->accumBlueSize + config->accumAlphaSize > 0)
{
attr[i++] = kCGLPFAAccumSize;
attr[i++] = (config->accumRedSize + config->accumGreenSize
+ config->accumBlueSize + config->accumAlphaSize);
}
if (config->depthSize > 0) {
attr[i++] = kCGLPFADepthSize;
attr[i++] = config->depthSize;
}
if (config->stencilSize > 0) {
attr[i++] = kCGLPFAStencilSize;
attr[i++] = config->stencilSize;
}
if (config->auxBuffers > 0) {
attr[i++] = kCGLPFAAuxBuffers;
attr[i++] = config->auxBuffers;
}
attr[i++] = 0;
result = NULL;
CGLChoosePixelFormat(attr, &result, &n_formats);
return result;
}
static void *driMesaCreateContext(Display *dpy, XVisualInfo *vis, void *shared,
__DRIcontext *pctx)
{
__DRIscreen *pDRIScreen;
__DRIcontextPrivate *pcp;
__DRIcontextPrivate *pshare = (__DRIcontextPrivate *)shared;
__DRIscreenPrivate *psp;
int i;
if (!(pDRIScreen = __glXFindDRIScreen(dpy, vis->screen))) {
return NULL;
} else if (!(psp = (__DRIscreenPrivate *)pDRIScreen->private)) {
return NULL;
}
if (!psp->drawHash) {
pthread_mutex_lock (&psp->mutex);
if (!psp->drawHash)
psp->drawHash = x_hash_table_new (NULL, NULL, NULL, NULL);
pthread_mutex_unlock (&psp->mutex);
}
pcp = (__DRIcontextPrivate *)Xmalloc(sizeof(__DRIcontextPrivate));
if (!pcp) {
return NULL;
}
pcp->display = dpy;
pcp->driScreenPriv = psp;
pcp->driDrawablePriv = NULL;
pcp->ctx = NULL;
pcp->surface_id = 0;
pcp->pending_clear = FALSE;
pcp->pending_update = FALSE;
pcp->ctx = NULL;
for (i = 0; pcp->ctx == NULL && i < psp->numVisuals; i++) {
if (psp->visuals[i].vid == vis->visualid) {
CGLCreateContext (psp->visuals[i].pixel_format,
pshare ? pshare->ctx : NULL, &pcp->ctx);
}
}
if (!pcp->ctx) {
Xfree(pcp);
return NULL;
}
pctx->destroyContext = driMesaDestroyContext;
pctx->bindContext = driMesaBindContext;
pctx->unbindContext = driMesaUnbindContext;
wrap_context (pcp);
pthread_mutex_lock (&psp->mutex);
__driMesaGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
pthread_mutex_unlock (&psp->mutex);
return pcp;
}
static void driMesaDestroyContext(Display *dpy, int scrn, void *contextPrivate)
{
__DRIcontextPrivate *pcp = (__DRIcontextPrivate *) contextPrivate;
if (pcp) {
pthread_mutex_lock (&pcp->driScreenPriv->mutex);
unbind_context (pcp);
__driMesaGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
pthread_mutex_unlock (&pcp->driScreenPriv->mutex);
CGLDestroyContext (pcp->ctx);
Xfree(pcp);
}
}
static void *driMesaCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config)
{
int directCapable, i, n;
__DRIscreenPrivate *psp;
XVisualInfo visTmpl, *visinfo;
pthread_mutexattr_t attr;
if (!XAppleDRIQueryDirectRenderingCapable(dpy, scrn, &directCapable)) {
return NULL;
}
if (!directCapable) {
return NULL;
}
psp = (__DRIscreenPrivate *)Xmalloc(sizeof(__DRIscreenPrivate));
if (!psp) {
return NULL;
}
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init (&psp->mutex, &attr);
pthread_mutexattr_destroy (&attr);
psp->display = dpy;
psp->myNum = scrn;
#if 0
if (!XAppleDRIAuthConnection(dpy, scrn, magic)) {
Xfree(psp);
(void)XAppleDRICloseConnection(dpy, scrn);
return NULL;
}
#endif
psp->visuals = (__DRIvisualPrivate *)Xmalloc(numConfigs *
sizeof(__DRIvisualPrivate));
if (!psp->visuals) {
Xfree(psp);
return NULL;
}
visTmpl.screen = scrn;
visinfo = XGetVisualInfo(dpy, VisualScreenMask, &visTmpl, &n);
if (n != numConfigs) {
Xfree(psp);
return NULL;
}
psp->numVisuals = 0;
for (i = 0; i < numConfigs; i++, config++) {
psp->visuals[psp->numVisuals].vid = visinfo[i].visualid;
psp->visuals[psp->numVisuals].pixel_format =
driCreatePixelFormat (dpy, psp, &visinfo[i], config);
if (psp->visuals[psp->numVisuals].pixel_format != NULL) {
psp->numVisuals++;
}
}
XFree(visinfo);
if (psp->numVisuals == 0) {
Xfree(psp->visuals);
Xfree(psp);
return NULL;
}
psp->drawHash = NULL;
psc->destroyScreen = driMesaDestroyScreen;
psc->createContext = driMesaCreateContext;
psc->createDrawable = driMesaCreateDrawable;
psc->getDrawable = driMesaGetDrawable;
return (void *)psp;
}
static void driMesaDestroyScreen(Display *dpy, int scrn, void *screenPrivate)
{
__DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
if (psp) {
Xfree(psp->visuals);
Xfree(psp);
}
}
static void driAppleSurfaceNotify (Display *dpy, unsigned int uid, int kind)
{
__DRIscreenPrivate *psp;
__DRIdrawablePrivate *pdp;
__DRIcontextPrivate *pcp;
if (driMesaFindDrawableByUID (dpy, uid, &psp, &pdp))
{
xthread_t self = xthread_self ();
switch (kind)
{
Bool all_safe;
case AppleDRISurfaceNotifyDestroyed:
xp_destroy_surface (pdp->surface_id);
pdp->surface_id = 0;
for (pcp = pdp->driContextPriv; pcp != NULL; pcp = pcp->next)
{
pcp->surface_id = 0;
if (pcp->thread_id == self || pcp->thread_id == 0) {
CGLClearDrawable (pcp->ctx);
pcp->pending_clear = FALSE;
} else
pcp->pending_clear = TRUE;
}
break;
case AppleDRISurfaceNotifyChanged:
all_safe = TRUE;
for (pcp = pdp->driContextPriv; pcp != NULL; pcp = pcp->next)
{
if (pcp->thread_id != 0 && pcp->thread_id != self) {
all_safe = FALSE;
break;
}
}
for (pcp = pdp->driContextPriv; pcp != NULL; pcp = pcp->next)
{
if (all_safe) {
xp_update_gl_context (pcp->ctx);
pcp->pending_update = FALSE;
} else
pcp->pending_update = TRUE;
}
break;
}
pthread_mutex_unlock (&psp->mutex);
}
}
void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config)
{
static int here_before;
if (!here_before)
{
XAppleDRISetSurfaceNotifyHandler (driAppleSurfaceNotify);
here_before = True;
}
return driMesaCreateScreen(dpy, scrn, psc, numConfigs, config);
}
void __driRegisterExtensions (void)
{
}
__private_extern__ void XAppleDRIUseIndirectDispatch (void)
{
CGLSetCurrentContext (XAppleDRIGetIndirectContext ());
}
#define WRAP_CGL(context, vec, fun) \
do { \
(context)->disp.vec = (context)->ctx->disp.vec; \
(context)->ctx->disp.vec = (fun); \
} while (0)
#define UNWRAP_CGL(context, vec) \
do { \
(context)->ctx->disp.vec = (context)->disp.vec; \
} while (0)
#define WRAP_BOILERPLATE \
GLXContext gc; \
__DRIcontextPrivate *pcp; \
gc = __glXGetCurrentContext (); \
if (gc == NULL || !gc->isDirect) return; \
pcp = (__DRIcontextPrivate *) gc->driContext.private; \
if (pcp == NULL) return;
static void viewport_callback (GLIContext ctx, GLint x, GLint y,
GLsizei width, GLsizei height)
{
WRAP_BOILERPLATE
pthread_mutex_lock (&pcp->driScreenPriv->mutex);
update_context (pcp);
pthread_mutex_unlock (&pcp->driScreenPriv->mutex);
(*pcp->disp.viewport) (ctx, x, y, width, height);
}
static void new_list_callback (GLIContext ctx, GLuint list, GLenum mode)
{
WRAP_BOILERPLATE
unwrap_context (pcp);
(*pcp->ctx->disp.new_list) (ctx, list, mode);
wrap_context (pcp);
}
static void end_list_callback (GLIContext ctx)
{
WRAP_BOILERPLATE
unwrap_context (pcp);
(*pcp->ctx->disp.end_list) (ctx);
wrap_context (pcp);
}
static void unwrap_context (__DRIcontextPrivate *pcp)
{
UNWRAP_CGL (pcp, viewport);
UNWRAP_CGL (pcp, new_list);
UNWRAP_CGL (pcp, end_list);
}
static void wrap_context (__DRIcontextPrivate *pcp)
{
WRAP_CGL (pcp, new_list, new_list_callback);
WRAP_CGL (pcp, end_list, end_list_callback);
WRAP_CGL (pcp, viewport, viewport_callback);
}
#endif