blob: f175e98eea632e4ed2bdfe066d0d9c86756ce9cd [file] [log] [blame]
Romain Guy40543602013-06-12 15:31:28 -07001/*
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
23namespace android {
24namespace 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 */
31class Fence {
32public:
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
78private:
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 */
95class AutoFence {
96public:
97 AutoFence(EGLTimeKHR timeout = Fence::kDefaultTimeout): mTimeout(timeout) {
98 }
99
100 ~AutoFence() {
101 mFence.wait(mTimeout);
102 }
103
104private:
105 EGLTimeKHR mTimeout;
106 Fence mFence;
107
108}; // class AutoFence
109
110}; // namespace uirenderer
111}; // namespace android
112
113#endif // ANDROID_HWUI_FENCE_H