/**************************************************************************1*2* Copyright 2008 VMware, Inc.3* Copyright 2009-2010 Chia-I Wu <[email protected]>4* Copyright 2010-2011 LunarG, Inc.5* All Rights Reserved.6*7* Permission is hereby granted, free of charge, to any person obtaining a8* copy of this software and associated documentation files (the9* "Software"), to deal in the Software without restriction, including10* without limitation the rights to use, copy, modify, merge, publish,11* distribute, sub license, and/or sell copies of the Software, and to12* permit persons to whom the Software is furnished to do so, subject to13* the following conditions:14*15* The above copyright notice and this permission notice (including the16* next paragraph) shall be included in all copies or substantial portions17* of the Software.18*19* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR20* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,21* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL22* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER23* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING24* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER25* DEALINGS IN THE SOFTWARE.26*27**************************************************************************/282930#include <assert.h>31#include <stdlib.h>32#include <string.h>33#include "eglconfig.h"34#include "eglcontext.h"35#include "egldisplay.h"36#include "eglcurrent.h"37#include "eglsurface.h"38#include "egllog.h"39#include "util/macros.h"404142/**43* Return the API bit (one of EGL_xxx_BIT) of the context.44*/45static EGLint46_eglGetContextAPIBit(_EGLContext *ctx)47{48EGLint bit = 0;4950switch (ctx->ClientAPI) {51case EGL_OPENGL_ES_API:52switch (ctx->ClientMajorVersion) {53case 1:54bit = EGL_OPENGL_ES_BIT;55break;56case 2:57bit = EGL_OPENGL_ES2_BIT;58break;59case 3:60bit = EGL_OPENGL_ES3_BIT_KHR;61break;62default:63break;64}65break;66case EGL_OPENVG_API:67bit = EGL_OPENVG_BIT;68break;69case EGL_OPENGL_API:70bit = EGL_OPENGL_BIT;71break;72default:73break;74}7576return bit;77}787980/**81* Parse the list of context attributes and return the proper error code.82*/83static EGLint84_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *disp,85const EGLint *attrib_list)86{87EGLenum api = ctx->ClientAPI;88EGLint i, err = EGL_SUCCESS;8990if (!attrib_list)91return EGL_SUCCESS;9293if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {94_eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);95return EGL_BAD_ATTRIBUTE;96}9798for (i = 0; attrib_list[i] != EGL_NONE; i++) {99EGLint attr = attrib_list[i++];100EGLint val = attrib_list[i];101102switch (attr) {103case EGL_CONTEXT_CLIENT_VERSION:104/* The EGL 1.4 spec says:105*106* "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the107* current rendering API is EGL_OPENGL_ES_API"108*109* The EGL_KHR_create_context spec says:110*111* "EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098112* (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"113*114* "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and115* EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API116* version. They are only meaningful for OpenGL and OpenGL ES117* contexts, and specifying them for other types of contexts will118* generate an error."119*/120if ((api != EGL_OPENGL_ES_API &&121(!disp->Extensions.KHR_create_context || api != EGL_OPENGL_API))) {122err = EGL_BAD_ATTRIBUTE;123break;124}125126ctx->ClientMajorVersion = val;127break;128129case EGL_CONTEXT_MINOR_VERSION_KHR:130/* The EGL_KHR_create_context spec says:131*132* "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and133* EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API134* version. They are only meaningful for OpenGL and OpenGL ES135* contexts, and specifying them for other types of contexts will136* generate an error."137*/138if (!disp->Extensions.KHR_create_context ||139(api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {140err = EGL_BAD_ATTRIBUTE;141break;142}143144ctx->ClientMinorVersion = val;145break;146147case EGL_CONTEXT_FLAGS_KHR:148if (!disp->Extensions.KHR_create_context) {149err = EGL_BAD_ATTRIBUTE;150break;151}152153/* The EGL_KHR_create_context spec says:154*155* "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in156* EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.157* [...]158* In some cases a debug context may be identical to a non-debug159* context. This bit is supported for OpenGL and OpenGL ES160* contexts."161*/162if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&163(api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {164err = EGL_BAD_ATTRIBUTE;165break;166}167168/* The EGL_KHR_create_context spec says:169*170* "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit171* is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>172* context will be created. Forward-compatible contexts are173* defined only for OpenGL versions 3.0 and later. They must not174* support functionality marked as <deprecated> by that version of175* the API, while a non-forward-compatible context must support176* all functionality in that version, deprecated or not. This bit177* is supported for OpenGL contexts, and requesting a178* forward-compatible context for OpenGL versions less than 3.0179* will generate an error."180*181* Note: since the forward-compatible flag can be set more than one way,182* the OpenGL version check is performed once, below.183*/184if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&185api != EGL_OPENGL_API) {186err = EGL_BAD_ATTRIBUTE;187break;188}189190if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&191api != EGL_OPENGL_API) {192/* The EGL_KHR_create_context spec says:193*194* 10) Which error should be generated if robust buffer access195* or reset notifications are requested under OpenGL ES?196*197* As per Issue 6, this extension does not support creating198* robust contexts for OpenGL ES. This is only supported via199* the EGL_EXT_create_context_robustness extension.200*201* Attempting to use this extension to create robust OpenGL202* ES context will generate an EGL_BAD_ATTRIBUTE error. This203* specific error is generated because this extension does204* not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR205* and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR206* bits for OpenGL ES contexts. Thus, use of these bits fall207* under condition described by: "If an attribute is208* specified that is not meaningful for the client API209* type.." in the above specification.210*211* The spec requires that we emit the error even if the display212* supports EGL_EXT_create_context_robustness. To create a robust213* GLES context, the *attribute*214* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the215* *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.216*/217err = EGL_BAD_ATTRIBUTE;218break;219}220221ctx->Flags |= val;222break;223224case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:225if (!disp->Extensions.KHR_create_context) {226err = EGL_BAD_ATTRIBUTE;227break;228}229230/* The EGL_KHR_create_context spec says:231*232* "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for233* OpenGL contexts, and specifying it for other types of234* contexts, including OpenGL ES contexts, will generate an235* error."236*/237if (api != EGL_OPENGL_API) {238err = EGL_BAD_ATTRIBUTE;239break;240}241242ctx->Profile = val;243break;244245case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:246/* The EGL_KHR_create_context spec says:247*248* "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only249* meaningful for OpenGL contexts, and specifying it for other250* types of contexts, including OpenGL ES contexts, will generate251* an error."252*253* EGL 1.5 defines EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY254* (without a suffix) which has the same value as the KHR token,255* and specifies that it now works with both GL and ES contexts:256*257* "This attribute is supported only for OpenGL and OpenGL ES258* contexts."259*/260if (!(disp->Extensions.KHR_create_context && api == EGL_OPENGL_API)261&& !(disp->Version >= 15 && (api == EGL_OPENGL_API ||262api == EGL_OPENGL_ES_API))) {263err = EGL_BAD_ATTRIBUTE;264break;265}266267ctx->ResetNotificationStrategy = val;268break;269270case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:271/* The EGL_EXT_create_context_robustness spec says:272*273* "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only274* meaningful for OpenGL ES contexts, and specifying it for other275* types of contexts will generate an EGL_BAD_ATTRIBUTE error."276*/277if (!disp->Extensions.EXT_create_context_robustness278|| api != EGL_OPENGL_ES_API) {279err = EGL_BAD_ATTRIBUTE;280break;281}282283ctx->ResetNotificationStrategy = val;284break;285286case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:287if (!disp->Extensions.EXT_create_context_robustness) {288err = EGL_BAD_ATTRIBUTE;289break;290}291292if (val == EGL_TRUE)293ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;294break;295296case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:297if (disp->Version < 15) {298err = EGL_BAD_ATTRIBUTE;299break;300}301302if (val == EGL_TRUE)303ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;304break;305306case EGL_CONTEXT_OPENGL_DEBUG:307if (disp->Version < 15) {308err = EGL_BAD_ATTRIBUTE;309break;310}311312if (val == EGL_TRUE)313ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;314break;315316case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:317if (disp->Version < 15) {318err = EGL_BAD_ATTRIBUTE;319break;320}321322if (val == EGL_TRUE)323ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;324break;325326case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:327if (disp->Version < 14 ||328!disp->Extensions.KHR_create_context_no_error) {329err = EGL_BAD_ATTRIBUTE;330break;331}332333/* The KHR_no_error spec only applies against OpenGL 2.0+ and334* OpenGL ES 2.0+335*/336if (((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||337ctx->ClientMajorVersion < 2) && val == EGL_TRUE) {338err = EGL_BAD_ATTRIBUTE;339break;340}341342/* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */343ctx->NoError = !!val;344break;345346case EGL_CONTEXT_PRIORITY_LEVEL_IMG:347/* The EGL_IMG_context_priority spec says:348*349* "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of350* the context to be created. This attribute is a hint, as an351* implementation may not support multiple contexts at some352* priority levels and system policy may limit access to high353* priority contexts to appropriate system privilege level. The354* default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is355* EGL_CONTEXT_PRIORITY_MEDIUM_IMG."356*/357{358int bit;359360switch (val) {361case EGL_CONTEXT_PRIORITY_HIGH_IMG:362bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;363break;364case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:365bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;366break;367case EGL_CONTEXT_PRIORITY_LOW_IMG:368bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;369break;370default:371bit = -1;372break;373}374375if (bit < 0) {376err = EGL_BAD_ATTRIBUTE;377break;378}379380/* "This extension allows an EGLContext to be created with a381* priority hint. It is possible that an implementation will not382* honour the hint, especially if there are constraints on the383* number of high priority contexts available in the system, or384* system policy limits access to high priority contexts to385* appropriate system privilege level. A query is provided to find386* the real priority level assigned to the context after creation."387*388* We currently assume that the driver applies the priority hint389* and filters out any it cannot handle during the screen setup,390* e.g. dri2_setup_screen(). As such we can mask any change that391* the driver would fail, and ctx->ContextPriority matches the392* hint applied to the driver/hardware backend.393*/394if (disp->Extensions.IMG_context_priority & (1 << bit))395ctx->ContextPriority = val;396397break;398}399400case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR:401if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR ||402val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) {403ctx->ReleaseBehavior = val;404} else {405err = EGL_BAD_ATTRIBUTE;406}407break;408409default:410err = EGL_BAD_ATTRIBUTE;411break;412}413414if (err != EGL_SUCCESS) {415_eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);416break;417}418}419420if (api == EGL_OPENGL_API) {421/* The EGL_KHR_create_context spec says:422*423* "If the requested OpenGL version is less than 3.2,424* EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the425* functionality of the context is determined solely by the426* requested version."427*428* Since the value is ignored, only validate the setting if the version429* is >= 3.2.430*/431if (ctx->ClientMajorVersion >= 4432|| (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {433switch (ctx->Profile) {434case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:435case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:436break;437438default:439/* The EGL_KHR_create_context spec says:440*441* "* If an OpenGL context is requested, the requested version442* is greater than 3.2, and the value for attribute443* EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has444* any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR445* and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has446* more than one of these bits set; or if the implementation does447* not support the requested profile, then an EGL_BAD_MATCH error448* is generated."449*/450err = EGL_BAD_MATCH;451break;452}453}454455/* The EGL_KHR_create_context spec says:456*457* "* If an OpenGL context is requested and the values for458* attributes EGL_CONTEXT_MAJOR_VERSION_KHR and459* EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with460* the value for attribute461* EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL462* version and feature set that are not defined, than an463* EGL_BAD_MATCH error is generated.464*465* ... Thus, examples of invalid combinations of attributes466* include:467*468* - Major version < 1 or > 4469* - Major version == 1 and minor version < 0 or > 5470* - Major version == 2 and minor version < 0 or > 1471* - Major version == 3 and minor version < 0 or > 2472* - Major version == 4 and minor version < 0 or > 2473* - Forward-compatible flag set and major version < 3"474*/475if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)476err = EGL_BAD_MATCH;477478switch (ctx->ClientMajorVersion) {479case 1:480if (ctx->ClientMinorVersion > 5481|| (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)482err = EGL_BAD_MATCH;483break;484485case 2:486if (ctx->ClientMinorVersion > 1487|| (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)488err = EGL_BAD_MATCH;489break;490491case 3:492/* Note: The text above is incorrect. There *is* an OpenGL 3.3!493*/494if (ctx->ClientMinorVersion > 3)495err = EGL_BAD_MATCH;496break;497498case 4:499default:500/* Don't put additional version checks here. We don't know that501* there won't be versions > 4.2.502*/503break;504}505} else if (api == EGL_OPENGL_ES_API) {506/* The EGL_KHR_create_context spec says:507*508* "* If an OpenGL ES context is requested and the values for509* attributes EGL_CONTEXT_MAJOR_VERSION_KHR and510* EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that511* is not defined, than an EGL_BAD_MATCH error is generated.512*513* ... Examples of invalid combinations of attributes include:514*515* - Major version < 1 or > 2516* - Major version == 1 and minor version < 0 or > 1517* - Major version == 2 and minor version != 0518*/519if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)520err = EGL_BAD_MATCH;521522switch (ctx->ClientMajorVersion) {523case 1:524if (ctx->ClientMinorVersion > 1)525err = EGL_BAD_MATCH;526break;527528case 2:529if (ctx->ClientMinorVersion > 0)530err = EGL_BAD_MATCH;531break;532533case 3:534/* Don't put additional version checks here. We don't know that535* there won't be versions > 3.0.536*/537break;538539default:540err = EGL_BAD_MATCH;541break;542}543}544545switch (ctx->ResetNotificationStrategy) {546case EGL_NO_RESET_NOTIFICATION_KHR:547case EGL_LOSE_CONTEXT_ON_RESET_KHR:548break;549550default:551err = EGL_BAD_ATTRIBUTE;552break;553}554555/* The EGL_KHR_create_context_no_error spec says:556*557* "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at558* the same time as a debug or robustness context is specified."559*/560if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||561ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {562err = EGL_BAD_MATCH;563}564565if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR566| EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR567| EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {568err = EGL_BAD_ATTRIBUTE;569}570571return err;572}573574575/**576* Initialize the given _EGLContext object to defaults and/or the values577* in the attrib_list.578*579* According to EGL 1.5 Section 3.7:580*581* "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all582* purposes except eglCreateContext."583*584* And since we only support GL and GLES, this is the only place where the585* bound API matters at all. We look up the current API from the current586* thread, and stash that in the context we're initializing. Our caller is587* responsible for determining whether that's an API it supports.588*/589EGLBoolean590_eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf,591const EGLint *attrib_list)592{593const EGLenum api = eglQueryAPI();594EGLint err;595596if (api == EGL_NONE)597return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");598599_eglInitResource(&ctx->Resource, sizeof(*ctx), disp);600ctx->ClientAPI = api;601ctx->Config = conf;602ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;603604ctx->ClientMajorVersion = 1; /* the default, per EGL spec */605ctx->ClientMinorVersion = 0;606ctx->Flags = 0;607ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;608ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;609ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR;610611err = _eglParseContextAttribList(ctx, disp, attrib_list);612if (err == EGL_SUCCESS && ctx->Config) {613EGLint api_bit;614615api_bit = _eglGetContextAPIBit(ctx);616if (!(ctx->Config->RenderableType & api_bit)) {617_eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",618api_bit, ctx->Config->RenderableType);619err = EGL_BAD_CONFIG;620}621}622if (err != EGL_SUCCESS)623return _eglError(err, "eglCreateContext");624625return EGL_TRUE;626}627628629static EGLint630_eglQueryContextRenderBuffer(_EGLContext *ctx)631{632_EGLSurface *surf = ctx->DrawSurface;633634/* From the EGL 1.5 spec:635*636* - If the context is not bound to a surface, then EGL_NONE will be637* returned.638*/639if (!surf)640return EGL_NONE;641642switch (surf->Type) {643default:644unreachable("bad EGLSurface type");645case EGL_PIXMAP_BIT:646/* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER647* will be returned.648*/649return EGL_SINGLE_BUFFER;650case EGL_PBUFFER_BIT:651/* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER652* will be returned.653*/654return EGL_BACK_BUFFER;655case EGL_WINDOW_BIT:656/* - If the context is bound to a window surface, then either657* EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value658* returned depends on both the buffer requested by the setting of the659* EGL_RENDER_BUFFER property of the surface [...], and on the client660* API (not all client APIs support single-buffer Rendering to window661* surfaces). Some client APIs allow control of whether rendering goes662* to the front or back buffer. This client API-specific choice is not663* reflected in the returned value, which only describes the buffer664* that will be rendered to by default if not overridden by the client665* API.666*/667return surf->ActiveRenderBuffer;668}669}670671672EGLBoolean673_eglQueryContext(_EGLContext *c, EGLint attribute, EGLint *value)674{675if (!value)676return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");677678switch (attribute) {679case EGL_CONFIG_ID:680/*681* From EGL_KHR_no_config_context:682*683* "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with684* respect to which the context was created, or zero if created685* without respect to an EGLConfig."686*/687*value = c->Config ? c->Config->ConfigID : 0;688break;689case EGL_CONTEXT_CLIENT_VERSION:690*value = c->ClientMajorVersion;691break;692case EGL_CONTEXT_CLIENT_TYPE:693*value = c->ClientAPI;694break;695case EGL_RENDER_BUFFER:696*value = _eglQueryContextRenderBuffer(c);697break;698case EGL_CONTEXT_PRIORITY_LEVEL_IMG:699*value = c->ContextPriority;700break;701default:702return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");703}704705return EGL_TRUE;706}707708709/**710* Bind the context to the thread and return the previous context.711*712* Note that the context may be NULL.713*/714_EGLContext *715_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)716{717_EGLContext *oldCtx;718719oldCtx = t->CurrentContext;720if (ctx != oldCtx) {721if (oldCtx)722oldCtx->Binding = NULL;723if (ctx)724ctx->Binding = t;725726t->CurrentContext = ctx;727}728729return oldCtx;730}731732733/**734* Return true if the given context and surfaces can be made current.735*/736static EGLBoolean737_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)738{739_EGLThreadInfo *t = _eglGetCurrentThread();740_EGLDisplay *disp;741742if (_eglIsCurrentThreadDummy())743return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");744745/* this is easy */746if (!ctx) {747if (draw || read)748return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");749return EGL_TRUE;750}751752disp = ctx->Resource.Display;753if (!disp->Extensions.KHR_surfaceless_context754&& (draw == NULL || read == NULL))755return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");756757/*758* The spec says759*760* "If ctx is current to some other thread, or if either draw or read are761* bound to contexts in another thread, an EGL_BAD_ACCESS error is762* generated."763*764* and765*766* "at most one context may be bound to a particular surface at a given767* time"768*/769if (ctx->Binding && ctx->Binding != t)770return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");771if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {772if (draw->CurrentContext->Binding != t)773return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");774}775if (read && read->CurrentContext && read->CurrentContext != ctx) {776if (read->CurrentContext->Binding != t)777return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");778}779780/* If the context has a config then it must match that of the two781* surfaces */782if (ctx->Config) {783if ((draw && draw->Config != ctx->Config) ||784(read && read->Config != ctx->Config))785return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");786} else {787/* Otherwise we must be using the EGL_KHR_no_config_context788* extension */789assert(disp->Extensions.KHR_no_config_context);790791/* The extension doesn't permit binding draw and read buffers with792* differing contexts */793if (draw && read && draw->Config != read->Config)794return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");795}796797return EGL_TRUE;798}799800801/**802* Bind the context to the current thread and given surfaces. Return the803* previous bound context and surfaces. The caller should unreference the804* returned context and surfaces.805*806* Making a second call with the resources returned by the first call807* unsurprisingly undoes the first call, except for the resouce reference808* counts.809*/810EGLBoolean811_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,812_EGLContext **old_ctx,813_EGLSurface **old_draw, _EGLSurface **old_read)814{815_EGLThreadInfo *t = _eglGetCurrentThread();816_EGLContext *prev_ctx;817_EGLSurface *prev_draw, *prev_read;818819if (!_eglCheckMakeCurrent(ctx, draw, read))820return EGL_FALSE;821822/* increment refcounts before binding */823_eglGetContext(ctx);824_eglGetSurface(draw);825_eglGetSurface(read);826827/* bind the new context */828prev_ctx = _eglBindContextToThread(ctx, t);829830/* break previous bindings */831if (prev_ctx) {832prev_draw = prev_ctx->DrawSurface;833prev_read = prev_ctx->ReadSurface;834835if (prev_draw)836prev_draw->CurrentContext = NULL;837if (prev_read)838prev_read->CurrentContext = NULL;839840prev_ctx->DrawSurface = NULL;841prev_ctx->ReadSurface = NULL;842}843else {844prev_draw = prev_read = NULL;845}846847/* establish new bindings */848if (ctx) {849if (draw)850draw->CurrentContext = ctx;851if (read)852read->CurrentContext = ctx;853854ctx->DrawSurface = draw;855ctx->ReadSurface = read;856}857858assert(old_ctx && old_draw && old_read);859*old_ctx = prev_ctx;860*old_draw = prev_draw;861*old_read = prev_read;862863return EGL_TRUE;864}865866867