• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/cpp/bindings/sync_dispatcher.h"
12 #include "mojo/services/gles2/command_buffer_type_conversions.h"
13 #include "mojo/services/gles2/mojo_buffer_backing.h"
14 
15 namespace mojo {
16 namespace gles2 {
17 
18 namespace {
19 
CreateMapAndDupSharedBuffer(size_t size,void ** memory,mojo::ScopedSharedBufferHandle * handle,mojo::ScopedSharedBufferHandle * duped)20 bool CreateMapAndDupSharedBuffer(size_t size,
21                                  void** memory,
22                                  mojo::ScopedSharedBufferHandle* handle,
23                                  mojo::ScopedSharedBufferHandle* duped) {
24   MojoResult result = mojo::CreateSharedBuffer(NULL, size, handle);
25   if (result != MOJO_RESULT_OK)
26     return false;
27   DCHECK(handle->is_valid());
28 
29   result = mojo::DuplicateBuffer(handle->get(), NULL, duped);
30   if (result != MOJO_RESULT_OK)
31     return false;
32   DCHECK(duped->is_valid());
33 
34   result = mojo::MapBuffer(
35       handle->get(), 0, size, memory, MOJO_MAP_BUFFER_FLAG_NONE);
36   if (result != MOJO_RESULT_OK)
37     return false;
38   DCHECK(*memory);
39 
40   return true;
41 }
42 }
43 
~CommandBufferDelegate()44 CommandBufferDelegate::~CommandBufferDelegate() {}
45 
ContextLost()46 void CommandBufferDelegate::ContextLost() {}
DrawAnimationFrame()47 void CommandBufferDelegate::DrawAnimationFrame() {}
48 
CommandBufferClientImpl(CommandBufferDelegate * delegate,const MojoAsyncWaiter * async_waiter,ScopedMessagePipeHandle command_buffer_handle)49 CommandBufferClientImpl::CommandBufferClientImpl(
50     CommandBufferDelegate* delegate,
51     const MojoAsyncWaiter* async_waiter,
52     ScopedMessagePipeHandle command_buffer_handle)
53     : delegate_(delegate),
54       shared_state_(NULL),
55       last_put_offset_(-1),
56       next_transfer_buffer_id_(0),
57       initialize_result_(false),
58       async_waiter_(async_waiter) {
59   command_buffer_.Bind(command_buffer_handle.Pass(), async_waiter);
60   command_buffer_.set_error_handler(this);
61   command_buffer_.set_client(this);
62 }
63 
~CommandBufferClientImpl()64 CommandBufferClientImpl::~CommandBufferClientImpl() {}
65 
Initialize()66 bool CommandBufferClientImpl::Initialize() {
67   const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState);
68   void* memory = NULL;
69   mojo::ScopedSharedBufferHandle duped;
70   bool result = CreateMapAndDupSharedBuffer(
71       kSharedStateSize, &memory, &shared_state_handle_, &duped);
72   if (!result)
73     return false;
74 
75   shared_state_ = static_cast<gpu::CommandBufferSharedState*>(memory);
76 
77   shared_state()->Initialize();
78 
79   // TODO(darin): We need better sugar for sync calls.
80   MessagePipe sync_pipe;
81   sync_dispatcher_.reset(new SyncDispatcher<CommandBufferSyncClient>(
82       sync_pipe.handle0.Pass(), this));
83   CommandBufferSyncClientPtr sync_client =
84       MakeProxy<CommandBufferSyncClient>(sync_pipe.handle1.Pass(),
85                                          async_waiter_);
86   command_buffer_->Initialize(sync_client.Pass(), duped.Pass());
87   // Wait for DidInitialize to come on the sync client pipe.
88   if (!sync_dispatcher_->WaitAndDispatchOneMessage()) {
89     VLOG(1) << "Channel encountered error while creating command buffer";
90     return false;
91   }
92   return initialize_result_;
93 }
94 
GetLastState()95 gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() {
96   return last_state_;
97 }
98 
GetLastToken()99 int32 CommandBufferClientImpl::GetLastToken() {
100   TryUpdateState();
101   return last_state_.token;
102 }
103 
Flush(int32 put_offset)104 void CommandBufferClientImpl::Flush(int32 put_offset) {
105   if (last_put_offset_ == put_offset)
106     return;
107 
108   last_put_offset_ = put_offset;
109   command_buffer_->Flush(put_offset);
110 }
111 
WaitForTokenInRange(int32 start,int32 end)112 void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) {
113   TryUpdateState();
114   while (!InRange(start, end, last_state_.token) &&
115          last_state_.error == gpu::error::kNoError) {
116     MakeProgressAndUpdateState();
117     TryUpdateState();
118   }
119 }
120 
WaitForGetOffsetInRange(int32 start,int32 end)121 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start, int32 end) {
122   TryUpdateState();
123   while (!InRange(start, end, last_state_.get_offset) &&
124          last_state_.error == gpu::error::kNoError) {
125     MakeProgressAndUpdateState();
126     TryUpdateState();
127   }
128 }
129 
SetGetBuffer(int32 shm_id)130 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id) {
131   command_buffer_->SetGetBuffer(shm_id);
132   last_put_offset_ = -1;
133 }
134 
CreateTransferBuffer(size_t size,int32 * id)135 scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer(
136     size_t size,
137     int32* id) {
138   if (size >= std::numeric_limits<uint32_t>::max())
139     return NULL;
140 
141   void* memory = NULL;
142   mojo::ScopedSharedBufferHandle handle;
143   mojo::ScopedSharedBufferHandle duped;
144   if (!CreateMapAndDupSharedBuffer(size, &memory, &handle, &duped))
145     return NULL;
146 
147   *id = ++next_transfer_buffer_id_;
148 
149   command_buffer_->RegisterTransferBuffer(
150       *id, duped.Pass(), static_cast<uint32_t>(size));
151 
152   scoped_ptr<gpu::BufferBacking> backing(
153       new MojoBufferBacking(handle.Pass(), memory, size));
154   scoped_refptr<gpu::Buffer> buffer(new gpu::Buffer(backing.Pass()));
155   return buffer;
156 }
157 
DestroyTransferBuffer(int32 id)158 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id) {
159   command_buffer_->DestroyTransferBuffer(id);
160 }
161 
GetCapabilities()162 gpu::Capabilities CommandBufferClientImpl::GetCapabilities() {
163   // TODO(piman)
164   NOTIMPLEMENTED();
165   return gpu::Capabilities();
166 }
167 
CreateGpuMemoryBuffer(size_t width,size_t height,unsigned internalformat,unsigned usage,int32 * id)168 gfx::GpuMemoryBuffer* CommandBufferClientImpl::CreateGpuMemoryBuffer(
169     size_t width,
170     size_t height,
171     unsigned internalformat,
172     unsigned usage,
173     int32* id) {
174   // TODO(piman)
175   NOTIMPLEMENTED();
176   return NULL;
177 }
178 
DestroyGpuMemoryBuffer(int32 id)179 void CommandBufferClientImpl::DestroyGpuMemoryBuffer(int32 id) {
180   // TODO(piman)
181   NOTIMPLEMENTED();
182 }
183 
InsertSyncPoint()184 uint32 CommandBufferClientImpl::InsertSyncPoint() {
185   // TODO(piman)
186   NOTIMPLEMENTED();
187   return 0;
188 }
189 
SignalSyncPoint(uint32 sync_point,const base::Closure & callback)190 void CommandBufferClientImpl::SignalSyncPoint(uint32 sync_point,
191                                               const base::Closure& callback) {
192   // TODO(piman)
193   NOTIMPLEMENTED();
194 }
195 
SignalQuery(uint32 query,const base::Closure & callback)196 void CommandBufferClientImpl::SignalQuery(uint32 query,
197                                           const base::Closure& callback) {
198   // TODO(piman)
199   NOTIMPLEMENTED();
200 }
201 
SetSurfaceVisible(bool visible)202 void CommandBufferClientImpl::SetSurfaceVisible(bool visible) {
203   // TODO(piman)
204   NOTIMPLEMENTED();
205 }
206 
Echo(const base::Closure & callback)207 void CommandBufferClientImpl::Echo(const base::Closure& callback) {
208   command_buffer_->Echo(callback);
209 }
210 
CreateStreamTexture(uint32 texture_id)211 uint32 CommandBufferClientImpl::CreateStreamTexture(uint32 texture_id) {
212   // TODO(piman)
213   NOTIMPLEMENTED();
214   return 0;
215 }
216 
RequestAnimationFrames()217 void CommandBufferClientImpl::RequestAnimationFrames() {
218   command_buffer_->RequestAnimationFrames();
219 }
220 
CancelAnimationFrames()221 void CommandBufferClientImpl::CancelAnimationFrames() {
222   command_buffer_->CancelAnimationFrames();
223 }
224 
DidInitialize(bool success)225 void CommandBufferClientImpl::DidInitialize(bool success) {
226   initialize_result_ = success;
227 }
228 
DidMakeProgress(CommandBufferStatePtr state)229 void CommandBufferClientImpl::DidMakeProgress(CommandBufferStatePtr state) {
230   if (state->generation - last_state_.generation < 0x80000000U)
231     last_state_ = state.To<State>();
232 }
233 
DidDestroy()234 void CommandBufferClientImpl::DidDestroy() {
235   LostContext(gpu::error::kUnknown);
236 }
237 
LostContext(int32_t lost_reason)238 void CommandBufferClientImpl::LostContext(int32_t lost_reason) {
239   last_state_.error = gpu::error::kLostContext;
240   last_state_.context_lost_reason =
241       static_cast<gpu::error::ContextLostReason>(lost_reason);
242   delegate_->ContextLost();
243 }
244 
OnConnectionError()245 void CommandBufferClientImpl::OnConnectionError() {
246   LostContext(gpu::error::kUnknown);
247 }
248 
TryUpdateState()249 void CommandBufferClientImpl::TryUpdateState() {
250   if (last_state_.error == gpu::error::kNoError)
251     shared_state()->Read(&last_state_);
252 }
253 
MakeProgressAndUpdateState()254 void CommandBufferClientImpl::MakeProgressAndUpdateState() {
255   command_buffer_->MakeProgress(last_state_.get_offset);
256   if (!sync_dispatcher_->WaitAndDispatchOneMessage()) {
257     VLOG(1) << "Channel encountered error while waiting for command buffer";
258     // TODO(piman): is it ok for this to re-enter?
259     DidDestroy();
260     return;
261   }
262 }
263 
DrawAnimationFrame()264 void CommandBufferClientImpl::DrawAnimationFrame() {
265   delegate_->DrawAnimationFrame();
266 }
267 
268 }  // namespace gles2
269 }  // namespace mojo
270