don't use compile-time configuration of libgui as much as possible

We now detect at runtime which sync features to use, which
allows us to remove a lot of the compile-time configuration
options. There  is still one option though, to disable
KHR_fence_sync on some devices (which are more efficient
without it).

- added a backdoor to get the vendor's EGL strings

the new logic is:
- use always ANDROID_native_fence_sync if available
- fallback to KHR_fence_sync if available and not disabled
  by the compile-time option
- use KHR_wait_sync if available and either of the above is
  enabled

Change-Id: I9c4b49d9ff1151faf902cc93bd53ea5f205aaabf
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 5c7bb4c..8fcfa7d 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -26,6 +26,7 @@
 	Surface.cpp \
 	SurfaceControl.cpp \
 	SurfaceComposerClient.cpp \
+	SyncFeatures.cpp \
 
 LOCAL_SHARED_LIBRARIES := \
 	libbinder \
@@ -39,23 +40,11 @@
 
 LOCAL_MODULE:= libgui
 
-ifeq ($(TARGET_BOARD_PLATFORM), omap4)
-	LOCAL_CFLAGS += -DUSE_FENCE_SYNC
+ifeq ($(TARGET_BOARD_PLATFORM), tegra)
+	LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC
 endif
-ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
-	LOCAL_CFLAGS += -DUSE_FENCE_SYNC
-endif
-ifeq ($(TARGET_BOARD_PLATFORM), exynos5)
-	LOCAL_CFLAGS += -DUSE_NATIVE_FENCE_SYNC
-	LOCAL_CFLAGS += -DUSE_WAIT_SYNC
-endif
-ifneq ($(filter generic%,$(TARGET_DEVICE)),)
-    # Emulator build
-    LOCAL_CFLAGS += -DUSE_FENCE_SYNC
-endif
-
-ifeq ($(TARGET_BOARD_PLATFORM), msm8960)
-	LOCAL_CFLAGS += -DUSE_NATIVE_FENCE_SYNC
+ifeq ($(TARGET_BOARD_PLATFORM), tegra3)
+	LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC
 endif
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index fb6ba7d..8694d21 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -18,7 +18,6 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 //#define LOG_NDEBUG 0
 
-#define GL_GLEXT_PROTOTYPES
 #define EGL_EGLEXT_PROTOTYPES
 
 #include <EGL/egl.h>
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 1ce75ea..f8f1241 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -28,12 +28,13 @@
 
 #include <hardware/hardware.h>
 
+#include <gui/GLConsumer.h>
 #include <gui/IGraphicBufferAlloc.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
-#include <gui/GLConsumer.h>
 
 #include <private/gui/ComposerService.h>
+#include <private/gui/SyncFeatures.h>
 
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -41,30 +42,6 @@
 
 namespace android {
 
-// This compile option makes GLConsumer use the
-// EGL_ANDROID_native_fence_sync extension to create Android native fences to
-// signal when all GLES reads for a given buffer have completed.  It is not
-// compatible with using the EGL_KHR_fence_sync extension for the same
-// purpose.
-#ifdef USE_NATIVE_FENCE_SYNC
-#ifdef USE_FENCE_SYNC
-#error "USE_NATIVE_FENCE_SYNC and USE_FENCE_SYNC are incompatible"
-#endif
-const bool GLConsumer::sUseNativeFenceSync = true;
-#else
-const bool GLConsumer::sUseNativeFenceSync = false;
-#endif
-
-// This compile option makes GLConsumer use the EGL_KHR_wait_sync
-// extension to insert server-side waits into the GLES command stream.  This
-// feature requires the EGL_ANDROID_native_fence_sync and
-// EGL_KHR_wait_sync extensions.
-#ifdef USE_WAIT_SYNC
-static const bool useWaitSync = true;
-#else
-static const bool useWaitSync = false;
-#endif
-
 // Macros for including the GLConsumer name in log messages
 #define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
 #define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
@@ -97,18 +74,6 @@
     0, 0, 1, 0,
     1, 0, 0, 1,
 };
-static float mtxRot180[16] = {
-    -1, 0, 0, 0,
-    0, -1, 0, 0,
-    0, 0, 1, 0,
-    1, 1, 0, 1,
-};
-static float mtxRot270[16] = {
-    0, -1, 0, 0,
-    1, 0, 0, 0,
-    0, 0, 1, 0,
-    0, 1, 0, 1,
-};
 
 static void mtxMul(float out[16], const float a[16], const float b[16]);
 
@@ -121,11 +86,7 @@
     mCurrentTimestamp(0),
     mFilteringEnabled(true),
     mTexName(tex),
-#ifdef USE_FENCE_SYNC
     mUseFenceSync(useFenceSync),
-#else
-    mUseFenceSync(false),
-#endif
     mTexTarget(texTarget),
     mEglDisplay(EGL_NO_DISPLAY),
     mEglContext(EGL_NO_CONTEXT),
@@ -522,7 +483,7 @@
     ST_LOGV("syncForReleaseLocked");
 
     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        if (sUseNativeFenceSync) {
+        if (SyncFeatures::getInstance().useNativeFenceSync()) {
             EGLSyncKHR sync = eglCreateSyncKHR(dpy,
                     EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
             if (sync == EGL_NO_SYNC_KHR) {
@@ -545,7 +506,7 @@
                         "%s (%d)", strerror(-err), err);
                 return err;
             }
-        } else if (mUseFenceSync) {
+        } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
             EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
             if (fence != EGL_NO_SYNC_KHR) {
                 // There is already a fence for the current slot.  We need to
@@ -825,7 +786,7 @@
     }
 
     if (mCurrentFence->isValid()) {
-        if (useWaitSync) {
+        if (SyncFeatures::getInstance().useWaitSync()) {
             // Create an EGLSyncKHR from the current fence.
             int fenceFd = mCurrentFence->dup();
             if (fenceFd == -1) {
diff --git a/libs/gui/GuiConfig.cpp b/libs/gui/GuiConfig.cpp
index bafd21a..bc0c83c 100644
--- a/libs/gui/GuiConfig.cpp
+++ b/libs/gui/GuiConfig.cpp
@@ -22,14 +22,8 @@
 {
     static const char* config =
             " [libgui"
-#ifdef USE_FENCE_SYNC
-            " USE_FENCE_SYNC"
-#endif
-#ifdef USE_NATIVE_FENCE_SYNC
-            " USE_NATIVE_FENCE_SYNC"
-#endif
-#ifdef USE_WAIT_SYNC
-            " USE_WAIT_SYNC"
+#ifdef DONT_USE_FENCE_SYNC
+            " DONT_USE_FENCE_SYNC"
 #endif
             "]";
     configStr.append(config);
diff --git a/libs/gui/SyncFeatures.cpp b/libs/gui/SyncFeatures.cpp
new file mode 100644
index 0000000..e5804a7
--- /dev/null
+++ b/libs/gui/SyncFeatures.cpp
@@ -0,0 +1,94 @@
+/*
+ ** Copyright 2013, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#define LOG_TAG "GLConsumer"
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <utils/Log.h>
+#include <utils/Singleton.h>
+#include <utils/String8.h>
+
+#include <private/gui/SyncFeatures.h>
+
+EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(SyncFeatures);
+
+SyncFeatures::SyncFeatures() : Singleton<SyncFeatures>(),
+        mHasNativeFenceSync(false),
+        mHasFenceSync(false),
+        mHasWaitSync(false) {
+    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    // This can only be called after EGL has been initialized; otherwise the
+    // check below will abort.
+    const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
+    LOG_ALWAYS_FATAL_IF(exts == NULL, "eglQueryStringImplementationANDROID failed");
+    if (strstr(exts, "EGL_ANDROID_native_fence_sync")) {
+        // This makes GLConsumer use the EGL_ANDROID_native_fence_sync
+        // extension to create Android native fences to signal when all
+        // GLES reads for a given buffer have completed.
+        mHasNativeFenceSync = true;
+    }
+    if (strstr(exts, "EGL_KHR_fence_sync")) {
+        mHasFenceSync = true;
+    }
+    if (strstr(exts, "EGL_KHR_wait_sync")) {
+        mHasWaitSync = true;
+    }
+    mString.append("[using:");
+    if (useNativeFenceSync()) {
+        mString.append(" EGL_ANDROID_native_fence_sync");
+    }
+    if (useFenceSync()) {
+        mString.append(" EGL_KHR_fence_sync");
+    }
+    if (useWaitSync()) {
+        mString.append(" EGL_KHR_wait_sync");
+    }
+    mString.append("]");
+}
+
+bool SyncFeatures::useNativeFenceSync() const {
+    // EGL_ANDROID_native_fence_sync is not compatible with using the
+    // EGL_KHR_fence_sync extension for the same purpose.
+    return mHasNativeFenceSync;
+}
+bool SyncFeatures::useFenceSync() const {
+#ifdef DONT_USE_FENCE_SYNC
+    // on some devices it's better to not use EGL_KHR_fence_sync
+    // even if they have it
+    return false;
+#endif
+    // currently we shall only attempt to use EGL_KHR_fence_sync if
+    // USE_FENCE_SYNC is set in our makefile
+    return !mHasNativeFenceSync && mHasFenceSync;
+}
+bool SyncFeatures::useWaitSync() const {
+    return (useNativeFenceSync() || useFenceSync()) && mHasWaitSync;
+}
+
+String8 SyncFeatures::toString() const {
+    return mString;
+}
+
+} // namespace android