X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=system%2Fegl%2FeglDisplay.cpp;h=2239e99bfd423255ee437fd1c02b838f4ac68c32;hb=596e8dec5700d2976d3b40ae498dbbf479c4abb6;hp=051368a493ac2c94c788cfe42b8c0401f6a42e3f;hpb=e3187eae5fb3a65dde2fee8871a96a59126e11c3;p=android-x86%2Fdevice-generic-goldfish-opengl.git diff --git a/system/egl/eglDisplay.cpp b/system/egl/eglDisplay.cpp index 051368a..2239e99 100644 --- a/system/egl/eglDisplay.cpp +++ b/system/egl/eglDisplay.cpp @@ -15,8 +15,12 @@ */ #include "eglDisplay.h" #include "HostConnection.h" +#include "goldfishHwc2.h" + #include +#include + static const int systemEGLVersionMajor = 1; static const int systemEGLVersionMinor = 4; static const char systemEGLVendor[] = "Google Android emulator"; @@ -29,6 +33,9 @@ static const char systemStaticEGLExtensions[] = "EGL_KHR_image_base " "EGL_KHR_gl_texture_2d_image "; +// extensions to add dynamically depending on host-side support +static const char kDynamicEGLExtNativeSync[] = "EGL_ANDROID_native_fence_sync "; + static void *s_gles_lib = NULL; static void *s_gles2_lib = NULL; @@ -63,11 +70,17 @@ eglDisplay::eglDisplay() : m_extensionString(NULL) { pthread_mutex_init(&m_lock, NULL); + pthread_mutex_init(&m_ctxLock, NULL); + pthread_mutex_init(&m_surfaceLock, NULL); + surfaceInterface_init(); } eglDisplay::~eglDisplay() { + terminate(); pthread_mutex_destroy(&m_lock); + pthread_mutex_destroy(&m_ctxLock); + pthread_mutex_destroy(&m_surfaceLock); } bool eglDisplay::initialize(EGLClient_eglInterface *eglIface) @@ -210,6 +223,20 @@ void eglDisplay::terminate() { pthread_mutex_lock(&m_lock); if (m_initialized) { + // Cannot use the for loop in the following code because + // eglDestroyContext may erase elements. + EGLContextSet::iterator ctxIte = m_contexts.begin(); + while (ctxIte != m_contexts.end()) { + EGLContextSet::iterator ctxToDelete = ctxIte; + ctxIte ++; + eglDestroyContext(static_cast(this), *ctxToDelete); + } + EGLSurfaceSet::iterator surfaceIte = m_surfaces.begin(); + while (surfaceIte != m_surfaces.end()) { + EGLSurfaceSet::iterator surfaceToDelete = surfaceIte; + surfaceIte ++; + eglDestroySurface(static_cast(this), *surfaceToDelete); + } m_initialized = false; delete [] m_configs; m_configs = NULL; @@ -259,14 +286,10 @@ static char *queryHostEGLString(EGLint name) if (rcEnc) { int n = rcEnc->rcQueryEGLString(rcEnc, name, NULL, 0); if (n < 0) { - // allocate space for the string with additional - // space charachter to be suffixed at the end. - char *str = (char *)malloc(-n+2); + // allocate space for the string. + char *str = (char *)malloc(-n); n = rcEnc->rcQueryEGLString(rcEnc, name, str, -n); if (n > 0) { - // add extra space at end of string which will be - // needed later when filtering the extension list. - strcat(str, " "); return str; } @@ -306,10 +329,27 @@ static char *buildExtensionString() int n = strlen(hostExt); if (n > 0) { - char *str; - asprintf(&str,"%s%s", systemStaticEGLExtensions, hostExt); + char *initialEGLExts; + char *finalEGLExts; + + HostConnection *hcon = HostConnection::get(); + // If we got here, we must have succeeded in queryHostEGLString + // and we thus should have a valid connection + assert(hcon); + + asprintf(&initialEGLExts,"%s%s", systemStaticEGLExtensions, hostExt); + + std::string dynamicEGLExtensions; + + if (hcon->rcEncoder()->hasNativeSync() && + !strstr(initialEGLExts, kDynamicEGLExtNativeSync)) { + dynamicEGLExtensions += kDynamicEGLExtNativeSync; + } + + asprintf(&finalEGLExts, "%s%s", initialEGLExts, dynamicEGLExtensions.c_str()); + free((char*)hostExt); - return str; + return finalEGLExts; } else { free((char*)hostExt); @@ -392,6 +432,19 @@ EGLBoolean eglDisplay::getAttribValue(EGLConfig config, EGLint attribIdx, EGLint EGLBoolean eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value) { + if (attrib == EGL_FRAMEBUFFER_TARGET_ANDROID) { + *value = EGL_TRUE; + return EGL_TRUE; + } + if (attrib == EGL_COVERAGE_SAMPLES_NV || + attrib == EGL_COVERAGE_BUFFERS_NV) { + *value = 0; + return EGL_TRUE; + } + if (attrib == EGL_DEPTH_ENCODING_NV) { + *value = EGL_DEPTH_ENCODING_NONE_NV; + return EGL_TRUE; + } //Though it seems that valueFor() is thread-safe, we don't take chanses pthread_mutex_lock(&m_lock); EGLBoolean ret = getAttribValue(config, m_attribs.valueFor(attrib), value); @@ -484,3 +537,28 @@ EGLBoolean eglDisplay::getConfigGLPixelFormat(EGLConfig config, GLenum * format) 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); +} +