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/sync_dispatcher.h"
12 #include "mojo/services/gles2/command_buffer_type_conversions.h"
13 #include "mojo/services/gles2/mojo_buffer_backing.h"
20 bool CreateMapAndDupSharedBuffer(size_t size
,
22 mojo::ScopedSharedBufferHandle
* handle
,
23 mojo::ScopedSharedBufferHandle
* duped
) {
24 MojoResult result
= mojo::CreateSharedBuffer(NULL
, size
, handle
);
25 if (result
!= MOJO_RESULT_OK
)
27 DCHECK(handle
->is_valid());
29 result
= mojo::DuplicateBuffer(handle
->get(), NULL
, duped
);
30 if (result
!= MOJO_RESULT_OK
)
32 DCHECK(duped
->is_valid());
34 result
= mojo::MapBuffer(
35 handle
->get(), 0, size
, memory
, MOJO_MAP_BUFFER_FLAG_NONE
);
36 if (result
!= MOJO_RESULT_OK
)
44 CommandBufferDelegate::~CommandBufferDelegate() {}
46 void CommandBufferDelegate::ContextLost() {}
47 void CommandBufferDelegate::DrawAnimationFrame() {}
49 CommandBufferClientImpl::CommandBufferClientImpl(
50 CommandBufferDelegate
* delegate
,
51 const MojoAsyncWaiter
* async_waiter
,
52 ScopedMessagePipeHandle command_buffer_handle
)
53 : delegate_(delegate
),
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);
64 CommandBufferClientImpl::~CommandBufferClientImpl() {}
66 bool CommandBufferClientImpl::Initialize() {
67 const size_t kSharedStateSize
= sizeof(gpu::CommandBufferSharedState
);
69 mojo::ScopedSharedBufferHandle duped
;
70 bool result
= CreateMapAndDupSharedBuffer(
71 kSharedStateSize
, &memory
, &shared_state_handle_
, &duped
);
75 shared_state_
= static_cast<gpu::CommandBufferSharedState
*>(memory
);
77 shared_state()->Initialize();
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(),
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";
92 return initialize_result_
;
95 gpu::CommandBuffer::State
CommandBufferClientImpl::GetLastState() {
99 int32
CommandBufferClientImpl::GetLastToken() {
101 return last_state_
.token
;
104 void CommandBufferClientImpl::Flush(int32 put_offset
) {
105 if (last_put_offset_
== put_offset
)
108 last_put_offset_
= put_offset
;
109 command_buffer_
->Flush(put_offset
);
112 void CommandBufferClientImpl::WaitForTokenInRange(int32 start
, int32 end
) {
114 while (!InRange(start
, end
, last_state_
.token
) &&
115 last_state_
.error
== gpu::error::kNoError
) {
116 MakeProgressAndUpdateState();
121 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start
, int32 end
) {
123 while (!InRange(start
, end
, last_state_
.get_offset
) &&
124 last_state_
.error
== gpu::error::kNoError
) {
125 MakeProgressAndUpdateState();
130 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id
) {
131 command_buffer_
->SetGetBuffer(shm_id
);
132 last_put_offset_
= -1;
135 scoped_refptr
<gpu::Buffer
> CommandBufferClientImpl::CreateTransferBuffer(
138 if (size
>= std::numeric_limits
<uint32_t>::max())
142 mojo::ScopedSharedBufferHandle handle
;
143 mojo::ScopedSharedBufferHandle duped
;
144 if (!CreateMapAndDupSharedBuffer(size
, &memory
, &handle
, &duped
))
147 *id
= ++next_transfer_buffer_id_
;
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
,
179 void CommandBufferClientImpl::DestroyGpuMemoryBuffer(int32 id
) {
184 uint32
CommandBufferClientImpl::InsertSyncPoint() {
190 uint32
CommandBufferClientImpl::InsertFutureSyncPoint() {
196 void CommandBufferClientImpl::RetireSyncPoint(uint32 sync_point
) {
201 void CommandBufferClientImpl::SignalSyncPoint(uint32 sync_point
,
202 const base::Closure
& callback
) {
207 void CommandBufferClientImpl::SignalQuery(uint32 query
,
208 const base::Closure
& callback
) {
213 void CommandBufferClientImpl::SetSurfaceVisible(bool visible
) {
218 void CommandBufferClientImpl::Echo(const base::Closure
& callback
) {
219 command_buffer_
->Echo(callback
);
222 uint32
CommandBufferClientImpl::CreateStreamTexture(uint32 texture_id
) {
228 void CommandBufferClientImpl::RequestAnimationFrames() {
229 command_buffer_
->RequestAnimationFrames();
232 void CommandBufferClientImpl::CancelAnimationFrames() {
233 command_buffer_
->CancelAnimationFrames();
236 void CommandBufferClientImpl::DidInitialize(bool success
) {
237 initialize_result_
= success
;
240 void CommandBufferClientImpl::DidMakeProgress(CommandBufferStatePtr state
) {
241 if (state
->generation
- last_state_
.generation
< 0x80000000U
)
242 last_state_
= state
.To
<State
>();
245 void CommandBufferClientImpl::DidDestroy() {
246 LostContext(gpu::error::kUnknown
);
249 void CommandBufferClientImpl::LostContext(int32_t lost_reason
) {
250 last_state_
.error
= gpu::error::kLostContext
;
251 last_state_
.context_lost_reason
=
252 static_cast<gpu::error::ContextLostReason
>(lost_reason
);
253 delegate_
->ContextLost();
256 void CommandBufferClientImpl::OnConnectionError() {
257 LostContext(gpu::error::kUnknown
);
260 void CommandBufferClientImpl::TryUpdateState() {
261 if (last_state_
.error
== gpu::error::kNoError
)
262 shared_state()->Read(&last_state_
);
265 void CommandBufferClientImpl::MakeProgressAndUpdateState() {
266 command_buffer_
->MakeProgress(last_state_
.get_offset
);
267 if (!sync_dispatcher_
->WaitAndDispatchOneMessage()) {
268 VLOG(1) << "Channel encountered error while waiting for command buffer";
269 // TODO(piman): is it ok for this to re-enter?
275 void CommandBufferClientImpl::DrawAnimationFrame() {
276 delegate_
->DrawAnimationFrame();