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"
19 bool CreateMapAndDupSharedBuffer(size_t size
,
21 mojo::ScopedSharedBufferHandle
* handle
,
22 mojo::ScopedSharedBufferHandle
* duped
) {
23 MojoResult result
= mojo::CreateSharedBuffer(NULL
, size
, handle
);
24 if (result
!= MOJO_RESULT_OK
)
26 DCHECK(handle
->is_valid());
28 result
= mojo::DuplicateBuffer(handle
->get(), NULL
, duped
);
29 if (result
!= MOJO_RESULT_OK
)
31 DCHECK(duped
->is_valid());
33 result
= mojo::MapBuffer(
34 handle
->get(), 0, size
, memory
, MOJO_MAP_BUFFER_FLAG_NONE
);
35 if (result
!= MOJO_RESULT_OK
)
44 CommandBufferDelegate::~CommandBufferDelegate() {}
46 void CommandBufferDelegate::ContextLost() {}
48 class CommandBufferClientImpl::SyncClientImpl
49 : public InterfaceImpl
<CommandBufferSyncClient
> {
51 SyncClientImpl() : initialized_successfully_(false) {}
53 bool WaitForInitialization() {
54 if (!WaitForIncomingMethodCall())
56 return initialized_successfully_
;
59 CommandBufferStatePtr
WaitForProgress() {
60 if (!WaitForIncomingMethodCall())
61 return CommandBufferStatePtr();
62 return command_buffer_state_
.Pass();
66 // CommandBufferSyncClient methods:
67 virtual void DidInitialize(bool success
) OVERRIDE
{
68 initialized_successfully_
= success
;
70 virtual void DidMakeProgress(CommandBufferStatePtr state
) OVERRIDE
{
71 command_buffer_state_
= state
.Pass();
74 bool initialized_successfully_
;
75 CommandBufferStatePtr command_buffer_state_
;
78 CommandBufferClientImpl::CommandBufferClientImpl(
79 CommandBufferDelegate
* delegate
,
80 const MojoAsyncWaiter
* async_waiter
,
81 ScopedMessagePipeHandle command_buffer_handle
)
82 : delegate_(delegate
),
85 next_transfer_buffer_id_(0),
86 async_waiter_(async_waiter
) {
87 command_buffer_
.Bind(command_buffer_handle
.Pass(), async_waiter
);
88 command_buffer_
.set_error_handler(this);
89 command_buffer_
.set_client(this);
92 CommandBufferClientImpl::~CommandBufferClientImpl() {}
94 bool CommandBufferClientImpl::Initialize() {
95 const size_t kSharedStateSize
= sizeof(gpu::CommandBufferSharedState
);
97 mojo::ScopedSharedBufferHandle duped
;
98 bool result
= CreateMapAndDupSharedBuffer(
99 kSharedStateSize
, &memory
, &shared_state_handle_
, &duped
);
103 shared_state_
= static_cast<gpu::CommandBufferSharedState
*>(memory
);
105 shared_state()->Initialize();
107 CommandBufferSyncClientPtr sync_client
;
108 sync_client_impl_
.reset(
109 WeakBindToProxy(new SyncClientImpl(), &sync_client
, async_waiter_
));
111 command_buffer_
->Initialize(sync_client
.Pass(), duped
.Pass());
113 // Wait for DidInitialize to come on the sync client pipe.
114 if (!sync_client_impl_
->WaitForInitialization()) {
115 VLOG(1) << "Channel encountered error while creating command buffer";
121 gpu::CommandBuffer::State
CommandBufferClientImpl::GetLastState() {
125 int32
CommandBufferClientImpl::GetLastToken() {
127 return last_state_
.token
;
130 void CommandBufferClientImpl::Flush(int32 put_offset
) {
131 if (last_put_offset_
== put_offset
)
134 last_put_offset_
= put_offset
;
135 command_buffer_
->Flush(put_offset
);
138 void CommandBufferClientImpl::WaitForTokenInRange(int32 start
, int32 end
) {
140 while (!InRange(start
, end
, last_state_
.token
) &&
141 last_state_
.error
== gpu::error::kNoError
) {
142 MakeProgressAndUpdateState();
147 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start
, int32 end
) {
149 while (!InRange(start
, end
, last_state_
.get_offset
) &&
150 last_state_
.error
== gpu::error::kNoError
) {
151 MakeProgressAndUpdateState();
156 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id
) {
157 command_buffer_
->SetGetBuffer(shm_id
);
158 last_put_offset_
= -1;
161 scoped_refptr
<gpu::Buffer
> CommandBufferClientImpl::CreateTransferBuffer(
164 if (size
>= std::numeric_limits
<uint32_t>::max())
168 mojo::ScopedSharedBufferHandle handle
;
169 mojo::ScopedSharedBufferHandle duped
;
170 if (!CreateMapAndDupSharedBuffer(size
, &memory
, &handle
, &duped
))
173 *id
= ++next_transfer_buffer_id_
;
175 command_buffer_
->RegisterTransferBuffer(
176 *id
, duped
.Pass(), static_cast<uint32_t>(size
));
178 scoped_ptr
<gpu::BufferBacking
> backing(
179 new MojoBufferBacking(handle
.Pass(), memory
, size
));
180 scoped_refptr
<gpu::Buffer
> buffer(new gpu::Buffer(backing
.Pass()));
184 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id
) {
185 command_buffer_
->DestroyTransferBuffer(id
);
188 gpu::Capabilities
CommandBufferClientImpl::GetCapabilities() {
191 return gpu::Capabilities();
194 gfx::GpuMemoryBuffer
* CommandBufferClientImpl::CreateGpuMemoryBuffer(
197 unsigned internalformat
,
205 void CommandBufferClientImpl::DestroyGpuMemoryBuffer(int32 id
) {
210 uint32
CommandBufferClientImpl::InsertSyncPoint() {
211 // TODO(jamesr): Optimize this.
212 WaitForGetOffsetInRange(last_put_offset_
, last_put_offset_
);
216 uint32
CommandBufferClientImpl::InsertFutureSyncPoint() {
217 // TODO(jamesr): Optimize this.
218 WaitForGetOffsetInRange(last_put_offset_
, last_put_offset_
);
222 void CommandBufferClientImpl::RetireSyncPoint(uint32 sync_point
) {
227 void CommandBufferClientImpl::SignalSyncPoint(uint32 sync_point
,
228 const base::Closure
& callback
) {
233 void CommandBufferClientImpl::SignalQuery(uint32 query
,
234 const base::Closure
& callback
) {
239 void CommandBufferClientImpl::SetSurfaceVisible(bool visible
) {
244 void CommandBufferClientImpl::Echo(const base::Closure
& callback
) {
245 command_buffer_
->Echo(callback
);
248 uint32
CommandBufferClientImpl::CreateStreamTexture(uint32 texture_id
) {
254 void CommandBufferClientImpl::DidDestroy() {
255 LostContext(gpu::error::kUnknown
);
258 void CommandBufferClientImpl::LostContext(int32_t lost_reason
) {
259 last_state_
.error
= gpu::error::kLostContext
;
260 last_state_
.context_lost_reason
=
261 static_cast<gpu::error::ContextLostReason
>(lost_reason
);
262 delegate_
->ContextLost();
265 void CommandBufferClientImpl::OnConnectionError() {
266 LostContext(gpu::error::kUnknown
);
269 void CommandBufferClientImpl::TryUpdateState() {
270 if (last_state_
.error
== gpu::error::kNoError
)
271 shared_state()->Read(&last_state_
);
274 void CommandBufferClientImpl::MakeProgressAndUpdateState() {
275 command_buffer_
->MakeProgress(last_state_
.get_offset
);
277 CommandBufferStatePtr state
= sync_client_impl_
->WaitForProgress();
279 VLOG(1) << "Channel encountered error while waiting for command buffer";
280 // TODO(piman): is it ok for this to re-enter?
285 if (state
->generation
- last_state_
.generation
< 0x80000000U
)
286 last_state_
= state
.To
<State
>();