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/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