diff options
-rw-r--r-- | content/common/gpu/gpu_channel.cc | 19 | ||||
-rw-r--r-- | content/common/gpu/gpu_channel.h | 6 | ||||
-rw-r--r-- | content/common/gpu/gpu_command_buffer_stub.cc | 3 | ||||
-rw-r--r-- | gpu/command_buffer/common/constants.h | 6 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 19 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.h | 5 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_mock.h | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.cc | 5 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.h | 7 |
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(); } |