1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_HWUI_FENCE_H 18 #define ANDROID_HWUI_FENCE_H 19 20 #include <EGL/egl.h> 21 #include <EGL/eglext.h> 22 23 namespace android { 24 namespace uirenderer { 25 26 /** 27 * Creating a Fence instance inserts a new sync fence in the OpenGL 28 * commands stream. The caller can then wait for the fence to be signaled 29 * by calling the wait method. 30 */ 31 class Fence { 32 public: 33 enum { 34 /** 35 * Default timeout in nano-seconds for wait() 36 */ 37 kDefaultTimeout = 1000000000 38 }; 39 40 /** 41 * Inserts a new sync fence in the OpenGL commands stream. 42 */ 43 Fence() { 44 mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 45 if (mDisplay != EGL_NO_DISPLAY) { 46 mFence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL); 47 } else { 48 mFence = EGL_NO_SYNC_KHR; 49 } 50 } 51 52 /** 53 * Destroys the fence. Any caller waiting on the fence will be 54 * signaled immediately. 55 */ 56 ~Fence() { 57 if (mFence != EGL_NO_SYNC_KHR) { 58 eglDestroySyncKHR(mDisplay, mFence); 59 } 60 } 61 62 /** 63 * Blocks the calling thread until this fence is signaled, or until 64 * <timeout> nanoseconds have passed. 65 * 66 * Returns true if waiting for the fence was successful, false if 67 * a timeout or an error occurred. 68 */ 69 bool wait(EGLTimeKHR timeout = kDefaultTimeout) { 70 EGLint waitStatus = eglClientWaitSyncKHR(mDisplay, mFence, 71 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, timeout); 72 if (waitStatus == EGL_FALSE) { 73 ALOGW("Failed to wait for the fence %#x", eglGetError()); 74 } 75 return waitStatus == EGL_CONDITION_SATISFIED_KHR; 76 } 77 78 private: 79 EGLDisplay mDisplay; 80 EGLSyncKHR mFence; 81 82 }; // class Fence 83 84 /** 85 * An AutoFence creates a Fence instance and waits for the fence 86 * to be signaled when the AutoFence is destroyed. This is useful 87 * to automatically wait for a series of OpenGL commands to be 88 * executed. For example: 89 * 90 * void drawAndWait() { 91 * glDrawElements(); 92 * AutoFence fence; 93 * } 94 */ 95 class AutoFence { 96 public: 97 AutoFence(EGLTimeKHR timeout = Fence::kDefaultTimeout): mTimeout(timeout) { 98 } 99 100 ~AutoFence() { 101 mFence.wait(mTimeout); 102 } 103 104 private: 105 EGLTimeKHR mTimeout; 106 Fence mFence; 107 108 }; // class AutoFence 109 110 }; // namespace uirenderer 111 }; // namespace android 112 113 #endif // ANDROID_HWUI_FENCE_H 114