createcontext.c revision 35c4bbdf
135c4bbdfSmrg/*
235c4bbdfSmrg * Copyright © 2011 Intel Corporation
335c4bbdfSmrg *
435c4bbdfSmrg * Permission is hereby granted, free of charge, to any person obtaining a
535c4bbdfSmrg * copy of this software and associated documentation files (the "Software"),
635c4bbdfSmrg * to deal in the Software without restriction, including without limitation
735c4bbdfSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
835c4bbdfSmrg * and/or sell copies of the Software, and to permit persons to whom the
935c4bbdfSmrg * Software is furnished to do so, subject to the following conditions:
1035c4bbdfSmrg *
1135c4bbdfSmrg * The above copyright notice and this permission notice (including the next
1235c4bbdfSmrg * paragraph) shall be included in all copies or substantial portions of the
1335c4bbdfSmrg * Software.
1435c4bbdfSmrg *
1535c4bbdfSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1635c4bbdfSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1735c4bbdfSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1835c4bbdfSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1935c4bbdfSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2035c4bbdfSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2135c4bbdfSmrg * DEALINGS IN THE SOFTWARE.
2235c4bbdfSmrg */
2335c4bbdfSmrg#ifdef HAVE_DIX_CONFIG_H
2435c4bbdfSmrg#include <dix-config.h>
2535c4bbdfSmrg#endif
2635c4bbdfSmrg
2735c4bbdfSmrg#include <GL/glxtokens.h>
2835c4bbdfSmrg#include "glxserver.h"
2935c4bbdfSmrg#include "glxext.h"
3035c4bbdfSmrg#include "indirect_dispatch.h"
3135c4bbdfSmrg
3235c4bbdfSmrg#define ALL_VALID_FLAGS \
3335c4bbdfSmrg    (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB \
3435c4bbdfSmrg     | GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
3535c4bbdfSmrg
3635c4bbdfSmrgstatic Bool
3735c4bbdfSmrgvalidate_GL_version(int major_version, int minor_version)
3835c4bbdfSmrg{
3935c4bbdfSmrg    if (major_version <= 0 || minor_version < 0)
4035c4bbdfSmrg        return False;
4135c4bbdfSmrg
4235c4bbdfSmrg    switch (major_version) {
4335c4bbdfSmrg    case 1:
4435c4bbdfSmrg        if (minor_version > 5)
4535c4bbdfSmrg            return False;
4635c4bbdfSmrg        break;
4735c4bbdfSmrg
4835c4bbdfSmrg    case 2:
4935c4bbdfSmrg        if (minor_version > 1)
5035c4bbdfSmrg            return False;
5135c4bbdfSmrg        break;
5235c4bbdfSmrg
5335c4bbdfSmrg    case 3:
5435c4bbdfSmrg        if (minor_version > 3)
5535c4bbdfSmrg            return False;
5635c4bbdfSmrg        break;
5735c4bbdfSmrg
5835c4bbdfSmrg    default:
5935c4bbdfSmrg        break;
6035c4bbdfSmrg    }
6135c4bbdfSmrg
6235c4bbdfSmrg    return True;
6335c4bbdfSmrg}
6435c4bbdfSmrg
6535c4bbdfSmrgstatic Bool
6635c4bbdfSmrgvalidate_render_type(uint32_t render_type)
6735c4bbdfSmrg{
6835c4bbdfSmrg    switch (render_type) {
6935c4bbdfSmrg    case GLX_RGBA_TYPE:
7035c4bbdfSmrg    case GLX_COLOR_INDEX_TYPE:
7135c4bbdfSmrg    case GLX_RGBA_FLOAT_TYPE_ARB:
7235c4bbdfSmrg    case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT:
7335c4bbdfSmrg        return True;
7435c4bbdfSmrg    default:
7535c4bbdfSmrg        return False;
7635c4bbdfSmrg    }
7735c4bbdfSmrg}
7835c4bbdfSmrg
7935c4bbdfSmrgint
8035c4bbdfSmrg__glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
8135c4bbdfSmrg{
8235c4bbdfSmrg    ClientPtr client = cl->client;
8335c4bbdfSmrg    xGLXCreateContextAttribsARBReq *req = (xGLXCreateContextAttribsARBReq *) pc;
8435c4bbdfSmrg    int32_t *attribs = (req->numAttribs != 0) ? (int32_t *) (req + 1) : NULL;
8535c4bbdfSmrg    unsigned i;
8635c4bbdfSmrg    int major_version = 1;
8735c4bbdfSmrg    int minor_version = 0;
8835c4bbdfSmrg    uint32_t flags = 0;
8935c4bbdfSmrg    uint32_t render_type = GLX_RGBA_TYPE;
9035c4bbdfSmrg#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
9135c4bbdfSmrg    uint32_t flush = GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB;
9235c4bbdfSmrg#endif
9335c4bbdfSmrg    __GLXcontext *ctx = NULL;
9435c4bbdfSmrg    __GLXcontext *shareCtx = NULL;
9535c4bbdfSmrg    __GLXscreen *glxScreen;
9635c4bbdfSmrg    __GLXconfig *config;
9735c4bbdfSmrg    int err;
9835c4bbdfSmrg
9935c4bbdfSmrg    /* The GLX_ARB_create_context_robustness spec says:
10035c4bbdfSmrg     *
10135c4bbdfSmrg     *     "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
10235c4bbdfSmrg     *     is GLX_NO_RESET_NOTIFICATION_ARB."
10335c4bbdfSmrg     */
10435c4bbdfSmrg    int reset = GLX_NO_RESET_NOTIFICATION_ARB;
10535c4bbdfSmrg
10635c4bbdfSmrg    /* The GLX_ARB_create_context_profile spec says:
10735c4bbdfSmrg     *
10835c4bbdfSmrg     *     "The default value for GLX_CONTEXT_PROFILE_MASK_ARB is
10935c4bbdfSmrg     *     GLX_CONTEXT_CORE_PROFILE_BIT_ARB."
11035c4bbdfSmrg     *
11135c4bbdfSmrg     * The core profile only makes sense for OpenGL versions 3.2 and later.
11235c4bbdfSmrg     * If the version ultimately specified is less than 3.2, the core profile
11335c4bbdfSmrg     * bit is cleared (see below).
11435c4bbdfSmrg     */
11535c4bbdfSmrg    int profile = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
11635c4bbdfSmrg
11735c4bbdfSmrg    /* Verify that the size of the packet matches the size inferred from the
11835c4bbdfSmrg     * sizes specified for the various fields.
11935c4bbdfSmrg     */
12035c4bbdfSmrg    const unsigned expected_size = (sz_xGLXCreateContextAttribsARBReq
12135c4bbdfSmrg                                    + (req->numAttribs * 8)) / 4;
12235c4bbdfSmrg
12335c4bbdfSmrg    if (req->length != expected_size)
12435c4bbdfSmrg        return BadLength;
12535c4bbdfSmrg
12635c4bbdfSmrg    LEGAL_NEW_RESOURCE(req->context, client);
12735c4bbdfSmrg
12835c4bbdfSmrg    /* The GLX_ARB_create_context spec says:
12935c4bbdfSmrg     *
13035c4bbdfSmrg     *     "* If <config> is not a valid GLXFBConfig, GLXBadFBConfig is
13135c4bbdfSmrg     *        generated."
13235c4bbdfSmrg     *
13335c4bbdfSmrg     * On the client, the screen comes from the FBConfig, so GLXBadFBConfig
13435c4bbdfSmrg     * should be issued if the screen is nonsense.
13535c4bbdfSmrg     */
13635c4bbdfSmrg    if (!validGlxScreen(client, req->screen, &glxScreen, &err))
13735c4bbdfSmrg        return __glXError(GLXBadFBConfig);
13835c4bbdfSmrg
13935c4bbdfSmrg    if (!validGlxFBConfig(client, glxScreen, req->fbconfig, &config, &err))
14035c4bbdfSmrg        return __glXError(GLXBadFBConfig);
14135c4bbdfSmrg
14235c4bbdfSmrg    /* Validate the context with which the new context should share resources.
14335c4bbdfSmrg     */
14435c4bbdfSmrg    if (req->shareList != None) {
14535c4bbdfSmrg        if (!validGlxContext(client, req->shareList, DixReadAccess,
14635c4bbdfSmrg                             &shareCtx, &err))
14735c4bbdfSmrg            return err;
14835c4bbdfSmrg
14935c4bbdfSmrg        /* The crazy condition is because C doesn't have a logical XOR
15035c4bbdfSmrg         * operator.  Comparing directly for equality may fail if one is 1 and
15135c4bbdfSmrg         * the other is 2 even though both are logically true.
15235c4bbdfSmrg         */
15335c4bbdfSmrg        if (!!req->isDirect != !!shareCtx->isDirect) {
15435c4bbdfSmrg            client->errorValue = req->shareList;
15535c4bbdfSmrg            return BadMatch;
15635c4bbdfSmrg        }
15735c4bbdfSmrg
15835c4bbdfSmrg        /* The GLX_ARB_create_context spec says:
15935c4bbdfSmrg         *
16035c4bbdfSmrg         *     "* If the server context state for <share_context>...was
16135c4bbdfSmrg         *        created on a different screen than the one referenced by
16235c4bbdfSmrg         *        <config>...BadMatch is generated."
16335c4bbdfSmrg         */
16435c4bbdfSmrg        if (glxScreen != shareCtx->pGlxScreen) {
16535c4bbdfSmrg            client->errorValue = shareCtx->pGlxScreen->pScreen->myNum;
16635c4bbdfSmrg            return BadMatch;
16735c4bbdfSmrg        }
16835c4bbdfSmrg    }
16935c4bbdfSmrg
17035c4bbdfSmrg    for (i = 0; i < req->numAttribs; i++) {
17135c4bbdfSmrg        switch (attribs[i * 2]) {
17235c4bbdfSmrg        case GLX_CONTEXT_MAJOR_VERSION_ARB:
17335c4bbdfSmrg            major_version = attribs[2 * i + 1];
17435c4bbdfSmrg            break;
17535c4bbdfSmrg
17635c4bbdfSmrg        case GLX_CONTEXT_MINOR_VERSION_ARB:
17735c4bbdfSmrg            minor_version = attribs[2 * i + 1];
17835c4bbdfSmrg            break;
17935c4bbdfSmrg
18035c4bbdfSmrg        case GLX_CONTEXT_FLAGS_ARB:
18135c4bbdfSmrg            flags = attribs[2 * i + 1];
18235c4bbdfSmrg            break;
18335c4bbdfSmrg
18435c4bbdfSmrg        case GLX_RENDER_TYPE:
18535c4bbdfSmrg            render_type = attribs[2 * i + 1];
18635c4bbdfSmrg            break;
18735c4bbdfSmrg
18835c4bbdfSmrg        case GLX_CONTEXT_PROFILE_MASK_ARB:
18935c4bbdfSmrg            profile = attribs[2 * i + 1];
19035c4bbdfSmrg            break;
19135c4bbdfSmrg
19235c4bbdfSmrg        case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
19335c4bbdfSmrg            reset = attribs[2 * i + 1];
19435c4bbdfSmrg            if (reset != GLX_NO_RESET_NOTIFICATION_ARB
19535c4bbdfSmrg                && reset != GLX_LOSE_CONTEXT_ON_RESET_ARB)
19635c4bbdfSmrg                return BadValue;
19735c4bbdfSmrg
19835c4bbdfSmrg            break;
19935c4bbdfSmrg
20035c4bbdfSmrg#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
20135c4bbdfSmrg        case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB:
20235c4bbdfSmrg            flush = attribs[2 * i + 1];
20335c4bbdfSmrg            if (flush != GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB
20435c4bbdfSmrg                && flush != GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB)
20535c4bbdfSmrg                return BadValue;
20635c4bbdfSmrg            break;
20735c4bbdfSmrg#endif
20835c4bbdfSmrg
20935c4bbdfSmrg        default:
21035c4bbdfSmrg            return BadValue;
21135c4bbdfSmrg        }
21235c4bbdfSmrg    }
21335c4bbdfSmrg
21435c4bbdfSmrg    /* The GLX_ARB_create_context spec says:
21535c4bbdfSmrg     *
21635c4bbdfSmrg     *     "If attributes GLX_CONTEXT_MAJOR_VERSION_ARB and
21735c4bbdfSmrg     *     GLX_CONTEXT_MINOR_VERSION_ARB, when considered together
21835c4bbdfSmrg     *     with attributes GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB and
21935c4bbdfSmrg     *     GLX_RENDER_TYPE, specify an OpenGL version and feature set
22035c4bbdfSmrg     *     that are not defined, BadMatch is generated.
22135c4bbdfSmrg     *
22235c4bbdfSmrg     *     ...Feature deprecation was introduced with OpenGL 3.0, so
22335c4bbdfSmrg     *     forward-compatible contexts may only be requested for
22435c4bbdfSmrg     *     OpenGL 3.0 and above. Thus, examples of invalid
22535c4bbdfSmrg     *     combinations of attributes include:
22635c4bbdfSmrg     *
22735c4bbdfSmrg     *       - Major version < 1 or > 3
22835c4bbdfSmrg     *       - Major version == 1 and minor version < 0 or > 5
22935c4bbdfSmrg     *       - Major version == 2 and minor version < 0 or > 1
23035c4bbdfSmrg     *       - Major version == 3 and minor version > 2
23135c4bbdfSmrg     *       - Forward-compatible flag set and major version < 3
23235c4bbdfSmrg     *       - Color index rendering and major version >= 3"
23335c4bbdfSmrg     */
23435c4bbdfSmrg    if (!validate_GL_version(major_version, minor_version))
23535c4bbdfSmrg        return BadMatch;
23635c4bbdfSmrg
23735c4bbdfSmrg    if (major_version < 3
23835c4bbdfSmrg        && ((flags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) != 0))
23935c4bbdfSmrg        return BadMatch;
24035c4bbdfSmrg
24135c4bbdfSmrg    if (major_version >= 3 && render_type == GLX_COLOR_INDEX_TYPE)
24235c4bbdfSmrg        return BadMatch;
24335c4bbdfSmrg
24435c4bbdfSmrg    if (!validate_render_type(render_type))
24535c4bbdfSmrg        return BadValue;
24635c4bbdfSmrg
24735c4bbdfSmrg    if ((flags & ~ALL_VALID_FLAGS) != 0)
24835c4bbdfSmrg        return BadValue;
24935c4bbdfSmrg
25035c4bbdfSmrg    /* The GLX_ARB_create_context_profile spec says:
25135c4bbdfSmrg     *
25235c4bbdfSmrg     *     "* If attribute GLX_CONTEXT_PROFILE_MASK_ARB has no bits set; has
25335c4bbdfSmrg     *        any bits set other than GLX_CONTEXT_CORE_PROFILE_BIT_ARB and
25435c4bbdfSmrg     *        GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; has more than one of
25535c4bbdfSmrg     *        these bits set; or if the implementation does not support the
25635c4bbdfSmrg     *        requested profile, then GLXBadProfileARB is generated."
25735c4bbdfSmrg     *
25835c4bbdfSmrg     * The GLX_EXT_create_context_es2_profile spec doesn't exactly say what
25935c4bbdfSmrg     * is supposed to happen if an invalid version is set, but it doesn't
26035c4bbdfSmrg     * much matter as support for GLES contexts is only defined for direct
26135c4bbdfSmrg     * contexts (at the moment anyway) so we can leave it up to the driver
26235c4bbdfSmrg     * to validate.
26335c4bbdfSmrg     */
26435c4bbdfSmrg    switch (profile) {
26535c4bbdfSmrg    case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
26635c4bbdfSmrg    case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
26735c4bbdfSmrg    case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
26835c4bbdfSmrg        break;
26935c4bbdfSmrg    default:
27035c4bbdfSmrg        return __glXError(GLXBadProfileARB);
27135c4bbdfSmrg    }
27235c4bbdfSmrg
27335c4bbdfSmrg    /* The GLX_ARB_create_context_robustness spec says:
27435c4bbdfSmrg     *
27535c4bbdfSmrg     *     "* If the reset notification behavior of <share_context> and the
27635c4bbdfSmrg     *        newly created context are different, BadMatch is generated."
27735c4bbdfSmrg     */
27835c4bbdfSmrg    if (shareCtx != NULL && shareCtx->resetNotificationStrategy != reset)
27935c4bbdfSmrg        return BadMatch;
28035c4bbdfSmrg
28135c4bbdfSmrg    /* There is no GLX protocol for desktop OpenGL versions after 1.4.  There
28235c4bbdfSmrg     * is no GLX protocol for any version of OpenGL ES.  If the application is
28335c4bbdfSmrg     * requested an indirect rendering context for a version that cannot be
28435c4bbdfSmrg     * satisfied, reject it.
28535c4bbdfSmrg     *
28635c4bbdfSmrg     * The GLX_ARB_create_context spec says:
28735c4bbdfSmrg     *
28835c4bbdfSmrg     *     "* If <config> does not support compatible OpenGL contexts
28935c4bbdfSmrg     *        providing the requested API major and minor version,
29035c4bbdfSmrg     *        forward-compatible flag, and debug context flag, GLXBadFBConfig
29135c4bbdfSmrg     *        is generated."
29235c4bbdfSmrg     */
29335c4bbdfSmrg    if (!req->isDirect && (major_version > 1 || minor_version > 4
29435c4bbdfSmrg                           || profile == GLX_CONTEXT_ES2_PROFILE_BIT_EXT)) {
29535c4bbdfSmrg        return __glXError(GLXBadFBConfig);
29635c4bbdfSmrg    }
29735c4bbdfSmrg
29835c4bbdfSmrg    /* Allocate memory for the new context
29935c4bbdfSmrg     */
30035c4bbdfSmrg    if (req->isDirect) {
30135c4bbdfSmrg        ctx = __glXdirectContextCreate(glxScreen, config, shareCtx);
30235c4bbdfSmrg        err = BadAlloc;
30335c4bbdfSmrg    }
30435c4bbdfSmrg    else {
30535c4bbdfSmrg        ctx = glxScreen->createContext(glxScreen, config, shareCtx,
30635c4bbdfSmrg                                       req->numAttribs, (uint32_t *) attribs,
30735c4bbdfSmrg                                       &err);
30835c4bbdfSmrg    }
30935c4bbdfSmrg
31035c4bbdfSmrg    if (ctx == NULL)
31135c4bbdfSmrg        return err;
31235c4bbdfSmrg
31335c4bbdfSmrg    ctx->pGlxScreen = glxScreen;
31435c4bbdfSmrg    ctx->config = config;
31535c4bbdfSmrg    ctx->id = req->context;
31635c4bbdfSmrg    ctx->share_id = req->shareList;
31735c4bbdfSmrg    ctx->idExists = True;
31835c4bbdfSmrg    ctx->currentClient = False;
31935c4bbdfSmrg    ctx->isDirect = req->isDirect;
32035c4bbdfSmrg    ctx->hasUnflushedCommands = False;
32135c4bbdfSmrg    ctx->renderMode = GL_RENDER;
32235c4bbdfSmrg    ctx->feedbackBuf = NULL;
32335c4bbdfSmrg    ctx->feedbackBufSize = 0;
32435c4bbdfSmrg    ctx->selectBuf = NULL;
32535c4bbdfSmrg    ctx->selectBufSize = 0;
32635c4bbdfSmrg    ctx->drawPriv = NULL;
32735c4bbdfSmrg    ctx->readPriv = NULL;
32835c4bbdfSmrg    ctx->resetNotificationStrategy = reset;
32935c4bbdfSmrg#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
33035c4bbdfSmrg    ctx->releaseBehavior = flush;
33135c4bbdfSmrg#endif
33235c4bbdfSmrg
33335c4bbdfSmrg    /* Add the new context to the various global tables of GLX contexts.
33435c4bbdfSmrg     */
33535c4bbdfSmrg    if (!__glXAddContext(ctx)) {
33635c4bbdfSmrg        (*ctx->destroy) (ctx);
33735c4bbdfSmrg        client->errorValue = req->context;
33835c4bbdfSmrg        return BadAlloc;
33935c4bbdfSmrg    }
34035c4bbdfSmrg
34135c4bbdfSmrg    return Success;
34235c4bbdfSmrg}
34335c4bbdfSmrg
34435c4bbdfSmrgint
34535c4bbdfSmrg__glXDispSwap_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc)
34635c4bbdfSmrg{
34735c4bbdfSmrg    return BadRequest;
34835c4bbdfSmrg}
349