summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer
diff options
context:
space:
mode:
authorbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-16 13:42:45 +0000
committerbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-16 13:42:45 +0000
commit6d76ba379fef00cbeed525a7911b89400b0ed853 (patch)
treef6682fc9df873dd242d406f26f9d0eec57831d25 /gpu/command_buffer
parent87256b85c8176ee543e44a32f29be009fe313a7e (diff)
downloadchromium_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.h8
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.cc44
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.h12
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_;