diff options
author | Adam Jackson <ajax@redhat.com> | 2018-01-10 13:05:48 -0500 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2018-02-14 17:04:48 -0500 |
commit | 133bd4443be6b76a36afadfae0905b832e998165 (patch) | |
tree | 27ce5bdc19c8b1e6700d0e4167b832da10bc1723 /glx | |
parent | 5d87e4f71355272c8da38c83f493b826623301cc (diff) | |
download | xserver-133bd4443be6b76a36afadfae0905b832e998165.tar.gz |
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.c | 70 | ||||
-rw-r--r-- | glx/glxcontext.h | 10 | ||||
-rw-r--r-- | glx/glxext.c | 31 | ||||
-rw-r--r-- | glx/glxext.h | 1 | ||||
-rw-r--r-- | glx/glxserver.h | 10 |
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; |