Chromium Code Reviews| 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 |