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/services/gles2/command_buffer_type_conversions.h"
12 #include "mojo/services/gles2/mojo_buffer_backing.h"
18 bool CreateMapAndDupSharedBuffer(size_t size
,
20 mojo::ScopedSharedBufferHandle
* handle
,
21 mojo::ScopedSharedBufferHandle
* duped
) {
22 MojoResult result
= mojo::CreateSharedBuffer(NULL
, size
, handle
);
23 if (result
!= MOJO_RESULT_OK
)
25 DCHECK(handle
->is_valid());
27 result
= mojo::DuplicateBuffer(handle
->get(), NULL
, duped
);
28 if (result
!= MOJO_RESULT_OK
)
30 DCHECK(duped
->is_valid());
32 result
= mojo::MapBuffer(
33 handle
->get(), 0, size
, memory
, MOJO_MAP_BUFFER_FLAG_NONE
);
34 if (result
!= MOJO_RESULT_OK
)
43 CommandBufferDelegate::~CommandBufferDelegate() {}
45 void CommandBufferDelegate::ContextLost() {}
47 class CommandBufferClientImpl::SyncClientImpl
48 : public mojo::CommandBufferSyncClient
{
50 SyncClientImpl(mojo::CommandBufferSyncClientPtr
* ptr
,
51 const MojoAsyncWaiter
* async_waiter
)
52 : initialized_successfully_(false), binding_(this, ptr
, async_waiter
) {}
54 bool WaitForInitialization() {
55 if (!binding_
.WaitForIncomingMethodCall())
57 return initialized_successfully_
;
60 mojo::CommandBufferStatePtr
WaitForProgress() {
61 if (!binding_
.WaitForIncomingMethodCall())
62 return mojo::CommandBufferStatePtr();
63 return command_buffer_state_
.Pass();
66 gpu::Capabilities
GetCapabilities() {
67 return capabilities_
.To
<gpu::Capabilities
>();
71 // CommandBufferSyncClient methods:
72 void DidInitialize(bool success
,
73 mojo::GpuCapabilitiesPtr capabilities
) override
{
74 initialized_successfully_
= success
;
75 capabilities_
= capabilities
.Pass();
77 void DidMakeProgress(mojo::CommandBufferStatePtr state
) override
{
78 command_buffer_state_
= state
.Pass();
81 bool initialized_successfully_
;
82 mojo::GpuCapabilitiesPtr capabilities_
;
83 mojo::CommandBufferStatePtr command_buffer_state_
;
84 mojo::Binding
<mojo::CommandBufferSyncClient
> binding_
;
86 DISALLOW_COPY_AND_ASSIGN(SyncClientImpl
);
89 class CommandBufferClientImpl::SyncPointClientImpl
90 : public mojo::CommandBufferSyncPointClient
{
92 SyncPointClientImpl(mojo::CommandBufferSyncPointClientPtr
* ptr
,
93 const MojoAsyncWaiter
* async_waiter
)
94 : sync_point_(0u), binding_(this, ptr
, async_waiter
) {}
96 uint32_t WaitForInsertSyncPoint() {
97 if (!binding_
.WaitForIncomingMethodCall())
99 uint32_t result
= sync_point_
;
105 void DidInsertSyncPoint(uint32_t sync_point
) override
{
106 sync_point_
= sync_point
;
109 uint32_t sync_point_
;
111 mojo::Binding
<mojo::CommandBufferSyncPointClient
> binding_
;
114 CommandBufferClientImpl::CommandBufferClientImpl(
115 CommandBufferDelegate
* delegate
,
116 const MojoAsyncWaiter
* async_waiter
,
117 mojo::ScopedMessagePipeHandle command_buffer_handle
)
118 : delegate_(delegate
),
119 observer_binding_(this),
121 last_put_offset_(-1),
122 next_transfer_buffer_id_(0),
123 async_waiter_(async_waiter
) {
124 command_buffer_
.Bind(command_buffer_handle
.Pass(), async_waiter
);
125 command_buffer_
.set_error_handler(this);
128 CommandBufferClientImpl::~CommandBufferClientImpl() {}
130 bool CommandBufferClientImpl::Initialize() {
131 const size_t kSharedStateSize
= sizeof(gpu::CommandBufferSharedState
);
133 mojo::ScopedSharedBufferHandle duped
;
134 bool result
= CreateMapAndDupSharedBuffer(
135 kSharedStateSize
, &memory
, &shared_state_handle_
, &duped
);
139 shared_state_
= static_cast<gpu::CommandBufferSharedState
*>(memory
);
141 shared_state()->Initialize();
143 mojo::CommandBufferSyncClientPtr sync_client
;
144 sync_client_impl_
.reset(new SyncClientImpl(&sync_client
, async_waiter_
));
146 mojo::CommandBufferSyncPointClientPtr sync_point_client
;
147 sync_point_client_impl_
.reset(
148 new SyncPointClientImpl(&sync_point_client
, async_waiter_
));
150 mojo::CommandBufferLostContextObserverPtr observer_ptr
;
151 observer_binding_
.Bind(GetProxy(&observer_ptr
), async_waiter_
);
152 command_buffer_
->Initialize(sync_client
.Pass(),
153 sync_point_client
.Pass(),
157 // Wait for DidInitialize to come on the sync client pipe.
158 if (!sync_client_impl_
->WaitForInitialization()) {
159 VLOG(1) << "Channel encountered error while creating command buffer";
162 capabilities_
= sync_client_impl_
->GetCapabilities();
166 gpu::CommandBuffer::State
CommandBufferClientImpl::GetLastState() {
170 int32
CommandBufferClientImpl::GetLastToken() {
172 return last_state_
.token
;
175 void CommandBufferClientImpl::Flush(int32 put_offset
) {
176 if (last_put_offset_
== put_offset
)
179 last_put_offset_
= put_offset
;
180 command_buffer_
->Flush(put_offset
);
183 void CommandBufferClientImpl::OrderingBarrier(int32_t put_offset
) {
184 // TODO(jamesr): Implement this more efficiently.
188 void CommandBufferClientImpl::WaitForTokenInRange(int32 start
, int32 end
) {
190 while (!InRange(start
, end
, last_state_
.token
) &&
191 last_state_
.error
== gpu::error::kNoError
) {
192 MakeProgressAndUpdateState();
197 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start
, int32 end
) {
199 while (!InRange(start
, end
, last_state_
.get_offset
) &&
200 last_state_
.error
== gpu::error::kNoError
) {
201 MakeProgressAndUpdateState();
206 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id
) {
207 command_buffer_
->SetGetBuffer(shm_id
);
208 last_put_offset_
= -1;
211 scoped_refptr
<gpu::Buffer
> CommandBufferClientImpl::CreateTransferBuffer(
214 if (size
>= std::numeric_limits
<uint32_t>::max())
218 mojo::ScopedSharedBufferHandle handle
;
219 mojo::ScopedSharedBufferHandle duped
;
220 if (!CreateMapAndDupSharedBuffer(size
, &memory
, &handle
, &duped
))
223 *id
= ++next_transfer_buffer_id_
;
225 command_buffer_
->RegisterTransferBuffer(
226 *id
, duped
.Pass(), static_cast<uint32_t>(size
));
228 scoped_ptr
<gpu::BufferBacking
> backing(
229 new MojoBufferBacking(handle
.Pass(), memory
, size
));
230 scoped_refptr
<gpu::Buffer
> buffer(new gpu::Buffer(backing
.Pass()));
234 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id
) {
235 command_buffer_
->DestroyTransferBuffer(id
);
238 gpu::Capabilities
CommandBufferClientImpl::GetCapabilities() {
239 return capabilities_
;
242 int32_t CommandBufferClientImpl::CreateImage(ClientBuffer buffer
,
245 unsigned internalformat
) {
251 void CommandBufferClientImpl::DestroyImage(int32 id
) {
256 int32_t CommandBufferClientImpl::CreateGpuMemoryBufferImage(
259 unsigned internalformat
,
266 uint32_t CommandBufferClientImpl::InsertSyncPoint() {
267 command_buffer_
->InsertSyncPoint(true);
268 return sync_point_client_impl_
->WaitForInsertSyncPoint();
271 uint32_t CommandBufferClientImpl::InsertFutureSyncPoint() {
272 command_buffer_
->InsertSyncPoint(false);
273 return sync_point_client_impl_
->WaitForInsertSyncPoint();
276 void CommandBufferClientImpl::RetireSyncPoint(uint32_t sync_point
) {
277 command_buffer_
->RetireSyncPoint(sync_point
);
280 void CommandBufferClientImpl::SignalSyncPoint(uint32_t sync_point
,
281 const base::Closure
& callback
) {
285 void CommandBufferClientImpl::SignalQuery(uint32_t query
,
286 const base::Closure
& callback
) {
291 void CommandBufferClientImpl::SetSurfaceVisible(bool visible
) {
296 uint32_t CommandBufferClientImpl::CreateStreamTexture(uint32_t texture_id
) {
302 void CommandBufferClientImpl::DidLoseContext(int32_t lost_reason
) {
303 last_state_
.error
= gpu::error::kLostContext
;
304 last_state_
.context_lost_reason
=
305 static_cast<gpu::error::ContextLostReason
>(lost_reason
);
306 delegate_
->ContextLost();
309 void CommandBufferClientImpl::OnConnectionError() {
310 DidLoseContext(gpu::error::kUnknown
);
313 void CommandBufferClientImpl::TryUpdateState() {
314 if (last_state_
.error
== gpu::error::kNoError
)
315 shared_state()->Read(&last_state_
);
318 void CommandBufferClientImpl::MakeProgressAndUpdateState() {
319 command_buffer_
->MakeProgress(last_state_
.get_offset
);
321 mojo::CommandBufferStatePtr state
= sync_client_impl_
->WaitForProgress();
323 VLOG(1) << "Channel encountered error while waiting for command buffer";
324 // TODO(piman): is it ok for this to re-enter?
325 DidLoseContext(gpu::error::kUnknown
);
329 if (state
->generation
- last_state_
.generation
< 0x80000000U
)
330 last_state_
= state
.To
<State
>();
333 void CommandBufferClientImpl::SetLock(base::Lock
* lock
) {