diff options
author | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-03 14:44:55 +0000 |
---|---|---|
committer | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-03 14:44:55 +0000 |
commit | f6c292fff1959661d15b27915d77f65964457e10 (patch) | |
tree | 5fdc07355cdfbe9f0dd4374b5c6b0b012613cdea /ui/gl | |
parent | eb4319e9a9d5088660f465b652c54b187bf951c8 (diff) | |
download | chromium_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.cc | 27 | ||||
-rw-r--r-- | ui/gl/gl_context.h | 26 | ||||
-rw-r--r-- | ui/gl/gl_fence.cc | 59 | ||||
-rw-r--r-- | ui/gl/gl_fence.h | 7 | ||||
-rw-r--r-- | ui/gl/gl_gl_api_implementation.cc | 25 | ||||
-rw-r--r-- | ui/gl/gl_gl_api_implementation.h | 9 |
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_; |