Home | History | Annotate | Download | only in hwui
      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