blob: 9e9857251d739de62d43058fd6293509510ced0e [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// 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.
4
5#include "mojo/gles2/command_buffer_client_impl.h"
6
7#include <limits>
8
9#include "base/logging.h"
10#include "base/process/process_handle.h"
James Robinsonc9b163e2014-12-03 13:31:32 -080011#include "services/gles2/command_buffer_type_conversions.h"
12#include "services/gles2/mojo_buffer_backing.h"
James Robinson646469d2014-10-03 15:33:28 -070013
14namespace mojo {
15namespace gles2 {
16
17namespace {
18
19bool CreateMapAndDupSharedBuffer(size_t size,
20 void** memory,
21 mojo::ScopedSharedBufferHandle* handle,
22 mojo::ScopedSharedBufferHandle* duped) {
23 MojoResult result = mojo::CreateSharedBuffer(NULL, size, handle);
24 if (result != MOJO_RESULT_OK)
25 return false;
26 DCHECK(handle->is_valid());
27
28 result = mojo::DuplicateBuffer(handle->get(), NULL, duped);
29 if (result != MOJO_RESULT_OK)
30 return false;
31 DCHECK(duped->is_valid());
32
33 result = mojo::MapBuffer(
34 handle->get(), 0, size, memory, MOJO_MAP_BUFFER_FLAG_NONE);
35 if (result != MOJO_RESULT_OK)
36 return false;
37 DCHECK(*memory);
38
39 return true;
40}
41
42} // namespace
43
44CommandBufferDelegate::~CommandBufferDelegate() {}
45
46void CommandBufferDelegate::ContextLost() {}
47
James Robinson52ea6b62014-11-18 16:23:56 -080048class CommandBufferClientImpl::SyncClientImpl : public CommandBufferSyncClient {
James Robinson646469d2014-10-03 15:33:28 -070049 public:
James Robinson52ea6b62014-11-18 16:23:56 -080050 SyncClientImpl(CommandBufferSyncClientPtr* ptr,
51 const MojoAsyncWaiter* async_waiter)
52 : initialized_successfully_(false), binding_(this, ptr, async_waiter) {}
James Robinson646469d2014-10-03 15:33:28 -070053
54 bool WaitForInitialization() {
James Robinson52ea6b62014-11-18 16:23:56 -080055 if (!binding_.WaitForIncomingMethodCall())
James Robinson646469d2014-10-03 15:33:28 -070056 return false;
57 return initialized_successfully_;
58 }
59
60 CommandBufferStatePtr WaitForProgress() {
James Robinson52ea6b62014-11-18 16:23:56 -080061 if (!binding_.WaitForIncomingMethodCall())
James Robinson646469d2014-10-03 15:33:28 -070062 return CommandBufferStatePtr();
63 return command_buffer_state_.Pass();
64 }
65
Adam Barth3da94cf2014-11-14 11:31:26 -080066 gpu::Capabilities GetCapabilities() {
67 return capabilities_.To<gpu::Capabilities>();
68 }
69
James Robinson646469d2014-10-03 15:33:28 -070070 private:
71 // CommandBufferSyncClient methods:
Adam Barth3da94cf2014-11-14 11:31:26 -080072 void DidInitialize(bool success, GpuCapabilitiesPtr capabilities) override {
James Robinson646469d2014-10-03 15:33:28 -070073 initialized_successfully_ = success;
Adam Barth3da94cf2014-11-14 11:31:26 -080074 capabilities_ = capabilities.Pass();
James Robinson646469d2014-10-03 15:33:28 -070075 }
James Robinsone1b30cf2014-10-21 12:25:40 -070076 void DidMakeProgress(CommandBufferStatePtr state) override {
James Robinson646469d2014-10-03 15:33:28 -070077 command_buffer_state_ = state.Pass();
78 }
79
80 bool initialized_successfully_;
Adam Barth3da94cf2014-11-14 11:31:26 -080081 GpuCapabilitiesPtr capabilities_;
James Robinson646469d2014-10-03 15:33:28 -070082 CommandBufferStatePtr command_buffer_state_;
James Robinson52ea6b62014-11-18 16:23:56 -080083 Binding<CommandBufferSyncClient> binding_;
84
85 DISALLOW_COPY_AND_ASSIGN(SyncClientImpl);
James Robinson646469d2014-10-03 15:33:28 -070086};
87
Adam Barthb087f9a2014-11-20 12:26:29 -080088class CommandBufferClientImpl::SyncPointClientImpl
89 : public CommandBufferSyncPointClient {
90 public:
91 SyncPointClientImpl(CommandBufferSyncPointClientPtr* ptr,
92 const MojoAsyncWaiter* async_waiter)
93 : sync_point_(0u), binding_(this, ptr, async_waiter) {}
94
95 uint32_t WaitForInsertSyncPoint() {
96 if (!binding_.WaitForIncomingMethodCall())
97 return 0u;
98 uint32_t result = sync_point_;
99 sync_point_ = 0u;
100 return result;
101 }
102
103 private:
104 void DidInsertSyncPoint(uint32_t sync_point) override {
105 sync_point_ = sync_point;
106 }
107
108 uint32_t sync_point_;
109
110 Binding<CommandBufferSyncPointClient> binding_;
111};
112
James Robinson646469d2014-10-03 15:33:28 -0700113CommandBufferClientImpl::CommandBufferClientImpl(
114 CommandBufferDelegate* delegate,
115 const MojoAsyncWaiter* async_waiter,
116 ScopedMessagePipeHandle command_buffer_handle)
117 : delegate_(delegate),
118 shared_state_(NULL),
119 last_put_offset_(-1),
120 next_transfer_buffer_id_(0),
121 async_waiter_(async_waiter) {
122 command_buffer_.Bind(command_buffer_handle.Pass(), async_waiter);
123 command_buffer_.set_error_handler(this);
124 command_buffer_.set_client(this);
125}
126
127CommandBufferClientImpl::~CommandBufferClientImpl() {}
128
129bool CommandBufferClientImpl::Initialize() {
130 const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState);
131 void* memory = NULL;
132 mojo::ScopedSharedBufferHandle duped;
133 bool result = CreateMapAndDupSharedBuffer(
134 kSharedStateSize, &memory, &shared_state_handle_, &duped);
135 if (!result)
136 return false;
137
138 shared_state_ = static_cast<gpu::CommandBufferSharedState*>(memory);
139
140 shared_state()->Initialize();
141
142 CommandBufferSyncClientPtr sync_client;
James Robinson52ea6b62014-11-18 16:23:56 -0800143 sync_client_impl_.reset(new SyncClientImpl(&sync_client, async_waiter_));
James Robinson646469d2014-10-03 15:33:28 -0700144
Adam Barthb087f9a2014-11-20 12:26:29 -0800145 CommandBufferSyncPointClientPtr sync_point_client;
146 sync_point_client_impl_.reset(
147 new SyncPointClientImpl(&sync_point_client, async_waiter_));
148
149 command_buffer_->Initialize(sync_client.Pass(), sync_point_client.Pass(),
150 duped.Pass());
James Robinson646469d2014-10-03 15:33:28 -0700151
152 // Wait for DidInitialize to come on the sync client pipe.
153 if (!sync_client_impl_->WaitForInitialization()) {
154 VLOG(1) << "Channel encountered error while creating command buffer";
155 return false;
156 }
Adam Barth3da94cf2014-11-14 11:31:26 -0800157 capabilities_ = sync_client_impl_->GetCapabilities();
James Robinson646469d2014-10-03 15:33:28 -0700158 return true;
159}
160
161gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() {
162 return last_state_;
163}
164
165int32 CommandBufferClientImpl::GetLastToken() {
166 TryUpdateState();
167 return last_state_.token;
168}
169
170void CommandBufferClientImpl::Flush(int32 put_offset) {
171 if (last_put_offset_ == put_offset)
172 return;
173
174 last_put_offset_ = put_offset;
175 command_buffer_->Flush(put_offset);
176}
177
178void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) {
179 TryUpdateState();
180 while (!InRange(start, end, last_state_.token) &&
181 last_state_.error == gpu::error::kNoError) {
182 MakeProgressAndUpdateState();
183 TryUpdateState();
184 }
185}
186
187void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start, int32 end) {
188 TryUpdateState();
189 while (!InRange(start, end, last_state_.get_offset) &&
190 last_state_.error == gpu::error::kNoError) {
191 MakeProgressAndUpdateState();
192 TryUpdateState();
193 }
194}
195
196void CommandBufferClientImpl::SetGetBuffer(int32 shm_id) {
197 command_buffer_->SetGetBuffer(shm_id);
198 last_put_offset_ = -1;
199}
200
201scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer(
202 size_t size,
203 int32* id) {
204 if (size >= std::numeric_limits<uint32_t>::max())
205 return NULL;
206
207 void* memory = NULL;
208 mojo::ScopedSharedBufferHandle handle;
209 mojo::ScopedSharedBufferHandle duped;
210 if (!CreateMapAndDupSharedBuffer(size, &memory, &handle, &duped))
211 return NULL;
212
213 *id = ++next_transfer_buffer_id_;
214
215 command_buffer_->RegisterTransferBuffer(
216 *id, duped.Pass(), static_cast<uint32_t>(size));
217
218 scoped_ptr<gpu::BufferBacking> backing(
219 new MojoBufferBacking(handle.Pass(), memory, size));
220 scoped_refptr<gpu::Buffer> buffer(new gpu::Buffer(backing.Pass()));
221 return buffer;
222}
223
224void CommandBufferClientImpl::DestroyTransferBuffer(int32 id) {
225 command_buffer_->DestroyTransferBuffer(id);
226}
227
228gpu::Capabilities CommandBufferClientImpl::GetCapabilities() {
Adam Barth3da94cf2014-11-14 11:31:26 -0800229 return capabilities_;
James Robinson646469d2014-10-03 15:33:28 -0700230}
231
James Robinsone2ac7e82014-10-15 13:21:59 -0700232int32_t CommandBufferClientImpl::CreateImage(ClientBuffer buffer,
233 size_t width,
234 size_t height,
235 unsigned internalformat) {
236 // TODO(piman)
237 NOTIMPLEMENTED();
238 return -1;
239}
240
241void CommandBufferClientImpl::DestroyImage(int32 id) {
242 // TODO(piman)
243 NOTIMPLEMENTED();
244}
245
246int32_t CommandBufferClientImpl::CreateGpuMemoryBufferImage(
James Robinson646469d2014-10-03 15:33:28 -0700247 size_t width,
248 size_t height,
249 unsigned internalformat,
James Robinsone2ac7e82014-10-15 13:21:59 -0700250 unsigned usage) {
James Robinson646469d2014-10-03 15:33:28 -0700251 // TODO(piman)
252 NOTIMPLEMENTED();
James Robinsone2ac7e82014-10-15 13:21:59 -0700253 return -1;
James Robinson646469d2014-10-03 15:33:28 -0700254}
255
James Robinsone24b0242014-11-21 11:04:09 -0800256uint32_t CommandBufferClientImpl::InsertSyncPoint() {
257 command_buffer_->InsertSyncPoint(true);
Adam Barthb087f9a2014-11-20 12:26:29 -0800258 return sync_point_client_impl_->WaitForInsertSyncPoint();
James Robinson646469d2014-10-03 15:33:28 -0700259}
260
James Robinsone24b0242014-11-21 11:04:09 -0800261uint32_t CommandBufferClientImpl::InsertFutureSyncPoint() {
262 command_buffer_->InsertSyncPoint(false);
Adam Barthb087f9a2014-11-20 12:26:29 -0800263 return sync_point_client_impl_->WaitForInsertSyncPoint();
James Robinson646469d2014-10-03 15:33:28 -0700264}
265
James Robinsone24b0242014-11-21 11:04:09 -0800266void CommandBufferClientImpl::RetireSyncPoint(uint32_t sync_point) {
267 command_buffer_->RetireSyncPoint(sync_point);
James Robinson646469d2014-10-03 15:33:28 -0700268}
269
James Robinsone24b0242014-11-21 11:04:09 -0800270void CommandBufferClientImpl::SignalSyncPoint(uint32_t sync_point,
James Robinson646469d2014-10-03 15:33:28 -0700271 const base::Closure& callback) {
272 // TODO(piman)
James Robinson646469d2014-10-03 15:33:28 -0700273}
274
James Robinsone24b0242014-11-21 11:04:09 -0800275void CommandBufferClientImpl::SignalQuery(uint32_t query,
James Robinson646469d2014-10-03 15:33:28 -0700276 const base::Closure& callback) {
277 // TODO(piman)
278 NOTIMPLEMENTED();
279}
280
281void CommandBufferClientImpl::SetSurfaceVisible(bool visible) {
282 // TODO(piman)
283 NOTIMPLEMENTED();
284}
285
James Robinsone24b0242014-11-21 11:04:09 -0800286uint32_t CommandBufferClientImpl::CreateStreamTexture(uint32_t texture_id) {
James Robinson646469d2014-10-03 15:33:28 -0700287 // TODO(piman)
288 NOTIMPLEMENTED();
289 return 0;
290}
291
292void CommandBufferClientImpl::DidDestroy() {
293 LostContext(gpu::error::kUnknown);
294}
295
296void CommandBufferClientImpl::LostContext(int32_t lost_reason) {
297 last_state_.error = gpu::error::kLostContext;
298 last_state_.context_lost_reason =
299 static_cast<gpu::error::ContextLostReason>(lost_reason);
300 delegate_->ContextLost();
301}
302
303void CommandBufferClientImpl::OnConnectionError() {
304 LostContext(gpu::error::kUnknown);
305}
306
307void CommandBufferClientImpl::TryUpdateState() {
308 if (last_state_.error == gpu::error::kNoError)
309 shared_state()->Read(&last_state_);
310}
311
312void CommandBufferClientImpl::MakeProgressAndUpdateState() {
313 command_buffer_->MakeProgress(last_state_.get_offset);
314
315 CommandBufferStatePtr state = sync_client_impl_->WaitForProgress();
316 if (!state) {
317 VLOG(1) << "Channel encountered error while waiting for command buffer";
318 // TODO(piman): is it ok for this to re-enter?
319 DidDestroy();
320 return;
321 }
322
323 if (state->generation - last_state_.generation < 0x80000000U)
324 last_state_ = state.To<State>();
325}
326
327} // namespace gles2
328} // namespace mojo