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
|
|
|
|
_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
|
|
|
|
EGLConfig config, const EGLint *attrib_list)
|
2005-04-22 22:09:39 +01:00
|
|
|
{
|
2005-11-27 23:57:19 +00:00
|
|
|
_EGLConfig *conf;
|
|
|
|
_EGLDisplay *display = _eglLookupDisplay(dpy);
|
|
|
|
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
|
|
|
|
|
|
|
conf = _eglLookupConfig(drv, dpy, config);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-22 22:09:39 +01:00
|
|
|
memset(ctx, 0, sizeof(_EGLContext));
|
2005-11-27 23:57:19 +00:00
|
|
|
ctx->Display = display;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-27 21:21:25 +01:00
|
|
|
/**
|
|
|
|
* Save a new _EGLContext into the hash table.
|
2005-04-22 22:09:39 +01:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
_eglSaveContext(_EGLContext *ctx)
|
|
|
|
{
|
2008-05-27 21:21:25 +01:00
|
|
|
/* no-op.
|
|
|
|
* Public EGLContext handle and private _EGLContext are the same.
|
|
|
|
*/
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove the given _EGLContext object from the hash table.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
_eglRemoveContext(_EGLContext *ctx)
|
|
|
|
{
|
2008-05-27 21:21:25 +01:00
|
|
|
/* no-op.
|
|
|
|
* Public EGLContext handle and private _EGLContext are the same.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the public handle for the given private context ptr.
|
|
|
|
* This is the inverse of _eglLookupContext().
|
|
|
|
*/
|
|
|
|
EGLContext
|
|
|
|
_eglGetContextHandle(_EGLContext *ctx)
|
|
|
|
{
|
|
|
|
/* just a cast! */
|
|
|
|
return (EGLContext) ctx;
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the _EGLContext object that corresponds to the given
|
|
|
|
* EGLContext handle.
|
2008-05-27 21:21:25 +01:00
|
|
|
* This is the inverse of _eglGetContextHandle().
|
2005-04-22 22:09:39 +01:00
|
|
|
*/
|
|
|
|
_EGLContext *
|
|
|
|
_eglLookupContext(EGLContext ctx)
|
|
|
|
{
|
2008-05-27 21:21:25 +01:00
|
|
|
/* just a cast since EGLContext is just a void ptr */
|
|
|
|
return (_EGLContext *) ctx;
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the currently bound _EGLContext object, or NULL.
|
|
|
|
*/
|
|
|
|
_EGLContext *
|
|
|
|
_eglGetCurrentContext(void)
|
|
|
|
{
|
2005-12-10 17:54:00 +00:00
|
|
|
_EGLThreadInfo *t = _eglGetCurrentThread();
|
|
|
|
return t->CurrentContext;
|
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;
|
|
|
|
|
|
|
|
context = (_EGLContext *) calloc(1, sizeof(_EGLContext));
|
|
|
|
if (!context)
|
2005-04-22 22:09:39 +01:00
|
|
|
return EGL_NO_CONTEXT;
|
|
|
|
|
2005-11-27 23:57:19 +00:00
|
|
|
if (!_eglInitContext(drv, dpy, context, config, attrib_list)) {
|
|
|
|
free(context);
|
|
|
|
return EGL_NO_CONTEXT;
|
2005-04-22 22:09:39 +01:00
|
|
|
}
|
|
|
|
|
2005-11-27 23:57:19 +00:00
|
|
|
_eglSaveContext(context);
|
2008-05-27 21:21:25 +01:00
|
|
|
return (EGLContext) context;
|
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) {
|
|
|
|
if (context->IsBound) {
|
|
|
|
context->DeletePending = EGL_TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
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;
|
|
|
|
return EGL_FALSE;
|
|
|
|
#endif /* EGL_VERSION_1_2 */
|
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 IsBound and DeletePending flags.
|
|
|
|
* 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);
|
|
|
|
|
|
|
|
_EGLContext *oldContext = _eglGetCurrentContext();
|
|
|
|
_EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW);
|
|
|
|
_EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ);
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* check if the old context or surfaces need to be deleted
|
|
|
|
*/
|
|
|
|
if (oldDrawSurface != NULL) {
|
|
|
|
oldDrawSurface->IsBound = EGL_FALSE;
|
|
|
|
if (oldDrawSurface->DeletePending) {
|
|
|
|
/* 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) {
|
|
|
|
oldReadSurface->IsBound = EGL_FALSE;
|
|
|
|
if (oldReadSurface->DeletePending) {
|
|
|
|
/* 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) {
|
|
|
|
oldContext->IsBound = EGL_FALSE;
|
|
|
|
if (oldContext->DeletePending) {
|
|
|
|
/* 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;
|
|
|
|
ctx->IsBound = EGL_TRUE;
|
|
|
|
draw->IsBound = EGL_TRUE;
|
|
|
|
read->IsBound = EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2005-12-10 17:54:00 +00:00
|
|
|
t->CurrentContext = ctx;
|
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;
|
|
|
|
}
|