aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/glx
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/glx')
-rw-r--r--xorg-server/glx/Makefile.am199
-rw-r--r--xorg-server/glx/glxcmds.c4665
-rw-r--r--xorg-server/glx/glxdri2.c1583
-rw-r--r--xorg-server/glx/glxext.c1108
4 files changed, 3783 insertions, 3772 deletions
diff --git a/xorg-server/glx/Makefile.am b/xorg-server/glx/Makefile.am
index 41fdf5fc2..ef8677a7c 100644
--- a/xorg-server/glx/Makefile.am
+++ b/xorg-server/glx/Makefile.am
@@ -1,98 +1,101 @@
-if AIGLX
-GLXDRI_LIBRARY = libglxdri.la
-endif
-
-noinst_LTLIBRARIES = libglx.la $(GLXDRI_LIBRARY)
-
-AM_CFLAGS = \
- @DIX_CFLAGS@ \
- @GL_CFLAGS@ \
- @DRI_CFLAGS@ \
- @XLIB_CFLAGS@ \
- @LIBDRM_CFLAGS@ \
- @DRIPROTO_CFLAGS@ \
- @GLX_DEFINES@ \
- @GLX_ARCH_DEFINES@
-
-# none yet
-#sdk_HEADERS =
-
-INCLUDES = \
- -I$(top_srcdir)/hw/xfree86/os-support \
- -I$(top_srcdir)/hw/xfree86/os-support/bus \
- -I$(top_srcdir)/hw/xfree86/common \
- -I$(top_srcdir)/hw/xfree86/dri \
- -I$(top_srcdir)/mi
-
-if DRI2_AIGLX
-INCLUDES += -I$(top_srcdir)/hw/xfree86/dri2
-endif
-
-glapi_sources = \
- indirect_dispatch.c \
- indirect_dispatch.h \
- indirect_dispatch_swap.c \
- indirect_reqsize.c \
- indirect_reqsize.h \
- indirect_size.h \
- indirect_size_get.c \
- indirect_size_get.h \
- indirect_table.c \
- dispatch.h \
- glapitable.h \
- glapi.c \
- glapi.h \
- glapioffsets.h \
- glprocs.h \
- glthread.c \
- glthread.h
-
-libglxdri_la_SOURCES = \
- glxdri.c \
- extension_string.c \
- extension_string.h
-
-if DRI2_AIGLX
-libglxdri_la_SOURCES += glxdri2.c
-endif
-
-libglxdri_la_LIBADD = $(DLOPEN_LIBS)
-
-libglx_la_SOURCES = \
- $(indirect_sources) \
- $(glapi_sources) \
- indirect_util.c \
- indirect_util.h \
- indirect_program.c \
- indirect_table.h \
- indirect_texture_compression.c \
- glxbyteorder.h \
- glxcmds.c \
- glxcmdsswap.c \
- glxcontext.h \
- glxdrawable.h \
- glxext.c \
- glxext.h \
- glxdriswrast.c \
- glxdricommon.c \
- glxdricommon.h \
- glxscreens.c \
- glxscreens.h \
- glxserver.h \
- glxutil.h \
- render2.c \
- render2swap.c \
- renderpix.c \
- renderpixswap.c \
- rensize.c \
- single2.c \
- single2swap.c \
- singlepix.c \
- singlepixswap.c \
- singlesize.c \
- singlesize.h \
- swap_interval.c \
- unpack.h \
- xfont.c
-
-libglx_la_LIBADD = $(DLOPEN_LIBS)
+if AIGLX
+GLXDRI_LIBRARY = libglxdri.la
+endif
+
+noinst_LTLIBRARIES = libglx.la $(GLXDRI_LIBRARY)
+
+AM_CFLAGS = \
+ @DIX_CFLAGS@ \
+ @GL_CFLAGS@ \
+ @DRI_CFLAGS@ \
+ @XLIB_CFLAGS@ \
+ @LIBDRM_CFLAGS@ \
+ @DRIPROTO_CFLAGS@ \
+ @GLX_DEFINES@ \
+ @GLX_ARCH_DEFINES@
+
+# none yet
+#sdk_HEADERS =
+
+INCLUDES = \
+ -I$(top_srcdir)/hw/xfree86/os-support \
+ -I$(top_srcdir)/hw/xfree86/os-support/bus \
+ -I$(top_srcdir)/hw/xfree86/common \
+ -I$(top_srcdir)/hw/xfree86/dri \
+ -I$(top_srcdir)/mi
+
+if DRI2_AIGLX
+INCLUDES += -I$(top_srcdir)/hw/xfree86/dri2
+endif
+
+glapi_sources = \
+ indirect_dispatch.c \
+ indirect_dispatch.h \
+ indirect_dispatch_swap.c \
+ indirect_reqsize.c \
+ indirect_reqsize.h \
+ indirect_size.h \
+ indirect_size_get.c \
+ indirect_size_get.h \
+ indirect_table.c \
+ dispatch.h \
+ glapitable.h \
+ glapi.c \
+ glapi.h \
+ glapioffsets.h \
+ glprocs.h \
+ glthread.c \
+ glthread.h
+
+libglxdri_la_SOURCES = \
+ extension_string.c \
+ extension_string.h
+
+if DRI
+libglxdri_la_SOURCES += glxdri.c
+endif
+
+if DRI2_AIGLX
+libglxdri_la_SOURCES += glxdri2.c
+endif
+
+libglxdri_la_LIBADD = $(DLOPEN_LIBS)
+
+libglx_la_SOURCES = \
+ $(indirect_sources) \
+ $(glapi_sources) \
+ indirect_util.c \
+ indirect_util.h \
+ indirect_program.c \
+ indirect_table.h \
+ indirect_texture_compression.c \
+ glxbyteorder.h \
+ glxcmds.c \
+ glxcmdsswap.c \
+ glxcontext.h \
+ glxdrawable.h \
+ glxext.c \
+ glxext.h \
+ glxdriswrast.c \
+ glxdricommon.c \
+ glxdricommon.h \
+ glxscreens.c \
+ glxscreens.h \
+ glxserver.h \
+ glxutil.h \
+ render2.c \
+ render2swap.c \
+ renderpix.c \
+ renderpixswap.c \
+ rensize.c \
+ single2.c \
+ single2swap.c \
+ singlepix.c \
+ singlepixswap.c \
+ singlesize.c \
+ singlesize.h \
+ swap_interval.c \
+ unpack.h \
+ xfont.c
+
+libglx_la_LIBADD = $(DLOPEN_LIBS)
diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c
index b524597a8..d5b764fd0 100644
--- a/xorg-server/glx/glxcmds.c
+++ b/xorg-server/glx/glxcmds.c
@@ -1,2331 +1,2334 @@
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-#include <assert.h>
-
-#include "glxserver.h"
-#include <GL/glxtokens.h>
-#include <unpack.h>
-#include <pixmapstr.h>
-#include <windowstr.h>
-#include "glxutil.h"
-#include "glxext.h"
-#include "glapitable.h"
-#include "glapi.h"
-#include "glthread.h"
-#include "dispatch.h"
-#include "indirect_dispatch.h"
-#include "indirect_table.h"
-#include "indirect_util.h"
-
-static int
-validGlxScreen(ClientPtr client, int screen, __GLXscreen **pGlxScreen, int *err)
-{
- /*
- ** Check if screen exists.
- */
- if (screen < 0 || screen >= screenInfo.numScreens) {
- client->errorValue = screen;
- *err = BadValue;
- return FALSE;
- }
- *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
-
- return TRUE;
-}
-
-static int
-validGlxFBConfig(ClientPtr client, __GLXscreen *pGlxScreen, XID id,
- __GLXconfig **config, int *err)
-{
- __GLXconfig *m;
-
- for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next)
- if (m->fbconfigID == id) {
- *config = m;
- return TRUE;
- }
-
- client->errorValue = id;
- *err = __glXError(GLXBadFBConfig);
-
- return FALSE;
-}
-
-static int
-validGlxVisual(ClientPtr client, __GLXscreen *pGlxScreen, XID id,
- __GLXconfig **config, int *err)
-{
- int i;
-
- for (i = 0; i < pGlxScreen->numVisuals; i++)
- if (pGlxScreen->visuals[i]->visualID == id) {
- *config = pGlxScreen->visuals[i];
- return TRUE;
- }
-
- client->errorValue = id;
- *err = BadValue;
-
- return FALSE;
-}
-
-static int
-validGlxFBConfigForWindow(ClientPtr client, __GLXconfig *config,
- DrawablePtr pDraw, int *err)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- VisualPtr pVisual = NULL;
- XID vid;
- int i;
-
- vid = wVisual((WindowPtr)pDraw);
- for (i = 0; i < pScreen->numVisuals; i++) {
- if (pScreen->visuals[i].vid == vid) {
- pVisual = &pScreen->visuals[i];
- break;
- }
- }
-
- /* FIXME: What exactly should we check here... */
- if (pVisual->class != glxConvertToXVisualType(config->visualType) ||
- !(config->drawableType & GLX_WINDOW_BIT)) {
- client->errorValue = pDraw->id;
- *err = BadMatch;
- return FALSE;
- }
-
- return TRUE;
-}
-
-static int
-validGlxContext(ClientPtr client, XID id, int access_mode,
- __GLXcontext **context, int *err)
-{
- *err = dixLookupResourceByType((pointer *) context, id,
- __glXContextRes, client, access_mode);
- if (*err != Success || (*context)->idExists == GL_FALSE) {
- client->errorValue = id;
- if (*err == BadValue || *err == Success)
- *err = __glXError(GLXBadContext);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static int
-validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
- __GLXdrawable **drawable, int *err)
-{
- int rc;
-
- rc = dixLookupResourceByType((pointer *) drawable, id,
- __glXDrawableRes, client, access_mode);
- if (rc != Success && rc != BadValue) {
- *err = rc;
- client->errorValue = id;
- return FALSE;
- }
-
- /* If the ID of the glx drawable we looked up doesn't match the id
- * we looked for, it's because we looked it up under the X
- * drawable ID (see DoCreateGLXDrawable). */
- if (rc == BadValue ||
- (*drawable)->drawId != id ||
- (type != GLX_DRAWABLE_ANY && type != (*drawable)->type)) {
- client->errorValue = id;
- switch (type) {
- case GLX_DRAWABLE_WINDOW:
- *err = __glXError(GLXBadWindow);
- return FALSE;
- case GLX_DRAWABLE_PIXMAP:
- *err = __glXError(GLXBadPixmap);
- return FALSE;
- case GLX_DRAWABLE_PBUFFER:
- *err = __glXError(GLXBadPbuffer);
- return FALSE;
- case GLX_DRAWABLE_ANY:
- *err = __glXError(GLXBadDrawable);
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-void
-__glXContextDestroy(__GLXcontext *context)
-{
- __glXFlushContextCache();
-}
-
-static void __glXdirectContextDestroy(__GLXcontext *context)
-{
- __glXContextDestroy(context);
- free(context);
-}
-
-static __GLXcontext *__glXdirectContextCreate(__GLXscreen *screen,
- __GLXconfig *modes,
- __GLXcontext *shareContext)
-{
- __GLXcontext *context;
-
- context = calloc(1, sizeof (__GLXcontext));
- if (context == NULL)
- return NULL;
-
- context->destroy = __glXdirectContextDestroy;
-
- return context;
-}
-
-/**
- * Create a GL context with the given properties. This routine is used
- * to implement \c glXCreateContext, \c glXCreateNewContext, and
- * \c glXCreateContextWithConfigSGIX. This works becuase of the hack way
- * that GLXFBConfigs are implemented. Basically, the FBConfigID is the
- * same as the VisualID.
- */
-
-static int
-DoCreateContext(__GLXclientState *cl, GLXContextID gcId,
- GLXContextID shareList, __GLXconfig *config,
- __GLXscreen *pGlxScreen, GLboolean isDirect)
-{
- ClientPtr client = cl->client;
- __GLXcontext *glxc, *shareglxc;
- int err;
-
- LEGAL_NEW_RESOURCE(gcId, client);
-
- /*
- ** Find the display list space that we want to share.
- **
- ** NOTE: In a multithreaded X server, we would need to keep a reference
- ** count for each display list so that if one client detroyed a list that
- ** another client was using, the list would not really be freed until it
- ** was no longer in use. Since this sample implementation has no support
- ** for multithreaded servers, we don't do this.
- */
- if (shareList == None) {
- shareglxc = 0;
- } else {
- if (!validGlxContext(client, shareList, DixReadAccess,
- &shareglxc, &err))
- return err;
-
- if (shareglxc->isDirect) {
- /*
- ** NOTE: no support for sharing display lists between direct
- ** contexts, even if they are in the same address space.
- */
-#if 0
- /* Disabling this code seems to allow shared display lists
- * and texture objects to work. We'll leave it disabled for now.
- */
- client->errorValue = shareList;
- return BadMatch;
-#endif
- } else {
- /*
- ** Create an indirect context regardless of what the client asked
- ** for; this way we can share display list space with shareList.
- */
- isDirect = GL_FALSE;
- }
- }
-
- /*
- ** Allocate memory for the new context
- */
- if (!isDirect)
- glxc = pGlxScreen->createContext(pGlxScreen, config, shareglxc);
- else
- glxc = __glXdirectContextCreate(pGlxScreen, config, shareglxc);
- if (!glxc) {
- return BadAlloc;
- }
-
- /*
- ** Initially, setup the part of the context that could be used by
- ** a GL core that needs windowing information (e.g., Mesa).
- */
- glxc->pGlxScreen = pGlxScreen;
- glxc->config = config;
-
- /*
- ** Register this context as a resource.
- */
- if (!AddResource(gcId, __glXContextRes, (pointer)glxc)) {
- (*glxc->destroy)(glxc);
- client->errorValue = gcId;
- return BadAlloc;
- }
-
- /*
- ** Finally, now that everything is working, setup the rest of the
- ** context.
- */
- glxc->id = gcId;
- glxc->share_id = shareList;
- glxc->idExists = GL_TRUE;
- glxc->isCurrent = GL_FALSE;
- glxc->isDirect = isDirect;
- glxc->renderMode = GL_RENDER;
-
- __glXAddToContextList(glxc);
-
- return Success;
-}
-
-int __glXDisp_CreateContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateContextReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
- return err;
-
- return DoCreateContext(cl, req->context, req->shareList,
- config, pGlxScreen, req->isDirect);
-}
-
-int __glXDisp_CreateNewContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateNewContextReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- return DoCreateContext(cl, req->context, req->shareList,
- config, pGlxScreen, req->isDirect);
-}
-
-int __glXDisp_CreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateContextWithConfigSGIXReq *req =
- (xGLXCreateContextWithConfigSGIXReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateContextWithConfigSGIXReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- return DoCreateContext(cl, req->context, req->shareList,
- config, pGlxScreen, req->isDirect);
-}
-
-int __glXDisp_DestroyContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc;
- __GLXcontext *glxc;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXDestroyContextReq);
-
- if (!validGlxContext(cl->client, req->context, DixDestroyAccess,
- &glxc, &err))
- return err;
-
- glxc->idExists = GL_FALSE;
- if (!glxc->isCurrent)
- FreeResourceByType(req->context, __glXContextRes, FALSE);
-
- return Success;
-}
-
-/*
- * This will return "deleted" contexts, ie, where idExists is GL_FALSE.
- * Contrast validGlxContext, which will not. We're cheating here and
- * using the XID as the context tag, which is fine as long as we defer
- * actually destroying the context until it's no longer referenced, and
- * block clients from trying to MakeCurrent on contexts that are on the
- * way to destruction. Notice that DoMakeCurrent calls validGlxContext
- * for new contexts but __glXLookupContextByTag for previous contexts.
- */
-__GLXcontext *__glXLookupContextByTag(__GLXclientState *cl, GLXContextTag tag)
-{
- __GLXcontext *ret;
-
- if (dixLookupResourceByType((void **)&ret, tag, __glXContextRes,
- cl->client, DixUseAccess) == Success)
- return ret;
-
- return NULL;
-}
-
-/*****************************************************************************/
-
-static void StopUsingContext(__GLXcontext *glxc)
-{
- if (glxc) {
- if (glxc == __glXLastContext) {
- /* Tell server GL library */
- __glXLastContext = 0;
- }
- glxc->isCurrent = GL_FALSE;
- if (!glxc->idExists) {
- FreeResourceByType(glxc->id, __glXContextRes, FALSE);
- }
- }
-}
-
-static void StartUsingContext(__GLXclientState *cl, __GLXcontext *glxc)
-{
- glxc->isCurrent = GL_TRUE;
- __glXLastContext = glxc;
-}
-
-/**
- * This is a helper function to handle the legacy (pre GLX 1.3) cases
- * where passing an X window to glXMakeCurrent is valid. Given a
- * resource ID, look up the GLX drawable if available, otherwise, make
- * sure it's an X window and create a GLX drawable one the fly.
- */
-static __GLXdrawable *
-__glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client,
- int *error)
-{
- DrawablePtr pDraw;
- __GLXdrawable *pGlxDraw;
- int rc;
-
- if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
- DixWriteAccess, &pGlxDraw, &rc)) {
- if (glxc != NULL && pGlxDraw->config != glxc->config) {
- client->errorValue = drawId;
- *error = BadMatch;
- return NULL;
- }
-
- return pGlxDraw;
- }
-
- /* No active context and an unknown drawable, bail. */
- if (glxc == NULL) {
- client->errorValue = drawId;
- *error = BadMatch;
- return NULL;
- }
-
- /* The drawId wasn't a GLX drawable. Make sure it's a window and
- * create a GLXWindow for it. Check that the drawable screen
- * matches the context screen and that the context fbconfig is
- * compatible with the window visual. */
-
- rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess);
- if (rc != Success || pDraw->type != DRAWABLE_WINDOW) {
- client->errorValue = drawId;
- *error = __glXError(GLXBadDrawable);
- return NULL;
- }
-
- if (pDraw->pScreen != glxc->pGlxScreen->pScreen) {
- client->errorValue = pDraw->pScreen->myNum;
- *error = BadMatch;
- return NULL;
- }
-
- if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error))
- return NULL;
-
- pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen,
- pDraw, drawId,
- GLX_DRAWABLE_WINDOW,
- drawId, glxc->config);
-
- /* since we are creating the drawablePrivate, drawId should be new */
- if (!AddResource(drawId, __glXDrawableRes, pGlxDraw)) {
- pGlxDraw->destroy (pGlxDraw);
- *error = BadAlloc;
- return NULL;
- }
-
- return pGlxDraw;
-}
-
-/*****************************************************************************/
-/*
-** Make an OpenGL context and drawable current.
-*/
-
-static int
-DoMakeCurrent(__GLXclientState *cl,
- GLXDrawable drawId, GLXDrawable readId,
- GLXContextID contextId, GLXContextTag tag)
-{
- ClientPtr client = cl->client;
- xGLXMakeCurrentReply reply;
- __GLXcontext *glxc, *prevglxc;
- __GLXdrawable *drawPriv = NULL;
- __GLXdrawable *readPriv = NULL;
- int error;
- GLuint mask;
-
- /*
- ** If one is None and the other isn't, it's a bad match.
- */
-
- mask = (drawId == None) ? (1 << 0) : 0;
- mask |= (readId == None) ? (1 << 1) : 0;
- mask |= (contextId == None) ? (1 << 2) : 0;
-
- if ( (mask != 0x00) && (mask != 0x07) ) {
- return BadMatch;
- }
-
- /*
- ** Lookup old context. If we have one, it must be in a usable state.
- */
- if (tag != 0) {
- prevglxc = __glXLookupContextByTag(cl, tag);
- if (!prevglxc) {
- /*
- ** Tag for previous context is invalid.
- */
- return __glXError(GLXBadContextTag);
- }
- if (prevglxc->renderMode != GL_RENDER) {
- /* Oops. Not in render mode render. */
- client->errorValue = prevglxc->id;
- return __glXError(GLXBadContextState);
- }
- } else {
- prevglxc = 0;
- }
-
- /*
- ** Lookup new context. It must not be current for someone else.
- */
- if (contextId != None) {
- int status;
-
- if (!validGlxContext(client, contextId, DixUseAccess, &glxc, &error))
- return error;
- if ((glxc != prevglxc) && glxc->isCurrent) {
- /* Context is current to somebody else */
- return BadAccess;
- }
-
- assert( drawId != None );
- assert( readId != None );
-
- drawPriv = __glXGetDrawable(glxc, drawId, client, &status);
- if (drawPriv == NULL)
- return status;
-
- readPriv = __glXGetDrawable(glxc, readId, client, &status);
- if (readPriv == NULL)
- return status;
-
- } else {
- /* Switching to no context. Ignore new drawable. */
- glxc = 0;
- drawPriv = 0;
- readPriv = 0;
- }
-
-
- if (prevglxc) {
- /*
- ** Flush the previous context if needed.
- */
- if (prevglxc->hasUnflushedCommands) {
- if (__glXForceCurrent(cl, tag, (int *)&error)) {
- CALL_Flush( GET_DISPATCH(), () );
- prevglxc->hasUnflushedCommands = GL_FALSE;
- } else {
- return error;
- }
- }
-
- /*
- ** Make the previous context not current.
- */
- if (!(*prevglxc->loseCurrent)(prevglxc)) {
- return __glXError(GLXBadContext);
- }
- __glXFlushContextCache();
- if (!prevglxc->isDirect) {
- prevglxc->drawPriv = NULL;
- prevglxc->readPriv = NULL;
- }
- }
-
-
- if ((glxc != 0) && !glxc->isDirect) {
-
- glxc->drawPriv = drawPriv;
- glxc->readPriv = readPriv;
-
- /* make the context current */
- if (!(*glxc->makeCurrent)(glxc)) {
- glxc->drawPriv = NULL;
- glxc->readPriv = NULL;
- return __glXError(GLXBadContext);
- }
-
- glxc->isCurrent = GL_TRUE;
- }
-
- StopUsingContext(prevglxc);
-
- if (glxc) {
- StartUsingContext(cl, glxc);
- reply.contextTag = glxc->id;
- } else {
- reply.contextTag = 0;
- }
-
- reply.length = 0;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __glXSwapMakeCurrentReply(client, &reply);
- } else {
- WriteToClient(client, sz_xGLXMakeCurrentReply, (char *)&reply);
- }
- return Success;
-}
-
-int __glXDisp_MakeCurrent(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXMakeCurrentReq);
-
- return DoMakeCurrent( cl, req->drawable, req->drawable,
- req->context, req->oldContextTag );
-}
-
-int __glXDisp_MakeContextCurrent(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXMakeContextCurrentReq);
-
- return DoMakeCurrent( cl, req->drawable, req->readdrawable,
- req->context, req->oldContextTag );
-}
-
-int __glXDisp_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXMakeCurrentReadSGIReq);
-
- return DoMakeCurrent( cl, req->drawable, req->readable,
- req->context, req->oldContextTag );
-}
-
-int __glXDisp_IsDirect(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXIsDirectReq *req = (xGLXIsDirectReq *) pc;
- xGLXIsDirectReply reply;
- __GLXcontext *glxc;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXIsDirectReq);
-
- if (!validGlxContext(cl->client, req->context, DixReadAccess, &glxc, &err))
- return err;
-
- reply.isDirect = glxc->isDirect;
- reply.length = 0;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __glXSwapIsDirectReply(client, &reply);
- } else {
- WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply);
- }
-
- return Success;
-}
-
-int __glXDisp_QueryVersion(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) pc;
- xGLXQueryVersionReply reply;
- GLuint major, minor;
-
- REQUEST_SIZE_MATCH(xGLXQueryVersionReq);
-
- major = req->majorVersion;
- minor = req->minorVersion;
- (void)major;
- (void)minor;
-
- /*
- ** Server should take into consideration the version numbers sent by the
- ** client if it wants to work with older clients; however, in this
- ** implementation the server just returns its version number.
- */
- reply.majorVersion = glxMajorVersion;
- reply.minorVersion = glxMinorVersion;
- reply.length = 0;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __glXSwapQueryVersionReply(client, &reply);
- } else {
- WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply);
- }
- return Success;
-}
-
-int __glXDisp_WaitGL(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXWaitGLReq *req = (xGLXWaitGLReq *)pc;
- GLXContextTag tag;
- __GLXcontext *glxc = NULL;
- int error;
-
- REQUEST_SIZE_MATCH(xGLXWaitGLReq);
-
- tag = req->contextTag;
- if (tag) {
- glxc = __glXLookupContextByTag(cl, tag);
- if (!glxc)
- return __glXError(GLXBadContextTag);
-
- if (!__glXForceCurrent(cl, req->contextTag, &error))
- return error;
-
- CALL_Finish( GET_DISPATCH(), () );
- }
-
- if (glxc && glxc->drawPriv->waitGL)
- (*glxc->drawPriv->waitGL)(glxc->drawPriv);
-
- return Success;
-}
-
-int __glXDisp_WaitX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXWaitXReq *req = (xGLXWaitXReq *)pc;
- GLXContextTag tag;
- __GLXcontext *glxc = NULL;
- int error;
-
- REQUEST_SIZE_MATCH(xGLXWaitXReq);
-
- tag = req->contextTag;
- if (tag) {
- glxc = __glXLookupContextByTag(cl, tag);
- if (!glxc)
- return __glXError(GLXBadContextTag);
-
- if (!__glXForceCurrent(cl, req->contextTag, &error))
- return error;
- }
-
- if (glxc && glxc->drawPriv->waitX)
- (*glxc->drawPriv->waitX)(glxc->drawPriv);
-
- return Success;
-}
-
-int __glXDisp_CopyContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc;
- GLXContextID source;
- GLXContextID dest;
- GLXContextTag tag;
- unsigned long mask;
- __GLXcontext *src, *dst;
- int error;
-
- REQUEST_SIZE_MATCH(xGLXCopyContextReq);
-
- source = req->source;
- dest = req->dest;
- tag = req->contextTag;
- mask = req->mask;
- if (!validGlxContext(cl->client, source, DixReadAccess, &src, &error))
- return error;
- if (!validGlxContext(cl->client, dest, DixWriteAccess, &dst, &error))
- return error;
-
- /*
- ** They must be in the same address space, and same screen.
- ** NOTE: no support for direct rendering contexts here.
- */
- if (src->isDirect || dst->isDirect ||
- (src->pGlxScreen != dst->pGlxScreen)) {
- client->errorValue = source;
- return BadMatch;
- }
-
- /*
- ** The destination context must not be current for any client.
- */
- if (dst->isCurrent) {
- client->errorValue = dest;
- return BadAccess;
- }
-
- if (tag) {
- __GLXcontext *tagcx = __glXLookupContextByTag(cl, tag);
-
- if (!tagcx) {
- return __glXError(GLXBadContextTag);
- }
- if (tagcx != src) {
- /*
- ** This would be caused by a faulty implementation of the client
- ** library.
- */
- return BadMatch;
- }
- /*
- ** In this case, glXCopyContext is in both GL and X streams, in terms
- ** of sequentiality.
- */
- if (__glXForceCurrent(cl, tag, &error)) {
- /*
- ** Do whatever is needed to make sure that all preceding requests
- ** in both streams are completed before the copy is executed.
- */
- CALL_Finish( GET_DISPATCH(), () );
- tagcx->hasUnflushedCommands = GL_FALSE;
- } else {
- return error;
- }
- }
- /*
- ** Issue copy. The only reason for failure is a bad mask.
- */
- if (!(*dst->copy)(dst, src, mask)) {
- client->errorValue = mask;
- return BadValue;
- }
- return Success;
-}
-
-enum {
- GLX_VIS_CONFIG_UNPAIRED = 18,
- GLX_VIS_CONFIG_PAIRED = 20
-};
-
-enum {
- GLX_VIS_CONFIG_TOTAL = GLX_VIS_CONFIG_UNPAIRED + GLX_VIS_CONFIG_PAIRED
-};
-
-int __glXDisp_GetVisualConfigs(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc;
- ClientPtr client = cl->client;
- xGLXGetVisualConfigsReply reply;
- __GLXscreen *pGlxScreen;
- __GLXconfig *modes;
- CARD32 buf[GLX_VIS_CONFIG_TOTAL];
- int p, i, err;
- __GLX_DECLARE_SWAP_VARIABLES;
- __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
-
- REQUEST_SIZE_MATCH(xGLXGetVisualConfigsReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
-
- reply.numVisuals = pGlxScreen->numVisuals;
- reply.numProps = GLX_VIS_CONFIG_TOTAL;
- reply.length = (reply.numVisuals * __GLX_SIZE_CARD32 * GLX_VIS_CONFIG_TOTAL) >> 2;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __GLX_SWAP_SHORT(&reply.sequenceNumber);
- __GLX_SWAP_INT(&reply.length);
- __GLX_SWAP_INT(&reply.numVisuals);
- __GLX_SWAP_INT(&reply.numProps);
- }
-
- WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char *)&reply);
-
- for (i = 0; i < pGlxScreen->numVisuals; i++) {
- modes = pGlxScreen->visuals[i];
-
- p = 0;
- buf[p++] = modes->visualID;
- buf[p++] = glxConvertToXVisualType( modes->visualType );
- buf[p++] = (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE;
-
- buf[p++] = modes->redBits;
- buf[p++] = modes->greenBits;
- buf[p++] = modes->blueBits;
- buf[p++] = modes->alphaBits;
- buf[p++] = modes->accumRedBits;
- buf[p++] = modes->accumGreenBits;
- buf[p++] = modes->accumBlueBits;
- buf[p++] = modes->accumAlphaBits;
-
- buf[p++] = modes->doubleBufferMode;
- buf[p++] = modes->stereoMode;
-
- buf[p++] = modes->rgbBits;
- buf[p++] = modes->depthBits;
- buf[p++] = modes->stencilBits;
- buf[p++] = modes->numAuxBuffers;
- buf[p++] = modes->level;
-
- assert(p == GLX_VIS_CONFIG_UNPAIRED);
- /*
- ** Add token/value pairs for extensions.
- */
- buf[p++] = GLX_VISUAL_CAVEAT_EXT;
- buf[p++] = modes->visualRating;
- buf[p++] = GLX_TRANSPARENT_TYPE;
- buf[p++] = modes->transparentPixel;
- buf[p++] = GLX_TRANSPARENT_RED_VALUE;
- buf[p++] = modes->transparentRed;
- buf[p++] = GLX_TRANSPARENT_GREEN_VALUE;
- buf[p++] = modes->transparentGreen;
- buf[p++] = GLX_TRANSPARENT_BLUE_VALUE;
- buf[p++] = modes->transparentBlue;
- buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE;
- buf[p++] = modes->transparentAlpha;
- buf[p++] = GLX_TRANSPARENT_INDEX_VALUE;
- buf[p++] = modes->transparentIndex;
- buf[p++] = GLX_SAMPLES_SGIS;
- buf[p++] = modes->samples;
- buf[p++] = GLX_SAMPLE_BUFFERS_SGIS;
- buf[p++] = modes->sampleBuffers;
- buf[p++] = 0; /* copy over visualSelectGroup (GLX_VISUAL_SELECT_GROUP_SGIX)? */
- buf[p++] = 0;
-
- assert(p == GLX_VIS_CONFIG_TOTAL);
- if (client->swapped) {
- __GLX_SWAP_INT_ARRAY(buf, p);
- }
- WriteToClient(client, __GLX_SIZE_CARD32 * p, (char *)buf);
- }
- return Success;
-}
-
-#define __GLX_TOTAL_FBCONFIG_ATTRIBS (36)
-#define __GLX_FBCONFIG_ATTRIBS_LENGTH (__GLX_TOTAL_FBCONFIG_ATTRIBS * 2)
-/**
- * Send the set of GLXFBConfigs to the client. There is not currently
- * and interface into the driver on the server-side to get GLXFBConfigs,
- * so we "invent" some based on the \c __GLXvisualConfig structures that
- * the driver does supply.
- *
- * The reply format for both \c glXGetFBConfigs and \c glXGetFBConfigsSGIX
- * is the same, so this routine pulls double duty.
- */
-
-static int
-DoGetFBConfigs(__GLXclientState *cl, unsigned screen)
-{
- ClientPtr client = cl->client;
- xGLXGetFBConfigsReply reply;
- __GLXscreen *pGlxScreen;
- CARD32 buf[__GLX_FBCONFIG_ATTRIBS_LENGTH];
- int p, err;
- __GLXconfig *modes;
- __GLX_DECLARE_SWAP_VARIABLES;
- __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
-
- if (!validGlxScreen(cl->client, screen, &pGlxScreen, &err))
- return err;
-
- reply.numFBConfigs = pGlxScreen->numFBConfigs;
- reply.numAttribs = __GLX_TOTAL_FBCONFIG_ATTRIBS;
- reply.length = (__GLX_FBCONFIG_ATTRIBS_LENGTH * reply.numFBConfigs);
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
-
- if (client->swapped) {
- __GLX_SWAP_SHORT(&reply.sequenceNumber);
- __GLX_SWAP_INT(&reply.length);
- __GLX_SWAP_INT(&reply.numFBConfigs);
- __GLX_SWAP_INT(&reply.numAttribs);
- }
-
- WriteToClient(client, sz_xGLXGetFBConfigsReply, (char *)&reply);
-
- for (modes = pGlxScreen->fbconfigs; modes != NULL; modes = modes->next) {
- p = 0;
-
-#define WRITE_PAIR(tag,value) \
- do { buf[p++] = tag ; buf[p++] = value ; } while( 0 )
-
- WRITE_PAIR( GLX_VISUAL_ID, modes->visualID );
- WRITE_PAIR( GLX_FBCONFIG_ID, modes->fbconfigID );
- WRITE_PAIR( GLX_X_RENDERABLE, GL_TRUE );
-
- WRITE_PAIR( GLX_RGBA,
- (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE );
- WRITE_PAIR( GLX_RENDER_TYPE, modes->renderType );
- WRITE_PAIR( GLX_DOUBLEBUFFER, modes->doubleBufferMode );
- WRITE_PAIR( GLX_STEREO, modes->stereoMode );
-
- WRITE_PAIR( GLX_BUFFER_SIZE, modes->rgbBits );
- WRITE_PAIR( GLX_LEVEL, modes->level );
- WRITE_PAIR( GLX_AUX_BUFFERS, modes->numAuxBuffers );
- WRITE_PAIR( GLX_RED_SIZE, modes->redBits );
- WRITE_PAIR( GLX_GREEN_SIZE, modes->greenBits );
- WRITE_PAIR( GLX_BLUE_SIZE, modes->blueBits );
- WRITE_PAIR( GLX_ALPHA_SIZE, modes->alphaBits );
- WRITE_PAIR( GLX_ACCUM_RED_SIZE, modes->accumRedBits );
- WRITE_PAIR( GLX_ACCUM_GREEN_SIZE, modes->accumGreenBits );
- WRITE_PAIR( GLX_ACCUM_BLUE_SIZE, modes->accumBlueBits );
- WRITE_PAIR( GLX_ACCUM_ALPHA_SIZE, modes->accumAlphaBits );
- WRITE_PAIR( GLX_DEPTH_SIZE, modes->depthBits );
- WRITE_PAIR( GLX_STENCIL_SIZE, modes->stencilBits );
- WRITE_PAIR( GLX_X_VISUAL_TYPE, modes->visualType );
- WRITE_PAIR( GLX_CONFIG_CAVEAT, modes->visualRating );
- WRITE_PAIR( GLX_TRANSPARENT_TYPE, modes->transparentPixel );
- WRITE_PAIR( GLX_TRANSPARENT_RED_VALUE, modes->transparentRed );
- WRITE_PAIR( GLX_TRANSPARENT_GREEN_VALUE, modes->transparentGreen );
- WRITE_PAIR( GLX_TRANSPARENT_BLUE_VALUE, modes->transparentBlue );
- WRITE_PAIR( GLX_TRANSPARENT_ALPHA_VALUE, modes->transparentAlpha );
- WRITE_PAIR( GLX_TRANSPARENT_INDEX_VALUE, modes->transparentIndex );
- WRITE_PAIR( GLX_SWAP_METHOD_OML, modes->swapMethod );
- WRITE_PAIR( GLX_SAMPLES_SGIS, modes->samples );
- WRITE_PAIR( GLX_SAMPLE_BUFFERS_SGIS, modes->sampleBuffers );
- /* GLX_VISUAL_SELECT_GROUP_SGIX ? */
- WRITE_PAIR( GLX_DRAWABLE_TYPE, modes->drawableType );
- WRITE_PAIR( GLX_BIND_TO_TEXTURE_RGB_EXT, modes->bindToTextureRgb );
- WRITE_PAIR( GLX_BIND_TO_TEXTURE_RGBA_EXT, modes->bindToTextureRgba );
- WRITE_PAIR( GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture );
- WRITE_PAIR( GLX_BIND_TO_TEXTURE_TARGETS_EXT, modes->bindToTextureTargets );
-
- if (client->swapped) {
- __GLX_SWAP_INT_ARRAY(buf, __GLX_FBCONFIG_ATTRIBS_LENGTH);
- }
- WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_FBCONFIG_ATTRIBS_LENGTH,
- (char *)buf);
- }
- return Success;
-}
-
-
-int __glXDisp_GetFBConfigs(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc;
- REQUEST_SIZE_MATCH(xGLXGetFBConfigsReq);
- return DoGetFBConfigs(cl, req->screen);
-}
-
-int __glXDisp_GetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc;
- /* work around mesa bug, don't use REQUEST_SIZE_MATCH */
- REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq);
- return DoGetFBConfigs(cl, req->screen);
-}
-
-GLboolean
-__glXDrawableInit(__GLXdrawable *drawable,
- __GLXscreen *screen, DrawablePtr pDraw, int type,
- XID drawId, __GLXconfig *config)
-{
- drawable->pDraw = pDraw;
- drawable->type = type;
- drawable->drawId = drawId;
- drawable->config = config;
- drawable->eventMask = 0;
-
- return GL_TRUE;
-}
-
-void
-__glXDrawableRelease(__GLXdrawable *drawable)
-{
-}
-
-static int
-DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen,
- __GLXconfig *config, DrawablePtr pDraw, XID drawableId,
- XID glxDrawableId, int type)
-{
- __GLXdrawable *pGlxDraw;
-
- if (pGlxScreen->pScreen != pDraw->pScreen)
- return BadMatch;
-
- pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw,
- drawableId, type,
- glxDrawableId, config);
- if (pGlxDraw == NULL)
- return BadAlloc;
-
- if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw)) {
- pGlxDraw->destroy (pGlxDraw);
- return BadAlloc;
- }
-
- /* Add the glx drawable under the XID of the underlying X drawable
- * too. That way we'll get a callback in DrawableGone and can
- * clean up properly when the drawable is destroyed. */
- if (drawableId != glxDrawableId &&
- !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
- pGlxDraw->destroy (pGlxDraw);
- return BadAlloc;
- }
-
- return Success;
-}
-
-static int
-DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config,
- XID drawableId, XID glxDrawableId)
-{
- DrawablePtr pDraw;
- int err;
-
- LEGAL_NEW_RESOURCE(glxDrawableId, client);
-
- err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess);
- if (err != Success) {
- client->errorValue = drawableId;
- return err;
- }
- if (pDraw->type != DRAWABLE_PIXMAP) {
- client->errorValue = drawableId;
- return BadPixmap;
- }
-
- err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId,
- glxDrawableId, GLX_DRAWABLE_PIXMAP);
-
- return err;
-}
-
-static void
-determineTextureTarget(ClientPtr client, XID glxDrawableID,
- CARD32 *attribs, CARD32 numAttribs)
-{
- GLenum target = 0;
- GLenum format = 0;
- int i, err;
- __GLXdrawable *pGlxDraw;
-
- if (!validGlxDrawable(client, glxDrawableID, GLX_DRAWABLE_PIXMAP,
- DixWriteAccess, &pGlxDraw, &err))
- /* We just added it in CreatePixmap, so we should never get here. */
- return;
-
- for (i = 0; i < numAttribs; i++) {
- if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
- switch (attribs[2 * i + 1]) {
- case GLX_TEXTURE_2D_EXT:
- target = GL_TEXTURE_2D;
- break;
- case GLX_TEXTURE_RECTANGLE_EXT:
- target = GL_TEXTURE_RECTANGLE_ARB;
- break;
- }
- }
-
- if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
- format = attribs[2 * i + 1];
- }
-
- if (!target) {
- int w = pGlxDraw->pDraw->width, h = pGlxDraw->pDraw->height;
-
- if (h & (h - 1) || w & (w - 1))
- target = GL_TEXTURE_RECTANGLE_ARB;
- else
- target = GL_TEXTURE_2D;
- }
-
- pGlxDraw->target = target;
- pGlxDraw->format = format;
-}
-
-int __glXDisp_CreateGLXPixmap(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
- return err;
-
- return DoCreateGLXPixmap(cl->client, pGlxScreen, config,
- req->pixmap, req->glxpixmap);
-}
-
-int __glXDisp_CreatePixmap(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_AT_LEAST_SIZE(xGLXCreatePixmapReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXCreatePixmapReq, req->numAttribs << 3);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- err = DoCreateGLXPixmap(cl->client, pGlxScreen, config,
- req->pixmap, req->glxpixmap);
- if (err != Success)
- return err;
-
- determineTextureTarget(cl->client, req->glxpixmap,
- (CARD32*) (req + 1), req->numAttribs);
-
- return Success;
-}
-
-int __glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateGLXPixmapWithConfigSGIXReq *req =
- (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapWithConfigSGIXReq);
-
- if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- return DoCreateGLXPixmap(cl->client, pGlxScreen,
- config, req->pixmap, req->glxpixmap);
-}
-
-
-static int DoDestroyDrawable(__GLXclientState *cl, XID glxdrawable, int type)
-{
- __GLXdrawable *pGlxDraw;
- int err;
-
- if (!validGlxDrawable(cl->client, glxdrawable, type,
- DixDestroyAccess, &pGlxDraw, &err))
- return err;
-
- FreeResource(glxdrawable, FALSE);
-
- return Success;
-}
-
-int __glXDisp_DestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq);
-
- return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
-}
-
-int __glXDisp_DestroyPixmap(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc;
-
- /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set
- * length to 3 instead of 2 */
- REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq);
-
- return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
-}
-
-static int
-DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
- int width, int height, XID glxDrawableId)
-{
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- PixmapPtr pPixmap;
- int err;
-
- LEGAL_NEW_RESOURCE(glxDrawableId, client);
-
- if (!validGlxScreen(client, screenNum, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err))
- return err;
-
- __glXenterServer(GL_FALSE);
- pPixmap = (*pGlxScreen->pScreen->CreatePixmap) (pGlxScreen->pScreen,
- width, height, config->rgbBits, 0);
- __glXleaveServer(GL_FALSE);
-
- /* Assign the pixmap the same id as the pbuffer and add it as a
- * resource so it and the DRI2 drawable will be reclaimed when the
- * pbuffer is destroyed. */
- pPixmap->drawable.id = glxDrawableId;
- if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap))
- return BadAlloc;
-
- return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
- glxDrawableId, glxDrawableId,
- GLX_DRAWABLE_PBUFFER);
-}
-
-int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc;
- CARD32 *attrs;
- int width, height, i;
-
- REQUEST_AT_LEAST_SIZE(xGLXCreatePbufferReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXCreatePbufferReq, req->numAttribs << 3);
-
- attrs = (CARD32 *) (req + 1);
- width = 0;
- height = 0;
-
- for (i = 0; i < req->numAttribs; i++) {
- switch (attrs[i * 2]) {
- case GLX_PBUFFER_WIDTH:
- width = attrs[i * 2 + 1];
- break;
- case GLX_PBUFFER_HEIGHT:
- height = attrs[i * 2 + 1];
- break;
- case GLX_LARGEST_PBUFFER:
- case GLX_PRESERVED_CONTENTS:
- /* FIXME: huh... */
- break;
- }
- }
-
- return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
- width, height, req->pbuffer);
-}
-
-int __glXDisp_CreateGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc;
-
- REQUEST_AT_LEAST_SIZE(xGLXCreateGLXPbufferSGIXReq);
-
- return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
- req->width, req->height, req->pbuffer);
-}
-
-int __glXDisp_DestroyPbuffer(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXDestroyPbufferReq);
-
- return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
-}
-
-int __glXDisp_DestroyGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXDestroyGLXPbufferSGIXReq);
-
- return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
-}
-
-static int
-DoChangeDrawableAttributes(ClientPtr client, XID glxdrawable,
- int numAttribs, CARD32 *attribs)
-{
- __GLXdrawable *pGlxDraw;
- int i, err;
-
- if (!validGlxDrawable(client, glxdrawable, GLX_DRAWABLE_ANY,
- DixSetAttrAccess, &pGlxDraw, &err))
- return err;
-
- for (i = 0; i < numAttribs; i++) {
- switch(attribs[i * 2]) {
- case GLX_EVENT_MASK:
- /* All we do is to record the event mask so we can send it
- * back when queried. We never actually clobber the
- * pbuffers, so we never need to send out the event. */
- pGlxDraw->eventMask = attribs[i * 2 + 1];
- break;
- }
- }
-
- return Success;
-}
-
-int __glXDisp_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXChangeDrawableAttributesReq *req =
- (xGLXChangeDrawableAttributesReq *) pc;
-
- REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
-#if 0
- /* mesa sends an additional 8 bytes */
- REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3);
-#else
- if (((sizeof(xGLXChangeDrawableAttributesReq) + (req->numAttribs << 3)) >> 2) < client->req_len)
- return BadLength;
-#endif
-
- return DoChangeDrawableAttributes(cl->client, req->drawable,
- req->numAttribs, (CARD32 *) (req + 1));
-}
-
-int __glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXChangeDrawableAttributesSGIXReq *req =
- (xGLXChangeDrawableAttributesSGIXReq *)pc;
-
- REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesSGIXReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesSGIXReq, req->numAttribs << 3);
-
- return DoChangeDrawableAttributes(cl->client, req->drawable,
- req->numAttribs, (CARD32 *) (req + 1));
-}
-
-int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc;
- __GLXconfig *config;
- __GLXscreen *pGlxScreen;
- ClientPtr client = cl->client;
- DrawablePtr pDraw;
- int err;
-
- REQUEST_AT_LEAST_SIZE(xGLXCreateWindowReq);
- if (req->numAttribs > (UINT32_MAX >> 3)) {
- client->errorValue = req->numAttribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXCreateWindowReq, req->numAttribs << 3);
-
- LEGAL_NEW_RESOURCE(req->glxwindow, client);
-
- if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
- return err;
- if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err))
- return err;
-
- err = dixLookupDrawable(&pDraw, req->window, client, 0, DixAddAccess);
- if (err != Success || pDraw->type != DRAWABLE_WINDOW) {
- client->errorValue = req->window;
- return BadWindow;
- }
-
- if (!validGlxFBConfigForWindow(client, config, pDraw, &err))
- return err;
-
- return DoCreateGLXDrawable(client, pGlxScreen, config,
- pDraw, req->window,
- req->glxwindow, GLX_DRAWABLE_WINDOW);
-}
-
-int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc;
-
- /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */
- REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq);
-
- return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW);
-}
-
-
-/*****************************************************************************/
-
-/*
-** NOTE: There is no portable implementation for swap buffers as of
-** this time that is of value. Consequently, this code must be
-** implemented by somebody other than SGI.
-*/
-int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc;
- GLXContextTag tag;
- XID drawId;
- __GLXcontext *glxc = NULL;
- __GLXdrawable *pGlxDraw;
- int error;
-
- REQUEST_SIZE_MATCH(xGLXSwapBuffersReq);
-
- tag = req->contextTag;
- drawId = req->drawable;
- if (tag) {
- glxc = __glXLookupContextByTag(cl, tag);
- if (!glxc) {
- return __glXError(GLXBadContextTag);
- }
- /*
- ** The calling thread is swapping its current drawable. In this case,
- ** glxSwapBuffers is in both GL and X streams, in terms of
- ** sequentiality.
- */
- if (__glXForceCurrent(cl, tag, &error)) {
- /*
- ** Do whatever is needed to make sure that all preceding requests
- ** in both streams are completed before the swap is executed.
- */
- CALL_Finish( GET_DISPATCH(), () );
- glxc->hasUnflushedCommands = GL_FALSE;
- } else {
- return error;
- }
- }
-
- pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
- if (pGlxDraw == NULL)
- return error;
-
- if (pGlxDraw->type == DRAWABLE_WINDOW &&
- (*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE)
- return __glXError(GLXBadDrawable);
-
- return Success;
-}
-
-
-static int
-DoQueryContext(__GLXclientState *cl, GLXContextID gcId)
-{
- ClientPtr client = cl->client;
- __GLXcontext *ctx;
- xGLXQueryContextInfoEXTReply reply;
- int nProps;
- int *sendBuf, *pSendBuf;
- int nReplyBytes;
- int err;
-
- if (!validGlxContext(cl->client, gcId, DixReadAccess, &ctx, &err))
- return err;
-
- nProps = 3;
- reply.length = nProps << 1;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.n = nProps;
-
- nReplyBytes = reply.length << 2;
- sendBuf = (int *)malloc((size_t)nReplyBytes);
- if (sendBuf == NULL) {
- return __glXError(GLXBadContext); /* XXX: Is this correct? */
- }
- pSendBuf = sendBuf;
- *pSendBuf++ = GLX_SHARE_CONTEXT_EXT;
- *pSendBuf++ = (int)(ctx->share_id);
- *pSendBuf++ = GLX_VISUAL_ID_EXT;
- *pSendBuf++ = (int)(ctx->config->visualID);
- *pSendBuf++ = GLX_SCREEN_EXT;
- *pSendBuf++ = (int)(ctx->pGlxScreen->pScreen->myNum);
-
- if (client->swapped) {
- __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf);
- } else {
- WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, (char *)&reply);
- WriteToClient(client, nReplyBytes, (char *)sendBuf);
- }
- free((char *)sendBuf);
-
- return Success;
-}
-
-int __glXDisp_QueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryContextInfoEXTReq *req = (xGLXQueryContextInfoEXTReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXQueryContextInfoEXTReq);
-
- return DoQueryContext(cl, req->context);
-}
-
-int __glXDisp_QueryContext(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc;
-
- REQUEST_SIZE_MATCH(xGLXQueryContextReq);
-
- return DoQueryContext(cl, req->context);
-}
-
-int __glXDisp_BindTexImageEXT(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- ClientPtr client = cl->client;
- __GLXcontext *context;
- __GLXdrawable *pGlxDraw;
- GLXDrawable drawId;
- int buffer;
- int error;
- CARD32 num_attribs;
-
- if ((sizeof(xGLXVendorPrivateReq) + 12) >> 2 > client->req_len)
- return BadLength;
-
- pc += __GLX_VENDPRIV_HDR_SIZE;
-
- drawId = *((CARD32 *) (pc));
- buffer = *((INT32 *) (pc + 4));
- num_attribs = *((CARD32 *) (pc + 8));
- if (num_attribs > (UINT32_MAX >> 3)) {
- client->errorValue = num_attribs;
- return BadValue;
- }
- REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 12 + (num_attribs << 3));
-
- if (buffer != GLX_FRONT_LEFT_EXT)
- return __glXError(GLXBadPixmap);
-
- context = __glXForceCurrent (cl, req->contextTag, &error);
- if (!context)
- return error;
-
- if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
- DixReadAccess, &pGlxDraw, &error))
- return error;
-
- if (!context->textureFromPixmap)
- return __glXError(GLXUnsupportedPrivateRequest);
-
- return context->textureFromPixmap->bindTexImage(context,
- buffer,
- pGlxDraw);
-}
-
-int __glXDisp_ReleaseTexImageEXT(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- ClientPtr client = cl->client;
- __GLXdrawable *pGlxDraw;
- __GLXcontext *context;
- GLXDrawable drawId;
- int buffer;
- int error;
-
- REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8);
-
- pc += __GLX_VENDPRIV_HDR_SIZE;
-
- drawId = *((CARD32 *) (pc));
- buffer = *((INT32 *) (pc + 4));
-
- context = __glXForceCurrent (cl, req->contextTag, &error);
- if (!context)
- return error;
-
- if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
- DixReadAccess, &pGlxDraw, &error))
- return error;
-
- if (!context->textureFromPixmap)
- return __glXError(GLXUnsupportedPrivateRequest);
-
- return context->textureFromPixmap->releaseTexImage(context,
- buffer,
- pGlxDraw);
-}
-
-int __glXDisp_CopySubBufferMESA(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- GLXContextTag tag = req->contextTag;
- __GLXcontext *glxc = NULL;
- __GLXdrawable *pGlxDraw;
- ClientPtr client = cl->client;
- GLXDrawable drawId;
- int error;
- int x, y, width, height;
-
- (void) client;
- (void) req;
-
- REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 20);
-
- pc += __GLX_VENDPRIV_HDR_SIZE;
-
- drawId = *((CARD32 *) (pc));
- x = *((INT32 *) (pc + 4));
- y = *((INT32 *) (pc + 8));
- width = *((INT32 *) (pc + 12));
- height = *((INT32 *) (pc + 16));
-
- if (tag) {
- glxc = __glXLookupContextByTag(cl, tag);
- if (!glxc) {
- return __glXError(GLXBadContextTag);
- }
- /*
- ** The calling thread is swapping its current drawable. In this case,
- ** glxSwapBuffers is in both GL and X streams, in terms of
- ** sequentiality.
- */
- if (__glXForceCurrent(cl, tag, &error)) {
- /*
- ** Do whatever is needed to make sure that all preceding requests
- ** in both streams are completed before the swap is executed.
- */
- CALL_Finish( GET_DISPATCH(), () );
- glxc->hasUnflushedCommands = GL_FALSE;
- } else {
- return error;
- }
- }
-
- pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
- if (!pGlxDraw)
- return error;
-
- if (pGlxDraw == NULL ||
- pGlxDraw->type != GLX_DRAWABLE_WINDOW ||
- pGlxDraw->copySubBuffer == NULL)
- return __glXError(GLXBadDrawable);
-
- (*pGlxDraw->copySubBuffer)(pGlxDraw, x, y, width, height);
-
- return Success;
-}
-
-/*
-** Get drawable attributes
-*/
-static int
-DoGetDrawableAttributes(__GLXclientState *cl, XID drawId)
-{
- ClientPtr client = cl->client;
- xGLXGetDrawableAttributesReply reply;
- __GLXdrawable *pGlxDraw;
- CARD32 attributes[6];
- int numAttribs, error;
-
- if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
- DixGetAttrAccess, &pGlxDraw, &error))
- return error;
-
- numAttribs = 3;
- reply.length = numAttribs << 1;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.numAttribs = numAttribs;
-
- attributes[0] = GLX_TEXTURE_TARGET_EXT;
- attributes[1] = pGlxDraw->target == GL_TEXTURE_2D ? GLX_TEXTURE_2D_EXT :
- GLX_TEXTURE_RECTANGLE_EXT;
- attributes[2] = GLX_Y_INVERTED_EXT;
- attributes[3] = GL_FALSE;
- attributes[4] = GLX_EVENT_MASK;
- attributes[5] = pGlxDraw->eventMask;
-
- if (client->swapped) {
- __glXSwapGetDrawableAttributesReply(client, &reply, attributes);
- } else {
- WriteToClient(client, sz_xGLXGetDrawableAttributesReply,
- (char *)&reply);
- WriteToClient(client, reply.length * sizeof (CARD32),
- (char *)attributes);
- }
-
- return Success;
-}
-
-int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc;
-
- /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */
- REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq);
-
- return DoGetDrawableAttributes(cl, req->drawable);
-}
-
-int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXGetDrawableAttributesSGIXReq *req =
- (xGLXGetDrawableAttributesSGIXReq *)pc;
-
- REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesSGIXReq);
-
- return DoGetDrawableAttributes(cl, req->drawable);
-}
-
-/************************************************************************/
-
-/*
-** Render and Renderlarge are not in the GLX API. They are used by the GLX
-** client library to send batches of GL rendering commands.
-*/
-
-/*
-** Execute all the drawing commands in a request.
-*/
-int __glXDisp_Render(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXRenderReq *req;
- ClientPtr client= cl->client;
- int left, cmdlen, error;
- int commandsDone;
- CARD16 opcode;
- __GLXrenderHeader *hdr;
- __GLXcontext *glxc;
- __GLX_DECLARE_SWAP_VARIABLES;
-
- REQUEST_AT_LEAST_SIZE(xGLXRenderReq);
-
- req = (xGLXRenderReq *) pc;
- if (client->swapped) {
- __GLX_SWAP_SHORT(&req->length);
- __GLX_SWAP_INT(&req->contextTag);
- }
-
- glxc = __glXForceCurrent(cl, req->contextTag, &error);
- if (!glxc) {
- return error;
- }
-
- commandsDone = 0;
- pc += sz_xGLXRenderReq;
- left = (req->length << 2) - sz_xGLXRenderReq;
- while (left > 0) {
- __GLXrenderSizeData entry;
- int extra;
- __GLXdispatchRenderProcPtr proc;
- int err;
-
- if (left < sizeof(__GLXrenderHeader))
- return BadLength;
-
- /*
- ** Verify that the header length and the overall length agree.
- ** Also, each command must be word aligned.
- */
- hdr = (__GLXrenderHeader *) pc;
- if (client->swapped) {
- __GLX_SWAP_SHORT(&hdr->length);
- __GLX_SWAP_SHORT(&hdr->opcode);
- }
- cmdlen = hdr->length;
- opcode = hdr->opcode;
-
- /*
- ** Check for core opcodes and grab entry data.
- */
- err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry);
- proc = (__GLXdispatchRenderProcPtr)
- __glXGetProtocolDecodeFunction(& Render_dispatch_info,
- opcode, client->swapped);
-
- if ((err < 0) || (proc == NULL)) {
- client->errorValue = commandsDone;
- return __glXError(GLXBadRenderRequest);
- }
-
- if (entry.varsize) {
- /* variable size command */
- extra = (*entry.varsize)(pc + __GLX_RENDER_HDR_SIZE,
- client->swapped);
- if (extra < 0) {
- extra = 0;
- }
- if (cmdlen != __GLX_PAD(entry.bytes + extra)) {
- return BadLength;
- }
- } else {
- /* constant size command */
- if (cmdlen != __GLX_PAD(entry.bytes)) {
- return BadLength;
- }
- }
- if (left < cmdlen) {
- return BadLength;
- }
-
- /*
- ** Skip over the header and execute the command. We allow the
- ** caller to trash the command memory. This is useful especially
- ** for things that require double alignment - they can just shift
- ** the data towards lower memory (trashing the header) by 4 bytes
- ** and achieve the required alignment.
- */
- (*proc)(pc + __GLX_RENDER_HDR_SIZE);
- pc += cmdlen;
- left -= cmdlen;
- commandsDone++;
- }
- glxc->hasUnflushedCommands = GL_TRUE;
- return Success;
-}
-
-
-/*
-** Execute a large rendering request (one that spans multiple X requests).
-*/
-int __glXDisp_RenderLarge(__GLXclientState *cl, GLbyte *pc)
-{
- xGLXRenderLargeReq *req;
- ClientPtr client= cl->client;
- size_t dataBytes;
- __GLXrenderLargeHeader *hdr;
- __GLXcontext *glxc;
- int error;
- CARD16 opcode;
- __GLX_DECLARE_SWAP_VARIABLES;
-
- req = (xGLXRenderLargeReq *) pc;
- if (client->swapped) {
- __GLX_SWAP_SHORT(&req->length);
- __GLX_SWAP_INT(&req->contextTag);
- __GLX_SWAP_INT(&req->dataBytes);
- __GLX_SWAP_SHORT(&req->requestNumber);
- __GLX_SWAP_SHORT(&req->requestTotal);
- }
-
- glxc = __glXForceCurrent(cl, req->contextTag, &error);
- if (!glxc) {
- /* Reset in case this isn't 1st request. */
- __glXResetLargeCommandStatus(cl);
- return error;
- }
- dataBytes = req->dataBytes;
-
- /*
- ** Check the request length.
- */
- if ((req->length << 2) != __GLX_PAD(dataBytes) + sz_xGLXRenderLargeReq) {
- client->errorValue = req->length;
- /* Reset in case this isn't 1st request. */
- __glXResetLargeCommandStatus(cl);
- return BadLength;
- }
- pc += sz_xGLXRenderLargeReq;
-
- if (cl->largeCmdRequestsSoFar == 0) {
- __GLXrenderSizeData entry;
- int extra;
- size_t cmdlen;
- int err;
-
- /*
- ** This is the first request of a multi request command.
- ** Make enough space in the buffer, then copy the entire request.
- */
- if (req->requestNumber != 1) {
- client->errorValue = req->requestNumber;
- return __glXError(GLXBadLargeRequest);
- }
-
- hdr = (__GLXrenderLargeHeader *) pc;
- if (client->swapped) {
- __GLX_SWAP_INT(&hdr->length);
- __GLX_SWAP_INT(&hdr->opcode);
- }
- cmdlen = hdr->length;
- opcode = hdr->opcode;
-
- /*
- ** Check for core opcodes and grab entry data.
- */
- err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry);
- if (err < 0) {
- client->errorValue = opcode;
- return __glXError(GLXBadLargeRequest);
- }
-
- if (entry.varsize) {
- /*
- ** If it's a variable-size command (a command whose length must
- ** be computed from its parameters), all the parameters needed
- ** will be in the 1st request, so it's okay to do this.
- */
- extra = (*entry.varsize)(pc + __GLX_RENDER_LARGE_HDR_SIZE,
- client->swapped);
- if (extra < 0) {
- extra = 0;
- }
- /* large command's header is 4 bytes longer, so add 4 */
- if (cmdlen != __GLX_PAD(entry.bytes + 4 + extra)) {
- return BadLength;
- }
- } else {
- /* constant size command */
- if (cmdlen != __GLX_PAD(entry.bytes + 4)) {
- return BadLength;
- }
- }
- /*
- ** Make enough space in the buffer, then copy the entire request.
- */
- if (cl->largeCmdBufSize < cmdlen) {
- if (!cl->largeCmdBuf) {
- cl->largeCmdBuf = (GLbyte *) malloc(cmdlen);
- } else {
- cl->largeCmdBuf = (GLbyte *) realloc(cl->largeCmdBuf, cmdlen);
- }
- if (!cl->largeCmdBuf) {
- return BadAlloc;
- }
- cl->largeCmdBufSize = cmdlen;
- }
- memcpy(cl->largeCmdBuf, pc, dataBytes);
-
- cl->largeCmdBytesSoFar = dataBytes;
- cl->largeCmdBytesTotal = cmdlen;
- cl->largeCmdRequestsSoFar = 1;
- cl->largeCmdRequestsTotal = req->requestTotal;
- return Success;
-
- } else {
- /*
- ** We are receiving subsequent (i.e. not the first) requests of a
- ** multi request command.
- */
-
- /*
- ** Check the request number and the total request count.
- */
- if (req->requestNumber != cl->largeCmdRequestsSoFar + 1) {
- client->errorValue = req->requestNumber;
- __glXResetLargeCommandStatus(cl);
- return __glXError(GLXBadLargeRequest);
- }
- if (req->requestTotal != cl->largeCmdRequestsTotal) {
- client->errorValue = req->requestTotal;
- __glXResetLargeCommandStatus(cl);
- return __glXError(GLXBadLargeRequest);
- }
-
- /*
- ** Check that we didn't get too much data.
- */
- if ((cl->largeCmdBytesSoFar + dataBytes) > cl->largeCmdBytesTotal) {
- client->errorValue = dataBytes;
- __glXResetLargeCommandStatus(cl);
- return __glXError(GLXBadLargeRequest);
- }
- memcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes);
- cl->largeCmdBytesSoFar += dataBytes;
- cl->largeCmdRequestsSoFar++;
-
- if (req->requestNumber == cl->largeCmdRequestsTotal) {
- __GLXdispatchRenderProcPtr proc;
-
- /*
- ** This is the last request; it must have enough bytes to complete
- ** the command.
- */
- /* NOTE: the two pad macros have been added below; they are needed
- ** because the client library pads the total byte count, but not
- ** the per-request byte counts. The Protocol Encoding says the
- ** total byte count should not be padded, so a proposal will be
- ** made to the ARB to relax the padding constraint on the total
- ** byte count, thus preserving backward compatibility. Meanwhile,
- ** the padding done below fixes a bug that did not allow
- ** large commands of odd sizes to be accepted by the server.
- */
- if (__GLX_PAD(cl->largeCmdBytesSoFar) !=
- __GLX_PAD(cl->largeCmdBytesTotal)) {
- client->errorValue = dataBytes;
- __glXResetLargeCommandStatus(cl);
- return __glXError(GLXBadLargeRequest);
- }
- hdr = (__GLXrenderLargeHeader *) cl->largeCmdBuf;
- /*
- ** The opcode and length field in the header had already been
- ** swapped when the first request was received.
- **
- ** Use the opcode to index into the procedure table.
- */
- opcode = hdr->opcode;
-
- proc = (__GLXdispatchRenderProcPtr)
- __glXGetProtocolDecodeFunction(& Render_dispatch_info, opcode,
- client->swapped);
- if (proc == NULL) {
- client->errorValue = opcode;
- return __glXError(GLXBadLargeRequest);
- }
-
- /*
- ** Skip over the header and execute the command.
- */
- (*proc)(cl->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE);
- glxc->hasUnflushedCommands = GL_TRUE;
-
- /*
- ** Reset for the next RenderLarge series.
- */
- __glXResetLargeCommandStatus(cl);
- } else {
- /*
- ** This is neither the first nor the last request.
- */
- }
- return Success;
- }
-}
-
-/************************************************************************/
-
-/*
-** No support is provided for the vendor-private requests other than
-** allocating the entry points in the dispatch table.
-*/
-
-int __glXDisp_VendorPrivate(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- GLint vendorcode = req->vendorCode;
- __GLXdispatchVendorPrivProcPtr proc;
-
- REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
-
- proc = (__GLXdispatchVendorPrivProcPtr)
- __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info,
- vendorcode, 0);
- if (proc != NULL) {
- (*proc)(cl, (GLbyte*)req);
- return Success;
- }
-
- cl->client->errorValue = req->vendorCode;
- return __glXError(GLXUnsupportedPrivateRequest);
-}
-
-int __glXDisp_VendorPrivateWithReply(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
- GLint vendorcode = req->vendorCode;
- __GLXdispatchVendorPrivProcPtr proc;
-
- REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
-
- proc = (__GLXdispatchVendorPrivProcPtr)
- __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info,
- vendorcode, 0);
- if (proc != NULL) {
- return (*proc)(cl, (GLbyte*)req);
- }
-
- cl->client->errorValue = vendorcode;
- return __glXError(GLXUnsupportedPrivateRequest);
-}
-
-int __glXDisp_QueryExtensionsString(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc;
- xGLXQueryExtensionsStringReply reply;
- __GLXscreen *pGlxScreen;
- size_t n, length;
- char *buf;
- int err;
-
- REQUEST_SIZE_MATCH(xGLXQueryExtensionsStringReq);
-
- if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
- return err;
-
- n = strlen(pGlxScreen->GLXextensions) + 1;
- length = __GLX_PAD(n) >> 2;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.length = length;
- reply.n = n;
-
- /* Allocate buffer to make sure it's a multiple of 4 bytes big.*/
- buf = (char *) malloc(length << 2);
- if (buf == NULL)
- return BadAlloc;
- memcpy(buf, pGlxScreen->GLXextensions, n);
-
- if (client->swapped) {
- glxSwapQueryExtensionsStringReply(client, &reply, buf);
- } else {
- WriteToClient(client, sz_xGLXQueryExtensionsStringReply,(char *)&reply);
- WriteToClient(client, (int)(length << 2), (char *)buf);
- }
-
- free(buf);
- return Success;
-}
-
-int __glXDisp_QueryServerString(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc;
- xGLXQueryServerStringReply reply;
- size_t n, length;
- const char *ptr;
- char *buf;
- __GLXscreen *pGlxScreen;
- int err;
- char ver_str[16];
-
- REQUEST_SIZE_MATCH(xGLXQueryServerStringReq);
-
- if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
- return err;
-
- switch(req->name) {
- case GLX_VENDOR:
- ptr = pGlxScreen->GLXvendor;
- break;
- case GLX_VERSION:
- /* Return to the server version rather than the screen version
- * to prevent confusion when they do not match.
- */
- snprintf(ver_str, 16, "%d.%d", glxMajorVersion, glxMinorVersion);
- ptr = ver_str;
- break;
- case GLX_EXTENSIONS:
- ptr = pGlxScreen->GLXextensions;
- break;
- default:
- return BadValue;
- }
-
- n = strlen(ptr) + 1;
- length = __GLX_PAD(n) >> 2;
- reply.type = X_Reply;
- reply.sequenceNumber = client->sequence;
- reply.length = length;
- reply.n = n;
-
- buf = (char *) malloc(length << 2);
- if (buf == NULL) {
- return BadAlloc;
- }
- memcpy(buf, ptr, n);
-
- if (client->swapped) {
- glxSwapQueryServerStringReply(client, &reply, buf);
- } else {
- WriteToClient(client, sz_xGLXQueryServerStringReply, (char *)&reply);
- WriteToClient(client, (int)(length << 2), buf);
- }
-
- free(buf);
- return Success;
-}
-
-int __glXDisp_ClientInfo(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc;
- const char *buf;
-
- REQUEST_AT_LEAST_SIZE(xGLXClientInfoReq);
-
- buf = (const char *)(req+1);
- if (!memchr(buf, 0, (client->req_len << 2) - sizeof(xGLXClientInfoReq)))
- return BadLength;
-
- cl->GLClientmajorVersion = req->major;
- cl->GLClientminorVersion = req->minor;
- free(cl->GLClientextensions);
- cl->GLClientextensions = strdup(buf);
-
- return Success;
-}
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+#include <assert.h>
+
+#include "glxserver.h"
+#include <GL/glxtokens.h>
+#include <unpack.h>
+#include <pixmapstr.h>
+#include <windowstr.h>
+#include "glxutil.h"
+#include "glxext.h"
+#include "glapitable.h"
+#include "glapi.h"
+#include "glthread.h"
+#include "dispatch.h"
+#include "indirect_dispatch.h"
+#include "indirect_table.h"
+#include "indirect_util.h"
+
+static int
+validGlxScreen(ClientPtr client, int screen, __GLXscreen **pGlxScreen, int *err)
+{
+ /*
+ ** Check if screen exists.
+ */
+ if (screen < 0 || screen >= screenInfo.numScreens) {
+ client->errorValue = screen;
+ *err = BadValue;
+ return FALSE;
+ }
+ *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
+
+ return TRUE;
+}
+
+static int
+validGlxFBConfig(ClientPtr client, __GLXscreen *pGlxScreen, XID id,
+ __GLXconfig **config, int *err)
+{
+ __GLXconfig *m;
+
+ for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next)
+ if (m->fbconfigID == id) {
+ *config = m;
+ return TRUE;
+ }
+
+ client->errorValue = id;
+ *err = __glXError(GLXBadFBConfig);
+
+ return FALSE;
+}
+
+static int
+validGlxVisual(ClientPtr client, __GLXscreen *pGlxScreen, XID id,
+ __GLXconfig **config, int *err)
+{
+ int i;
+
+ for (i = 0; i < pGlxScreen->numVisuals; i++)
+ if (pGlxScreen->visuals[i]->visualID == id) {
+ *config = pGlxScreen->visuals[i];
+ return TRUE;
+ }
+
+ client->errorValue = id;
+ *err = BadValue;
+
+ return FALSE;
+}
+
+static int
+validGlxFBConfigForWindow(ClientPtr client, __GLXconfig *config,
+ DrawablePtr pDraw, int *err)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ VisualPtr pVisual = NULL;
+ XID vid;
+ int i;
+
+ vid = wVisual((WindowPtr)pDraw);
+ for (i = 0; i < pScreen->numVisuals; i++) {
+ if (pScreen->visuals[i].vid == vid) {
+ pVisual = &pScreen->visuals[i];
+ break;
+ }
+ }
+
+ /* FIXME: What exactly should we check here... */
+ if (pVisual->class != glxConvertToXVisualType(config->visualType) ||
+ !(config->drawableType & GLX_WINDOW_BIT)) {
+ client->errorValue = pDraw->id;
+ *err = BadMatch;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int
+validGlxContext(ClientPtr client, XID id, int access_mode,
+ __GLXcontext **context, int *err)
+{
+ *err = dixLookupResourceByType((pointer *) context, id,
+ __glXContextRes, client, access_mode);
+ if (*err != Success || (*context)->idExists == GL_FALSE) {
+ client->errorValue = id;
+ if (*err == BadValue || *err == Success)
+ *err = __glXError(GLXBadContext);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int
+validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
+ __GLXdrawable **drawable, int *err)
+{
+ int rc;
+
+ rc = dixLookupResourceByType((pointer *) drawable, id,
+ __glXDrawableRes, client, access_mode);
+ if (rc != Success && rc != BadValue) {
+ *err = rc;
+ client->errorValue = id;
+ return FALSE;
+ }
+
+ /* If the ID of the glx drawable we looked up doesn't match the id
+ * we looked for, it's because we looked it up under the X
+ * drawable ID (see DoCreateGLXDrawable). */
+ if (rc == BadValue ||
+ (*drawable)->drawId != id ||
+ (type != GLX_DRAWABLE_ANY && type != (*drawable)->type)) {
+ client->errorValue = id;
+ switch (type) {
+ case GLX_DRAWABLE_WINDOW:
+ *err = __glXError(GLXBadWindow);
+ return FALSE;
+ case GLX_DRAWABLE_PIXMAP:
+ *err = __glXError(GLXBadPixmap);
+ return FALSE;
+ case GLX_DRAWABLE_PBUFFER:
+ *err = __glXError(GLXBadPbuffer);
+ return FALSE;
+ case GLX_DRAWABLE_ANY:
+ *err = __glXError(GLXBadDrawable);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+void
+__glXContextDestroy(__GLXcontext *context)
+{
+ __glXFlushContextCache();
+}
+
+static void __glXdirectContextDestroy(__GLXcontext *context)
+{
+ __glXContextDestroy(context);
+ free(context);
+}
+
+static __GLXcontext *__glXdirectContextCreate(__GLXscreen *screen,
+ __GLXconfig *modes,
+ __GLXcontext *shareContext)
+{
+ __GLXcontext *context;
+
+ context = calloc(1, sizeof (__GLXcontext));
+ if (context == NULL)
+ return NULL;
+
+ context->destroy = __glXdirectContextDestroy;
+
+ return context;
+}
+
+/**
+ * Create a GL context with the given properties. This routine is used
+ * to implement \c glXCreateContext, \c glXCreateNewContext, and
+ * \c glXCreateContextWithConfigSGIX. This works becuase of the hack way
+ * that GLXFBConfigs are implemented. Basically, the FBConfigID is the
+ * same as the VisualID.
+ */
+
+static int
+DoCreateContext(__GLXclientState *cl, GLXContextID gcId,
+ GLXContextID shareList, __GLXconfig *config,
+ __GLXscreen *pGlxScreen, GLboolean isDirect)
+{
+ ClientPtr client = cl->client;
+ __GLXcontext *glxc, *shareglxc;
+ int err;
+
+ LEGAL_NEW_RESOURCE(gcId, client);
+
+ /*
+ ** Find the display list space that we want to share.
+ **
+ ** NOTE: In a multithreaded X server, we would need to keep a reference
+ ** count for each display list so that if one client detroyed a list that
+ ** another client was using, the list would not really be freed until it
+ ** was no longer in use. Since this sample implementation has no support
+ ** for multithreaded servers, we don't do this.
+ */
+ if (shareList == None) {
+ shareglxc = 0;
+ } else {
+ if (!validGlxContext(client, shareList, DixReadAccess,
+ &shareglxc, &err))
+ return err;
+
+ if (shareglxc->isDirect) {
+ /*
+ ** NOTE: no support for sharing display lists between direct
+ ** contexts, even if they are in the same address space.
+ */
+#if 0
+ /* Disabling this code seems to allow shared display lists
+ * and texture objects to work. We'll leave it disabled for now.
+ */
+ client->errorValue = shareList;
+ return BadMatch;
+#endif
+ } else {
+ /*
+ ** Create an indirect context regardless of what the client asked
+ ** for; this way we can share display list space with shareList.
+ */
+ isDirect = GL_FALSE;
+ }
+ }
+
+ /*
+ ** Allocate memory for the new context
+ */
+ if (!isDirect)
+ glxc = pGlxScreen->createContext(pGlxScreen, config, shareglxc);
+ else
+ glxc = __glXdirectContextCreate(pGlxScreen, config, shareglxc);
+ if (!glxc) {
+ return BadAlloc;
+ }
+
+ /*
+ ** Initially, setup the part of the context that could be used by
+ ** a GL core that needs windowing information (e.g., Mesa).
+ */
+ glxc->pGlxScreen = pGlxScreen;
+ glxc->config = config;
+
+ /*
+ ** Register this context as a resource.
+ */
+ if (!AddResource(gcId, __glXContextRes, (pointer)glxc)) {
+ (*glxc->destroy)(glxc);
+ client->errorValue = gcId;
+ return BadAlloc;
+ }
+
+ /*
+ ** Finally, now that everything is working, setup the rest of the
+ ** context.
+ */
+ glxc->id = gcId;
+ glxc->share_id = shareList;
+ glxc->idExists = GL_TRUE;
+ glxc->isCurrent = GL_FALSE;
+ glxc->isDirect = isDirect;
+ glxc->renderMode = GL_RENDER;
+
+ __glXAddToContextList(glxc);
+
+ return Success;
+}
+
+int __glXDisp_CreateContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateContextReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
+ return err;
+
+ return DoCreateContext(cl, req->context, req->shareList,
+ config, pGlxScreen, req->isDirect);
+}
+
+int __glXDisp_CreateNewContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateNewContextReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ return DoCreateContext(cl, req->context, req->shareList,
+ config, pGlxScreen, req->isDirect);
+}
+
+int __glXDisp_CreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateContextWithConfigSGIXReq *req =
+ (xGLXCreateContextWithConfigSGIXReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateContextWithConfigSGIXReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ return DoCreateContext(cl, req->context, req->shareList,
+ config, pGlxScreen, req->isDirect);
+}
+
+int __glXDisp_DestroyContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc;
+ __GLXcontext *glxc;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXDestroyContextReq);
+
+ if (!validGlxContext(cl->client, req->context, DixDestroyAccess,
+ &glxc, &err))
+ return err;
+
+ glxc->idExists = GL_FALSE;
+ if (!glxc->isCurrent)
+ FreeResourceByType(req->context, __glXContextRes, FALSE);
+
+ return Success;
+}
+
+/*
+ * This will return "deleted" contexts, ie, where idExists is GL_FALSE.
+ * Contrast validGlxContext, which will not. We're cheating here and
+ * using the XID as the context tag, which is fine as long as we defer
+ * actually destroying the context until it's no longer referenced, and
+ * block clients from trying to MakeCurrent on contexts that are on the
+ * way to destruction. Notice that DoMakeCurrent calls validGlxContext
+ * for new contexts but __glXLookupContextByTag for previous contexts.
+ */
+__GLXcontext *__glXLookupContextByTag(__GLXclientState *cl, GLXContextTag tag)
+{
+ __GLXcontext *ret;
+
+ if (dixLookupResourceByType((void **)&ret, tag, __glXContextRes,
+ cl->client, DixUseAccess) == Success)
+ return ret;
+
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static void StopUsingContext(__GLXcontext *glxc)
+{
+ if (glxc) {
+ if (glxc == __glXLastContext) {
+ /* Tell server GL library */
+ __glXLastContext = 0;
+ }
+ glxc->isCurrent = GL_FALSE;
+ if (!glxc->idExists) {
+ FreeResourceByType(glxc->id, __glXContextRes, FALSE);
+ }
+ }
+}
+
+static void StartUsingContext(__GLXclientState *cl, __GLXcontext *glxc)
+{
+ glxc->isCurrent = GL_TRUE;
+ __glXLastContext = glxc;
+}
+
+/**
+ * This is a helper function to handle the legacy (pre GLX 1.3) cases
+ * where passing an X window to glXMakeCurrent is valid. Given a
+ * resource ID, look up the GLX drawable if available, otherwise, make
+ * sure it's an X window and create a GLX drawable one the fly.
+ */
+static __GLXdrawable *
+__glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client,
+ int *error)
+{
+ DrawablePtr pDraw;
+ __GLXdrawable *pGlxDraw;
+ int rc;
+
+ if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
+ DixWriteAccess, &pGlxDraw, &rc)) {
+ if (glxc != NULL && pGlxDraw->config != glxc->config) {
+ client->errorValue = drawId;
+ *error = BadMatch;
+ return NULL;
+ }
+
+ return pGlxDraw;
+ }
+
+ /* No active context and an unknown drawable, bail. */
+ if (glxc == NULL) {
+ client->errorValue = drawId;
+ *error = BadMatch;
+ return NULL;
+ }
+
+ /* The drawId wasn't a GLX drawable. Make sure it's a window and
+ * create a GLXWindow for it. Check that the drawable screen
+ * matches the context screen and that the context fbconfig is
+ * compatible with the window visual. */
+
+ rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess);
+ if (rc != Success || pDraw->type != DRAWABLE_WINDOW) {
+ client->errorValue = drawId;
+ *error = __glXError(GLXBadDrawable);
+ return NULL;
+ }
+
+ if (pDraw->pScreen != glxc->pGlxScreen->pScreen) {
+ client->errorValue = pDraw->pScreen->myNum;
+ *error = BadMatch;
+ return NULL;
+ }
+
+ if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error))
+ return NULL;
+
+ pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen,
+ pDraw, drawId,
+ GLX_DRAWABLE_WINDOW,
+ drawId, glxc->config);
+
+ /* since we are creating the drawablePrivate, drawId should be new */
+ if (!AddResource(drawId, __glXDrawableRes, pGlxDraw)) {
+ pGlxDraw->destroy (pGlxDraw);
+ *error = BadAlloc;
+ return NULL;
+ }
+
+ return pGlxDraw;
+}
+
+/*****************************************************************************/
+/*
+** Make an OpenGL context and drawable current.
+*/
+
+static int
+DoMakeCurrent(__GLXclientState *cl,
+ GLXDrawable drawId, GLXDrawable readId,
+ GLXContextID contextId, GLXContextTag tag)
+{
+ ClientPtr client = cl->client;
+ xGLXMakeCurrentReply reply;
+ __GLXcontext *glxc, *prevglxc;
+ __GLXdrawable *drawPriv = NULL;
+ __GLXdrawable *readPriv = NULL;
+ int error;
+ GLuint mask;
+
+ /*
+ ** If one is None and the other isn't, it's a bad match.
+ */
+
+ mask = (drawId == None) ? (1 << 0) : 0;
+ mask |= (readId == None) ? (1 << 1) : 0;
+ mask |= (contextId == None) ? (1 << 2) : 0;
+
+ if ( (mask != 0x00) && (mask != 0x07) ) {
+ return BadMatch;
+ }
+
+ /*
+ ** Lookup old context. If we have one, it must be in a usable state.
+ */
+ if (tag != 0) {
+ prevglxc = __glXLookupContextByTag(cl, tag);
+ if (!prevglxc) {
+ /*
+ ** Tag for previous context is invalid.
+ */
+ return __glXError(GLXBadContextTag);
+ }
+ if (prevglxc->renderMode != GL_RENDER) {
+ /* Oops. Not in render mode render. */
+ client->errorValue = prevglxc->id;
+ return __glXError(GLXBadContextState);
+ }
+ } else {
+ prevglxc = 0;
+ }
+
+ /*
+ ** Lookup new context. It must not be current for someone else.
+ */
+ if (contextId != None) {
+ int status;
+
+ if (!validGlxContext(client, contextId, DixUseAccess, &glxc, &error))
+ return error;
+ if ((glxc != prevglxc) && glxc->isCurrent) {
+ /* Context is current to somebody else */
+ return BadAccess;
+ }
+
+ assert( drawId != None );
+ assert( readId != None );
+
+ drawPriv = __glXGetDrawable(glxc, drawId, client, &status);
+ if (drawPriv == NULL)
+ return status;
+
+ readPriv = __glXGetDrawable(glxc, readId, client, &status);
+ if (readPriv == NULL)
+ return status;
+
+ } else {
+ /* Switching to no context. Ignore new drawable. */
+ glxc = 0;
+ drawPriv = 0;
+ readPriv = 0;
+ }
+
+
+ if (prevglxc) {
+ /*
+ ** Flush the previous context if needed.
+ */
+ if (prevglxc->hasUnflushedCommands) {
+ if (__glXForceCurrent(cl, tag, (int *)&error)) {
+ CALL_Flush( GET_DISPATCH(), () );
+ prevglxc->hasUnflushedCommands = GL_FALSE;
+ } else {
+ return error;
+ }
+ }
+
+ /*
+ ** Make the previous context not current.
+ */
+ if (!(*prevglxc->loseCurrent)(prevglxc)) {
+ return __glXError(GLXBadContext);
+ }
+ __glXFlushContextCache();
+ if (!prevglxc->isDirect) {
+ prevglxc->drawPriv = NULL;
+ prevglxc->readPriv = NULL;
+ }
+ }
+
+
+ if ((glxc != 0) && !glxc->isDirect) {
+
+ glxc->drawPriv = drawPriv;
+ glxc->readPriv = readPriv;
+
+ /* make the context current */
+ if (!(*glxc->makeCurrent)(glxc)) {
+ glxc->drawPriv = NULL;
+ glxc->readPriv = NULL;
+ return __glXError(GLXBadContext);
+ }
+
+ glxc->isCurrent = GL_TRUE;
+ }
+
+ StopUsingContext(prevglxc);
+
+ if (glxc) {
+ StartUsingContext(cl, glxc);
+ reply.contextTag = glxc->id;
+ } else {
+ reply.contextTag = 0;
+ }
+
+ reply.length = 0;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __glXSwapMakeCurrentReply(client, &reply);
+ } else {
+ WriteToClient(client, sz_xGLXMakeCurrentReply, (char *)&reply);
+ }
+ return Success;
+}
+
+int __glXDisp_MakeCurrent(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXMakeCurrentReq);
+
+ return DoMakeCurrent( cl, req->drawable, req->drawable,
+ req->context, req->oldContextTag );
+}
+
+int __glXDisp_MakeContextCurrent(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXMakeContextCurrentReq);
+
+ return DoMakeCurrent( cl, req->drawable, req->readdrawable,
+ req->context, req->oldContextTag );
+}
+
+int __glXDisp_MakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXMakeCurrentReadSGIReq);
+
+ return DoMakeCurrent( cl, req->drawable, req->readable,
+ req->context, req->oldContextTag );
+}
+
+int __glXDisp_IsDirect(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXIsDirectReq *req = (xGLXIsDirectReq *) pc;
+ xGLXIsDirectReply reply;
+ __GLXcontext *glxc;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXIsDirectReq);
+
+ if (!validGlxContext(cl->client, req->context, DixReadAccess, &glxc, &err))
+ return err;
+
+ reply.isDirect = glxc->isDirect;
+ reply.length = 0;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __glXSwapIsDirectReply(client, &reply);
+ } else {
+ WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply);
+ }
+
+ return Success;
+}
+
+int __glXDisp_QueryVersion(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) pc;
+ xGLXQueryVersionReply reply;
+ GLuint major, minor;
+
+ REQUEST_SIZE_MATCH(xGLXQueryVersionReq);
+
+ major = req->majorVersion;
+ minor = req->minorVersion;
+ (void)major;
+ (void)minor;
+
+ /*
+ ** Server should take into consideration the version numbers sent by the
+ ** client if it wants to work with older clients; however, in this
+ ** implementation the server just returns its version number.
+ */
+ reply.majorVersion = glxMajorVersion;
+ reply.minorVersion = glxMinorVersion;
+ reply.length = 0;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __glXSwapQueryVersionReply(client, &reply);
+ } else {
+ WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply);
+ }
+ return Success;
+}
+
+int __glXDisp_WaitGL(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXWaitGLReq *req = (xGLXWaitGLReq *)pc;
+ GLXContextTag tag;
+ __GLXcontext *glxc = NULL;
+ int error;
+
+ REQUEST_SIZE_MATCH(xGLXWaitGLReq);
+
+ tag = req->contextTag;
+ if (tag) {
+ glxc = __glXLookupContextByTag(cl, tag);
+ if (!glxc)
+ return __glXError(GLXBadContextTag);
+
+ if (!__glXForceCurrent(cl, req->contextTag, &error))
+ return error;
+
+ CALL_Finish( GET_DISPATCH(), () );
+ }
+
+ if (glxc && glxc->drawPriv->waitGL)
+ (*glxc->drawPriv->waitGL)(glxc->drawPriv);
+
+ return Success;
+}
+
+int __glXDisp_WaitX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXWaitXReq *req = (xGLXWaitXReq *)pc;
+ GLXContextTag tag;
+ __GLXcontext *glxc = NULL;
+ int error;
+
+ REQUEST_SIZE_MATCH(xGLXWaitXReq);
+
+ tag = req->contextTag;
+ if (tag) {
+ glxc = __glXLookupContextByTag(cl, tag);
+ if (!glxc)
+ return __glXError(GLXBadContextTag);
+
+ if (!__glXForceCurrent(cl, req->contextTag, &error))
+ return error;
+ }
+
+ if (glxc && glxc->drawPriv->waitX)
+ (*glxc->drawPriv->waitX)(glxc->drawPriv);
+
+ return Success;
+}
+
+int __glXDisp_CopyContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc;
+ GLXContextID source;
+ GLXContextID dest;
+ GLXContextTag tag;
+ unsigned long mask;
+ __GLXcontext *src, *dst;
+ int error;
+
+ REQUEST_SIZE_MATCH(xGLXCopyContextReq);
+
+ source = req->source;
+ dest = req->dest;
+ tag = req->contextTag;
+ mask = req->mask;
+ if (!validGlxContext(cl->client, source, DixReadAccess, &src, &error))
+ return error;
+ if (!validGlxContext(cl->client, dest, DixWriteAccess, &dst, &error))
+ return error;
+
+ /*
+ ** They must be in the same address space, and same screen.
+ ** NOTE: no support for direct rendering contexts here.
+ */
+ if (src->isDirect || dst->isDirect ||
+ (src->pGlxScreen != dst->pGlxScreen)) {
+ client->errorValue = source;
+ return BadMatch;
+ }
+
+ /*
+ ** The destination context must not be current for any client.
+ */
+ if (dst->isCurrent) {
+ client->errorValue = dest;
+ return BadAccess;
+ }
+
+ if (tag) {
+ __GLXcontext *tagcx = __glXLookupContextByTag(cl, tag);
+
+ if (!tagcx) {
+ return __glXError(GLXBadContextTag);
+ }
+ if (tagcx != src) {
+ /*
+ ** This would be caused by a faulty implementation of the client
+ ** library.
+ */
+ return BadMatch;
+ }
+ /*
+ ** In this case, glXCopyContext is in both GL and X streams, in terms
+ ** of sequentiality.
+ */
+ if (__glXForceCurrent(cl, tag, &error)) {
+ /*
+ ** Do whatever is needed to make sure that all preceding requests
+ ** in both streams are completed before the copy is executed.
+ */
+ CALL_Finish( GET_DISPATCH(), () );
+ tagcx->hasUnflushedCommands = GL_FALSE;
+ } else {
+ return error;
+ }
+ }
+ /*
+ ** Issue copy. The only reason for failure is a bad mask.
+ */
+ if (!(*dst->copy)(dst, src, mask)) {
+ client->errorValue = mask;
+ return BadValue;
+ }
+ return Success;
+}
+
+enum {
+ GLX_VIS_CONFIG_UNPAIRED = 18,
+ GLX_VIS_CONFIG_PAIRED = 20
+};
+
+enum {
+ GLX_VIS_CONFIG_TOTAL = GLX_VIS_CONFIG_UNPAIRED + GLX_VIS_CONFIG_PAIRED
+};
+
+int __glXDisp_GetVisualConfigs(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc;
+ ClientPtr client = cl->client;
+ xGLXGetVisualConfigsReply reply;
+ __GLXscreen *pGlxScreen;
+ __GLXconfig *modes;
+ CARD32 buf[GLX_VIS_CONFIG_TOTAL];
+ int p, i, err;
+ __GLX_DECLARE_SWAP_VARIABLES;
+ __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
+
+ REQUEST_SIZE_MATCH(xGLXGetVisualConfigsReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+
+ reply.numVisuals = pGlxScreen->numVisuals;
+ reply.numProps = GLX_VIS_CONFIG_TOTAL;
+ reply.length = (reply.numVisuals * __GLX_SIZE_CARD32 * GLX_VIS_CONFIG_TOTAL) >> 2;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&reply.sequenceNumber);
+ __GLX_SWAP_INT(&reply.length);
+ __GLX_SWAP_INT(&reply.numVisuals);
+ __GLX_SWAP_INT(&reply.numProps);
+ }
+
+ WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char *)&reply);
+
+ for (i = 0; i < pGlxScreen->numVisuals; i++) {
+ modes = pGlxScreen->visuals[i];
+
+ p = 0;
+ buf[p++] = modes->visualID;
+ buf[p++] = glxConvertToXVisualType( modes->visualType );
+ buf[p++] = (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE;
+
+ buf[p++] = modes->redBits;
+ buf[p++] = modes->greenBits;
+ buf[p++] = modes->blueBits;
+ buf[p++] = modes->alphaBits;
+ buf[p++] = modes->accumRedBits;
+ buf[p++] = modes->accumGreenBits;
+ buf[p++] = modes->accumBlueBits;
+ buf[p++] = modes->accumAlphaBits;
+
+ buf[p++] = modes->doubleBufferMode;
+ buf[p++] = modes->stereoMode;
+
+ buf[p++] = modes->rgbBits;
+ buf[p++] = modes->depthBits;
+ buf[p++] = modes->stencilBits;
+ buf[p++] = modes->numAuxBuffers;
+ buf[p++] = modes->level;
+
+ assert(p == GLX_VIS_CONFIG_UNPAIRED);
+ /*
+ ** Add token/value pairs for extensions.
+ */
+ buf[p++] = GLX_VISUAL_CAVEAT_EXT;
+ buf[p++] = modes->visualRating;
+ buf[p++] = GLX_TRANSPARENT_TYPE;
+ buf[p++] = modes->transparentPixel;
+ buf[p++] = GLX_TRANSPARENT_RED_VALUE;
+ buf[p++] = modes->transparentRed;
+ buf[p++] = GLX_TRANSPARENT_GREEN_VALUE;
+ buf[p++] = modes->transparentGreen;
+ buf[p++] = GLX_TRANSPARENT_BLUE_VALUE;
+ buf[p++] = modes->transparentBlue;
+ buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE;
+ buf[p++] = modes->transparentAlpha;
+ buf[p++] = GLX_TRANSPARENT_INDEX_VALUE;
+ buf[p++] = modes->transparentIndex;
+ buf[p++] = GLX_SAMPLES_SGIS;
+ buf[p++] = modes->samples;
+ buf[p++] = GLX_SAMPLE_BUFFERS_SGIS;
+ buf[p++] = modes->sampleBuffers;
+ buf[p++] = 0; /* copy over visualSelectGroup (GLX_VISUAL_SELECT_GROUP_SGIX)? */
+ buf[p++] = 0;
+
+ assert(p == GLX_VIS_CONFIG_TOTAL);
+ if (client->swapped) {
+ __GLX_SWAP_INT_ARRAY(buf, p);
+ }
+ WriteToClient(client, __GLX_SIZE_CARD32 * p, (char *)buf);
+ }
+ return Success;
+}
+
+#define __GLX_TOTAL_FBCONFIG_ATTRIBS (36)
+#define __GLX_FBCONFIG_ATTRIBS_LENGTH (__GLX_TOTAL_FBCONFIG_ATTRIBS * 2)
+/**
+ * Send the set of GLXFBConfigs to the client. There is not currently
+ * and interface into the driver on the server-side to get GLXFBConfigs,
+ * so we "invent" some based on the \c __GLXvisualConfig structures that
+ * the driver does supply.
+ *
+ * The reply format for both \c glXGetFBConfigs and \c glXGetFBConfigsSGIX
+ * is the same, so this routine pulls double duty.
+ */
+
+static int
+DoGetFBConfigs(__GLXclientState *cl, unsigned screen)
+{
+ ClientPtr client = cl->client;
+ xGLXGetFBConfigsReply reply;
+ __GLXscreen *pGlxScreen;
+ CARD32 buf[__GLX_FBCONFIG_ATTRIBS_LENGTH];
+ int p, err;
+ __GLXconfig *modes;
+ __GLX_DECLARE_SWAP_VARIABLES;
+ __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
+
+ if (!validGlxScreen(cl->client, screen, &pGlxScreen, &err))
+ return err;
+
+ reply.numFBConfigs = pGlxScreen->numFBConfigs;
+ reply.numAttribs = __GLX_TOTAL_FBCONFIG_ATTRIBS;
+ reply.length = (__GLX_FBCONFIG_ATTRIBS_LENGTH * reply.numFBConfigs);
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&reply.sequenceNumber);
+ __GLX_SWAP_INT(&reply.length);
+ __GLX_SWAP_INT(&reply.numFBConfigs);
+ __GLX_SWAP_INT(&reply.numAttribs);
+ }
+
+ WriteToClient(client, sz_xGLXGetFBConfigsReply, (char *)&reply);
+
+ for (modes = pGlxScreen->fbconfigs; modes != NULL; modes = modes->next) {
+ p = 0;
+
+#define WRITE_PAIR(tag,value) \
+ do { buf[p++] = tag ; buf[p++] = value ; } while( 0 )
+
+ WRITE_PAIR( GLX_VISUAL_ID, modes->visualID );
+ WRITE_PAIR( GLX_FBCONFIG_ID, modes->fbconfigID );
+ WRITE_PAIR( GLX_X_RENDERABLE, GL_TRUE );
+
+ WRITE_PAIR( GLX_RGBA,
+ (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE );
+ WRITE_PAIR( GLX_RENDER_TYPE, modes->renderType );
+ WRITE_PAIR( GLX_DOUBLEBUFFER, modes->doubleBufferMode );
+ WRITE_PAIR( GLX_STEREO, modes->stereoMode );
+
+ WRITE_PAIR( GLX_BUFFER_SIZE, modes->rgbBits );
+ WRITE_PAIR( GLX_LEVEL, modes->level );
+ WRITE_PAIR( GLX_AUX_BUFFERS, modes->numAuxBuffers );
+ WRITE_PAIR( GLX_RED_SIZE, modes->redBits );
+ WRITE_PAIR( GLX_GREEN_SIZE, modes->greenBits );
+ WRITE_PAIR( GLX_BLUE_SIZE, modes->blueBits );
+ WRITE_PAIR( GLX_ALPHA_SIZE, modes->alphaBits );
+ WRITE_PAIR( GLX_ACCUM_RED_SIZE, modes->accumRedBits );
+ WRITE_PAIR( GLX_ACCUM_GREEN_SIZE, modes->accumGreenBits );
+ WRITE_PAIR( GLX_ACCUM_BLUE_SIZE, modes->accumBlueBits );
+ WRITE_PAIR( GLX_ACCUM_ALPHA_SIZE, modes->accumAlphaBits );
+ WRITE_PAIR( GLX_DEPTH_SIZE, modes->depthBits );
+ WRITE_PAIR( GLX_STENCIL_SIZE, modes->stencilBits );
+ WRITE_PAIR( GLX_X_VISUAL_TYPE, modes->visualType );
+ WRITE_PAIR( GLX_CONFIG_CAVEAT, modes->visualRating );
+ WRITE_PAIR( GLX_TRANSPARENT_TYPE, modes->transparentPixel );
+ WRITE_PAIR( GLX_TRANSPARENT_RED_VALUE, modes->transparentRed );
+ WRITE_PAIR( GLX_TRANSPARENT_GREEN_VALUE, modes->transparentGreen );
+ WRITE_PAIR( GLX_TRANSPARENT_BLUE_VALUE, modes->transparentBlue );
+ WRITE_PAIR( GLX_TRANSPARENT_ALPHA_VALUE, modes->transparentAlpha );
+ WRITE_PAIR( GLX_TRANSPARENT_INDEX_VALUE, modes->transparentIndex );
+ WRITE_PAIR( GLX_SWAP_METHOD_OML, modes->swapMethod );
+ WRITE_PAIR( GLX_SAMPLES_SGIS, modes->samples );
+ WRITE_PAIR( GLX_SAMPLE_BUFFERS_SGIS, modes->sampleBuffers );
+ /* GLX_VISUAL_SELECT_GROUP_SGIX ? */
+ WRITE_PAIR( GLX_DRAWABLE_TYPE, modes->drawableType );
+ WRITE_PAIR( GLX_BIND_TO_TEXTURE_RGB_EXT, modes->bindToTextureRgb );
+ WRITE_PAIR( GLX_BIND_TO_TEXTURE_RGBA_EXT, modes->bindToTextureRgba );
+ WRITE_PAIR( GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture );
+ WRITE_PAIR( GLX_BIND_TO_TEXTURE_TARGETS_EXT, modes->bindToTextureTargets );
+
+ if (client->swapped) {
+ __GLX_SWAP_INT_ARRAY(buf, __GLX_FBCONFIG_ATTRIBS_LENGTH);
+ }
+ WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_FBCONFIG_ATTRIBS_LENGTH,
+ (char *)buf);
+ }
+ return Success;
+}
+
+
+int __glXDisp_GetFBConfigs(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc;
+ REQUEST_SIZE_MATCH(xGLXGetFBConfigsReq);
+ return DoGetFBConfigs(cl, req->screen);
+}
+
+int __glXDisp_GetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc;
+ /* work around mesa bug, don't use REQUEST_SIZE_MATCH */
+ REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq);
+ return DoGetFBConfigs(cl, req->screen);
+}
+
+GLboolean
+__glXDrawableInit(__GLXdrawable *drawable,
+ __GLXscreen *screen, DrawablePtr pDraw, int type,
+ XID drawId, __GLXconfig *config)
+{
+ drawable->pDraw = pDraw;
+ drawable->type = type;
+ drawable->drawId = drawId;
+ drawable->config = config;
+ drawable->eventMask = 0;
+
+ return GL_TRUE;
+}
+
+void
+__glXDrawableRelease(__GLXdrawable *drawable)
+{
+}
+
+static int
+DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen,
+ __GLXconfig *config, DrawablePtr pDraw, XID drawableId,
+ XID glxDrawableId, int type)
+{
+ __GLXdrawable *pGlxDraw;
+
+ if (pGlxScreen->pScreen != pDraw->pScreen)
+ return BadMatch;
+
+ pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw,
+ drawableId, type,
+ glxDrawableId, config);
+ if (pGlxDraw == NULL)
+ return BadAlloc;
+
+ if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw)) {
+ pGlxDraw->destroy (pGlxDraw);
+ return BadAlloc;
+ }
+
+ /*
+ * Windows aren't refcounted, so track both the X and the GLX window
+ * so we get called regardless of destruction order.
+ */
+ if (drawableId != glxDrawableId && type == GLX_DRAWABLE_WINDOW &&
+ !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
+ pGlxDraw->destroy (pGlxDraw);
+ return BadAlloc;
+ }
+
+ return Success;
+}
+
+static int
+DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config,
+ XID drawableId, XID glxDrawableId)
+{
+ DrawablePtr pDraw;
+ int err;
+
+ LEGAL_NEW_RESOURCE(glxDrawableId, client);
+
+ err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess);
+ if (err != Success) {
+ client->errorValue = drawableId;
+ return err;
+ }
+ if (pDraw->type != DRAWABLE_PIXMAP) {
+ client->errorValue = drawableId;
+ return BadPixmap;
+ }
+
+ err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId,
+ glxDrawableId, GLX_DRAWABLE_PIXMAP);
+
+ ((PixmapPtr)pDraw)->refcnt++;
+
+ return err;
+}
+
+static void
+determineTextureTarget(ClientPtr client, XID glxDrawableID,
+ CARD32 *attribs, CARD32 numAttribs)
+{
+ GLenum target = 0;
+ GLenum format = 0;
+ int i, err;
+ __GLXdrawable *pGlxDraw;
+
+ if (!validGlxDrawable(client, glxDrawableID, GLX_DRAWABLE_PIXMAP,
+ DixWriteAccess, &pGlxDraw, &err))
+ /* We just added it in CreatePixmap, so we should never get here. */
+ return;
+
+ for (i = 0; i < numAttribs; i++) {
+ if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
+ switch (attribs[2 * i + 1]) {
+ case GLX_TEXTURE_2D_EXT:
+ target = GL_TEXTURE_2D;
+ break;
+ case GLX_TEXTURE_RECTANGLE_EXT:
+ target = GL_TEXTURE_RECTANGLE_ARB;
+ break;
+ }
+ }
+
+ if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
+ format = attribs[2 * i + 1];
+ }
+
+ if (!target) {
+ int w = pGlxDraw->pDraw->width, h = pGlxDraw->pDraw->height;
+
+ if (h & (h - 1) || w & (w - 1))
+ target = GL_TEXTURE_RECTANGLE_ARB;
+ else
+ target = GL_TEXTURE_2D;
+ }
+
+ pGlxDraw->target = target;
+ pGlxDraw->format = format;
+}
+
+int __glXDisp_CreateGLXPixmap(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
+ return err;
+
+ return DoCreateGLXPixmap(cl->client, pGlxScreen, config,
+ req->pixmap, req->glxpixmap);
+}
+
+int __glXDisp_CreatePixmap(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_AT_LEAST_SIZE(xGLXCreatePixmapReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXCreatePixmapReq, req->numAttribs << 3);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ err = DoCreateGLXPixmap(cl->client, pGlxScreen, config,
+ req->pixmap, req->glxpixmap);
+ if (err != Success)
+ return err;
+
+ determineTextureTarget(cl->client, req->glxpixmap,
+ (CARD32*) (req + 1), req->numAttribs);
+
+ return Success;
+}
+
+int __glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateGLXPixmapWithConfigSGIXReq *req =
+ (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapWithConfigSGIXReq);
+
+ if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ return DoCreateGLXPixmap(cl->client, pGlxScreen,
+ config, req->pixmap, req->glxpixmap);
+}
+
+
+static int DoDestroyDrawable(__GLXclientState *cl, XID glxdrawable, int type)
+{
+ __GLXdrawable *pGlxDraw;
+ int err;
+
+ if (!validGlxDrawable(cl->client, glxdrawable, type,
+ DixDestroyAccess, &pGlxDraw, &err))
+ return err;
+
+ FreeResource(glxdrawable, FALSE);
+
+ return Success;
+}
+
+int __glXDisp_DestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq);
+
+ return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
+}
+
+int __glXDisp_DestroyPixmap(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc;
+
+ /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set
+ * length to 3 instead of 2 */
+ REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq);
+
+ return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
+}
+
+static int
+DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
+ int width, int height, XID glxDrawableId)
+{
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ PixmapPtr pPixmap;
+ int err;
+
+ LEGAL_NEW_RESOURCE(glxDrawableId, client);
+
+ if (!validGlxScreen(client, screenNum, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err))
+ return err;
+
+ __glXenterServer(GL_FALSE);
+ pPixmap = (*pGlxScreen->pScreen->CreatePixmap) (pGlxScreen->pScreen,
+ width, height, config->rgbBits, 0);
+ __glXleaveServer(GL_FALSE);
+
+ /* Assign the pixmap the same id as the pbuffer and add it as a
+ * resource so it and the DRI2 drawable will be reclaimed when the
+ * pbuffer is destroyed. */
+ pPixmap->drawable.id = glxDrawableId;
+ if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap))
+ return BadAlloc;
+
+ return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
+ glxDrawableId, glxDrawableId,
+ GLX_DRAWABLE_PBUFFER);
+}
+
+int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc;
+ CARD32 *attrs;
+ int width, height, i;
+
+ REQUEST_AT_LEAST_SIZE(xGLXCreatePbufferReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXCreatePbufferReq, req->numAttribs << 3);
+
+ attrs = (CARD32 *) (req + 1);
+ width = 0;
+ height = 0;
+
+ for (i = 0; i < req->numAttribs; i++) {
+ switch (attrs[i * 2]) {
+ case GLX_PBUFFER_WIDTH:
+ width = attrs[i * 2 + 1];
+ break;
+ case GLX_PBUFFER_HEIGHT:
+ height = attrs[i * 2 + 1];
+ break;
+ case GLX_LARGEST_PBUFFER:
+ case GLX_PRESERVED_CONTENTS:
+ /* FIXME: huh... */
+ break;
+ }
+ }
+
+ return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
+ width, height, req->pbuffer);
+}
+
+int __glXDisp_CreateGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXCreateGLXPbufferSGIXReq);
+
+ return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
+ req->width, req->height, req->pbuffer);
+}
+
+int __glXDisp_DestroyPbuffer(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXDestroyPbufferReq);
+
+ return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
+}
+
+int __glXDisp_DestroyGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXDestroyGLXPbufferSGIXReq);
+
+ return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
+}
+
+static int
+DoChangeDrawableAttributes(ClientPtr client, XID glxdrawable,
+ int numAttribs, CARD32 *attribs)
+{
+ __GLXdrawable *pGlxDraw;
+ int i, err;
+
+ if (!validGlxDrawable(client, glxdrawable, GLX_DRAWABLE_ANY,
+ DixSetAttrAccess, &pGlxDraw, &err))
+ return err;
+
+ for (i = 0; i < numAttribs; i++) {
+ switch(attribs[i * 2]) {
+ case GLX_EVENT_MASK:
+ /* All we do is to record the event mask so we can send it
+ * back when queried. We never actually clobber the
+ * pbuffers, so we never need to send out the event. */
+ pGlxDraw->eventMask = attribs[i * 2 + 1];
+ break;
+ }
+ }
+
+ return Success;
+}
+
+int __glXDisp_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXChangeDrawableAttributesReq *req =
+ (xGLXChangeDrawableAttributesReq *) pc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+#if 0
+ /* mesa sends an additional 8 bytes */
+ REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3);
+#else
+ if (((sizeof(xGLXChangeDrawableAttributesReq) + (req->numAttribs << 3)) >> 2) < client->req_len)
+ return BadLength;
+#endif
+
+ return DoChangeDrawableAttributes(cl->client, req->drawable,
+ req->numAttribs, (CARD32 *) (req + 1));
+}
+
+int __glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXChangeDrawableAttributesSGIXReq *req =
+ (xGLXChangeDrawableAttributesSGIXReq *)pc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesSGIXReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesSGIXReq, req->numAttribs << 3);
+
+ return DoChangeDrawableAttributes(cl->client, req->drawable,
+ req->numAttribs, (CARD32 *) (req + 1));
+}
+
+int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc;
+ __GLXconfig *config;
+ __GLXscreen *pGlxScreen;
+ ClientPtr client = cl->client;
+ DrawablePtr pDraw;
+ int err;
+
+ REQUEST_AT_LEAST_SIZE(xGLXCreateWindowReq);
+ if (req->numAttribs > (UINT32_MAX >> 3)) {
+ client->errorValue = req->numAttribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXCreateWindowReq, req->numAttribs << 3);
+
+ LEGAL_NEW_RESOURCE(req->glxwindow, client);
+
+ if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
+ return err;
+ if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err))
+ return err;
+
+ err = dixLookupDrawable(&pDraw, req->window, client, 0, DixAddAccess);
+ if (err != Success || pDraw->type != DRAWABLE_WINDOW) {
+ client->errorValue = req->window;
+ return BadWindow;
+ }
+
+ if (!validGlxFBConfigForWindow(client, config, pDraw, &err))
+ return err;
+
+ return DoCreateGLXDrawable(client, pGlxScreen, config,
+ pDraw, req->window,
+ req->glxwindow, GLX_DRAWABLE_WINDOW);
+}
+
+int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc;
+
+ /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */
+ REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq);
+
+ return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW);
+}
+
+
+/*****************************************************************************/
+
+/*
+** NOTE: There is no portable implementation for swap buffers as of
+** this time that is of value. Consequently, this code must be
+** implemented by somebody other than SGI.
+*/
+int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc;
+ GLXContextTag tag;
+ XID drawId;
+ __GLXcontext *glxc = NULL;
+ __GLXdrawable *pGlxDraw;
+ int error;
+
+ REQUEST_SIZE_MATCH(xGLXSwapBuffersReq);
+
+ tag = req->contextTag;
+ drawId = req->drawable;
+ if (tag) {
+ glxc = __glXLookupContextByTag(cl, tag);
+ if (!glxc) {
+ return __glXError(GLXBadContextTag);
+ }
+ /*
+ ** The calling thread is swapping its current drawable. In this case,
+ ** glxSwapBuffers is in both GL and X streams, in terms of
+ ** sequentiality.
+ */
+ if (__glXForceCurrent(cl, tag, &error)) {
+ /*
+ ** Do whatever is needed to make sure that all preceding requests
+ ** in both streams are completed before the swap is executed.
+ */
+ CALL_Finish( GET_DISPATCH(), () );
+ glxc->hasUnflushedCommands = GL_FALSE;
+ } else {
+ return error;
+ }
+ }
+
+ pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
+ if (pGlxDraw == NULL)
+ return error;
+
+ if (pGlxDraw->type == DRAWABLE_WINDOW &&
+ (*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE)
+ return __glXError(GLXBadDrawable);
+
+ return Success;
+}
+
+
+static int
+DoQueryContext(__GLXclientState *cl, GLXContextID gcId)
+{
+ ClientPtr client = cl->client;
+ __GLXcontext *ctx;
+ xGLXQueryContextInfoEXTReply reply;
+ int nProps;
+ int *sendBuf, *pSendBuf;
+ int nReplyBytes;
+ int err;
+
+ if (!validGlxContext(cl->client, gcId, DixReadAccess, &ctx, &err))
+ return err;
+
+ nProps = 3;
+ reply.length = nProps << 1;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.n = nProps;
+
+ nReplyBytes = reply.length << 2;
+ sendBuf = (int *)malloc((size_t)nReplyBytes);
+ if (sendBuf == NULL) {
+ return __glXError(GLXBadContext); /* XXX: Is this correct? */
+ }
+ pSendBuf = sendBuf;
+ *pSendBuf++ = GLX_SHARE_CONTEXT_EXT;
+ *pSendBuf++ = (int)(ctx->share_id);
+ *pSendBuf++ = GLX_VISUAL_ID_EXT;
+ *pSendBuf++ = (int)(ctx->config->visualID);
+ *pSendBuf++ = GLX_SCREEN_EXT;
+ *pSendBuf++ = (int)(ctx->pGlxScreen->pScreen->myNum);
+
+ if (client->swapped) {
+ __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf);
+ } else {
+ WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, (char *)&reply);
+ WriteToClient(client, nReplyBytes, (char *)sendBuf);
+ }
+ free((char *)sendBuf);
+
+ return Success;
+}
+
+int __glXDisp_QueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryContextInfoEXTReq *req = (xGLXQueryContextInfoEXTReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXQueryContextInfoEXTReq);
+
+ return DoQueryContext(cl, req->context);
+}
+
+int __glXDisp_QueryContext(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc;
+
+ REQUEST_SIZE_MATCH(xGLXQueryContextReq);
+
+ return DoQueryContext(cl, req->context);
+}
+
+int __glXDisp_BindTexImageEXT(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ ClientPtr client = cl->client;
+ __GLXcontext *context;
+ __GLXdrawable *pGlxDraw;
+ GLXDrawable drawId;
+ int buffer;
+ int error;
+ CARD32 num_attribs;
+
+ if ((sizeof(xGLXVendorPrivateReq) + 12) >> 2 > client->req_len)
+ return BadLength;
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+
+ drawId = *((CARD32 *) (pc));
+ buffer = *((INT32 *) (pc + 4));
+ num_attribs = *((CARD32 *) (pc + 8));
+ if (num_attribs > (UINT32_MAX >> 3)) {
+ client->errorValue = num_attribs;
+ return BadValue;
+ }
+ REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 12 + (num_attribs << 3));
+
+ if (buffer != GLX_FRONT_LEFT_EXT)
+ return __glXError(GLXBadPixmap);
+
+ context = __glXForceCurrent (cl, req->contextTag, &error);
+ if (!context)
+ return error;
+
+ if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
+ DixReadAccess, &pGlxDraw, &error))
+ return error;
+
+ if (!context->textureFromPixmap)
+ return __glXError(GLXUnsupportedPrivateRequest);
+
+ return context->textureFromPixmap->bindTexImage(context,
+ buffer,
+ pGlxDraw);
+}
+
+int __glXDisp_ReleaseTexImageEXT(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ ClientPtr client = cl->client;
+ __GLXdrawable *pGlxDraw;
+ __GLXcontext *context;
+ GLXDrawable drawId;
+ int buffer;
+ int error;
+
+ REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+
+ drawId = *((CARD32 *) (pc));
+ buffer = *((INT32 *) (pc + 4));
+
+ context = __glXForceCurrent (cl, req->contextTag, &error);
+ if (!context)
+ return error;
+
+ if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
+ DixReadAccess, &pGlxDraw, &error))
+ return error;
+
+ if (!context->textureFromPixmap)
+ return __glXError(GLXUnsupportedPrivateRequest);
+
+ return context->textureFromPixmap->releaseTexImage(context,
+ buffer,
+ pGlxDraw);
+}
+
+int __glXDisp_CopySubBufferMESA(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ GLXContextTag tag = req->contextTag;
+ __GLXcontext *glxc = NULL;
+ __GLXdrawable *pGlxDraw;
+ ClientPtr client = cl->client;
+ GLXDrawable drawId;
+ int error;
+ int x, y, width, height;
+
+ (void) client;
+ (void) req;
+
+ REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 20);
+
+ pc += __GLX_VENDPRIV_HDR_SIZE;
+
+ drawId = *((CARD32 *) (pc));
+ x = *((INT32 *) (pc + 4));
+ y = *((INT32 *) (pc + 8));
+ width = *((INT32 *) (pc + 12));
+ height = *((INT32 *) (pc + 16));
+
+ if (tag) {
+ glxc = __glXLookupContextByTag(cl, tag);
+ if (!glxc) {
+ return __glXError(GLXBadContextTag);
+ }
+ /*
+ ** The calling thread is swapping its current drawable. In this case,
+ ** glxSwapBuffers is in both GL and X streams, in terms of
+ ** sequentiality.
+ */
+ if (__glXForceCurrent(cl, tag, &error)) {
+ /*
+ ** Do whatever is needed to make sure that all preceding requests
+ ** in both streams are completed before the swap is executed.
+ */
+ CALL_Finish( GET_DISPATCH(), () );
+ glxc->hasUnflushedCommands = GL_FALSE;
+ } else {
+ return error;
+ }
+ }
+
+ pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
+ if (!pGlxDraw)
+ return error;
+
+ if (pGlxDraw == NULL ||
+ pGlxDraw->type != GLX_DRAWABLE_WINDOW ||
+ pGlxDraw->copySubBuffer == NULL)
+ return __glXError(GLXBadDrawable);
+
+ (*pGlxDraw->copySubBuffer)(pGlxDraw, x, y, width, height);
+
+ return Success;
+}
+
+/*
+** Get drawable attributes
+*/
+static int
+DoGetDrawableAttributes(__GLXclientState *cl, XID drawId)
+{
+ ClientPtr client = cl->client;
+ xGLXGetDrawableAttributesReply reply;
+ __GLXdrawable *pGlxDraw;
+ CARD32 attributes[6];
+ int numAttribs, error;
+
+ if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
+ DixGetAttrAccess, &pGlxDraw, &error))
+ return error;
+
+ numAttribs = 3;
+ reply.length = numAttribs << 1;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.numAttribs = numAttribs;
+
+ attributes[0] = GLX_TEXTURE_TARGET_EXT;
+ attributes[1] = pGlxDraw->target == GL_TEXTURE_2D ? GLX_TEXTURE_2D_EXT :
+ GLX_TEXTURE_RECTANGLE_EXT;
+ attributes[2] = GLX_Y_INVERTED_EXT;
+ attributes[3] = GL_FALSE;
+ attributes[4] = GLX_EVENT_MASK;
+ attributes[5] = pGlxDraw->eventMask;
+
+ if (client->swapped) {
+ __glXSwapGetDrawableAttributesReply(client, &reply, attributes);
+ } else {
+ WriteToClient(client, sz_xGLXGetDrawableAttributesReply,
+ (char *)&reply);
+ WriteToClient(client, reply.length * sizeof (CARD32),
+ (char *)attributes);
+ }
+
+ return Success;
+}
+
+int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc;
+
+ /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */
+ REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq);
+
+ return DoGetDrawableAttributes(cl, req->drawable);
+}
+
+int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXGetDrawableAttributesSGIXReq *req =
+ (xGLXGetDrawableAttributesSGIXReq *)pc;
+
+ REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesSGIXReq);
+
+ return DoGetDrawableAttributes(cl, req->drawable);
+}
+
+/************************************************************************/
+
+/*
+** Render and Renderlarge are not in the GLX API. They are used by the GLX
+** client library to send batches of GL rendering commands.
+*/
+
+/*
+** Execute all the drawing commands in a request.
+*/
+int __glXDisp_Render(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXRenderReq *req;
+ ClientPtr client= cl->client;
+ int left, cmdlen, error;
+ int commandsDone;
+ CARD16 opcode;
+ __GLXrenderHeader *hdr;
+ __GLXcontext *glxc;
+ __GLX_DECLARE_SWAP_VARIABLES;
+
+ REQUEST_AT_LEAST_SIZE(xGLXRenderReq);
+
+ req = (xGLXRenderReq *) pc;
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&req->length);
+ __GLX_SWAP_INT(&req->contextTag);
+ }
+
+ glxc = __glXForceCurrent(cl, req->contextTag, &error);
+ if (!glxc) {
+ return error;
+ }
+
+ commandsDone = 0;
+ pc += sz_xGLXRenderReq;
+ left = (req->length << 2) - sz_xGLXRenderReq;
+ while (left > 0) {
+ __GLXrenderSizeData entry;
+ int extra;
+ __GLXdispatchRenderProcPtr proc;
+ int err;
+
+ if (left < sizeof(__GLXrenderHeader))
+ return BadLength;
+
+ /*
+ ** Verify that the header length and the overall length agree.
+ ** Also, each command must be word aligned.
+ */
+ hdr = (__GLXrenderHeader *) pc;
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&hdr->length);
+ __GLX_SWAP_SHORT(&hdr->opcode);
+ }
+ cmdlen = hdr->length;
+ opcode = hdr->opcode;
+
+ /*
+ ** Check for core opcodes and grab entry data.
+ */
+ err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry);
+ proc = (__GLXdispatchRenderProcPtr)
+ __glXGetProtocolDecodeFunction(& Render_dispatch_info,
+ opcode, client->swapped);
+
+ if ((err < 0) || (proc == NULL)) {
+ client->errorValue = commandsDone;
+ return __glXError(GLXBadRenderRequest);
+ }
+
+ if (entry.varsize) {
+ /* variable size command */
+ extra = (*entry.varsize)(pc + __GLX_RENDER_HDR_SIZE,
+ client->swapped);
+ if (extra < 0) {
+ extra = 0;
+ }
+ if (cmdlen != __GLX_PAD(entry.bytes + extra)) {
+ return BadLength;
+ }
+ } else {
+ /* constant size command */
+ if (cmdlen != __GLX_PAD(entry.bytes)) {
+ return BadLength;
+ }
+ }
+ if (left < cmdlen) {
+ return BadLength;
+ }
+
+ /*
+ ** Skip over the header and execute the command. We allow the
+ ** caller to trash the command memory. This is useful especially
+ ** for things that require double alignment - they can just shift
+ ** the data towards lower memory (trashing the header) by 4 bytes
+ ** and achieve the required alignment.
+ */
+ (*proc)(pc + __GLX_RENDER_HDR_SIZE);
+ pc += cmdlen;
+ left -= cmdlen;
+ commandsDone++;
+ }
+ glxc->hasUnflushedCommands = GL_TRUE;
+ return Success;
+}
+
+
+/*
+** Execute a large rendering request (one that spans multiple X requests).
+*/
+int __glXDisp_RenderLarge(__GLXclientState *cl, GLbyte *pc)
+{
+ xGLXRenderLargeReq *req;
+ ClientPtr client= cl->client;
+ size_t dataBytes;
+ __GLXrenderLargeHeader *hdr;
+ __GLXcontext *glxc;
+ int error;
+ CARD16 opcode;
+ __GLX_DECLARE_SWAP_VARIABLES;
+
+ req = (xGLXRenderLargeReq *) pc;
+ if (client->swapped) {
+ __GLX_SWAP_SHORT(&req->length);
+ __GLX_SWAP_INT(&req->contextTag);
+ __GLX_SWAP_INT(&req->dataBytes);
+ __GLX_SWAP_SHORT(&req->requestNumber);
+ __GLX_SWAP_SHORT(&req->requestTotal);
+ }
+
+ glxc = __glXForceCurrent(cl, req->contextTag, &error);
+ if (!glxc) {
+ /* Reset in case this isn't 1st request. */
+ __glXResetLargeCommandStatus(cl);
+ return error;
+ }
+ dataBytes = req->dataBytes;
+
+ /*
+ ** Check the request length.
+ */
+ if ((req->length << 2) != __GLX_PAD(dataBytes) + sz_xGLXRenderLargeReq) {
+ client->errorValue = req->length;
+ /* Reset in case this isn't 1st request. */
+ __glXResetLargeCommandStatus(cl);
+ return BadLength;
+ }
+ pc += sz_xGLXRenderLargeReq;
+
+ if (cl->largeCmdRequestsSoFar == 0) {
+ __GLXrenderSizeData entry;
+ int extra;
+ size_t cmdlen;
+ int err;
+
+ /*
+ ** This is the first request of a multi request command.
+ ** Make enough space in the buffer, then copy the entire request.
+ */
+ if (req->requestNumber != 1) {
+ client->errorValue = req->requestNumber;
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ hdr = (__GLXrenderLargeHeader *) pc;
+ if (client->swapped) {
+ __GLX_SWAP_INT(&hdr->length);
+ __GLX_SWAP_INT(&hdr->opcode);
+ }
+ cmdlen = hdr->length;
+ opcode = hdr->opcode;
+
+ /*
+ ** Check for core opcodes and grab entry data.
+ */
+ err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry);
+ if (err < 0) {
+ client->errorValue = opcode;
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ if (entry.varsize) {
+ /*
+ ** If it's a variable-size command (a command whose length must
+ ** be computed from its parameters), all the parameters needed
+ ** will be in the 1st request, so it's okay to do this.
+ */
+ extra = (*entry.varsize)(pc + __GLX_RENDER_LARGE_HDR_SIZE,
+ client->swapped);
+ if (extra < 0) {
+ extra = 0;
+ }
+ /* large command's header is 4 bytes longer, so add 4 */
+ if (cmdlen != __GLX_PAD(entry.bytes + 4 + extra)) {
+ return BadLength;
+ }
+ } else {
+ /* constant size command */
+ if (cmdlen != __GLX_PAD(entry.bytes + 4)) {
+ return BadLength;
+ }
+ }
+ /*
+ ** Make enough space in the buffer, then copy the entire request.
+ */
+ if (cl->largeCmdBufSize < cmdlen) {
+ if (!cl->largeCmdBuf) {
+ cl->largeCmdBuf = (GLbyte *) malloc(cmdlen);
+ } else {
+ cl->largeCmdBuf = (GLbyte *) realloc(cl->largeCmdBuf, cmdlen);
+ }
+ if (!cl->largeCmdBuf) {
+ return BadAlloc;
+ }
+ cl->largeCmdBufSize = cmdlen;
+ }
+ memcpy(cl->largeCmdBuf, pc, dataBytes);
+
+ cl->largeCmdBytesSoFar = dataBytes;
+ cl->largeCmdBytesTotal = cmdlen;
+ cl->largeCmdRequestsSoFar = 1;
+ cl->largeCmdRequestsTotal = req->requestTotal;
+ return Success;
+
+ } else {
+ /*
+ ** We are receiving subsequent (i.e. not the first) requests of a
+ ** multi request command.
+ */
+
+ /*
+ ** Check the request number and the total request count.
+ */
+ if (req->requestNumber != cl->largeCmdRequestsSoFar + 1) {
+ client->errorValue = req->requestNumber;
+ __glXResetLargeCommandStatus(cl);
+ return __glXError(GLXBadLargeRequest);
+ }
+ if (req->requestTotal != cl->largeCmdRequestsTotal) {
+ client->errorValue = req->requestTotal;
+ __glXResetLargeCommandStatus(cl);
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ /*
+ ** Check that we didn't get too much data.
+ */
+ if ((cl->largeCmdBytesSoFar + dataBytes) > cl->largeCmdBytesTotal) {
+ client->errorValue = dataBytes;
+ __glXResetLargeCommandStatus(cl);
+ return __glXError(GLXBadLargeRequest);
+ }
+ memcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes);
+ cl->largeCmdBytesSoFar += dataBytes;
+ cl->largeCmdRequestsSoFar++;
+
+ if (req->requestNumber == cl->largeCmdRequestsTotal) {
+ __GLXdispatchRenderProcPtr proc;
+
+ /*
+ ** This is the last request; it must have enough bytes to complete
+ ** the command.
+ */
+ /* NOTE: the two pad macros have been added below; they are needed
+ ** because the client library pads the total byte count, but not
+ ** the per-request byte counts. The Protocol Encoding says the
+ ** total byte count should not be padded, so a proposal will be
+ ** made to the ARB to relax the padding constraint on the total
+ ** byte count, thus preserving backward compatibility. Meanwhile,
+ ** the padding done below fixes a bug that did not allow
+ ** large commands of odd sizes to be accepted by the server.
+ */
+ if (__GLX_PAD(cl->largeCmdBytesSoFar) !=
+ __GLX_PAD(cl->largeCmdBytesTotal)) {
+ client->errorValue = dataBytes;
+ __glXResetLargeCommandStatus(cl);
+ return __glXError(GLXBadLargeRequest);
+ }
+ hdr = (__GLXrenderLargeHeader *) cl->largeCmdBuf;
+ /*
+ ** The opcode and length field in the header had already been
+ ** swapped when the first request was received.
+ **
+ ** Use the opcode to index into the procedure table.
+ */
+ opcode = hdr->opcode;
+
+ proc = (__GLXdispatchRenderProcPtr)
+ __glXGetProtocolDecodeFunction(& Render_dispatch_info, opcode,
+ client->swapped);
+ if (proc == NULL) {
+ client->errorValue = opcode;
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ /*
+ ** Skip over the header and execute the command.
+ */
+ (*proc)(cl->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE);
+ glxc->hasUnflushedCommands = GL_TRUE;
+
+ /*
+ ** Reset for the next RenderLarge series.
+ */
+ __glXResetLargeCommandStatus(cl);
+ } else {
+ /*
+ ** This is neither the first nor the last request.
+ */
+ }
+ return Success;
+ }
+}
+
+/************************************************************************/
+
+/*
+** No support is provided for the vendor-private requests other than
+** allocating the entry points in the dispatch table.
+*/
+
+int __glXDisp_VendorPrivate(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ GLint vendorcode = req->vendorCode;
+ __GLXdispatchVendorPrivProcPtr proc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
+
+ proc = (__GLXdispatchVendorPrivProcPtr)
+ __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info,
+ vendorcode, 0);
+ if (proc != NULL) {
+ (*proc)(cl, (GLbyte*)req);
+ return Success;
+ }
+
+ cl->client->errorValue = req->vendorCode;
+ return __glXError(GLXUnsupportedPrivateRequest);
+}
+
+int __glXDisp_VendorPrivateWithReply(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
+ GLint vendorcode = req->vendorCode;
+ __GLXdispatchVendorPrivProcPtr proc;
+
+ REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
+
+ proc = (__GLXdispatchVendorPrivProcPtr)
+ __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info,
+ vendorcode, 0);
+ if (proc != NULL) {
+ return (*proc)(cl, (GLbyte*)req);
+ }
+
+ cl->client->errorValue = vendorcode;
+ return __glXError(GLXUnsupportedPrivateRequest);
+}
+
+int __glXDisp_QueryExtensionsString(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc;
+ xGLXQueryExtensionsStringReply reply;
+ __GLXscreen *pGlxScreen;
+ size_t n, length;
+ char *buf;
+ int err;
+
+ REQUEST_SIZE_MATCH(xGLXQueryExtensionsStringReq);
+
+ if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
+ return err;
+
+ n = strlen(pGlxScreen->GLXextensions) + 1;
+ length = __GLX_PAD(n) >> 2;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = length;
+ reply.n = n;
+
+ /* Allocate buffer to make sure it's a multiple of 4 bytes big.*/
+ buf = (char *) malloc(length << 2);
+ if (buf == NULL)
+ return BadAlloc;
+ memcpy(buf, pGlxScreen->GLXextensions, n);
+
+ if (client->swapped) {
+ glxSwapQueryExtensionsStringReply(client, &reply, buf);
+ } else {
+ WriteToClient(client, sz_xGLXQueryExtensionsStringReply,(char *)&reply);
+ WriteToClient(client, (int)(length << 2), (char *)buf);
+ }
+
+ free(buf);
+ return Success;
+}
+
+int __glXDisp_QueryServerString(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc;
+ xGLXQueryServerStringReply reply;
+ size_t n, length;
+ const char *ptr;
+ char *buf;
+ __GLXscreen *pGlxScreen;
+ int err;
+ char ver_str[16];
+
+ REQUEST_SIZE_MATCH(xGLXQueryServerStringReq);
+
+ if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
+ return err;
+
+ switch(req->name) {
+ case GLX_VENDOR:
+ ptr = pGlxScreen->GLXvendor;
+ break;
+ case GLX_VERSION:
+ /* Return to the server version rather than the screen version
+ * to prevent confusion when they do not match.
+ */
+ snprintf(ver_str, 16, "%d.%d", glxMajorVersion, glxMinorVersion);
+ ptr = ver_str;
+ break;
+ case GLX_EXTENSIONS:
+ ptr = pGlxScreen->GLXextensions;
+ break;
+ default:
+ return BadValue;
+ }
+
+ n = strlen(ptr) + 1;
+ length = __GLX_PAD(n) >> 2;
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = length;
+ reply.n = n;
+
+ buf = (char *) malloc(length << 2);
+ if (buf == NULL) {
+ return BadAlloc;
+ }
+ memcpy(buf, ptr, n);
+
+ if (client->swapped) {
+ glxSwapQueryServerStringReply(client, &reply, buf);
+ } else {
+ WriteToClient(client, sz_xGLXQueryServerStringReply, (char *)&reply);
+ WriteToClient(client, (int)(length << 2), buf);
+ }
+
+ free(buf);
+ return Success;
+}
+
+int __glXDisp_ClientInfo(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc;
+ const char *buf;
+
+ REQUEST_AT_LEAST_SIZE(xGLXClientInfoReq);
+
+ buf = (const char *)(req+1);
+ if (!memchr(buf, 0, (client->req_len << 2) - sizeof(xGLXClientInfoReq)))
+ return BadLength;
+
+ cl->GLClientmajorVersion = req->major;
+ cl->GLClientminorVersion = req->minor;
+ free(cl->GLClientextensions);
+ cl->GLClientextensions = strdup(buf);
+
+ return Success;
+}
diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c
index db0d3d999..d97971739 100644
--- a/xorg-server/glx/glxdri2.c
+++ b/xorg-server/glx/glxdri2.c
@@ -1,791 +1,792 @@
-/*
- * Copyright © 2007 Red Hat, Inc
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without
- * fee, provided that the above copyright notice appear in all copies
- * and that both that copyright notice and this permission notice
- * appear in supporting documentation, and that the name of Red Hat,
- * Inc not be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission. Red Hat, Inc makes no representations about the
- * suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
- * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
- * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <dlfcn.h>
-
-#include <drm.h>
-#include <GL/gl.h>
-#include <GL/internal/dri_interface.h>
-#include <GL/glxtokens.h>
-
-#include <windowstr.h>
-#include <os.h>
-
-#define _XF86DRI_SERVER_
-#include <xf86drm.h>
-#include <xf86.h>
-#include <dri2.h>
-
-#include "glxserver.h"
-#include "glxutil.h"
-#include "glxdricommon.h"
-
-#include "glapitable.h"
-#include "glapi.h"
-#include "glthread.h"
-#include "dispatch.h"
-#include "extension_string.h"
-
-typedef struct __GLXDRIscreen __GLXDRIscreen;
-typedef struct __GLXDRIcontext __GLXDRIcontext;
-typedef struct __GLXDRIdrawable __GLXDRIdrawable;
-
-struct __GLXDRIscreen {
- __GLXscreen base;
- __DRIscreen *driScreen;
- void *driver;
- int fd;
-
- xf86EnterVTProc *enterVT;
- xf86LeaveVTProc *leaveVT;
-
- const __DRIcoreExtension *core;
- const __DRIdri2Extension *dri2;
- const __DRI2flushExtension *flush;
- const __DRIcopySubBufferExtension *copySubBuffer;
- const __DRIswapControlExtension *swapControl;
- const __DRItexBufferExtension *texBuffer;
-
- unsigned char glx_enable_bits[__GLX_EXT_BYTES];
-};
-
-struct __GLXDRIcontext {
- __GLXcontext base;
- __DRIcontext *driContext;
-};
-
-#define MAX_DRAWABLE_BUFFERS 5
-
-struct __GLXDRIdrawable {
- __GLXdrawable base;
- __DRIdrawable *driDrawable;
- __GLXDRIscreen *screen;
-
- /* Dimensions as last reported by DRI2GetBuffers. */
- int width;
- int height;
- __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
- int count;
-};
-
-static void
-__glXDRIdrawableDestroy(__GLXdrawable *drawable)
-{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- const __DRIcoreExtension *core = private->screen->core;
-
- (*core->destroyDrawable)(private->driDrawable);
-
- __glXDrawableRelease(drawable);
-
- free(private);
-}
-
-static void
-__glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
- int x, int y, int w, int h)
-{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- BoxRec box;
- RegionRec region;
-
- box.x1 = x;
- box.y1 = private->height - y - h;
- box.x2 = x + w;
- box.y2 = private->height - y;
- RegionInit(&region, &box, 0);
-
- DRI2CopyRegion(drawable->pDraw, &region,
- DRI2BufferFrontLeft, DRI2BufferBackLeft);
-}
-
-static void
-__glXDRIdrawableWaitX(__GLXdrawable *drawable)
-{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = private->width;
- box.y2 = private->height;
- RegionInit(&region, &box, 0);
-
- DRI2CopyRegion(drawable->pDraw, &region,
- DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
-}
-
-static void
-__glXDRIdrawableWaitGL(__GLXdrawable *drawable)
-{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = private->width;
- box.y2 = private->height;
- RegionInit(&region, &box, 0);
-
- DRI2CopyRegion(drawable->pDraw, &region,
- DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
-}
-
-static void
-__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
- CARD64 msc, CARD64 sbc)
-{
- __GLXdrawable *drawable = data;
- xGLXBufferSwapComplete wire;
-
- if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
- return;
-
- wire.type = __glXEventBase + GLX_BufferSwapComplete;
- switch (type) {
- case DRI2_EXCHANGE_COMPLETE:
- wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL;
- break;
- case DRI2_BLIT_COMPLETE:
- wire.event_type = GLX_BLIT_COMPLETE_INTEL;
- break;
- case DRI2_FLIP_COMPLETE:
- wire.event_type = GLX_FLIP_COMPLETE_INTEL;
- break;
- default:
- /* unknown swap completion type */
- break;
- }
- wire.drawable = drawable->drawId;
- wire.ust_hi = ust >> 32;
- wire.ust_lo = ust & 0xffffffff;
- wire.msc_hi = msc >> 32;
- wire.msc_lo = msc & 0xffffffff;
- wire.sbc_hi = sbc >> 32;
- wire.sbc_lo = sbc & 0xffffffff;
-
- WriteEventsToClient(client, 1, (xEvent *) &wire);
-}
-
-/*
- * Copy or flip back to front, honoring the swap interval if possible.
- *
- * If the kernel supports it, we request an event for the frame when the
- * swap should happen, then perform the copy when we receive it.
- */
-static GLboolean
-__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
-{
- __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
- __GLXDRIscreen *screen = priv->screen;
- CARD64 unused;
-
-#if __DRI2_FLUSH_VERSION >= 3
- if (screen->flush) {
- (*screen->flush->flush)(priv->driDrawable);
- (*screen->flush->invalidate)(priv->driDrawable);
- }
-#else
- if (screen->flush)
- (*screen->flush->flushInvalidate)(priv->driDrawable);
-#endif
-
- if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
- __glXdriSwapEvent, drawable->pDraw) != Success)
- return FALSE;
-
- return TRUE;
-}
-
-static int
-__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
-{
- if (interval <= 0) /* || interval > BIGNUM? */
- return GLX_BAD_VALUE;
-
- DRI2SwapInterval(drawable->pDraw, interval);
-
- return 0;
-}
-
-static void
-__glXDRIcontextDestroy(__GLXcontext *baseContext)
-{
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
-
- (*screen->core->destroyContext)(context->driContext);
- __glXContextDestroy(&context->base);
- free(context);
-}
-
-static int
-__glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
-{
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
- __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
-
- return (*screen->core->bindContext)(context->driContext,
- draw->driDrawable,
- read->driDrawable);
-}
-
-static int
-__glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
-{
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
-
- return (*screen->core->unbindContext)(context->driContext);
-}
-
-static int
-__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
- unsigned long mask)
-{
- __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
- __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
- __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
-
- return (*screen->core->copyContext)(dst->driContext,
- src->driContext, mask);
-}
-
-static Bool
-__glXDRIcontextWait(__GLXcontext *baseContext,
- __GLXclientState *cl, int *error)
-{
- if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
- *error = cl->client->noClientException;
- return TRUE;
- }
-
- return FALSE;
-}
-
-#ifdef __DRI_TEX_BUFFER
-
-static int
-__glXDRIbindTexImage(__GLXcontext *baseContext,
- int buffer,
- __GLXdrawable *glxPixmap)
-{
- __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
- const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
- __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
-
- if (texBuffer == NULL)
- return Success;
-
-#if __DRI_TEX_BUFFER_VERSION >= 2
- if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
- (*texBuffer->setTexBuffer2)(context->driContext,
- glxPixmap->target,
- glxPixmap->format,
- drawable->driDrawable);
- } else
-#endif
- {
- texBuffer->setTexBuffer(context->driContext,
- glxPixmap->target,
- drawable->driDrawable);
- }
-
- return Success;
-}
-
-static int
-__glXDRIreleaseTexImage(__GLXcontext *baseContext,
- int buffer,
- __GLXdrawable *pixmap)
-{
- /* FIXME: Just unbind the texture? */
- return Success;
-}
-
-#else
-
-static int
-__glXDRIbindTexImage(__GLXcontext *baseContext,
- int buffer,
- __GLXdrawable *glxPixmap)
-{
- return Success;
-}
-
-static int
-__glXDRIreleaseTexImage(__GLXcontext *baseContext,
- int buffer,
- __GLXdrawable *pixmap)
-{
- return Success;
-}
-
-#endif
-
-static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
- __glXDRIbindTexImage,
- __glXDRIreleaseTexImage
-};
-
-static void
-__glXDRIscreenDestroy(__GLXscreen *baseScreen)
-{
- __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
-
- (*screen->core->destroyScreen)(screen->driScreen);
-
- dlclose(screen->driver);
-
- __glXScreenDestroy(baseScreen);
-
- free(screen);
-}
-
-static __GLXcontext *
-__glXDRIscreenCreateContext(__GLXscreen *baseScreen,
- __GLXconfig *glxConfig,
- __GLXcontext *baseShareContext)
-{
- __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
- __GLXDRIcontext *context, *shareContext;
- __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
- __DRIcontext *driShare;
-
- shareContext = (__GLXDRIcontext *) baseShareContext;
- if (shareContext)
- driShare = shareContext->driContext;
- else
- driShare = NULL;
-
- context = calloc(1, sizeof *context);
- if (context == NULL)
- return NULL;
-
- context->base.destroy = __glXDRIcontextDestroy;
- context->base.makeCurrent = __glXDRIcontextMakeCurrent;
- context->base.loseCurrent = __glXDRIcontextLoseCurrent;
- context->base.copy = __glXDRIcontextCopy;
- context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
- context->base.wait = __glXDRIcontextWait;
-
- context->driContext =
- (*screen->dri2->createNewContext)(screen->driScreen,
- config->driConfig,
- driShare, context);
- if (context->driContext == NULL) {
- free(context);
- return NULL;
- }
-
- return &context->base;
-}
-
-static void
-__glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv)
-{
-#if __DRI2_FLUSH_VERSION >= 3
- __GLXDRIdrawable *private = priv;
- __GLXDRIscreen *screen = private->screen;
-
- if (screen->flush)
- (*screen->flush->invalidate)(private->driDrawable);
-#endif
-}
-
-static __GLXdrawable *
-__glXDRIscreenCreateDrawable(ClientPtr client,
- __GLXscreen *screen,
- DrawablePtr pDraw,
- XID drawId,
- int type,
- XID glxDrawId,
- __GLXconfig *glxConfig)
-{
- __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
- __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
- __GLXDRIdrawable *private;
-
- private = calloc(1, sizeof *private);
- if (private == NULL)
- return NULL;
-
- private->screen = driScreen;
- if (!__glXDrawableInit(&private->base, screen,
- pDraw, type, glxDrawId, glxConfig)) {
- free(private);
- return NULL;
- }
-
- private->base.destroy = __glXDRIdrawableDestroy;
- private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
- private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
- private->base.waitGL = __glXDRIdrawableWaitGL;
- private->base.waitX = __glXDRIdrawableWaitX;
-
- if (DRI2CreateDrawable(client, pDraw, drawId,
- __glXDRIinvalidateBuffers, private)) {
- free(private);
- return NULL;
- }
-
- private->driDrawable =
- (*driScreen->dri2->createNewDrawable)(driScreen->driScreen,
- config->driConfig, private);
-
- return &private->base;
-}
-
-static __DRIbuffer *
-dri2GetBuffers(__DRIdrawable *driDrawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *out_count, void *loaderPrivate)
-{
- __GLXDRIdrawable *private = loaderPrivate;
- DRI2BufferPtr *buffers;
- int i;
- int j;
-
- buffers = DRI2GetBuffers(private->base.pDraw,
- width, height, attachments, count, out_count);
- if (*out_count > MAX_DRAWABLE_BUFFERS) {
- *out_count = 0;
- return NULL;
- }
-
- private->width = *width;
- private->height = *height;
-
- /* This assumes the DRI2 buffer attachment tokens matches the
- * __DRIbuffer tokens. */
- j = 0;
- for (i = 0; i < *out_count; i++) {
- /* Do not send the real front buffer of a window to the client.
- */
- if ((private->base.pDraw->type == DRAWABLE_WINDOW)
- && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
- continue;
- }
-
- private->buffers[j].attachment = buffers[i]->attachment;
- private->buffers[j].name = buffers[i]->name;
- private->buffers[j].pitch = buffers[i]->pitch;
- private->buffers[j].cpp = buffers[i]->cpp;
- private->buffers[j].flags = buffers[i]->flags;
- j++;
- }
-
- *out_count = j;
- return private->buffers;
-}
-
-static __DRIbuffer *
-dri2GetBuffersWithFormat(__DRIdrawable *driDrawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *out_count, void *loaderPrivate)
-{
- __GLXDRIdrawable *private = loaderPrivate;
- DRI2BufferPtr *buffers;
- int i;
- int j = 0;
-
- buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
- width, height, attachments, count,
- out_count);
- if (*out_count > MAX_DRAWABLE_BUFFERS) {
- *out_count = 0;
- return NULL;
- }
-
- private->width = *width;
- private->height = *height;
-
- /* This assumes the DRI2 buffer attachment tokens matches the
- * __DRIbuffer tokens. */
- for (i = 0; i < *out_count; i++) {
- /* Do not send the real front buffer of a window to the client.
- */
- if ((private->base.pDraw->type == DRAWABLE_WINDOW)
- && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
- continue;
- }
-
- private->buffers[j].attachment = buffers[i]->attachment;
- private->buffers[j].name = buffers[i]->name;
- private->buffers[j].pitch = buffers[i]->pitch;
- private->buffers[j].cpp = buffers[i]->cpp;
- private->buffers[j].flags = buffers[i]->flags;
- j++;
- }
-
- *out_count = j;
- return private->buffers;
-}
-
-static void
-dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
-{
- (void) driDrawable;
- __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate);
-}
-
-static const __DRIdri2LoaderExtension loaderExtension = {
- { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
- dri2GetBuffers,
- dri2FlushFrontBuffer,
- dri2GetBuffersWithFormat,
-};
-
-#ifdef __DRI_USE_INVALIDATE
-static const __DRIuseInvalidateExtension dri2UseInvalidate = {
- { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION }
-};
-#endif
-
-static const __DRIextension *loader_extensions[] = {
- &systemTimeExtension.base,
- &loaderExtension.base,
-#ifdef __DRI_USE_INVALIDATE
- &dri2UseInvalidate.base,
-#endif
- NULL
-};
-
-static Bool
-glxDRIEnterVT (int index, int flags)
-{
- ScrnInfoPtr scrn = xf86Screens[index];
- Bool ret;
- __GLXDRIscreen *screen = (__GLXDRIscreen *)
- glxGetScreen(screenInfo.screens[index]);
-
- LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
-
- scrn->EnterVT = screen->enterVT;
-
- ret = scrn->EnterVT (index, flags);
-
- screen->enterVT = scrn->EnterVT;
- scrn->EnterVT = glxDRIEnterVT;
-
- if (!ret)
- return FALSE;
-
- glxResumeClients();
-
- return TRUE;
-}
-
-static void
-glxDRILeaveVT (int index, int flags)
-{
- ScrnInfoPtr scrn = xf86Screens[index];
- __GLXDRIscreen *screen = (__GLXDRIscreen *)
- glxGetScreen(screenInfo.screens[index]);
-
- LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n");
-
- glxSuspendClients();
-
- scrn->LeaveVT = screen->leaveVT;
- (*screen->leaveVT) (index, flags);
- screen->leaveVT = scrn->LeaveVT;
- scrn->LeaveVT = glxDRILeaveVT;
-}
-
-static void
-initializeExtensions(__GLXDRIscreen *screen)
-{
- ScreenPtr pScreen = screen->base.pScreen;
- const __DRIextension **extensions;
- int i;
-
- extensions = screen->core->getExtensions(screen->driScreen);
-
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_MESA_copy_sub_buffer");
- LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
-
- __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
- LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
-
- if (DRI2HasSwapControl(pScreen)) {
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_SGI_swap_control");
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_MESA_swap_control");
- LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
- }
-
- for (i = 0; extensions[i]; i++) {
-#ifdef __DRI_READ_DRAWABLE
- if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
- __glXEnableExtension(screen->glx_enable_bits,
- "GLX_SGI_make_current_read");
-
- LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
- }
-#endif
-
-#ifdef __DRI_TEX_BUFFER
- if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
- screen->texBuffer =
- (const __DRItexBufferExtension *) extensions[i];
- /* GLX_EXT_texture_from_pixmap is always enabled. */
- LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
- }
-#endif
-
-#ifdef __DRI2_FLUSH
- if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
- extensions[i]->version >= 3) {
- screen->flush = (__DRI2flushExtension *) extensions[i];
- }
-#endif
-
- /* Ignore unknown extensions */
- }
-}
-
-static __GLXscreen *
-__glXDRIscreenProbe(ScreenPtr pScreen)
-{
- const char *driverName, *deviceName;
- __GLXDRIscreen *screen;
- size_t buffer_size;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- const __DRIconfig **driConfigs;
-
- screen = calloc(1, sizeof *screen);
- if (screen == NULL)
- return NULL;
-
- if (!xf86LoaderCheckSymbol("DRI2Connect") ||
- !DRI2Connect(pScreen, DRI2DriverDRI,
- &screen->fd, &driverName, &deviceName)) {
- LogMessage(X_INFO,
- "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
- return NULL;
- }
-
- screen->base.destroy = __glXDRIscreenDestroy;
- screen->base.createContext = __glXDRIscreenCreateContext;
- screen->base.createDrawable = __glXDRIscreenCreateDrawable;
- screen->base.swapInterval = __glXDRIdrawableSwapInterval;
- screen->base.pScreen = pScreen;
-
- __glXInitExtensionEnableBits(screen->glx_enable_bits);
-
- screen->driver = glxProbeDriver(driverName, (void **)&screen->core, __DRI_CORE, 1,
- (void **)&screen->dri2, __DRI_DRI2, 1);
- if (screen->driver == NULL) {
- goto handle_error;
- }
-
- screen->driScreen =
- (*screen->dri2->createNewScreen)(pScreen->myNum,
- screen->fd,
- loader_extensions,
- &driConfigs,
- screen);
-
- if (screen->driScreen == NULL) {
- LogMessage(X_ERROR,
- "AIGLX error: Calling driver entry point failed\n");
- goto handle_error;
- }
-
- initializeExtensions(screen);
-
- screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs,
- GLX_WINDOW_BIT |
- GLX_PIXMAP_BIT |
- GLX_PBUFFER_BIT);
-
- __glXScreenInit(&screen->base, pScreen);
-
- /* The first call simply determines the length of the extension string.
- * This allows us to allocate some memory to hold the extension string,
- * but it requires that we call __glXGetExtensionString a second time.
- */
- buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
- if (buffer_size > 0) {
- free(screen->base.GLXextensions);
-
- screen->base.GLXextensions = xnfalloc(buffer_size);
- (void) __glXGetExtensionString(screen->glx_enable_bits,
- screen->base.GLXextensions);
- }
-
- /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled
- * drivers support the required extensions for GLX 1.4. The extensions
- * we're assuming are:
- *
- * - GLX_SGI_make_current_read (1.3)
- * - GLX_SGIX_fbconfig (1.3)
- * - GLX_SGIX_pbuffer (1.3)
- * - GLX_ARB_multisample (1.4)
- */
- screen->base.GLXmajor = 1;
- screen->base.GLXminor = 4;
-
- screen->enterVT = pScrn->EnterVT;
- pScrn->EnterVT = glxDRIEnterVT;
- screen->leaveVT = pScrn->LeaveVT;
- pScrn->LeaveVT = glxDRILeaveVT;
-
- LogMessage(X_INFO,
- "AIGLX: Loaded and initialized %s\n", driverName);
-
- return &screen->base;
-
- handle_error:
- if (screen->driver)
- dlclose(screen->driver);
-
- free(screen);
-
- LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
-
- return NULL;
-}
-
-_X_EXPORT __GLXprovider __glXDRI2Provider = {
- __glXDRIscreenProbe,
- "DRI2",
- NULL
-};
+/*
+ * Copyright © 2007 Red Hat, Inc
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Red Hat,
+ * Inc not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <dlfcn.h>
+
+#include <drm.h>
+#include <GL/gl.h>
+#include <GL/internal/dri_interface.h>
+#include <GL/glxtokens.h>
+
+#include <windowstr.h>
+#include <os.h>
+
+#define _XF86DRI_SERVER_
+#include <xf86drm.h>
+#include <xf86.h>
+#include <dri2.h>
+
+#include "glxserver.h"
+#include "glxutil.h"
+#include "glxdricommon.h"
+
+#include "glapitable.h"
+#include "glapi.h"
+#include "glthread.h"
+#include "dispatch.h"
+#include "extension_string.h"
+
+typedef struct __GLXDRIscreen __GLXDRIscreen;
+typedef struct __GLXDRIcontext __GLXDRIcontext;
+typedef struct __GLXDRIdrawable __GLXDRIdrawable;
+
+struct __GLXDRIscreen {
+ __GLXscreen base;
+ __DRIscreen *driScreen;
+ void *driver;
+ int fd;
+
+ xf86EnterVTProc *enterVT;
+ xf86LeaveVTProc *leaveVT;
+
+ const __DRIcoreExtension *core;
+ const __DRIdri2Extension *dri2;
+ const __DRI2flushExtension *flush;
+ const __DRIcopySubBufferExtension *copySubBuffer;
+ const __DRIswapControlExtension *swapControl;
+ const __DRItexBufferExtension *texBuffer;
+
+ unsigned char glx_enable_bits[__GLX_EXT_BYTES];
+};
+
+struct __GLXDRIcontext {
+ __GLXcontext base;
+ __DRIcontext *driContext;
+};
+
+#define MAX_DRAWABLE_BUFFERS 5
+
+struct __GLXDRIdrawable {
+ __GLXdrawable base;
+ __DRIdrawable *driDrawable;
+ __GLXDRIscreen *screen;
+
+ /* Dimensions as last reported by DRI2GetBuffers. */
+ int width;
+ int height;
+ __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
+ int count;
+};
+
+static void
+__glXDRIdrawableDestroy(__GLXdrawable *drawable)
+{
+ __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+ const __DRIcoreExtension *core = private->screen->core;
+
+ (*core->destroyDrawable)(private->driDrawable);
+
+ __glXDrawableRelease(drawable);
+
+ free(private);
+}
+
+static void
+__glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
+ int x, int y, int w, int h)
+{
+ __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = x;
+ box.y1 = private->height - y - h;
+ box.x2 = x + w;
+ box.y2 = private->height - y;
+ RegionInit(&region, &box, 0);
+
+ DRI2CopyRegion(drawable->pDraw, &region,
+ DRI2BufferFrontLeft, DRI2BufferBackLeft);
+}
+
+static void
+__glXDRIdrawableWaitX(__GLXdrawable *drawable)
+{
+ __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = private->width;
+ box.y2 = private->height;
+ RegionInit(&region, &box, 0);
+
+ DRI2CopyRegion(drawable->pDraw, &region,
+ DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+}
+
+static void
+__glXDRIdrawableWaitGL(__GLXdrawable *drawable)
+{
+ __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = private->width;
+ box.y2 = private->height;
+ RegionInit(&region, &box, 0);
+
+ DRI2CopyRegion(drawable->pDraw, &region,
+ DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
+}
+
+static void
+__glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
+ CARD64 msc, CARD64 sbc)
+{
+ __GLXdrawable *drawable = data;
+ xGLXBufferSwapComplete wire;
+
+ if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
+ return;
+
+ wire.type = __glXEventBase + GLX_BufferSwapComplete;
+ switch (type) {
+ case DRI2_EXCHANGE_COMPLETE:
+ wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL;
+ break;
+ case DRI2_BLIT_COMPLETE:
+ wire.event_type = GLX_BLIT_COMPLETE_INTEL;
+ break;
+ case DRI2_FLIP_COMPLETE:
+ wire.event_type = GLX_FLIP_COMPLETE_INTEL;
+ break;
+ default:
+ /* unknown swap completion type */
+ wire.event_type = 0;
+ break;
+ }
+ wire.drawable = drawable->drawId;
+ wire.ust_hi = ust >> 32;
+ wire.ust_lo = ust & 0xffffffff;
+ wire.msc_hi = msc >> 32;
+ wire.msc_lo = msc & 0xffffffff;
+ wire.sbc_hi = sbc >> 32;
+ wire.sbc_lo = sbc & 0xffffffff;
+
+ WriteEventsToClient(client, 1, (xEvent *) &wire);
+}
+
+/*
+ * Copy or flip back to front, honoring the swap interval if possible.
+ *
+ * If the kernel supports it, we request an event for the frame when the
+ * swap should happen, then perform the copy when we receive it.
+ */
+static GLboolean
+__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
+{
+ __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
+ __GLXDRIscreen *screen = priv->screen;
+ CARD64 unused;
+
+#if __DRI2_FLUSH_VERSION >= 3
+ if (screen->flush) {
+ (*screen->flush->flush)(priv->driDrawable);
+ (*screen->flush->invalidate)(priv->driDrawable);
+ }
+#else
+ if (screen->flush)
+ (*screen->flush->flushInvalidate)(priv->driDrawable);
+#endif
+
+ if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
+ __glXdriSwapEvent, drawable->pDraw) != Success)
+ return FALSE;
+
+ return TRUE;
+}
+
+static int
+__glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
+{
+ if (interval <= 0) /* || interval > BIGNUM? */
+ return GLX_BAD_VALUE;
+
+ DRI2SwapInterval(drawable->pDraw, interval);
+
+ return 0;
+}
+
+static void
+__glXDRIcontextDestroy(__GLXcontext *baseContext)
+{
+ __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
+
+ (*screen->core->destroyContext)(context->driContext);
+ __glXContextDestroy(&context->base);
+ free(context);
+}
+
+static int
+__glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
+{
+ __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
+ __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
+ __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
+
+ return (*screen->core->bindContext)(context->driContext,
+ draw->driDrawable,
+ read->driDrawable);
+}
+
+static int
+__glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
+{
+ __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
+
+ return (*screen->core->unbindContext)(context->driContext);
+}
+
+static int
+__glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
+ unsigned long mask)
+{
+ __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
+ __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
+
+ return (*screen->core->copyContext)(dst->driContext,
+ src->driContext, mask);
+}
+
+static Bool
+__glXDRIcontextWait(__GLXcontext *baseContext,
+ __GLXclientState *cl, int *error)
+{
+ if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
+ *error = cl->client->noClientException;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#ifdef __DRI_TEX_BUFFER
+
+static int
+__glXDRIbindTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *glxPixmap)
+{
+ __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
+ const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
+ __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
+
+ if (texBuffer == NULL)
+ return Success;
+
+#if __DRI_TEX_BUFFER_VERSION >= 2
+ if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
+ (*texBuffer->setTexBuffer2)(context->driContext,
+ glxPixmap->target,
+ glxPixmap->format,
+ drawable->driDrawable);
+ } else
+#endif
+ {
+ texBuffer->setTexBuffer(context->driContext,
+ glxPixmap->target,
+ drawable->driDrawable);
+ }
+
+ return Success;
+}
+
+static int
+__glXDRIreleaseTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *pixmap)
+{
+ /* FIXME: Just unbind the texture? */
+ return Success;
+}
+
+#else
+
+static int
+__glXDRIbindTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *glxPixmap)
+{
+ return Success;
+}
+
+static int
+__glXDRIreleaseTexImage(__GLXcontext *baseContext,
+ int buffer,
+ __GLXdrawable *pixmap)
+{
+ return Success;
+}
+
+#endif
+
+static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
+ __glXDRIbindTexImage,
+ __glXDRIreleaseTexImage
+};
+
+static void
+__glXDRIscreenDestroy(__GLXscreen *baseScreen)
+{
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
+
+ (*screen->core->destroyScreen)(screen->driScreen);
+
+ dlclose(screen->driver);
+
+ __glXScreenDestroy(baseScreen);
+
+ free(screen);
+}
+
+static __GLXcontext *
+__glXDRIscreenCreateContext(__GLXscreen *baseScreen,
+ __GLXconfig *glxConfig,
+ __GLXcontext *baseShareContext)
+{
+ __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
+ __GLXDRIcontext *context, *shareContext;
+ __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
+ __DRIcontext *driShare;
+
+ shareContext = (__GLXDRIcontext *) baseShareContext;
+ if (shareContext)
+ driShare = shareContext->driContext;
+ else
+ driShare = NULL;
+
+ context = calloc(1, sizeof *context);
+ if (context == NULL)
+ return NULL;
+
+ context->base.destroy = __glXDRIcontextDestroy;
+ context->base.makeCurrent = __glXDRIcontextMakeCurrent;
+ context->base.loseCurrent = __glXDRIcontextLoseCurrent;
+ context->base.copy = __glXDRIcontextCopy;
+ context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
+ context->base.wait = __glXDRIcontextWait;
+
+ context->driContext =
+ (*screen->dri2->createNewContext)(screen->driScreen,
+ config->driConfig,
+ driShare, context);
+ if (context->driContext == NULL) {
+ free(context);
+ return NULL;
+ }
+
+ return &context->base;
+}
+
+static void
+__glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv)
+{
+#if __DRI2_FLUSH_VERSION >= 3
+ __GLXDRIdrawable *private = priv;
+ __GLXDRIscreen *screen = private->screen;
+
+ if (screen->flush)
+ (*screen->flush->invalidate)(private->driDrawable);
+#endif
+}
+
+static __GLXdrawable *
+__glXDRIscreenCreateDrawable(ClientPtr client,
+ __GLXscreen *screen,
+ DrawablePtr pDraw,
+ XID drawId,
+ int type,
+ XID glxDrawId,
+ __GLXconfig *glxConfig)
+{
+ __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
+ __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
+ __GLXDRIdrawable *private;
+
+ private = calloc(1, sizeof *private);
+ if (private == NULL)
+ return NULL;
+
+ private->screen = driScreen;
+ if (!__glXDrawableInit(&private->base, screen,
+ pDraw, type, glxDrawId, glxConfig)) {
+ free(private);
+ return NULL;
+ }
+
+ private->base.destroy = __glXDRIdrawableDestroy;
+ private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
+ private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
+ private->base.waitGL = __glXDRIdrawableWaitGL;
+ private->base.waitX = __glXDRIdrawableWaitX;
+
+ if (DRI2CreateDrawable(client, pDraw, drawId,
+ __glXDRIinvalidateBuffers, private)) {
+ free(private);
+ return NULL;
+ }
+
+ private->driDrawable =
+ (*driScreen->dri2->createNewDrawable)(driScreen->driScreen,
+ config->driConfig, private);
+
+ return &private->base;
+}
+
+static __DRIbuffer *
+dri2GetBuffers(__DRIdrawable *driDrawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, void *loaderPrivate)
+{
+ __GLXDRIdrawable *private = loaderPrivate;
+ DRI2BufferPtr *buffers;
+ int i;
+ int j;
+
+ buffers = DRI2GetBuffers(private->base.pDraw,
+ width, height, attachments, count, out_count);
+ if (*out_count > MAX_DRAWABLE_BUFFERS) {
+ *out_count = 0;
+ return NULL;
+ }
+
+ private->width = *width;
+ private->height = *height;
+
+ /* This assumes the DRI2 buffer attachment tokens matches the
+ * __DRIbuffer tokens. */
+ j = 0;
+ for (i = 0; i < *out_count; i++) {
+ /* Do not send the real front buffer of a window to the client.
+ */
+ if ((private->base.pDraw->type == DRAWABLE_WINDOW)
+ && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
+ continue;
+ }
+
+ private->buffers[j].attachment = buffers[i]->attachment;
+ private->buffers[j].name = buffers[i]->name;
+ private->buffers[j].pitch = buffers[i]->pitch;
+ private->buffers[j].cpp = buffers[i]->cpp;
+ private->buffers[j].flags = buffers[i]->flags;
+ j++;
+ }
+
+ *out_count = j;
+ return private->buffers;
+}
+
+static __DRIbuffer *
+dri2GetBuffersWithFormat(__DRIdrawable *driDrawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *out_count, void *loaderPrivate)
+{
+ __GLXDRIdrawable *private = loaderPrivate;
+ DRI2BufferPtr *buffers;
+ int i;
+ int j = 0;
+
+ buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
+ width, height, attachments, count,
+ out_count);
+ if (*out_count > MAX_DRAWABLE_BUFFERS) {
+ *out_count = 0;
+ return NULL;
+ }
+
+ private->width = *width;
+ private->height = *height;
+
+ /* This assumes the DRI2 buffer attachment tokens matches the
+ * __DRIbuffer tokens. */
+ for (i = 0; i < *out_count; i++) {
+ /* Do not send the real front buffer of a window to the client.
+ */
+ if ((private->base.pDraw->type == DRAWABLE_WINDOW)
+ && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
+ continue;
+ }
+
+ private->buffers[j].attachment = buffers[i]->attachment;
+ private->buffers[j].name = buffers[i]->name;
+ private->buffers[j].pitch = buffers[i]->pitch;
+ private->buffers[j].cpp = buffers[i]->cpp;
+ private->buffers[j].flags = buffers[i]->flags;
+ j++;
+ }
+
+ *out_count = j;
+ return private->buffers;
+}
+
+static void
+dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
+{
+ (void) driDrawable;
+ __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate);
+}
+
+static const __DRIdri2LoaderExtension loaderExtension = {
+ { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
+ dri2GetBuffers,
+ dri2FlushFrontBuffer,
+ dri2GetBuffersWithFormat,
+};
+
+#ifdef __DRI_USE_INVALIDATE
+static const __DRIuseInvalidateExtension dri2UseInvalidate = {
+ { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION }
+};
+#endif
+
+static const __DRIextension *loader_extensions[] = {
+ &systemTimeExtension.base,
+ &loaderExtension.base,
+#ifdef __DRI_USE_INVALIDATE
+ &dri2UseInvalidate.base,
+#endif
+ NULL
+};
+
+static Bool
+glxDRIEnterVT (int index, int flags)
+{
+ ScrnInfoPtr scrn = xf86Screens[index];
+ Bool ret;
+ __GLXDRIscreen *screen = (__GLXDRIscreen *)
+ glxGetScreen(screenInfo.screens[index]);
+
+ LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
+
+ scrn->EnterVT = screen->enterVT;
+
+ ret = scrn->EnterVT (index, flags);
+
+ screen->enterVT = scrn->EnterVT;
+ scrn->EnterVT = glxDRIEnterVT;
+
+ if (!ret)
+ return FALSE;
+
+ glxResumeClients();
+
+ return TRUE;
+}
+
+static void
+glxDRILeaveVT (int index, int flags)
+{
+ ScrnInfoPtr scrn = xf86Screens[index];
+ __GLXDRIscreen *screen = (__GLXDRIscreen *)
+ glxGetScreen(screenInfo.screens[index]);
+
+ LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n");
+
+ glxSuspendClients();
+
+ scrn->LeaveVT = screen->leaveVT;
+ (*screen->leaveVT) (index, flags);
+ screen->leaveVT = scrn->LeaveVT;
+ scrn->LeaveVT = glxDRILeaveVT;
+}
+
+static void
+initializeExtensions(__GLXDRIscreen *screen)
+{
+ ScreenPtr pScreen = screen->base.pScreen;
+ const __DRIextension **extensions;
+ int i;
+
+ extensions = screen->core->getExtensions(screen->driScreen);
+
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_MESA_copy_sub_buffer");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
+
+ __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
+
+ if (DRI2HasSwapControl(pScreen)) {
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_SGI_swap_control");
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_MESA_swap_control");
+ LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
+ }
+
+ for (i = 0; extensions[i]; i++) {
+#ifdef __DRI_READ_DRAWABLE
+ if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
+ __glXEnableExtension(screen->glx_enable_bits,
+ "GLX_SGI_make_current_read");
+
+ LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
+ }
+#endif
+
+#ifdef __DRI_TEX_BUFFER
+ if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
+ screen->texBuffer =
+ (const __DRItexBufferExtension *) extensions[i];
+ /* GLX_EXT_texture_from_pixmap is always enabled. */
+ LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
+ }
+#endif
+
+#ifdef __DRI2_FLUSH
+ if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
+ extensions[i]->version >= 3) {
+ screen->flush = (__DRI2flushExtension *) extensions[i];
+ }
+#endif
+
+ /* Ignore unknown extensions */
+ }
+}
+
+static __GLXscreen *
+__glXDRIscreenProbe(ScreenPtr pScreen)
+{
+ const char *driverName, *deviceName;
+ __GLXDRIscreen *screen;
+ size_t buffer_size;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ const __DRIconfig **driConfigs;
+
+ screen = calloc(1, sizeof *screen);
+ if (screen == NULL)
+ return NULL;
+
+ if (!xf86LoaderCheckSymbol("DRI2Connect") ||
+ !DRI2Connect(pScreen, DRI2DriverDRI,
+ &screen->fd, &driverName, &deviceName)) {
+ LogMessage(X_INFO,
+ "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
+ return NULL;
+ }
+
+ screen->base.destroy = __glXDRIscreenDestroy;
+ screen->base.createContext = __glXDRIscreenCreateContext;
+ screen->base.createDrawable = __glXDRIscreenCreateDrawable;
+ screen->base.swapInterval = __glXDRIdrawableSwapInterval;
+ screen->base.pScreen = pScreen;
+
+ __glXInitExtensionEnableBits(screen->glx_enable_bits);
+
+ screen->driver = glxProbeDriver(driverName, (void **)&screen->core, __DRI_CORE, 1,
+ (void **)&screen->dri2, __DRI_DRI2, 1);
+ if (screen->driver == NULL) {
+ goto handle_error;
+ }
+
+ screen->driScreen =
+ (*screen->dri2->createNewScreen)(pScreen->myNum,
+ screen->fd,
+ loader_extensions,
+ &driConfigs,
+ screen);
+
+ if (screen->driScreen == NULL) {
+ LogMessage(X_ERROR,
+ "AIGLX error: Calling driver entry point failed\n");
+ goto handle_error;
+ }
+
+ initializeExtensions(screen);
+
+ screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs,
+ GLX_WINDOW_BIT |
+ GLX_PIXMAP_BIT |
+ GLX_PBUFFER_BIT);
+
+ __glXScreenInit(&screen->base, pScreen);
+
+ /* The first call simply determines the length of the extension string.
+ * This allows us to allocate some memory to hold the extension string,
+ * but it requires that we call __glXGetExtensionString a second time.
+ */
+ buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
+ if (buffer_size > 0) {
+ free(screen->base.GLXextensions);
+
+ screen->base.GLXextensions = xnfalloc(buffer_size);
+ (void) __glXGetExtensionString(screen->glx_enable_bits,
+ screen->base.GLXextensions);
+ }
+
+ /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled
+ * drivers support the required extensions for GLX 1.4. The extensions
+ * we're assuming are:
+ *
+ * - GLX_SGI_make_current_read (1.3)
+ * - GLX_SGIX_fbconfig (1.3)
+ * - GLX_SGIX_pbuffer (1.3)
+ * - GLX_ARB_multisample (1.4)
+ */
+ screen->base.GLXmajor = 1;
+ screen->base.GLXminor = 4;
+
+ screen->enterVT = pScrn->EnterVT;
+ pScrn->EnterVT = glxDRIEnterVT;
+ screen->leaveVT = pScrn->LeaveVT;
+ pScrn->LeaveVT = glxDRILeaveVT;
+
+ LogMessage(X_INFO,
+ "AIGLX: Loaded and initialized %s\n", driverName);
+
+ return &screen->base;
+
+ handle_error:
+ if (screen->driver)
+ dlclose(screen->driver);
+
+ free(screen);
+
+ LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
+
+ return NULL;
+}
+
+_X_EXPORT __GLXprovider __glXDRI2Provider = {
+ __glXDRIscreenProbe,
+ "DRI2",
+ NULL
+};
diff --git a/xorg-server/glx/glxext.c b/xorg-server/glx/glxext.c
index 054ece76d..9cfc096c3 100644
--- a/xorg-server/glx/glxext.c
+++ b/xorg-server/glx/glxext.c
@@ -1,552 +1,556 @@
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-#include "glxserver.h"
-#include <windowstr.h>
-#include <propertyst.h>
-#include <registry.h>
-#include "privates.h"
-#include <os.h>
-#include "unpack.h"
-#include "glxutil.h"
-#include "glxext.h"
-#include "indirect_table.h"
-#include "indirect_util.h"
-
-/*
-** The last context used by the server. It is the context that is current
-** from the server's perspective.
-*/
-__GLXcontext *__glXLastContext;
-
-/*
-** X resources.
-*/
-RESTYPE __glXContextRes;
-RESTYPE __glXDrawableRes;
-
-/*
-** Reply for most singles.
-*/
-xGLXSingleReply __glXReply;
-
-static DevPrivateKeyRec glxClientPrivateKeyRec;
-#define glxClientPrivateKey (&glxClientPrivateKeyRec)
-
-/*
-** Forward declarations.
-*/
-static int __glXDispatch(ClientPtr);
-
-/*
-** Called when the extension is reset.
-*/
-static void ResetExtension(ExtensionEntry* extEntry)
-{
- __glXFlushContextCache();
-}
-
-/*
-** Reset state used to keep track of large (multi-request) commands.
-*/
-void __glXResetLargeCommandStatus(__GLXclientState *cl)
-{
- cl->largeCmdBytesSoFar = 0;
- cl->largeCmdBytesTotal = 0;
- cl->largeCmdRequestsSoFar = 0;
- cl->largeCmdRequestsTotal = 0;
-}
-
-/*
-** This procedure is called when the client who created the context goes
-** away OR when glXDestroyContext is called. In either case, all we do is
-** flag that the ID is no longer valid, and (maybe) free the context.
-** use.
-*/
-static int ContextGone(__GLXcontext* cx, XID id)
-{
- cx->idExists = GL_FALSE;
- if (!cx->isCurrent) {
- __glXFreeContext(cx);
- }
-
- return True;
-}
-
-static __GLXcontext *glxPendingDestroyContexts;
-static __GLXcontext *glxAllContexts;
-static int glxServerLeaveCount;
-static int glxBlockClients;
-
-/*
-** Destroy routine that gets called when a drawable is freed. A drawable
-** contains the ancillary buffers needed for rendering.
-*/
-static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
-{
- __GLXcontext *c, *next;
-
- /* If this drawable was created using glx 1.3 drawable
- * constructors, we added it as a glx drawable resource under both
- * its glx drawable ID and it X drawable ID. Remove the other
- * resource now so we don't a callback for freed memory. */
- if (glxPriv->drawId != glxPriv->pDraw->id) {
- if (xid == glxPriv->drawId)
- FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE);
- else
- FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE);
- }
-
- for (c = glxAllContexts; c; c = next) {
- next = c->next;
- if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
- (*c->loseCurrent)(c);
- c->isCurrent = GL_FALSE;
- if (c == __glXLastContext)
- __glXFlushContextCache();
- }
- if (c->drawPriv == glxPriv)
- c->drawPriv = NULL;
- if (c->readPriv == glxPriv)
- c->readPriv = NULL;
- }
-
- glxPriv->destroy(glxPriv);
-
- return True;
-}
-
-void __glXAddToContextList(__GLXcontext *cx)
-{
- cx->next = glxAllContexts;
- glxAllContexts = cx;
-}
-
-static void __glXRemoveFromContextList(__GLXcontext *cx)
-{
- __GLXcontext *c, *prev;
-
- if (cx == glxAllContexts)
- glxAllContexts = cx->next;
- else {
- prev = glxAllContexts;
- for (c = glxAllContexts; c; c = c->next) {
- if (c == cx)
- prev->next = c->next;
- prev = c;
- }
- }
-}
-
-/*
-** Free a context.
-*/
-GLboolean __glXFreeContext(__GLXcontext *cx)
-{
- if (cx->idExists || cx->isCurrent) return GL_FALSE;
-
- free(cx->feedbackBuf);
- free(cx->selectBuf);
- if (cx == __glXLastContext) {
- __glXFlushContextCache();
- }
-
- __glXRemoveFromContextList(cx);
-
- /* We can get here through both regular dispatching from
- * __glXDispatch() or as a callback from the resource manager. In
- * the latter case we need to lift the DRI lock manually. */
-
- if (!glxBlockClients) {
- __glXleaveServer(GL_FALSE);
- cx->destroy(cx);
- __glXenterServer(GL_FALSE);
- } else {
- cx->next = glxPendingDestroyContexts;
- glxPendingDestroyContexts = cx;
- }
-
- return GL_TRUE;
-}
-
-/************************************************************************/
-
-/*
-** These routines can be used to check whether a particular GL command
-** has caused an error. Specifically, we use them to check whether a
-** given query has caused an error, in which case a zero-length data
-** reply is sent to the client.
-*/
-
-static GLboolean errorOccured = GL_FALSE;
-
-/*
-** The GL was will call this routine if an error occurs.
-*/
-void __glXErrorCallBack(GLenum code)
-{
- errorOccured = GL_TRUE;
-}
-
-/*
-** Clear the error flag before calling the GL command.
-*/
-void __glXClearErrorOccured(void)
-{
- errorOccured = GL_FALSE;
-}
-
-/*
-** Check if the GL command caused an error.
-*/
-GLboolean __glXErrorOccured(void)
-{
- return errorOccured;
-}
-
-static int __glXErrorBase;
-int __glXEventBase;
-
-int __glXError(int error)
-{
- return __glXErrorBase + error;
-}
-
-__GLXclientState *
-glxGetClient(ClientPtr pClient)
-{
- return dixLookupPrivate(&pClient->devPrivates, glxClientPrivateKey);
-}
-
-static void
-glxClientCallback (CallbackListPtr *list,
- pointer closure,
- pointer data)
-{
- NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
- ClientPtr pClient = clientinfo->client;
- __GLXclientState *cl = glxGetClient(pClient);
-
- switch (pClient->clientState) {
- case ClientStateRunning:
- /*
- ** By default, assume that the client supports
- ** GLX major version 1 minor version 0 protocol.
- */
- cl->GLClientmajorVersion = 1;
- cl->GLClientminorVersion = 0;
- cl->client = pClient;
- break;
-
- case ClientStateGone:
- free(cl->returnBuf);
- free(cl->largeCmdBuf);
- free(cl->GLClientextensions);
- break;
-
- default:
- break;
- }
-}
-
-/************************************************************************/
-
-static __GLXprovider *__glXProviderStack;
-
-void GlxPushProvider(__GLXprovider *provider)
-{
- provider->next = __glXProviderStack;
- __glXProviderStack = provider;
-}
-
-/*
-** Initialize the GLX extension.
-*/
-void GlxExtensionInit(void)
-{
- ExtensionEntry *extEntry;
- ScreenPtr pScreen;
- int i;
- __GLXprovider *p;
- Bool glx_provided = False;
-
- __glXContextRes = CreateNewResourceType((DeleteType)ContextGone,
- "GLXContext");
- __glXDrawableRes = CreateNewResourceType((DeleteType)DrawableGone,
- "GLXDrawable");
- if (!__glXContextRes || !__glXDrawableRes)
- return;
-
- if (!dixRegisterPrivateKey(&glxClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (__GLXclientState)))
- return;
- if (!AddCallback (&ClientStateCallback, glxClientCallback, 0))
- return;
-
- for (i = 0; i < screenInfo.numScreens; i++) {
- pScreen = screenInfo.screens[i];
-
- for (p = __glXProviderStack; p != NULL; p = p->next) {
- __GLXscreen *glxScreen;
-
- glxScreen = p->screenProbe(pScreen);
- if (glxScreen != NULL) {
- if (glxScreen->GLXminor < glxMinorVersion)
- glxMinorVersion = glxScreen->GLXminor;
- LogMessage(X_INFO,
- "GLX: Initialized %s GL provider for screen %d\n",
- p->name, i);
- break;
- }
-
- }
-
- if (!p)
- LogMessage(X_INFO,
- "GLX: no usable GL providers found for screen %d\n", i);
- else
- glx_provided = True;
- }
-
- /* don't register extension if GL is not provided on any screen */
- if (!glx_provided)
- return;
-
- /*
- ** Add extension to server extensions.
- */
- 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;
- __glXEventBase = extEntry->eventBase;
-}
-
-/************************************************************************/
-
-void __glXFlushContextCache(void)
-{
- __glXLastContext = 0;
-}
-
-/*
-** Make a context the current one for the GL (in this implementation, there
-** is only one instance of the GL, and we use it to serve all GL clients by
-** switching it between different contexts). While we are at it, look up
-** a context by its tag and return its (__GLXcontext *).
-*/
-__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
- int *error)
-{
- __GLXcontext *cx;
-
- /*
- ** See if the context tag is legal; it is managed by the extension,
- ** so if it's invalid, we have an implementation error.
- */
- cx = __glXLookupContextByTag(cl, tag);
- if (!cx) {
- cl->client->errorValue = tag;
- *error = __glXError(GLXBadContextTag);
- return 0;
- }
-
- if (!cx->isDirect) {
- if (cx->drawPriv == NULL) {
- /*
- ** The drawable has vanished. It must be a window, because only
- ** windows can be destroyed from under us; GLX pixmaps are
- ** refcounted and don't go away until no one is using them.
- */
- *error = __glXError(GLXBadCurrentWindow);
- return 0;
- }
- }
-
- if (cx->wait && (*cx->wait)(cx, cl, error))
- return NULL;
-
- if (cx == __glXLastContext) {
- /* No need to re-bind */
- return cx;
- }
-
- /* Make this context the current one for the GL. */
- if (!cx->isDirect) {
- if (!(*cx->makeCurrent)(cx)) {
- /* Bind failed, and set the error code. Bummer */
- cl->client->errorValue = cx->id;
- *error = __glXError(GLXBadContextState);
- return 0;
- }
- }
- __glXLastContext = cx;
- return cx;
-}
-
-/************************************************************************/
-
-void glxSuspendClients(void)
-{
- int i;
-
- for (i = 1; i < currentMaxClients; i++) {
- if (clients[i] && glxGetClient(clients[i])->inUse)
- IgnoreClient(clients[i]);
- }
-
- glxBlockClients = TRUE;
-}
-
-void glxResumeClients(void)
-{
- __GLXcontext *cx, *next;
- int i;
-
- glxBlockClients = FALSE;
-
- for (i = 1; i < currentMaxClients; i++) {
- if (clients[i] && glxGetClient(clients[i])->inUse)
- AttendClient(clients[i]);
- }
-
- __glXleaveServer(GL_FALSE);
- for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) {
- next = cx->next;
-
- cx->destroy(cx);
- }
- glxPendingDestroyContexts = NULL;
- __glXenterServer(GL_FALSE);
-}
-
-static void
-__glXnopEnterServer(GLboolean rendering)
-{
-}
-
-static void
-__glXnopLeaveServer(GLboolean rendering)
-{
-}
-
-static void (*__glXenterServerFunc)(GLboolean) = __glXnopEnterServer;
-static void (*__glXleaveServerFunc)(GLboolean) = __glXnopLeaveServer;
-
-void __glXsetEnterLeaveServerFuncs(void (*enter)(GLboolean),
- void (*leave)(GLboolean))
-{
- __glXenterServerFunc = enter;
- __glXleaveServerFunc = leave;
-}
-
-
-void __glXenterServer(GLboolean rendering)
-{
- glxServerLeaveCount--;
-
- if (glxServerLeaveCount == 0)
- (*__glXenterServerFunc)(rendering);
-}
-
-void __glXleaveServer(GLboolean rendering)
-{
- if (glxServerLeaveCount == 0)
- (*__glXleaveServerFunc)(rendering);
-
- glxServerLeaveCount++;
-}
-
-/*
-** Top level dispatcher; all commands are executed from here down.
-*/
-static int __glXDispatch(ClientPtr client)
-{
- REQUEST(xGLXSingleReq);
- CARD8 opcode;
- __GLXdispatchSingleProcPtr proc;
- __GLXclientState *cl;
- int retval;
-
- opcode = stuff->glxCode;
- cl = glxGetClient(client);
- /* Mark it in use so we suspend it on VT switch. */
- cl->inUse = TRUE;
-
- /*
- ** If we're expecting a glXRenderLarge request, this better be one.
- */
- if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) {
- client->errorValue = stuff->glxCode;
- return __glXError(GLXBadLargeRequest);
- }
-
- /* If we're currently blocking GLX clients, just put this guy to
- * sleep, reset the request and return. */
- if (glxBlockClients) {
- ResetCurrentRequest(client);
- client->sequence--;
- IgnoreClient(client);
- return Success;
- }
-
- /*
- ** Use the opcode to index into the procedure table.
- */
- proc = __glXGetProtocolDecodeFunction(& Single_dispatch_info, opcode,
- client->swapped);
- if (proc != NULL) {
- GLboolean rendering = opcode <= X_GLXRenderLarge;
- __glXleaveServer(rendering);
-
- retval = (*proc)(cl, (GLbyte *) stuff);
-
- __glXenterServer(rendering);
- }
- else {
- retval = BadRequest;
- }
-
- return retval;
-}
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+#include "glxserver.h"
+#include <windowstr.h>
+#include <propertyst.h>
+#include <registry.h>
+#include "privates.h"
+#include <os.h>
+#include "unpack.h"
+#include "glxutil.h"
+#include "glxext.h"
+#include "indirect_table.h"
+#include "indirect_util.h"
+
+/*
+** The last context used by the server. It is the context that is current
+** from the server's perspective.
+*/
+__GLXcontext *__glXLastContext;
+
+/*
+** X resources.
+*/
+RESTYPE __glXContextRes;
+RESTYPE __glXDrawableRes;
+
+/*
+** Reply for most singles.
+*/
+xGLXSingleReply __glXReply;
+
+static DevPrivateKeyRec glxClientPrivateKeyRec;
+#define glxClientPrivateKey (&glxClientPrivateKeyRec)
+
+/*
+** Forward declarations.
+*/
+static int __glXDispatch(ClientPtr);
+
+/*
+** Called when the extension is reset.
+*/
+static void ResetExtension(ExtensionEntry* extEntry)
+{
+ __glXFlushContextCache();
+}
+
+/*
+** Reset state used to keep track of large (multi-request) commands.
+*/
+void __glXResetLargeCommandStatus(__GLXclientState *cl)
+{
+ cl->largeCmdBytesSoFar = 0;
+ cl->largeCmdBytesTotal = 0;
+ cl->largeCmdRequestsSoFar = 0;
+ cl->largeCmdRequestsTotal = 0;
+}
+
+/*
+** This procedure is called when the client who created the context goes
+** away OR when glXDestroyContext is called. In either case, all we do is
+** flag that the ID is no longer valid, and (maybe) free the context.
+** use.
+*/
+static int ContextGone(__GLXcontext* cx, XID id)
+{
+ cx->idExists = GL_FALSE;
+ if (!cx->isCurrent) {
+ __glXFreeContext(cx);
+ }
+
+ return True;
+}
+
+static __GLXcontext *glxPendingDestroyContexts;
+static __GLXcontext *glxAllContexts;
+static int glxServerLeaveCount;
+static int glxBlockClients;
+
+/*
+** Destroy routine that gets called when a drawable is freed. A drawable
+** contains the ancillary buffers needed for rendering.
+*/
+static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
+{
+ __GLXcontext *c, *next;
+
+ if (glxPriv->type == GLX_DRAWABLE_WINDOW) {
+ /* If this was created by glXCreateWindow, free the matching resource */
+ if (glxPriv->drawId != glxPriv->pDraw->id) {
+ if (xid == glxPriv->drawId)
+ FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE);
+ else
+ FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE);
+ }
+ /* otherwise this window was implicitly created by MakeCurrent */
+ }
+
+ for (c = glxAllContexts; c; c = next) {
+ next = c->next;
+ if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
+ (*c->loseCurrent)(c);
+ c->isCurrent = GL_FALSE;
+ if (c == __glXLastContext)
+ __glXFlushContextCache();
+ }
+ if (c->drawPriv == glxPriv)
+ c->drawPriv = NULL;
+ if (c->readPriv == glxPriv)
+ c->readPriv = NULL;
+ }
+
+ /* drop our reference to any backing pixmap */
+ if (glxPriv->type == GLX_DRAWABLE_PIXMAP)
+ glxPriv->pDraw->pScreen->DestroyPixmap((PixmapPtr)glxPriv->pDraw);
+
+ glxPriv->destroy(glxPriv);
+
+ return True;
+}
+
+void __glXAddToContextList(__GLXcontext *cx)
+{
+ cx->next = glxAllContexts;
+ glxAllContexts = cx;
+}
+
+static void __glXRemoveFromContextList(__GLXcontext *cx)
+{
+ __GLXcontext *c, *prev;
+
+ if (cx == glxAllContexts)
+ glxAllContexts = cx->next;
+ else {
+ prev = glxAllContexts;
+ for (c = glxAllContexts; c; c = c->next) {
+ if (c == cx)
+ prev->next = c->next;
+ prev = c;
+ }
+ }
+}
+
+/*
+** Free a context.
+*/
+GLboolean __glXFreeContext(__GLXcontext *cx)
+{
+ if (cx->idExists || cx->isCurrent) return GL_FALSE;
+
+ free(cx->feedbackBuf);
+ free(cx->selectBuf);
+ if (cx == __glXLastContext) {
+ __glXFlushContextCache();
+ }
+
+ __glXRemoveFromContextList(cx);
+
+ /* We can get here through both regular dispatching from
+ * __glXDispatch() or as a callback from the resource manager. In
+ * the latter case we need to lift the DRI lock manually. */
+
+ if (!glxBlockClients) {
+ __glXleaveServer(GL_FALSE);
+ cx->destroy(cx);
+ __glXenterServer(GL_FALSE);
+ } else {
+ cx->next = glxPendingDestroyContexts;
+ glxPendingDestroyContexts = cx;
+ }
+
+ return GL_TRUE;
+}
+
+/************************************************************************/
+
+/*
+** These routines can be used to check whether a particular GL command
+** has caused an error. Specifically, we use them to check whether a
+** given query has caused an error, in which case a zero-length data
+** reply is sent to the client.
+*/
+
+static GLboolean errorOccured = GL_FALSE;
+
+/*
+** The GL was will call this routine if an error occurs.
+*/
+void __glXErrorCallBack(GLenum code)
+{
+ errorOccured = GL_TRUE;
+}
+
+/*
+** Clear the error flag before calling the GL command.
+*/
+void __glXClearErrorOccured(void)
+{
+ errorOccured = GL_FALSE;
+}
+
+/*
+** Check if the GL command caused an error.
+*/
+GLboolean __glXErrorOccured(void)
+{
+ return errorOccured;
+}
+
+static int __glXErrorBase;
+int __glXEventBase;
+
+int __glXError(int error)
+{
+ return __glXErrorBase + error;
+}
+
+__GLXclientState *
+glxGetClient(ClientPtr pClient)
+{
+ return dixLookupPrivate(&pClient->devPrivates, glxClientPrivateKey);
+}
+
+static void
+glxClientCallback (CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+ __GLXclientState *cl = glxGetClient(pClient);
+
+ switch (pClient->clientState) {
+ case ClientStateRunning:
+ /*
+ ** By default, assume that the client supports
+ ** GLX major version 1 minor version 0 protocol.
+ */
+ cl->GLClientmajorVersion = 1;
+ cl->GLClientminorVersion = 0;
+ cl->client = pClient;
+ break;
+
+ case ClientStateGone:
+ free(cl->returnBuf);
+ free(cl->largeCmdBuf);
+ free(cl->GLClientextensions);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/************************************************************************/
+
+static __GLXprovider *__glXProviderStack;
+
+void GlxPushProvider(__GLXprovider *provider)
+{
+ provider->next = __glXProviderStack;
+ __glXProviderStack = provider;
+}
+
+/*
+** Initialize the GLX extension.
+*/
+void GlxExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+ ScreenPtr pScreen;
+ int i;
+ __GLXprovider *p;
+ Bool glx_provided = False;
+
+ __glXContextRes = CreateNewResourceType((DeleteType)ContextGone,
+ "GLXContext");
+ __glXDrawableRes = CreateNewResourceType((DeleteType)DrawableGone,
+ "GLXDrawable");
+ if (!__glXContextRes || !__glXDrawableRes)
+ return;
+
+ if (!dixRegisterPrivateKey(&glxClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (__GLXclientState)))
+ return;
+ if (!AddCallback (&ClientStateCallback, glxClientCallback, 0))
+ return;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ pScreen = screenInfo.screens[i];
+
+ for (p = __glXProviderStack; p != NULL; p = p->next) {
+ __GLXscreen *glxScreen;
+
+ glxScreen = p->screenProbe(pScreen);
+ if (glxScreen != NULL) {
+ if (glxScreen->GLXminor < glxMinorVersion)
+ glxMinorVersion = glxScreen->GLXminor;
+ LogMessage(X_INFO,
+ "GLX: Initialized %s GL provider for screen %d\n",
+ p->name, i);
+ break;
+ }
+
+ }
+
+ if (!p)
+ LogMessage(X_INFO,
+ "GLX: no usable GL providers found for screen %d\n", i);
+ else
+ glx_provided = True;
+ }
+
+ /* don't register extension if GL is not provided on any screen */
+ if (!glx_provided)
+ return;
+
+ /*
+ ** Add extension to server extensions.
+ */
+ 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;
+ __glXEventBase = extEntry->eventBase;
+}
+
+/************************************************************************/
+
+void __glXFlushContextCache(void)
+{
+ __glXLastContext = 0;
+}
+
+/*
+** Make a context the current one for the GL (in this implementation, there
+** is only one instance of the GL, and we use it to serve all GL clients by
+** switching it between different contexts). While we are at it, look up
+** a context by its tag and return its (__GLXcontext *).
+*/
+__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
+ int *error)
+{
+ __GLXcontext *cx;
+
+ /*
+ ** See if the context tag is legal; it is managed by the extension,
+ ** so if it's invalid, we have an implementation error.
+ */
+ cx = __glXLookupContextByTag(cl, tag);
+ if (!cx) {
+ cl->client->errorValue = tag;
+ *error = __glXError(GLXBadContextTag);
+ return 0;
+ }
+
+ if (!cx->isDirect) {
+ if (cx->drawPriv == NULL) {
+ /*
+ ** The drawable has vanished. It must be a window, because only
+ ** windows can be destroyed from under us; GLX pixmaps are
+ ** refcounted and don't go away until no one is using them.
+ */
+ *error = __glXError(GLXBadCurrentWindow);
+ return 0;
+ }
+ }
+
+ if (cx->wait && (*cx->wait)(cx, cl, error))
+ return NULL;
+
+ if (cx == __glXLastContext) {
+ /* No need to re-bind */
+ return cx;
+ }
+
+ /* Make this context the current one for the GL. */
+ if (!cx->isDirect) {
+ if (!(*cx->makeCurrent)(cx)) {
+ /* Bind failed, and set the error code. Bummer */
+ cl->client->errorValue = cx->id;
+ *error = __glXError(GLXBadContextState);
+ return 0;
+ }
+ }
+ __glXLastContext = cx;
+ return cx;
+}
+
+/************************************************************************/
+
+void glxSuspendClients(void)
+{
+ int i;
+
+ for (i = 1; i < currentMaxClients; i++) {
+ if (clients[i] && glxGetClient(clients[i])->inUse)
+ IgnoreClient(clients[i]);
+ }
+
+ glxBlockClients = TRUE;
+}
+
+void glxResumeClients(void)
+{
+ __GLXcontext *cx, *next;
+ int i;
+
+ glxBlockClients = FALSE;
+
+ for (i = 1; i < currentMaxClients; i++) {
+ if (clients[i] && glxGetClient(clients[i])->inUse)
+ AttendClient(clients[i]);
+ }
+
+ __glXleaveServer(GL_FALSE);
+ for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) {
+ next = cx->next;
+
+ cx->destroy(cx);
+ }
+ glxPendingDestroyContexts = NULL;
+ __glXenterServer(GL_FALSE);
+}
+
+static void
+__glXnopEnterServer(GLboolean rendering)
+{
+}
+
+static void
+__glXnopLeaveServer(GLboolean rendering)
+{
+}
+
+static void (*__glXenterServerFunc)(GLboolean) = __glXnopEnterServer;
+static void (*__glXleaveServerFunc)(GLboolean) = __glXnopLeaveServer;
+
+void __glXsetEnterLeaveServerFuncs(void (*enter)(GLboolean),
+ void (*leave)(GLboolean))
+{
+ __glXenterServerFunc = enter;
+ __glXleaveServerFunc = leave;
+}
+
+
+void __glXenterServer(GLboolean rendering)
+{
+ glxServerLeaveCount--;
+
+ if (glxServerLeaveCount == 0)
+ (*__glXenterServerFunc)(rendering);
+}
+
+void __glXleaveServer(GLboolean rendering)
+{
+ if (glxServerLeaveCount == 0)
+ (*__glXleaveServerFunc)(rendering);
+
+ glxServerLeaveCount++;
+}
+
+/*
+** Top level dispatcher; all commands are executed from here down.
+*/
+static int __glXDispatch(ClientPtr client)
+{
+ REQUEST(xGLXSingleReq);
+ CARD8 opcode;
+ __GLXdispatchSingleProcPtr proc;
+ __GLXclientState *cl;
+ int retval;
+
+ opcode = stuff->glxCode;
+ cl = glxGetClient(client);
+ /* Mark it in use so we suspend it on VT switch. */
+ cl->inUse = TRUE;
+
+ /*
+ ** If we're expecting a glXRenderLarge request, this better be one.
+ */
+ if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) {
+ client->errorValue = stuff->glxCode;
+ return __glXError(GLXBadLargeRequest);
+ }
+
+ /* If we're currently blocking GLX clients, just put this guy to
+ * sleep, reset the request and return. */
+ if (glxBlockClients) {
+ ResetCurrentRequest(client);
+ client->sequence--;
+ IgnoreClient(client);
+ return Success;
+ }
+
+ /*
+ ** Use the opcode to index into the procedure table.
+ */
+ proc = __glXGetProtocolDecodeFunction(& Single_dispatch_info, opcode,
+ client->swapped);
+ if (proc != NULL) {
+ GLboolean rendering = opcode <= X_GLXRenderLarge;
+ __glXleaveServer(rendering);
+
+ retval = (*proc)(cl, (GLbyte *) stuff);
+
+ __glXenterServer(rendering);
+ }
+ else {
+ retval = BadRequest;
+ }
+
+ return retval;
+}