mesa/src/egl/main/eglcontext.c

228 lines
6.1 KiB
C
Raw Normal View History

2005-04-22 22:09:39 +01:00
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "eglconfig.h"
#include "eglcontext.h"
#include "egldisplay.h"
2005-04-22 22:09:39 +01:00
#include "egldriver.h"
#include "eglglobals.h"
#include "eglsurface.h"
/**
* Initialize the given _EGLContext object to defaults and/or the values
* in the attrib_list.
2005-04-22 22:09:39 +01:00
*/
EGLBoolean
_eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
_EGLConfig *conf, const EGLint *attrib_list)
2005-04-22 22:09:39 +01:00
{
EGLint i;
const EGLenum api = eglQueryAPI();
if (api == EGL_NONE) {
_eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
return EGL_FALSE;
}
memset(ctx, 0, sizeof(_EGLContext));
ctx->ClientVersion = 1; /* the default, per EGL spec */
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
switch (attrib_list[i]) {
case EGL_CONTEXT_CLIENT_VERSION:
i++;
ctx->ClientVersion = attrib_list[i];
break;
default:
_eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext");
return EGL_FALSE;
}
}
ctx->Config = conf;
ctx->DrawSurface = EGL_NO_SURFACE;
ctx->ReadSurface = EGL_NO_SURFACE;
ctx->ClientAPI = api;
return EGL_TRUE;
2005-04-22 22:09:39 +01:00
}
/**
* Just a placeholder/demo function. Real driver will never use this!
*/
_EGLContext *
_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
_EGLContext *share_list, const EGLint *attrib_list)
2005-04-22 22:09:39 +01:00
{
#if 0 /* example code */
_EGLContext *context;
context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
if (!context)
return NULL;
2005-04-22 22:09:39 +01:00
if (!_eglInitContext(drv, context, conf, attrib_list)) {
free(context);
return NULL;
2005-04-22 22:09:39 +01:00
}
return context;
#endif
return NULL;
2005-04-22 22:09:39 +01:00
}
/**
* Default fallback routine - drivers should usually override this.
*/
EGLBoolean
_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
2005-04-22 22:09:39 +01:00
{
if (!_eglIsContextBound(ctx))
free(ctx);
return EGL_TRUE;
2005-04-22 22:09:39 +01:00
}
EGLBoolean
_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
EGLint attribute, EGLint *value)
2005-04-22 22:09:39 +01:00
{
(void) drv;
(void) dpy;
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;
return EGL_TRUE;
2006-01-30 00:10:55 +00:00
#endif /* EGL_VERSION_1_2 */
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
* update the various flags.
2005-04-22 22:09:39 +01:00
* Then, the driver will do its device-dependent Make-Current stuff.
*/
EGLBoolean
_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw,
_EGLSurface *read, _EGLContext *ctx)
2005-04-22 22:09:39 +01:00
{
_EGLThreadInfo *t = _eglGetCurrentThread();
_EGLContext *oldContext = NULL;
_EGLSurface *oldDrawSurface = NULL;
_EGLSurface *oldReadSurface = NULL;
EGLint apiIndex;
2005-04-22 22:09:39 +01:00
if (_eglIsCurrentThreadDummy())
return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
2005-04-22 22:09:39 +01:00
if (ctx) {
/* error checking */
if (ctx->Binding && ctx->Binding != t)
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
if (draw == NULL || read == NULL)
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
if (draw->Config != ctx->Config || read->Config != ctx->Config)
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
if ((draw->Binding && draw->Binding->Binding != t) ||
(read->Binding && read->Binding->Binding != t))
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
#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 {
if (draw != NULL || read != NULL)
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
apiIndex = t->CurrentAPIIndex;
}
oldContext = t->CurrentContexts[apiIndex];
if (oldContext) {
oldDrawSurface = oldContext->DrawSurface;
oldReadSurface = oldContext->ReadSurface;
assert(oldDrawSurface);
assert(oldReadSurface);
2005-04-22 22:09:39 +01:00
/* break old bindings */
t->CurrentContexts[apiIndex] = NULL;
oldContext->Binding = NULL;
oldContext->DrawSurface = NULL;
oldContext->ReadSurface = NULL;
oldDrawSurface->Binding = NULL;
oldReadSurface->Binding = NULL;
/*
* check if the old context or surfaces need to be deleted
*/
if (!_eglIsSurfaceLinked(oldDrawSurface)) {
assert(draw != oldDrawSurface && read != oldDrawSurface);
drv->API.DestroySurface(drv, dpy, oldDrawSurface);
2005-04-22 22:09:39 +01:00
}
if (oldReadSurface != oldDrawSurface &&
!_eglIsSurfaceLinked(oldReadSurface)) {
assert(draw != oldReadSurface && read != oldReadSurface);
drv->API.DestroySurface(drv, dpy, oldReadSurface);
2005-04-22 22:09:39 +01:00
}
if (!_eglIsContextLinked(oldContext)) {
assert(ctx != oldContext);
drv->API.DestroyContext(drv, dpy, oldContext);
2005-04-22 22:09:39 +01:00
}
}
/* build new bindings */
2005-04-22 22:09:39 +01:00
if (ctx) {
t->CurrentContexts[apiIndex] = ctx;
ctx->Binding = t;
2005-04-22 22:09:39 +01:00
ctx->DrawSurface = draw;
ctx->ReadSurface = read;
draw->Binding = ctx;
read->Binding = ctx;
2005-04-22 22:09:39 +01:00
}
return EGL_TRUE;
}
/**
* This is defined by the EGL_MESA_copy_context extension.
*/
EGLBoolean
_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source,
EGLContext dest, EGLint mask)
{
/* This function will always have to be overridden/implemented in the
* device driver. If the driver is based on Mesa, use _mesa_copy_context().
*/
return EGL_FALSE;
}