*/
#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";
"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;
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)
{
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;
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;
}
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);
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);
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);
+}
+