diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-16 13:42:45 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-16 13:42:45 +0000 |
commit | 6d76ba379fef00cbeed525a7911b89400b0ed853 (patch) | |
tree | f6682fc9df873dd242d406f26f9d0eec57831d25 /gpu/command_buffer | |
parent | 87256b85c8176ee543e44a32f29be009fe313a7e (diff) | |
download | chromium_src-6d76ba379fef00cbeed525a7911b89400b0ed853.zip chromium_src-6d76ba379fef00cbeed525a7911b89400b0ed853.tar.gz chromium_src-6d76ba379fef00cbeed525a7911b89400b0ed853.tar.bz2 |
Don't tell browser to swap until swap actually executed.
By deferring to fence, we're ensuring that the GL commands are executed GPU side before sending a message to the browser to act on them. This is lighter weight than a glFinish because the other commands buffers on the channel (e.g. WebGL) can continue executing while we're waiting for the fence.
TEST=by hand building use_aura running http://webglsamples.googlecode.com/hg/aquarium/aquarium.html
Review URL: http://codereview.chromium.org/8497015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114798 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
-rw-r--r-- | gpu/command_buffer/common/gl_mock.h | 8 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.cc | 44 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.h | 12 |
3 files changed, 29 insertions, 35 deletions
diff --git a/gpu/command_buffer/common/gl_mock.h b/gpu/command_buffer/common/gl_mock.h index ae2259d..8ebb4c3 100644 --- a/gpu/command_buffer/common/gl_mock.h +++ b/gpu/command_buffer/common/gl_mock.h @@ -472,6 +472,14 @@ class MockGLInterface : public GLInterface { MOCK_METHOD3(GetFenceivNV, void(GLuint fence, GLenum pname, GLint *params)); + MOCK_METHOD2(FenceSync, GLsync(GLenum condition, GLbitfield flags)); + + MOCK_METHOD1(DeleteSync, void(GLsync sync)); + + MOCK_METHOD5(GetSynciv, void( + GLsync sync, GLenum pname, GLsizei bufSize, + GLsizei* length, GLint* values)); + MOCK_METHOD1(SetSurfaceCHROMIUM, void(GLuint)); MOCK_METHOD0(GetGraphicsResetStatusARB, GLenum()); diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc index e294dcf..cff93f2 100644 --- a/gpu/command_buffer/service/gpu_scheduler.cc +++ b/gpu/command_buffer/service/gpu_scheduler.cc @@ -11,6 +11,7 @@ #include "base/message_loop.h" #include "base/time.h" #include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_fence.h" #include "ui/gfx/gl/gl_switches.h" using ::base::SharedMemory; @@ -154,48 +155,28 @@ void GpuScheduler::SetCommandProcessedCallback( } void GpuScheduler::DeferToFence(base::Closure task) { - UnscheduleFence fence; - - // What if either of these GL calls fails? TestFenceNV will return true and - // PutChanged will treat the fence as having been crossed and thereby not - // poll indefinately. 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. - if (gfx::g_GL_NV_fence) { - glGenFencesNV(1, &fence.fence); - glSetFenceNV(fence.fence, GL_ALL_COMPLETED_NV); - } - - glFlush(); - - fence.task = task; - - unschedule_fences_.push(fence); + unschedule_fences_.push(make_linked_ptr( + new UnscheduleFence(gfx::GLFence::Create(), task))); } bool GpuScheduler::PollUnscheduleFences() { - if (gfx::g_GL_NV_fence) { + if (unschedule_fences_.empty()) + return true; + + if (unschedule_fences_.front()->fence.get()) { while (!unschedule_fences_.empty()) { - if (glTestFenceNV(unschedule_fences_.front().fence)) { - glDeleteFencesNV(1, &unschedule_fences_.front().fence); - unschedule_fences_.front().task.Run(); + if (unschedule_fences_.front()->fence->HasCompleted()) { + unschedule_fences_.front()->task.Run(); unschedule_fences_.pop(); } else { return false; } } } else { - if (!unschedule_fences_.empty()) - glFinish(); + glFinish(); while (!unschedule_fences_.empty()) { - unschedule_fences_.front().task.Run(); + unschedule_fences_.front()->task.Run(); unschedule_fences_.pop(); } } @@ -203,7 +184,8 @@ bool GpuScheduler::PollUnscheduleFences() { return true; } -GpuScheduler::UnscheduleFence::UnscheduleFence() : fence(0) { +GpuScheduler::UnscheduleFence::UnscheduleFence( + gfx::GLFence* fence_, base::Closure task_): fence(fence_), task(task_) { } GpuScheduler::UnscheduleFence::~UnscheduleFence() { diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h index 3a33da4..46afc60 100644 --- a/gpu/command_buffer/service/gpu_scheduler.h +++ b/gpu/command_buffer/service/gpu_scheduler.h @@ -8,8 +8,8 @@ #include <queue> #include "base/callback.h" -#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" #include "base/shared_memory.h" #include "gpu/command_buffer/common/command_buffer.h" @@ -17,6 +17,10 @@ #include "gpu/command_buffer/service/cmd_parser.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +namespace gfx { +class GLFence; +} + namespace gpu { // This class schedules commands that have been flushed. They are received via @@ -95,13 +99,13 @@ class GpuScheduler // The GpuScheduler will unschedule itself in the event that further GL calls // are issued to it before all these fences have been crossed by the GPU. struct UnscheduleFence { - UnscheduleFence(); + UnscheduleFence(gfx::GLFence* fence, base::Closure task); ~UnscheduleFence(); - uint32 fence; + scoped_ptr<gfx::GLFence> fence; base::Closure task; }; - std::queue<UnscheduleFence> unschedule_fences_; + std::queue<linked_ptr<UnscheduleFence> > unschedule_fences_; base::Closure scheduled_callback_; base::Closure command_processed_callback_; |