[PATCH 11/11] glx: Implement protocol for glXCreateContextAttribsARB

Ian Romanick idr at freedesktop.org
Fri Dec 23 15:18:29 PST 2011


From: Ian Romanick <ian.d.romanick at intel.com>

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 glx/createcontext.c |  211 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 210 insertions(+), 1 deletions(-)

diff --git a/glx/createcontext.c b/glx/createcontext.c
index 785061d..b94fbbb 100644
--- a/glx/createcontext.c
+++ b/glx/createcontext.c
@@ -24,12 +24,221 @@
 #include <dix-config.h>
 #endif
 
+#include <GL/glxtokens.h>
 #include "glxserver.h"
+#include "glxext.h"
 #include "indirect_dispatch.h"
 
+#define ALL_VALID_FLAGS \
+    (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
+
+static Bool validate_GL_version(int major_version, int minor_version)
+{
+    if (major_version <= 0 || minor_version < 0)
+	return False;
+
+    switch (major_version) {
+    case 1:
+	if (minor_version > 5)
+	    return False;
+	break;
+
+    case 2:
+	if (minor_version > 1)
+	    return False;
+	break;
+
+    case 3:
+	if (minor_version > 3)
+	    return False;
+	break;
+
+    default:
+	break;
+    }
+
+    return True;
+}
+
+static Bool validate_render_type(uint32_t render_type)
+{
+    switch (render_type) {
+    case GLX_RGBA_TYPE:
+    case GLX_COLOR_INDEX_TYPE:
+	return True;
+    default:
+	return False;
+    }
+}
+
 int __glXDisp_CreateContextAttribsARB(__GLXclientState *cl, GLbyte *pc)
 {
-    return BadRequest;
+    ClientPtr client = cl->client;
+    xGLXCreateContextAttribsARBReq *req =
+	(xGLXCreateContextAttribsARBReq *) pc;
+    int32_t *attribs = (req->numAttribs != 0) ? (int32_t *) (req + 1) : NULL;
+    unsigned i;
+    int major_version = 1;
+    int minor_version = 0;
+    uint32_t flags = 0;
+    uint32_t render_type = GLX_RGBA_TYPE;
+    __GLXcontext *ctx = NULL;
+    __GLXcontext *shareCtx = NULL;
+    __GLXscreen *glxScreen;
+    __GLXconfig *config;
+    int err;
+
+    /* Verify that the size of the packet matches the size inferred from the
+     * sizes specified for the various fields.
+     */
+    const unsigned expected_size = (sz_xGLXCreateContextAttribsARBReq
+				    + (req->numAttribs * 8)) / 4;
+
+    if (req->length != expected_size)
+	return BadLength;
+
+    LEGAL_NEW_RESOURCE(req->context, client);
+
+    /* The GLX_ARB_create_context spec says:
+     *
+     *     "* If <config> is not a valid GLXFBConfig, GLXBadFBConfig is
+     *        generated."
+     *
+     * On the client, the screen comes from the FBConfig, so GLXBadFBConfig
+     * should be issued if the screen is nonsense.
+     */
+    if (!validGlxScreen(client, req->screen, &glxScreen, &err))
+	return __glXError(GLXBadFBConfig);
+
+    if (!validGlxFBConfig(client, glxScreen, req->fbconfig, &config, &err))
+	return __glXError(GLXBadFBConfig);
+
+    /* Validate the context with which the new context should share resources.
+     */
+    if (req->shareList != None) {
+	if (!validGlxContext(client, req->shareList, DixReadAccess,
+			     &shareCtx, &err))
+	    return err;
+
+	/* The crazy condition is because C doesn't have a logical XOR
+	 * operator.  Comparing directly for equality may fail if one is 1 and
+	 * the other is 2 even though both are logically true.
+	 */
+	if (!!req->isDirect != !!shareCtx->isDirect) {
+	    client->errorValue = req->shareList;
+	    return BadMatch;
+	}
+
+	/* The GLX_ARB_create_context spec says:
+	 *
+	 *     "* If the server context state for <share_context>...was
+	 *        created on a different screen than the one referenced by
+	 *        <config>...BadMatch is generated."
+	 */
+ 	if (glxScreen != shareCtx->pGlxScreen) {
+	    client->errorValue = shareCtx->pGlxScreen->pScreen->myNum;
+	    return BadMatch;
+	}
+    }
+
+    for (i = 0; i < req->numAttribs; i++) {
+	switch (attribs[i * 2]) {
+	case GLX_CONTEXT_MAJOR_VERSION_ARB:
+	    major_version = attribs[2 * i + 1];
+	    break;
+
+	case GLX_CONTEXT_MINOR_VERSION_ARB:
+	    minor_version = attribs[2 * i + 1];
+	    break;
+
+	case GLX_CONTEXT_FLAGS_ARB:
+	    flags = attribs[2 * i + 1];
+	    break;
+
+	case GLX_RENDER_TYPE:
+	    render_type = attribs[2 * i + 1];
+	    break;
+
+	default:
+	    return BadValue;
+	}
+    }
+
+    /* The GLX_ARB_create_context spec says:
+     *
+     *     "If attributes GLX_CONTEXT_MAJOR_VERSION_ARB and
+     *     GLX_CONTEXT_MINOR_VERSION_ARB, when considered together
+     *     with attributes GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB and
+     *     GLX_RENDER_TYPE, specify an OpenGL version and feature set
+     *     that are not defined, BadMatch is generated.
+     *
+     *     ...Feature deprecation was introduced with OpenGL 3.0, so
+     *     forward-compatible contexts may only be requested for
+     *     OpenGL 3.0 and above. Thus, examples of invalid
+     *     combinations of attributes include:
+     *
+     *       - Major version < 1 or > 3
+     *       - Major version == 1 and minor version < 0 or > 5
+     *       - Major version == 2 and minor version < 0 or > 1
+     *       - Major version == 3 and minor version > 2
+     *       - Forward-compatible flag set and major version < 3
+     *       - Color index rendering and major version >= 3"
+     */
+    if (!validate_GL_version(major_version, minor_version))
+	return BadMatch;
+
+    if (major_version < 3
+	&& ((flags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) != 0))
+	return BadMatch;
+
+    if (major_version >= 3 && render_type == GLX_COLOR_INDEX_TYPE)
+	return BadMatch;
+
+    if (!validate_render_type(render_type))
+	return BadValue;
+
+    if ((flags & ~ALL_VALID_FLAGS) != 0)
+	return BadValue;
+
+    /* Allocate memory for the new context
+     */
+    if (req->isDirect) {
+	ctx = __glXdirectContextCreate(glxScreen, config, shareCtx);
+	err = BadAlloc;
+    } else {
+	ctx = glxScreen->createContext(glxScreen, config, shareCtx,
+				       req->numAttribs, (uint32_t *) attribs,
+				       &err);
+    }
+
+    if (ctx == NULL)
+	return err;
+
+    ctx->pGlxScreen = glxScreen;
+    ctx->config = config;
+    ctx->id = req->context;
+    ctx->share_id = req->shareList;
+    ctx->idExists = True;
+    ctx->isCurrent = False;
+    ctx->isDirect = req->isDirect;
+    ctx->hasUnflushedCommands = False;
+    ctx->renderMode = GL_RENDER;
+    ctx->feedbackBuf = NULL;
+    ctx->feedbackBufSize = 0;
+    ctx->selectBuf = NULL;
+    ctx->selectBufSize = 0;
+    ctx->drawPriv = NULL;
+    ctx->readPriv = NULL;
+
+    /* Add the new context to the various global tables of GLX contexts.
+     */
+    if (!__glXAddContext(ctx)) {
+	(*ctx->destroy)(ctx);
+	client->errorValue = req->context;
+	return BadAlloc;
+    }
+
+    return Success;
 }
 
 int __glXDispSwap_CreateContextAttribsARB(__GLXclientState *cl, GLbyte *pc)
-- 
1.7.6.4



More information about the xorg-devel mailing list