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"
|
2005-04-22 22:09:39 +01:00
|
|
|
#include "egldriver.h"
|
|
|
|
#include "eglglobals.h"
|
|
|
|
#include "eglsurface.h"
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
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
|
2009-07-17 18:53:03 +01:00
|
|
|
_eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
|
|
|
|
_EGLConfig *conf, const EGLint *attrib_list)
|
2005-04-22 22:09:39 +01:00
|
|
|
{
|
2005-11-27 23:57:19 +00:00
|
|
|
EGLint i;
|
2008-05-30 20:45:40 +01:00
|
|
|
const EGLenum api = eglQueryAPI();
|
|
|
|
|
|
|
|
if (api == EGL_NONE) {
|
|
|
|
_eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
2005-11-27 23:57:19 +00:00
|
|
|
|
|
|
|
if (!conf) {
|
2008-05-27 21:21:25 +01:00
|
|
|
_eglError(EGL_BAD_CONFIG, "_eglInitContext");
|
2005-11-27 23:57:19 +00:00
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
|
2008-06-20 04:19:33 +01:00
|
|
|
memset(ctx, 0, sizeof(_EGLContext));
|
|
|
|
|
2008-06-19 23:06:56 +01:00
|
|
|
ctx->ClientVersion = 1; /* the default, per EGL spec */
|
|
|
|
|
2005-11-27 23:57:19 +00:00
|
|
|
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
|
|
|
|
switch (attrib_list[i]) {
|
2008-05-27 21:21:25 +01:00
|
|
|
case EGL_CONTEXT_CLIENT_VERSION:
|
2008-05-30 20:45:40 +01:00
|
|
|
i++;
|
|
|
|
ctx->ClientVersion = attrib_list[i];
|
2008-05-27 21:21:25 +01:00
|
|
|
break;
|
2005-11-27 23:57:19 +00:00
|
|
|
default:
|
2008-05-27 21:21:25 +01:00
|
|
|
_eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext");
|
2008-05-27 20:45:41 +01:00
|
|
|
return EGL_FALSE;
|
2005-11-27 23:57:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->Config = conf;
|
|
|
|
ctx->DrawSurface = EGL_NO_SURFACE;
|
|
|
|
ctx->ReadSurface = EGL_NO_SURFACE;
|
2008-05-30 20:45:40 +01:00
|
|
|
ctx->ClientAPI = api;
|
2005-11-27 23:57:19 +00:00
|
|
|
|
|
|
|
return EGL_TRUE;
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Just a placeholder/demo function. Real driver will never use this!
|
|
|
|
*/
|
|
|
|
EGLContext
|
2005-11-27 23:57:19 +00:00
|
|
|
_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
|
|
|
|
EGLContext share_list, const EGLint *attrib_list)
|
2005-04-22 22:09:39 +01:00
|
|
|
{
|
2005-11-27 23:57:19 +00:00
|
|
|
#if 0 /* example code */
|
|
|
|
_EGLContext *context;
|
2009-07-17 18:53:03 +01:00
|
|
|
_EGLConfig *conf;
|
|
|
|
|
|
|
|
conf = _eglLookupConfig(drv, dpy, config);
|
|
|
|
if (!conf) {
|
|
|
|
_eglError(EGL_BAD_CONFIG, "eglCreateContext");
|
|
|
|
return EGL_NO_CONTEXT;
|
|
|
|
}
|
2005-11-27 23:57:19 +00:00
|
|
|
|
|
|
|
context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
|
|
|
|
if (!context)
|
2005-04-22 22:09:39 +01:00
|
|
|
return EGL_NO_CONTEXT;
|
|
|
|
|
2009-07-17 18:53:03 +01:00
|
|
|
if (!_eglInitContext(drv, context, conf, attrib_list)) {
|
2005-11-27 23:57:19 +00:00
|
|
|
free(context);
|
|
|
|
return EGL_NO_CONTEXT;
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
2009-07-17 18:53:03 +01:00
|
|
|
return _eglLinkContext(context, _eglLookupDisplay(dpy));
|
2005-11-27 23:57:19 +00:00
|
|
|
#endif
|
2005-04-22 22:09:39 +01:00
|
|
|
return EGL_NO_CONTEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Default fallback routine - drivers should usually override this.
|
|
|
|
*/
|
|
|
|
EGLBoolean
|
|
|
|
_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
|
|
|
|
{
|
|
|
|
_EGLContext *context = _eglLookupContext(ctx);
|
|
|
|
if (context) {
|
2009-07-17 18:53:03 +01:00
|
|
|
_eglUnlinkContext(context);
|
2009-08-03 18:34:37 +01:00
|
|
|
if (!_eglIsContextBound(context))
|
2005-04-22 22:09:39 +01:00
|
|
|
free(context);
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_eglError(EGL_BAD_CONTEXT, "eglDestroyContext");
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EGLBoolean
|
2005-11-27 23:57:19 +00:00
|
|
|
_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
|
|
|
|
EGLint attribute, EGLint *value)
|
2005-04-22 22:09:39 +01:00
|
|
|
{
|
|
|
|
_EGLContext *c = _eglLookupContext(ctx);
|
|
|
|
|
|
|
|
(void) drv;
|
|
|
|
(void) dpy;
|
|
|
|
|
|
|
|
if (!c) {
|
|
|
|
_eglError(EGL_BAD_CONTEXT, "eglQueryContext");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (attribute) {
|
|
|
|
case EGL_CONFIG_ID:
|
|
|
|
*value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
|
|
|
|
return EGL_TRUE;
|
2006-01-30 00:10:55 +00:00
|
|
|
#ifdef EGL_VERSION_1_2
|
|
|
|
case EGL_CONTEXT_CLIENT_TYPE:
|
|
|
|
*value = c->ClientAPI;
|
2008-06-20 04:19:33 +01:00
|
|
|
return EGL_TRUE;
|
2006-01-30 00:10:55 +00:00
|
|
|
#endif /* EGL_VERSION_1_2 */
|
2008-06-20 04:19:33 +01:00
|
|
|
case EGL_CONTEXT_CLIENT_VERSION:
|
|
|
|
*value = c->ClientVersion;
|
|
|
|
return EGL_TRUE;
|
2005-04-22 22:09:39 +01:00
|
|
|
default:
|
|
|
|
_eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Drivers will typically call this to do the error checking and
|
2009-07-17 18:56:00 +01:00
|
|
|
* update the various flags.
|
2005-04-22 22:09:39 +01:00
|
|
|
* Then, the driver will do its device-dependent Make-Current stuff.
|
|
|
|
*/
|
|
|
|
EGLBoolean
|
2005-11-27 23:57:19 +00:00
|
|
|
_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
|
|
|
|
EGLSurface r, EGLContext context)
|
2005-04-22 22:09:39 +01:00
|
|
|
{
|
2005-12-10 17:54:00 +00:00
|
|
|
_EGLThreadInfo *t = _eglGetCurrentThread();
|
2005-04-22 22:09:39 +01:00
|
|
|
_EGLContext *ctx = _eglLookupContext(context);
|
|
|
|
_EGLSurface *draw = _eglLookupSurface(d);
|
|
|
|
_EGLSurface *read = _eglLookupSurface(r);
|
2009-07-17 18:42:04 +01:00
|
|
|
_EGLContext *oldContext = NULL;
|
|
|
|
_EGLSurface *oldDrawSurface = NULL;
|
|
|
|
_EGLSurface *oldReadSurface = NULL;
|
|
|
|
EGLint apiIndex;
|
2005-04-22 22:09:39 +01:00
|
|
|
|
2009-07-17 18:41:02 +01:00
|
|
|
if (_eglIsCurrentThreadDummy())
|
|
|
|
return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
|
|
|
|
|
2005-04-22 22:09:39 +01:00
|
|
|
/* error checking */
|
|
|
|
if (ctx) {
|
|
|
|
if (draw == NULL || read == NULL) {
|
|
|
|
_eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
if (draw->Config != ctx->Config) {
|
|
|
|
_eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
if (read->Config != ctx->Config) {
|
|
|
|
_eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
2009-07-17 18:42:04 +01:00
|
|
|
|
|
|
|
#ifdef EGL_VERSION_1_4
|
|
|
|
/* OpenGL and OpenGL ES are conflicting */
|
|
|
|
switch (ctx->ClientAPI) {
|
|
|
|
case EGL_OPENGL_ES_API:
|
|
|
|
if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)])
|
|
|
|
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
|
|
|
|
break;
|
|
|
|
case EGL_OPENGL_API:
|
|
|
|
if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)])
|
|
|
|
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
apiIndex = _eglConvertApiToIndex(ctx->ClientAPI);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
apiIndex = t->CurrentAPIIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
oldContext = t->CurrentContexts[apiIndex];
|
|
|
|
if (oldContext) {
|
|
|
|
oldDrawSurface = oldContext->DrawSurface;
|
|
|
|
oldReadSurface = oldContext->ReadSurface;
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check if the old context or surfaces need to be deleted
|
|
|
|
*/
|
|
|
|
if (oldDrawSurface != NULL) {
|
2009-08-03 18:34:37 +01:00
|
|
|
oldDrawSurface->Binding = NULL;
|
2009-07-17 18:56:00 +01:00
|
|
|
if (!_eglIsSurfaceLinked(oldDrawSurface)) {
|
2005-04-22 22:09:39 +01:00
|
|
|
/* make sure we don't try to rebind a deleted surface */
|
|
|
|
if (draw == oldDrawSurface || draw == oldReadSurface) {
|
|
|
|
draw = NULL;
|
|
|
|
}
|
|
|
|
/* really delete surface now */
|
2005-11-24 04:02:16 +00:00
|
|
|
drv->API.DestroySurface(drv, dpy, oldDrawSurface->Handle);
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) {
|
2009-08-03 18:34:37 +01:00
|
|
|
oldReadSurface->Binding = NULL;
|
2009-07-17 18:56:00 +01:00
|
|
|
if (!_eglIsSurfaceLinked(oldReadSurface)) {
|
2005-04-22 22:09:39 +01:00
|
|
|
/* make sure we don't try to rebind a deleted surface */
|
|
|
|
if (read == oldDrawSurface || read == oldReadSurface) {
|
|
|
|
read = NULL;
|
|
|
|
}
|
|
|
|
/* really delete surface now */
|
2005-11-24 04:02:16 +00:00
|
|
|
drv->API.DestroySurface(drv, dpy, oldReadSurface->Handle);
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (oldContext != NULL) {
|
2009-08-03 18:34:37 +01:00
|
|
|
oldContext->Binding = NULL;
|
2009-07-17 18:56:00 +01:00
|
|
|
if (!_eglIsContextLinked(oldContext)) {
|
2005-04-22 22:09:39 +01:00
|
|
|
/* make sure we don't try to rebind a deleted context */
|
|
|
|
if (ctx == oldContext) {
|
|
|
|
ctx = NULL;
|
|
|
|
}
|
|
|
|
/* really delete context now */
|
2008-05-27 21:21:25 +01:00
|
|
|
drv->API.DestroyContext(drv, dpy, _eglGetContextHandle(oldContext));
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx) {
|
|
|
|
/* check read/draw again, in case we deleted them above */
|
|
|
|
if (draw == NULL || read == NULL) {
|
|
|
|
_eglError(EGL_BAD_MATCH, "eglMakeCurrent");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
ctx->DrawSurface = draw;
|
|
|
|
ctx->ReadSurface = read;
|
2009-08-03 18:34:37 +01:00
|
|
|
ctx->Binding = t;
|
|
|
|
draw->Binding = ctx;
|
|
|
|
read->Binding = ctx;
|
2009-07-17 18:42:04 +01:00
|
|
|
t->CurrentContexts[apiIndex] = ctx;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
t->CurrentContexts[apiIndex] = NULL;
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
2005-05-14 15:54:38 +01:00
|
|
|
|
|
|
|
|
2005-05-16 03:21:08 +01:00
|
|
|
/**
|
|
|
|
* This is defined by the EGL_MESA_copy_context extension.
|
|
|
|
*/
|
2005-05-14 15:54:38 +01:00
|
|
|
EGLBoolean
|
2005-05-16 03:21:08 +01:00
|
|
|
_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source,
|
|
|
|
EGLContext dest, EGLint mask)
|
2005-05-14 15:54:38 +01:00
|
|
|
{
|
2005-05-16 03:21:08 +01:00
|
|
|
/* This function will always have to be overridden/implemented in the
|
|
|
|
* device driver. If the driver is based on Mesa, use _mesa_copy_context().
|
|
|
|
*/
|
2005-05-14 15:54:38 +01:00
|
|
|
return EGL_FALSE;
|
|
|
|
}
|