1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "gpu/command_buffer/service/command_buffer_service.h" 6 7#include <limits> 8 9#include "base/logging.h" 10#include "base/debug/trace_event.h" 11#include "gpu/command_buffer/common/cmd_buffer_common.h" 12#include "gpu/command_buffer/common/command_buffer_shared.h" 13#include "gpu/command_buffer/service/transfer_buffer_manager.h" 14 15using ::base::SharedMemory; 16 17namespace gpu { 18 19CommandBufferService::CommandBufferService( 20 TransferBufferManagerInterface* transfer_buffer_manager) 21 : ring_buffer_id_(-1), 22 shared_state_(NULL), 23 num_entries_(0), 24 get_offset_(0), 25 put_offset_(0), 26 transfer_buffer_manager_(transfer_buffer_manager), 27 token_(0), 28 generation_(0), 29 error_(error::kNoError), 30 context_lost_reason_(error::kUnknown) { 31} 32 33CommandBufferService::~CommandBufferService() { 34} 35 36bool CommandBufferService::Initialize() { 37 return true; 38} 39 40CommandBufferService::State CommandBufferService::GetState() { 41 State state; 42 state.num_entries = num_entries_; 43 state.get_offset = get_offset_; 44 state.put_offset = put_offset_; 45 state.token = token_; 46 state.error = error_; 47 state.context_lost_reason = context_lost_reason_; 48 state.generation = ++generation_; 49 50 return state; 51} 52 53CommandBufferService::State CommandBufferService::GetLastState() { 54 return GetState(); 55} 56 57int32 CommandBufferService::GetLastToken() { 58 return GetState().token; 59} 60 61void CommandBufferService::UpdateState() { 62 if (shared_state_) { 63 CommandBufferService::State state = GetState(); 64 shared_state_->Write(state); 65 } 66} 67 68CommandBufferService::State CommandBufferService::FlushSync( 69 int32 put_offset, int32 last_known_get) { 70 if (put_offset < 0 || put_offset > num_entries_) { 71 error_ = gpu::error::kOutOfBounds; 72 return GetState(); 73 } 74 75 put_offset_ = put_offset; 76 77 if (!put_offset_change_callback_.is_null()) 78 put_offset_change_callback_.Run(); 79 80 return GetState(); 81} 82 83void CommandBufferService::Flush(int32 put_offset) { 84 if (put_offset < 0 || put_offset > num_entries_) { 85 error_ = gpu::error::kOutOfBounds; 86 return; 87 } 88 89 put_offset_ = put_offset; 90 91 if (!put_offset_change_callback_.is_null()) 92 put_offset_change_callback_.Run(); 93} 94 95void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) { 96 DCHECK_EQ(-1, ring_buffer_id_); 97 DCHECK_EQ(put_offset_, get_offset_); // Only if it's empty. 98 ring_buffer_ = GetTransferBuffer(transfer_buffer_id); 99 DCHECK(ring_buffer_.ptr); 100 ring_buffer_id_ = transfer_buffer_id; 101 num_entries_ = ring_buffer_.size / sizeof(CommandBufferEntry); 102 put_offset_ = 0; 103 SetGetOffset(0); 104 if (!get_buffer_change_callback_.is_null()) { 105 get_buffer_change_callback_.Run(ring_buffer_id_); 106 } 107 108 UpdateState(); 109} 110 111bool CommandBufferService::SetSharedStateBuffer( 112 scoped_ptr<base::SharedMemory> shared_state_shm) { 113 shared_state_shm_.reset(shared_state_shm.release()); 114 if (!shared_state_shm_->Map(sizeof(*shared_state_))) 115 return false; 116 117 shared_state_ = 118 static_cast<CommandBufferSharedState*>(shared_state_shm_->memory()); 119 120 UpdateState(); 121 return true; 122} 123 124void CommandBufferService::SetGetOffset(int32 get_offset) { 125 DCHECK(get_offset >= 0 && get_offset < num_entries_); 126 get_offset_ = get_offset; 127} 128 129Buffer CommandBufferService::CreateTransferBuffer(size_t size, 130 int32* id) { 131 *id = -1; 132 133 SharedMemory buffer; 134 if (!buffer.CreateAnonymous(size)) 135 return Buffer(); 136 137 static int32 next_id = 1; 138 *id = next_id++; 139 140 if (!RegisterTransferBuffer(*id, &buffer, size)) { 141 *id = -1; 142 return Buffer(); 143 } 144 145 return GetTransferBuffer(*id); 146} 147 148void CommandBufferService::DestroyTransferBuffer(int32 id) { 149 transfer_buffer_manager_->DestroyTransferBuffer(id); 150 if (id == ring_buffer_id_) { 151 ring_buffer_id_ = -1; 152 ring_buffer_ = Buffer(); 153 num_entries_ = 0; 154 get_offset_ = 0; 155 put_offset_ = 0; 156 } 157} 158 159Buffer CommandBufferService::GetTransferBuffer(int32 id) { 160 return transfer_buffer_manager_->GetTransferBuffer(id); 161} 162 163bool CommandBufferService::RegisterTransferBuffer( 164 int32 id, 165 base::SharedMemory* shared_memory, 166 size_t size) { 167 return transfer_buffer_manager_->RegisterTransferBuffer(id, 168 shared_memory, 169 size); 170} 171 172void CommandBufferService::SetToken(int32 token) { 173 token_ = token; 174 UpdateState(); 175} 176 177void CommandBufferService::SetParseError(error::Error error) { 178 if (error_ == error::kNoError) { 179 error_ = error; 180 if (!parse_error_callback_.is_null()) 181 parse_error_callback_.Run(); 182 } 183} 184 185void CommandBufferService::SetContextLostReason( 186 error::ContextLostReason reason) { 187 context_lost_reason_ = reason; 188} 189 190void CommandBufferService::SetPutOffsetChangeCallback( 191 const base::Closure& callback) { 192 put_offset_change_callback_ = callback; 193} 194 195void CommandBufferService::SetGetBufferChangeCallback( 196 const GetBufferChangedCallback& callback) { 197 get_buffer_change_callback_ = callback; 198} 199 200void CommandBufferService::SetParseErrorCallback( 201 const base::Closure& callback) { 202 parse_error_callback_ = callback; 203} 204 205} // namespace gpu 206