1405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy/*
2405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * Copyright (C) 2013 The Android Open Source Project
3405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy *
4405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * you may not use this file except in compliance with the License.
6405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * You may obtain a copy of the License at
7405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy *
8405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy *
10405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * Unless required by applicable law or agreed to in writing, software
11405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * See the License for the specific language governing permissions and
14405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * limitations under the License.
15405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy */
16405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
17405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy#ifndef ANDROID_HWUI_FENCE_H
18405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy#define ANDROID_HWUI_FENCE_H
19405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
20405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy#include <EGL/egl.h>
21405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy#include <EGL/eglext.h>
22405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
23405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guynamespace android {
24405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guynamespace uirenderer {
25405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
26405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy/**
27405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * Creating a Fence instance inserts a new sync fence in the OpenGL
28405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * commands stream. The caller can then wait for the fence to be signaled
29405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * by calling the wait method.
30405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy */
31405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guyclass Fence {
32405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guypublic:
33405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    enum {
34405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        /**
35405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy         * Default timeout in nano-seconds for wait()
36405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy         */
37405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        kDefaultTimeout = 1000000000
38405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    };
39405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
40405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    /**
41405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     * Inserts a new sync fence in the OpenGL commands stream.
42405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     */
43405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    Fence() {
44405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
45405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        if (mDisplay != EGL_NO_DISPLAY) {
46405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy            mFence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL);
47405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        } else {
48405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy            mFence = EGL_NO_SYNC_KHR;
49405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        }
50405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    }
51405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
52405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    /**
53405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     * Destroys the fence. Any caller waiting on the fence will be
54405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     * signaled immediately.
55405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     */
56405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    ~Fence() {
57405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        if (mFence != EGL_NO_SYNC_KHR) {
58405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy            eglDestroySyncKHR(mDisplay, mFence);
59405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        }
60405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    }
61405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
62405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    /**
63405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     * Blocks the calling thread until this fence is signaled, or until
64405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     * <timeout> nanoseconds have passed.
65405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     *
66405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     * Returns true if waiting for the fence was successful, false if
67405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     * a timeout or an error occurred.
68405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy     */
69405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    bool wait(EGLTimeKHR timeout = kDefaultTimeout) {
70405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        EGLint waitStatus = eglClientWaitSyncKHR(mDisplay, mFence,
71405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy                EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, timeout);
72405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        if (waitStatus == EGL_FALSE) {
73405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy            ALOGW("Failed to wait for the fence %#x", eglGetError());
74405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        }
75405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        return waitStatus == EGL_CONDITION_SATISFIED_KHR;
76405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    }
77405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
78405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guyprivate:
79405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    EGLDisplay mDisplay;
80405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    EGLSyncKHR mFence;
81405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
82405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy}; // class Fence
83405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
84405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy/**
85405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * An AutoFence creates a Fence instance and waits for the fence
86405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * to be signaled when the AutoFence is destroyed. This is useful
87405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * to automatically wait for a series of OpenGL commands to be
88405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * executed. For example:
89405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy *
90405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * void drawAndWait() {
91405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy *     glDrawElements();
92405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy *     AutoFence fence;
93405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy * }
94405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy */
95405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guyclass AutoFence {
96405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guypublic:
97405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    AutoFence(EGLTimeKHR timeout = Fence::kDefaultTimeout): mTimeout(timeout) {
98405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    }
99405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
100405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    ~AutoFence() {
101405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy        mFence.wait(mTimeout);
102405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    }
103405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
104405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guyprivate:
105405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    EGLTimeKHR mTimeout;
106405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy    Fence mFence;
107405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
108405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy}; // class AutoFence
109405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
110405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy}; // namespace uirenderer
111405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy}; // namespace android
112405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy
113405436021da156fbe3c5d4de48bdefa564cf7fc0Romain Guy#endif // ANDROID_HWUI_FENCE_H
114