#include #include #include #include "eglconfig.h" #include "eglcontext.h" #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.h" #include "eglsurface.h" /** * Initialize the given _EGLContext object to defaults and/or the values * in the attrib_list. */ EGLBoolean _eglInitContext(_EGLDriver *drv, _EGLContext *ctx, _EGLConfig *conf, const EGLint *attrib_list) { 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; } /** * 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) { #if 0 /* example code */ _EGLContext *context; context = (_EGLContext *) calloc(1, sizeof(_EGLContext)); if (!context) return NULL; if (!_eglInitContext(drv, context, conf, attrib_list)) { free(context); return NULL; } return context; #endif return NULL; } /** * Default fallback routine - drivers should usually override this. */ EGLBoolean _eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) { if (!_eglIsContextBound(ctx)) free(ctx); return EGL_TRUE; } EGLBoolean _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, EGLint attribute, EGLint *value) { (void) drv; (void) dpy; switch (attribute) { case EGL_CONFIG_ID: *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID); return EGL_TRUE; #ifdef EGL_VERSION_1_2 case EGL_CONTEXT_CLIENT_TYPE: *value = c->ClientAPI; return EGL_TRUE; #endif /* EGL_VERSION_1_2 */ case EGL_CONTEXT_CLIENT_VERSION: *value = c->ClientVersion; return EGL_TRUE; default: _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); return EGL_FALSE; } } /** * Drivers will typically call this to do the error checking and * update the various flags. * Then, the driver will do its device-dependent Make-Current stuff. */ EGLBoolean _eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) { _EGLThreadInfo *t = _eglGetCurrentThread(); _EGLContext *oldContext = NULL; _EGLSurface *oldDrawSurface = NULL; _EGLSurface *oldReadSurface = NULL; EGLint apiIndex; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); 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); /* 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); } if (oldReadSurface != oldDrawSurface && !_eglIsSurfaceLinked(oldReadSurface)) { assert(draw != oldReadSurface && read != oldReadSurface); drv->API.DestroySurface(drv, dpy, oldReadSurface); } if (!_eglIsContextLinked(oldContext)) { assert(ctx != oldContext); drv->API.DestroyContext(drv, dpy, oldContext); } } /* build new bindings */ if (ctx) { t->CurrentContexts[apiIndex] = ctx; ctx->Binding = t; ctx->DrawSurface = draw; ctx->ReadSurface = read; draw->Binding = ctx; read->Binding = ctx; } 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; }