#define NEED_REPLIES
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <string.h>
#include "glxserver.h"
#include <windowstr.h>
#include <propertyst.h>
#include <os.h>
#include "g_disptab.h"
#include "unpack.h"
#include "glxutil.h"
#include "glxext.h"
#include "indirect_table.h"
#include "indirect_util.h"
__GLXcontext *__glXLastContext;
RESTYPE __glXContextRes;
RESTYPE __glXClientRes;
RESTYPE __glXPixmapRes;
RESTYPE __glXDrawableRes;
RESTYPE __glXSwapBarrierRes;
xGLXSingleReply __glXReply;
static __GLXclientState *__glXClients[MAXCLIENTS + 1];
static int __glXDispatch(ClientPtr);
static void ResetExtension(ExtensionEntry* extEntry)
{
__glXFlushContextCache();
__glXResetScreens();
}
static void ResetClientState(int clientIndex)
{
__GLXclientState *cl = __glXClients[clientIndex];
if (cl->returnBuf) xfree(cl->returnBuf);
if (cl->largeCmdBuf) xfree(cl->largeCmdBuf);
if (cl->currentContexts) xfree(cl->currentContexts);
memset(cl, 0, sizeof(__GLXclientState));
cl->GLClientmajorVersion = 1;
cl->GLClientminorVersion = 0;
if (cl->GLClientextensions)
xfree(cl->GLClientextensions);
}
void __glXResetLargeCommandStatus(__GLXclientState *cl)
{
cl->largeCmdBytesSoFar = 0;
cl->largeCmdBytesTotal = 0;
cl->largeCmdRequestsSoFar = 0;
cl->largeCmdRequestsTotal = 0;
}
static int ContextGone(__GLXcontext* cx, XID id)
{
cx->idExists = GL_FALSE;
if (!cx->isCurrent) {
__glXFreeContext(cx);
}
return True;
}
static int ClientGone(int clientIndex, XID id)
{
__GLXcontext *cx;
__GLXclientState *cl = __glXClients[clientIndex];
int i;
if (cl) {
for (i=0; i < cl->numCurrentContexts; i++) {
cx = cl->currentContexts[i];
if (cx) {
__glXDeassociateContext(cx);
cx->isCurrent = GL_FALSE;
if (!cx->idExists) {
__glXFreeContext(cx);
}
}
}
ResetClientState(clientIndex);
}
return True;
}
static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id)
{
PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw;
pGlxPixmap->idExists = False;
if (!pGlxPixmap->refcnt) {
if (pGlxPixmap->pDamage) {
DamageUnregister (pGlxPixmap->pDraw, pGlxPixmap->pDamage);
DamageDestroy(pGlxPixmap->pDamage);
}
(*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap);
xfree(pGlxPixmap);
}
return True;
}
static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
{
__GLXcontext *cx, *cx1;
if (glxPriv->type == DRAWABLE_WINDOW) {
for (cx = glxPriv->drawGlxc; cx; cx = cx1) {
cx1 = cx->nextDrawPriv;
cx->pendingState |= __GLX_PENDING_DESTROY;
}
for (cx = glxPriv->readGlxc; cx; cx = cx1) {
cx1 = cx->nextReadPriv;
cx->pendingState |= __GLX_PENDING_DESTROY;
}
}
__glXUnrefDrawable(glxPriv);
return True;
}
static __GLXcontext *glxPendingDestroyContexts;
static int glxServerLeaveCount;
static int glxBlockClients;
GLboolean __glXFreeContext(__GLXcontext *cx)
{
if (cx->idExists || cx->isCurrent) return GL_FALSE;
if (cx->feedbackBuf) xfree(cx->feedbackBuf);
if (cx->selectBuf) xfree(cx->selectBuf);
if (cx == __glXLastContext) {
__glXFlushContextCache();
}
if (!glxBlockClients) {
__glXleaveServer();
cx->destroy(cx);
__glXenterServer();
} else {
cx->next = glxPendingDestroyContexts;
glxPendingDestroyContexts = cx;
}
return GL_TRUE;
}
extern RESTYPE __glXSwapBarrierRes;
static int SwapBarrierGone(int screen, XID drawable)
{
if (__glXSwapBarrierFuncs &&
__glXSwapBarrierFuncs[screen].bindSwapBarrierFunc != NULL) {
__glXSwapBarrierFuncs[screen].bindSwapBarrierFunc(screen, drawable, 0);
}
FreeResourceByType(drawable, __glXSwapBarrierRes, FALSE);
return True;
}
static GLboolean errorOccured = GL_FALSE;
void __glXErrorCallBack(__GLinterface *gc, GLenum code)
{
errorOccured = GL_TRUE;
}
void __glXClearErrorOccured(void)
{
errorOccured = GL_FALSE;
}
GLboolean __glXErrorOccured(void)
{
return errorOccured;
}
static int __glXErrorBase;
int __glXError(int error)
{
return __glXErrorBase + error;
}
void GlxExtensionInit(void)
{
ExtensionEntry *extEntry;
int i;
__glXContextRes = CreateNewResourceType((DeleteType)ContextGone);
__glXClientRes = CreateNewResourceType((DeleteType)ClientGone);
__glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone);
__glXDrawableRes = CreateNewResourceType((DeleteType)DrawableGone);
__glXSwapBarrierRes = CreateNewResourceType((DeleteType)SwapBarrierGone);
extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS,
__GLX_NUMBER_ERRORS, __glXDispatch,
__glXDispatch, ResetExtension,
StandardMinorOpcode);
if (!extEntry) {
FatalError("__glXExtensionInit: AddExtensions failed\n");
return;
}
if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) {
ErrorF("__glXExtensionInit: AddExtensionAlias failed\n");
return;
}
__glXErrorBase = extEntry->errorBase;
for (i = 1; i <= MAXCLIENTS; i++) {
__glXClients[i] = 0;
}
__glXInitScreens();
}
void __glXFlushContextCache(void)
{
__glXLastContext = 0;
}
__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
int *error)
{
__GLXcontext *cx;
cx = (__GLXcontext *) __glXLookupContextByTag(cl, tag);
if (!cx) {
cl->client->errorValue = tag;
*error = __glXError(GLXBadContextTag);
return 0;
}
if (!cx->isDirect) {
if (cx->drawPriv == NULL) {
*error = __glXError(GLXBadCurrentWindow);
return 0;
}
}
if (cx == __glXLastContext) {
return cx;
}
if (!cx->isDirect) {
if (!(*cx->forceCurrent)(cx)) {
cl->client->errorValue = cx->id;
*error = __glXError(GLXBadContextState);
return 0;
}
}
__glXLastContext = cx;
return cx;
}
void glxSuspendClients(void)
{
int i;
for (i = 1; i <= MAXCLIENTS; i++) {
if (__glXClients[i] == NULL || !__glXClients[i]->inUse)
continue;
IgnoreClient(__glXClients[i]->client);
}
glxBlockClients = TRUE;
}
void glxResumeClients(void)
{
__GLXcontext *cx, *next;
int i;
glxBlockClients = FALSE;
for (i = 1; i <= MAXCLIENTS; i++) {
if (__glXClients[i] == NULL || !__glXClients[i]->inUse)
continue;
AttendClient(__glXClients[i]->client);
}
__glXleaveServer();
for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) {
next = cx->next;
cx->destroy(cx);
}
glxPendingDestroyContexts = NULL;
__glXenterServer();
}
static void
__glXnopEnterServer(void)
{
}
static void
__glXnopLeaveServer(void)
{
}
static void (*__glXenterServerFunc)(void) = __glXnopEnterServer;
static void (*__glXleaveServerFunc)(void) = __glXnopLeaveServer;
void __glXsetEnterLeaveServerFuncs(void (*enter)(void),
void (*leave)(void))
{
__glXenterServerFunc = enter;
__glXleaveServerFunc = leave;
}
void __glXenterServer(void)
{
glxServerLeaveCount--;
if (glxServerLeaveCount == 0)
(*__glXenterServerFunc)();
}
void __glXleaveServer(void)
{
if (glxServerLeaveCount == 0)
(*__glXleaveServerFunc)();
glxServerLeaveCount++;
}
static int __glXDispatch(ClientPtr client)
{
REQUEST(xGLXSingleReq);
CARD8 opcode;
__GLXdispatchSingleProcPtr proc;
__GLXclientState *cl;
int retval;
opcode = stuff->glxCode;
cl = __glXClients[client->index];
if (!cl) {
cl = (__GLXclientState *) xalloc(sizeof(__GLXclientState));
__glXClients[client->index] = cl;
if (!cl) {
return BadAlloc;
}
memset(cl, 0, sizeof(__GLXclientState));
}
if (!cl->inUse) {
XID xid = FakeClientID(client->index);
if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) {
return BadAlloc;
}
ResetClientState(client->index);
cl->inUse = GL_TRUE;
cl->client = client;
}
if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) {
client->errorValue = stuff->glxCode;
return __glXError(GLXBadLargeRequest);
}
if (glxBlockClients) {
ResetCurrentRequest(client);
client->sequence--;
IgnoreClient(client);
return(client->noClientException);
}
proc = (__GLXdispatchSingleProcPtr) __glXGetProtocolDecodeFunction(& Single_dispatch_info,
opcode,
client->swapped);
if (proc != NULL) {
__glXleaveServer();
retval = (*proc)(cl, (GLbyte *) stuff);
__glXenterServer();
}
else {
retval = BadRequest;
}
return retval;
}