Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / command_buffer_service.cc
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::GetLastState() {
41   State state;
42   state.get_offset = get_offset_;
43   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
51 int32 CommandBufferService::GetLastToken() {
52   return GetLastState().token;
53 }
54
55 void CommandBufferService::UpdateState() {
56   if (shared_state_) {
57     CommandBufferService::State state = GetLastState();
58     shared_state_->Write(state);
59   }
60 }
61
62 void CommandBufferService::WaitForTokenInRange(int32 start, int32 end) {
63   DCHECK(error_ != error::kNoError || InRange(start, end, token_));
64 }
65
66 void CommandBufferService::WaitForGetOffsetInRange(int32 start, int32 end) {
67   DCHECK(error_ != error::kNoError || InRange(start, end, get_offset_));
68 }
69
70 void 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
82 void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) {
83   DCHECK_EQ(-1, ring_buffer_id_);
84   DCHECK_EQ(put_offset_, get_offset_);  // Only if it's empty.
85   // If the buffer is invalid we handle it gracefully.
86   // This means ring_buffer_ can be NULL.
87   ring_buffer_ = GetTransferBuffer(transfer_buffer_id);
88   ring_buffer_id_ = transfer_buffer_id;
89   int32 size = ring_buffer_.get() ? ring_buffer_->size() : 0;
90   num_entries_ = size / sizeof(CommandBufferEntry);
91   put_offset_ = 0;
92   SetGetOffset(0);
93   if (!get_buffer_change_callback_.is_null()) {
94     get_buffer_change_callback_.Run(ring_buffer_id_);
95   }
96
97   UpdateState();
98 }
99
100 void CommandBufferService::SetSharedStateBuffer(
101     scoped_ptr<BufferBacking> shared_state_buffer) {
102   shared_state_buffer_ = shared_state_buffer.Pass();
103   DCHECK(shared_state_buffer_->GetSize() >= sizeof(*shared_state_));
104
105   shared_state_ =
106       static_cast<CommandBufferSharedState*>(shared_state_buffer_->GetMemory());
107
108   UpdateState();
109 }
110
111 void CommandBufferService::SetGetOffset(int32 get_offset) {
112   DCHECK(get_offset >= 0 && get_offset < num_entries_);
113   get_offset_ = get_offset;
114 }
115
116 scoped_refptr<Buffer> CommandBufferService::CreateTransferBuffer(size_t size,
117                                                                  int32* id) {
118   *id = -1;
119
120   scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
121   if (!shared_memory->CreateAndMapAnonymous(size))
122     return NULL;
123
124   static int32 next_id = 1;
125   *id = next_id++;
126
127   if (!RegisterTransferBuffer(
128           *id, MakeBackingFromSharedMemory(shared_memory.Pass(), size))) {
129     *id = -1;
130     return NULL;
131   }
132
133   return GetTransferBuffer(*id);
134 }
135
136 void CommandBufferService::DestroyTransferBuffer(int32 id) {
137   transfer_buffer_manager_->DestroyTransferBuffer(id);
138   if (id == ring_buffer_id_) {
139     ring_buffer_id_ = -1;
140     ring_buffer_ = NULL;
141     num_entries_ = 0;
142     get_offset_ = 0;
143     put_offset_ = 0;
144   }
145 }
146
147 scoped_refptr<Buffer> CommandBufferService::GetTransferBuffer(int32 id) {
148   return transfer_buffer_manager_->GetTransferBuffer(id);
149 }
150
151 bool CommandBufferService::RegisterTransferBuffer(
152     int32 id,
153     scoped_ptr<BufferBacking> buffer) {
154   return transfer_buffer_manager_->RegisterTransferBuffer(id, buffer.Pass());
155 }
156
157 void CommandBufferService::SetToken(int32 token) {
158   token_ = token;
159   UpdateState();
160 }
161
162 void CommandBufferService::SetParseError(error::Error error) {
163   if (error_ == error::kNoError) {
164     error_ = error;
165     if (!parse_error_callback_.is_null())
166       parse_error_callback_.Run();
167   }
168 }
169
170 void CommandBufferService::SetContextLostReason(
171     error::ContextLostReason reason) {
172   context_lost_reason_ = reason;
173 }
174
175 int32 CommandBufferService::GetPutOffset() {
176   return put_offset_;
177 }
178
179 void CommandBufferService::SetPutOffsetChangeCallback(
180     const base::Closure& callback) {
181   put_offset_change_callback_ = callback;
182 }
183
184 void CommandBufferService::SetGetBufferChangeCallback(
185     const GetBufferChangedCallback& callback) {
186   get_buffer_change_callback_ = callback;
187 }
188
189 void CommandBufferService::SetParseErrorCallback(
190     const base::Closure& callback) {
191   parse_error_callback_ = callback;
192 }
193
194 }  // namespace gpu