eglcontext.c revision 848b8605
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" 40848b8605Smrg 41848b8605Smrg 42848b8605Smrg/** 43848b8605Smrg * Return the API bit (one of EGL_xxx_BIT) of the context. 44848b8605Smrg */ 45848b8605Smrgstatic EGLint 46848b8605Smrg_eglGetContextAPIBit(_EGLContext *ctx) 47848b8605Smrg{ 48848b8605Smrg EGLint bit = 0; 49848b8605Smrg 50848b8605Smrg switch (ctx->ClientAPI) { 51848b8605Smrg case EGL_OPENGL_ES_API: 52848b8605Smrg switch (ctx->ClientMajorVersion) { 53848b8605Smrg case 1: 54848b8605Smrg bit = EGL_OPENGL_ES_BIT; 55848b8605Smrg break; 56848b8605Smrg case 2: 57848b8605Smrg bit = EGL_OPENGL_ES2_BIT; 58848b8605Smrg break; 59848b8605Smrg case 3: 60848b8605Smrg bit = EGL_OPENGL_ES3_BIT_KHR; 61848b8605Smrg break; 62848b8605Smrg default: 63848b8605Smrg break; 64848b8605Smrg } 65848b8605Smrg break; 66848b8605Smrg case EGL_OPENVG_API: 67848b8605Smrg bit = EGL_OPENVG_BIT; 68848b8605Smrg break; 69848b8605Smrg case EGL_OPENGL_API: 70848b8605Smrg bit = EGL_OPENGL_BIT; 71848b8605Smrg break; 72848b8605Smrg default: 73848b8605Smrg break; 74848b8605Smrg } 75848b8605Smrg 76848b8605Smrg return bit; 77848b8605Smrg} 78848b8605Smrg 79848b8605Smrg 80848b8605Smrg/** 81848b8605Smrg * Parse the list of context attributes and return the proper error code. 82848b8605Smrg */ 83848b8605Smrgstatic EGLint 84848b8605Smrg_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy, 85848b8605Smrg const EGLint *attrib_list) 86848b8605Smrg{ 87848b8605Smrg EGLenum api = ctx->ClientAPI; 88848b8605Smrg EGLint i, err = EGL_SUCCESS; 89848b8605Smrg 90848b8605Smrg if (!attrib_list) 91848b8605Smrg return EGL_SUCCESS; 92848b8605Smrg 93848b8605Smrg if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) { 94848b8605Smrg _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]); 95848b8605Smrg return EGL_BAD_ATTRIBUTE; 96848b8605Smrg } 97848b8605Smrg 98848b8605Smrg for (i = 0; attrib_list[i] != EGL_NONE; i++) { 99848b8605Smrg EGLint attr = attrib_list[i++]; 100848b8605Smrg EGLint val = attrib_list[i]; 101848b8605Smrg 102848b8605Smrg switch (attr) { 103848b8605Smrg case EGL_CONTEXT_CLIENT_VERSION: 104848b8605Smrg ctx->ClientMajorVersion = val; 105848b8605Smrg break; 106848b8605Smrg 107848b8605Smrg case EGL_CONTEXT_MINOR_VERSION_KHR: 108848b8605Smrg if (!dpy->Extensions.KHR_create_context) { 109848b8605Smrg err = EGL_BAD_ATTRIBUTE; 110848b8605Smrg break; 111848b8605Smrg } 112848b8605Smrg 113848b8605Smrg ctx->ClientMinorVersion = val; 114848b8605Smrg break; 115848b8605Smrg 116848b8605Smrg case EGL_CONTEXT_FLAGS_KHR: 117848b8605Smrg if (!dpy->Extensions.KHR_create_context) { 118848b8605Smrg err = EGL_BAD_ATTRIBUTE; 119848b8605Smrg break; 120848b8605Smrg } 121848b8605Smrg 122848b8605Smrg /* The EGL_KHR_create_context spec says: 123848b8605Smrg * 124848b8605Smrg * "Flags are only defined for OpenGL context creation, and 125848b8605Smrg * specifying a flags value other than zero for other types of 126848b8605Smrg * contexts, including OpenGL ES contexts, will generate an 127848b8605Smrg * error." 128848b8605Smrg */ 129848b8605Smrg if (api != EGL_OPENGL_API && val != 0) { 130848b8605Smrg err = EGL_BAD_ATTRIBUTE; 131848b8605Smrg break; 132848b8605Smrg } 133848b8605Smrg 134848b8605Smrg ctx->Flags = val; 135848b8605Smrg break; 136848b8605Smrg 137848b8605Smrg case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR: 138848b8605Smrg if (!dpy->Extensions.KHR_create_context) { 139848b8605Smrg err = EGL_BAD_ATTRIBUTE; 140848b8605Smrg break; 141848b8605Smrg } 142848b8605Smrg 143848b8605Smrg /* The EGL_KHR_create_context spec says: 144848b8605Smrg * 145848b8605Smrg * "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for 146848b8605Smrg * OpenGL contexts, and specifying it for other types of 147848b8605Smrg * contexts, including OpenGL ES contexts, will generate an 148848b8605Smrg * error." 149848b8605Smrg */ 150848b8605Smrg if (api != EGL_OPENGL_API) { 151848b8605Smrg err = EGL_BAD_ATTRIBUTE; 152848b8605Smrg break; 153848b8605Smrg } 154848b8605Smrg 155848b8605Smrg ctx->Profile = val; 156848b8605Smrg break; 157848b8605Smrg 158848b8605Smrg case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR: 159848b8605Smrg /* The EGL_KHR_create_context spec says: 160848b8605Smrg * 161848b8605Smrg * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only 162848b8605Smrg * meaningful for OpenGL contexts, and specifying it for other 163848b8605Smrg * types of contexts, including OpenGL ES contexts, will generate 164848b8605Smrg * an error." 165848b8605Smrg */ 166848b8605Smrg if (!dpy->Extensions.KHR_create_context 167848b8605Smrg || api != EGL_OPENGL_API) { 168848b8605Smrg err = EGL_BAD_ATTRIBUTE; 169848b8605Smrg break; 170848b8605Smrg } 171848b8605Smrg 172848b8605Smrg ctx->ResetNotificationStrategy = val; 173848b8605Smrg break; 174848b8605Smrg 175848b8605Smrg case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: 176848b8605Smrg /* The EGL_EXT_create_context_robustness spec says: 177848b8605Smrg * 178848b8605Smrg * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only 179848b8605Smrg * meaningful for OpenGL ES contexts, and specifying it for other 180848b8605Smrg * types of contexts will generate an EGL_BAD_ATTRIBUTE error." 181848b8605Smrg */ 182848b8605Smrg if (!dpy->Extensions.EXT_create_context_robustness 183848b8605Smrg || api != EGL_OPENGL_ES_API) { 184848b8605Smrg err = EGL_BAD_ATTRIBUTE; 185848b8605Smrg break; 186848b8605Smrg } 187848b8605Smrg 188848b8605Smrg ctx->ResetNotificationStrategy = val; 189848b8605Smrg break; 190848b8605Smrg 191848b8605Smrg case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: 192848b8605Smrg if (!dpy->Extensions.EXT_create_context_robustness) { 193848b8605Smrg err = EGL_BAD_ATTRIBUTE; 194848b8605Smrg break; 195848b8605Smrg } 196848b8605Smrg 197848b8605Smrg ctx->Flags = EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 198848b8605Smrg break; 199848b8605Smrg 200848b8605Smrg default: 201848b8605Smrg err = EGL_BAD_ATTRIBUTE; 202848b8605Smrg break; 203848b8605Smrg } 204848b8605Smrg 205848b8605Smrg if (err != EGL_SUCCESS) { 206848b8605Smrg _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr); 207848b8605Smrg break; 208848b8605Smrg } 209848b8605Smrg } 210848b8605Smrg 211848b8605Smrg if (api == EGL_OPENGL_API) { 212848b8605Smrg /* The EGL_KHR_create_context spec says: 213848b8605Smrg * 214848b8605Smrg * "If the requested OpenGL version is less than 3.2, 215848b8605Smrg * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the 216848b8605Smrg * functionality of the context is determined solely by the 217848b8605Smrg * requested version." 218848b8605Smrg * 219848b8605Smrg * Since the value is ignored, only validate the setting if the version 220848b8605Smrg * is >= 3.2. 221848b8605Smrg */ 222848b8605Smrg if (ctx->ClientMajorVersion >= 4 223848b8605Smrg || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) { 224848b8605Smrg switch (ctx->Profile) { 225848b8605Smrg case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR: 226848b8605Smrg case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR: 227848b8605Smrg break; 228848b8605Smrg 229848b8605Smrg default: 230848b8605Smrg /* The EGL_KHR_create_context spec says: 231848b8605Smrg * 232848b8605Smrg * "* If an OpenGL context is requested, the requested version 233848b8605Smrg * is greater than 3.2, and the value for attribute 234848b8605Smrg * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has 235848b8605Smrg * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 236848b8605Smrg * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has 237848b8605Smrg * more than one of these bits set; or if the implementation does 238848b8605Smrg * not support the requested profile, then an EGL_BAD_MATCH error 239848b8605Smrg * is generated." 240848b8605Smrg */ 241848b8605Smrg err = EGL_BAD_MATCH; 242848b8605Smrg break; 243848b8605Smrg } 244848b8605Smrg } 245848b8605Smrg 246848b8605Smrg /* The EGL_KHR_create_context spec says: 247848b8605Smrg * 248848b8605Smrg * "* If an OpenGL context is requested and the values for 249848b8605Smrg * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 250848b8605Smrg * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with 251848b8605Smrg * the value for attribute 252848b8605Smrg * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL 253848b8605Smrg * version and feature set that are not defined, than an 254848b8605Smrg * EGL_BAD_MATCH error is generated. 255848b8605Smrg * 256848b8605Smrg * ... Thus, examples of invalid combinations of attributes 257848b8605Smrg * include: 258848b8605Smrg * 259848b8605Smrg * - Major version < 1 or > 4 260848b8605Smrg * - Major version == 1 and minor version < 0 or > 5 261848b8605Smrg * - Major version == 2 and minor version < 0 or > 1 262848b8605Smrg * - Major version == 3 and minor version < 0 or > 2 263848b8605Smrg * - Major version == 4 and minor version < 0 or > 2 264848b8605Smrg * - Forward-compatible flag set and major version < 3" 265848b8605Smrg */ 266848b8605Smrg if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 267848b8605Smrg err = EGL_BAD_MATCH; 268848b8605Smrg 269848b8605Smrg switch (ctx->ClientMajorVersion) { 270848b8605Smrg case 1: 271848b8605Smrg if (ctx->ClientMinorVersion > 5 272848b8605Smrg || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 273848b8605Smrg err = EGL_BAD_MATCH; 274848b8605Smrg break; 275848b8605Smrg 276848b8605Smrg case 2: 277848b8605Smrg if (ctx->ClientMinorVersion > 1 278848b8605Smrg || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 279848b8605Smrg err = EGL_BAD_MATCH; 280848b8605Smrg break; 281848b8605Smrg 282848b8605Smrg case 3: 283848b8605Smrg /* Note: The text above is incorrect. There *is* an OpenGL 3.3! 284848b8605Smrg */ 285848b8605Smrg if (ctx->ClientMinorVersion > 3) 286848b8605Smrg err = EGL_BAD_MATCH; 287848b8605Smrg break; 288848b8605Smrg 289848b8605Smrg case 4: 290848b8605Smrg default: 291848b8605Smrg /* Don't put additional version checks here. We don't know that 292848b8605Smrg * there won't be versions > 4.2. 293848b8605Smrg */ 294848b8605Smrg break; 295848b8605Smrg } 296848b8605Smrg } else if (api == EGL_OPENGL_ES_API) { 297848b8605Smrg /* The EGL_KHR_create_context spec says: 298848b8605Smrg * 299848b8605Smrg * "* If an OpenGL ES context is requested and the values for 300848b8605Smrg * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 301848b8605Smrg * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 302848b8605Smrg * is not defined, than an EGL_BAD_MATCH error is generated. 303848b8605Smrg * 304848b8605Smrg * ... Examples of invalid combinations of attributes include: 305848b8605Smrg * 306848b8605Smrg * - Major version < 1 or > 2 307848b8605Smrg * - Major version == 1 and minor version < 0 or > 1 308848b8605Smrg * - Major version == 2 and minor version != 0 309848b8605Smrg */ 310848b8605Smrg if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 311848b8605Smrg err = EGL_BAD_MATCH; 312848b8605Smrg 313848b8605Smrg switch (ctx->ClientMajorVersion) { 314848b8605Smrg case 1: 315848b8605Smrg if (ctx->ClientMinorVersion > 1) 316848b8605Smrg err = EGL_BAD_MATCH; 317848b8605Smrg break; 318848b8605Smrg 319848b8605Smrg case 2: 320848b8605Smrg if (ctx->ClientMinorVersion > 0) 321848b8605Smrg err = EGL_BAD_MATCH; 322848b8605Smrg break; 323848b8605Smrg 324848b8605Smrg case 3: 325848b8605Smrg /* Don't put additional version checks here. We don't know that 326848b8605Smrg * there won't be versions > 3.0. 327848b8605Smrg */ 328848b8605Smrg break; 329848b8605Smrg 330848b8605Smrg default: 331848b8605Smrg err = EGL_BAD_MATCH; 332848b8605Smrg break; 333848b8605Smrg } 334848b8605Smrg } 335848b8605Smrg 336848b8605Smrg switch (ctx->ResetNotificationStrategy) { 337848b8605Smrg case EGL_NO_RESET_NOTIFICATION_KHR: 338848b8605Smrg case EGL_LOSE_CONTEXT_ON_RESET_KHR: 339848b8605Smrg break; 340848b8605Smrg 341848b8605Smrg default: 342848b8605Smrg err = EGL_BAD_ATTRIBUTE; 343848b8605Smrg break; 344848b8605Smrg } 345848b8605Smrg 346848b8605Smrg if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 347848b8605Smrg | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 348848b8605Smrg | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) { 349848b8605Smrg err = EGL_BAD_ATTRIBUTE; 350848b8605Smrg } 351848b8605Smrg 352848b8605Smrg return err; 353848b8605Smrg} 354848b8605Smrg 355848b8605Smrg 356848b8605Smrg/** 357848b8605Smrg * Initialize the given _EGLContext object to defaults and/or the values 358848b8605Smrg * in the attrib_list. 359848b8605Smrg */ 360848b8605SmrgEGLBoolean 361848b8605Smrg_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, 362848b8605Smrg const EGLint *attrib_list) 363848b8605Smrg{ 364848b8605Smrg const EGLenum api = eglQueryAPI(); 365848b8605Smrg EGLint err; 366848b8605Smrg 367848b8605Smrg if (api == EGL_NONE) { 368848b8605Smrg _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); 369848b8605Smrg return EGL_FALSE; 370848b8605Smrg } 371848b8605Smrg 372848b8605Smrg _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy); 373848b8605Smrg ctx->ClientAPI = api; 374848b8605Smrg ctx->Config = conf; 375848b8605Smrg ctx->WindowRenderBuffer = EGL_NONE; 376848b8605Smrg ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 377848b8605Smrg 378848b8605Smrg ctx->ClientMajorVersion = 1; /* the default, per EGL spec */ 379848b8605Smrg ctx->ClientMinorVersion = 0; 380848b8605Smrg ctx->Flags = 0; 381848b8605Smrg ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 382848b8605Smrg ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR; 383848b8605Smrg 384848b8605Smrg err = _eglParseContextAttribList(ctx, dpy, attrib_list); 385848b8605Smrg if (err == EGL_SUCCESS && ctx->Config) { 386848b8605Smrg EGLint api_bit; 387848b8605Smrg 388848b8605Smrg api_bit = _eglGetContextAPIBit(ctx); 389848b8605Smrg if (!(ctx->Config->RenderableType & api_bit)) { 390848b8605Smrg _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x", 391848b8605Smrg api_bit, ctx->Config->RenderableType); 392848b8605Smrg err = EGL_BAD_CONFIG; 393848b8605Smrg } 394848b8605Smrg } 395848b8605Smrg if (err != EGL_SUCCESS) 396848b8605Smrg return _eglError(err, "eglCreateContext"); 397848b8605Smrg 398848b8605Smrg return EGL_TRUE; 399848b8605Smrg} 400848b8605Smrg 401848b8605Smrg 402848b8605Smrgstatic EGLint 403848b8605Smrg_eglQueryContextRenderBuffer(_EGLContext *ctx) 404848b8605Smrg{ 405848b8605Smrg _EGLSurface *surf = ctx->DrawSurface; 406848b8605Smrg EGLint rb; 407848b8605Smrg 408848b8605Smrg if (!surf) 409848b8605Smrg return EGL_NONE; 410848b8605Smrg if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE) 411848b8605Smrg rb = ctx->WindowRenderBuffer; 412848b8605Smrg else 413848b8605Smrg rb = surf->RenderBuffer; 414848b8605Smrg return rb; 415848b8605Smrg} 416848b8605Smrg 417848b8605Smrg 418848b8605SmrgEGLBoolean 419848b8605Smrg_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, 420848b8605Smrg EGLint attribute, EGLint *value) 421848b8605Smrg{ 422848b8605Smrg (void) drv; 423848b8605Smrg (void) dpy; 424848b8605Smrg 425848b8605Smrg if (!value) 426848b8605Smrg return _eglError(EGL_BAD_PARAMETER, "eglQueryContext"); 427848b8605Smrg 428848b8605Smrg switch (attribute) { 429848b8605Smrg case EGL_CONFIG_ID: 430848b8605Smrg if (!c->Config) 431848b8605Smrg return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); 432848b8605Smrg *value = c->Config->ConfigID; 433848b8605Smrg break; 434848b8605Smrg case EGL_CONTEXT_CLIENT_VERSION: 435848b8605Smrg *value = c->ClientMajorVersion; 436848b8605Smrg break; 437848b8605Smrg case EGL_CONTEXT_CLIENT_TYPE: 438848b8605Smrg *value = c->ClientAPI; 439848b8605Smrg break; 440848b8605Smrg case EGL_RENDER_BUFFER: 441848b8605Smrg *value = _eglQueryContextRenderBuffer(c); 442848b8605Smrg break; 443848b8605Smrg default: 444848b8605Smrg return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); 445848b8605Smrg } 446848b8605Smrg 447848b8605Smrg return EGL_TRUE; 448848b8605Smrg} 449848b8605Smrg 450848b8605Smrg 451848b8605Smrg/** 452848b8605Smrg * Bind the context to the thread and return the previous context. 453848b8605Smrg * 454848b8605Smrg * Note that the context may be NULL. 455848b8605Smrg */ 456848b8605Smrgstatic _EGLContext * 457848b8605Smrg_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t) 458848b8605Smrg{ 459848b8605Smrg EGLint apiIndex; 460848b8605Smrg _EGLContext *oldCtx; 461848b8605Smrg 462848b8605Smrg apiIndex = (ctx) ? 463848b8605Smrg _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex; 464848b8605Smrg 465848b8605Smrg oldCtx = t->CurrentContexts[apiIndex]; 466848b8605Smrg if (ctx != oldCtx) { 467848b8605Smrg if (oldCtx) 468848b8605Smrg oldCtx->Binding = NULL; 469848b8605Smrg if (ctx) 470848b8605Smrg ctx->Binding = t; 471848b8605Smrg 472848b8605Smrg t->CurrentContexts[apiIndex] = ctx; 473848b8605Smrg } 474848b8605Smrg 475848b8605Smrg return oldCtx; 476848b8605Smrg} 477848b8605Smrg 478848b8605Smrg 479848b8605Smrg/** 480848b8605Smrg * Return true if the given context and surfaces can be made current. 481848b8605Smrg */ 482848b8605Smrgstatic EGLBoolean 483848b8605Smrg_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) 484848b8605Smrg{ 485848b8605Smrg _EGLThreadInfo *t = _eglGetCurrentThread(); 486848b8605Smrg _EGLDisplay *dpy; 487848b8605Smrg EGLint conflict_api; 488848b8605Smrg 489848b8605Smrg if (_eglIsCurrentThreadDummy()) 490848b8605Smrg return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); 491848b8605Smrg 492848b8605Smrg /* this is easy */ 493848b8605Smrg if (!ctx) { 494848b8605Smrg if (draw || read) 495848b8605Smrg return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 496848b8605Smrg return EGL_TRUE; 497848b8605Smrg } 498848b8605Smrg 499848b8605Smrg dpy = ctx->Resource.Display; 500848b8605Smrg if (!dpy->Extensions.KHR_surfaceless_context 501848b8605Smrg && (draw == NULL || read == NULL)) 502848b8605Smrg return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 503848b8605Smrg 504848b8605Smrg /* 505848b8605Smrg * The spec says 506848b8605Smrg * 507848b8605Smrg * "If ctx is current to some other thread, or if either draw or read are 508848b8605Smrg * bound to contexts in another thread, an EGL_BAD_ACCESS error is 509848b8605Smrg * generated." 510848b8605Smrg * 511848b8605Smrg * and 512848b8605Smrg * 513848b8605Smrg * "at most one context may be bound to a particular surface at a given 514848b8605Smrg * time" 515848b8605Smrg */ 516848b8605Smrg if (ctx->Binding && ctx->Binding != t) 517848b8605Smrg return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 518848b8605Smrg if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { 519848b8605Smrg if (draw->CurrentContext->Binding != t || 520848b8605Smrg draw->CurrentContext->ClientAPI != ctx->ClientAPI) 521848b8605Smrg return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 522848b8605Smrg } 523848b8605Smrg if (read && read->CurrentContext && read->CurrentContext != ctx) { 524848b8605Smrg if (read->CurrentContext->Binding != t || 525848b8605Smrg read->CurrentContext->ClientAPI != ctx->ClientAPI) 526848b8605Smrg return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 527848b8605Smrg } 528848b8605Smrg 529848b8605Smrg /* If the context has a config then it must match that of the two 530848b8605Smrg * surfaces */ 531848b8605Smrg if (ctx->Config) { 532848b8605Smrg if ((draw && draw->Config != ctx->Config) || 533848b8605Smrg (read && read->Config != ctx->Config)) 534848b8605Smrg return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 535848b8605Smrg } else { 536848b8605Smrg /* Otherwise we must be using the EGL_MESA_configless_context 537848b8605Smrg * extension */ 538848b8605Smrg assert(dpy->Extensions.MESA_configless_context); 539848b8605Smrg 540848b8605Smrg /* The extension doesn't permit binding draw and read buffers with 541848b8605Smrg * differing contexts */ 542848b8605Smrg if (draw && read && draw->Config != read->Config) 543848b8605Smrg return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 544848b8605Smrg } 545848b8605Smrg 546848b8605Smrg switch (ctx->ClientAPI) { 547848b8605Smrg /* OpenGL and OpenGL ES are conflicting */ 548848b8605Smrg case EGL_OPENGL_ES_API: 549848b8605Smrg conflict_api = EGL_OPENGL_API; 550848b8605Smrg break; 551848b8605Smrg case EGL_OPENGL_API: 552848b8605Smrg conflict_api = EGL_OPENGL_ES_API; 553848b8605Smrg break; 554848b8605Smrg default: 555848b8605Smrg conflict_api = -1; 556848b8605Smrg break; 557848b8605Smrg } 558848b8605Smrg 559848b8605Smrg if (conflict_api >= 0 && _eglGetAPIContext(conflict_api)) 560848b8605Smrg return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 561848b8605Smrg 562848b8605Smrg return EGL_TRUE; 563848b8605Smrg} 564848b8605Smrg 565848b8605Smrg 566848b8605Smrg/** 567848b8605Smrg * Bind the context to the current thread and given surfaces. Return the 568848b8605Smrg * previous bound context and surfaces. The caller should unreference the 569848b8605Smrg * returned context and surfaces. 570848b8605Smrg * 571848b8605Smrg * Making a second call with the resources returned by the first call 572848b8605Smrg * unsurprisingly undoes the first call, except for the resouce reference 573848b8605Smrg * counts. 574848b8605Smrg */ 575848b8605SmrgEGLBoolean 576848b8605Smrg_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read, 577848b8605Smrg _EGLContext **old_ctx, 578848b8605Smrg _EGLSurface **old_draw, _EGLSurface **old_read) 579848b8605Smrg{ 580848b8605Smrg _EGLThreadInfo *t = _eglGetCurrentThread(); 581848b8605Smrg _EGLContext *prev_ctx; 582848b8605Smrg _EGLSurface *prev_draw, *prev_read; 583848b8605Smrg 584848b8605Smrg if (!_eglCheckMakeCurrent(ctx, draw, read)) 585848b8605Smrg return EGL_FALSE; 586848b8605Smrg 587848b8605Smrg /* increment refcounts before binding */ 588848b8605Smrg _eglGetContext(ctx); 589848b8605Smrg _eglGetSurface(draw); 590848b8605Smrg _eglGetSurface(read); 591848b8605Smrg 592848b8605Smrg /* bind the new context */ 593848b8605Smrg prev_ctx = _eglBindContextToThread(ctx, t); 594848b8605Smrg 595848b8605Smrg /* break previous bindings */ 596848b8605Smrg if (prev_ctx) { 597848b8605Smrg prev_draw = prev_ctx->DrawSurface; 598848b8605Smrg prev_read = prev_ctx->ReadSurface; 599848b8605Smrg 600848b8605Smrg if (prev_draw) 601848b8605Smrg prev_draw->CurrentContext = NULL; 602848b8605Smrg if (prev_read) 603848b8605Smrg prev_read->CurrentContext = NULL; 604848b8605Smrg 605848b8605Smrg prev_ctx->DrawSurface = NULL; 606848b8605Smrg prev_ctx->ReadSurface = NULL; 607848b8605Smrg } 608848b8605Smrg else { 609848b8605Smrg prev_draw = prev_read = NULL; 610848b8605Smrg } 611848b8605Smrg 612848b8605Smrg /* establish new bindings */ 613848b8605Smrg if (ctx) { 614848b8605Smrg if (draw) 615848b8605Smrg draw->CurrentContext = ctx; 616848b8605Smrg if (read) 617848b8605Smrg read->CurrentContext = ctx; 618848b8605Smrg 619848b8605Smrg ctx->DrawSurface = draw; 620848b8605Smrg ctx->ReadSurface = read; 621848b8605Smrg } 622848b8605Smrg 623848b8605Smrg assert(old_ctx && old_draw && old_read); 624848b8605Smrg *old_ctx = prev_ctx; 625848b8605Smrg *old_draw = prev_draw; 626848b8605Smrg *old_read = prev_read; 627848b8605Smrg 628848b8605Smrg return EGL_TRUE; 629848b8605Smrg} 630