summaryrefslogtreecommitdiffstats
path: root/ui/gl
diff options
context:
space:
mode:
authorsievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-03 14:44:55 +0000
committersievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-03 14:44:55 +0000
commitf6c292fff1959661d15b27915d77f65964457e10 (patch)
tree5fdc07355cdfbe9f0dd4374b5c6b0b012613cdea /ui/gl
parenteb4319e9a9d5088660f465b652c54b187bf951c8 (diff)
downloadchromium_src-f6c292fff1959661d15b27915d77f65964457e10.zip
chromium_src-f6c292fff1959661d15b27915d77f65964457e10.tar.gz
chromium_src-f6c292fff1959661d15b27915d77f65964457e10.tar.bz2
Revert r258965 aka reland r258122
gpu: Allow fences to check whether a flush has occurred This skips waiting on a fence that was created but never committed. BUG=352419,355275 TBR=piman@chromium.org > Original Review URL: https://codereview.chromium.org/197563003 Review URL: https://codereview.chromium.org/222103008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261383 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gl')
-rw-r--r--ui/gl/gl_context.cc27
-rw-r--r--ui/gl/gl_context.h26
-rw-r--r--ui/gl/gl_fence.cc59
-rw-r--r--ui/gl/gl_fence.h7
-rw-r--r--ui/gl/gl_gl_api_implementation.cc25
-rw-r--r--ui/gl/gl_gl_api_implementation.h9
6 files changed, 139 insertions, 14 deletions
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
index baa20fa..533b7d3 100644
--- a/ui/gl/gl_context.cc
+++ b/ui/gl/gl_context.cc
@@ -38,6 +38,20 @@ void GLContext::ScopedReleaseCurrent::Cancel() {
canceled_ = true;
}
+GLContext::FlushEvent::FlushEvent() {
+}
+
+GLContext::FlushEvent::~FlushEvent() {
+}
+
+void GLContext::FlushEvent::Signal() {
+ flag_.Set();
+}
+
+bool GLContext::FlushEvent::IsSignaled() {
+ return flag_.IsSet();
+}
+
GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) {
if (!share_group_.get())
share_group_ = new GLShareGroup;
@@ -52,6 +66,13 @@ GLContext::~GLContext() {
}
}
+scoped_refptr<GLContext::FlushEvent> GLContext::SignalFlush() {
+ DCHECK(IsCurrent(NULL));
+ scoped_refptr<FlushEvent> flush_event = new FlushEvent();
+ flush_events_.push_back(flush_event);
+ return flush_event;
+}
+
bool GLContext::GetTotalGpuMemory(size_t* bytes) {
DCHECK(bytes);
*bytes = 0;
@@ -190,6 +211,12 @@ void GLContext::SetRealGLApi() {
SetGLToRealGLApi();
}
+void GLContext::OnFlush() {
+ for (size_t n = 0; n < flush_events_.size(); n++)
+ flush_events_[n]->Signal();
+ flush_events_.clear();
+}
+
GLContextReal::GLContextReal(GLShareGroup* share_group)
: GLContext(share_group) {}
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h
index 63589c7..323b373 100644
--- a/ui/gl/gl_context.h
+++ b/ui/gl/gl_context.h
@@ -6,10 +6,12 @@
#define UI_GL_GL_CONTEXT_H_
#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/cancellation_flag.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_state_restorer.h"
#include "ui/gl/gpu_preference.h"
@@ -32,6 +34,25 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
virtual bool Initialize(
GLSurface* compatible_surface, GpuPreference gpu_preference) = 0;
+ class FlushEvent : public base::RefCountedThreadSafe<FlushEvent> {
+ public:
+ bool IsSignaled();
+
+ private:
+ friend class base::RefCountedThreadSafe<FlushEvent>;
+ friend class GLContext;
+ FlushEvent();
+ virtual ~FlushEvent();
+ void Signal();
+
+ base::CancellationFlag flag_;
+ };
+
+ // Needs to be called with this context current. It will return a FlushEvent
+ // that is initially unsignaled, but will transition to signaled after the
+ // next glFlush() or glFinish() occurs in this context.
+ scoped_refptr<FlushEvent> SignalFlush();
+
// Destroys the GL context.
virtual void Destroy() = 0;
@@ -114,6 +135,9 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
// Returns the GL renderer string. The context must be current.
virtual std::string GetGLRenderer();
+ // Called when glFlush()/glFinish() is called with this context current.
+ void OnFlush();
+
protected:
virtual ~GLContext();
@@ -152,6 +176,8 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
scoped_ptr<GLStateRestorer> state_restorer_;
scoped_ptr<GLVersionInfo> version_info_;
+ std::vector<scoped_refptr<FlushEvent> > flush_events_;
+
DISALLOW_COPY_AND_ASSIGN(GLContext);
};
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
index f44570e..262de48 100644
--- a/ui/gl/gl_fence.cc
+++ b/ui/gl/gl_fence.cc
@@ -25,8 +25,11 @@ class GLFenceNVFence: public gfx::GLFence {
// We will arbitrarily return TRUE for consistency.
glGenFencesNV(1, &fence_);
glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
- if (flush)
+ if (flush) {
glFlush();
+ } else {
+ flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
+ }
}
virtual bool HasCompleted() OVERRIDE {
@@ -34,11 +37,15 @@ class GLFenceNVFence: public gfx::GLFence {
}
virtual void ClientWait() OVERRIDE {
- glFinishFenceNV(fence_);
+ if (!flush_event_ || flush_event_->IsSignaled()) {
+ glFinishFenceNV(fence_);
+ } else {
+ LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+ }
}
virtual void ServerWait() OVERRIDE {
- glFinishFenceNV(fence_);
+ ClientWait();
}
private:
@@ -47,14 +54,18 @@ class GLFenceNVFence: public gfx::GLFence {
}
GLuint fence_;
+ scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
};
class GLFenceARBSync: public gfx::GLFence {
public:
GLFenceARBSync(bool flush) {
sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- if (flush)
+ if (flush) {
glFlush();
+ } else {
+ flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
+ }
}
virtual bool HasCompleted() OVERRIDE {
@@ -69,11 +80,19 @@ class GLFenceARBSync: public gfx::GLFence {
}
virtual void ClientWait() OVERRIDE {
- glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+ if (!flush_event_ || flush_event_->IsSignaled()) {
+ glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
+ } else {
+ LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+ }
}
virtual void ServerWait() OVERRIDE {
- glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
+ if (!flush_event_ || flush_event_->IsSignaled()) {
+ glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
+ } else {
+ LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+ }
}
private:
@@ -82,6 +101,7 @@ class GLFenceARBSync: public gfx::GLFence {
}
GLsync sync_;
+ scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
};
#if !defined(OS_MACOSX)
@@ -90,8 +110,11 @@ class EGLFenceSync : public gfx::GLFence {
EGLFenceSync(bool flush) {
display_ = eglGetCurrentDisplay();
sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL);
- if (flush)
+ if (flush) {
glFlush();
+ } else {
+ flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
+ }
}
virtual bool HasCompleted() OVERRIDE {
@@ -102,14 +125,22 @@ class EGLFenceSync : public gfx::GLFence {
}
virtual void ClientWait() OVERRIDE {
- EGLint flags = 0;
- EGLTimeKHR time = EGL_FOREVER_KHR;
- eglClientWaitSyncKHR(display_, sync_, flags, time);
+ if (!flush_event_ || flush_event_->IsSignaled()) {
+ EGLint flags = 0;
+ EGLTimeKHR time = EGL_FOREVER_KHR;
+ eglClientWaitSyncKHR(display_, sync_, flags, time);
+ } else {
+ LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+ }
}
virtual void ServerWait() OVERRIDE {
- EGLint flags = 0;
- eglWaitSyncKHR(display_, sync_, flags);
+ if (!flush_event_ || flush_event_->IsSignaled()) {
+ EGLint flags = 0;
+ eglWaitSyncKHR(display_, sync_, flags);
+ } else {
+ LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
+ }
}
@@ -120,11 +151,15 @@ class EGLFenceSync : public gfx::GLFence {
EGLSyncKHR sync_;
EGLDisplay display_;
+ scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
};
#endif // !OS_MACOSX
// static
gfx::GLFence* CreateFence(bool flush) {
+ DCHECK(gfx::GLContext::GetCurrent())
+ << "Trying to create fence with no context";
+
#if !defined(OS_MACOSX)
if (gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync)
return new EGLFenceSync(flush);
diff --git a/ui/gl/gl_fence.h b/ui/gl/gl_fence.h
index c1967ec..021f345 100644
--- a/ui/gl/gl_fence.h
+++ b/ui/gl/gl_fence.h
@@ -16,11 +16,16 @@ class GL_EXPORT GLFence {
virtual ~GLFence();
static GLFence* Create();
+
// Creates a fence that is not guaranteed to signal until the current context
- // is flushed. Use with caution.
+ // is flushed. It is illegal to call Client/ServerWait() on a fence without
+ // having explicitly called glFlush() or glFinish() in the originating
+ // context.
static GLFence* CreateWithoutFlush();
+
virtual bool HasCompleted() = 0;
virtual void ClientWait() = 0;
+
// Will block the server if supported, but might fall back to blocking the
// client.
virtual void ServerWait() = 0;
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index 9d57247..fd5309c 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -355,6 +355,11 @@ void GLApiBase::InitializeBase(DriverGL* driver) {
driver_ = driver;
}
+void GLApiBase::SignalFlush() {
+ DCHECK(GLContext::GetCurrent());
+ GLContext::GetCurrent()->OnFlush();
+}
+
RealGLApi::RealGLApi() {
}
@@ -365,6 +370,16 @@ void RealGLApi::Initialize(DriverGL* driver) {
InitializeBase(driver);
}
+void RealGLApi::glFlushFn() {
+ GLApiBase::glFlushFn();
+ GLApiBase::SignalFlush();
+}
+
+void RealGLApi::glFinishFn() {
+ GLApiBase::glFinishFn();
+ GLApiBase::SignalFlush();
+}
+
TraceGLApi::~TraceGLApi() {
}
@@ -463,4 +478,14 @@ const GLubyte* VirtualGLApi::glGetStringFn(GLenum name) {
}
}
+void VirtualGLApi::glFlushFn() {
+ GLApiBase::glFlushFn();
+ GLApiBase::SignalFlush();
+}
+
+void VirtualGLApi::glFinishFn() {
+ GLApiBase::glFinishFn();
+ GLApiBase::SignalFlush();
+}
+
} // namespace gfx
diff --git a/ui/gl/gl_gl_api_implementation.h b/ui/gl/gl_gl_api_implementation.h
index d189691..aff5926 100644
--- a/ui/gl/gl_gl_api_implementation.h
+++ b/ui/gl/gl_gl_api_implementation.h
@@ -41,6 +41,7 @@ class GLApiBase : public GLApi {
GLApiBase();
virtual ~GLApiBase();
void InitializeBase(DriverGL* driver);
+ void SignalFlush();
DriverGL* driver_;
};
@@ -51,6 +52,10 @@ class RealGLApi : public GLApiBase {
RealGLApi();
virtual ~RealGLApi();
void Initialize(DriverGL* driver);
+
+ private:
+ virtual void glFinishFn() OVERRIDE;
+ virtual void glFlushFn() OVERRIDE;
};
// Inserts a TRACE for every GL call.
@@ -94,10 +99,12 @@ class VirtualGLApi : public GLApiBase {
void OnReleaseVirtuallyCurrent(GLContext* virtual_context);
+private:
// Overridden functions from GLApiBase
virtual const GLubyte* glGetStringFn(GLenum name) OVERRIDE;
+ virtual void glFinishFn() OVERRIDE;
+ virtual void glFlushFn() OVERRIDE;
- private:
// The real context we're running on.
GLContext* real_context_;