Fence.h revision 405436021da156fbe3c5d4de48bdefa564cf7fc0
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
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
114