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();