Index: gpu/command_buffer/service/gpu_scheduler.cc |
=================================================================== |
--- gpu/command_buffer/service/gpu_scheduler.cc (revision 106933) |
+++ gpu/command_buffer/service/gpu_scheduler.cc (working copy) |
@@ -4,6 +4,7 @@ |
#include "gpu/command_buffer/service/gpu_scheduler.h" |
+#include "base/bind.h" |
#include "base/callback.h" |
#include "base/command_line.h" |
#include "base/compiler_specific.h" |
@@ -18,6 +19,9 @@ |
using ::base::SharedMemory; |
namespace gpu { |
+namespace { |
+const uint64 kPollFencePeriod = 1; |
+} |
GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, |
gles2::GLES2Decoder* decoder, |
@@ -56,8 +60,44 @@ |
if (state.error != error::kNoError) |
return; |
+ // Check that the GPU has passed all fences. |
+ if (!unschedule_fences_.empty()) { |
+ if (glGenFencesNV) { |
+ while (!unschedule_fences_.empty()) { |
+ if (glTestFenceNV(unschedule_fences_.front().fence)) { |
+ glDeleteFencesNV(1, &unschedule_fences_.front().fence); |
+ unschedule_fences_.front().task.Run(); |
+ unschedule_fences_.pop(); |
+ } else { |
+ SetScheduled(false); |
+ MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&GpuScheduler::SetScheduled, AsWeakPtr(), true), |
+ kPollFencePeriod); |
+ return; |
+ } |
+ } |
+ } else { |
+ // Hopefully no recent drivers don't support GL_NV_fence and this will |
+ // not happen in practice. |
+ glFinish(); |
+ |
+ while (!unschedule_fences_.empty()) { |
+ unschedule_fences_.front().task.Run(); |
+ unschedule_fences_.pop(); |
+ } |
+ } |
+ } |
+ |
+ // One of the unschedule fence tasks might have unscheduled us. |
+ if (!IsScheduled()) |
+ return; |
+ |
error::Error error = error::kNoError; |
while (!parser_->IsEmpty()) { |
+ DCHECK(IsScheduled()); |
+ DCHECK(unschedule_fences_.empty()); |
+ |
error = parser_->ProcessCommand(); |
// TODO(piman): various classes duplicate various pieces of state, leading |
@@ -127,4 +167,36 @@ |
command_processed_callback_.reset(callback); |
} |
+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 (glGenFencesNV) { |
+ glGenFencesNV(1, &fence.fence); |
+ glSetFenceNV(fence.fence, GL_ALL_COMPLETED_NV); |
+ } |
+ |
+ glFlush(); |
apatrick_chromium
2011/10/25 00:54:45
I might as well flush here in the no GL_NV_fence c
|
+ |
+ fence.task = task; |
+ |
+ unschedule_fences_.push(fence); |
+} |
+ |
+GpuScheduler::UnscheduleFence::UnscheduleFence() : fence(0) { |
+} |
+ |
+GpuScheduler::UnscheduleFence::~UnscheduleFence() { |
+} |
+ |
} // namespace gpu |