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/cpp/bindings/allocation_scope.h"
12 #include "mojo/public/cpp/bindings/sync_dispatcher.h"
13 #include "mojo/services/gles2/command_buffer_type_conversions.h"
14 #include "mojo/services/gles2/mojo_buffer_backing.h"
21 bool CreateMapAndDupSharedBuffer(size_t size
,
23 mojo::ScopedSharedBufferHandle
* handle
,
24 mojo::ScopedSharedBufferHandle
* duped
) {
25 MojoResult result
= mojo::CreateSharedBuffer(NULL
, size
, handle
);
26 if (result
!= MOJO_RESULT_OK
)
28 DCHECK(handle
->is_valid());
30 result
= mojo::DuplicateBuffer(handle
->get(), NULL
, duped
);
31 if (result
!= MOJO_RESULT_OK
)
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
)
45 CommandBufferDelegate::~CommandBufferDelegate() {}
47 void CommandBufferDelegate::ContextLost() {}
48 void CommandBufferDelegate::DrawAnimationFrame() {}
50 CommandBufferClientImpl::CommandBufferClientImpl(
51 CommandBufferDelegate
* delegate
,
52 MojoAsyncWaiter
* async_waiter
,
53 ScopedCommandBufferHandle command_buffer_handle
)
54 : delegate_(delegate
),
55 command_buffer_(command_buffer_handle
.Pass(), this, this, async_waiter
),
58 next_transfer_buffer_id_(0),
59 initialize_result_(false) {}
61 CommandBufferClientImpl::~CommandBufferClientImpl() {}
63 bool CommandBufferClientImpl::Initialize() {
64 const size_t kSharedStateSize
= sizeof(gpu::CommandBufferSharedState
);
66 mojo::ScopedSharedBufferHandle duped
;
67 bool result
= CreateMapAndDupSharedBuffer(
68 kSharedStateSize
, &memory
, &shared_state_handle_
, &duped
);
72 shared_state_
= static_cast<gpu::CommandBufferSharedState
*>(memory
);
74 shared_state()->Initialize();
76 InterfacePipe
<CommandBufferSyncClient
, NoInterface
> sync_pipe
;
77 sync_dispatcher_
.reset(new SyncDispatcher
<CommandBufferSyncClient
>(
78 sync_pipe
.handle_to_peer
.Pass(), this));
79 AllocationScope scope
;
80 command_buffer_
->Initialize(sync_pipe
.handle_to_self
.Pass(), duped
.Pass());
81 // Wait for DidInitialize to come on the sync client pipe.
82 if (!sync_dispatcher_
->WaitAndDispatchOneMessage()) {
83 VLOG(1) << "Channel encountered error while creating command buffer";
86 return initialize_result_
;
89 gpu::CommandBuffer::State
CommandBufferClientImpl::GetState() {
90 MakeProgressAndUpdateState();
94 gpu::CommandBuffer::State
CommandBufferClientImpl::GetLastState() {
98 int32
CommandBufferClientImpl::GetLastToken() {
100 return last_state_
.token
;
103 void CommandBufferClientImpl::Flush(int32 put_offset
) {
104 if (last_put_offset_
== put_offset
)
107 last_put_offset_
= put_offset
;
108 command_buffer_
->Flush(put_offset
);
111 void CommandBufferClientImpl::WaitForTokenInRange(int32 start
, int32 end
) {
113 while (!InRange(start
, end
, last_state_
.token
) &&
114 last_state_
.error
== gpu::error::kNoError
) {
115 MakeProgressAndUpdateState();
120 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start
, int32 end
) {
122 while (!InRange(start
, end
, last_state_
.get_offset
) &&
123 last_state_
.error
== gpu::error::kNoError
) {
124 MakeProgressAndUpdateState();
129 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id
) {
130 command_buffer_
->SetGetBuffer(shm_id
);
131 last_put_offset_
= -1;
134 scoped_refptr
<gpu::Buffer
> CommandBufferClientImpl::CreateTransferBuffer(
137 if (size
>= std::numeric_limits
<uint32_t>::max())
141 mojo::ScopedSharedBufferHandle handle
;
142 mojo::ScopedSharedBufferHandle duped
;
143 if (!CreateMapAndDupSharedBuffer(size
, &memory
, &handle
, &duped
))
146 *id
= ++next_transfer_buffer_id_
;
148 AllocationScope scope
;
149 command_buffer_
->RegisterTransferBuffer(
150 *id
, duped
.Pass(), static_cast<uint32_t>(size
));
152 scoped_ptr
<gpu::BufferBacking
> backing(
153 new MojoBufferBacking(handle
.Pass(), memory
, size
));
154 scoped_refptr
<gpu::Buffer
> buffer(new gpu::Buffer(backing
.Pass()));
158 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id
) {
159 command_buffer_
->DestroyTransferBuffer(id
);
162 gpu::Capabilities
CommandBufferClientImpl::GetCapabilities() {
165 return gpu::Capabilities();
168 gfx::GpuMemoryBuffer
* CommandBufferClientImpl::CreateGpuMemoryBuffer(
171 unsigned internalformat
,
178 void CommandBufferClientImpl::DestroyGpuMemoryBuffer(int32 id
) {
183 uint32
CommandBufferClientImpl::InsertSyncPoint() {
189 void CommandBufferClientImpl::SignalSyncPoint(uint32 sync_point
,
190 const base::Closure
& callback
) {
195 void CommandBufferClientImpl::SignalQuery(uint32 query
,
196 const base::Closure
& callback
) {
201 void CommandBufferClientImpl::SetSurfaceVisible(bool visible
) {
206 void CommandBufferClientImpl::SendManagedMemoryStats(
207 const gpu::ManagedMemoryStats
& stats
) {
212 void CommandBufferClientImpl::Echo(const base::Closure
& callback
) {
213 command_buffer_
->Echo(callback
);
216 uint32
CommandBufferClientImpl::CreateStreamTexture(uint32 texture_id
) {
222 void CommandBufferClientImpl::RequestAnimationFrames() {
223 command_buffer_
->RequestAnimationFrames();
226 void CommandBufferClientImpl::CancelAnimationFrames() {
227 command_buffer_
->CancelAnimationFrames();
230 void CommandBufferClientImpl::DidInitialize(bool success
) {
231 initialize_result_
= success
;
234 void CommandBufferClientImpl::DidMakeProgress(const CommandBufferState
& state
) {
235 if (state
.generation() - last_state_
.generation
< 0x80000000U
)
239 void CommandBufferClientImpl::DidDestroy() {
240 LostContext(gpu::error::kUnknown
);
243 void CommandBufferClientImpl::LostContext(int32_t lost_reason
) {
244 last_state_
.error
= gpu::error::kLostContext
;
245 last_state_
.context_lost_reason
=
246 static_cast<gpu::error::ContextLostReason
>(lost_reason
);
247 delegate_
->ContextLost();
250 void CommandBufferClientImpl::OnError() { LostContext(gpu::error::kUnknown
); }
252 void CommandBufferClientImpl::TryUpdateState() {
253 if (last_state_
.error
== gpu::error::kNoError
)
254 shared_state()->Read(&last_state_
);
257 void CommandBufferClientImpl::MakeProgressAndUpdateState() {
258 command_buffer_
->MakeProgress(last_state_
.get_offset
);
259 if (!sync_dispatcher_
->WaitAndDispatchOneMessage()) {
260 VLOG(1) << "Channel encountered error while waiting for command buffer";
261 // TODO(piman): is it ok for this to re-enter?
267 void CommandBufferClientImpl::DrawAnimationFrame() {
268 delegate_
->DrawAnimationFrame();