• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/gl/gl_fence.h"
6 
7 #include "base/compiler_specific.h"
8 #include "ui/gl/gl_bindings.h"
9 #include "ui/gl/gl_context.h"
10 
11 namespace {
12 
13 class GLFenceNVFence: public gfx::GLFence {
14  public:
GLFenceNVFence(bool flush)15   GLFenceNVFence(bool flush) {
16     // What if either of these GL calls fails? TestFenceNV will return true.
17     // See spec:
18     // http://www.opengl.org/registry/specs/NV/fence.txt
19     //
20     // What should happen if TestFenceNV is called for a name before SetFenceNV
21     // is called?
22     //     We generate an INVALID_OPERATION error, and return TRUE.
23     //     This follows the semantics for texture object names before
24     //     they are bound, in that they acquire their state upon binding.
25     //     We will arbitrarily return TRUE for consistency.
26     glGenFencesNV(1, &fence_);
27     glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
28     if (flush)
29       glFlush();
30   }
31 
HasCompleted()32   virtual bool HasCompleted() OVERRIDE {
33     return !!glTestFenceNV(fence_);
34   }
35 
ClientWait()36   virtual void ClientWait() OVERRIDE {
37     glFinishFenceNV(fence_);
38   }
39 
ServerWait()40   virtual void ServerWait() OVERRIDE {
41     glFinishFenceNV(fence_);
42   }
43 
44  private:
~GLFenceNVFence()45   virtual ~GLFenceNVFence() {
46     glDeleteFencesNV(1, &fence_);
47   }
48 
49   GLuint fence_;
50 };
51 
52 class GLFenceARBSync: public gfx::GLFence {
53  public:
GLFenceARBSync(bool flush)54   GLFenceARBSync(bool flush) {
55     sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
56     if (flush)
57       glFlush();
58   }
59 
HasCompleted()60   virtual bool HasCompleted() OVERRIDE {
61     // Handle the case where FenceSync failed.
62     if (!sync_)
63       return true;
64 
65     // We could potentially use glGetSynciv here, but it doesn't work
66     // on OSX 10.7 (always says the fence is not signaled yet).
67     // glClientWaitSync works better, so let's use that instead.
68     return  glClientWaitSync(sync_, 0, 0) != GL_TIMEOUT_EXPIRED;
69   }
70 
ClientWait()71   virtual void ClientWait() OVERRIDE {
72     glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
73   }
74 
ServerWait()75   virtual void ServerWait() OVERRIDE {
76     glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
77   }
78 
79  private:
~GLFenceARBSync()80   virtual ~GLFenceARBSync() {
81     glDeleteSync(sync_);
82   }
83 
84   GLsync sync_;
85 };
86 
87 #if !defined(OS_MACOSX)
88 class EGLFenceSync : public gfx::GLFence {
89  public:
EGLFenceSync(bool flush)90   EGLFenceSync(bool flush) {
91     display_ = eglGetCurrentDisplay();
92     sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL);
93     if (flush)
94       glFlush();
95   }
96 
HasCompleted()97   virtual bool HasCompleted() OVERRIDE {
98     EGLint value = 0;
99     eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value);
100     DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR);
101     return !value || value == EGL_SIGNALED_KHR;
102   }
103 
ClientWait()104   virtual void ClientWait() OVERRIDE {
105     EGLint flags = 0;
106     EGLTimeKHR time = EGL_FOREVER_KHR;
107     eglClientWaitSyncKHR(display_, sync_, flags, time);
108   }
109 
ServerWait()110   virtual void ServerWait() OVERRIDE {
111     EGLint flags = 0;
112     eglWaitSyncKHR(display_, sync_, flags);
113   }
114 
115 
116  private:
~EGLFenceSync()117   virtual ~EGLFenceSync() {
118     eglDestroySyncKHR(display_, sync_);
119   }
120 
121   EGLSyncKHR sync_;
122   EGLDisplay display_;
123 };
124 #endif // !OS_MACOSX
125 
126 // static
CreateFence(bool flush)127 gfx::GLFence* CreateFence(bool flush) {
128 #if !defined(OS_MACOSX)
129   if (gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync)
130     return new EGLFenceSync(flush);
131 #endif
132   if (gfx::g_driver_gl.ext.b_GL_NV_fence)
133     return new GLFenceNVFence(flush);
134   if (gfx::g_driver_gl.ext.b_GL_ARB_sync)
135     return new GLFenceARBSync(flush);
136   return NULL;
137 }
138 
139 }  // namespace
140 
141 namespace gfx {
142 
GLFence()143 GLFence::GLFence() {
144 }
145 
~GLFence()146 GLFence::~GLFence() {
147 }
148 
Create()149 GLFence* GLFence::Create() {
150   return CreateFence(true);
151 }
152 
CreateWithoutFlush()153 GLFence* GLFence::CreateWithoutFlush() {
154   return CreateFence(false);
155 }
156 
157 }  // namespace gfx
158