EGLBoolean EGLAPIENTRY eglReleaseThread(void) { /* unbind current contexts */ if (!_eglIsCurrentThreadDummy()) { _EGLThreadInfo *t = _eglGetCurrentThread(); EGLint api_index = t->CurrentAPIIndex; EGLint i; for (i = 0; i < _EGL_API_NUM_APIS; i++) { _EGLContext *ctx = t->CurrentContexts[i]; if (ctx) { _EGLDisplay *disp = ctx->Resource.Display; _EGLDriver *drv; t->CurrentAPIIndex = i; _eglLockMutex(&disp->Mutex); drv = disp->Driver; (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); _eglUnlockMutex(&disp->Mutex); } } t->CurrentAPIIndex = api_index; } _eglDestroyCurrentThread(); RETURN_EGL_SUCCESS(NULL, EGL_TRUE); }
EGLint EGLAPIENTRY eglGetError(void) { _EGLThreadInfo *t = _eglGetCurrentThread(); EGLint e = t->LastError; if (!_eglIsCurrentThreadDummy()) t->LastError = EGL_SUCCESS; return e; }
/** * Specify the client API to use for subsequent calls including: * eglCreateContext() * eglGetCurrentContext() * eglGetCurrentDisplay() * eglGetCurrentSurface() * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT) * eglWaitClient() * eglWaitNative() * See section 3.7 "Rendering Context" in the EGL specification for details. */ EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) { _EGLThreadInfo *t = _eglGetCurrentThread(); if (_eglIsCurrentThreadDummy()) RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE); if (!_eglIsApiValid(api)) RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE); t->CurrentAPIIndex = _eglConvertApiToIndex(api); RETURN_EGL_SUCCESS(NULL, EGL_TRUE); }
EGLBoolean EGLAPIENTRY eglWaitGL(void) { _EGLThreadInfo *t = _eglGetCurrentThread(); EGLint api_index = t->CurrentAPIIndex; EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API); EGLBoolean ret; if (api_index != es_index && _eglIsCurrentThreadDummy()) RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE); t->CurrentAPIIndex = es_index; ret = eglWaitClient(); t->CurrentAPIIndex = api_index; return ret; }
/** * Return true if the given context and surfaces can be made current. */ static EGLBoolean _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) { _EGLThreadInfo *t = _eglGetCurrentThread(); _EGLDisplay *dpy; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); /* this is easy */ if (!ctx) { if (draw || read) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); return EGL_TRUE; } dpy = ctx->Resource.Display; if (!dpy->Extensions.KHR_surfaceless_context && (draw == NULL || read == NULL)) 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." * * and * * "at most one context may be bound to a particular surface at a given * time" */ if (ctx->Binding && ctx->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { if (draw->CurrentContext->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); } if (read && read->CurrentContext && read->CurrentContext != ctx) { if (read->CurrentContext->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); } /* If the context has a config then it must match that of the two * surfaces */ if (ctx->Config) { if ((draw && draw->Config != ctx->Config) || (read && read->Config != ctx->Config)) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); } else { /* Otherwise we must be using the EGL_KHR_no_config_context * extension */ assert(dpy->Extensions.KHR_no_config_context); /* The extension doesn't permit binding draw and read buffers with * differing contexts */ if (draw && read && draw->Config != read->Config) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); } return EGL_TRUE; }
/** * Return true if the given context and surfaces can be made current. */ static EGLBoolean _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) { _EGLThreadInfo *t = _eglGetCurrentThread(); _EGLDisplay *dpy; EGLint conflict_api; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); /* this is easy */ if (!ctx) { if (draw || read) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); return EGL_TRUE; } dpy = ctx->Resource.Display; if (!dpy->Extensions.KHR_surfaceless_context && (draw == NULL || read == NULL)) 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." * * and * * "at most one context may be bound to a particular surface at a given * time" */ if (ctx->Binding && ctx->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 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"); } /* simply require the configs to be equal */ if ((draw && draw->Config != ctx->Config) || (read && read->Config != ctx->Config)) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 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; } if (conflict_api >= 0 && _eglGetAPIContext(conflict_api)) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); return EGL_TRUE; }
/** * 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; }
/** * Return true if the given context and surfaces can be made current. */ static EGLBoolean _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) { _EGLThreadInfo *t = _eglGetCurrentThread(); EGLint conflict_api; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); /* this is easy */ if (!ctx) { if (draw || read) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); return EGL_TRUE; } /* ctx/draw/read must be all given */ if (draw == NULL || read == NULL) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); /* context stealing from another thread is not allowed */ if (ctx->Binding && ctx->Binding != t) return _eglError(EGL_BAD_ACCESS, "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." * * But it also says * * "at most one context may be bound to a particular surface at a given * time" * * The latter is more restrictive so we can check only the latter case. */ if ((draw->CurrentContext && draw->CurrentContext != ctx) || (read->CurrentContext && read->CurrentContext != ctx)) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); /* simply require the configs to be equal */ if (draw->Config != ctx->Config || read->Config != ctx->Config) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); switch (ctx->ClientAPI) { #ifdef EGL_VERSION_1_4 /* 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; #endif default: conflict_api = -1; break; } if (conflict_api >= 0 && _eglGetAPIContext(conflict_api)) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); return EGL_TRUE; }