#include "packrender.h"
#include <stdio.h>
#include <Xext.h>
#include <extutil.h>
#include <assert.h>
#include "indirect_init.h"
#include "glapi.h"
#ifdef XTHREADS
#include "Xthreads.h"
#endif
#include "glxextensions.h"
#include "glcontextmodes.h"
#include <assert.h>
#ifdef DEBUG
void __glXDumpDrawBuffer(__GLXcontext *ctx);
#endif
#ifdef USE_SPARC_ASM
extern unsigned int _mesa_sparc_glapi_begin;
extern unsigned int _mesa_sparc_glapi_end;
extern void __glapi_sparc_icache_flush(unsigned int *);
static void _glx_mesa_init_sparc_glapi_relocs(void);
static int _mesa_sparc_needs_init = 1;
#define INIT_MESA_SPARC { \
if(_mesa_sparc_needs_init) { \
_glx_mesa_init_sparc_glapi_relocs(); \
_mesa_sparc_needs_init = 0; \
} \
}
#else
#define INIT_MESA_SPARC
#endif
static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
GLXDrawable read, GLXContext gc);
static GLubyte dummyBuffer[__GLX_BUFFER_LIMIT_SIZE];
static __GLXcontext dummyContext = {
&dummyBuffer[0],
&dummyBuffer[0],
&dummyBuffer[0],
&dummyBuffer[__GLX_BUFFER_LIMIT_SIZE],
sizeof(dummyBuffer),
};
static __GLapi *IndirectAPI = NULL;
#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
static GLboolean TSDinitialized = GL_FALSE;
static xthread_key_t ContextTSD;
__GLXcontext *__glXGetCurrentContext(void)
{
if (!TSDinitialized) {
xthread_key_create(&ContextTSD, NULL);
TSDinitialized = GL_TRUE;
return &dummyContext;
}
else {
void *p;
xthread_get_specific(ContextTSD, &p);
if (!p)
return &dummyContext;
else
return (__GLXcontext *) p;
}
}
void __glXSetCurrentContext(__GLXcontext *c)
{
if (!TSDinitialized) {
xthread_key_create(&ContextTSD, NULL);
TSDinitialized = GL_TRUE;
}
xthread_set_specific(ContextTSD, c);
}
xmutex_rec __glXmutex;
#else
__GLXcontext *__glXcurrentContext = &dummyContext;
#endif
int __glXDebug = 0;
int __glXCloseDisplay(Display *dpy, XExtCodes *codes);
static GLboolean FillInVisuals( __GLXscreenConfigs * psc );
static char *__glXExtensionName = GLX_EXTENSION_NAME;
XExtensionInfo *__glXExtensionInfo = NULL;
static char *error_list[] = {
"GLXBadContext",
"GLXBadContextState",
"GLXBadDrawable",
"GLXBadPixmap",
"GLXBadContextTag",
"GLXBadCurrentWindow",
"GLXBadRenderRequest",
"GLXBadLargeRequest",
"GLXUnsupportedPrivateRequest",
};
int __glXCloseDisplay(Display *dpy, XExtCodes *codes)
{
GLXContext gc;
gc = __glXGetCurrentContext();
if (dpy == gc->currentDpy) {
__glXSetCurrentContext(&dummyContext);
#ifdef GLX_DIRECT_RENDERING
_glapi_set_dispatch(NULL);
#endif
__glXFreeContext(gc);
}
return XextRemoveDisplay(__glXExtensionInfo, dpy);
}
static XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
__GLX_NUMBER_ERRORS, error_list)
static XExtensionHooks __glXExtensionHooks = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
__glXCloseDisplay,
NULL,
NULL,
NULL,
__glXErrorString,
};
static
XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
__glXExtensionName, &__glXExtensionHooks,
__GLX_NUMBER_EVENTS, NULL)
static void FreeScreenConfigs(__GLXdisplayPrivate *priv)
{
__GLXscreenConfigs *psc;
GLint i, screens;
psc = priv->screenConfigs;
screens = ScreenCount(priv->dpy);
for (i = 0; i < screens; i++, psc++) {
if (psc->configs) {
Xfree((char*) psc->configs);
if(psc->effectiveGLXexts)
Xfree(psc->effectiveGLXexts);
if ( psc->old_configs != NULL ) {
Xfree( psc->old_configs );
psc->old_configs = NULL;
psc->numOldConfigs = 0;
}
psc->configs = 0;
}
#ifdef GLX_DIRECT_RENDERING
if (psc->driScreen.private)
(*psc->driScreen.destroyScreen)(priv->dpy, i,
psc->driScreen.private);
psc->driScreen.private = NULL;
#endif
}
XFree((char*) priv->screenConfigs);
}
static int __glXFreeDisplayPrivate(XExtData *extension)
{
__GLXdisplayPrivate *priv;
priv = (__GLXdisplayPrivate*) extension->private_data;
FreeScreenConfigs(priv);
if(priv->serverGLXvendor) {
Xfree((char*)priv->serverGLXvendor);
priv->serverGLXvendor = 0x0;
}
if(priv->serverGLXversion) {
Xfree((char*)priv->serverGLXversion);
priv->serverGLXversion = 0x0;
}
#if 0
if (priv->driDisplay.private)
(*priv->driDisplay.destroyDisplay)(priv->dpy,
priv->driDisplay.private);
priv->driDisplay.private = NULL;
#endif
#ifdef GLX_DIRECT_RENDERING
XFree(priv->driDisplay.createScreen);
#endif
Xfree((char*) priv);
return 0;
}
static Bool QueryVersion(Display *dpy, int opcode, int *major, int *minor)
{
xGLXQueryVersionReq *req;
xGLXQueryVersionReply reply;
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) {
return GL_FALSE;
}
*major = reply.majorVersion;
*minor = min(reply.minorVersion, GLX_MINOR_VERSION);
return GL_TRUE;
}
static GLboolean
FillInVisuals( __GLXscreenConfigs * psc )
{
int glx_visual_count;
int i;
glx_visual_count = 0;
for ( i = 0 ; i < psc->numConfigs ; i++ ) {
if ( (psc->configs[i].visualID != GLX_DONT_CARE)
&& (psc->configs[i].sampleBuffers == 0)
&& (psc->configs[i].samples == 0)
&& (psc->configs[i].drawableType == GLX_WINDOW_BIT)
&& ((psc->configs[i].xRenderable == GL_TRUE)
|| (psc->configs[i].xRenderable == GLX_DONT_CARE)) ) {
glx_visual_count++;
}
}
psc->old_configs = (__GLXvisualConfig *)
Xmalloc( sizeof( __GLXvisualConfig ) * glx_visual_count );
if ( psc->old_configs == NULL ) {
return GL_FALSE;
}
glx_visual_count = 0;
for ( i = 0 ; i < psc->numConfigs ; i++ ) {
if ( (psc->configs[i].visualID != GLX_DONT_CARE)
&& (psc->configs[i].sampleBuffers == 0)
&& (psc->configs[i].samples == 0)
&& (psc->configs[i].drawableType == GLX_WINDOW_BIT)
&& ((psc->configs[i].xRenderable == GL_TRUE)
|| (psc->configs[i].xRenderable == GLX_DONT_CARE)) ) {
#define COPY_VALUE(src_tag,dst_tag) \
psc->old_configs[glx_visual_count]. dst_tag = psc->configs[i]. src_tag
COPY_VALUE( visualID, vid );
COPY_VALUE( rgbMode, rgba );
COPY_VALUE( stereoMode, stereo );
COPY_VALUE( doubleBufferMode, doubleBuffer );
psc->old_configs[glx_visual_count].class =
_gl_convert_to_x_visual_type( psc->configs[i].visualType );
COPY_VALUE( level, level );
COPY_VALUE( numAuxBuffers, auxBuffers );
COPY_VALUE( redBits, redSize );
COPY_VALUE( greenBits, greenSize );
COPY_VALUE( blueBits, blueSize );
COPY_VALUE( alphaBits, alphaSize );
COPY_VALUE( rgbBits, bufferSize );
COPY_VALUE( accumRedBits, accumRedSize );
COPY_VALUE( accumGreenBits, accumGreenSize );
COPY_VALUE( accumBlueBits, accumBlueSize );
COPY_VALUE( accumAlphaBits, accumAlphaSize );
COPY_VALUE( depthBits, depthSize );
COPY_VALUE( stencilBits, stencilSize );
COPY_VALUE( visualRating, visualRating );
COPY_VALUE( transparentPixel, transparentPixel );
COPY_VALUE( transparentRed, transparentRed );
COPY_VALUE( transparentGreen, transparentGreen );
COPY_VALUE( transparentBlue, transparentBlue );
COPY_VALUE( transparentAlpha, transparentAlpha );
COPY_VALUE( transparentIndex, transparentIndex );
#undef COPY_VALUE
glx_visual_count++;
}
}
psc->numOldConfigs = glx_visual_count;
return GL_TRUE;
}
void
__glXInitializeVisualConfigFromTags( __GLcontextModes *config, int count,
const INT32 *bp, Bool tagged_only,
Bool fbconfig_style_tags )
{
int i;
if (!tagged_only) {
config->visualID = *bp++;
config->visualType = _gl_convert_from_x_visual_type( *bp++ );
config->rgbMode = *bp++;
config->redBits = *bp++;
config->greenBits = *bp++;
config->blueBits = *bp++;
config->alphaBits = *bp++;
config->accumRedBits = *bp++;
config->accumGreenBits = *bp++;
config->accumBlueBits = *bp++;
config->accumAlphaBits = *bp++;
config->doubleBufferMode = *bp++;
config->stereoMode = *bp++;
config->rgbBits = *bp++;
config->depthBits = *bp++;
config->stencilBits = *bp++;
config->numAuxBuffers = *bp++;
config->level = *bp++;
count -= __GLX_MIN_CONFIG_PROPS;
}
else {
config->visualID = (XID) GLX_DONT_CARE;
config->visualType = GLX_DONT_CARE;
config->rgbMode = ( fbconfig_style_tags )
? GL_TRUE
: GL_FALSE;
config->redBits = 0;
config->greenBits = 0;
config->blueBits = 0;
config->alphaBits = 0;
config->accumRedBits = 0;
config->accumGreenBits = 0;
config->accumBlueBits = 0;
config->accumAlphaBits = 0;
config->doubleBufferMode = ( fbconfig_style_tags )
? GLX_DONT_CARE
: GL_FALSE;
config->stereoMode = GL_FALSE;
config->rgbBits = 0;
config->depthBits = 0;
config->stencilBits = 0;
config->numAuxBuffers = 0;
config->level = 0;
}
config->visualRating = GLX_DONT_CARE;
config->visualSelectGroup = 0;
config->transparentPixel = GLX_NONE;
config->transparentRed = GLX_DONT_CARE;
config->transparentGreen = GLX_DONT_CARE;
config->transparentBlue = GLX_DONT_CARE;
config->transparentAlpha = GLX_DONT_CARE;
config->transparentIndex = GLX_DONT_CARE;
config->floatMode = GL_FALSE;
config->drawableType = GLX_WINDOW_BIT;
config->renderType = (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
config->xRenderable = GLX_DONT_CARE;
config->fbconfigID = (GLXFBConfigID)(GLX_DONT_CARE);
config->maxPbufferWidth = 0;
config->maxPbufferHeight = 0;
config->maxPbufferPixels = 0;
config->optimalPbufferWidth = 0;
config->optimalPbufferHeight = 0;
config->sampleBuffers = 0;
config->samples = 0;
config->swapMethod = GLX_SWAP_UNDEFINED_OML;
#define FETCH_OR_SET(tag) \
config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
for (i = 0; i < count; i += 2 ) {
switch(*bp++) {
case GLX_RGBA:
FETCH_OR_SET( rgbMode );
config->renderType = (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
break;
case GLX_BUFFER_SIZE:
config->rgbBits = *bp++;
break;
case GLX_LEVEL:
config->level = *bp++;
break;
case GLX_DOUBLEBUFFER:
FETCH_OR_SET( doubleBufferMode );
break;
case GLX_STEREO:
FETCH_OR_SET( stereoMode );
break;
case GLX_AUX_BUFFERS:
config->numAuxBuffers = *bp++;
break;
case GLX_RED_SIZE:
config->redBits = *bp++;
break;
case GLX_GREEN_SIZE:
config->greenBits = *bp++;
break;
case GLX_BLUE_SIZE:
config->blueBits = *bp++;
break;
case GLX_ALPHA_SIZE:
config->alphaBits = *bp++;
break;
case GLX_DEPTH_SIZE:
config->depthBits = *bp++;
break;
case GLX_STENCIL_SIZE:
config->stencilBits = *bp++;
break;
case GLX_ACCUM_RED_SIZE:
config->accumRedBits = *bp++;
break;
case GLX_ACCUM_GREEN_SIZE:
config->accumGreenBits = *bp++;
break;
case GLX_ACCUM_BLUE_SIZE:
config->accumBlueBits = *bp++;
break;
case GLX_ACCUM_ALPHA_SIZE:
config->accumAlphaBits = *bp++;
break;
case GLX_VISUAL_CAVEAT_EXT:
config->visualRating = *bp++;
break;
case GLX_X_VISUAL_TYPE:
config->visualType = *bp++;
break;
case GLX_TRANSPARENT_TYPE:
config->transparentPixel = *bp++;
break;
case GLX_TRANSPARENT_INDEX_VALUE:
config->transparentIndex = *bp++;
break;
case GLX_TRANSPARENT_RED_VALUE:
config->transparentRed = *bp++;
break;
case GLX_TRANSPARENT_GREEN_VALUE:
config->transparentGreen = *bp++;
break;
case GLX_TRANSPARENT_BLUE_VALUE:
config->transparentBlue = *bp++;
break;
case GLX_TRANSPARENT_ALPHA_VALUE:
config->transparentAlpha = *bp++;
break;
case GLX_VISUAL_ID:
config->visualID = *bp++;
break;
case GLX_DRAWABLE_TYPE:
config->drawableType = *bp++;
break;
case GLX_RENDER_TYPE:
config->renderType = *bp++;
break;
case GLX_X_RENDERABLE:
config->xRenderable = *bp++;
break;
case GLX_FBCONFIG_ID:
config->fbconfigID = *bp++;
break;
case GLX_MAX_PBUFFER_WIDTH:
config->maxPbufferWidth = *bp++;
break;
case GLX_MAX_PBUFFER_HEIGHT:
config->maxPbufferHeight = *bp++;
break;
case GLX_MAX_PBUFFER_PIXELS:
config->maxPbufferPixels = *bp++;
break;
case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
config->optimalPbufferWidth = *bp++;
break;
case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
config->optimalPbufferHeight = *bp++;
break;
case GLX_VISUAL_SELECT_GROUP_SGIX:
config->visualSelectGroup = *bp++;
break;
case GLX_SWAP_METHOD_OML:
config->swapMethod = *bp++;
break;
case GLX_SAMPLE_BUFFERS_SGIS:
config->sampleBuffers = *bp++;
break;
case GLX_SAMPLES_SGIS:
config->samples = *bp++;
break;
case None:
i = count;
break;
default:
break;
}
}
config->haveAccumBuffer = ((config->accumRedBits +
config->accumGreenBits +
config->accumBlueBits +
config->accumAlphaBits) > 0);
config->haveDepthBuffer = (config->depthBits > 0);
config->haveStencilBuffer = (config->stencilBits > 0);
}
static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv)
{
xGLXGetVisualConfigsReq *req;
xGLXGetFBConfigsReq *fb_req;
xGLXVendorPrivateReq *vpreq;
xGLXGetFBConfigsSGIXReq *sgi_req;
xGLXGetVisualConfigsReply reply;
__GLXscreenConfigs *psc;
__GLcontextModes *config;
GLint i, j, nprops, screens;
INT32 buf[__GLX_TOTAL_CONFIG], *props;
unsigned supported_request = 0;
unsigned prop_size;
screens = ScreenCount(dpy);
psc = (__GLXscreenConfigs*) Xmalloc(screens * sizeof(__GLXscreenConfigs));
if (!psc) {
return GL_FALSE;
}
memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
priv->screenConfigs = psc;
priv->serverGLXversion = __glXInternalQueryServerString(dpy,
priv->majorOpcode, 0, GLX_VERSION);
if ( priv->serverGLXversion == NULL ) {
FreeScreenConfigs(priv);
return GL_FALSE;
}
if ( atof( priv->serverGLXversion ) >= 1.3 ) {
supported_request = 1;
}
for (i = 0; i < screens; i++, psc++) {
if ( supported_request != 1 ) {
psc->serverGLXexts = __glXInternalQueryServerString(dpy,
priv->majorOpcode, i, GLX_EXTENSIONS);
if ( strstr( psc->serverGLXexts, "GLX_SGIX_fbconfig" ) != NULL ) {
supported_request = 2;
}
else {
supported_request = 3;
}
}
LockDisplay(dpy);
switch( supported_request ) {
case 1:
GetReq(GLXGetFBConfigs,fb_req);
fb_req->reqType = priv->majorOpcode;
fb_req->glxCode = X_GLXGetFBConfigs;
fb_req->screen = i;
break;
case 2:
GetReqExtra(GLXVendorPrivate,
sz_xGLXGetFBConfigsSGIXReq-sz_xGLXVendorPrivateReq,vpreq);
sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
sgi_req->reqType = priv->majorOpcode;
sgi_req->glxCode = X_GLXVendorPrivateWithReply;
sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
sgi_req->screen = i;
break;
case 3:
GetReq(GLXGetVisualConfigs,req);
req->reqType = priv->majorOpcode;
req->glxCode = X_GLXGetVisualConfigs;
req->screen = i;
break;
}
if (!_XReply(dpy, (xReply*) &reply, 0, False)) {
UnlockDisplay(dpy);
FreeScreenConfigs(priv);
return GL_FALSE;
}
UnlockDisplay(dpy);
if (!reply.numVisuals) {
UnlockDisplay(dpy);
continue;
}
nprops = reply.numProps;
if ((nprops < __GLX_MIN_CONFIG_PROPS) ||
(nprops > __GLX_MAX_CONFIG_PROPS)) {
UnlockDisplay(dpy);
SyncHandle();
FreeScreenConfigs(priv);
return GL_FALSE;
}
psc->configs = (__GLcontextModes*)
Xmalloc(reply.numVisuals * sizeof(__GLcontextModes));
psc->numConfigs = reply.numVisuals;
if (!psc->configs) {
UnlockDisplay(dpy);
SyncHandle();
FreeScreenConfigs(priv);
return GL_FALSE;
}
if ( supported_request != 3 ) {
nprops *= 2;
}
prop_size = nprops * __GLX_SIZE_INT32;
if (prop_size <= sizeof(buf)) {
props = buf;
} else {
props = (INT32 *) Xmalloc(prop_size);
}
config = psc->configs;
for (j = 0; j < reply.numVisuals; j++, config++) {
_XRead(dpy, (char *)props, prop_size);
__glXInitializeVisualConfigFromTags( config, nprops, props,
(supported_request != 3),
GL_TRUE );
config->screen = i;
}
if (props != buf) {
Xfree((char *)props);
}
UnlockDisplay(dpy);
#ifdef GLX_DIRECT_RENDERING
psc->ext_list_first_time = GL_TRUE;
if (priv->driDisplay.private &&
priv->driDisplay.createScreen &&
priv->driDisplay.createScreen[i]) {
if ( (psc->old_configs == NULL)
&& !FillInVisuals(psc) ) {
FreeScreenConfigs(priv);
return GL_FALSE;
}
psc->driScreen.screenConfigs = (void *)psc;
psc->driScreen.private =
(*(priv->driDisplay.createScreen[i]))(dpy, i, &psc->driScreen,
psc->numOldConfigs,
psc->old_configs);
}
#endif
}
SyncHandle();
return GL_TRUE;
}
__GLXdisplayPrivate *__glXInitialize(Display* dpy)
{
XExtDisplayInfo *info = __glXFindDisplay(dpy);
XExtData **privList, *private, *found;
__GLXdisplayPrivate *dpyPriv;
XEDataObject dataObj;
int major, minor;
#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
{
static int firstCall = 1;
if (firstCall) {
# if !defined(GLX_USE_APPLEGL)
xmutex_init(&__glXmutex);
# else
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init (&__glXmutex, &attr);
pthread_mutexattr_destroy (&attr);
# endif
firstCall = 0;
}
}
#endif
INIT_MESA_SPARC
__glXLock();
if (!XextHasExtension(info)) {
__glXUnlock();
XMissingExtension(dpy, __glXExtensionName);
return 0;
}
dataObj.display = dpy;
privList = XEHeadOfExtensionList(dataObj);
found = XFindOnExtensionList(privList, info->codes->extension);
if (found) {
__glXUnlock();
return (__GLXdisplayPrivate *) found->private_data;
}
if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) {
__glXUnlock();
return 0;
}
private = (XExtData *) Xmalloc(sizeof(XExtData));
if (!private) {
__glXUnlock();
return 0;
}
dpyPriv = (__GLXdisplayPrivate *) Xmalloc(sizeof(__GLXdisplayPrivate));
if (!dpyPriv) {
__glXUnlock();
Xfree((char*) private);
return 0;
}
dpyPriv->majorOpcode = info->codes->major_opcode;
dpyPriv->majorVersion = major;
dpyPriv->minorVersion = minor;
dpyPriv->dpy = dpy;
dpyPriv->serverGLXvendor = 0x0;
dpyPriv->serverGLXversion = 0x0;
#ifdef GLX_DIRECT_RENDERING
if (getenv("LIBGL_ALWAYS_INDIRECT")) {
dpyPriv->driDisplay.private = 0;
dpyPriv->driDisplay.destroyDisplay = 0;
dpyPriv->driDisplay.createScreen = 0;
}
else {
dpyPriv->driDisplay.private =
driCreateDisplay(dpy, &dpyPriv->driDisplay);
}
#endif
if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
__glXUnlock();
Xfree((char*) dpyPriv);
Xfree((char*) private);
return 0;
}
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);
}
__glXUnlock();
return dpyPriv;
}
CARD8 __glXSetupForCommand(Display *dpy)
{
GLXContext gc;
__GLXdisplayPrivate *priv;
gc = __glXGetCurrentContext();
if (gc->currentDpy) {
(void) __glXFlushRenderBuffer(gc, gc->pc);
if (gc->currentDpy == dpy) {
INIT_MESA_SPARC
return gc->majorOpcode;
} else {
}
}
priv = __glXInitialize(dpy);
if (!priv) {
return 0;
}
return priv->majorOpcode;
}
GLubyte *__glXFlushRenderBuffer(__GLXcontext *ctx, GLubyte *pc)
{
Display *dpy;
xGLXRenderReq *req;
GLint size;
if (!(dpy = ctx->currentDpy)) {
ctx->pc = ctx->buf;
return ctx->pc;
}
size = pc - ctx->buf;
if (size) {
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();
}
ctx->pc = ctx->buf;
return ctx->pc;
}
void __glXSendLargeCommand(__GLXcontext *ctx,
const GLvoid *header, GLint headerLen,
const GLvoid *data, GLint dataLen)
{
Display *dpy = ctx->currentDpy;
xGLXRenderLargeReq *req;
GLint maxSize, amount;
GLint totalRequests, requestNumber;
maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
totalRequests = 1 + (dataLen / maxSize);
if (dataLen % maxSize) totalRequests++;
assert( headerLen <= maxSize );
LockDisplay(dpy);
GetReq(GLXRenderLarge,req);
req->reqType = ctx->majorOpcode;
req->glxCode = X_GLXRenderLarge;
req->contextTag = ctx->currentContextTag;
req->length += (headerLen + 3) >> 2;
req->requestNumber = 1;
req->requestTotal = totalRequests;
req->dataBytes = headerLen;
Data(dpy, (const void *)header, headerLen);
requestNumber = 2;
while (dataLen > 0) {
amount = dataLen;
if (amount > maxSize) {
amount = maxSize;
}
GetReq(GLXRenderLarge,req);
req->reqType = ctx->majorOpcode;
req->glxCode = X_GLXRenderLarge;
req->contextTag = ctx->currentContextTag;
req->length += (amount + 3) >> 2;
req->requestNumber = requestNumber++;
req->requestTotal = totalRequests;
req->dataBytes = amount;
Data(dpy, (const void *)data, amount);
dataLen -= amount;
data = ((const char*) data) + amount;
}
UnlockDisplay(dpy);
SyncHandle();
}
GLXContext glXGetCurrentContext(void)
{
GLXContext cx = __glXGetCurrentContext();
if (cx == &dummyContext) {
return NULL;
} else {
return cx;
}
}
GLXDrawable glXGetCurrentDrawable(void)
{
GLXContext gc = __glXGetCurrentContext();
return gc->currentDrawable;
}
#ifdef GLX_DIRECT_RENDERING
__DRIscreen *__glXFindDRIScreen(Display *dpy, int scrn)
{
__DRIscreen *pDRIScreen = NULL;
XExtDisplayInfo *info = __glXFindDisplay(dpy);
XExtData **privList, *found;
__GLXdisplayPrivate *dpyPriv;
XEDataObject dataObj;
__glXLock();
dataObj.display = dpy;
privList = XEHeadOfExtensionList(dataObj);
found = XFindOnExtensionList(privList, info->codes->extension);
__glXUnlock();
if (found) {
dpyPriv = (__GLXdisplayPrivate *)found->private_data;
pDRIScreen = &dpyPriv->screenConfigs[scrn].driScreen;
}
return pDRIScreen;
}
#endif
static Bool SendMakeCurrentRequest( Display *dpy, CARD8 opcode,
GLXContextID gc, GLXContextTag old_gc, GLXDrawable draw, GLXDrawable read,
xGLXMakeCurrentReply * reply );
static Bool SendMakeCurrentRequest( Display *dpy, CARD8 opcode,
GLXContextID gc_id, GLXContextTag gc_tag,
GLXDrawable draw, GLXDrawable read,
xGLXMakeCurrentReply * reply )
{
opcode = __glXSetupForCommand(dpy);
if (!opcode) {
return GL_FALSE;
}
LockDisplay(dpy);
if ( draw == read ) {
xGLXMakeCurrentReq *req;
GetReq(GLXMakeCurrent,req);
req->reqType = opcode;
req->glxCode = X_GLXMakeCurrent;
req->drawable = draw;
req->context = gc_id;
req->oldContextTag = gc_tag;
}
else {
__GLXdisplayPrivate *priv = __glXInitialize(dpy);
if ( (priv->majorVersion > 1) || (priv->minorVersion >= 3) ) {
xGLXMakeContextCurrentReq *req;
GetReq(GLXMakeContextCurrent,req);
req->reqType = opcode;
req->glxCode = X_GLXMakeContextCurrent;
req->drawable = draw;
req->readdrawable = read;
req->context = gc_id;
req->oldContextTag = gc_tag;
}
else {
xGLXVendorPrivateWithReplyReq *vpreq;
xGLXMakeCurrentReadSGIReq *req;
GetReqExtra(GLXVendorPrivateWithReply,
sz_xGLXMakeCurrentReadSGIReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
req = (xGLXMakeCurrentReadSGIReq *)vpreq;
req->reqType = opcode;
req->glxCode = X_GLXVendorPrivateWithReply;
req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
req->drawable = draw;
req->readable = read;
req->context = gc_id;
req->oldContextTag = gc_tag;
}
}
return _XReply(dpy, (xReply*) reply, 0, False);
}
static Bool MakeContextCurrent(Display *dpy,
GLXDrawable draw, GLXDrawable read,
GLXContext gc)
{
xGLXMakeCurrentReply reply;
GLXContext oldGC;
CARD8 opcode, oldOpcode;
Bool sentRequestToOldDpy = False;
Bool bindReturnValue = True;
opcode = __glXSetupForCommand(dpy);
if (!opcode) {
return GL_FALSE;
}
if ((gc != NULL) && (gc->xid == None)) {
return GL_FALSE;
}
oldGC = __glXGetCurrentContext();
oldOpcode = (gc == oldGC) ? opcode : __glXSetupForCommand(dpy);
if (!oldOpcode) {
return GL_FALSE;
}
if ((dpy != oldGC->currentDpy || (gc && gc->isDirect)) &&
!oldGC->isDirect && oldGC != &dummyContext) {
sentRequestToOldDpy = True;
if ( ! SendMakeCurrentRequest( oldGC->currentDpy, oldOpcode, None,
oldGC->currentContextTag, None, None,
&reply ) ) {
UnlockDisplay(dpy);
SyncHandle();
return GL_FALSE;
}
oldGC->currentContextTag = 0;
}
#ifdef GLX_DIRECT_RENDERING
if (oldGC->isDirect) {
if (oldGC->driContext.private) {
if (!(*oldGC->driContext.unbindContext2)(oldGC->currentDpy,
oldGC->screen,
oldGC->currentDrawable,
oldGC->currentReadable,
oldGC)) {
return GL_FALSE;
}
}
oldGC->currentContextTag = 0;
}
if (gc && gc->isDirect) {
if (gc->driContext.private) {
bindReturnValue =
(*gc->driContext.bindContext2)(dpy, gc->screen, draw, read, gc);
}
} else {
#endif
_glapi_check_multithread();
LockDisplay(dpy);
bindReturnValue = SendMakeCurrentRequest( dpy, opcode,
gc ? gc->xid : None,
oldGC->currentContextTag,
draw, read, &reply );
#ifdef GLX_DIRECT_RENDERING
}
#endif
if (!bindReturnValue) {
if (gc && !gc->isDirect) {
SyncHandle();
}
#ifdef GLX_DIRECT_RENDERING
if (oldGC->isDirect) {
if (oldGC->driContext.private) {
if (!(*oldGC->driContext.bindContext2)(oldGC->currentDpy,
oldGC->screen,
oldGC->currentDrawable,
oldGC->currentReadable,
oldGC)) {
}
}
} else
#endif
if (sentRequestToOldDpy) {
if ( !SendMakeCurrentRequest( oldGC->currentDpy, oldOpcode,
oldGC->xid, 0,
oldGC->currentDrawable,
oldGC->currentReadable, &reply ) ) {
UnlockDisplay(dpy);
SyncHandle();
}
else {
UnlockDisplay(dpy);
}
oldGC->currentContextTag = reply.contextTag;
}
return GL_FALSE;
}
__glXLock();
if (gc == oldGC) {
gc->currentDrawable = draw;
gc->currentReadable = read;
} else {
if (oldGC != &dummyContext) {
oldGC->currentDpy = 0;
oldGC->currentDrawable = None;
oldGC->currentReadable = None;
oldGC->currentContextTag = 0;
if (oldGC->xid == None) {
#ifdef GLX_DIRECT_RENDERING
if (oldGC->isDirect) {
if (oldGC->driContext.private) {
(*oldGC->driContext.destroyContext)
(dpy, oldGC->screen, oldGC->driContext.private);
oldGC->driContext.private = NULL;
}
}
#endif
__glXFreeContext(oldGC);
}
}
if (gc) {
__glXSetCurrentContext(gc);
#ifdef GLX_DIRECT_RENDERING
if (!gc->isDirect) {
if (!IndirectAPI)
IndirectAPI = __glXNewIndirectAPI();
_glapi_set_dispatch(IndirectAPI);
# ifdef GLX_USE_APPLEGL
do {
extern void XAppleDRIUseIndirectDispatch(void);
XAppleDRIUseIndirectDispatch();
} while (0);
# endif
}
#else
if (!IndirectAPI)
IndirectAPI = __glXNewIndirectAPI();
_glapi_set_dispatch(IndirectAPI);
#endif
gc->currentDpy = dpy;
gc->currentDrawable = draw;
gc->currentReadable = read;
#ifdef GLX_DIRECT_RENDERING
if (gc->isDirect) reply.contextTag = -1;
#endif
gc->currentContextTag = reply.contextTag;
} else {
__glXSetCurrentContext(&dummyContext);
#ifdef GLX_DIRECT_RENDERING
_glapi_set_dispatch(NULL);
#endif
}
}
__glXUnlock();
return GL_TRUE;
}
Bool GLX_PREFIX(glXMakeCurrent)(Display *dpy, GLXDrawable draw, GLXContext gc)
{
return MakeContextCurrent( dpy, draw, draw, gc );
}
GLX_ALIAS(Bool, glXMakeCurrentReadSGI,
(Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
(dpy, d, r, ctx), MakeContextCurrent)
GLX_ALIAS(Bool, glXMakeContextCurrent,
(Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
(dpy, d, r, ctx), MakeContextCurrent)
#ifdef DEBUG
void __glXDumpDrawBuffer(__GLXcontext *ctx)
{
GLubyte *p = ctx->buf;
GLubyte *end = ctx->pc;
GLushort opcode, length;
while (p < end) {
opcode = *((GLushort*) p);
length = *((GLushort*) (p + 2));
printf("%2x: %5d: ", opcode, length);
length -= 4;
p += 4;
while (length > 0) {
printf("%08x ", *((unsigned *) p));
p += 4;
length -= 4;
}
printf("\n");
}
}
#endif
#ifdef USE_SPARC_ASM
static void
_glx_mesa_init_sparc_glapi_relocs(void)
{
unsigned int *insn_ptr, *end_ptr;
unsigned long disp_addr;
insn_ptr = &_mesa_sparc_glapi_begin;
end_ptr = &_mesa_sparc_glapi_end;
disp_addr = (unsigned long) &_glapi_Dispatch;
while (insn_ptr < end_ptr) {
#if ( defined(__sparc_v9__) && ( !defined(__linux__) || defined(__linux_64__) ) )
insn_ptr[0] |= (disp_addr >> (32 + 10));
insn_ptr[1] |= ((disp_addr & 0xffffffff) >> 10);
__glapi_sparc_icache_flush(&insn_ptr[0]);
insn_ptr[2] |= ((disp_addr >> 32) & ((1 << 10) - 1));
insn_ptr[3] |= (disp_addr & ((1 << 10) - 1));
__glapi_sparc_icache_flush(&insn_ptr[2]);
insn_ptr += 11;
#else
insn_ptr[0] |= (disp_addr >> 10);
insn_ptr[1] |= (disp_addr & ((1 << 10) - 1));
__glapi_sparc_icache_flush(&insn_ptr[0]);
insn_ptr += 5;
#endif
}
}
#endif