Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / mojo / gles2 / command_buffer_client_impl.cc
blob37dc30cd6dbe5a24e60af3de8d0bad520883b518
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"
7 #include <limits>
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"
14 namespace gles2 {
16 namespace {
18 bool CreateMapAndDupSharedBuffer(size_t size,
19 void** memory,
20 mojo::ScopedSharedBufferHandle* handle,
21 mojo::ScopedSharedBufferHandle* duped) {
22 MojoResult result = mojo::CreateSharedBuffer(NULL, size, handle);
23 if (result != MOJO_RESULT_OK)
24 return false;
25 DCHECK(handle->is_valid());
27 result = mojo::DuplicateBuffer(handle->get(), NULL, duped);
28 if (result != MOJO_RESULT_OK)
29 return false;
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)
35 return false;
36 DCHECK(*memory);
38 return true;
41 } // namespace
43 CommandBufferDelegate::~CommandBufferDelegate() {}
45 void CommandBufferDelegate::ContextLost() {}
47 class CommandBufferClientImpl::SyncClientImpl
48 : public mojo::CommandBufferSyncClient {
49 public:
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())
56 return false;
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>();
70 private:
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 {
91 public:
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())
98 return 0u;
99 uint32_t result = sync_point_;
100 sync_point_ = 0u;
101 return result;
104 private:
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),
120 shared_state_(NULL),
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);
132 void* memory = NULL;
133 mojo::ScopedSharedBufferHandle duped;
134 bool result = CreateMapAndDupSharedBuffer(
135 kSharedStateSize, &memory, &shared_state_handle_, &duped);
136 if (!result)
137 return false;
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(),
154 observer_ptr.Pass(),
155 duped.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";
160 return false;
162 capabilities_ = sync_client_impl_->GetCapabilities();
163 return true;
166 gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() {
167 return last_state_;
170 int32 CommandBufferClientImpl::GetLastToken() {
171 TryUpdateState();
172 return last_state_.token;
175 void CommandBufferClientImpl::Flush(int32 put_offset) {
176 if (last_put_offset_ == put_offset)
177 return;
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.
185 Flush(put_offset);
188 void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) {
189 TryUpdateState();
190 while (!InRange(start, end, last_state_.token) &&
191 last_state_.error == gpu::error::kNoError) {
192 MakeProgressAndUpdateState();
193 TryUpdateState();
197 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start, int32 end) {
198 TryUpdateState();
199 while (!InRange(start, end, last_state_.get_offset) &&
200 last_state_.error == gpu::error::kNoError) {
201 MakeProgressAndUpdateState();
202 TryUpdateState();
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(
212 size_t size,
213 int32* id) {
214 if (size >= std::numeric_limits<uint32_t>::max())
215 return NULL;
217 void* memory = NULL;
218 mojo::ScopedSharedBufferHandle handle;
219 mojo::ScopedSharedBufferHandle duped;
220 if (!CreateMapAndDupSharedBuffer(size, &memory, &handle, &duped))
221 return NULL;
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()));
231 return buffer;
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,
243 size_t width,
244 size_t height,
245 unsigned internalformat) {
246 // TODO(piman)
247 NOTIMPLEMENTED();
248 return -1;
251 void CommandBufferClientImpl::DestroyImage(int32 id) {
252 // TODO(piman)
253 NOTIMPLEMENTED();
256 int32_t CommandBufferClientImpl::CreateGpuMemoryBufferImage(
257 size_t width,
258 size_t height,
259 unsigned internalformat,
260 unsigned usage) {
261 // TODO(piman)
262 NOTIMPLEMENTED();
263 return -1;
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) {
282 // TODO(piman)
285 void CommandBufferClientImpl::SignalQuery(uint32_t query,
286 const base::Closure& callback) {
287 // TODO(piman)
288 NOTIMPLEMENTED();
291 void CommandBufferClientImpl::SetSurfaceVisible(bool visible) {
292 // TODO(piman)
293 NOTIMPLEMENTED();
296 uint32_t CommandBufferClientImpl::CreateStreamTexture(uint32_t texture_id) {
297 // TODO(piman)
298 NOTIMPLEMENTED();
299 return 0;
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();
322 if (!state) {
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);
326 return;
329 if (state->generation - last_state_.generation < 0x80000000U)
330 last_state_ = state.To<State>();
333 void CommandBufferClientImpl::SetLock(base::Lock* lock) {
336 } // namespace gles2