diff options
23 files changed, 346 insertions, 536 deletions
diff --git a/chrome/common/command_buffer_messages.h b/chrome/common/command_buffer_messages.h index 2c586d0..7e3ae9c 100644 --- a/chrome/common/command_buffer_messages.h +++ b/chrome/common/command_buffer_messages.h @@ -5,6 +5,39 @@ #ifndef CHROME_COMMON_COMMAND_BUFFER_MESSAGES_H_ #define CHROME_COMMON_COMMAND_BUFFER_MESSAGES_H_ +#include "chrome/common/common_param_traits.h" +#include "gpu/command_buffer/common/command_buffer.h" + +namespace IPC { +template <> +struct ParamTraits<gpu::CommandBuffer::State> { + typedef gpu::CommandBuffer::State param_type; + static void Write(Message* m, const param_type& p) { + m->WriteInt(p.size); + m->WriteInt(p.get_offset); + m->WriteInt(p.put_offset); + m->WriteInt(p.token); + m->WriteInt(p.error); + } + static bool Read(const Message* m, void** iter, param_type* p) { + int32 temp; + if (m->ReadInt(iter, &p->size) && + m->ReadInt(iter, &p->get_offset) && + m->ReadInt(iter, &p->put_offset) && + m->ReadInt(iter, &p->token) && + m->ReadInt(iter, &temp)) { + p->error = static_cast<gpu::parse_error::ParseError>(temp); + return true; + } else { + return false; + } + } + static void Log(const param_type& p, std::wstring* l) { + l->append(L"<CommandBuffer::State>"); + } +}; +} // namespace IPC + #define MESSAGES_INTERNAL_FILE "chrome/common/command_buffer_messages_internal.h" #include "ipc/ipc_message_macros.h" diff --git a/chrome/common/command_buffer_messages_internal.h b/chrome/common/command_buffer_messages_internal.h index cbcda79..274223b5 100644 --- a/chrome/common/command_buffer_messages_internal.h +++ b/chrome/common/command_buffer_messages_internal.h @@ -13,23 +13,16 @@ IPC_BEGIN_MESSAGES(CommandBuffer) int32 /* size */, base::SharedMemoryHandle /* ring_buffer */) - // Get the number of command entries in the command buffer. - IPC_SYNC_MESSAGE_ROUTED0_1(CommandBufferMsg_GetSize, - int32 /* size */) + // Get the current state of the command buffer, optionally reseting the + // parse error. + IPC_SYNC_MESSAGE_ROUTED0_1(CommandBufferMsg_GetState, + gpu::CommandBuffer::State /* state */) // Synchronize the put and get offsets of both processes. Caller passes its // current put offset. Current get offset is returned. - IPC_SYNC_MESSAGE_ROUTED1_1(CommandBufferMsg_SyncOffsets, + IPC_SYNC_MESSAGE_ROUTED1_1(CommandBufferMsg_Flush, int32 /* put_offset */, - int32 /* get_offset */) - - // Get the current get offset. - IPC_SYNC_MESSAGE_ROUTED0_1(CommandBufferMsg_GetGetOffset, - int32 /* get_offset */) - - // Get the current put offset. - IPC_SYNC_MESSAGE_ROUTED0_1(CommandBufferMsg_GetPutOffset, - int32 /* put_offset */) + gpu::CommandBuffer::State /* state */) // Create a shared memory transfer buffer. Returns an id that can be used to // identify the transfer buffer from a comment. @@ -48,19 +41,4 @@ IPC_BEGIN_MESSAGES(CommandBuffer) base::SharedMemoryHandle /* transfer_buffer */, size_t /* size */) - // Get the most recently processed token. Used for implementing fences. - IPC_SYNC_MESSAGE_ROUTED0_1(CommandBufferMsg_GetToken, - int32 /* token */) - - // Get the current parse error. Calling this resets the parse error if it is - // recoverable. - // TODO(apatrick): Switch to the parse_error::ParseError enum now that NPAPI - // no longer limits to restricted set of datatypes. - IPC_SYNC_MESSAGE_ROUTED0_1(CommandBufferMsg_ResetParseError, - int32 /* parse_error */) - - // Get the current error status. - IPC_SYNC_MESSAGE_ROUTED0_1(CommandBufferMsg_GetErrorStatus, - bool /* status */) - IPC_END_MESSAGES(CommandBuffer) diff --git a/chrome/plugin/command_buffer_stub.cc b/chrome/plugin/command_buffer_stub.cc index 4a9dd5c..4b062e8 100644 --- a/chrome/plugin/command_buffer_stub.cc +++ b/chrome/plugin/command_buffer_stub.cc @@ -69,16 +69,13 @@ void CommandBufferStub::OnInitialize(int32 size, base::CloseProcessHandle(peer_handle); } -void CommandBufferStub::OnSyncOffsets(int32 put_offset, int32* get_offset) { - *get_offset = command_buffer_->SyncOffsets(put_offset); +void CommandBufferStub::OnGetState(gpu::CommandBuffer::State* state) { + *state = command_buffer_->GetState(); } -void CommandBufferStub::OnGetGetOffset(int32* get_offset) { - *get_offset = command_buffer_->GetGetOffset(); -} - -void CommandBufferStub::OnGetPutOffset(int32* put_offset) { - *put_offset = command_buffer_->GetPutOffset(); +void CommandBufferStub::OnFlush(int32 put_offset, + gpu::CommandBuffer::State* state) { + *state = command_buffer_->Flush(put_offset); } void CommandBufferStub::OnCreateTransferBuffer(int32 size, int32* id) { @@ -111,33 +108,17 @@ void CommandBufferStub::OnGetTransferBuffer( base::CloseProcessHandle(peer_handle); } -void CommandBufferStub::OnGetToken(int32* token) { - *token = command_buffer_->GetToken(); -} - -void CommandBufferStub::OnResetParseError(int32* parse_error) { - *parse_error = command_buffer_->ResetParseError(); -} - -void CommandBufferStub::OnGetErrorStatus(bool* error_status) { - *error_status = command_buffer_->GetErrorStatus(); -} - void CommandBufferStub::OnMessageReceived(const IPC::Message& msg) { IPC_BEGIN_MESSAGE_MAP(CommandBufferStub, msg) IPC_MESSAGE_HANDLER(CommandBufferMsg_Initialize, OnInitialize); - IPC_MESSAGE_HANDLER(CommandBufferMsg_SyncOffsets, OnSyncOffsets); - IPC_MESSAGE_HANDLER(CommandBufferMsg_GetGetOffset, OnGetGetOffset); - IPC_MESSAGE_HANDLER(CommandBufferMsg_GetPutOffset, OnGetPutOffset); + IPC_MESSAGE_HANDLER(CommandBufferMsg_GetState, OnGetState); + IPC_MESSAGE_HANDLER(CommandBufferMsg_Flush, OnFlush); IPC_MESSAGE_HANDLER(CommandBufferMsg_CreateTransferBuffer, OnCreateTransferBuffer); IPC_MESSAGE_HANDLER(CommandBufferMsg_DestroyTransferBuffer, OnDestroyTransferBuffer); IPC_MESSAGE_HANDLER(CommandBufferMsg_GetTransferBuffer, OnGetTransferBuffer); - IPC_MESSAGE_HANDLER(CommandBufferMsg_GetToken, OnGetToken); - IPC_MESSAGE_HANDLER(CommandBufferMsg_ResetParseError, OnResetParseError); - IPC_MESSAGE_HANDLER(CommandBufferMsg_GetErrorStatus, OnGetErrorStatus); IPC_MESSAGE_UNHANDLED_ERROR() IPC_END_MESSAGE_MAP() } diff --git a/chrome/plugin/command_buffer_stub.h b/chrome/plugin/command_buffer_stub.h index 4608d0e..1001ce9 100644 --- a/chrome/plugin/command_buffer_stub.h +++ b/chrome/plugin/command_buffer_stub.h @@ -9,6 +9,7 @@ #include "app/gfx/native_widget_types.h" #include "base/ref_counted.h" +#include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/gpu_processor.h" #include "ipc/ipc_channel.h" @@ -37,17 +38,13 @@ class CommandBufferStub : public IPC::Channel::Listener, private: // Message handlers: void OnInitialize(int32 size, base::SharedMemoryHandle* ring_buffer); - void OnSyncOffsets(int32 put_offset, int32* get_offset); - void OnGetGetOffset(int32* get_offset); - void OnGetPutOffset(int32* put_offset); + void OnGetState(gpu::CommandBuffer::State* state); + void OnFlush(int32 put_offset, gpu::CommandBuffer::State* state); void OnCreateTransferBuffer(int32 size, int32* id); void OnDestroyTransferBuffer(int32 id); void OnGetTransferBuffer(int32 id, base::SharedMemoryHandle* transfer_buffer, size_t* size); - void OnGetToken(int32* token); - void OnResetParseError(int32* parse_error); - void OnGetErrorStatus(bool* error_status); scoped_refptr<PluginChannel> channel_; gfx::PluginWindowHandle window_; diff --git a/chrome/renderer/command_buffer_proxy.cc b/chrome/renderer/command_buffer_proxy.cc index 5b97e3c..e63ca5a 100644 --- a/chrome/renderer/command_buffer_proxy.cc +++ b/chrome/renderer/command_buffer_proxy.cc @@ -71,27 +71,18 @@ Buffer CommandBufferProxy::GetRingBuffer() { return buffer; } -int32 CommandBufferProxy::GetSize() { - // Return locally cached size. - return size_; +gpu::CommandBuffer::State CommandBufferProxy::GetState() { + gpu::CommandBuffer::State state; + Send(new CommandBufferMsg_GetState(route_id_, &state)); + return state; } -int32 CommandBufferProxy::SyncOffsets(int32 put_offset) { - int32 get_offset; - if (Send(new CommandBufferMsg_SyncOffsets(route_id_, - put_offset, - &get_offset))) - return get_offset; - - return -1; -} - -int32 CommandBufferProxy::GetGetOffset() { - int32 get_offset; - if (Send(new CommandBufferMsg_GetGetOffset(route_id_, &get_offset))) - return get_offset; - - return -1; +gpu::CommandBuffer::State CommandBufferProxy::Flush(int32 put_offset) { + gpu::CommandBuffer::State state; + Send(new CommandBufferMsg_Flush(route_id_, + put_offset, + &state)); + return state; } void CommandBufferProxy::SetGetOffset(int32 get_offset) { @@ -99,14 +90,6 @@ void CommandBufferProxy::SetGetOffset(int32 get_offset) { NOTREACHED(); } -int32 CommandBufferProxy::GetPutOffset() { - int put_offset; - if (Send(new CommandBufferMsg_GetPutOffset(route_id_, &put_offset))) - return put_offset; - - return -1; -} - int32 CommandBufferProxy::CreateTransferBuffer(size_t size) { int32 id; if (Send(new CommandBufferMsg_CreateTransferBuffer(route_id_, size, &id))) @@ -176,41 +159,13 @@ Buffer CommandBufferProxy::GetTransferBuffer(int32 id) { return buffer; } -int32 CommandBufferProxy::GetToken() { - int32 token; - if (Send(new CommandBufferMsg_GetToken(route_id_, &token))) - return token; - - return -1; -} - void CommandBufferProxy::SetToken(int32 token) { // Not implemented in proxy. NOTREACHED(); } -int32 CommandBufferProxy::ResetParseError() { - int32 parse_error; - if (Send(new CommandBufferMsg_ResetParseError(route_id_, &parse_error))) - return parse_error; - - return -1; -} - -void CommandBufferProxy::SetParseError(int32 parse_error) { - // Not implemented in proxy. - NOTREACHED(); -} - -bool CommandBufferProxy::GetErrorStatus() { - bool status; - if (Send(new CommandBufferMsg_GetErrorStatus(route_id_, &status))) - return status; - - return true; -} - -void CommandBufferProxy::RaiseErrorStatus() { +void CommandBufferProxy::SetParseError( + gpu::parse_error::ParseError parse_error) { // Not implemented in proxy. NOTREACHED(); } diff --git a/chrome/renderer/command_buffer_proxy.h b/chrome/renderer/command_buffer_proxy.h index 0be704a..849f540 100644 --- a/chrome/renderer/command_buffer_proxy.h +++ b/chrome/renderer/command_buffer_proxy.h @@ -35,20 +35,14 @@ class CommandBufferProxy : public gpu::CommandBuffer, // CommandBuffer implementation: virtual bool Initialize(int32 size); virtual gpu::Buffer GetRingBuffer(); - virtual int32 GetSize(); - virtual int32 SyncOffsets(int32 put_offset); - virtual int32 GetGetOffset(); + virtual State GetState(); + virtual State Flush(int32 put_offset); virtual void SetGetOffset(int32 get_offset); - virtual int32 GetPutOffset(); virtual int32 CreateTransferBuffer(size_t size); virtual void DestroyTransferBuffer(int32 id); virtual gpu::Buffer GetTransferBuffer(int32 handle); - virtual int32 GetToken(); virtual void SetToken(int32 token); - virtual int32 ResetParseError(); - virtual void SetParseError(int32 parse_error); - virtual bool GetErrorStatus(); - virtual void RaiseErrorStatus(); + virtual void SetParseError(gpu::parse_error::ParseError parse_error); private: // As with the service, the client takes ownership of the ring buffer. diff --git a/chrome/renderer/webplugin_delegate_pepper.cc b/chrome/renderer/webplugin_delegate_pepper.cc index 68e611d..d25364f 100644 --- a/chrome/renderer/webplugin_delegate_pepper.cc +++ b/chrome/renderer/webplugin_delegate_pepper.cc @@ -352,13 +352,15 @@ NPError WebPluginDelegatePepper::Device3DInitializeContext( if (command_buffer_.get()) { // Initialize the proxy command buffer. if (command_buffer_->Initialize(config->commandBufferEntries)) { + // Get the initial command buffer state. + gpu::CommandBuffer::State state = command_buffer_->GetState(); + // Initialize the 3D context. context->reserved = NULL; Buffer ring_buffer = command_buffer_->GetRingBuffer(); context->commandBuffer = ring_buffer.ptr; - context->commandBufferEntries = command_buffer_->GetSize(); - context->getOffset = command_buffer_->GetGetOffset(); - context->putOffset = command_buffer_->GetPutOffset(); + context->commandBufferEntries = state.size; + Synchronize3DContext(context, state); // Ensure the service knows the window size before rendering anything. nested_delegate_->UpdateGeometry(window_rect_, clip_rect_); @@ -392,32 +394,7 @@ NPError WebPluginDelegatePepper::Device3DGetStateContext( NPDeviceContext3D* context, int32 state, int32* value) { -#if defined(ENABLE_GPU) - if (!command_buffer_.get()) - return NPERR_GENERIC_ERROR; - - switch (state) { - case NPDeviceContext3DState_GetOffset: - context->getOffset = *value = command_buffer_->GetGetOffset(); - break; - case NPDeviceContext3DState_PutOffset: - *value = command_buffer_->GetPutOffset(); - break; - case NPDeviceContext3DState_Token: - *value = command_buffer_->GetToken(); - break; - case NPDeviceContext3DState_ParseError: - *value = command_buffer_->ResetParseError(); - break; - case NPDeviceContext3DState_ErrorStatus: - *value = command_buffer_->GetErrorStatus() ? 1 : 0; - break; - default: - return NPERR_GENERIC_ERROR; - }; -#endif // ENABLE_GPU - - return NPERR_NO_ERROR; + return NPERR_GENERIC_ERROR; } NPError WebPluginDelegatePepper::Device3DFlushContext( @@ -426,8 +403,16 @@ NPError WebPluginDelegatePepper::Device3DFlushContext( NPDeviceFlushContextCallbackPtr callback, void* user_data) { #if defined(ENABLE_GPU) - DCHECK(callback == NULL); - context->getOffset = command_buffer_->SyncOffsets(context->putOffset); + gpu::CommandBuffer::State state; + // Only flush if new commands have been put in the command buffer. Otherwise + // update the state to the current service state. + if (context->putOffset == last_command_buffer_put_offset_) { + state = command_buffer_->GetState(); + } else { + last_command_buffer_put_offset_ = context->putOffset; + state = command_buffer_->Flush(context->putOffset); + } + Synchronize3DContext(context, state); #endif // ENABLE_GPU return NPERR_NO_ERROR; } @@ -556,7 +541,8 @@ WebPluginDelegatePepper::WebPluginDelegatePepper( : render_view_(render_view), plugin_(NULL), instance_(instance), - nested_delegate_(NULL) { + nested_delegate_(NULL), + last_command_buffer_put_offset_(-1) { // For now we keep a window struct, although it isn't used. memset(&window_, 0, sizeof(window_)); // All Pepper plugins are windowless and transparent. @@ -720,3 +706,14 @@ bool WebPluginDelegatePepper::HandleInputEvent(const WebInputEvent& event, } return instance()->NPP_HandleEvent(&npevent) != 0; } + +#if defined(ENABLE_GPU) +void WebPluginDelegatePepper::Synchronize3DContext( + NPDeviceContext3D* context, + gpu::CommandBuffer::State state) { + context->getOffset = state.get_offset; + context->putOffset = state.put_offset; + context->token = state.token; + context->error = static_cast<int32>(state.error); +} +#endif // ENABLE_GPU diff --git a/chrome/renderer/webplugin_delegate_pepper.h b/chrome/renderer/webplugin_delegate_pepper.h index 91e35b6..b2ac3c6 100644 --- a/chrome/renderer/webplugin_delegate_pepper.h +++ b/chrome/renderer/webplugin_delegate_pepper.h @@ -164,6 +164,12 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { // Closes down and destroys our plugin instance. void DestroyInstance(); +#if defined(ENABLE_GPU) + // Synchronize a 3D context state with the service. + void Synchronize3DContext(NPDeviceContext3D* context, + gpu::CommandBuffer::State state); +#endif + base::WeakPtr<RenderView> render_view_; webkit_glue::WebPlugin* plugin_; @@ -190,6 +196,10 @@ class WebPluginDelegatePepper : public webkit_glue::WebPluginDelegate { scoped_ptr<CommandBufferProxy> command_buffer_; #endif + // Used to track whether additional commands have been put in the command + // buffer since the last flush. + int32 last_command_buffer_put_offset_; + DISALLOW_COPY_AND_ASSIGN(WebPluginDelegatePepper); }; diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc index 0651ee6..d58338e 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -24,12 +24,11 @@ bool CommandBufferHelper::Initialize() { if (!ring_buffer_.ptr) return false; + CommandBuffer::State state = command_buffer_->GetState(); entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr); - entry_count_ = command_buffer_->GetSize(); - get_ = command_buffer_->GetGetOffset(); - put_ = command_buffer_->GetPutOffset(); - last_token_read_ = command_buffer_->GetToken(); - + entry_count_ = state.size; + put_ = state.put_offset; + SynchronizeState(state); return true; } @@ -37,8 +36,9 @@ CommandBufferHelper::~CommandBufferHelper() { } bool CommandBufferHelper::Flush() { - get_ = command_buffer_->SyncOffsets(put_); - return !command_buffer_->GetErrorStatus(); + CommandBuffer::State state = command_buffer_->Flush(put_); + SynchronizeState(state); + return state.error == parse_error::kParseNoError; } // Calls Flush() and then waits until the buffer is empty. Break early if the @@ -46,7 +46,7 @@ bool CommandBufferHelper::Flush() { bool CommandBufferHelper::Finish() { do { // Do not loop forever if the flush fails, meaning the command buffer reader - // has shutdown). + // has shutdown. if (!Flush()) return false; } while (put_ != get_); @@ -67,7 +67,6 @@ int32 CommandBufferHelper::InsertToken() { if (token_ == 0) { // we wrapped Finish(); - last_token_read_ = command_buffer_->GetToken(); DCHECK_EQ(token_, last_token_read_); } return token_; @@ -82,7 +81,6 @@ void CommandBufferHelper::WaitForToken(int32 token) { if (last_token_read_ >= token) return; // fast path. if (token > token_) return; // we wrapped Flush(); - last_token_read_ = command_buffer_->GetToken(); while (last_token_read_ < token) { if (get_ == put_) { LOG(FATAL) << "Empty command buffer while waiting on a token."; @@ -92,7 +90,6 @@ void CommandBufferHelper::WaitForToken(int32 token) { // has shutdown. if (!Flush()) return; - last_token_read_ = command_buffer_->GetToken(); } } @@ -145,9 +142,15 @@ CommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) { return space; } -parse_error::ParseError CommandBufferHelper::GetParseError() { - int32 parse_error = command_buffer_->ResetParseError(); - return static_cast<parse_error::ParseError>(parse_error); +parse_error::ParseError CommandBufferHelper::GetError() { + CommandBuffer::State state = command_buffer_->GetState(); + SynchronizeState(state); + return static_cast<parse_error::ParseError>(state.error); +} + +void CommandBufferHelper::SynchronizeState(CommandBuffer::State state) { + get_ = state.get_offset; + last_token_read_ = state.token; } } // namespace gpu diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h index df56e2e..d26d927 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.h +++ b/gpu/command_buffer/client/cmd_buffer_helper.h @@ -103,7 +103,7 @@ class CommandBufferHelper { return *reinterpret_cast<T*>(data); } - parse_error::ParseError GetParseError(); + parse_error::ParseError GetError(); // Common Commands void Noop(uint32 skip_count) { @@ -127,6 +127,9 @@ class CommandBufferHelper { return (get_ - put_ - 1 + entry_count_) % entry_count_; } + // Synchronize with current service state. + void SynchronizeState(CommandBuffer::State state); + CommandBuffer* command_buffer_; Buffer ring_buffer_; CommandBufferEntry *entries_; diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc index 96f7004..3134051 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc @@ -111,6 +111,18 @@ class CommandBufferHelperTest : public testing::Test { } } + int32 GetGetOffset() { + return command_buffer_->GetState().get_offset; + } + + int32 GetPutOffset() { + return command_buffer_->GetState().put_offset; + } + + parse_error::ParseError GetError() { + return command_buffer_->GetState().error; + } + CommandBufferOffset get_helper_put() { return helper_->put_; } base::AtExitManager at_exit_manager_; @@ -128,9 +140,8 @@ TEST_F(CommandBufferHelperTest, TestCommandProcessing) { // Check initial state of the engine - it should have been configured by the // helper. EXPECT_TRUE(parser_ != NULL); - EXPECT_FALSE(command_buffer_->GetErrorStatus()); - EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError()); - EXPECT_EQ(0, command_buffer_->GetGetOffset()); + EXPECT_EQ(parse_error::kParseNoError, GetError()); + EXPECT_EQ(0, GetGetOffset()); // Add 3 commands through the helper AddCommandWithExpect(parse_error::kParseNoError, 1, 0, NULL); @@ -158,8 +169,7 @@ TEST_F(CommandBufferHelperTest, TestCommandProcessing) { Mock::VerifyAndClearExpectations(api_mock_.get()); // Check the error status. - EXPECT_FALSE(command_buffer_->GetErrorStatus()); - EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError()); + EXPECT_EQ(parse_error::kParseNoError, GetError()); } // Checks that commands in the buffer are properly executed when wrapping the @@ -179,34 +189,7 @@ TEST_F(CommandBufferHelperTest, TestCommandWrapping) { Mock::VerifyAndClearExpectations(api_mock_.get()); // Check the error status. - EXPECT_FALSE(command_buffer_->GetErrorStatus()); - EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError()); -} - - -// Checks that commands in the buffer are properly executed, even if they -// generate a recoverable error. Check that the error status is properly set, -// and reset when queried. -TEST_F(CommandBufferHelperTest, TestRecoverableError) { - CommandBufferEntry args[2]; - args[0].value_uint32 = 3; - args[1].value_float = 4.f; - - // Create a command buffer with 3 commands, 2 of them generating errors - AddCommandWithExpect(parse_error::kParseNoError, 1, 2, args); - AddCommandWithExpect(parse_error::kParseUnknownCommand, 2, 2, args); - AddCommandWithExpect(parse_error::kParseInvalidArguments, 3, 2, - args); - - helper_->Finish(); - // Check that the commands did happen. - Mock::VerifyAndClearExpectations(api_mock_.get()); - - // Check that the error status was set to the first error. - EXPECT_EQ(parse_error::kParseUnknownCommand, - command_buffer_->ResetParseError()); - // Check that the error status was reset after the query. - EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError()); + EXPECT_EQ(parse_error::kParseNoError, GetError()); } // Checks that asking for available entries work, and that the parser @@ -238,8 +221,7 @@ TEST_F(CommandBufferHelperTest, TestAvailableEntries) { Mock::VerifyAndClearExpectations(api_mock_.get()); // Check the error status. - EXPECT_FALSE(command_buffer_->GetErrorStatus()); - EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError()); + EXPECT_EQ(parse_error::kParseNoError, GetError()); } // Checks that the InsertToken/WaitForToken work. @@ -261,15 +243,14 @@ TEST_F(CommandBufferHelperTest, TestToken) { AddCommandWithExpect(parse_error::kParseNoError, 4, 2, args); helper_->WaitForToken(token); // check that the get pointer is beyond the first command. - EXPECT_LE(command1_put, command_buffer_->GetGetOffset()); + EXPECT_LE(command1_put, GetGetOffset()); helper_->Finish(); // Check that the commands did happen. Mock::VerifyAndClearExpectations(api_mock_.get()); // Check the error status. - EXPECT_FALSE(command_buffer_->GetErrorStatus()); - EXPECT_EQ(parse_error::kParseNoError, command_buffer_->ResetParseError()); + EXPECT_EQ(parse_error::kParseNoError, GetError()); } } // namespace gpu diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc index a086463..8ef3bb4 100644 --- a/gpu/command_buffer/client/fenced_allocator_test.cc +++ b/gpu/command_buffer/client/fenced_allocator_test.cc @@ -61,6 +61,10 @@ class BaseFencedAllocatorTest : public testing::Test { helper_->Initialize(); } + int32 GetToken() { + return command_buffer_->GetState().token; + } + virtual void TearDown() { helper_.release(); } @@ -187,7 +191,7 @@ TEST_F(FencedAllocatorTest, TestFreePendingToken) { // The way we hooked up the helper and engine, it won't process commands // until it has to wait for something. Which means the token shouldn't have // passed yet at this point. - EXPECT_GT(token, command_buffer_->GetToken()); + EXPECT_GT(token, GetToken()); // This allocation will need to reclaim the space freed above, so that should // process the commands until the token is passed. @@ -196,7 +200,7 @@ TEST_F(FencedAllocatorTest, TestFreePendingToken) { EXPECT_GE(kBufferSize, offsets[0]+kSize); EXPECT_TRUE(allocator_->CheckConsistency()); // Check that the token has indeed passed. - EXPECT_LE(token, command_buffer_->GetToken()); + EXPECT_LE(token, GetToken()); // Free up everything. for (unsigned int i = 0; i < kAllocCount; ++i) { @@ -292,13 +296,13 @@ TEST_F(FencedAllocatorTest, TestGetLargestFreeOrPendingSize) { // The way we hooked up the helper and engine, it won't process commands // until it has to wait for something. Which means the token shouldn't have // passed yet at this point. - EXPECT_GT(token, command_buffer_->GetToken()); + EXPECT_GT(token, GetToken()); // This allocation will need to reclaim the space freed above, so that should // process the commands until the token is passed, but it will succeed. offset = allocator_->Alloc(kBufferSize); ASSERT_NE(FencedAllocator::kInvalidOffset, offset); // Check that the token has indeed passed. - EXPECT_LE(token, command_buffer_->GetToken()); + EXPECT_LE(token, GetToken()); allocator_->Free(offset); // Everything now has been freed... @@ -443,7 +447,7 @@ TEST_F(FencedAllocatorWrapperTest, TestFreePendingToken) { // The way we hooked up the helper and engine, it won't process commands // until it has to wait for something. Which means the token shouldn't have // passed yet at this point. - EXPECT_GT(token, command_buffer_->GetToken()); + EXPECT_GT(token, GetToken()); // This allocation will need to reclaim the space freed above, so that should // process the commands until the token is passed. @@ -451,7 +455,7 @@ TEST_F(FencedAllocatorWrapperTest, TestFreePendingToken) { EXPECT_TRUE(pointers[0]); EXPECT_TRUE(allocator_->CheckConsistency()); // Check that the token has indeed passed. - EXPECT_LE(token, command_buffer_->GetToken()); + EXPECT_LE(token, GetToken()); // Free up everything. for (unsigned int i = 0; i < kAllocCount; ++i) { diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h index 7126e53..85e7596 100644 --- a/gpu/command_buffer/common/command_buffer.h +++ b/gpu/command_buffer/common/command_buffer.h @@ -7,12 +7,42 @@ #include "base/basictypes.h" #include "gpu/command_buffer/common/buffer.h" +#include "gpu/command_buffer/common/constants.h" namespace gpu { // Common interface for CommandBuffer implementations. class CommandBuffer { public: + struct State { + State() + : size(0), + get_offset(0), + put_offset(0), + token(-1), + error(parse_error::kParseNoError) { + } + + // Size of the command buffer in command buffer entries. + int32 size; + + // The offset (in entries) from which the reader is reading. + int32 get_offset; + + // The offset (in entries) at which the writer is writing. + int32 put_offset; + + // The current token value. This is used by the writer to defer + // changes to shared memory objects until the reader has reached a certain + // point in the command buffer. The reader is responsible for updating the + // token value, for example in response to an asynchronous set token command + // embedded in the command buffer. The default token value is zero. + int32 token; + + // Error status. + parse_error::ParseError error; + }; + CommandBuffer() { } @@ -26,22 +56,17 @@ class CommandBuffer { // Gets the ring buffer for the command buffer. virtual Buffer GetRingBuffer() = 0; - virtual int32 GetSize() = 0; + // Returns the current status. + virtual State GetState() = 0; // The writer calls this to update its put offset. This function returns the // reader's most recent get offset. Does not return until after the put offset // change callback has been invoked. Returns -1 if the put offset is invalid. - virtual int32 SyncOffsets(int32 put_offset) = 0; - - // Returns the current get offset. This can be called from any thread. - virtual int32 GetGetOffset() = 0; + virtual State Flush(int32 put_offset) = 0; // Sets the current get offset. This can be called from any thread. virtual void SetGetOffset(int32 get_offset) = 0; - // Returns the current put offset. This can be called from any thread. - virtual int32 GetPutOffset() = 0; - // Create a transfer buffer and return a handle that uniquely // identifies it or -1 on error. virtual int32 CreateTransferBuffer(size_t size) = 0; @@ -52,29 +77,11 @@ class CommandBuffer { // Get the transfer buffer associated with a handle. virtual Buffer GetTransferBuffer(int32 handle) = 0; - // Get the current token value. This is used for by the writer to defer - // changes to shared memory objects until the reader has reached a certain - // point in the command buffer. The reader is responsible for updating the - // token value, for example in response to an asynchronous set token command - // embedded in the command buffer. The default token value is zero. - virtual int32 GetToken() = 0; - // Allows the reader to update the current token value. virtual void SetToken(int32 token) = 0; - // Get the current parse error and reset it to zero. Zero means no error. Non- - // zero means error. The default error status is zero. - virtual int32 ResetParseError() = 0; - // Allows the reader to set the current parse error. - virtual void SetParseError(int32 parse_error) = 0; - - // Returns whether the command buffer is in the error state. - virtual bool GetErrorStatus() = 0; - - // Allows the reader to set the error status. Once in an error state, the - // command buffer cannot recover and ceases to process commands. - virtual void RaiseErrorStatus() = 0; + virtual void SetParseError(parse_error::ParseError) = 0; private: DISALLOW_COPY_AND_ASSIGN(CommandBuffer); diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h index 6295c85..6795975 100644 --- a/gpu/command_buffer/common/command_buffer_mock.h +++ b/gpu/command_buffer/common/command_buffer_mock.h @@ -23,20 +23,14 @@ class MockCommandBuffer : public CommandBuffer { MOCK_METHOD1(Initialize, bool(int32 size)); MOCK_METHOD0(GetRingBuffer, Buffer()); - MOCK_METHOD0(GetSize, int32()); - MOCK_METHOD1(SyncOffsets, int32(int32 put_offset)); - MOCK_METHOD0(GetGetOffset, int32()); + MOCK_METHOD0(GetState, State()); + MOCK_METHOD1(Flush, State(int32 put_offset)); MOCK_METHOD1(SetGetOffset, void(int32 get_offset)); - MOCK_METHOD0(GetPutOffset, int32()); MOCK_METHOD1(CreateTransferBuffer, int32(size_t size)); MOCK_METHOD1(DestroyTransferBuffer, void(int32 handle)); MOCK_METHOD1(GetTransferBuffer, Buffer(int32 handle)); - MOCK_METHOD0(GetToken, int32()); MOCK_METHOD1(SetToken, void(int32 token)); - MOCK_METHOD0(ResetParseError, int32()); - MOCK_METHOD1(SetParseError, void(int32 parse_erro)); - MOCK_METHOD0(GetErrorStatus, bool()); - MOCK_METHOD0(RaiseErrorStatus, void()); + MOCK_METHOD1(SetParseError, void(parse_error::ParseError parse_error)); private: DISALLOW_COPY_AND_ASSIGN(MockCommandBuffer); diff --git a/gpu/command_buffer/common/constants.h b/gpu/command_buffer/common/constants.h index e07dd0f..ad7836b 100644 --- a/gpu/command_buffer/common/constants.h +++ b/gpu/command_buffer/common/constants.h @@ -12,18 +12,7 @@ namespace gpu { typedef int32 CommandBufferOffset; const CommandBufferOffset kInvalidCommandBufferOffset = -1; -// Status of the command buffer service. It does not process commands -// (meaning: get will not change) unless in kParsing state. -namespace parser_status { - enum ParserStatus { - kNotConnected, // The service is not connected - initial state. - kNoBuffer, // The service is connected but no buffer was set. - kParsing, // The service is connected, and parsing commands from the - // buffer. - kParseError, // Parsing stopped because a parse error was found. - }; -} - +// TODO(apatrick): rename to something more generic like just Error. namespace parse_error { enum ParseError { kParseNoError, @@ -31,6 +20,7 @@ namespace parse_error { kParseOutOfBounds, kParseUnknownCommand, kParseInvalidArguments, + kParseGenericError, }; } diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc index f0a96e1..053a22b 100644 --- a/gpu/command_buffer/service/command_buffer_service.cc +++ b/gpu/command_buffer/service/command_buffer_service.cc @@ -17,8 +17,7 @@ CommandBufferService::CommandBufferService() get_offset_(0), put_offset_(0), token_(0), - parse_error_(0), - error_status_(false) { + error_(parse_error::kParseNoError) { // Element zero is always NULL. registered_objects_.push_back(linked_ptr<SharedMemory>()); } @@ -54,13 +53,22 @@ Buffer CommandBufferService::GetRingBuffer() { return buffer; } -int32 CommandBufferService::GetSize() { - return size_; +CommandBufferService::State CommandBufferService::GetState() { + State state; + state.size = size_; + state.get_offset = get_offset_; + state.put_offset = put_offset_; + state.token = token_; + state.error = error_; + + return state; } -int32 CommandBufferService::SyncOffsets(int32 put_offset) { - if (put_offset < 0 || put_offset >= size_) - return -1; +CommandBufferService::State CommandBufferService::Flush(int32 put_offset) { + if (put_offset < 0 || put_offset >= size_) { + error_ = gpu::parse_error::kParseOutOfBounds; + return GetState(); + } put_offset_ = put_offset; @@ -68,11 +76,7 @@ int32 CommandBufferService::SyncOffsets(int32 put_offset) { put_offset_change_callback_->Run(); } - return get_offset_; -} - -int32 CommandBufferService::GetGetOffset() { - return get_offset_; + return GetState(); } void CommandBufferService::SetGetOffset(int32 get_offset) { @@ -80,10 +84,6 @@ void CommandBufferService::SetGetOffset(int32 get_offset) { get_offset_ = get_offset; } -int32 CommandBufferService::GetPutOffset() { - return put_offset_; -} - int32 CommandBufferService::CreateTransferBuffer(size_t size) { linked_ptr<SharedMemory> buffer(new SharedMemory); if (!buffer->Create(std::wstring(), false, false, size)) @@ -150,34 +150,16 @@ Buffer CommandBufferService::GetTransferBuffer(int32 handle) { return buffer; } -int32 CommandBufferService::GetToken() { - return token_; -} - void CommandBufferService::SetToken(int32 token) { token_ = token; } -int32 CommandBufferService::ResetParseError() { - int32 last_error = parse_error_; - parse_error_ = 0; - return last_error; -} - -void CommandBufferService::SetParseError(int32 parse_error) { - if (parse_error_ == 0) { - parse_error_ = parse_error; +void CommandBufferService::SetParseError(parse_error::ParseError error) { + if (error_ == parse_error::kParseNoError) { + error_ = error; } } -bool CommandBufferService::GetErrorStatus() { - return error_status_; -} - -void CommandBufferService::RaiseErrorStatus() { - error_status_ = true; -} - void CommandBufferService::SetPutOffsetChangeCallback( Callback0::Type* callback) { put_offset_change_callback_.reset(callback); diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h index aec7c14..3e58d7e 100644 --- a/gpu/command_buffer/service/command_buffer_service.h +++ b/gpu/command_buffer/service/command_buffer_service.h @@ -26,20 +26,14 @@ class CommandBufferService : public CommandBuffer { // CommandBuffer implementation: virtual bool Initialize(int32 size); virtual Buffer GetRingBuffer(); - virtual int32 GetSize(); - virtual int32 SyncOffsets(int32 put_offset); - virtual int32 GetGetOffset(); + virtual State GetState(); + virtual State Flush(int32 put_offset); virtual void SetGetOffset(int32 get_offset); - virtual int32 GetPutOffset(); virtual int32 CreateTransferBuffer(size_t size); virtual void DestroyTransferBuffer(int32 id); virtual Buffer GetTransferBuffer(int32 handle); - virtual int32 GetToken(); virtual void SetToken(int32 token); - virtual int32 ResetParseError(); - virtual void SetParseError(int32 parse_error); - virtual bool GetErrorStatus(); - virtual void RaiseErrorStatus(); + virtual void SetParseError(parse_error::ParseError); // Sets a callback that should be posted on another thread whenever the put // offset is changed. The callback must not return until some progress has @@ -62,8 +56,7 @@ class CommandBufferService : public CommandBuffer { std::vector<linked_ptr< base::SharedMemory> > registered_objects_; std::set<int32> unused_registered_object_elements_; int32 token_; - int32 parse_error_; - bool error_status_; + parse_error::ParseError error_; }; } // namespace gpu diff --git a/gpu/command_buffer/service/command_buffer_service_unittest.cc b/gpu/command_buffer/service/command_buffer_service_unittest.cc index 98ec0ec..ea0193b 100644 --- a/gpu/command_buffer/service/command_buffer_service_unittest.cc +++ b/gpu/command_buffer/service/command_buffer_service_unittest.cc @@ -23,6 +23,22 @@ class CommandBufferServiceTest : public testing::Test { command_buffer_.reset(new CommandBufferService); } + int32 GetGetOffset() { + return command_buffer_->GetState().get_offset; + } + + int32 GetPutOffset() { + return command_buffer_->GetState().put_offset; + } + + int32 GetToken() { + return command_buffer_->GetState().token; + } + + int32 GetError() { + return command_buffer_->GetState().error; + } + scoped_ptr<CommandBufferService> command_buffer_; }; @@ -33,9 +49,12 @@ TEST_F(CommandBufferServiceTest, NullRingBufferByDefault) { TEST_F(CommandBufferServiceTest, InitializesCommandBuffer) { EXPECT_TRUE(command_buffer_->Initialize(1024)); EXPECT_TRUE(NULL != command_buffer_->GetRingBuffer().ptr); - EXPECT_EQ(1024, command_buffer_->GetSize()); - EXPECT_EQ(1024 * sizeof(CommandBufferEntry), - command_buffer_->GetRingBuffer().size); + CommandBuffer::State state = command_buffer_->GetState(); + EXPECT_EQ(1024, state.size); + EXPECT_EQ(0, state.get_offset); + EXPECT_EQ(0, state.put_offset); + EXPECT_EQ(0, state.token); + EXPECT_EQ(parse_error::kParseNoError, state.error); } TEST_F(CommandBufferServiceTest, InitializationSizeIsInEntriesNotBytes) { @@ -51,11 +70,6 @@ TEST_F(CommandBufferServiceTest, InitializeFailsSecondTime) { EXPECT_FALSE(command_buffer_->Initialize(1024)); } -TEST_F(CommandBufferServiceTest, GetAndPutOffsetsDefaultToZero) { - EXPECT_EQ(0, command_buffer_->GetGetOffset()); - EXPECT_EQ(0, command_buffer_->GetPutOffset()); -} - class MockCallback : public CallbackRunner<Tuple0> { public: MOCK_METHOD1(RunWithParams, void(const Tuple0&)); @@ -69,20 +83,21 @@ TEST_F(CommandBufferServiceTest, CanSyncGetAndPutOffset) { command_buffer_->SetPutOffsetChangeCallback(put_offset_change_callback); EXPECT_CALL(*put_offset_change_callback, RunWithParams(_)); - EXPECT_EQ(0, command_buffer_->SyncOffsets(2)); - EXPECT_EQ(2, command_buffer_->GetPutOffset()); + EXPECT_EQ(0, command_buffer_->Flush(2).get_offset); + EXPECT_EQ(2, GetPutOffset()); EXPECT_CALL(*put_offset_change_callback, RunWithParams(_)); - EXPECT_EQ(0, command_buffer_->SyncOffsets(4)); - EXPECT_EQ(4, command_buffer_->GetPutOffset()); + EXPECT_EQ(0, command_buffer_->Flush(4).get_offset); + EXPECT_EQ(4, GetPutOffset()); command_buffer_->SetGetOffset(2); - EXPECT_EQ(2, command_buffer_->GetGetOffset()); + EXPECT_EQ(2, GetGetOffset()); EXPECT_CALL(*put_offset_change_callback, RunWithParams(_)); - EXPECT_EQ(2, command_buffer_->SyncOffsets(6)); + EXPECT_EQ(2, command_buffer_->Flush(6).get_offset); - EXPECT_EQ(-1, command_buffer_->SyncOffsets(-1)); - EXPECT_EQ(-1, command_buffer_->SyncOffsets(1024)); + EXPECT_NE(parse_error::kParseNoError, command_buffer_->Flush(-1).error); + EXPECT_NE(parse_error::kParseNoError, + command_buffer_->Flush(1024).error); } TEST_F(CommandBufferServiceTest, ZeroHandleMapsToNull) { @@ -153,31 +168,20 @@ TEST_F(CommandBufferServiceTest, UnregistersTwoLastRegisteredHandles) { } TEST_F(CommandBufferServiceTest, DefaultTokenIsZero) { - EXPECT_EQ(0, command_buffer_->GetToken()); + EXPECT_EQ(0, GetToken()); } TEST_F(CommandBufferServiceTest, CanSetToken) { command_buffer_->SetToken(7); - EXPECT_EQ(7, command_buffer_->GetToken()); + EXPECT_EQ(7, GetToken()); } TEST_F(CommandBufferServiceTest, DefaultParseErrorIsNoError) { - EXPECT_EQ(0, command_buffer_->ResetParseError()); -} - -TEST_F(CommandBufferServiceTest, CanSetAndResetParseError) { - command_buffer_->SetParseError(1); - EXPECT_EQ(1, command_buffer_->ResetParseError()); - EXPECT_EQ(0, command_buffer_->ResetParseError()); -} - -TEST_F(CommandBufferServiceTest, DefaultErrorStatusIsFalse) { - EXPECT_FALSE(command_buffer_->GetErrorStatus()); + EXPECT_EQ(0, GetError()); } -TEST_F(CommandBufferServiceTest, CanRaiseErrorStatus) { - command_buffer_->RaiseErrorStatus(); - EXPECT_TRUE(command_buffer_->GetErrorStatus()); +TEST_F(CommandBufferServiceTest, CanSetParseError) { + command_buffer_->SetParseError(parse_error::kParseInvalidSize); + EXPECT_EQ(1, GetError()); } - } // namespace gpu diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc index 8697c8b..30f07ef 100644 --- a/gpu/command_buffer/service/gpu_processor.cc +++ b/gpu/command_buffer/service/gpu_processor.cc @@ -32,7 +32,8 @@ GPUProcessor::~GPUProcessor() { } void GPUProcessor::ProcessCommands() { - if (command_buffer_->GetErrorStatus()) + CommandBuffer::State state = command_buffer_->GetState(); + if (state.error != parse_error::kParseNoError) return; if (decoder_.get()) { @@ -41,26 +42,15 @@ void GPUProcessor::ProcessCommands() { return; } - parser_->set_put(command_buffer_->GetPutOffset()); + parser_->set_put(state.put_offset); int commands_processed = 0; while (commands_processed < commands_per_update_ && !parser_->IsEmpty()) { parse_error::ParseError parse_error = parser_->ProcessCommand(); - switch (parse_error) { - case parse_error::kParseUnknownCommand: - case parse_error::kParseInvalidArguments: - command_buffer_->SetParseError(parse_error); - break; - - case parse_error::kParseInvalidSize: - case parse_error::kParseOutOfBounds: - command_buffer_->SetParseError(parse_error); - command_buffer_->RaiseErrorStatus(); - return; - case gpu::parse_error::kParseNoError: - break; + if (parse_error != parse_error::kParseNoError) { + command_buffer_->SetParseError(parse_error); + return; } - ++commands_processed; } diff --git a/gpu/command_buffer/service/gpu_processor_unittest.cc b/gpu/command_buffer/service/gpu_processor_unittest.cc index 38ba3fd..4f97acc 100644 --- a/gpu/command_buffer/service/gpu_processor_unittest.cc +++ b/gpu/command_buffer/service/gpu_processor_unittest.cc @@ -39,8 +39,11 @@ class GPUProcessorTest : public testing::Test { command_buffer_.reset(new MockCommandBuffer); ON_CALL(*command_buffer_.get(), GetRingBuffer()) .WillByDefault(Return(shared_memory_buffer_)); - ON_CALL(*command_buffer_.get(), GetSize()) - .WillByDefault(Return(kRingBufferEntries)); + + CommandBuffer::State default_state; + default_state.size = kRingBufferEntries; + ON_CALL(*command_buffer_.get(), GetState()) + .WillByDefault(Return(default_state)); async_api_.reset(new StrictMock<AsyncAPIMock>); @@ -65,6 +68,10 @@ class GPUProcessorTest : public testing::Test { MessageLoop::current()->RunAllPending(); } + parse_error::ParseError GetError() { + return command_buffer_->GetState().error; + } + base::AtExitManager at_exit_manager; MessageLoop message_loop; scoped_ptr<MockCommandBuffer> command_buffer_; @@ -78,15 +85,17 @@ class GPUProcessorTest : public testing::Test { }; TEST_F(GPUProcessorTest, ProcessorDoesNothingIfRingBufferIsEmpty) { - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .WillOnce(Return(0)); + CommandBuffer::State state; + + state.put_offset = 0; + EXPECT_CALL(*command_buffer_, GetState()) + .WillOnce(Return(state)); EXPECT_CALL(*command_buffer_, SetGetOffset(0)); - processor_->ProcessCommands(); + EXPECT_CALL(*command_buffer_, SetParseError(_)) + .Times(0); - EXPECT_EQ(parse_error::kParseNoError, - command_buffer_->ResetParseError()); - EXPECT_FALSE(command_buffer_->GetErrorStatus()); + processor_->ProcessCommands(); } TEST_F(GPUProcessorTest, ProcessesOneCommand) { @@ -95,18 +104,20 @@ TEST_F(GPUProcessorTest, ProcessesOneCommand) { header[0].size = 2; buffer_[1] = 123; - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .WillOnce(Return(2)); + CommandBuffer::State state; + + state.put_offset = 2; + EXPECT_CALL(*command_buffer_, GetState()) + .WillOnce(Return(state)); EXPECT_CALL(*command_buffer_, SetGetOffset(2)); EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) .WillOnce(Return(parse_error::kParseNoError)); - processor_->ProcessCommands(); + EXPECT_CALL(*command_buffer_, SetParseError(_)) + .Times(0); - EXPECT_EQ(parse_error::kParseNoError, - command_buffer_->ResetParseError()); - EXPECT_FALSE(command_buffer_->GetErrorStatus()); + processor_->ProcessCommands(); } TEST_F(GPUProcessorTest, ProcessesTwoCommands) { @@ -117,8 +128,11 @@ TEST_F(GPUProcessorTest, ProcessesTwoCommands) { header[2].command = 8; header[2].size = 1; - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .WillOnce(Return(3)); + CommandBuffer::State state; + + state.put_offset = 3; + EXPECT_CALL(*command_buffer_, GetState()) + .WillOnce(Return(state)); EXPECT_CALL(*command_buffer_, SetGetOffset(3)); EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) @@ -130,11 +144,15 @@ TEST_F(GPUProcessorTest, ProcessesTwoCommands) { processor_->ProcessCommands(); } -TEST_F(GPUProcessorTest, ProcessorSetsAndResetsTheGLContext) { +TEST_F(GPUProcessorTest, ProcessorSetsTheGLContext) { EXPECT_CALL(*decoder_, MakeCurrent()) .WillOnce(Return(true)); - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .WillOnce(Return(0)); + + CommandBuffer::State state; + state.put_offset = 0; + EXPECT_CALL(*command_buffer_, GetState()) + .WillOnce(Return(state)); + EXPECT_CALL(*command_buffer_, SetGetOffset(0)); processor_->ProcessCommands(); @@ -150,8 +168,11 @@ TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) { header[3].command = 9; header[3].size = 1; - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .WillOnce(Return(4)); + CommandBuffer::State state; + + state.put_offset = 4; + EXPECT_CALL(*command_buffer_, GetState()) + .WillOnce(Return(state)); EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) .WillOnce(Return(parse_error::kParseNoError)); @@ -165,8 +186,9 @@ TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) { // ProcessCommands is called a second time when the pending task is run. - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .WillOnce(Return(4)); + state.put_offset = 4; + EXPECT_CALL(*command_buffer_, GetState()) + .WillOnce(Return(state)); EXPECT_CALL(*async_api_, DoCommand(9, 0, &buffer_[3])) .WillOnce(Return(parse_error::kParseNoError)); @@ -181,73 +203,28 @@ TEST_F(GPUProcessorTest, SetsErrorCodeOnCommandBuffer) { header[0].command = 7; header[0].size = 1; - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .WillOnce(Return(1)); - EXPECT_CALL(*command_buffer_, SetGetOffset(1)); - - EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0])) - .WillOnce(Return( - parse_error::kParseUnknownCommand)); - - EXPECT_CALL(*command_buffer_, - SetParseError(parse_error::kParseUnknownCommand)); - - processor_->ProcessCommands(); -} - -TEST_F(GPUProcessorTest, - RecoverableParseErrorsAreNotClearedByFollowingSuccessfulCommands) { - CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]); - header[0].command = 7; - header[0].size = 1; - header[1].command = 8; - header[1].size = 1; + CommandBuffer::State state; - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .WillOnce(Return(2)); - EXPECT_CALL(*command_buffer_, SetGetOffset(2)); + state.put_offset = 1; + EXPECT_CALL(*command_buffer_, GetState()) + .WillOnce(Return(state)); EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0])) .WillOnce(Return( parse_error::kParseUnknownCommand)); - EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[1])) - .WillOnce(Return(parse_error::kParseNoError)); - EXPECT_CALL(*command_buffer_, SetParseError(parse_error::kParseUnknownCommand)); processor_->ProcessCommands(); } -TEST_F(GPUProcessorTest, UnrecoverableParseErrorsRaiseTheErrorStatus) { - CommandHeader* header = - reinterpret_cast<CommandHeader*>(&buffer_[0]); - header[0].command = 7; - header[0].size = 1; - header[1].command = 8; - header[1].size = 1; - - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .WillOnce(Return(2)); +TEST_F(GPUProcessorTest, ProcessCommandsDoesNothingAfterError) { + CommandBuffer::State state; + state.error = parse_error::kParseGenericError; - EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0])) - .WillOnce(Return(parse_error::kParseInvalidSize)); - - EXPECT_CALL(*command_buffer_, - SetParseError(parse_error::kParseInvalidSize)); - - EXPECT_CALL(*command_buffer_, RaiseErrorStatus()); - - processor_->ProcessCommands(); -} - -TEST_F(GPUProcessorTest, ProcessCommandsDoesNothingAfterUnrecoverableError) { - EXPECT_CALL(*command_buffer_, GetErrorStatus()) - .WillOnce(Return(true)); - - EXPECT_CALL(*command_buffer_, GetPutOffset()) - .Times(0); + EXPECT_CALL(*command_buffer_, GetState()) + .WillOnce(Return(state)); processor_->ProcessCommands(); } diff --git a/gpu/pgl/command_buffer_pepper.cc b/gpu/pgl/command_buffer_pepper.cc index 9dd3c70..8522bbe 100644 --- a/gpu/pgl/command_buffer_pepper.cc +++ b/gpu/pgl/command_buffer_pepper.cc @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "gpu/command_buffer/common/constants.h" #include "gpu/pgl/command_buffer_pepper.h" + #ifdef __native_client__ #include <assert.h> #define NOTREACHED() assert(0) @@ -12,6 +14,7 @@ using base::SharedMemory; using gpu::Buffer; +using gpu::CommandBuffer; CommandBufferPepper::CommandBufferPepper(NPP npp, NPDevice* device, @@ -37,29 +40,20 @@ Buffer CommandBufferPepper::GetRingBuffer() { return buffer; } -int32 CommandBufferPepper::GetSize() { - return context_->commandBufferEntries; -} - -int32 CommandBufferPepper::SyncOffsets(int32 put_offset) { - context_->putOffset = put_offset; +CommandBuffer::State CommandBufferPepper::GetState() { if (NPERR_NO_ERROR != device_->flushContext(npp_, context_, NULL, NULL)) - return -1; + context_->error = gpu::parse_error::kParseGenericError; - return context_->getOffset; + return ConvertState(); } -int32 CommandBufferPepper::GetGetOffset() { - int32 value; - if (NPERR_NO_ERROR != device_->getStateContext( - npp_, - context_, - NPDeviceContext3DState_GetOffset, - &value)) { - return -1; - } +CommandBuffer::State CommandBufferPepper::Flush(int32 put_offset) { + context_->putOffset = put_offset; - return value; + if (NPERR_NO_ERROR != device_->flushContext(npp_, context_, NULL, NULL)) + context_->error = gpu::parse_error::kParseGenericError; + + return ConvertState(); } void CommandBufferPepper::SetGetOffset(int32 get_offset) { @@ -67,19 +61,6 @@ void CommandBufferPepper::SetGetOffset(int32 get_offset) { NOTREACHED(); } -int32 CommandBufferPepper::GetPutOffset() { - int32 value; - if (NPERR_NO_ERROR != device_->getStateContext( - npp_, - context_, - NPDeviceContext3DState_PutOffset, - &value)) { - return -1; - } - - return value; -} - int32 CommandBufferPepper::CreateTransferBuffer(size_t size) { int32 id; if (NPERR_NO_ERROR != device_->createBuffer(npp_, context_, size, &id)) @@ -103,56 +84,24 @@ Buffer CommandBufferPepper::GetTransferBuffer(int32 id) { return buffer; } -int32 CommandBufferPepper::GetToken() { - int32 value; - if (NPERR_NO_ERROR != device_->getStateContext( - npp_, - context_, - NPDeviceContext3DState_Token, - &value)) { - return -1; - } - - return value; -} - void CommandBufferPepper::SetToken(int32 token) { // Not implemented by proxy. NOTREACHED(); } -int32 CommandBufferPepper::ResetParseError() { - int32 value; - if (NPERR_NO_ERROR != device_->getStateContext( - npp_, - context_, - NPDeviceContext3DState_ParseError, - &value)) { - return -1; - } - - return value; -} - -void CommandBufferPepper::SetParseError(int32 parse_error) { +void CommandBufferPepper::SetParseError( + gpu::parse_error::ParseError parse_error) { // Not implemented by proxy. NOTREACHED(); } -bool CommandBufferPepper::GetErrorStatus() { - int32 value; - if (NPERR_NO_ERROR != device_->getStateContext( - npp_, - context_, - NPDeviceContext3DState_ErrorStatus, - &value)) { - return value != 0; - } - - return true; -} - -void CommandBufferPepper::RaiseErrorStatus() { - // Not implemented by proxy. - NOTREACHED(); +CommandBuffer::State CommandBufferPepper::ConvertState() { + CommandBuffer::State state; + state.size = context_->commandBufferEntries; + state.get_offset = context_->getOffset; + state.put_offset = context_->putOffset; + state.token = context_->token; + state.error = static_cast<gpu::parse_error::ParseError>( + context_->error); + return state; } diff --git a/gpu/pgl/command_buffer_pepper.h b/gpu/pgl/command_buffer_pepper.h index aa1d14b..b3efaea 100644 --- a/gpu/pgl/command_buffer_pepper.h +++ b/gpu/pgl/command_buffer_pepper.h @@ -28,22 +28,18 @@ class CommandBufferPepper : public gpu::CommandBuffer { // CommandBuffer implementation. virtual bool Initialize(int32 size); virtual gpu::Buffer GetRingBuffer(); - virtual int32 GetSize(); - virtual int32 SyncOffsets(int32 put_offset); - virtual int32 GetGetOffset(); + virtual State GetState(); + virtual State Flush(int32 put_offset); virtual void SetGetOffset(int32 get_offset); - virtual int32 GetPutOffset(); virtual int32 CreateTransferBuffer(size_t size); virtual void DestroyTransferBuffer(int32 id); virtual gpu::Buffer GetTransferBuffer(int32 handle); - virtual int32 GetToken(); virtual void SetToken(int32 token); - virtual int32 ResetParseError(); - virtual void SetParseError(int32 parse_error); - virtual bool GetErrorStatus(); - virtual void RaiseErrorStatus(); + virtual void SetParseError(gpu::parse_error::ParseError parse_error); private: + CommandBuffer::State ConvertState(); + NPP npp_; NPDevice* device_; NPDeviceContext3D* context_; diff --git a/third_party/npapi/bindings/npapi_extensions.h b/third_party/npapi/bindings/npapi_extensions.h index c24cd99..c60a82a 100644 --- a/third_party/npapi/bindings/npapi_extensions.h +++ b/third_party/npapi/bindings/npapi_extensions.h @@ -271,20 +271,6 @@ typedef struct _NPDeviceContext3DConfig { int32 commandBufferEntries; } NPDeviceContext3DConfig; -typedef enum { - // The offset the command buffer service has read to. - NPDeviceContext3DState_GetOffset, - // The offset the plugin instance has written to. - NPDeviceContext3DState_PutOffset, - // The last token processed by the command buffer service. - NPDeviceContext3DState_Token, - // The most recent parse error. Getting this value resets the parse error - // if it recoverable. - NPDeviceContext3DState_ParseError, - // Wether the command buffer has encountered an unrecoverable error. - NPDeviceContext3DState_ErrorStatus -} NPDeviceContext3DState; - typedef struct _NPDeviceContext3D { void* reserved; @@ -298,6 +284,12 @@ typedef struct _NPDeviceContext3D // Offset in command buffer writer has reached. Synchronized on flush. int32 putOffset; + + // Last processed token. Synchronized on flush. + int32 token; + + // Error status. Synchronized on flush. + int32 error; } NPDeviceContext3D; /* Audio --------------------------------------------------------------------*/ |