aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/glx
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/glx')
-rw-r--r--xorg-server/glx/glxcmds.c22
-rw-r--r--xorg-server/glx/glxdri2.c124
-rw-r--r--xorg-server/glx/glxdriswrast.c10
-rw-r--r--xorg-server/glx/glxext.c27
-rw-r--r--xorg-server/glx/glxserver.h1
5 files changed, 122 insertions, 62 deletions
diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c
index 187e42665..2fc3f4cc8 100644
--- a/xorg-server/glx/glxcmds.c
+++ b/xorg-server/glx/glxcmds.c
@@ -188,7 +188,7 @@ validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
void
__glXContextDestroy(__GLXcontext * context)
{
- __glXFlushContextCache();
+ lastGLContext = NULL;
}
static void
@@ -275,6 +275,17 @@ DoCreateContext(__GLXclientState * cl, GLXContextID gcId,
** Allocate memory for the new context
*/
if (!isDirect) {
+ /* Only allow creating indirect GLX contexts if allowed by
+ * server command line. Indirect GLX is of limited use (since
+ * it's only GL 1.4), it's slower than direct contexts, and
+ * it's a massive attack surface for buffer overflow type
+ * errors.
+ */
+ if (!enableIndirectGLX) {
+ client->errorValue = isDirect;
+ return BadValue;
+ }
+
/* Without any attributes, the only error that the driver should be
* able to generate is BadAlloc. As result, just drop the error
* returned from the driver on the floor.
@@ -434,10 +445,6 @@ static void
StopUsingContext(__GLXcontext * glxc)
{
if (glxc) {
- if (glxc == __glXLastContext) {
- /* Tell server GL library */
- __glXLastContext = 0;
- }
glxc->currentClient = NULL;
if (!glxc->idExists) {
FreeResourceByType(glxc->id, __glXContextRes, FALSE);
@@ -448,7 +455,6 @@ StopUsingContext(__GLXcontext * glxc)
static void
StartUsingContext(__GLXclientState * cl, __GLXcontext * glxc)
{
- __glXLastContext = glxc;
glxc->currentClient = cl->client;
}
@@ -627,7 +633,7 @@ DoMakeCurrent(__GLXclientState * cl,
if (!(*prevglxc->loseCurrent) (prevglxc)) {
return __glXError(GLXBadContext);
}
- __glXFlushContextCache();
+ lastGLContext = NULL;
if (!prevglxc->isDirect) {
prevglxc->drawPriv = NULL;
prevglxc->readPriv = NULL;
@@ -640,7 +646,9 @@ DoMakeCurrent(__GLXclientState * cl,
glxc->readPriv = readPriv;
/* make the context current */
+ lastGLContext = glxc;
if (!(*glxc->makeCurrent) (glxc)) {
+ lastGLContext = NULL;
glxc->drawPriv = NULL;
glxc->readPriv = NULL;
return __glXError(GLXBadContext);
diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c
index 5d1a45bff..c756bf570 100644
--- a/xorg-server/glx/glxdri2.c
+++ b/xorg-server/glx/glxdri2.c
@@ -115,55 +115,54 @@ __glXDRIdrawableDestroy(__GLXdrawable * drawable)
}
static void
-__glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,
- int x, int y, int w, int h)
+copy_box(__GLXdrawable * drawable,
+ int dst, int src,
+ int x, int y, int w, int h)
{
- __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
BoxRec box;
RegionRec region;
+ __GLXcontext *cx = lastGLContext;
box.x1 = x;
- box.y1 = private->height - y - h;
+ box.y1 = y;
box.x2 = x + w;
- box.y2 = private->height - y;
+ box.y2 = y + h;
RegionInit(&region, &box, 0);
- DRI2CopyRegion(drawable->pDraw, &region,
- DRI2BufferFrontLeft, DRI2BufferBackLeft);
+ DRI2CopyRegion(drawable->pDraw, &region, dst, src);
+ if (cx != lastGLContext) {
+ lastGLContext = cx;
+ cx->makeCurrent(cx);
+ }
}
static void
-__glXDRIdrawableWaitX(__GLXdrawable * drawable)
+__glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,
+ int x, int y, int w, int h)
{
__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);
+ copy_box(drawable, x, private->height - y - h,
+ w, h,
+ DRI2BufferFrontLeft, DRI2BufferBackLeft);
+}
+
+static void
+__glXDRIdrawableWaitX(__GLXdrawable * drawable)
+{
+ __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
- DRI2CopyRegion(drawable->pDraw, &region,
- DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
+ copy_box(drawable, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft,
+ 0, 0, private->width, private->height);
}
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);
+ copy_box(drawable, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft,
+ 0, 0, private->width, private->height);
}
static void
@@ -204,26 +203,37 @@ __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
__GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
__GLXDRIscreen *screen = priv->screen;
CARD64 unused;
+ __GLXcontext *cx = lastGLContext;
+ int status;
if (screen->flush) {
(*screen->flush->flush) (priv->driDrawable);
(*screen->flush->invalidate) (priv->driDrawable);
}
- if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
- __glXdriSwapEvent, drawable) != Success)
- return FALSE;
+ status = DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
+ __glXdriSwapEvent, drawable);
+ if (cx != lastGLContext) {
+ lastGLContext = cx;
+ cx->makeCurrent(cx);
+ }
- return TRUE;
+ return status == Success;
}
static int
__glXDRIdrawableSwapInterval(__GLXdrawable * drawable, int interval)
{
+ __GLXcontext *cx = lastGLContext;
+
if (interval <= 0) /* || interval > BIGNUM? */
return GLX_BAD_VALUE;
DRI2SwapInterval(drawable->pDraw, interval);
+ if (cx != lastGLContext) {
+ lastGLContext = cx;
+ cx->makeCurrent(cx);
+ }
return 0;
}
@@ -276,7 +286,16 @@ static Bool
__glXDRIcontextWait(__GLXcontext * baseContext,
__GLXclientState * cl, int *error)
{
- if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
+ __GLXcontext *cx = lastGLContext;
+ Bool ret;
+
+ ret = DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw);
+ if (cx != lastGLContext) {
+ lastGLContext = cx;
+ cx->makeCurrent(cx);
+ }
+
+ if (ret) {
*error = cl->client->noClientException;
return TRUE;
}
@@ -600,6 +619,8 @@ __glXDRIscreenCreateDrawable(ClientPtr client,
__GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
__GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
__GLXDRIdrawable *private;
+ __GLXcontext *cx = lastGLContext;
+ Bool ret;
private = calloc(1, sizeof *private);
if (private == NULL)
@@ -618,9 +639,15 @@ __glXDRIscreenCreateDrawable(ClientPtr client,
private->base.waitGL = __glXDRIdrawableWaitGL;
private->base.waitX = __glXDRIdrawableWaitX;
- if (DRI2CreateDrawable2(client, pDraw, drawId,
- __glXDRIinvalidateBuffers, private,
- &private->dri2_id)) {
+ ret = DRI2CreateDrawable2(client, pDraw, drawId,
+ __glXDRIinvalidateBuffers, private,
+ &private->dri2_id);
+ if (cx != lastGLContext) {
+ lastGLContext = cx;
+ cx->makeCurrent(cx);
+ }
+
+ if (ret) {
free(private);
return NULL;
}
@@ -642,9 +669,22 @@ dri2GetBuffers(__DRIdrawable * driDrawable,
DRI2BufferPtr *buffers;
int i;
int j;
+ __GLXcontext *cx = lastGLContext;
buffers = DRI2GetBuffers(private->base.pDraw,
width, height, attachments, count, out_count);
+ if (cx != lastGLContext) {
+ lastGLContext = cx;
+ cx->makeCurrent(cx);
+
+ /* If DRI2GetBuffers() changed the GL context, it may also have
+ * invalidated the DRI2 buffers, so let's get them again
+ */
+ buffers = DRI2GetBuffers(private->base.pDraw,
+ width, height, attachments, count, out_count);
+ assert(lastGLContext == cx);
+ }
+
if (*out_count > MAX_DRAWABLE_BUFFERS) {
*out_count = 0;
return NULL;
@@ -686,10 +726,24 @@ dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
DRI2BufferPtr *buffers;
int i;
int j = 0;
+ __GLXcontext *cx = lastGLContext;
buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
width, height, attachments, count,
out_count);
+ if (cx != lastGLContext) {
+ lastGLContext = cx;
+ cx->makeCurrent(cx);
+
+ /* If DRI2GetBuffersWithFormat() changed the GL context, it may also have
+ * invalidated the DRI2 buffers, so let's get them again
+ */
+ buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
+ width, height, attachments, count,
+ out_count);
+ assert(lastGLContext == cx);
+ }
+
if (*out_count > MAX_DRAWABLE_BUFFERS) {
*out_count = 0;
return NULL;
diff --git a/xorg-server/glx/glxdriswrast.c b/xorg-server/glx/glxdriswrast.c
index 6fa328831..c30ce9aed 100644
--- a/xorg-server/glx/glxdriswrast.c
+++ b/xorg-server/glx/glxdriswrast.c
@@ -337,6 +337,7 @@ swrastPutImage(__DRIdrawable * draw, int op,
__GLXDRIdrawable *drawable = loaderPrivate;
DrawablePtr pDraw = drawable->base.pDraw;
GCPtr gc;
+ __GLXcontext *cx = lastGLContext;
switch (op) {
case __DRI_SWRAST_IMAGE_OP_DRAW:
@@ -352,6 +353,10 @@ swrastPutImage(__DRIdrawable * draw, int op,
ValidateGC(pDraw, gc);
gc->ops->PutImage(pDraw, gc, pDraw->depth, x, y, w, h, 0, ZPixmap, data);
+ if (cx != lastGLContext) {
+ lastGLContext = cx;
+ cx->makeCurrent(cx);
+ }
}
static void
@@ -361,8 +366,13 @@ swrastGetImage(__DRIdrawable * draw,
__GLXDRIdrawable *drawable = loaderPrivate;
DrawablePtr pDraw = drawable->base.pDraw;
ScreenPtr pScreen = pDraw->pScreen;
+ __GLXcontext *cx = lastGLContext;
pScreen->GetImage(pDraw, x, y, w, h, ZPixmap, ~0L, data);
+ if (cx != lastGLContext) {
+ lastGLContext = cx;
+ cx->makeCurrent(cx);
+ }
}
static const __DRIswrastLoaderExtension swrastLoaderExtension = {
diff --git a/xorg-server/glx/glxext.c b/xorg-server/glx/glxext.c
index c9b8cc5b3..c0142fe2e 100644
--- a/xorg-server/glx/glxext.c
+++ b/xorg-server/glx/glxext.c
@@ -48,12 +48,6 @@
#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;
@@ -79,7 +73,7 @@ static int __glXDispatch(ClientPtr);
static void
ResetExtension(ExtensionEntry * extEntry)
{
- __glXFlushContextCache();
+ lastGLContext = NULL;
}
/*
@@ -141,8 +135,7 @@ DrawableGone(__GLXdrawable * glxPriv, XID xid)
(c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
/* just force a re-bind the next time through */
(*c->loseCurrent) (c);
- if (c == __glXLastContext)
- __glXFlushContextCache();
+ lastGLContext = NULL;
}
if (c->drawPriv == glxPriv)
c->drawPriv = NULL;
@@ -203,8 +196,8 @@ __glXFreeContext(__GLXcontext * cx)
free(cx->feedbackBuf);
free(cx->selectBuf);
- if (cx == __glXLastContext) {
- __glXFlushContextCache();
+ if (cx == lastGLContext) {
+ lastGLContext = NULL;
}
/* We can get here through both regular dispatching from
@@ -296,6 +289,7 @@ glxClientCallback(CallbackListPtr *list, void *closure, void *data)
next = c->next;
if (c->currentClient == pClient) {
c->loseCurrent(c);
+ lastGLContext = NULL;
c->currentClient = NULL;
__glXFreeContext(c);
}
@@ -406,12 +400,6 @@ GlxExtensionInit(void)
/************************************************************************/
-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
@@ -449,21 +437,22 @@ __glXForceCurrent(__GLXclientState * cl, GLXContextTag tag, int *error)
if (cx->wait && (*cx->wait) (cx, cl, error))
return NULL;
- if (cx == __glXLastContext) {
+ if (cx == lastGLContext) {
/* No need to re-bind */
return cx;
}
/* Make this context the current one for the GL. */
if (!cx->isDirect) {
+ lastGLContext = cx;
if (!(*cx->makeCurrent) (cx)) {
/* Bind failed, and set the error code. Bummer */
+ lastGLContext = NULL;
cl->client->errorValue = cx->id;
*error = __glXError(GLXBadContextState);
return 0;
}
}
- __glXLastContext = cx;
return cx;
}
diff --git a/xorg-server/glx/glxserver.h b/xorg-server/glx/glxserver.h
index 3f2ae3593..a324b290f 100644
--- a/xorg-server/glx/glxserver.h
+++ b/xorg-server/glx/glxserver.h
@@ -84,7 +84,6 @@ void __glXScreenInitVisuals(__GLXscreen * screen);
/*
** The last context used (from the server's persective) is cached.
*/
-extern __GLXcontext *__glXLastContext;
extern __GLXcontext *__glXForceCurrent(__GLXclientState *, GLXContextTag,
int *);