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"
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"
18 CommandBufferDelegate::~CommandBufferDelegate() {}
20 void CommandBufferDelegate::ContextLost() {}
21 void CommandBufferDelegate::DrawAnimationFrame() {}
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),
30 next_transfer_buffer_id_(0),
31 initialize_result_(false) {}
33 CommandBufferClientImpl::~CommandBufferClientImpl() {}
35 bool CommandBufferClientImpl::Initialize() {
36 shared_state_shm_.reset(new base::SharedMemory);
37 if (!shared_state_shm_->CreateAndMapAnonymous(
38 sizeof(gpu::CommandBufferSharedState)))
41 base::SharedMemoryHandle handle;
42 shared_state_shm_->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
43 if (!base::SharedMemory::IsHandleValid(handle))
46 shared_state()->Initialize();
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";
58 return initialize_result_;
61 gpu::CommandBuffer::State CommandBufferClientImpl::GetState() {
62 MakeProgressAndUpdateState();
66 gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() {
70 int32 CommandBufferClientImpl::GetLastToken() {
72 return last_state_.token;
75 void CommandBufferClientImpl::Flush(int32 put_offset) {
76 if (last_put_offset_ == put_offset)
79 last_put_offset_ = put_offset;
80 command_buffer_->Flush(put_offset);
83 gpu::CommandBuffer::State CommandBufferClientImpl::FlushSync(
85 int32 last_known_get) {
88 if (last_known_get == last_state_.get_offset)
89 MakeProgressAndUpdateState();
94 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id) {
95 command_buffer_->SetGetBuffer(shm_id);
96 last_put_offset_ = -1;
99 void CommandBufferClientImpl::SetGetOffset(int32 get_offset) {
100 // Not implemented in proxy.
104 gpu::Buffer CommandBufferClientImpl::CreateTransferBuffer(size_t size,
107 if (size >= std::numeric_limits<uint32_t>::max())
110 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
111 if (!shared_memory->CreateAndMapAnonymous(size))
114 base::SharedMemoryHandle handle;
115 shared_memory->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
116 if (!base::SharedMemory::IsHandleValid(handle))
119 *id = ++next_transfer_buffer_id_;
120 DCHECK(transfer_buffers_.find(*id) == transfer_buffers_.end());
122 AllocationScope scope;
123 command_buffer_->RegisterTransferBuffer(
124 *id, handle, static_cast<uint32_t>(size));
126 buffer.ptr = shared_memory->memory();
128 buffer.shared_memory = shared_memory.release();
129 transfer_buffers_[*id] = buffer;
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);
140 command_buffer_->DestroyTransferBuffer(id);
143 gpu::Buffer CommandBufferClientImpl::GetTransferBuffer(int32 id) {
144 TransferBufferMap::iterator it = transfer_buffers_.find(id);
145 if (it != transfer_buffers_.end()) {
148 return gpu::Buffer();
152 void CommandBufferClientImpl::SetToken(int32 token) {
153 // Not implemented in proxy.
157 void CommandBufferClientImpl::SetParseError(gpu::error::Error error) {
158 // Not implemented in proxy.
162 void CommandBufferClientImpl::SetContextLostReason(
163 gpu::error::ContextLostReason reason) {
164 // Not implemented in proxy.
168 gpu::Capabilities CommandBufferClientImpl::GetCapabilities() {
171 return gpu::Capabilities();
174 gfx::GpuMemoryBuffer* CommandBufferClientImpl::CreateGpuMemoryBuffer(
177 unsigned internalformat,
184 void CommandBufferClientImpl::DestroyGpuMemoryBuffer(int32 id) {
189 uint32 CommandBufferClientImpl::InsertSyncPoint() {
195 void CommandBufferClientImpl::SignalSyncPoint(uint32 sync_point,
196 const base::Closure& callback) {
201 void CommandBufferClientImpl::SignalQuery(uint32 query,
202 const base::Closure& callback) {
207 void CommandBufferClientImpl::SetSurfaceVisible(bool visible) {
212 void CommandBufferClientImpl::SendManagedMemoryStats(
213 const gpu::ManagedMemoryStats& stats) {
218 void CommandBufferClientImpl::Echo(const base::Closure& callback) {
219 echo_closures_.push(callback);
220 command_buffer_->Echo();
223 uint32 CommandBufferClientImpl::CreateStreamTexture(uint32 texture_id) {
229 void CommandBufferClientImpl::RequestAnimationFrames() {
230 command_buffer_->RequestAnimationFrames();
233 void CommandBufferClientImpl::CancelAnimationFrames() {
234 command_buffer_->CancelAnimationFrames();
237 void CommandBufferClientImpl::DidInitialize(bool success) {
238 initialize_result_ = success;
241 void CommandBufferClientImpl::DidMakeProgress(const CommandBufferState& state) {
242 if (state.generation() - last_state_.generation < 0x80000000U)
246 void CommandBufferClientImpl::DidDestroy() {
247 LostContext(gpu::error::kUnknown);
250 void CommandBufferClientImpl::EchoAck() {
251 base::Closure closure = echo_closures_.front();
252 echo_closures_.pop();
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();
263 void CommandBufferClientImpl::OnError() { LostContext(gpu::error::kUnknown); }
265 void CommandBufferClientImpl::TryUpdateState() {
266 if (last_state_.error == gpu::error::kNoError)
267 shared_state()->Read(&last_state_);
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?
280 void CommandBufferClientImpl::DrawAnimationFrame() {
281 delegate_->DrawAnimationFrame();