Chromium Code Reviews| 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 |