2011-07-02 09:57:30 +01:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
|
|
|
* Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
|
|
|
|
* Copyright 2010-2011 LunarG, Inc.
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
* distribute, sub license, and/or sell copies of the Software, and to
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
* the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the
|
|
|
|
* next paragraph) shall be included in all copies or substantial portions
|
|
|
|
* of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
2005-04-22 22:09:39 +01:00
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "eglconfig.h"
|
|
|
|
#include "eglcontext.h"
|
2005-11-27 23:57:19 +00:00
|
|
|
#include "egldisplay.h"
|
2010-01-29 01:00:30 +00:00
|
|
|
#include "eglcurrent.h"
|
2005-04-22 22:09:39 +01:00
|
|
|
#include "eglsurface.h"
|
2010-01-31 04:57:53 +00:00
|
|
|
#include "egllog.h"
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the API bit (one of EGL_xxx_BIT) of the context.
|
|
|
|
*/
|
|
|
|
static EGLint
|
|
|
|
_eglGetContextAPIBit(_EGLContext *ctx)
|
|
|
|
{
|
|
|
|
EGLint bit = 0;
|
|
|
|
|
|
|
|
switch (ctx->ClientAPI) {
|
|
|
|
case EGL_OPENGL_ES_API:
|
2012-07-18 23:59:15 +01:00
|
|
|
switch (ctx->ClientMajorVersion) {
|
2010-01-31 04:57:53 +00:00
|
|
|
case 1:
|
|
|
|
bit = EGL_OPENGL_ES_BIT;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
bit = EGL_OPENGL_ES2_BIT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EGL_OPENVG_API:
|
|
|
|
bit = EGL_OPENVG_BIT;
|
|
|
|
break;
|
|
|
|
case EGL_OPENGL_API:
|
|
|
|
bit = EGL_OPENGL_BIT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse the list of context attributes and return the proper error code.
|
|
|
|
*/
|
|
|
|
static EGLint
|
2012-07-19 19:10:15 +01:00
|
|
|
_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
|
|
|
|
const EGLint *attrib_list)
|
2010-01-31 04:57:53 +00:00
|
|
|
{
|
|
|
|
EGLenum api = ctx->ClientAPI;
|
|
|
|
EGLint i, err = EGL_SUCCESS;
|
|
|
|
|
|
|
|
if (!attrib_list)
|
|
|
|
return EGL_SUCCESS;
|
|
|
|
|
2012-07-19 19:10:15 +01:00
|
|
|
if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
|
|
|
|
_eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
|
|
|
|
return EGL_BAD_ATTRIBUTE;
|
|
|
|
}
|
|
|
|
|
2010-01-31 04:57:53 +00:00
|
|
|
for (i = 0; attrib_list[i] != EGL_NONE; i++) {
|
|
|
|
EGLint attr = attrib_list[i++];
|
|
|
|
EGLint val = attrib_list[i];
|
|
|
|
|
|
|
|
switch (attr) {
|
|
|
|
case EGL_CONTEXT_CLIENT_VERSION:
|
2012-07-19 19:10:15 +01:00
|
|
|
ctx->ClientMajorVersion = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EGL_CONTEXT_MINOR_VERSION_KHR:
|
|
|
|
if (!dpy->Extensions.KHR_create_context) {
|
2010-01-31 04:57:53 +00:00
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
}
|
2012-07-19 19:10:15 +01:00
|
|
|
|
|
|
|
ctx->ClientMinorVersion = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EGL_CONTEXT_FLAGS_KHR:
|
|
|
|
if (!dpy->Extensions.KHR_create_context) {
|
2010-01-31 04:57:53 +00:00
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
}
|
2012-07-19 19:10:15 +01:00
|
|
|
|
|
|
|
/* The EGL_KHR_create_context spec says:
|
|
|
|
*
|
|
|
|
* "Flags are only defined for OpenGL context creation, and
|
|
|
|
* specifying a flags value other than zero for other types of
|
|
|
|
* contexts, including OpenGL ES contexts, will generate an
|
|
|
|
* error."
|
|
|
|
*/
|
|
|
|
if (api != EGL_OPENGL_API && val != 0) {
|
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->Flags = val;
|
2010-01-31 04:57:53 +00:00
|
|
|
break;
|
2012-07-19 19:10:15 +01:00
|
|
|
|
|
|
|
case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
|
|
|
|
if (!dpy->Extensions.KHR_create_context) {
|
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The EGL_KHR_create_context spec says:
|
|
|
|
*
|
|
|
|
* "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
|
|
|
|
* OpenGL contexts, and specifying it for other types of
|
|
|
|
* contexts, including OpenGL ES contexts, will generate an
|
|
|
|
* error."
|
|
|
|
*/
|
|
|
|
if (api != EGL_OPENGL_API) {
|
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->Profile = val;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
|
|
|
|
/* The EGL_KHR_create_context spec says:
|
|
|
|
*
|
|
|
|
* "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
|
|
|
|
* meaningful for OpenGL contexts, and specifying it for other
|
|
|
|
* types of contexts, including OpenGL ES contexts, will generate
|
|
|
|
* an error."
|
|
|
|
*/
|
|
|
|
if (!dpy->Extensions.KHR_create_context
|
|
|
|
|| api != EGL_OPENGL_API) {
|
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->ResetNotificationStrategy = val;
|
|
|
|
break;
|
|
|
|
|
2010-01-31 04:57:53 +00:00
|
|
|
default:
|
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err != EGL_SUCCESS) {
|
|
|
|
_eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-19 19:10:15 +01:00
|
|
|
if (api == EGL_OPENGL_API) {
|
|
|
|
/* The EGL_KHR_create_context spec says:
|
|
|
|
*
|
|
|
|
* "If the requested OpenGL version is less than 3.2,
|
|
|
|
* EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
|
|
|
|
* functionality of the context is determined solely by the
|
|
|
|
* requested version."
|
|
|
|
*
|
|
|
|
* Since the value is ignored, only validate the setting if the version
|
|
|
|
* is >= 3.2.
|
|
|
|
*/
|
|
|
|
if (ctx->ClientMajorVersion >= 4
|
|
|
|
|| (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
|
|
|
|
switch (ctx->Profile) {
|
|
|
|
case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
|
|
|
|
case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* The EGL_KHR_create_context spec says:
|
|
|
|
*
|
|
|
|
* "* If an OpenGL context is requested, the requested version
|
|
|
|
* is greater than 3.2, and the value for attribute
|
|
|
|
* EGL_CONTEXT_PROFILE_MASK_KHR has no bits set; has any
|
|
|
|
* bits set other than EGL_CONTEXT_CORE_PROFILE_BIT_KHR and
|
|
|
|
* EGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_KHR; has more than
|
|
|
|
* one of these bits set; or if the implementation does not
|
|
|
|
* support the requested profile, then an
|
|
|
|
* EGL_BAD_PROFILE_KHR error is generated."
|
|
|
|
*
|
|
|
|
* However, it does not define EGL_BAD_PROFILE_KHR. For now use
|
|
|
|
* EGL_BAD_ATTRIBUTE.
|
|
|
|
*/
|
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The EGL_KHR_create_context spec says:
|
|
|
|
*
|
|
|
|
* "* If an OpenGL context is requested and the values for
|
|
|
|
* attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
|
|
|
|
* EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
|
|
|
|
* the value for attribute
|
|
|
|
* EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
|
|
|
|
* version and feature set that are not defined, than an
|
|
|
|
* EGL_BAD_MATCH error is generated.
|
|
|
|
*
|
|
|
|
* ... Thus, examples of invalid combinations of attributes
|
|
|
|
* include:
|
|
|
|
*
|
|
|
|
* - Major version < 1 or > 4
|
|
|
|
* - Major version == 1 and minor version < 0 or > 5
|
|
|
|
* - Major version == 2 and minor version < 0 or > 1
|
|
|
|
* - Major version == 3 and minor version < 0 or > 2
|
|
|
|
* - Major version == 4 and minor version < 0 or > 2
|
|
|
|
* - Forward-compatible flag set and major version < 3"
|
|
|
|
*/
|
|
|
|
if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
|
|
|
|
err = EGL_BAD_MATCH;
|
|
|
|
|
|
|
|
switch (ctx->ClientMajorVersion) {
|
|
|
|
case 1:
|
|
|
|
if (ctx->ClientMinorVersion > 5
|
|
|
|
|| (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
|
|
|
|
err = EGL_BAD_MATCH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
if (ctx->ClientMinorVersion > 1
|
|
|
|
|| (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
|
|
|
|
err = EGL_BAD_MATCH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
/* Note: The text above is incorrect. There *is* an OpenGL 3.3!
|
|
|
|
*/
|
|
|
|
if (ctx->ClientMinorVersion > 3)
|
|
|
|
err = EGL_BAD_MATCH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
default:
|
|
|
|
/* Don't put additional version checks here. We don't know that
|
|
|
|
* there won't be versions > 4.2.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (api == EGL_OPENGL_ES_API) {
|
|
|
|
/* The EGL_KHR_create_context spec says:
|
|
|
|
*
|
|
|
|
* "* If an OpenGL ES context is requested and the values for
|
|
|
|
* attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
|
|
|
|
* EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
|
|
|
|
* is not defined, than an EGL_BAD_MATCH error is generated.
|
|
|
|
*
|
|
|
|
* ... Examples of invalid combinations of attributes include:
|
|
|
|
*
|
|
|
|
* - Major version < 1 or > 2
|
|
|
|
* - Major version == 1 and minor version < 0 or > 1
|
|
|
|
* - Major version == 2 and minor version != 0
|
|
|
|
*/
|
|
|
|
if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
|
|
|
|
err = EGL_BAD_MATCH;
|
|
|
|
|
|
|
|
switch (ctx->ClientMajorVersion) {
|
|
|
|
case 1:
|
|
|
|
if (ctx->ClientMinorVersion > 1)
|
|
|
|
err = EGL_BAD_MATCH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
default:
|
|
|
|
/* Don't put additional version checks here. We don't know that
|
|
|
|
* there won't be versions > 2.0.
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (ctx->ResetNotificationStrategy) {
|
|
|
|
case EGL_NO_RESET_NOTIFICATION_KHR:
|
|
|
|
case EGL_LOSE_CONTEXT_ON_RESET_KHR:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ctx->Flags & (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
|
|
|
|
| EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
|
|
|
|
| EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
|
|
|
|
err = EGL_BAD_ATTRIBUTE;
|
|
|
|
}
|
|
|
|
|
2010-01-31 04:57:53 +00:00
|
|
|
return err;
|
|
|
|
}
|
2005-04-22 22:09:39 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
2008-05-27 21:21:25 +01:00
|
|
|
* Initialize the given _EGLContext object to defaults and/or the values
|
|
|
|
* in the attrib_list.
|
2005-04-22 22:09:39 +01:00
|
|
|
*/
|
2005-11-27 23:57:19 +00:00
|
|
|
EGLBoolean
|
2010-01-31 05:33:57 +00:00
|
|
|
_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
|
|
|
|
const EGLint *attrib_list)
|
2005-04-22 22:09:39 +01:00
|
|
|
{
|
2008-05-30 20:45:40 +01:00
|
|
|
const EGLenum api = eglQueryAPI();
|
2010-01-31 04:57:53 +00:00
|
|
|
EGLint err;
|
2008-05-30 20:45:40 +01:00
|
|
|
|
|
|
|
if (api == EGL_NONE) {
|
|
|
|
_eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
2005-11-27 23:57:19 +00:00
|
|
|
|
2010-10-23 04:59:03 +01:00
|
|
|
_eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
|
2010-01-31 04:57:53 +00:00
|
|
|
ctx->ClientAPI = api;
|
|
|
|
ctx->Config = conf;
|
|
|
|
ctx->WindowRenderBuffer = EGL_NONE;
|
2012-07-19 19:10:15 +01:00
|
|
|
ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
2008-06-20 04:19:33 +01:00
|
|
|
|
2012-07-18 23:59:15 +01:00
|
|
|
ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
|
|
|
|
ctx->ClientMinorVersion = 0;
|
2012-07-19 19:10:15 +01:00
|
|
|
ctx->Flags = 0;
|
|
|
|
ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
|
|
|
ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
|
2008-06-19 23:06:56 +01:00
|
|
|
|
2012-07-19 19:10:15 +01:00
|
|
|
err = _eglParseContextAttribList(ctx, dpy, attrib_list);
|
2010-08-20 06:19:10 +01:00
|
|
|
if (err == EGL_SUCCESS && ctx->Config) {
|
2010-10-14 09:38:58 +01:00
|
|
|
EGLint api_bit;
|
2010-08-20 06:19:10 +01:00
|
|
|
|
|
|
|
api_bit = _eglGetContextAPIBit(ctx);
|
2010-10-14 09:38:58 +01:00
|
|
|
if (!(ctx->Config->RenderableType & api_bit)) {
|
2010-08-20 06:19:10 +01:00
|
|
|
_eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
|
2010-10-14 09:38:58 +01:00
|
|
|
api_bit, ctx->Config->RenderableType);
|
2010-08-20 06:19:10 +01:00
|
|
|
err = EGL_BAD_CONFIG;
|
|
|
|
}
|
|
|
|
}
|
2010-01-31 04:57:53 +00:00
|
|
|
if (err != EGL_SUCCESS)
|
|
|
|
return _eglError(err, "eglCreateContext");
|
2005-11-27 23:57:19 +00:00
|
|
|
|
|
|
|
return EGL_TRUE;
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-27 10:00:51 +01:00
|
|
|
static EGLint
|
|
|
|
_eglQueryContextRenderBuffer(_EGLContext *ctx)
|
|
|
|
{
|
|
|
|
_EGLSurface *surf = ctx->DrawSurface;
|
|
|
|
EGLint rb;
|
|
|
|
|
|
|
|
if (!surf)
|
|
|
|
return EGL_NONE;
|
|
|
|
if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
|
|
|
|
rb = ctx->WindowRenderBuffer;
|
|
|
|
else
|
|
|
|
rb = surf->RenderBuffer;
|
|
|
|
return rb;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-22 22:09:39 +01:00
|
|
|
EGLBoolean
|
2009-08-11 10:09:39 +01:00
|
|
|
_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
|
2005-11-27 23:57:19 +00:00
|
|
|
EGLint attribute, EGLint *value)
|
2005-04-22 22:09:39 +01:00
|
|
|
{
|
|
|
|
(void) drv;
|
|
|
|
(void) dpy;
|
|
|
|
|
2009-09-27 10:00:51 +01:00
|
|
|
if (!value)
|
|
|
|
return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
|
|
|
|
|
2005-04-22 22:09:39 +01:00
|
|
|
switch (attribute) {
|
|
|
|
case EGL_CONFIG_ID:
|
2010-10-14 09:38:58 +01:00
|
|
|
if (!c->Config)
|
|
|
|
return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
|
|
|
|
*value = c->Config->ConfigID;
|
2009-09-27 10:00:51 +01:00
|
|
|
break;
|
|
|
|
case EGL_CONTEXT_CLIENT_VERSION:
|
2012-07-18 23:59:15 +01:00
|
|
|
*value = c->ClientMajorVersion;
|
2009-09-27 10:00:51 +01:00
|
|
|
break;
|
2006-01-30 00:10:55 +00:00
|
|
|
case EGL_CONTEXT_CLIENT_TYPE:
|
|
|
|
*value = c->ClientAPI;
|
2009-09-27 10:00:51 +01:00
|
|
|
break;
|
|
|
|
case EGL_RENDER_BUFFER:
|
|
|
|
*value = _eglQueryContextRenderBuffer(c);
|
|
|
|
break;
|
2005-04-22 22:09:39 +01:00
|
|
|
default:
|
2009-09-27 10:00:51 +01:00
|
|
|
return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
2009-09-27 10:00:51 +01:00
|
|
|
|
|
|
|
return EGL_TRUE;
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-26 08:53:40 +00:00
|
|
|
/**
|
|
|
|
* Bind the context to the thread and return the previous context.
|
|
|
|
*
|
|
|
|
* Note that the context may be NULL.
|
|
|
|
*/
|
|
|
|
static _EGLContext *
|
|
|
|
_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
|
2005-04-22 22:09:39 +01:00
|
|
|
{
|
2009-07-17 18:42:04 +01:00
|
|
|
EGLint apiIndex;
|
2010-01-26 08:53:40 +00:00
|
|
|
_EGLContext *oldCtx;
|
|
|
|
|
|
|
|
apiIndex = (ctx) ?
|
|
|
|
_eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex;
|
|
|
|
|
|
|
|
oldCtx = t->CurrentContexts[apiIndex];
|
2010-03-27 18:11:16 +00:00
|
|
|
if (ctx != oldCtx) {
|
|
|
|
if (oldCtx)
|
|
|
|
oldCtx->Binding = NULL;
|
|
|
|
if (ctx)
|
|
|
|
ctx->Binding = t;
|
2010-01-26 08:53:40 +00:00
|
|
|
|
2010-03-27 18:11:16 +00:00
|
|
|
t->CurrentContexts[apiIndex] = ctx;
|
|
|
|
}
|
2010-01-26 08:53:40 +00:00
|
|
|
|
|
|
|
return oldCtx;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if the given context and surfaces can be made current.
|
|
|
|
*/
|
|
|
|
static EGLBoolean
|
|
|
|
_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
|
|
|
|
{
|
|
|
|
_EGLThreadInfo *t = _eglGetCurrentThread();
|
2010-07-29 04:54:16 +01:00
|
|
|
_EGLDisplay *dpy;
|
2010-01-26 08:53:40 +00:00
|
|
|
EGLint conflict_api;
|
2005-04-22 22:09:39 +01:00
|
|
|
|
2009-07-17 18:41:02 +01:00
|
|
|
if (_eglIsCurrentThreadDummy())
|
|
|
|
return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
|
|
|
|
|
2010-01-26 08:53:40 +00:00
|
|
|
/* this is easy */
|
|
|
|
if (!ctx) {
|
|
|
|
if (draw || read)
|
2009-08-03 18:35:14 +01:00
|
|
|
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
2010-01-26 08:53:40 +00:00
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-07-29 04:54:16 +01:00
|
|
|
dpy = ctx->Resource.Display;
|
2012-07-18 17:38:34 +01:00
|
|
|
if (!dpy->Extensions.KHR_surfaceless_context
|
|
|
|
&& (draw == NULL || read == NULL))
|
2010-01-26 08:53:40 +00:00
|
|
|
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The spec says
|
|
|
|
*
|
|
|
|
* "If ctx is current to some other thread, or if either draw or read are
|
|
|
|
* bound to contexts in another thread, an EGL_BAD_ACCESS error is
|
|
|
|
* generated."
|
|
|
|
*
|
2010-10-23 09:51:01 +01:00
|
|
|
* and
|
2010-01-26 08:53:40 +00:00
|
|
|
*
|
|
|
|
* "at most one context may be bound to a particular surface at a given
|
|
|
|
* time"
|
|
|
|
*/
|
2010-10-23 09:51:01 +01:00
|
|
|
if (ctx->Binding && ctx->Binding != t)
|
2010-01-26 08:53:40 +00:00
|
|
|
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
|
2010-10-23 09:51:01 +01:00
|
|
|
if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
|
|
|
|
if (draw->CurrentContext->Binding != t ||
|
|
|
|
draw->CurrentContext->ClientAPI != ctx->ClientAPI)
|
|
|
|
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
|
|
|
|
}
|
|
|
|
if (read && read->CurrentContext && read->CurrentContext != ctx) {
|
|
|
|
if (read->CurrentContext->Binding != t ||
|
|
|
|
read->CurrentContext->ClientAPI != ctx->ClientAPI)
|
|
|
|
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
|
|
|
|
}
|
2010-01-26 08:53:40 +00:00
|
|
|
|
|
|
|
/* simply require the configs to be equal */
|
2010-06-03 03:48:06 +01:00
|
|
|
if ((draw && draw->Config != ctx->Config) ||
|
|
|
|
(read && read->Config != ctx->Config))
|
2010-01-26 08:53:40 +00:00
|
|
|
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
2009-07-17 18:42:04 +01:00
|
|
|
|
2010-01-26 08:53:40 +00:00
|
|
|
switch (ctx->ClientAPI) {
|
|
|
|
/* OpenGL and OpenGL ES are conflicting */
|
|
|
|
case EGL_OPENGL_ES_API:
|
|
|
|
conflict_api = EGL_OPENGL_API;
|
|
|
|
break;
|
|
|
|
case EGL_OPENGL_API:
|
|
|
|
conflict_api = EGL_OPENGL_ES_API;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
conflict_api = -1;
|
|
|
|
break;
|
2009-07-17 18:42:04 +01:00
|
|
|
}
|
|
|
|
|
2010-01-26 08:53:40 +00:00
|
|
|
if (conflict_api >= 0 && _eglGetAPIContext(conflict_api))
|
|
|
|
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-27 15:31:20 +00:00
|
|
|
/**
|
|
|
|
* Bind the context to the current thread and given surfaces. Return the
|
2010-10-23 05:52:26 +01:00
|
|
|
* previous bound context and surfaces. The caller should unreference the
|
|
|
|
* returned context and surfaces.
|
|
|
|
*
|
|
|
|
* Making a second call with the resources returned by the first call
|
|
|
|
* unsurprisingly undoes the first call, except for the resouce reference
|
|
|
|
* counts.
|
2010-01-27 15:31:20 +00:00
|
|
|
*/
|
|
|
|
EGLBoolean
|
2010-10-23 05:52:26 +01:00
|
|
|
_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
|
|
|
|
_EGLContext **old_ctx,
|
|
|
|
_EGLSurface **old_draw, _EGLSurface **old_read)
|
2010-01-27 15:31:20 +00:00
|
|
|
{
|
|
|
|
_EGLThreadInfo *t = _eglGetCurrentThread();
|
2010-10-23 05:52:26 +01:00
|
|
|
_EGLContext *prev_ctx;
|
|
|
|
_EGLSurface *prev_draw, *prev_read;
|
2010-01-27 15:31:20 +00:00
|
|
|
|
2010-10-23 05:52:26 +01:00
|
|
|
if (!_eglCheckMakeCurrent(ctx, draw, read))
|
2010-01-27 15:31:20 +00:00
|
|
|
return EGL_FALSE;
|
|
|
|
|
2010-10-23 05:52:26 +01:00
|
|
|
/* increment refcounts before binding */
|
|
|
|
_eglGetContext(ctx);
|
|
|
|
_eglGetSurface(draw);
|
|
|
|
_eglGetSurface(read);
|
|
|
|
|
2010-01-27 15:31:20 +00:00
|
|
|
/* bind the new context */
|
2010-10-23 05:52:26 +01:00
|
|
|
prev_ctx = _eglBindContextToThread(ctx, t);
|
2010-04-05 14:26:34 +01:00
|
|
|
|
2010-10-23 05:52:26 +01:00
|
|
|
/* break previous bindings */
|
|
|
|
if (prev_ctx) {
|
|
|
|
prev_draw = prev_ctx->DrawSurface;
|
|
|
|
prev_read = prev_ctx->ReadSurface;
|
2010-04-06 04:51:25 +01:00
|
|
|
|
2010-10-23 05:52:26 +01:00
|
|
|
if (prev_draw)
|
|
|
|
prev_draw->CurrentContext = NULL;
|
|
|
|
if (prev_read)
|
|
|
|
prev_read->CurrentContext = NULL;
|
2010-09-10 11:26:03 +01:00
|
|
|
|
2010-10-23 05:52:26 +01:00
|
|
|
prev_ctx->DrawSurface = NULL;
|
|
|
|
prev_ctx->ReadSurface = NULL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
prev_draw = prev_read = NULL;
|
2010-09-10 11:26:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* establish new bindings */
|
2010-10-23 05:52:26 +01:00
|
|
|
if (ctx) {
|
|
|
|
if (draw)
|
|
|
|
draw->CurrentContext = ctx;
|
|
|
|
if (read)
|
|
|
|
read->CurrentContext = ctx;
|
|
|
|
|
|
|
|
ctx->DrawSurface = draw;
|
|
|
|
ctx->ReadSurface = read;
|
2010-01-27 15:31:20 +00:00
|
|
|
}
|
|
|
|
|
2010-10-23 05:52:26 +01:00
|
|
|
assert(old_ctx && old_draw && old_read);
|
|
|
|
*old_ctx = prev_ctx;
|
|
|
|
*old_draw = prev_draw;
|
|
|
|
*old_read = prev_read;
|
2010-04-05 14:26:34 +01:00
|
|
|
|
2010-01-27 15:31:20 +00:00
|
|
|
return EGL_TRUE;
|
|
|
|
}
|