* limitations under the License.
*/
+#include <assert.h>
#include "HostConnection.h"
#include "ThreadInfo.h"
#include "eglDisplay.h"
setErrorReturn(EGL_BAD_DISPLAY, EGL_FALSE); \
}
+// The one and only supported display object.
+static eglDisplay s_display;
EGLContext_t::EGLContext_t(EGLDisplay dpy, EGLConfig config, EGLContext_t* shareCtx) :
dpy(dpy),
sharedGroup = shareCtx->getSharedGroup();
else
sharedGroup = GLSharedGroupPtr(new GLSharedGroup());
+ assert(dpy == (EGLDisplay)&s_display);
+ s_display.onCreateContext((EGLContext)this);
};
EGLContext_t::~EGLContext_t()
{
+ assert(dpy == (EGLDisplay)&s_display);
+ s_display.onDestroyContext((EGLContext)this);
delete clientState;
delete [] versionString;
delete [] vendorString;
height = 0;
texFormat = EGL_NO_TEXTURE;
texTarget = EGL_NO_TEXTURE;
+ assert(dpy == (EGLDisplay)&s_display);
+ s_display.onCreateSurface((EGLSurface)this);
}
EGLint egl_surface_t::getSwapBehavior() const {
egl_surface_t::~egl_surface_t()
{
+ assert(dpy == (EGLDisplay)&s_display);
+ s_display.onDestroySurface((EGLSurface)this);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
-// The one and only supported display object.
-static eglDisplay s_display;
-
static EGLClient_eglInterface s_eglIface = {
getThreadInfo: getEGLThreadInfo,
getGLString: getGLString
EGLBoolean eglReleaseThread()
{
EGLThreadInfo *tInfo = getEGLThreadInfo();
- if (tInfo && tInfo->currentContext) {
- return eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
+ if (tInfo) {
+ tInfo->eglError = EGL_SUCCESS;
+ EGLContext_t* context = tInfo->currentContext;
+ if (context) {
+ // The following code is doing pretty much the same thing as
+ // eglMakeCurrent(&s_display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)
+ // with the only issue that we do not require a valid display here.
+ DEFINE_AND_VALIDATE_HOST_CONNECTION(EGL_FALSE);
+ rcEnc->rcMakeCurrent(rcEnc, 0, 0, 0);
+ if (context->version == 2) {
+ hostCon->gl2Encoder()->setClientState(NULL);
+ hostCon->gl2Encoder()->setSharedGroup(GLSharedGroupPtr());
+ }
+ else {
+ hostCon->glEncoder()->setClientState(NULL);
+ hostCon->glEncoder()->setSharedGroup(GLSharedGroupPtr());
+ }
+ context->flags &= ~EGLContext_t::IS_CURRENT;
+
+ if (context->deletePending) {
+ if (context->rcContext) {
+ rcEnc->rcDestroyContext(rcEnc, context->rcContext);
+ context->rcContext = 0;
+ }
+ delete context;
+ }
+ tInfo->currentContext = 0;
+ }
}
return EGL_TRUE;
}
m_extensionString(NULL)
{
pthread_mutex_init(&m_lock, NULL);
+ pthread_mutex_init(&m_ctxLock, NULL);
+ pthread_mutex_init(&m_surfaceLock, NULL);
}
eglDisplay::~eglDisplay()
{
+ terminate();
pthread_mutex_destroy(&m_lock);
+ pthread_mutex_destroy(&m_ctxLock);
+ pthread_mutex_destroy(&m_surfaceLock);
}
bool eglDisplay::initialize(EGLClient_eglInterface *eglIface)
{
pthread_mutex_lock(&m_lock);
if (m_initialized) {
+ // Cannot use the for loop in the following code because
+ // eglDestroyContext may erase elements.
+ auto ctxIte = m_contexts.begin();
+ while (ctxIte != m_contexts.end()) {
+ auto ctxToDelete = ctxIte;
+ ctxIte ++;
+ eglDestroyContext(static_cast<EGLDisplay>(this), *ctxToDelete);
+ }
+ auto surfaceIte = m_surfaces.begin();
+ while (surfaceIte != m_surfaces.end()) {
+ auto surfaceToDelete = surfaceIte;
+ surfaceIte ++;
+ eglDestroySurface(static_cast<EGLDisplay>(this), *surfaceToDelete);
+ }
m_initialized = false;
delete [] m_configs;
m_configs = NULL;
return EGL_TRUE;
}
+
+void eglDisplay::onCreateContext(EGLContext ctx) {
+ pthread_mutex_lock(&m_ctxLock);
+ m_contexts.insert(ctx);
+ pthread_mutex_unlock(&m_ctxLock);
+}
+
+void eglDisplay::onCreateSurface(EGLSurface surface) {
+ pthread_mutex_lock(&m_surfaceLock);
+ m_surfaces.insert(surface);
+ pthread_mutex_unlock(&m_surfaceLock);
+}
+
+void eglDisplay::onDestroyContext(EGLContext ctx) {
+ pthread_mutex_lock(&m_ctxLock);
+ m_contexts.erase(ctx);
+ pthread_mutex_unlock(&m_ctxLock);
+}
+
+void eglDisplay::onDestroySurface(EGLSurface surface) {
+ pthread_mutex_lock(&m_surfaceLock);
+ m_surfaces.erase(surface);
+ pthread_mutex_unlock(&m_surfaceLock);
+}
+
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "EGLClientIface.h"
+#include <unordered_set>
#include <utils/KeyedVector.h>
#include <ui/PixelFormat.h>
EGLBoolean getConfigNativePixelFormat(EGLConfig config, PixelFormat * format);
void dumpConfig(EGLConfig config);
+
+ void onCreateContext(EGLContext ctx);
+ void onCreateSurface(EGLSurface surface);
+
+ void onDestroyContext(EGLContext ctx);
+ void onDestroySurface(EGLSurface surface);
private:
EGLClient_glesInterface *loadGLESClientAPI(const char *libName,
EGLClient_eglInterface *eglIface,
char *m_versionString;
char *m_vendorString;
char *m_extensionString;
+
+ std::unordered_set<EGLContext> m_contexts;
+ std::unordered_set<EGLSurface> m_surfaces;
+ pthread_mutex_t m_ctxLock;
+ pthread_mutex_t m_surfaceLock;
};
#endif