OSDN Git Service

[hwc2] Add surfaceInterface/goldfishHwc2
[android-x86/device-generic-goldfish-opengl.git] / system / egl / eglDisplay.cpp
index 051368a..2239e99 100644 (file)
 */
 #include "eglDisplay.h"
 #include "HostConnection.h"
+#include "goldfishHwc2.h"
+
 #include <dlfcn.h>
 
+#include <string>
+
 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<EGLDisplay>(this), *ctxToDelete);
+        }
+        EGLSurfaceSet::iterator surfaceIte = m_surfaces.begin();
+        while (surfaceIte != m_surfaces.end()) {
+            EGLSurfaceSet::iterator surfaceToDelete = surfaceIte;
+            surfaceIte ++;
+            eglDestroySurface(static_cast<EGLDisplay>(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);
+}
+