15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/command_buffer_service.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/logging.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/cmd_buffer_common.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/common/command_buffer_shared.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gpu/command_buffer/service/transfer_buffer_manager.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::base::SharedMemory; 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::CommandBufferService( 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TransferBufferManagerInterface* transfer_buffer_manager) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ring_buffer_id_(-1), 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_state_(NULL), 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_entries_(0), 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_offset_(0), 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_(0), 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transfer_buffer_manager_(transfer_buffer_manager), 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_(0), 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) generation_(0), 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_(error::kNoError), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_lost_reason_(error::kUnknown) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::~CommandBufferService() { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferService::Initialize() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuCommandBufferService::State CommandBufferService::GetLastState() { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) State state; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state.num_entries = num_entries_; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state.get_offset = get_offset_; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state.put_offset = put_offset_; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state.token = token_; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state.error = error_; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state.context_lost_reason = context_lost_reason_; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state.generation = ++generation_; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 CommandBufferService::GetLastToken() { 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return GetLastState().token; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::UpdateState() { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shared_state_) { 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CommandBufferService::State state = GetLastState(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_state_->Write(state); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void CommandBufferService::WaitForTokenInRange(int32 start, int32 end) { 6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK(error_ != error::kNoError || InRange(start, end, token_)); 6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void CommandBufferService::WaitForGetOffsetInRange(int32 start, int32 end) { 6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK(error_ != error::kNoError || InRange(start, end, get_offset_)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::Flush(int32 put_offset) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (put_offset < 0 || put_offset > num_entries_) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = gpu::error::kOutOfBounds; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_ = put_offset; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!put_offset_change_callback_.is_null()) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_change_callback_.Run(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(-1, ring_buffer_id_); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(put_offset_, get_offset_); // Only if it's empty. 87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // If the buffer is invalid we handle it gracefully. 88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // This means ring_buffer_ can be NULL. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_ = GetTransferBuffer(transfer_buffer_id); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_id_ = transfer_buffer_id; 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32 size = ring_buffer_.get() ? ring_buffer_->size() : 0; 92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch num_entries_ = size / sizeof(CommandBufferEntry); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_ = 0; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetGetOffset(0); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!get_buffer_change_callback_.is_null()) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_buffer_change_callback_.Run(ring_buffer_id_); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateState(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid CommandBufferService::SetSharedStateBuffer( 103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<BufferBacking> shared_state_buffer) { 104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shared_state_buffer_ = shared_state_buffer.Pass(); 105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(shared_state_buffer_->GetSize() >= sizeof(*shared_state_)); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shared_state_ = 108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch static_cast<CommandBufferSharedState*>(shared_state_buffer_->GetMemory()); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateState(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetGetOffset(int32 get_offset) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(get_offset >= 0 && get_offset < num_entries_); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_offset_ = get_offset; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_refptr<Buffer> CommandBufferService::CreateTransferBuffer(size_t size, 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int32* id) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *id = -1; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<SharedMemory> shared_memory(new SharedMemory()); 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!shared_memory->CreateAndMapAnonymous(size)) 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return NULL; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static int32 next_id = 1; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *id = next_id++; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 129e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!RegisterTransferBuffer( 130e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch *id, MakeBackingFromSharedMemory(shared_memory.Pass(), size))) { 131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) *id = -1; 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return NULL; 133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetTransferBuffer(*id); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CommandBufferService::DestroyTransferBuffer(int32 id) { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) transfer_buffer_manager_->DestroyTransferBuffer(id); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (id == ring_buffer_id_) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_id_ = -1; 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ring_buffer_ = NULL; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_entries_ = 0; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_offset_ = 0; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_ = 0; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_refptr<Buffer> CommandBufferService::GetTransferBuffer(int32 id) { 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return transfer_buffer_manager_->GetTransferBuffer(id); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CommandBufferService::RegisterTransferBuffer( 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 id, 155e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_ptr<BufferBacking> buffer) { 156e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return transfer_buffer_manager_->RegisterTransferBuffer(id, buffer.Pass()); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetToken(int32 token) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_ = token; 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateState(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetParseError(error::Error error) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_ == error::kNoError) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = error; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parse_error_callback_.is_null()) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_error_callback_.Run(); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetContextLostReason( 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error::ContextLostReason reason) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_lost_reason_ = reason; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetPutOffsetChangeCallback( 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& callback) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_change_callback_ = callback; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetGetBufferChangeCallback( 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GetBufferChangedCallback& callback) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_buffer_change_callback_ = callback; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetParseErrorCallback( 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& callback) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_error_callback_ = callback; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gpu 193