From ca08833d5ea99130797e10ad68a651b50e99da74 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 28 Mar 2013 17:44:13 -0700 Subject: [PATCH] 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 --- include/gui/GLConsumer.h | 4 - include/private/gui/SyncFeatures.h | 45 +++++++++ libs/gui/Android.mk | 21 +---- libs/gui/ConsumerBase.cpp | 1 - libs/gui/GLConsumer.cpp | 49 +--------- libs/gui/GuiConfig.cpp | 10 +- libs/gui/SyncFeatures.cpp | 94 +++++++++++++++++++ opengl/libs/EGL/eglApi.cpp | 23 ++++- services/surfaceflinger/GLExtensions.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 25 +++-- .../surfaceflinger/SurfaceFlingerConsumer.cpp | 5 +- 11 files changed, 190 insertions(+), 89 deletions(-) create mode 100644 include/private/gui/SyncFeatures.h create mode 100644 libs/gui/SyncFeatures.cpp diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h index b1622d2e8..3b8dd7726 100644 --- a/include/gui/GLConsumer.h +++ b/include/gui/GLConsumer.h @@ -267,10 +267,6 @@ protected: // values. status_t checkAndUpdateEglStateLocked(); - // If set, GLConsumer will use the EGL_ANDROID_native_fence_sync - // extension to create Android native fences for GLES activity. - static const bool sUseNativeFenceSync; - private: // createImage creates a new EGLImage from a GraphicBuffer. EGLImageKHR createImage(EGLDisplay dpy, diff --git a/include/private/gui/SyncFeatures.h b/include/private/gui/SyncFeatures.h new file mode 100644 index 000000000..79fb75bcb --- /dev/null +++ b/include/private/gui/SyncFeatures.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 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. + */ + +#ifndef ANDROID_GUI_SYNC_FEATURES_H +#define ANDROID_GUI_SYNC_FEATURES_H + +#include +#include + + +namespace android { +// ---------------------------------------------------------------------------- + +class SyncFeatures : public Singleton { + friend class Singleton; + bool mHasNativeFenceSync; + bool mHasFenceSync; + bool mHasWaitSync; + String8 mString; + SyncFeatures(); + +public: + bool useNativeFenceSync() const; + bool useFenceSync() const; + bool useWaitSync() const; + String8 toString() const; +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_GUI_SYNC_FEATURES_H diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk index 5c7bb4cb4..8fcfa7de2 100644 --- a/libs/gui/Android.mk +++ b/libs/gui/Android.mk @@ -26,6 +26,7 @@ LOCAL_SRC_FILES:= \ Surface.cpp \ SurfaceControl.cpp \ SurfaceComposerClient.cpp \ + SyncFeatures.cpp \ LOCAL_SHARED_LIBRARIES := \ libbinder \ @@ -39,23 +40,11 @@ LOCAL_SHARED_LIBRARIES := \ 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 fb6ba7dbf..8694d21c8 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 diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 1ce75eaae..f8f124136 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -28,12 +28,13 @@ #include +#include #include #include #include -#include #include +#include #include #include @@ -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 @@ static float mtxRot90[16] = { 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 @@ GLConsumer::GLConsumer(GLuint tex, bool allowSynchronousMode, 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 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { 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 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { "%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 @@ status_t GLConsumer::doGLFenceWaitLocked() const { } 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 bafd21aae..bc0c83c55 100644 --- a/libs/gui/GuiConfig.cpp +++ b/libs/gui/GuiConfig.cpp @@ -22,14 +22,8 @@ void appendGuiConfigString(String8& configStr) { 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 000000000..e5804a77b --- /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 +#include + +#include +#include +#include + +#include + +EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); + +namespace android { + +ANDROID_SINGLETON_STATIC_INSTANCE(SyncFeatures); + +SyncFeatures::SyncFeatures() : Singleton(), + 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 diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp index 50b08b071..1be4961e3 100644 --- a/opengl/libs/EGL/eglApi.cpp +++ b/opengl/libs/EGL/eglApi.cpp @@ -52,8 +52,6 @@ using namespace android; // ---------------------------------------------------------------------------- -#define EGL_VERSION_HW_ANDROID 0x3143 - namespace android { struct extention_map_t { @@ -1021,12 +1019,29 @@ const char* eglQueryString(EGLDisplay dpy, EGLint name) return dp->getExtensionString(); case EGL_CLIENT_APIS: return dp->getClientApiString(); - case EGL_VERSION_HW_ANDROID: - return dp->disp.queryString.version; } return setError(EGL_BAD_PARAMETER, (const char *)0); } +EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) +{ + clearError(); + + const egl_display_ptr dp = validate_display(dpy); + if (!dp) return (const char *) NULL; + + switch (name) { + case EGL_VENDOR: + return dp->disp.queryString.vendor; + case EGL_VERSION: + return dp->disp.queryString.version; + case EGL_EXTENSIONS: + return dp->disp.queryString.extensions; + case EGL_CLIENT_APIS: + return dp->disp.queryString.clientApi; + } + return setError(EGL_BAD_PARAMETER, (const char *)0); +} // ---------------------------------------------------------------------------- // EGL 1.1 diff --git a/services/surfaceflinger/GLExtensions.cpp b/services/surfaceflinger/GLExtensions.cpp index 0cbf4b10c..e5fb083a8 100644 --- a/services/surfaceflinger/GLExtensions.cpp +++ b/services/surfaceflinger/GLExtensions.cpp @@ -80,7 +80,7 @@ void GLExtensions::initWithGLStrings( mHaveDirectTexture = true; } #else -#warning "EGL_ANDROID_image_native_buffer not supported" +#error "EGL_ANDROID_image_native_buffer not supported" #endif if (hasExtension("GL_ARB_texture_non_power_of_two")) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0a210f7ac..3ed8b1b2e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -53,6 +53,7 @@ #include #include +#include #include "clz.h" #include "DdmConnection.h" @@ -68,11 +69,10 @@ #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" - -#define EGL_VERSION_HW_ANDROID 0x3143 - #define DISPLAY_COUNT 1 +EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); + namespace android { // --------------------------------------------------------------------------- @@ -2280,6 +2280,10 @@ void SurfaceFlinger::dumpAllLocked( appendGuiConfigString(result); result.append("\n"); + result.append("Sync configuration: "); + result.append(SyncFeatures::getInstance().toString()); + result.append("\n"); + /* * Dump the visible layer list */ @@ -2313,17 +2317,20 @@ void SurfaceFlinger::dumpAllLocked( HWComposer& hwc(getHwComposer()); sp hw(getDefaultDisplayDevice()); const GLExtensions& extensions(GLExtensions::getInstance()); + + snprintf(buffer, SIZE, "EGL implementation : %s\n", + eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION)); + result.append(buffer); + snprintf(buffer, SIZE, "%s\n", + eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS)); + result.append(buffer); + snprintf(buffer, SIZE, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(), extensions.getVersion()); result.append(buffer); - - snprintf(buffer, SIZE, "EGL : %s\n", - eglQueryString(mEGLDisplay, EGL_VERSION_HW_ANDROID)); - result.append(buffer); - - snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension()); + snprintf(buffer, SIZE, "%s\n", extensions.getExtension()); result.append(buffer); hw->undefinedRegion.dump(result, "undefinedRegion"); diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index e42707244..286925050 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -19,10 +19,11 @@ #include "SurfaceFlingerConsumer.h" +#include + #include #include - namespace android { // --------------------------------------------------------------------------- @@ -78,7 +79,7 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter) return err; } - if (!sUseNativeFenceSync) { + if (!SyncFeatures::getInstance().useNativeFenceSync()) { // Bind the new buffer to the GL texture. // // Older devices require the "implicit" synchronization provided