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