summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'gpu')
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.cc72
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.h20
2 files changed, 91 insertions, 1 deletions
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index a6442e9..09e6478 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -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 @@ void GpuScheduler::PutChanged() {
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 @@ void GpuScheduler::SetCommandProcessedCallback(
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();
+
+ fence.task = task;
+
+ unschedule_fences_.push(fence);
+}
+
+GpuScheduler::UnscheduleFence::UnscheduleFence() : fence(0) {
+}
+
+GpuScheduler::UnscheduleFence::~UnscheduleFence() {
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h
index 32b072c..5c7cfe0 100644
--- a/gpu/command_buffer/service/gpu_scheduler.h
+++ b/gpu/command_buffer/service/gpu_scheduler.h
@@ -5,9 +5,12 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_
#define GPU_COMMAND_BUFFER_SERVICE_GPU_SCHEDULER_H_
+#include <queue>
+
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/shared_memory.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
@@ -20,7 +23,9 @@ namespace gpu {
// a command buffer and forwarded to a command parser. TODO(apatrick): This
// class should not know about the decoder. Do not add additional dependencies
// on it.
-class GpuScheduler : public CommandBufferEngine {
+class GpuScheduler
+ : public CommandBufferEngine,
+ public base::SupportsWeakPtr<GpuScheduler> {
public:
GpuScheduler(CommandBuffer* command_buffer,
gles2::GLES2Decoder* decoder,
@@ -51,6 +56,8 @@ class GpuScheduler : public CommandBufferEngine {
void SetCommandProcessedCallback(Callback0::Type* callback);
+ void DeferToFence(base::Closure task);
+
private:
// The GpuScheduler holds a weak reference to the CommandBuffer. The
@@ -71,6 +78,17 @@ class GpuScheduler : public CommandBufferEngine {
// Greater than zero if this is waiting to be rescheduled before continuing.
int unscheduled_count_;
+ // 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();
+
+ uint32 fence;
+ base::Closure task;
+ };
+ std::queue<UnscheduleFence> unschedule_fences_;
+
scoped_ptr<Callback0::Type> scheduled_callback_;
scoped_ptr<Callback0::Type> command_processed_callback_;
};