summaryrefslogtreecommitdiffstats
path: root/ui/gl/gl_fence.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ui/gl/gl_fence.cc')
-rw-r--r--ui/gl/gl_fence.cc108
1 files changed, 108 insertions, 0 deletions
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
new file mode 100644
index 0000000..82cdf30
--- /dev/null
+++ b/ui/gl/gl_fence.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_fence.h"
+
+#include "base/compiler_specific.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+
+namespace {
+
+class GLFenceNVFence: public gfx::GLFence {
+ public:
+ GLFenceNVFence() {
+ // What if either of these GL calls fails? TestFenceNV will return true.
+ // See spec:
+ // http://www.opengl.org/registry/specs/NV/fence.txt
+ //
+ // What should happen if TestFenceNV is called for a name before SetFenceNV
+ // is called?
+ // We generate an INVALID_OPERATION error, and return TRUE.
+ // This follows the semantics for texture object names before
+ // they are bound, in that they acquire their state upon binding.
+ // We will arbitrarily return TRUE for consistency.
+ glGenFencesNV(1, &fence_);
+ glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
+ glFlush();
+ }
+
+ virtual bool HasCompleted() OVERRIDE {
+ return IsContextLost() || glTestFenceNV(fence_);
+ }
+
+ private:
+ ~GLFenceNVFence() {
+ glDeleteFencesNV(1, &fence_);
+ }
+
+ GLuint fence_;
+};
+
+class GLFenceARBSync: public gfx::GLFence {
+ public:
+ GLFenceARBSync() {
+ sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ }
+
+ virtual bool HasCompleted() OVERRIDE {
+ // Handle the case where FenceSync failed.
+ if (!sync_ || IsContextLost())
+ return true;
+
+ GLsizei length = 0;
+ GLsizei value = 0;
+ glGetSynciv(sync_,
+ GL_SYNC_STATUS,
+ 1, // bufSize
+ &length,
+ &value);
+ return length == 1 && value == GL_SIGNALED;
+ }
+
+ private:
+ ~GLFenceARBSync() {
+ glDeleteSync(sync_);
+ }
+
+ GLsync sync_;
+};
+
+} // namespace
+
+namespace gfx {
+
+GLFence::GLFence() {
+}
+
+GLFence::~GLFence() {
+}
+
+// static
+GLFence* GLFence::Create() {
+ if (gfx::g_GL_NV_fence) {
+ return new GLFenceNVFence();
+ } else if (gfx::g_GL_ARB_sync) {
+ return new GLFenceARBSync();
+ } else {
+ return NULL;
+ }
+}
+
+// static
+bool GLFence::IsContextLost() {
+ if (!gfx::g_GL_ARB_robustness)
+ return false;
+
+ if (!gfx::GLContext::GetCurrent() ||
+ !gfx::GLContext::GetCurrent()->
+ WasAllocatedUsingARBRobustness())
+ return false;
+
+ GLenum status = glGetGraphicsResetStatusARB();
+ return status != GL_NO_ERROR;
+}
+
+} // namespace gfx