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) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::State CommandBufferService::GetState() { 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) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::State CommandBufferService::GetLastState() { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetState(); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 CommandBufferService::GetLastToken() { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetState().token; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::UpdateState() { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shared_state_) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandBufferService::State state = GetState(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shared_state_->Write(state); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferService::State CommandBufferService::FlushSync( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 put_offset, int32 last_known_get) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (put_offset < 0 || put_offset > num_entries_) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = gpu::error::kOutOfBounds; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetState(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_ = put_offset; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!put_offset_change_callback_.is_null()) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_change_callback_.Run(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetState(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::Flush(int32 put_offset) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (put_offset < 0 || put_offset > num_entries_) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = gpu::error::kOutOfBounds; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_ = put_offset; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!put_offset_change_callback_.is_null()) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_change_callback_.Run(); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(-1, ring_buffer_id_); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(put_offset_, get_offset_); // Only if it's empty. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_ = GetTransferBuffer(transfer_buffer_id); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ring_buffer_.ptr); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_id_ = transfer_buffer_id; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_entries_ = ring_buffer_.size / sizeof(CommandBufferEntry); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_ = 0; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetGetOffset(0); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!get_buffer_change_callback_.is_null()) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_buffer_change_callback_.Run(ring_buffer_id_); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateState(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CommandBufferService::SetSharedStateBuffer( 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<base::SharedMemory> shared_state_shm) { 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shared_state_shm_.reset(shared_state_shm.release()); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!shared_state_shm_->Map(sizeof(*shared_state_))) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shared_state_ = 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<CommandBufferSharedState*>(shared_state_shm_->memory()); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateState(); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetGetOffset(int32 get_offset) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(get_offset >= 0 && get_offset < num_entries_); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_offset_ = get_offset; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Buffer CommandBufferService::CreateTransferBuffer(size_t size, 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32* id) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *id = -1; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SharedMemory buffer; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buffer.CreateAnonymous(size)) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Buffer(); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static int32 next_id = 1; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *id = next_id++; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!RegisterTransferBuffer(*id, &buffer, size)) { 141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) *id = -1; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Buffer(); 143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetTransferBuffer(*id); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CommandBufferService::DestroyTransferBuffer(int32 id) { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) transfer_buffer_manager_->DestroyTransferBuffer(id); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (id == ring_buffer_id_) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_id_ = -1; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_ = Buffer(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_entries_ = 0; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_offset_ = 0; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_ = 0; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Buffer CommandBufferService::GetTransferBuffer(int32 id) { 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return transfer_buffer_manager_->GetTransferBuffer(id); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CommandBufferService::RegisterTransferBuffer( 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 id, 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::SharedMemory* shared_memory, 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t size) { 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return transfer_buffer_manager_->RegisterTransferBuffer(id, 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shared_memory, 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetToken(int32 token) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_ = token; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateState(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetParseError(error::Error error) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_ == error::kNoError) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_ = error; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parse_error_callback_.is_null()) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_error_callback_.Run(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetContextLostReason( 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error::ContextLostReason reason) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_lost_reason_ = reason; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetPutOffsetChangeCallback( 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& callback) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_offset_change_callback_ = callback; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetGetBufferChangeCallback( 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GetBufferChangedCallback& callback) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) get_buffer_change_callback_ = callback; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferService::SetParseErrorCallback( 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& callback) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_error_callback_ = callback; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gpu 206