Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / mojo / gles2 / command_buffer_client_impl.cc
1 // Copyright 2014 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 "mojo/gles2/command_buffer_client_impl.h"
6
7 #include <limits>
8
9 #include "base/logging.h"
10 #include "base/process/process_handle.h"
11 #include "mojo/public/bindings/allocation_scope.h"
12 #include "mojo/public/bindings/sync_dispatcher.h"
13 #include "mojo/services/gles2/command_buffer_type_conversions.h"
14
15 namespace mojo {
16 namespace gles2 {
17
18 CommandBufferDelegate::~CommandBufferDelegate() {}
19
20 void CommandBufferDelegate::ContextLost() {}
21 void CommandBufferDelegate::DrawAnimationFrame() {}
22
23 CommandBufferClientImpl::CommandBufferClientImpl(
24     CommandBufferDelegate* delegate,
25     MojoAsyncWaiter* async_waiter,
26     ScopedCommandBufferHandle command_buffer_handle)
27     : delegate_(delegate),
28       command_buffer_(command_buffer_handle.Pass(), this, this, async_waiter),
29       last_put_offset_(-1),
30       next_transfer_buffer_id_(0),
31       initialize_result_(false) {}
32
33 CommandBufferClientImpl::~CommandBufferClientImpl() {}
34
35 bool CommandBufferClientImpl::Initialize() {
36   shared_state_shm_.reset(new base::SharedMemory);
37   if (!shared_state_shm_->CreateAndMapAnonymous(
38            sizeof(gpu::CommandBufferSharedState)))
39     return false;
40
41   base::SharedMemoryHandle handle;
42   shared_state_shm_->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
43   if (!base::SharedMemory::IsHandleValid(handle))
44     return false;
45
46   shared_state()->Initialize();
47
48   InterfacePipe<CommandBufferSyncClient, NoInterface> sync_pipe;
49   sync_dispatcher_.reset(new SyncDispatcher<CommandBufferSyncClient>(
50       sync_pipe.handle_to_peer.Pass(), this));
51   AllocationScope scope;
52   command_buffer_->Initialize(sync_pipe.handle_to_self.Pass(), handle);
53   // Wait for DidInitialize to come on the sync client pipe.
54   if (!sync_dispatcher_->WaitAndDispatchOneMessage()) {
55     VLOG(1) << "Channel encountered error while creating command buffer";
56     return false;
57   }
58   return initialize_result_;
59 }
60
61 gpu::CommandBuffer::State CommandBufferClientImpl::GetState() {
62   MakeProgressAndUpdateState();
63   return last_state_;
64 }
65
66 gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() {
67   return last_state_;
68 }
69
70 int32 CommandBufferClientImpl::GetLastToken() {
71   TryUpdateState();
72   return last_state_.token;
73 }
74
75 void CommandBufferClientImpl::Flush(int32 put_offset) {
76   if (last_put_offset_ == put_offset)
77     return;
78
79   last_put_offset_ = put_offset;
80   command_buffer_->Flush(put_offset);
81 }
82
83 gpu::CommandBuffer::State CommandBufferClientImpl::FlushSync(
84     int32 put_offset,
85     int32 last_known_get) {
86   Flush(put_offset);
87   TryUpdateState();
88   if (last_known_get == last_state_.get_offset)
89     MakeProgressAndUpdateState();
90
91   return last_state_;
92 }
93
94 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id) {
95   command_buffer_->SetGetBuffer(shm_id);
96   last_put_offset_ = -1;
97 }
98
99 void CommandBufferClientImpl::SetGetOffset(int32 get_offset) {
100   // Not implemented in proxy.
101   NOTREACHED();
102 }
103
104 gpu::Buffer CommandBufferClientImpl::CreateTransferBuffer(size_t size,
105                                                           int32* id) {
106   gpu::Buffer buffer;
107   if (size >= std::numeric_limits<uint32_t>::max())
108     return buffer;
109
110   scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
111   if (!shared_memory->CreateAndMapAnonymous(size))
112     return buffer;
113
114   base::SharedMemoryHandle handle;
115   shared_memory->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
116   if (!base::SharedMemory::IsHandleValid(handle))
117     return buffer;
118
119   *id = ++next_transfer_buffer_id_;
120   DCHECK(transfer_buffers_.find(*id) == transfer_buffers_.end());
121
122   AllocationScope scope;
123   command_buffer_->RegisterTransferBuffer(
124       *id, handle, static_cast<uint32_t>(size));
125
126   buffer.ptr = shared_memory->memory();
127   buffer.size = size;
128   buffer.shared_memory = shared_memory.release();
129   transfer_buffers_[*id] = buffer;
130
131   return buffer;
132 }
133
134 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id) {
135   TransferBufferMap::iterator it = transfer_buffers_.find(id);
136   if (it != transfer_buffers_.end()) {
137     delete it->second.shared_memory;
138     transfer_buffers_.erase(it);
139   }
140   command_buffer_->DestroyTransferBuffer(id);
141 }
142
143 gpu::Buffer CommandBufferClientImpl::GetTransferBuffer(int32 id) {
144   TransferBufferMap::iterator it = transfer_buffers_.find(id);
145   if (it != transfer_buffers_.end()) {
146     return it->second;
147   } else {
148     return gpu::Buffer();
149   }
150 }
151
152 void CommandBufferClientImpl::SetToken(int32 token) {
153   // Not implemented in proxy.
154   NOTREACHED();
155 }
156
157 void CommandBufferClientImpl::SetParseError(gpu::error::Error error) {
158   // Not implemented in proxy.
159   NOTREACHED();
160 }
161
162 void CommandBufferClientImpl::SetContextLostReason(
163     gpu::error::ContextLostReason reason) {
164   // Not implemented in proxy.
165   NOTREACHED();
166 }
167
168 gpu::Capabilities CommandBufferClientImpl::GetCapabilities() {
169   // TODO(piman)
170   NOTIMPLEMENTED();
171   return gpu::Capabilities();
172 }
173
174 gfx::GpuMemoryBuffer* CommandBufferClientImpl::CreateGpuMemoryBuffer(
175     size_t width,
176     size_t height,
177     unsigned internalformat,
178     int32* id) {
179   // TODO(piman)
180   NOTIMPLEMENTED();
181   return NULL;
182 }
183
184 void CommandBufferClientImpl::DestroyGpuMemoryBuffer(int32 id) {
185   // TODO(piman)
186   NOTIMPLEMENTED();
187 }
188
189 uint32 CommandBufferClientImpl::InsertSyncPoint() {
190   // TODO(piman)
191   NOTIMPLEMENTED();
192   return 0;
193 }
194
195 void CommandBufferClientImpl::SignalSyncPoint(uint32 sync_point,
196                                               const base::Closure& callback) {
197   // TODO(piman)
198   NOTIMPLEMENTED();
199 }
200
201 void CommandBufferClientImpl::SignalQuery(uint32 query,
202                                           const base::Closure& callback) {
203   // TODO(piman)
204   NOTIMPLEMENTED();
205 }
206
207 void CommandBufferClientImpl::SetSurfaceVisible(bool visible) {
208   // TODO(piman)
209   NOTIMPLEMENTED();
210 }
211
212 void CommandBufferClientImpl::SendManagedMemoryStats(
213     const gpu::ManagedMemoryStats& stats) {
214   // TODO(piman)
215   NOTIMPLEMENTED();
216 }
217
218 void CommandBufferClientImpl::Echo(const base::Closure& callback) {
219   echo_closures_.push(callback);
220   command_buffer_->Echo();
221 }
222
223 uint32 CommandBufferClientImpl::CreateStreamTexture(uint32 texture_id) {
224   // TODO(piman)
225   NOTIMPLEMENTED();
226   return 0;
227 }
228
229 void CommandBufferClientImpl::RequestAnimationFrames() {
230   command_buffer_->RequestAnimationFrames();
231 }
232
233 void CommandBufferClientImpl::CancelAnimationFrames() {
234   command_buffer_->CancelAnimationFrames();
235 }
236
237 void CommandBufferClientImpl::DidInitialize(bool success) {
238   initialize_result_ = success;
239 }
240
241 void CommandBufferClientImpl::DidMakeProgress(const CommandBufferState& state) {
242   if (state.generation() - last_state_.generation < 0x80000000U)
243     last_state_ = state;
244 }
245
246 void CommandBufferClientImpl::DidDestroy() {
247   LostContext(gpu::error::kUnknown);
248 }
249
250 void CommandBufferClientImpl::EchoAck() {
251   base::Closure closure = echo_closures_.front();
252   echo_closures_.pop();
253   closure.Run();
254 }
255
256 void CommandBufferClientImpl::LostContext(int32_t lost_reason) {
257   last_state_.error = gpu::error::kLostContext;
258   last_state_.context_lost_reason =
259       static_cast<gpu::error::ContextLostReason>(lost_reason);
260   delegate_->ContextLost();
261 }
262
263 void CommandBufferClientImpl::OnError() { LostContext(gpu::error::kUnknown); }
264
265 void CommandBufferClientImpl::TryUpdateState() {
266   if (last_state_.error == gpu::error::kNoError)
267     shared_state()->Read(&last_state_);
268 }
269
270 void CommandBufferClientImpl::MakeProgressAndUpdateState() {
271   command_buffer_->MakeProgress(last_state_.get_offset);
272   if (!sync_dispatcher_->WaitAndDispatchOneMessage()) {
273     VLOG(1) << "Channel encountered error while waiting for command buffer";
274     // TODO(piman): is it ok for this to re-enter?
275     DidDestroy();
276     return;
277   }
278 }
279
280 void CommandBufferClientImpl::DrawAnimationFrame() {
281   delegate_->DrawAnimationFrame();
282 }
283
284 }  // namespace gles2
285 }  // namespace mojo