• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
Fence()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      */
~Fence()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:
mTimeout(timeout)97     AutoFence(EGLTimeKHR timeout = Fence::kDefaultTimeout): mTimeout(timeout) {
98     }
99 
~AutoFence()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