summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/common/gpu/gpu_channel.cc19
-rw-r--r--content/common/gpu/gpu_channel.h6
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.cc3
-rw-r--r--gpu/command_buffer/common/constants.h6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc19
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.h5
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_mock.h1
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.cc5
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.h7
9 files changed, 64 insertions, 7 deletions
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc
index 21b6d06..0da5925 100644
--- a/content/common/gpu/gpu_channel.cc
+++ b/content/common/gpu/gpu_channel.cc
@@ -55,6 +55,25 @@ void GpuChannel::DestroyTransportTexture(int32 route_id) {
router_.RemoveRoute(route_id);
}
+void GpuChannel::OnLatchCallback(int route_id, bool is_set_latch) {
+#if defined(ENABLE_GPU)
+ if (is_set_latch) {
+ // Wake up any waiting contexts. If they are still blocked, they will re-add
+ // themselves to the set.
+ for (std::set<int32>::iterator i = latched_routes_.begin();
+ i != latched_routes_.end(); ++i) {
+ GpuCommandBufferStub* stub = stubs_.Lookup(*i);
+ if (stub)
+ stub->scheduler()->ScheduleProcessCommands();
+ }
+ latched_routes_.clear();
+ } else {
+ // Add route_id context to a set to be woken upon any set latch.
+ latched_routes_.insert(route_id);
+ }
+#endif
+}
+
bool GpuChannel::OnMessageReceived(const IPC::Message& message) {
if (log_messages_) {
VLOG(1) << "received message @" << &message << " on channel @" << this
diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h
index 012656e..05af1ca 100644
--- a/content/common/gpu/gpu_channel.h
+++ b/content/common/gpu/gpu_channel.h
@@ -89,6 +89,11 @@ class GpuChannel : public IPC::Channel::Listener,
// TransportTexture to delete and detach itself.
void DestroyTransportTexture(int32 route_id);
+ // A callback which is called after a Set/WaitLatch command is processed.
+ // The bool parameter will be true for SetLatch, and false for a WaitLatch
+ // that is blocked. An unblocked WaitLatch will not trigger a callback.
+ void OnLatchCallback(int route_id, bool is_set_latch);
+
private:
bool OnControlMessageReceived(const IPC::Message& msg);
@@ -131,6 +136,7 @@ class GpuChannel : public IPC::Channel::Listener,
#if defined(ENABLE_GPU)
typedef IDMap<GpuCommandBufferStub, IDMapOwnPointer> StubMap;
StubMap stubs_;
+ std::set<int32> latched_routes_;
#endif // defined (ENABLE_GPU)
// A collection of transport textures created.
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index 94c8c6f..42e086d 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -4,6 +4,7 @@
#if defined(ENABLE_GPU)
+#include "base/bind.h"
#include "base/process_util.h"
#include "base/shared_memory.h"
#include "build/build_config.h"
@@ -258,6 +259,8 @@ void GpuCommandBufferStub::OnInitialize(
&gpu::GpuScheduler::ProcessCommands));
scheduler_->SetSwapBuffersCallback(
NewCallback(this, &GpuCommandBufferStub::OnSwapBuffers));
+ scheduler_->SetLatchCallback(
+ base::Bind(&GpuChannel::OnLatchCallback, channel_, route_id_));
if (watchdog_)
scheduler_->SetCommandProcessedCallback(
NewCallback(this, &GpuCommandBufferStub::OnCommandProcessed));
diff --git a/gpu/command_buffer/common/constants.h b/gpu/command_buffer/common/constants.h
index bebc046..6ef22aa 100644
--- a/gpu/command_buffer/common/constants.h
+++ b/gpu/command_buffer/common/constants.h
@@ -23,9 +23,9 @@ namespace error {
kLostContext,
kGenericError,
- // This is not an error. It is returned by commands that want to
- // be called again until they return a different error. For
- // example: WaitLatch.
+ // This is not an error. It is returned by WaitLatch when it is blocked.
+ // When blocked, the context will not reschedule itself until another
+ // context executes a SetLatch command.
kWaiting,
// This is not an error. It is returned by commands to mark a position
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 2c0de18..9e14183 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -686,6 +686,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback);
virtual void SetSwapBuffersCallback(Callback0::Type* callback);
+ virtual void SetLatchCallback(const base::Callback<void(bool)>& callback);;
virtual bool GetServiceTextureId(uint32 client_texture_id,
uint32* service_texture_id);
@@ -1447,6 +1448,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
scoped_ptr<Callback1<gfx::Size>::Type> resize_callback_;
scoped_ptr<Callback0::Type> swap_buffers_callback_;
+ base::Callback<void(bool)> latch_callback_;
// The format of the back buffer_
GLenum back_buffer_color_format_;
@@ -2458,6 +2460,11 @@ void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
swap_buffers_callback_.reset(callback);
}
+void GLES2DecoderImpl::SetLatchCallback(
+ const base::Callback<void(bool)>& callback) {
+ latch_callback_ = callback;
+}
+
bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
uint32* service_texture_id) {
TextureManager::TextureInfo* texture =
@@ -6398,7 +6405,9 @@ error::Error GLES2DecoderImpl::HandleSetLatchCHROMIUM(
if (!latch) {
return error::kOutOfBounds;
}
- *latch = 1;
+ base::subtle::NoBarrier_Store(latch, 1);
+ if (!latch_callback_.is_null())
+ latch_callback_.Run(true);
return error::kNoError;
}
@@ -6419,7 +6428,13 @@ error::Error GLES2DecoderImpl::HandleWaitLatchCHROMIUM(
base::subtle::Atomic32 old =
base::subtle::NoBarrier_CompareAndSwap(latch, 1, 0);
- return (old == 0) ? error::kWaiting : error::kNoError;
+ if (old == 0) {
+ if (!latch_callback_.is_null())
+ latch_callback_.Run(false);
+ return error::kWaiting;
+ } else {
+ return error::kNoError;
+ }
}
error::Error GLES2DecoderImpl::HandleCommandBufferEnableCHROMIUM(
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 1646c90..cb28d21 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -103,6 +103,11 @@ class GLES2Decoder : public CommonDecoder {
// Sets a callback which is called when a SwapBuffers command is processed.
virtual void SetSwapBuffersCallback(Callback0::Type* callback) = 0;
+ // Sets a callback which is called after a Set/WaitLatch command is processed.
+ // The bool parameter will be true for SetLatch, and false for a WaitLatch
+ // that is blocked. An unblocked WaitLatch will not trigger a callback.
+ virtual void SetLatchCallback(const base::Callback<void(bool)>& callback) = 0;
+
// Get the service texture ID corresponding to a client texture ID.
// If no such record is found then return false.
virtual bool GetServiceTextureId(uint32 client_texture_id,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 37a7e72..3ab6f06 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -43,6 +43,7 @@ class MockGLES2Decoder : public GLES2Decoder {
MOCK_METHOD0(GetContextGroup, ContextGroup*());
MOCK_METHOD1(SetResizeCallback, void(Callback1<gfx::Size>::Type*));
MOCK_METHOD1(SetSwapBuffersCallback, void(Callback0::Type*));
+ MOCK_METHOD1(SetLatchCallback, void(const base::Callback<void(bool)>&));
MOCK_METHOD3(DoCommand, error::Error(unsigned int command,
unsigned int arg_count,
const void* cmd_data));
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index 933b468..1ae36c4 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -166,9 +166,10 @@ void GpuScheduler::ProcessCommands() {
throttle_fences_.pop();
}
+ error::Error error = error::kNoError;
int commands_processed = 0;
while (commands_processed < commands_per_update_ && !parser_->IsEmpty()) {
- error::Error error = parser_->ProcessCommand();
+ error = parser_->ProcessCommand();
if (error == error::kWaiting) {
break;
}
@@ -201,7 +202,7 @@ void GpuScheduler::ProcessCommands() {
command_buffer_->SetGetOffset(static_cast<int32>(parser_->get()));
- if (!parser_->IsEmpty()) {
+ if (error != error::kWaiting && !parser_->IsEmpty()) {
ScheduleProcessCommands();
}
}
diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h
index 5ed808c..36cc009 100644
--- a/gpu/command_buffer/service/gpu_scheduler.h
+++ b/gpu/command_buffer/service/gpu_scheduler.h
@@ -114,6 +114,13 @@ class GpuScheduler : public CommandBufferEngine {
virtual void SetCommandProcessedCallback(Callback0::Type* callback);
+ // Sets a callback which is called after a Set/WaitLatch command is processed.
+ // The bool parameter will be true for SetLatch, and false for a WaitLatch
+ // that is blocked. An unblocked WaitLatch will not trigger a callback.
+ void SetLatchCallback(const base::Callback<void(bool)>& callback) {
+ decoder_->SetLatchCallback(callback);
+ }
+
// Get the GLES2Decoder associated with this scheduler.
gles2::GLES2Decoder* decoder() const { return decoder_.get(); }