| /* | |
| ** 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 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> | |
| namespace android { | |
| ANDROID_SINGLETON_STATIC_INSTANCE(SyncFeatures); | |
| SyncFeatures::SyncFeatures() : Singleton<SyncFeatures>(), | |
| mHasNativeFenceSync(false), | |
| mHasFenceSync(false), | |
| mHasWaitSync(false) { | |
| EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); | |
| // eglQueryString can only be called after EGL has been initialized; | |
| // otherwise the check below will abort. If RenderEngine is using SkiaVk, | |
| // EGL will not have been initialized. There's no problem with initializing | |
| // it again here (it is ref counted), and then terminating it later. | |
| EGLBoolean initialized = eglInitialize(dpy, nullptr, nullptr); | |
| LOG_ALWAYS_FATAL_IF(!initialized, "eglInitialize failed"); | |
| const char* exts = eglQueryString(dpy, EGL_EXTENSIONS); | |
| LOG_ALWAYS_FATAL_IF(exts == nullptr, "eglQueryString 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("]"); | |
| // Terminate EGL to match the eglInitialize above | |
| eglTerminate(dpy); | |
| } | |
| 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 { | |
| return !mHasNativeFenceSync && mHasFenceSync; | |
| } | |
| bool SyncFeatures::useWaitSync() const { | |
| return (useNativeFenceSync() || useFenceSync()) && mHasWaitSync; | |
| } | |
| String8 SyncFeatures::toString() const { | |
| return mString; | |
| } | |
| } // namespace android |