Cleanup: Pass std::string as const reference from chromeos/
[chromium-blink-merge.git] / mojo / gles2 / command_buffer_client_impl.cc
blobb34d438078400d12ebb164b47afe11212a56bd4b
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.
5 #include "mojo/gles2/command_buffer_client_impl.h"
7 #include <limits>
9 #include "base/logging.h"
10 #include "base/process/process_handle.h"
11 #include "components/mus/gles2/command_buffer_type_conversions.h"
12 #include "components/mus/gles2/mojo_buffer_backing.h"
13 #include "components/mus/gles2/mojo_gpu_memory_buffer.h"
14 #include "gpu/command_buffer/service/image_factory.h"
15 #include "mojo/platform_handle/platform_handle_functions.h"
17 namespace gles2 {
19 namespace {
21 bool CreateMapAndDupSharedBuffer(size_t size,
22 void** memory,
23 mojo::ScopedSharedBufferHandle* handle,
24 mojo::ScopedSharedBufferHandle* duped) {
25 MojoResult result = mojo::CreateSharedBuffer(NULL, size, handle);
26 if (result != MOJO_RESULT_OK)
27 return false;
28 DCHECK(handle->is_valid());
30 result = mojo::DuplicateBuffer(handle->get(), NULL, duped);
31 if (result != MOJO_RESULT_OK)
32 return false;
33 DCHECK(duped->is_valid());
35 result = mojo::MapBuffer(
36 handle->get(), 0, size, memory, MOJO_MAP_BUFFER_FLAG_NONE);
37 if (result != MOJO_RESULT_OK)
38 return false;
39 DCHECK(*memory);
41 return true;
44 } // namespace
46 CommandBufferDelegate::~CommandBufferDelegate() {}
48 void CommandBufferDelegate::ContextLost() {}
50 class CommandBufferClientImpl::SyncClientImpl
51 : public mojo::CommandBufferSyncClient {
52 public:
53 SyncClientImpl(mojo::CommandBufferSyncClientPtr* ptr,
54 const MojoAsyncWaiter* async_waiter)
55 : initialized_successfully_(false), binding_(this, ptr, async_waiter) {}
57 bool WaitForInitialization() {
58 if (!binding_.WaitForIncomingMethodCall())
59 return false;
60 return initialized_successfully_;
63 mojo::CommandBufferStatePtr WaitForProgress() {
64 if (!binding_.WaitForIncomingMethodCall())
65 return mojo::CommandBufferStatePtr();
66 return command_buffer_state_.Pass();
69 gpu::Capabilities GetCapabilities() {
70 if (capabilities_)
71 return capabilities_.To<gpu::Capabilities>();
72 return gpu::Capabilities();
75 private:
76 // CommandBufferSyncClient methods:
77 void DidInitialize(bool success,
78 mojo::GpuCapabilitiesPtr capabilities) override {
79 initialized_successfully_ = success;
80 capabilities_ = capabilities.Pass();
82 void DidMakeProgress(mojo::CommandBufferStatePtr state) override {
83 command_buffer_state_ = state.Pass();
86 bool initialized_successfully_;
87 mojo::GpuCapabilitiesPtr capabilities_;
88 mojo::CommandBufferStatePtr command_buffer_state_;
89 mojo::Binding<mojo::CommandBufferSyncClient> binding_;
91 DISALLOW_COPY_AND_ASSIGN(SyncClientImpl);
94 class CommandBufferClientImpl::SyncPointClientImpl
95 : public mojo::CommandBufferSyncPointClient {
96 public:
97 SyncPointClientImpl(mojo::CommandBufferSyncPointClientPtr* ptr,
98 const MojoAsyncWaiter* async_waiter)
99 : sync_point_(0u), binding_(this, ptr, async_waiter) {}
101 uint32_t WaitForInsertSyncPoint() {
102 if (!binding_.WaitForIncomingMethodCall())
103 return 0u;
104 uint32_t result = sync_point_;
105 sync_point_ = 0u;
106 return result;
109 private:
110 void DidInsertSyncPoint(uint32_t sync_point) override {
111 sync_point_ = sync_point;
114 uint32_t sync_point_;
116 mojo::Binding<mojo::CommandBufferSyncPointClient> binding_;
119 CommandBufferClientImpl::CommandBufferClientImpl(
120 CommandBufferDelegate* delegate,
121 const std::vector<int32_t>& attribs,
122 const MojoAsyncWaiter* async_waiter,
123 mojo::ScopedMessagePipeHandle command_buffer_handle)
124 : delegate_(delegate),
125 attribs_(attribs),
126 observer_binding_(this),
127 shared_state_(NULL),
128 last_put_offset_(-1),
129 next_transfer_buffer_id_(0),
130 next_image_id_(0),
131 async_waiter_(async_waiter) {
132 command_buffer_.Bind(mojo::InterfacePtrInfo<mojo::CommandBuffer>(
133 command_buffer_handle.Pass(), 0u),
134 async_waiter);
135 command_buffer_.set_connection_error_handler(
136 [this]() { DidLoseContext(gpu::error::kUnknown); });
139 CommandBufferClientImpl::~CommandBufferClientImpl() {}
141 bool CommandBufferClientImpl::Initialize() {
142 const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState);
143 void* memory = NULL;
144 mojo::ScopedSharedBufferHandle duped;
145 bool result = CreateMapAndDupSharedBuffer(
146 kSharedStateSize, &memory, &shared_state_handle_, &duped);
147 if (!result)
148 return false;
150 shared_state_ = static_cast<gpu::CommandBufferSharedState*>(memory);
152 shared_state()->Initialize();
154 mojo::CommandBufferSyncClientPtr sync_client;
155 sync_client_impl_.reset(new SyncClientImpl(&sync_client, async_waiter_));
157 mojo::CommandBufferSyncPointClientPtr sync_point_client;
158 sync_point_client_impl_.reset(
159 new SyncPointClientImpl(&sync_point_client, async_waiter_));
161 mojo::CommandBufferLostContextObserverPtr observer_ptr;
162 observer_binding_.Bind(GetProxy(&observer_ptr), async_waiter_);
163 command_buffer_->Initialize(sync_client.Pass(),
164 sync_point_client.Pass(),
165 observer_ptr.Pass(),
166 duped.Pass(),
167 mojo::Array<int32_t>::From(attribs_));
169 // Wait for DidInitialize to come on the sync client pipe.
170 if (!sync_client_impl_->WaitForInitialization()) {
171 VLOG(1) << "Channel encountered error while creating command buffer";
172 return false;
174 capabilities_ = sync_client_impl_->GetCapabilities();
175 return true;
178 gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() {
179 return last_state_;
182 int32 CommandBufferClientImpl::GetLastToken() {
183 TryUpdateState();
184 return last_state_.token;
187 void CommandBufferClientImpl::Flush(int32 put_offset) {
188 if (last_put_offset_ == put_offset)
189 return;
191 last_put_offset_ = put_offset;
192 command_buffer_->Flush(put_offset);
195 void CommandBufferClientImpl::OrderingBarrier(int32_t put_offset) {
196 // TODO(jamesr): Implement this more efficiently.
197 Flush(put_offset);
200 void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) {
201 TryUpdateState();
202 while (!InRange(start, end, last_state_.token) &&
203 last_state_.error == gpu::error::kNoError) {
204 MakeProgressAndUpdateState();
205 TryUpdateState();
209 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start, int32 end) {
210 TryUpdateState();
211 while (!InRange(start, end, last_state_.get_offset) &&
212 last_state_.error == gpu::error::kNoError) {
213 MakeProgressAndUpdateState();
214 TryUpdateState();
218 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id) {
219 command_buffer_->SetGetBuffer(shm_id);
220 last_put_offset_ = -1;
223 scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer(
224 size_t size,
225 int32* id) {
226 if (size >= std::numeric_limits<uint32_t>::max())
227 return NULL;
229 void* memory = NULL;
230 mojo::ScopedSharedBufferHandle handle;
231 mojo::ScopedSharedBufferHandle duped;
232 if (!CreateMapAndDupSharedBuffer(size, &memory, &handle, &duped)) {
233 if (last_state_.error == gpu::error::kNoError)
234 last_state_.error = gpu::error::kLostContext;
235 return NULL;
238 *id = ++next_transfer_buffer_id_;
240 command_buffer_->RegisterTransferBuffer(
241 *id, duped.Pass(), static_cast<uint32_t>(size));
243 scoped_ptr<gpu::BufferBacking> backing(
244 new mus::MojoBufferBacking(handle.Pass(), memory, size));
245 scoped_refptr<gpu::Buffer> buffer(new gpu::Buffer(backing.Pass()));
246 return buffer;
249 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id) {
250 command_buffer_->DestroyTransferBuffer(id);
253 gpu::Capabilities CommandBufferClientImpl::GetCapabilities() {
254 return capabilities_;
257 int32_t CommandBufferClientImpl::CreateImage(ClientBuffer buffer,
258 size_t width,
259 size_t height,
260 unsigned internalformat) {
261 int32 new_id = ++next_image_id_;
263 mojo::SizePtr size = mojo::Size::New();
264 size->width = static_cast<int32_t>(width);
265 size->height = static_cast<int32_t>(height);
267 mus::MojoGpuMemoryBufferImpl* gpu_memory_buffer =
268 mus::MojoGpuMemoryBufferImpl::FromClientBuffer(buffer);
269 gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->GetHandle();
271 bool requires_sync_point = false;
272 base::SharedMemoryHandle dupd_handle =
273 base::SharedMemory::DuplicateHandle(handle.handle);
274 #if defined(OS_WIN)
275 HANDLE platform_handle = dupd_handle;
276 #else
277 int platform_handle = dupd_handle.fd;
278 #endif
280 if (handle.type != gfx::SHARED_MEMORY_BUFFER) {
281 requires_sync_point = true;
282 NOTIMPLEMENTED();
283 return -1;
286 MojoHandle mojo_handle = MOJO_HANDLE_INVALID;
287 MojoResult create_result = MojoCreatePlatformHandleWrapper(
288 platform_handle, &mojo_handle);
289 if (create_result != MOJO_RESULT_OK) {
290 NOTIMPLEMENTED();
291 return -1;
293 mojo::ScopedHandle scoped_handle;
294 scoped_handle.reset(mojo::Handle(mojo_handle));
295 command_buffer_->CreateImage(
296 new_id, scoped_handle.Pass(), handle.type, size.Pass(),
297 static_cast<int32_t>(gpu_memory_buffer->GetFormat()), internalformat);
298 if (requires_sync_point) {
299 NOTIMPLEMENTED();
300 // TODO(jam): need to support this if we support types other than
301 // SHARED_MEMORY_BUFFER.
302 //gpu_memory_buffer_manager->SetDestructionSyncPoint(gpu_memory_buffer,
303 // InsertSyncPoint());
306 return new_id;
309 void CommandBufferClientImpl::DestroyImage(int32 id) {
310 command_buffer_->DestroyImage(id);
313 int32_t CommandBufferClientImpl::CreateGpuMemoryBufferImage(
314 size_t width,
315 size_t height,
316 unsigned internalformat,
317 unsigned usage) {
318 scoped_ptr<gfx::GpuMemoryBuffer> buffer(mus::MojoGpuMemoryBufferImpl::Create(
319 gfx::Size(static_cast<int>(width), static_cast<int>(height)),
320 gpu::ImageFactory::DefaultBufferFormatForImageFormat(internalformat),
321 gpu::ImageFactory::ImageUsageToGpuMemoryBufferUsage(usage)));
322 if (!buffer)
323 return -1;
325 return CreateImage(buffer->AsClientBuffer(), width, height, internalformat);
328 uint32_t CommandBufferClientImpl::InsertSyncPoint() {
329 command_buffer_->InsertSyncPoint(true);
330 return sync_point_client_impl_->WaitForInsertSyncPoint();
333 uint32_t CommandBufferClientImpl::InsertFutureSyncPoint() {
334 command_buffer_->InsertSyncPoint(false);
335 return sync_point_client_impl_->WaitForInsertSyncPoint();
338 void CommandBufferClientImpl::RetireSyncPoint(uint32_t sync_point) {
339 command_buffer_->RetireSyncPoint(sync_point);
342 void CommandBufferClientImpl::SignalSyncPoint(uint32_t sync_point,
343 const base::Closure& callback) {
344 // TODO(piman)
347 void CommandBufferClientImpl::SignalQuery(uint32_t query,
348 const base::Closure& callback) {
349 // TODO(piman)
350 NOTIMPLEMENTED();
353 void CommandBufferClientImpl::SetSurfaceVisible(bool visible) {
354 // TODO(piman)
355 NOTIMPLEMENTED();
358 uint32_t CommandBufferClientImpl::CreateStreamTexture(uint32_t texture_id) {
359 // TODO(piman)
360 NOTIMPLEMENTED();
361 return 0;
364 void CommandBufferClientImpl::DidLoseContext(int32_t lost_reason) {
365 last_state_.error = gpu::error::kLostContext;
366 last_state_.context_lost_reason =
367 static_cast<gpu::error::ContextLostReason>(lost_reason);
368 delegate_->ContextLost();
371 void CommandBufferClientImpl::TryUpdateState() {
372 if (last_state_.error == gpu::error::kNoError)
373 shared_state()->Read(&last_state_);
376 void CommandBufferClientImpl::MakeProgressAndUpdateState() {
377 command_buffer_->MakeProgress(last_state_.get_offset);
379 mojo::CommandBufferStatePtr state = sync_client_impl_->WaitForProgress();
380 if (!state) {
381 VLOG(1) << "Channel encountered error while waiting for command buffer";
382 // TODO(piman): is it ok for this to re-enter?
383 DidLoseContext(gpu::error::kUnknown);
384 return;
387 if (state->generation - last_state_.generation < 0x80000000U)
388 last_state_ = state.To<State>();
391 void CommandBufferClientImpl::SetLock(base::Lock* lock) {
394 bool CommandBufferClientImpl::IsGpuChannelLost() {
395 // This is only possible for out-of-process command buffers.
396 return false;
399 gpu::CommandBufferNamespace CommandBufferClientImpl::GetNamespaceID() const {
400 return gpu::CommandBufferNamespace::MOJO;
403 uint64_t CommandBufferClientImpl::GetCommandBufferID() const {
404 // TODO (rjkroege): This must correspond to the command buffer ID on the
405 // server side. Most likely a combination of the client-specific integer and
406 // the connect id.
407 NOTIMPLEMENTED();
408 return 0;
411 } // namespace gles2