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 15 using ::base::SharedMemory; 16 17 namespace gpu { 18 19 CommandBufferService::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 33 CommandBufferService::~CommandBufferService() { 34 } 35 36 bool CommandBufferService::Initialize() { 37 return true; 38 } 39 40 CommandBufferService::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 53 CommandBufferService::State CommandBufferService::GetLastState() { 54 return GetState(); 55 } 56 57 int32 CommandBufferService::GetLastToken() { 58 return GetState().token; 59 } 60 61 void CommandBufferService::UpdateState() { 62 if (shared_state_) { 63 CommandBufferService::State state = GetState(); 64 shared_state_->Write(state); 65 } 66 } 67 68 CommandBufferService::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 83 void 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 95 void 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 111 bool 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 124 void CommandBufferService::SetGetOffset(int32 get_offset) { 125 DCHECK(get_offset >= 0 && get_offset < num_entries_); 126 get_offset_ = get_offset; 127 } 128 129 Buffer 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 148 void 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 159 Buffer CommandBufferService::GetTransferBuffer(int32 id) { 160 return transfer_buffer_manager_->GetTransferBuffer(id); 161 } 162 163 bool 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 172 void CommandBufferService::SetToken(int32 token) { 173 token_ = token; 174 UpdateState(); 175 } 176 177 void 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 185 void CommandBufferService::SetContextLostReason( 186 error::ContextLostReason reason) { 187 context_lost_reason_ = reason; 188 } 189 190 void CommandBufferService::SetPutOffsetChangeCallback( 191 const base::Closure& callback) { 192 put_offset_change_callback_ = callback; 193 } 194 195 void CommandBufferService::SetGetBufferChangeCallback( 196 const GetBufferChangedCallback& callback) { 197 get_buffer_change_callback_ = callback; 198 } 199 200 void CommandBufferService::SetParseErrorCallback( 201 const base::Closure& callback) { 202 parse_error_callback_ = callback; 203 } 204 205 } // namespace gpu 206