summaryrefslogtreecommitdiff
path: root/glx
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2018-01-10 13:05:48 -0500
committerAdam Jackson <ajax@redhat.com>2018-02-14 17:04:48 -0500
commit133bd4443be6b76a36afadfae0905b832e998165 (patch)
tree27ce5bdc19c8b1e6700d0e4167b832da10bc1723 /glx
parent5d87e4f71355272c8da38c83f493b826623301cc (diff)
glx: Large commands are context state, not client state
There's no reason a multithreaded client shouldn't be allowed to interleave other requests (for other contexts) with a RenderLarge. Move the check into __glXForceCurrent, and store the state in the context not the client. Signed-off-by: Adam Jackson <ajax@redhat.com>
Diffstat (limited to 'glx')
-rw-r--r--glx/glxcmds.c70
-rw-r--r--glx/glxcontext.h10
-rw-r--r--glx/glxext.c31
-rw-r--r--glx/glxext.h1
-rw-r--r--glx/glxserver.h10
5 files changed, 61 insertions, 61 deletions
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index c5d6324d3..6785e9db3 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -1949,6 +1949,18 @@ __glXDisp_GetDrawableAttributesSGIX(__GLXclientState * cl, GLbyte * pc)
*/
/*
+** Reset state used to keep track of large (multi-request) commands.
+*/
+static void
+ResetLargeCommandStatus(__GLXcontext *cx)
+{
+ cx->largeCmdBytesSoFar = 0;
+ cx->largeCmdBytesTotal = 0;
+ cx->largeCmdRequestsSoFar = 0;
+ cx->largeCmdRequestsTotal = 0;
+}
+
+/*
** Execute all the drawing commands in a request.
*/
int
@@ -2079,8 +2091,6 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc)
glxc = __glXForceCurrent(cl, req->contextTag, &error);
if (!glxc) {
- /* Reset in case this isn't 1st request. */
- __glXResetLargeCommandStatus(cl);
return error;
}
if (safe_pad(req->dataBytes) < 0)
@@ -2093,12 +2103,12 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc)
if ((req->length << 2) != safe_pad(dataBytes) + sz_xGLXRenderLargeReq) {
client->errorValue = req->length;
/* Reset in case this isn't 1st request. */
- __glXResetLargeCommandStatus(cl);
+ ResetLargeCommandStatus(glxc);
return BadLength;
}
pc += sz_xGLXRenderLargeReq;
- if (cl->largeCmdRequestsSoFar == 0) {
+ if (glxc->largeCmdRequestsSoFar == 0) {
__GLXrenderSizeData entry;
int extra = 0;
int left = (req->length << 2) - sz_xGLXRenderLargeReq;
@@ -2157,21 +2167,21 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc)
/*
** Make enough space in the buffer, then copy the entire request.
*/
- if (cl->largeCmdBufSize < cmdlen) {
- GLbyte *newbuf = cl->largeCmdBuf;
+ if (glxc->largeCmdBufSize < cmdlen) {
+ GLbyte *newbuf = glxc->largeCmdBuf;
if (!(newbuf = realloc(newbuf, cmdlen)))
return BadAlloc;
- cl->largeCmdBuf = newbuf;
- cl->largeCmdBufSize = cmdlen;
+ glxc->largeCmdBuf = newbuf;
+ glxc->largeCmdBufSize = cmdlen;
}
- memcpy(cl->largeCmdBuf, pc, dataBytes);
+ memcpy(glxc->largeCmdBuf, pc, dataBytes);
- cl->largeCmdBytesSoFar = dataBytes;
- cl->largeCmdBytesTotal = cmdlen;
- cl->largeCmdRequestsSoFar = 1;
- cl->largeCmdRequestsTotal = req->requestTotal;
+ glxc->largeCmdBytesSoFar = dataBytes;
+ glxc->largeCmdBytesTotal = cmdlen;
+ glxc->largeCmdRequestsSoFar = 1;
+ glxc->largeCmdRequestsTotal = req->requestTotal;
return Success;
}
@@ -2185,37 +2195,37 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc)
/*
** Check the request number and the total request count.
*/
- if (req->requestNumber != cl->largeCmdRequestsSoFar + 1) {
+ if (req->requestNumber != glxc->largeCmdRequestsSoFar + 1) {
client->errorValue = req->requestNumber;
- __glXResetLargeCommandStatus(cl);
+ ResetLargeCommandStatus(glxc);
return __glXError(GLXBadLargeRequest);
}
- if (req->requestTotal != cl->largeCmdRequestsTotal) {
+ if (req->requestTotal != glxc->largeCmdRequestsTotal) {
client->errorValue = req->requestTotal;
- __glXResetLargeCommandStatus(cl);
+ ResetLargeCommandStatus(glxc);
return __glXError(GLXBadLargeRequest);
}
/*
** Check that we didn't get too much data.
*/
- if ((bytesSoFar = safe_add(cl->largeCmdBytesSoFar, dataBytes)) < 0) {
+ if ((bytesSoFar = safe_add(glxc->largeCmdBytesSoFar, dataBytes)) < 0) {
client->errorValue = dataBytes;
- __glXResetLargeCommandStatus(cl);
+ ResetLargeCommandStatus(glxc);
return __glXError(GLXBadLargeRequest);
}
- if (bytesSoFar > cl->largeCmdBytesTotal) {
+ if (bytesSoFar > glxc->largeCmdBytesTotal) {
client->errorValue = dataBytes;
- __glXResetLargeCommandStatus(cl);
+ ResetLargeCommandStatus(glxc);
return __glXError(GLXBadLargeRequest);
}
- memcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes);
- cl->largeCmdBytesSoFar += dataBytes;
- cl->largeCmdRequestsSoFar++;
+ memcpy(glxc->largeCmdBuf + glxc->largeCmdBytesSoFar, pc, dataBytes);
+ glxc->largeCmdBytesSoFar += dataBytes;
+ glxc->largeCmdRequestsSoFar++;
- if (req->requestNumber == cl->largeCmdRequestsTotal) {
+ if (req->requestNumber == glxc->largeCmdRequestsTotal) {
__GLXdispatchRenderProcPtr proc;
/*
@@ -2231,12 +2241,12 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc)
** fixes a bug that did not allow large commands of odd sizes to
** be accepted by the server.
*/
- if (safe_pad(cl->largeCmdBytesSoFar) != cl->largeCmdBytesTotal) {
+ if (safe_pad(glxc->largeCmdBytesSoFar) != glxc->largeCmdBytesTotal) {
client->errorValue = dataBytes;
- __glXResetLargeCommandStatus(cl);
+ ResetLargeCommandStatus(glxc);
return __glXError(GLXBadLargeRequest);
}
- hdr = (__GLXrenderLargeHeader *) cl->largeCmdBuf;
+ hdr = (__GLXrenderLargeHeader *) glxc->largeCmdBuf;
/*
** The opcode and length field in the header had already been
** swapped when the first request was received.
@@ -2256,12 +2266,12 @@ __glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc)
/*
** Skip over the header and execute the command.
*/
- (*proc) (cl->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE);
+ (*proc) (glxc->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE);
/*
** Reset for the next RenderLarge series.
*/
- __glXResetLargeCommandStatus(cl);
+ ResetLargeCommandStatus(glxc);
}
else {
/*
diff --git a/glx/glxcontext.h b/glx/glxcontext.h
index 19d347fdb..8f623b4b4 100644
--- a/glx/glxcontext.h
+++ b/glx/glxcontext.h
@@ -113,6 +113,16 @@ struct __GLXcontext {
GLint selectBufSize; /* number of elements allocated */
/*
+ ** Keep track of large rendering commands, which span multiple requests.
+ */
+ GLint largeCmdBytesSoFar; /* bytes received so far */
+ GLint largeCmdBytesTotal; /* total bytes expected */
+ GLint largeCmdRequestsSoFar; /* requests received so far */
+ GLint largeCmdRequestsTotal; /* total requests expected */
+ GLbyte *largeCmdBuf;
+ GLint largeCmdBufSize;
+
+ /*
** The drawable private this context is bound to
*/
__GLXdrawable *drawPriv;
diff --git a/glx/glxext.c b/glx/glxext.c
index a345c437a..a51c13ff1 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -66,18 +66,6 @@ static int __glXDispatch(ClientPtr);
static GLboolean __glXFreeContext(__GLXcontext * cx);
/*
-** 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. If the context is current for a client
* the dispatch layer will have moved the context struct to a fake resource ID
@@ -188,6 +176,7 @@ __glXFreeContext(__GLXcontext * cx)
free(cx->feedbackBuf);
free(cx->selectBuf);
+ free(cx->largeCmdBuf);
if (cx == lastGLContext) {
lastGLContext = NULL;
}
@@ -270,7 +259,6 @@ glxClientCallback(CallbackListPtr *list, void *closure, void *data)
switch (pClient->clientState) {
case ClientStateGone:
free(cl->returnBuf);
- free(cl->largeCmdBuf);
free(cl->GLClientextensions);
cl->returnBuf = NULL;
cl->GLClientextensions = NULL;
@@ -591,6 +579,9 @@ xorgGlxCreateVendor(void)
__GLXcontext *
__glXForceCurrent(__GLXclientState * cl, GLXContextTag tag, int *error)
{
+ ClientPtr client = cl->client;
+ REQUEST(xGLXSingleReq);
+
__GLXcontext *cx;
/*
@@ -604,6 +595,13 @@ __glXForceCurrent(__GLXclientState * cl, GLXContextTag tag, int *error)
return 0;
}
+ /* If we're expecting a glXRenderLarge request, this better be one. */
+ if (cx->largeCmdRequestsSoFar != 0 && stuff->glxCode != X_GLXRenderLarge) {
+ client->errorValue = stuff->glxCode;
+ *error = __glXError(GLXBadLargeRequest);
+ return 0;
+ }
+
if (!cx->isDirect) {
if (cx->drawPriv == NULL) {
/*
@@ -710,13 +708,6 @@ __glXDispatch(ClientPtr client)
opcode = stuff->glxCode;
cl = glxGetClient(client);
- /*
- ** 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 (!cl->client)
cl->client = client;
diff --git a/glx/glxext.h b/glx/glxext.h
index af59165bf..5ad497e4a 100644
--- a/glx/glxext.h
+++ b/glx/glxext.h
@@ -57,7 +57,6 @@ extern Bool __glXAddContext(__GLXcontext * cx);
extern void __glXErrorCallBack(GLenum code);
extern void __glXClearErrorOccured(void);
extern GLboolean __glXErrorOccured(void);
-extern void __glXResetLargeCommandStatus(__GLXclientState *);
extern const char GLServerVersion[];
extern int DoGetString(__GLXclientState * cl, GLbyte * pc, GLboolean need_swap);
diff --git a/glx/glxserver.h b/glx/glxserver.h
index 8ffde2342..60bdeb00d 100644
--- a/glx/glxserver.h
+++ b/glx/glxserver.h
@@ -115,16 +115,6 @@ struct __GLXclientStateRec {
GLbyte *returnBuf;
GLint returnBufSize;
- /*
- ** Keep track of large rendering commands, which span multiple requests.
- */
- GLint largeCmdBytesSoFar; /* bytes received so far */
- GLint largeCmdBytesTotal; /* total bytes expected */
- GLint largeCmdRequestsSoFar; /* requests received so far */
- GLint largeCmdRequestsTotal; /* total requests expected */
- GLbyte *largeCmdBuf;
- GLint largeCmdBufSize;
-
/* Back pointer to X client record */
ClientPtr client;