OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gl/gl_fence.h" | 5 #include "ui/gl/gl_fence.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "ui/gl/gl_bindings.h" | 8 #include "ui/gl/gl_bindings.h" |
9 #include "ui/gl/gl_context.h" | 9 #include "ui/gl/gl_context.h" |
10 #include "ui/gl/gl_gl_api_implementation.h" | |
10 #include "ui/gl/gl_version_info.h" | 11 #include "ui/gl/gl_version_info.h" |
11 | 12 |
13 namespace gfx { | |
14 | |
12 namespace { | 15 namespace { |
13 | 16 |
14 class GLFenceNVFence: public gfx::GLFence { | 17 class GLFenceNVFence: public GLFence { |
15 public: | 18 public: |
16 GLFenceNVFence(bool flush) { | 19 GLFenceNVFence(bool flush) { |
17 // What if either of these GL calls fails? TestFenceNV will return true. | 20 // What if either of these GL calls fails? TestFenceNV will return true. |
18 // See spec: | 21 // See spec: |
19 // http://www.opengl.org/registry/specs/NV/fence.txt | 22 // http://www.opengl.org/registry/specs/NV/fence.txt |
20 // | 23 // |
21 // What should happen if TestFenceNV is called for a name before SetFenceNV | 24 // What should happen if TestFenceNV is called for a name before SetFenceNV |
22 // is called? | 25 // is called? |
23 // We generate an INVALID_OPERATION error, and return TRUE. | 26 // We generate an INVALID_OPERATION error, and return TRUE. |
24 // This follows the semantics for texture object names before | 27 // This follows the semantics for texture object names before |
25 // they are bound, in that they acquire their state upon binding. | 28 // they are bound, in that they acquire their state upon binding. |
26 // We will arbitrarily return TRUE for consistency. | 29 // We will arbitrarily return TRUE for consistency. |
27 glGenFencesNV(1, &fence_); | 30 glGenFencesNV(1, &fence_); |
28 glSetFenceNV(fence_, GL_ALL_COMPLETED_NV); | 31 glSetFenceNV(fence_, GL_ALL_COMPLETED_NV); |
29 if (flush) { | 32 if (flush) { |
30 glFlush(); | 33 glFlush(); |
31 } else { | 34 } else { |
32 flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush(); | 35 flush_event_ = GLContext::GetCurrent()->SignalFlush(); |
33 } | 36 } |
34 } | 37 } |
35 | 38 |
36 virtual bool HasCompleted() OVERRIDE { | 39 virtual bool HasCompleted() OVERRIDE { |
37 return !!glTestFenceNV(fence_); | 40 return !!glTestFenceNV(fence_); |
38 } | 41 } |
39 | 42 |
40 virtual void ClientWait() OVERRIDE { | 43 virtual void ClientWait() OVERRIDE { |
41 if (!flush_event_ || flush_event_->IsSignaled()) { | 44 if (!flush_event_ || flush_event_->IsSignaled()) { |
42 glFinishFenceNV(fence_); | 45 glFinishFenceNV(fence_); |
43 } else { | 46 } else { |
44 LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping..."; | 47 LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping..."; |
45 } | 48 } |
46 } | 49 } |
47 | 50 |
48 virtual void ServerWait() OVERRIDE { | 51 virtual void ServerWait() OVERRIDE { |
49 ClientWait(); | 52 ClientWait(); |
50 } | 53 } |
51 | 54 |
52 private: | 55 private: |
53 virtual ~GLFenceNVFence() { | 56 virtual ~GLFenceNVFence() { |
54 glDeleteFencesNV(1, &fence_); | 57 glDeleteFencesNV(1, &fence_); |
55 } | 58 } |
56 | 59 |
57 GLuint fence_; | 60 GLuint fence_; |
58 scoped_refptr<gfx::GLContext::FlushEvent> flush_event_; | 61 scoped_refptr<GLContext::FlushEvent> flush_event_; |
59 }; | 62 }; |
60 | 63 |
61 class GLFenceARBSync: public gfx::GLFence { | 64 class GLFenceARBSync: public GLFence { |
62 public: | 65 public: |
63 GLFenceARBSync(bool flush) { | 66 GLFenceARBSync(bool flush) { |
64 sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); | 67 sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); |
65 if (flush) { | 68 if (flush) { |
66 glFlush(); | 69 glFlush(); |
67 } else { | 70 } else { |
68 flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush(); | 71 flush_event_ = GLContext::GetCurrent()->SignalFlush(); |
69 } | 72 } |
70 } | 73 } |
71 | 74 |
72 virtual bool HasCompleted() OVERRIDE { | 75 virtual bool HasCompleted() OVERRIDE { |
73 // Handle the case where FenceSync failed. | 76 // Handle the case where FenceSync failed. |
74 if (!sync_) | 77 if (!sync_) |
75 return true; | 78 return true; |
76 | 79 |
77 // We could potentially use glGetSynciv here, but it doesn't work | 80 // We could potentially use glGetSynciv here, but it doesn't work |
78 // on OSX 10.7 (always says the fence is not signaled yet). | 81 // on OSX 10.7 (always says the fence is not signaled yet). |
(...skipping 16 matching lines...) Expand all Loading... | |
95 LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping..."; | 98 LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping..."; |
96 } | 99 } |
97 } | 100 } |
98 | 101 |
99 private: | 102 private: |
100 virtual ~GLFenceARBSync() { | 103 virtual ~GLFenceARBSync() { |
101 glDeleteSync(sync_); | 104 glDeleteSync(sync_); |
102 } | 105 } |
103 | 106 |
104 GLsync sync_; | 107 GLsync sync_; |
105 scoped_refptr<gfx::GLContext::FlushEvent> flush_event_; | 108 scoped_refptr<GLContext::FlushEvent> flush_event_; |
106 }; | 109 }; |
107 | 110 |
108 #if !defined(OS_MACOSX) | 111 #if !defined(OS_MACOSX) |
109 class EGLFenceSync : public gfx::GLFence { | 112 class EGLFenceSync : public GLFence { |
110 public: | 113 public: |
111 EGLFenceSync(bool flush) { | 114 EGLFenceSync(bool flush) { |
112 display_ = eglGetCurrentDisplay(); | 115 display_ = eglGetCurrentDisplay(); |
113 sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL); | 116 sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL); |
114 if (flush) { | 117 if (flush) { |
115 glFlush(); | 118 glFlush(); |
116 } else { | 119 } else { |
117 flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush(); | 120 flush_event_ = GLContext::GetCurrent()->SignalFlush(); |
118 } | 121 } |
119 } | 122 } |
120 | 123 |
121 virtual bool HasCompleted() OVERRIDE { | 124 virtual bool HasCompleted() OVERRIDE { |
122 EGLint value = 0; | 125 EGLint value = 0; |
123 eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value); | 126 eglGetSyncAttribKHR(display_, sync_, EGL_SYNC_STATUS_KHR, &value); |
124 DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR); | 127 DCHECK(value == EGL_SIGNALED_KHR || value == EGL_UNSIGNALED_KHR); |
125 return !value || value == EGL_SIGNALED_KHR; | 128 return !value || value == EGL_SIGNALED_KHR; |
126 } | 129 } |
127 | 130 |
(...skipping 17 matching lines...) Expand all Loading... | |
145 } | 148 } |
146 | 149 |
147 | 150 |
148 private: | 151 private: |
149 virtual ~EGLFenceSync() { | 152 virtual ~EGLFenceSync() { |
150 eglDestroySyncKHR(display_, sync_); | 153 eglDestroySyncKHR(display_, sync_); |
151 } | 154 } |
152 | 155 |
153 EGLSyncKHR sync_; | 156 EGLSyncKHR sync_; |
154 EGLDisplay display_; | 157 EGLDisplay display_; |
155 scoped_refptr<gfx::GLContext::FlushEvent> flush_event_; | 158 scoped_refptr<GLContext::FlushEvent> flush_event_; |
156 }; | 159 }; |
157 #endif // !OS_MACOSX | 160 #endif // !OS_MACOSX |
158 | 161 |
159 // static | 162 // static |
160 gfx::GLFence* CreateFence(bool flush) { | 163 GLFence* CreateFence(bool flush) { |
161 DCHECK(gfx::GLContext::GetCurrent()) | 164 DCHECK(GLContext::GetCurrent()) |
162 << "Trying to create fence with no context"; | 165 << "Trying to create fence with no context"; |
163 | 166 |
167 scoped_ptr<GLFence> fence; | |
164 // Prefer ARB_sync which supports server-side wait. | 168 // Prefer ARB_sync which supports server-side wait. |
165 if (gfx::g_driver_gl.ext.b_GL_ARB_sync || | 169 if (g_driver_gl.ext.b_GL_ARB_sync || |
166 gfx::GLContext::GetCurrent()->GetVersionInfo()->is_es3) | 170 GetGLVersionInfo()->is_es3) { |
167 return new GLFenceARBSync(flush); | 171 fence.reset(new GLFenceARBSync(flush)); |
168 #if !defined(OS_MACOSX) | 172 #if !defined(OS_MACOSX) |
169 if (gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) | 173 } else if (g_driver_egl.ext.b_EGL_KHR_fence_sync) { |
170 return new EGLFenceSync(flush); | 174 fence.reset(new EGLFenceSync(flush)); |
171 #endif | 175 #endif |
172 if (gfx::g_driver_gl.ext.b_GL_NV_fence) | 176 } else if (g_driver_gl.ext.b_GL_NV_fence) { |
173 return new GLFenceNVFence(flush); | 177 fence.reset(new GLFenceNVFence(flush)); |
174 return NULL; | 178 } |
179 | |
180 DCHECK(!!fence.get() == GLFence::IsSupported()); | |
reveman
2014/06/17 00:50:05
DCHECK_EQ?
| |
181 return fence.release(); | |
175 } | 182 } |
176 | 183 |
177 } // namespace | 184 } // namespace |
178 | 185 |
179 namespace gfx { | |
180 | |
181 GLFence::GLFence() { | 186 GLFence::GLFence() { |
182 } | 187 } |
183 | 188 |
184 GLFence::~GLFence() { | 189 GLFence::~GLFence() { |
185 } | 190 } |
186 | 191 |
192 bool GLFence::IsSupported() { | |
193 DCHECK(GetGLVersionInfo()); | |
194 return g_driver_gl.ext.b_GL_ARB_sync || GetGLVersionInfo()->is_es3 || | |
195 #if !defined(OS_MACOSX) | |
196 g_driver_egl.ext.b_EGL_KHR_fence_sync || | |
197 #endif | |
198 g_driver_gl.ext.b_GL_NV_fence; | |
199 } | |
200 | |
187 GLFence* GLFence::Create() { | 201 GLFence* GLFence::Create() { |
188 return CreateFence(true); | 202 return CreateFence(true); |
189 } | 203 } |
190 | 204 |
191 GLFence* GLFence::CreateWithoutFlush() { | 205 GLFence* GLFence::CreateWithoutFlush() { |
192 return CreateFence(false); | 206 return CreateFence(false); |
193 } | 207 } |
194 | 208 |
195 } // namespace gfx | 209 } // namespace gfx |
OLD | NEW |