1/* 2 * Copyright © 2011 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23#ifdef HAVE_DIX_CONFIG_H 24#include <dix-config.h> 25#endif 26 27#include <GL/glxtokens.h> 28#include "glxserver.h" 29#include "glxext.h" 30#include "indirect_dispatch.h" 31#include "opaque.h" 32 33#define ALL_VALID_FLAGS \ 34 (GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB \ 35 | GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB) 36 37static Bool 38validate_GL_version(int major_version, int minor_version) 39{ 40 if (major_version <= 0 || minor_version < 0) 41 return FALSE; 42 43 switch (major_version) { 44 case 1: 45 if (minor_version > 5) 46 return FALSE; 47 break; 48 49 case 2: 50 if (minor_version > 1) 51 return FALSE; 52 break; 53 54 case 3: 55 if (minor_version > 3) 56 return FALSE; 57 break; 58 59 default: 60 break; 61 } 62 63 return TRUE; 64} 65 66static Bool 67validate_render_type(uint32_t render_type) 68{ 69 switch (render_type) { 70 case GLX_RGBA_TYPE: 71 case GLX_COLOR_INDEX_TYPE: 72 case GLX_RGBA_FLOAT_TYPE_ARB: 73 case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT: 74 return TRUE; 75 default: 76 return FALSE; 77 } 78} 79 80int 81__glXDisp_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc) 82{ 83 ClientPtr client = cl->client; 84 xGLXCreateContextAttribsARBReq *req = (xGLXCreateContextAttribsARBReq *) pc; 85 int32_t *attribs = (req->numAttribs != 0) ? (int32_t *) (req + 1) : NULL; 86 unsigned i; 87 int major_version = 1; 88 int minor_version = 0; 89 uint32_t flags = 0; 90 uint32_t render_type = GLX_RGBA_TYPE; 91 uint32_t flush = GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB; 92 __GLXcontext *ctx = NULL; 93 __GLXcontext *shareCtx = NULL; 94 __GLXscreen *glxScreen; 95 __GLXconfig *config = NULL; 96 int err; 97 98 /* The GLX_ARB_create_context_robustness spec says: 99 * 100 * "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 101 * is GLX_NO_RESET_NOTIFICATION_ARB." 102 */ 103 int reset = GLX_NO_RESET_NOTIFICATION_ARB; 104 105 /* The GLX_ARB_create_context_profile spec says: 106 * 107 * "The default value for GLX_CONTEXT_PROFILE_MASK_ARB is 108 * GLX_CONTEXT_CORE_PROFILE_BIT_ARB." 109 * 110 * The core profile only makes sense for OpenGL versions 3.2 and later. 111 * If the version ultimately specified is less than 3.2, the core profile 112 * bit is cleared (see below). 113 */ 114 int profile = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; 115 116 /* Verify that the size of the packet matches the size inferred from the 117 * sizes specified for the various fields. 118 */ 119 const unsigned expected_size = (sz_xGLXCreateContextAttribsARBReq 120 + (req->numAttribs * 8)) / 4; 121 122 if (req->length != expected_size) 123 return BadLength; 124 125 /* The GLX_ARB_create_context spec says: 126 * 127 * "* If <config> is not a valid GLXFBConfig, GLXBadFBConfig is 128 * generated." 129 * 130 * On the client, the screen comes from the FBConfig, so GLXBadFBConfig 131 * should be issued if the screen is nonsense. 132 */ 133 if (!validGlxScreen(client, req->screen, &glxScreen, &err)) { 134 client->errorValue = req->fbconfig; 135 return __glXError(GLXBadFBConfig); 136 } 137 138 if (req->fbconfig) { 139 if (!validGlxFBConfig(client, glxScreen, req->fbconfig, &config, &err)) { 140 client->errorValue = req->fbconfig; 141 return __glXError(GLXBadFBConfig); 142 } 143 } 144 145 /* Validate the context with which the new context should share resources. 146 */ 147 if (req->shareList != None) { 148 if (!validGlxContext(client, req->shareList, DixReadAccess, 149 &shareCtx, &err)) 150 return err; 151 152 /* The crazy condition is because C doesn't have a logical XOR 153 * operator. Comparing directly for equality may fail if one is 1 and 154 * the other is 2 even though both are logically true. 155 */ 156 if (!!req->isDirect != !!shareCtx->isDirect) { 157 client->errorValue = req->shareList; 158 return BadMatch; 159 } 160 161 /* The GLX_ARB_create_context spec says: 162 * 163 * "* If the server context state for <share_context>...was 164 * created on a different screen than the one referenced by 165 * <config>...BadMatch is generated." 166 */ 167 if (glxScreen != shareCtx->pGlxScreen) { 168 client->errorValue = shareCtx->pGlxScreen->pScreen->myNum; 169 return BadMatch; 170 } 171 } 172 173 for (i = 0; i < req->numAttribs; i++) { 174 switch (attribs[i * 2]) { 175 case GLX_CONTEXT_MAJOR_VERSION_ARB: 176 major_version = attribs[2 * i + 1]; 177 break; 178 179 case GLX_CONTEXT_MINOR_VERSION_ARB: 180 minor_version = attribs[2 * i + 1]; 181 break; 182 183 case GLX_CONTEXT_FLAGS_ARB: 184 flags = attribs[2 * i + 1]; 185 break; 186 187 case GLX_RENDER_TYPE: 188 /* Not valid for GLX_EXT_no_config_context */ 189 if (!req->fbconfig) 190 return BadValue; 191 render_type = attribs[2 * i + 1]; 192 break; 193 194 case GLX_CONTEXT_PROFILE_MASK_ARB: 195 profile = attribs[2 * i + 1]; 196 break; 197 198 case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB: 199 reset = attribs[2 * i + 1]; 200 if (reset != GLX_NO_RESET_NOTIFICATION_ARB 201 && reset != GLX_LOSE_CONTEXT_ON_RESET_ARB) 202 return BadValue; 203 204 break; 205 206 case GLX_CONTEXT_RELEASE_BEHAVIOR_ARB: 207 flush = attribs[2 * i + 1]; 208 if (flush != GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 209 && flush != GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB) 210 return BadValue; 211 break; 212 213 case GLX_SCREEN: 214 /* Only valid for GLX_EXT_no_config_context */ 215 if (req->fbconfig) 216 return BadValue; 217 /* Must match the value in the request header */ 218 if (attribs[2 * i + 1] != req->screen) 219 return BadValue; 220 break; 221 222 case GLX_CONTEXT_OPENGL_NO_ERROR_ARB: 223 /* ignore */ 224 break; 225 226 default: 227 if (!req->isDirect) 228 return BadValue; 229 break; 230 } 231 } 232 233 /* The GLX_ARB_create_context spec says: 234 * 235 * "If attributes GLX_CONTEXT_MAJOR_VERSION_ARB and 236 * GLX_CONTEXT_MINOR_VERSION_ARB, when considered together 237 * with attributes GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB and 238 * GLX_RENDER_TYPE, specify an OpenGL version and feature set 239 * that are not defined, BadMatch is generated. 240 * 241 * ...Feature deprecation was introduced with OpenGL 3.0, so 242 * forward-compatible contexts may only be requested for 243 * OpenGL 3.0 and above. Thus, examples of invalid 244 * combinations of attributes include: 245 * 246 * - Major version < 1 or > 3 247 * - Major version == 1 and minor version < 0 or > 5 248 * - Major version == 2 and minor version < 0 or > 1 249 * - Major version == 3 and minor version > 2 250 * - Forward-compatible flag set and major version < 3 251 * - Color index rendering and major version >= 3" 252 */ 253 if (!validate_GL_version(major_version, minor_version)) 254 return BadMatch; 255 256 if (major_version < 3 257 && ((flags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) != 0)) 258 return BadMatch; 259 260 if (major_version >= 3 && render_type == GLX_COLOR_INDEX_TYPE) 261 return BadMatch; 262 263 if (!validate_render_type(render_type)) 264 return BadValue; 265 266 if ((flags & ~ALL_VALID_FLAGS) != 0) 267 return BadValue; 268 269 /* The GLX_ARB_create_context_profile spec says: 270 * 271 * "* If attribute GLX_CONTEXT_PROFILE_MASK_ARB has no bits set; has 272 * any bits set other than GLX_CONTEXT_CORE_PROFILE_BIT_ARB and 273 * GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; has more than one of 274 * these bits set; or if the implementation does not support the 275 * requested profile, then GLXBadProfileARB is generated." 276 * 277 * The GLX_EXT_create_context_es2_profile spec doesn't exactly say what 278 * is supposed to happen if an invalid version is set, but it doesn't 279 * much matter as support for GLES contexts is only defined for direct 280 * contexts (at the moment anyway) so we can leave it up to the driver 281 * to validate. 282 */ 283 switch (profile) { 284 case GLX_CONTEXT_CORE_PROFILE_BIT_ARB: 285 case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: 286 case GLX_CONTEXT_ES2_PROFILE_BIT_EXT: 287 break; 288 default: 289 return __glXError(GLXBadProfileARB); 290 } 291 292 /* The GLX_ARB_create_context_robustness spec says: 293 * 294 * "* If the reset notification behavior of <share_context> and the 295 * newly created context are different, BadMatch is generated." 296 */ 297 if (shareCtx != NULL && shareCtx->resetNotificationStrategy != reset) 298 return BadMatch; 299 300 /* There is no GLX protocol for desktop OpenGL versions after 1.4. There 301 * is no GLX protocol for any version of OpenGL ES. If the application is 302 * requested an indirect rendering context for a version that cannot be 303 * satisfied, reject it. 304 * 305 * The GLX_ARB_create_context spec says: 306 * 307 * "* If <config> does not support compatible OpenGL contexts 308 * providing the requested API major and minor version, 309 * forward-compatible flag, and debug context flag, GLXBadFBConfig 310 * is generated." 311 */ 312 if (!req->isDirect && (major_version > 1 || minor_version > 4 313 || profile == GLX_CONTEXT_ES2_PROFILE_BIT_EXT)) { 314 client->errorValue = req->fbconfig; 315 return __glXError(GLXBadFBConfig); 316 } 317 318 /* Allocate memory for the new context 319 */ 320 if (req->isDirect) { 321 ctx = __glXdirectContextCreate(glxScreen, config, shareCtx); 322 err = BadAlloc; 323 } 324 else { 325 /* Only allow creating indirect GLX contexts if allowed by 326 * server command line. Indirect GLX is of limited use (since 327 * it's only GL 1.4), it's slower than direct contexts, and 328 * it's a massive attack surface for buffer overflow type 329 * errors. 330 */ 331 if (!enableIndirectGLX) { 332 client->errorValue = req->isDirect; 333 return BadValue; 334 } 335 336 ctx = glxScreen->createContext(glxScreen, config, shareCtx, 337 req->numAttribs, (uint32_t *) attribs, 338 &err); 339 } 340 341 if (ctx == NULL) 342 return err; 343 344 ctx->pGlxScreen = glxScreen; 345 ctx->config = config; 346 ctx->id = req->context; 347 ctx->share_id = req->shareList; 348 ctx->idExists = TRUE; 349 ctx->isDirect = req->isDirect; 350 ctx->renderMode = GL_RENDER; 351 ctx->resetNotificationStrategy = reset; 352 ctx->releaseBehavior = flush; 353 ctx->renderType = render_type; 354 355 /* Add the new context to the various global tables of GLX contexts. 356 */ 357 if (!__glXAddContext(ctx)) { 358 (*ctx->destroy) (ctx); 359 client->errorValue = req->context; 360 return BadAlloc; 361 } 362 363 return Success; 364} 365 366int 367__glXDispSwap_CreateContextAttribsARB(__GLXclientState * cl, GLbyte * pc) 368{ 369 return BadRequest; 370} 371