blob: f2444b31e9f091fd7f67c9bd41f5bcd583b385ed [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// 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"
Benjamin Lermancdfc88d2015-02-03 14:35:12 +010010#include "base/trace_event/trace_event.h"
James Robinson646469d2014-10-03 15:33:28 -070011#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::GetLastState() {
41 State state;
James Robinson646469d2014-10-03 15:33:28 -070042 state.get_offset = get_offset_;
James Robinson646469d2014-10-03 15:33:28 -070043 state.token = token_;
44 state.error = error_;
45 state.context_lost_reason = context_lost_reason_;
46 state.generation = ++generation_;
47
48 return state;
49}
50
51int32 CommandBufferService::GetLastToken() {
52 return GetLastState().token;
53}
54
55void CommandBufferService::UpdateState() {
56 if (shared_state_) {
57 CommandBufferService::State state = GetLastState();
58 shared_state_->Write(state);
59 }
60}
61
62void CommandBufferService::WaitForTokenInRange(int32 start, int32 end) {
63 DCHECK(error_ != error::kNoError || InRange(start, end, token_));
64}
65
66void CommandBufferService::WaitForGetOffsetInRange(int32 start, int32 end) {
67 DCHECK(error_ != error::kNoError || InRange(start, end, get_offset_));
68}
69
70void CommandBufferService::Flush(int32 put_offset) {
71 if (put_offset < 0 || put_offset > num_entries_) {
72 error_ = gpu::error::kOutOfBounds;
73 return;
74 }
75
76 put_offset_ = put_offset;
77
78 if (!put_offset_change_callback_.is_null())
79 put_offset_change_callback_.Run();
80}
81
James Robinson7b766f42015-02-06 15:14:04 -080082void CommandBufferService::OrderingBarrier(int32 put_offset) {
83 Flush(put_offset);
84}
85
James Robinson646469d2014-10-03 15:33:28 -070086void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) {
87 DCHECK_EQ(-1, ring_buffer_id_);
88 DCHECK_EQ(put_offset_, get_offset_); // Only if it's empty.
89 // If the buffer is invalid we handle it gracefully.
90 // This means ring_buffer_ can be NULL.
91 ring_buffer_ = GetTransferBuffer(transfer_buffer_id);
92 ring_buffer_id_ = transfer_buffer_id;
93 int32 size = ring_buffer_.get() ? ring_buffer_->size() : 0;
94 num_entries_ = size / sizeof(CommandBufferEntry);
95 put_offset_ = 0;
96 SetGetOffset(0);
97 if (!get_buffer_change_callback_.is_null()) {
98 get_buffer_change_callback_.Run(ring_buffer_id_);
99 }
100
101 UpdateState();
102}
103
104void CommandBufferService::SetSharedStateBuffer(
105 scoped_ptr<BufferBacking> shared_state_buffer) {
106 shared_state_buffer_ = shared_state_buffer.Pass();
107 DCHECK(shared_state_buffer_->GetSize() >= sizeof(*shared_state_));
108
109 shared_state_ =
110 static_cast<CommandBufferSharedState*>(shared_state_buffer_->GetMemory());
111
112 UpdateState();
113}
114
115void CommandBufferService::SetGetOffset(int32 get_offset) {
116 DCHECK(get_offset >= 0 && get_offset < num_entries_);
117 get_offset_ = get_offset;
118}
119
120scoped_refptr<Buffer> CommandBufferService::CreateTransferBuffer(size_t size,
121 int32* id) {
122 *id = -1;
123
124 scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
125 if (!shared_memory->CreateAndMapAnonymous(size))
126 return NULL;
127
128 static int32 next_id = 1;
129 *id = next_id++;
130
131 if (!RegisterTransferBuffer(
132 *id, MakeBackingFromSharedMemory(shared_memory.Pass(), size))) {
133 *id = -1;
134 return NULL;
135 }
136
137 return GetTransferBuffer(*id);
138}
139
140void CommandBufferService::DestroyTransferBuffer(int32 id) {
141 transfer_buffer_manager_->DestroyTransferBuffer(id);
142 if (id == ring_buffer_id_) {
143 ring_buffer_id_ = -1;
144 ring_buffer_ = NULL;
145 num_entries_ = 0;
146 get_offset_ = 0;
147 put_offset_ = 0;
148 }
149}
150
151scoped_refptr<Buffer> CommandBufferService::GetTransferBuffer(int32 id) {
152 return transfer_buffer_manager_->GetTransferBuffer(id);
153}
154
155bool CommandBufferService::RegisterTransferBuffer(
156 int32 id,
157 scoped_ptr<BufferBacking> buffer) {
158 return transfer_buffer_manager_->RegisterTransferBuffer(id, buffer.Pass());
159}
160
161void CommandBufferService::SetToken(int32 token) {
162 token_ = token;
163 UpdateState();
164}
165
166void CommandBufferService::SetParseError(error::Error error) {
167 if (error_ == error::kNoError) {
168 error_ = error;
169 if (!parse_error_callback_.is_null())
170 parse_error_callback_.Run();
171 }
172}
173
174void CommandBufferService::SetContextLostReason(
175 error::ContextLostReason reason) {
176 context_lost_reason_ = reason;
177}
178
James Robinson1ae030a2014-11-07 08:32:47 -0800179int32 CommandBufferService::GetPutOffset() {
180 return put_offset_;
181}
182
James Robinson646469d2014-10-03 15:33:28 -0700183void CommandBufferService::SetPutOffsetChangeCallback(
184 const base::Closure& callback) {
185 put_offset_change_callback_ = callback;
186}
187
188void CommandBufferService::SetGetBufferChangeCallback(
189 const GetBufferChangedCallback& callback) {
190 get_buffer_change_callback_ = callback;
191}
192
193void CommandBufferService::SetParseErrorCallback(
194 const base::Closure& callback) {
195 parse_error_callback_ = callback;
196}
197
198} // namespace gpu