1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2008 VMware, Inc. 4848b8605Smrg * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 5848b8605Smrg * Copyright 2010-2011 LunarG, Inc. 6848b8605Smrg * All Rights Reserved. 7848b8605Smrg * 8848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 9848b8605Smrg * copy of this software and associated documentation files (the 10848b8605Smrg * "Software"), to deal in the Software without restriction, including 11848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 12848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 13848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 14848b8605Smrg * the following conditions: 15848b8605Smrg * 16848b8605Smrg * The above copyright notice and this permission notice (including the 17848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 18848b8605Smrg * of the Software. 19848b8605Smrg * 20848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26848b8605Smrg * DEALINGS IN THE SOFTWARE. 27848b8605Smrg * 28848b8605Smrg **************************************************************************/ 29848b8605Smrg 30848b8605Smrg 31848b8605Smrg#include <assert.h> 32848b8605Smrg#include <stdlib.h> 33848b8605Smrg#include <string.h> 34848b8605Smrg#include "eglconfig.h" 35848b8605Smrg#include "eglcontext.h" 36848b8605Smrg#include "egldisplay.h" 37848b8605Smrg#include "eglcurrent.h" 38848b8605Smrg#include "eglsurface.h" 39848b8605Smrg#include "egllog.h" 40b8e80941Smrg#include "util/macros.h" 41848b8605Smrg 42848b8605Smrg 43848b8605Smrg/** 44848b8605Smrg * Return the API bit (one of EGL_xxx_BIT) of the context. 45848b8605Smrg */ 46848b8605Smrgstatic EGLint 47848b8605Smrg_eglGetContextAPIBit(_EGLContext *ctx) 48848b8605Smrg{ 49848b8605Smrg EGLint bit = 0; 50848b8605Smrg 51848b8605Smrg switch (ctx->ClientAPI) { 52848b8605Smrg case EGL_OPENGL_ES_API: 53848b8605Smrg switch (ctx->ClientMajorVersion) { 54848b8605Smrg case 1: 55848b8605Smrg bit = EGL_OPENGL_ES_BIT; 56848b8605Smrg break; 57848b8605Smrg case 2: 58848b8605Smrg bit = EGL_OPENGL_ES2_BIT; 59848b8605Smrg break; 60848b8605Smrg case 3: 61848b8605Smrg bit = EGL_OPENGL_ES3_BIT_KHR; 62848b8605Smrg break; 63848b8605Smrg default: 64848b8605Smrg break; 65848b8605Smrg } 66848b8605Smrg break; 67848b8605Smrg case EGL_OPENVG_API: 68848b8605Smrg bit = EGL_OPENVG_BIT; 69848b8605Smrg break; 70848b8605Smrg case EGL_OPENGL_API: 71848b8605Smrg bit = EGL_OPENGL_BIT; 72848b8605Smrg break; 73848b8605Smrg default: 74848b8605Smrg break; 75848b8605Smrg } 76848b8605Smrg 77848b8605Smrg return bit; 78848b8605Smrg} 79848b8605Smrg 80848b8605Smrg 81848b8605Smrg/** 82848b8605Smrg * Parse the list of context attributes and return the proper error code. 83848b8605Smrg */ 84848b8605Smrgstatic EGLint 85b8e80941Smrg_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *disp, 86848b8605Smrg const EGLint *attrib_list) 87848b8605Smrg{ 88848b8605Smrg EGLenum api = ctx->ClientAPI; 89848b8605Smrg EGLint i, err = EGL_SUCCESS; 90848b8605Smrg 91848b8605Smrg if (!attrib_list) 92848b8605Smrg return EGL_SUCCESS; 93848b8605Smrg 94848b8605Smrg if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) { 95848b8605Smrg _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]); 96848b8605Smrg return EGL_BAD_ATTRIBUTE; 97848b8605Smrg } 98848b8605Smrg 99848b8605Smrg for (i = 0; attrib_list[i] != EGL_NONE; i++) { 100848b8605Smrg EGLint attr = attrib_list[i++]; 101848b8605Smrg EGLint val = attrib_list[i]; 102848b8605Smrg 103848b8605Smrg switch (attr) { 104848b8605Smrg case EGL_CONTEXT_CLIENT_VERSION: 105b8e80941Smrg /* The EGL 1.4 spec says: 106b8e80941Smrg * 107b8e80941Smrg * "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the 108b8e80941Smrg * current rendering API is EGL_OPENGL_ES_API" 109b8e80941Smrg * 110b8e80941Smrg * The EGL_KHR_create_context spec says: 111b8e80941Smrg * 112b8e80941Smrg * "EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 113b8e80941Smrg * (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)" 114b8e80941Smrg * 115b8e80941Smrg * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 116b8e80941Smrg * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API 117b8e80941Smrg * version. They are only meaningful for OpenGL and OpenGL ES 118b8e80941Smrg * contexts, and specifying them for other types of contexts will 119b8e80941Smrg * generate an error." 120b8e80941Smrg */ 121b8e80941Smrg if ((api != EGL_OPENGL_ES_API && 122b8e80941Smrg (!disp->Extensions.KHR_create_context || api != EGL_OPENGL_API))) { 123b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 124b8e80941Smrg break; 125b8e80941Smrg } 126b8e80941Smrg 127848b8605Smrg ctx->ClientMajorVersion = val; 128848b8605Smrg break; 129848b8605Smrg 130848b8605Smrg case EGL_CONTEXT_MINOR_VERSION_KHR: 131b8e80941Smrg /* The EGL_KHR_create_context spec says: 132b8e80941Smrg * 133b8e80941Smrg * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 134b8e80941Smrg * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API 135b8e80941Smrg * version. They are only meaningful for OpenGL and OpenGL ES 136b8e80941Smrg * contexts, and specifying them for other types of contexts will 137b8e80941Smrg * generate an error." 138b8e80941Smrg */ 139b8e80941Smrg if (!disp->Extensions.KHR_create_context || 140b8e80941Smrg (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) { 141848b8605Smrg err = EGL_BAD_ATTRIBUTE; 142848b8605Smrg break; 143848b8605Smrg } 144848b8605Smrg 145848b8605Smrg ctx->ClientMinorVersion = val; 146848b8605Smrg break; 147848b8605Smrg 148848b8605Smrg case EGL_CONTEXT_FLAGS_KHR: 149b8e80941Smrg if (!disp->Extensions.KHR_create_context) { 150848b8605Smrg err = EGL_BAD_ATTRIBUTE; 151848b8605Smrg break; 152848b8605Smrg } 153848b8605Smrg 154848b8605Smrg /* The EGL_KHR_create_context spec says: 155848b8605Smrg * 156b8e80941Smrg * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in 157b8e80941Smrg * EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created. 158b8e80941Smrg * [...] 159b8e80941Smrg * In some cases a debug context may be identical to a non-debug 160b8e80941Smrg * context. This bit is supported for OpenGL and OpenGL ES 161b8e80941Smrg * contexts." 162b8e80941Smrg */ 163b8e80941Smrg if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) && 164b8e80941Smrg (api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) { 165b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 166b8e80941Smrg break; 167b8e80941Smrg } 168b8e80941Smrg 169b8e80941Smrg /* The EGL_KHR_create_context spec says: 170b8e80941Smrg * 171b8e80941Smrg * "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit 172b8e80941Smrg * is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible> 173b8e80941Smrg * context will be created. Forward-compatible contexts are 174b8e80941Smrg * defined only for OpenGL versions 3.0 and later. They must not 175b8e80941Smrg * support functionality marked as <deprecated> by that version of 176b8e80941Smrg * the API, while a non-forward-compatible context must support 177b8e80941Smrg * all functionality in that version, deprecated or not. This bit 178b8e80941Smrg * is supported for OpenGL contexts, and requesting a 179b8e80941Smrg * forward-compatible context for OpenGL versions less than 3.0 180b8e80941Smrg * will generate an error." 181b8e80941Smrg * 182b8e80941Smrg * Note: since the forward-compatible flag can be set more than one way, 183b8e80941Smrg * the OpenGL version check is performed once, below. 184848b8605Smrg */ 185b8e80941Smrg if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) && 186b8e80941Smrg api != EGL_OPENGL_API) { 187b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 188b8e80941Smrg break; 189b8e80941Smrg } 190b8e80941Smrg 191b8e80941Smrg if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) && 192b8e80941Smrg api != EGL_OPENGL_API) { 193b8e80941Smrg /* The EGL_KHR_create_context spec says: 194b8e80941Smrg * 195b8e80941Smrg * 10) Which error should be generated if robust buffer access 196b8e80941Smrg * or reset notifications are requested under OpenGL ES? 197b8e80941Smrg * 198b8e80941Smrg * As per Issue 6, this extension does not support creating 199b8e80941Smrg * robust contexts for OpenGL ES. This is only supported via 200b8e80941Smrg * the EGL_EXT_create_context_robustness extension. 201b8e80941Smrg * 202b8e80941Smrg * Attempting to use this extension to create robust OpenGL 203b8e80941Smrg * ES context will generate an EGL_BAD_ATTRIBUTE error. This 204b8e80941Smrg * specific error is generated because this extension does 205b8e80941Smrg * not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 206b8e80941Smrg * and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 207b8e80941Smrg * bits for OpenGL ES contexts. Thus, use of these bits fall 208b8e80941Smrg * under condition described by: "If an attribute is 209b8e80941Smrg * specified that is not meaningful for the client API 210b8e80941Smrg * type.." in the above specification. 211b8e80941Smrg * 212b8e80941Smrg * The spec requires that we emit the error even if the display 213b8e80941Smrg * supports EGL_EXT_create_context_robustness. To create a robust 214b8e80941Smrg * GLES context, the *attribute* 215b8e80941Smrg * EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the 216b8e80941Smrg * *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR. 217b8e80941Smrg */ 218848b8605Smrg err = EGL_BAD_ATTRIBUTE; 219848b8605Smrg break; 220848b8605Smrg } 221848b8605Smrg 222b8e80941Smrg ctx->Flags |= val; 223848b8605Smrg break; 224848b8605Smrg 225848b8605Smrg case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR: 226b8e80941Smrg if (!disp->Extensions.KHR_create_context) { 227848b8605Smrg err = EGL_BAD_ATTRIBUTE; 228848b8605Smrg break; 229848b8605Smrg } 230848b8605Smrg 231848b8605Smrg /* The EGL_KHR_create_context spec says: 232848b8605Smrg * 233848b8605Smrg * "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for 234848b8605Smrg * OpenGL contexts, and specifying it for other types of 235848b8605Smrg * contexts, including OpenGL ES contexts, will generate an 236848b8605Smrg * error." 237848b8605Smrg */ 238848b8605Smrg if (api != EGL_OPENGL_API) { 239848b8605Smrg err = EGL_BAD_ATTRIBUTE; 240848b8605Smrg break; 241848b8605Smrg } 242848b8605Smrg 243848b8605Smrg ctx->Profile = val; 244848b8605Smrg break; 245848b8605Smrg 246848b8605Smrg case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR: 247848b8605Smrg /* The EGL_KHR_create_context spec says: 248848b8605Smrg * 249848b8605Smrg * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only 250848b8605Smrg * meaningful for OpenGL contexts, and specifying it for other 251848b8605Smrg * types of contexts, including OpenGL ES contexts, will generate 252848b8605Smrg * an error." 253848b8605Smrg */ 254b8e80941Smrg if (!disp->Extensions.KHR_create_context 255848b8605Smrg || api != EGL_OPENGL_API) { 256848b8605Smrg err = EGL_BAD_ATTRIBUTE; 257848b8605Smrg break; 258848b8605Smrg } 259848b8605Smrg 260848b8605Smrg ctx->ResetNotificationStrategy = val; 261848b8605Smrg break; 262848b8605Smrg 263848b8605Smrg case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: 264848b8605Smrg /* The EGL_EXT_create_context_robustness spec says: 265848b8605Smrg * 266848b8605Smrg * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only 267848b8605Smrg * meaningful for OpenGL ES contexts, and specifying it for other 268848b8605Smrg * types of contexts will generate an EGL_BAD_ATTRIBUTE error." 269848b8605Smrg */ 270b8e80941Smrg if (!disp->Extensions.EXT_create_context_robustness 271848b8605Smrg || api != EGL_OPENGL_ES_API) { 272848b8605Smrg err = EGL_BAD_ATTRIBUTE; 273848b8605Smrg break; 274848b8605Smrg } 275848b8605Smrg 276848b8605Smrg ctx->ResetNotificationStrategy = val; 277848b8605Smrg break; 278848b8605Smrg 279848b8605Smrg case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: 280b8e80941Smrg if (!disp->Extensions.EXT_create_context_robustness) { 281b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 282b8e80941Smrg break; 283b8e80941Smrg } 284b8e80941Smrg 285b8e80941Smrg if (val == EGL_TRUE) 286b8e80941Smrg ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 287b8e80941Smrg break; 288b8e80941Smrg 289b8e80941Smrg case EGL_CONTEXT_OPENGL_ROBUST_ACCESS: 290b8e80941Smrg if (disp->Version < 15) { 291b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 292b8e80941Smrg break; 293b8e80941Smrg } 294b8e80941Smrg 295b8e80941Smrg if (val == EGL_TRUE) 296b8e80941Smrg ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 297b8e80941Smrg break; 298b8e80941Smrg 299b8e80941Smrg case EGL_CONTEXT_OPENGL_DEBUG: 300b8e80941Smrg if (disp->Version < 15) { 301848b8605Smrg err = EGL_BAD_ATTRIBUTE; 302848b8605Smrg break; 303848b8605Smrg } 304848b8605Smrg 305b8e80941Smrg if (val == EGL_TRUE) 306b8e80941Smrg ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; 307b8e80941Smrg break; 308b8e80941Smrg 309b8e80941Smrg case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE: 310b8e80941Smrg if (disp->Version < 15) { 311b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 312b8e80941Smrg break; 313b8e80941Smrg } 314b8e80941Smrg 315b8e80941Smrg if (val == EGL_TRUE) 316b8e80941Smrg ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; 317b8e80941Smrg break; 318b8e80941Smrg 319b8e80941Smrg case EGL_CONTEXT_OPENGL_NO_ERROR_KHR: 320b8e80941Smrg if (disp->Version < 14 || 321b8e80941Smrg !disp->Extensions.KHR_create_context_no_error) { 322b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 323b8e80941Smrg break; 324b8e80941Smrg } 325b8e80941Smrg 326b8e80941Smrg /* The KHR_no_error spec only applies against OpenGL 2.0+ and 327b8e80941Smrg * OpenGL ES 2.0+ 328b8e80941Smrg */ 329b8e80941Smrg if ((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) || 330b8e80941Smrg ctx->ClientMajorVersion < 2) { 331b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 332b8e80941Smrg break; 333b8e80941Smrg } 334b8e80941Smrg 335b8e80941Smrg /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */ 336b8e80941Smrg ctx->NoError = !!val; 337b8e80941Smrg break; 338b8e80941Smrg 339b8e80941Smrg case EGL_CONTEXT_PRIORITY_LEVEL_IMG: 340b8e80941Smrg /* The EGL_IMG_context_priority spec says: 341b8e80941Smrg * 342b8e80941Smrg * "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of 343b8e80941Smrg * the context to be created. This attribute is a hint, as an 344b8e80941Smrg * implementation may not support multiple contexts at some 345b8e80941Smrg * priority levels and system policy may limit access to high 346b8e80941Smrg * priority contexts to appropriate system privilege level. The 347b8e80941Smrg * default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is 348b8e80941Smrg * EGL_CONTEXT_PRIORITY_MEDIUM_IMG." 349b8e80941Smrg */ 350b8e80941Smrg { 351b8e80941Smrg int bit; 352b8e80941Smrg 353b8e80941Smrg switch (val) { 354b8e80941Smrg case EGL_CONTEXT_PRIORITY_HIGH_IMG: 355b8e80941Smrg bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT; 356b8e80941Smrg break; 357b8e80941Smrg case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: 358b8e80941Smrg bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT; 359b8e80941Smrg break; 360b8e80941Smrg case EGL_CONTEXT_PRIORITY_LOW_IMG: 361b8e80941Smrg bit = __EGL_CONTEXT_PRIORITY_LOW_BIT; 362b8e80941Smrg break; 363b8e80941Smrg default: 364b8e80941Smrg bit = -1; 365b8e80941Smrg break; 366b8e80941Smrg } 367b8e80941Smrg 368b8e80941Smrg if (bit < 0) { 369b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 370b8e80941Smrg break; 371b8e80941Smrg } 372b8e80941Smrg 373b8e80941Smrg /* "This extension allows an EGLContext to be created with a 374b8e80941Smrg * priority hint. It is possible that an implementation will not 375b8e80941Smrg * honour the hint, especially if there are constraints on the 376b8e80941Smrg * number of high priority contexts available in the system, or 377b8e80941Smrg * system policy limits access to high priority contexts to 378b8e80941Smrg * appropriate system privilege level. A query is provided to find 379b8e80941Smrg * the real priority level assigned to the context after creation." 380b8e80941Smrg * 381b8e80941Smrg * We currently assume that the driver applies the priority hint 382b8e80941Smrg * and filters out any it cannot handle during the screen setup, 383b8e80941Smrg * e.g. dri2_setup_screen(). As such we can mask any change that 384b8e80941Smrg * the driver would fail, and ctx->ContextPriority matches the 385b8e80941Smrg * hint applied to the driver/hardware backend. 386b8e80941Smrg */ 387b8e80941Smrg if (disp->Extensions.IMG_context_priority & (1 << bit)) 388b8e80941Smrg ctx->ContextPriority = val; 389b8e80941Smrg 390b8e80941Smrg break; 391b8e80941Smrg } 392b8e80941Smrg 393b8e80941Smrg case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR: 394b8e80941Smrg if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR || 395b8e80941Smrg val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) { 396b8e80941Smrg ctx->ReleaseBehavior = val; 397b8e80941Smrg } else { 398b8e80941Smrg err = EGL_BAD_ATTRIBUTE; 399b8e80941Smrg } 400848b8605Smrg break; 401848b8605Smrg 402848b8605Smrg default: 403848b8605Smrg err = EGL_BAD_ATTRIBUTE; 404848b8605Smrg break; 405848b8605Smrg } 406848b8605Smrg 407848b8605Smrg if (err != EGL_SUCCESS) { 408848b8605Smrg _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr); 409848b8605Smrg break; 410848b8605Smrg } 411848b8605Smrg } 412848b8605Smrg 413848b8605Smrg if (api == EGL_OPENGL_API) { 414848b8605Smrg /* The EGL_KHR_create_context spec says: 415848b8605Smrg * 416848b8605Smrg * "If the requested OpenGL version is less than 3.2, 417848b8605Smrg * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the 418848b8605Smrg * functionality of the context is determined solely by the 419848b8605Smrg * requested version." 420848b8605Smrg * 421848b8605Smrg * Since the value is ignored, only validate the setting if the version 422848b8605Smrg * is >= 3.2. 423848b8605Smrg */ 424848b8605Smrg if (ctx->ClientMajorVersion >= 4 425848b8605Smrg || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) { 426848b8605Smrg switch (ctx->Profile) { 427848b8605Smrg case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR: 428848b8605Smrg case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR: 429848b8605Smrg break; 430848b8605Smrg 431848b8605Smrg default: 432848b8605Smrg /* The EGL_KHR_create_context spec says: 433848b8605Smrg * 434848b8605Smrg * "* If an OpenGL context is requested, the requested version 435848b8605Smrg * is greater than 3.2, and the value for attribute 436848b8605Smrg * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has 437848b8605Smrg * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 438848b8605Smrg * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has 439848b8605Smrg * more than one of these bits set; or if the implementation does 440848b8605Smrg * not support the requested profile, then an EGL_BAD_MATCH error 441848b8605Smrg * is generated." 442848b8605Smrg */ 443848b8605Smrg err = EGL_BAD_MATCH; 444848b8605Smrg break; 445848b8605Smrg } 446848b8605Smrg } 447848b8605Smrg 448848b8605Smrg /* The EGL_KHR_create_context spec says: 449848b8605Smrg * 450848b8605Smrg * "* If an OpenGL context is requested and the values for 451848b8605Smrg * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 452848b8605Smrg * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with 453848b8605Smrg * the value for attribute 454848b8605Smrg * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL 455848b8605Smrg * version and feature set that are not defined, than an 456848b8605Smrg * EGL_BAD_MATCH error is generated. 457848b8605Smrg * 458848b8605Smrg * ... Thus, examples of invalid combinations of attributes 459848b8605Smrg * include: 460848b8605Smrg * 461848b8605Smrg * - Major version < 1 or > 4 462848b8605Smrg * - Major version == 1 and minor version < 0 or > 5 463848b8605Smrg * - Major version == 2 and minor version < 0 or > 1 464848b8605Smrg * - Major version == 3 and minor version < 0 or > 2 465848b8605Smrg * - Major version == 4 and minor version < 0 or > 2 466848b8605Smrg * - Forward-compatible flag set and major version < 3" 467848b8605Smrg */ 468848b8605Smrg if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 469848b8605Smrg err = EGL_BAD_MATCH; 470848b8605Smrg 471848b8605Smrg switch (ctx->ClientMajorVersion) { 472848b8605Smrg case 1: 473848b8605Smrg if (ctx->ClientMinorVersion > 5 474848b8605Smrg || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 475848b8605Smrg err = EGL_BAD_MATCH; 476848b8605Smrg break; 477848b8605Smrg 478848b8605Smrg case 2: 479848b8605Smrg if (ctx->ClientMinorVersion > 1 480848b8605Smrg || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 481848b8605Smrg err = EGL_BAD_MATCH; 482848b8605Smrg break; 483848b8605Smrg 484848b8605Smrg case 3: 485848b8605Smrg /* Note: The text above is incorrect. There *is* an OpenGL 3.3! 486848b8605Smrg */ 487848b8605Smrg if (ctx->ClientMinorVersion > 3) 488848b8605Smrg err = EGL_BAD_MATCH; 489848b8605Smrg break; 490848b8605Smrg 491848b8605Smrg case 4: 492848b8605Smrg default: 493848b8605Smrg /* Don't put additional version checks here. We don't know that 494848b8605Smrg * there won't be versions > 4.2. 495848b8605Smrg */ 496848b8605Smrg break; 497848b8605Smrg } 498848b8605Smrg } else if (api == EGL_OPENGL_ES_API) { 499848b8605Smrg /* The EGL_KHR_create_context spec says: 500848b8605Smrg * 501848b8605Smrg * "* If an OpenGL ES context is requested and the values for 502848b8605Smrg * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 503848b8605Smrg * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 504848b8605Smrg * is not defined, than an EGL_BAD_MATCH error is generated. 505848b8605Smrg * 506848b8605Smrg * ... Examples of invalid combinations of attributes include: 507848b8605Smrg * 508848b8605Smrg * - Major version < 1 or > 2 509848b8605Smrg * - Major version == 1 and minor version < 0 or > 1 510848b8605Smrg * - Major version == 2 and minor version != 0 511848b8605Smrg */ 512848b8605Smrg if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 513848b8605Smrg err = EGL_BAD_MATCH; 514848b8605Smrg 515848b8605Smrg switch (ctx->ClientMajorVersion) { 516848b8605Smrg case 1: 517848b8605Smrg if (ctx->ClientMinorVersion > 1) 518848b8605Smrg err = EGL_BAD_MATCH; 519848b8605Smrg break; 520848b8605Smrg 521848b8605Smrg case 2: 522848b8605Smrg if (ctx->ClientMinorVersion > 0) 523848b8605Smrg err = EGL_BAD_MATCH; 524848b8605Smrg break; 525848b8605Smrg 526848b8605Smrg case 3: 527848b8605Smrg /* Don't put additional version checks here. We don't know that 528848b8605Smrg * there won't be versions > 3.0. 529848b8605Smrg */ 530848b8605Smrg break; 531848b8605Smrg 532848b8605Smrg default: 533848b8605Smrg err = EGL_BAD_MATCH; 534848b8605Smrg break; 535848b8605Smrg } 536848b8605Smrg } 537848b8605Smrg 538848b8605Smrg switch (ctx->ResetNotificationStrategy) { 539848b8605Smrg case EGL_NO_RESET_NOTIFICATION_KHR: 540848b8605Smrg case EGL_LOSE_CONTEXT_ON_RESET_KHR: 541848b8605Smrg break; 542848b8605Smrg 543848b8605Smrg default: 544848b8605Smrg err = EGL_BAD_ATTRIBUTE; 545848b8605Smrg break; 546848b8605Smrg } 547848b8605Smrg 548b8e80941Smrg /* The EGL_KHR_create_context_no_error spec says: 549b8e80941Smrg * 550b8e80941Smrg * "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at 551b8e80941Smrg * the same time as a debug or robustness context is specified." 552b8e80941Smrg */ 553b8e80941Smrg if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR || 554b8e80941Smrg ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) { 555b8e80941Smrg err = EGL_BAD_MATCH; 556b8e80941Smrg } 557b8e80941Smrg 558848b8605Smrg if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 559848b8605Smrg | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 560848b8605Smrg | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) { 561848b8605Smrg err = EGL_BAD_ATTRIBUTE; 562848b8605Smrg } 563848b8605Smrg 564848b8605Smrg return err; 565848b8605Smrg} 566848b8605Smrg 567848b8605Smrg 568848b8605Smrg/** 569848b8605Smrg * Initialize the given _EGLContext object to defaults and/or the values 570848b8605Smrg * in the attrib_list. 571b8e80941Smrg * 572b8e80941Smrg * According to EGL 1.5 Section 3.7: 573b8e80941Smrg * 574b8e80941Smrg * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all 575b8e80941Smrg * purposes except eglCreateContext." 576b8e80941Smrg * 577b8e80941Smrg * And since we only support GL and GLES, this is the only place where the 578b8e80941Smrg * bound API matters at all. We look up the current API from the current 579b8e80941Smrg * thread, and stash that in the context we're initializing. Our caller is 580b8e80941Smrg * responsible for determining whether that's an API it supports. 581848b8605Smrg */ 582848b8605SmrgEGLBoolean 583b8e80941Smrg_eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf, 584848b8605Smrg const EGLint *attrib_list) 585848b8605Smrg{ 586848b8605Smrg const EGLenum api = eglQueryAPI(); 587848b8605Smrg EGLint err; 588848b8605Smrg 589b8e80941Smrg if (api == EGL_NONE) 590b8e80941Smrg return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); 591848b8605Smrg 592b8e80941Smrg _eglInitResource(&ctx->Resource, sizeof(*ctx), disp); 593848b8605Smrg ctx->ClientAPI = api; 594848b8605Smrg ctx->Config = conf; 595848b8605Smrg ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 596848b8605Smrg 597848b8605Smrg ctx->ClientMajorVersion = 1; /* the default, per EGL spec */ 598848b8605Smrg ctx->ClientMinorVersion = 0; 599848b8605Smrg ctx->Flags = 0; 600848b8605Smrg ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR; 601b8e80941Smrg ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; 602b8e80941Smrg ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR; 603848b8605Smrg 604b8e80941Smrg err = _eglParseContextAttribList(ctx, disp, attrib_list); 605848b8605Smrg if (err == EGL_SUCCESS && ctx->Config) { 606848b8605Smrg EGLint api_bit; 607848b8605Smrg 608848b8605Smrg api_bit = _eglGetContextAPIBit(ctx); 609848b8605Smrg if (!(ctx->Config->RenderableType & api_bit)) { 610848b8605Smrg _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x", 611848b8605Smrg api_bit, ctx->Config->RenderableType); 612848b8605Smrg err = EGL_BAD_CONFIG; 613848b8605Smrg } 614848b8605Smrg } 615848b8605Smrg if (err != EGL_SUCCESS) 616848b8605Smrg return _eglError(err, "eglCreateContext"); 617848b8605Smrg 618848b8605Smrg return EGL_TRUE; 619848b8605Smrg} 620848b8605Smrg 621848b8605Smrg 622848b8605Smrgstatic EGLint 623848b8605Smrg_eglQueryContextRenderBuffer(_EGLContext *ctx) 624848b8605Smrg{ 625848b8605Smrg _EGLSurface *surf = ctx->DrawSurface; 626848b8605Smrg 627b8e80941Smrg /* From the EGL 1.5 spec: 628b8e80941Smrg * 629b8e80941Smrg * - If the context is not bound to a surface, then EGL_NONE will be 630b8e80941Smrg * returned. 631b8e80941Smrg */ 632848b8605Smrg if (!surf) 633848b8605Smrg return EGL_NONE; 634b8e80941Smrg 635b8e80941Smrg switch (surf->Type) { 636b8e80941Smrg default: 637b8e80941Smrg unreachable("bad EGLSurface type"); 638b8e80941Smrg case EGL_PIXMAP_BIT: 639b8e80941Smrg /* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER 640b8e80941Smrg * will be returned. 641b8e80941Smrg */ 642b8e80941Smrg return EGL_SINGLE_BUFFER; 643b8e80941Smrg case EGL_PBUFFER_BIT: 644b8e80941Smrg /* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER 645b8e80941Smrg * will be returned. 646b8e80941Smrg */ 647b8e80941Smrg return EGL_BACK_BUFFER; 648b8e80941Smrg case EGL_WINDOW_BIT: 649b8e80941Smrg /* - If the context is bound to a window surface, then either 650b8e80941Smrg * EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value 651b8e80941Smrg * returned depends on both the buffer requested by the setting of the 652b8e80941Smrg * EGL_RENDER_BUFFER property of the surface [...], and on the client 653b8e80941Smrg * API (not all client APIs support single-buffer Rendering to window 654b8e80941Smrg * surfaces). Some client APIs allow control of whether rendering goes 655b8e80941Smrg * to the front or back buffer. This client API-specific choice is not 656b8e80941Smrg * reflected in the returned value, which only describes the buffer 657b8e80941Smrg * that will be rendered to by default if not overridden by the client 658b8e80941Smrg * API. 659b8e80941Smrg */ 660b8e80941Smrg return surf->ActiveRenderBuffer; 661b8e80941Smrg } 662848b8605Smrg} 663848b8605Smrg 664848b8605Smrg 665848b8605SmrgEGLBoolean 666b8e80941Smrg_eglQueryContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *c, 667848b8605Smrg EGLint attribute, EGLint *value) 668848b8605Smrg{ 669848b8605Smrg (void) drv; 670b8e80941Smrg (void) disp; 671848b8605Smrg 672848b8605Smrg if (!value) 673848b8605Smrg return _eglError(EGL_BAD_PARAMETER, "eglQueryContext"); 674848b8605Smrg 675848b8605Smrg switch (attribute) { 676848b8605Smrg case EGL_CONFIG_ID: 677b8e80941Smrg /* 678b8e80941Smrg * From EGL_KHR_no_config_context: 679b8e80941Smrg * 680b8e80941Smrg * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with 681b8e80941Smrg * respect to which the context was created, or zero if created 682b8e80941Smrg * without respect to an EGLConfig." 683b8e80941Smrg */ 684b8e80941Smrg *value = c->Config ? c->Config->ConfigID : 0; 685848b8605Smrg break; 686848b8605Smrg case EGL_CONTEXT_CLIENT_VERSION: 687848b8605Smrg *value = c->ClientMajorVersion; 688848b8605Smrg break; 689848b8605Smrg case EGL_CONTEXT_CLIENT_TYPE: 690848b8605Smrg *value = c->ClientAPI; 691848b8605Smrg break; 692848b8605Smrg case EGL_RENDER_BUFFER: 693848b8605Smrg *value = _eglQueryContextRenderBuffer(c); 694848b8605Smrg break; 695b8e80941Smrg case EGL_CONTEXT_PRIORITY_LEVEL_IMG: 696b8e80941Smrg *value = c->ContextPriority; 697b8e80941Smrg break; 698848b8605Smrg default: 699848b8605Smrg return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); 700848b8605Smrg } 701848b8605Smrg 702848b8605Smrg return EGL_TRUE; 703848b8605Smrg} 704848b8605Smrg 705848b8605Smrg 706848b8605Smrg/** 707848b8605Smrg * Bind the context to the thread and return the previous context. 708848b8605Smrg * 709848b8605Smrg * Note that the context may be NULL. 710848b8605Smrg */ 711b8e80941Smrg_EGLContext * 712848b8605Smrg_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t) 713848b8605Smrg{ 714848b8605Smrg _EGLContext *oldCtx; 715848b8605Smrg 716b8e80941Smrg oldCtx = t->CurrentContext; 717848b8605Smrg if (ctx != oldCtx) { 718848b8605Smrg if (oldCtx) 719848b8605Smrg oldCtx->Binding = NULL; 720848b8605Smrg if (ctx) 721848b8605Smrg ctx->Binding = t; 722848b8605Smrg 723b8e80941Smrg t->CurrentContext = ctx; 724848b8605Smrg } 725848b8605Smrg 726848b8605Smrg return oldCtx; 727848b8605Smrg} 728848b8605Smrg 729848b8605Smrg 730848b8605Smrg/** 731848b8605Smrg * Return true if the given context and surfaces can be made current. 732848b8605Smrg */ 733848b8605Smrgstatic EGLBoolean 734848b8605Smrg_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) 735848b8605Smrg{ 736848b8605Smrg _EGLThreadInfo *t = _eglGetCurrentThread(); 737b8e80941Smrg _EGLDisplay *disp; 738848b8605Smrg 739848b8605Smrg if (_eglIsCurrentThreadDummy()) 740848b8605Smrg return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); 741848b8605Smrg 742848b8605Smrg /* this is easy */ 743848b8605Smrg if (!ctx) { 744848b8605Smrg if (draw || read) 745848b8605Smrg return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 746848b8605Smrg return EGL_TRUE; 747848b8605Smrg } 748848b8605Smrg 749b8e80941Smrg disp = ctx->Resource.Display; 750b8e80941Smrg if (!disp->Extensions.KHR_surfaceless_context 751848b8605Smrg && (draw == NULL || read == NULL)) 752848b8605Smrg return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 753848b8605Smrg 754848b8605Smrg /* 755848b8605Smrg * The spec says 756848b8605Smrg * 757848b8605Smrg * "If ctx is current to some other thread, or if either draw or read are 758848b8605Smrg * bound to contexts in another thread, an EGL_BAD_ACCESS error is 759848b8605Smrg * generated." 760848b8605Smrg * 761848b8605Smrg * and 762848b8605Smrg * 763848b8605Smrg * "at most one context may be bound to a particular surface at a given 764848b8605Smrg * time" 765848b8605Smrg */ 766848b8605Smrg if (ctx->Binding && ctx->Binding != t) 767848b8605Smrg return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 768848b8605Smrg if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { 769b8e80941Smrg if (draw->CurrentContext->Binding != t) 770848b8605Smrg return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 771848b8605Smrg } 772848b8605Smrg if (read && read->CurrentContext && read->CurrentContext != ctx) { 773b8e80941Smrg if (read->CurrentContext->Binding != t) 774848b8605Smrg return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 775848b8605Smrg } 776848b8605Smrg 777848b8605Smrg /* If the context has a config then it must match that of the two 778848b8605Smrg * surfaces */ 779848b8605Smrg if (ctx->Config) { 780848b8605Smrg if ((draw && draw->Config != ctx->Config) || 781848b8605Smrg (read && read->Config != ctx->Config)) 782848b8605Smrg return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 783848b8605Smrg } else { 784b8e80941Smrg /* Otherwise we must be using the EGL_KHR_no_config_context 785848b8605Smrg * extension */ 786b8e80941Smrg assert(disp->Extensions.KHR_no_config_context); 787848b8605Smrg 788848b8605Smrg /* The extension doesn't permit binding draw and read buffers with 789848b8605Smrg * differing contexts */ 790848b8605Smrg if (draw && read && draw->Config != read->Config) 791848b8605Smrg return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 792848b8605Smrg } 793848b8605Smrg 794848b8605Smrg return EGL_TRUE; 795848b8605Smrg} 796848b8605Smrg 797848b8605Smrg 798848b8605Smrg/** 799848b8605Smrg * Bind the context to the current thread and given surfaces. Return the 800848b8605Smrg * previous bound context and surfaces. The caller should unreference the 801848b8605Smrg * returned context and surfaces. 802848b8605Smrg * 803848b8605Smrg * Making a second call with the resources returned by the first call 804848b8605Smrg * unsurprisingly undoes the first call, except for the resouce reference 805848b8605Smrg * counts. 806848b8605Smrg */ 807848b8605SmrgEGLBoolean 808848b8605Smrg_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read, 809848b8605Smrg _EGLContext **old_ctx, 810848b8605Smrg _EGLSurface **old_draw, _EGLSurface **old_read) 811848b8605Smrg{ 812848b8605Smrg _EGLThreadInfo *t = _eglGetCurrentThread(); 813848b8605Smrg _EGLContext *prev_ctx; 814848b8605Smrg _EGLSurface *prev_draw, *prev_read; 815848b8605Smrg 816848b8605Smrg if (!_eglCheckMakeCurrent(ctx, draw, read)) 817848b8605Smrg return EGL_FALSE; 818848b8605Smrg 819848b8605Smrg /* increment refcounts before binding */ 820848b8605Smrg _eglGetContext(ctx); 821848b8605Smrg _eglGetSurface(draw); 822848b8605Smrg _eglGetSurface(read); 823848b8605Smrg 824848b8605Smrg /* bind the new context */ 825848b8605Smrg prev_ctx = _eglBindContextToThread(ctx, t); 826848b8605Smrg 827848b8605Smrg /* break previous bindings */ 828848b8605Smrg if (prev_ctx) { 829848b8605Smrg prev_draw = prev_ctx->DrawSurface; 830848b8605Smrg prev_read = prev_ctx->ReadSurface; 831848b8605Smrg 832848b8605Smrg if (prev_draw) 833848b8605Smrg prev_draw->CurrentContext = NULL; 834848b8605Smrg if (prev_read) 835848b8605Smrg prev_read->CurrentContext = NULL; 836848b8605Smrg 837848b8605Smrg prev_ctx->DrawSurface = NULL; 838848b8605Smrg prev_ctx->ReadSurface = NULL; 839848b8605Smrg } 840848b8605Smrg else { 841848b8605Smrg prev_draw = prev_read = NULL; 842848b8605Smrg } 843848b8605Smrg 844848b8605Smrg /* establish new bindings */ 845848b8605Smrg if (ctx) { 846848b8605Smrg if (draw) 847848b8605Smrg draw->CurrentContext = ctx; 848848b8605Smrg if (read) 849848b8605Smrg read->CurrentContext = ctx; 850848b8605Smrg 851848b8605Smrg ctx->DrawSurface = draw; 852848b8605Smrg ctx->ReadSurface = read; 853848b8605Smrg } 854848b8605Smrg 855848b8605Smrg assert(old_ctx && old_draw && old_read); 856848b8605Smrg *old_ctx = prev_ctx; 857848b8605Smrg *old_draw = prev_draw; 858848b8605Smrg *old_read = prev_read; 859848b8605Smrg 860848b8605Smrg return EGL_TRUE; 861848b8605Smrg} 862