OLD | NEW |
| (Empty) |
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. | |
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" | |
11 #include "mojo/services/gles2/command_buffer_type_conversions.h" | |
12 #include "mojo/services/gles2/mojo_buffer_backing.h" | |
13 | |
14 namespace mojo { | |
15 namespace gles2 { | |
16 | |
17 namespace { | |
18 | |
19 bool 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 | |
44 CommandBufferDelegate::~CommandBufferDelegate() {} | |
45 | |
46 void CommandBufferDelegate::ContextLost() {} | |
47 | |
48 class CommandBufferClientImpl::SyncClientImpl | |
49 : public InterfaceImpl<CommandBufferSyncClient> { | |
50 public: | |
51 SyncClientImpl() : initialized_successfully_(false) {} | |
52 | |
53 bool WaitForInitialization() { | |
54 if (!WaitForIncomingMethodCall()) | |
55 return false; | |
56 return initialized_successfully_; | |
57 } | |
58 | |
59 CommandBufferStatePtr WaitForProgress() { | |
60 if (!WaitForIncomingMethodCall()) | |
61 return CommandBufferStatePtr(); | |
62 return command_buffer_state_.Pass(); | |
63 } | |
64 | |
65 private: | |
66 // CommandBufferSyncClient methods: | |
67 void DidInitialize(bool success) override { | |
68 initialized_successfully_ = success; | |
69 } | |
70 void DidMakeProgress(CommandBufferStatePtr state) override { | |
71 command_buffer_state_ = state.Pass(); | |
72 } | |
73 | |
74 bool initialized_successfully_; | |
75 CommandBufferStatePtr command_buffer_state_; | |
76 }; | |
77 | |
78 CommandBufferClientImpl::CommandBufferClientImpl( | |
79 CommandBufferDelegate* delegate, | |
80 const MojoAsyncWaiter* async_waiter, | |
81 ScopedMessagePipeHandle command_buffer_handle) | |
82 : delegate_(delegate), | |
83 shared_state_(NULL), | |
84 last_put_offset_(-1), | |
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); | |
90 } | |
91 | |
92 CommandBufferClientImpl::~CommandBufferClientImpl() {} | |
93 | |
94 bool CommandBufferClientImpl::Initialize() { | |
95 const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState); | |
96 void* memory = NULL; | |
97 mojo::ScopedSharedBufferHandle duped; | |
98 bool result = CreateMapAndDupSharedBuffer( | |
99 kSharedStateSize, &memory, &shared_state_handle_, &duped); | |
100 if (!result) | |
101 return false; | |
102 | |
103 shared_state_ = static_cast<gpu::CommandBufferSharedState*>(memory); | |
104 | |
105 shared_state()->Initialize(); | |
106 | |
107 CommandBufferSyncClientPtr sync_client; | |
108 sync_client_impl_.reset( | |
109 WeakBindToProxy(new SyncClientImpl(), &sync_client, async_waiter_)); | |
110 | |
111 command_buffer_->Initialize(sync_client.Pass(), duped.Pass()); | |
112 | |
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"; | |
116 return false; | |
117 } | |
118 return true; | |
119 } | |
120 | |
121 gpu::CommandBuffer::State CommandBufferClientImpl::GetLastState() { | |
122 return last_state_; | |
123 } | |
124 | |
125 int32 CommandBufferClientImpl::GetLastToken() { | |
126 TryUpdateState(); | |
127 return last_state_.token; | |
128 } | |
129 | |
130 void CommandBufferClientImpl::Flush(int32 put_offset) { | |
131 if (last_put_offset_ == put_offset) | |
132 return; | |
133 | |
134 last_put_offset_ = put_offset; | |
135 command_buffer_->Flush(put_offset); | |
136 } | |
137 | |
138 void CommandBufferClientImpl::WaitForTokenInRange(int32 start, int32 end) { | |
139 TryUpdateState(); | |
140 while (!InRange(start, end, last_state_.token) && | |
141 last_state_.error == gpu::error::kNoError) { | |
142 MakeProgressAndUpdateState(); | |
143 TryUpdateState(); | |
144 } | |
145 } | |
146 | |
147 void CommandBufferClientImpl::WaitForGetOffsetInRange(int32 start, int32 end) { | |
148 TryUpdateState(); | |
149 while (!InRange(start, end, last_state_.get_offset) && | |
150 last_state_.error == gpu::error::kNoError) { | |
151 MakeProgressAndUpdateState(); | |
152 TryUpdateState(); | |
153 } | |
154 } | |
155 | |
156 void CommandBufferClientImpl::SetGetBuffer(int32 shm_id) { | |
157 command_buffer_->SetGetBuffer(shm_id); | |
158 last_put_offset_ = -1; | |
159 } | |
160 | |
161 scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer( | |
162 size_t size, | |
163 int32* id) { | |
164 if (size >= std::numeric_limits<uint32_t>::max()) | |
165 return NULL; | |
166 | |
167 void* memory = NULL; | |
168 mojo::ScopedSharedBufferHandle handle; | |
169 mojo::ScopedSharedBufferHandle duped; | |
170 if (!CreateMapAndDupSharedBuffer(size, &memory, &handle, &duped)) | |
171 return NULL; | |
172 | |
173 *id = ++next_transfer_buffer_id_; | |
174 | |
175 command_buffer_->RegisterTransferBuffer( | |
176 *id, duped.Pass(), static_cast<uint32_t>(size)); | |
177 | |
178 scoped_ptr<gpu::BufferBacking> backing( | |
179 new MojoBufferBacking(handle.Pass(), memory, size)); | |
180 scoped_refptr<gpu::Buffer> buffer(new gpu::Buffer(backing.Pass())); | |
181 return buffer; | |
182 } | |
183 | |
184 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id) { | |
185 command_buffer_->DestroyTransferBuffer(id); | |
186 } | |
187 | |
188 gpu::Capabilities CommandBufferClientImpl::GetCapabilities() { | |
189 // TODO(piman) | |
190 NOTIMPLEMENTED(); | |
191 return gpu::Capabilities(); | |
192 } | |
193 | |
194 int32_t CommandBufferClientImpl::CreateImage(ClientBuffer buffer, | |
195 size_t width, | |
196 size_t height, | |
197 unsigned internalformat) { | |
198 // TODO(piman) | |
199 NOTIMPLEMENTED(); | |
200 return -1; | |
201 } | |
202 | |
203 void CommandBufferClientImpl::DestroyImage(int32 id) { | |
204 // TODO(piman) | |
205 NOTIMPLEMENTED(); | |
206 } | |
207 | |
208 int32_t CommandBufferClientImpl::CreateGpuMemoryBufferImage( | |
209 size_t width, | |
210 size_t height, | |
211 unsigned internalformat, | |
212 unsigned usage) { | |
213 // TODO(piman) | |
214 NOTIMPLEMENTED(); | |
215 return -1; | |
216 } | |
217 | |
218 uint32 CommandBufferClientImpl::InsertSyncPoint() { | |
219 // TODO(jamesr): Optimize this. | |
220 WaitForGetOffsetInRange(last_put_offset_, last_put_offset_); | |
221 return 0; | |
222 } | |
223 | |
224 uint32 CommandBufferClientImpl::InsertFutureSyncPoint() { | |
225 // TODO(jamesr): Optimize this. | |
226 WaitForGetOffsetInRange(last_put_offset_, last_put_offset_); | |
227 return 0; | |
228 } | |
229 | |
230 void CommandBufferClientImpl::RetireSyncPoint(uint32 sync_point) { | |
231 // TODO(piman) | |
232 NOTIMPLEMENTED(); | |
233 } | |
234 | |
235 void CommandBufferClientImpl::SignalSyncPoint(uint32 sync_point, | |
236 const base::Closure& callback) { | |
237 // TODO(piman) | |
238 NOTIMPLEMENTED(); | |
239 } | |
240 | |
241 void CommandBufferClientImpl::SignalQuery(uint32 query, | |
242 const base::Closure& callback) { | |
243 // TODO(piman) | |
244 NOTIMPLEMENTED(); | |
245 } | |
246 | |
247 void CommandBufferClientImpl::SetSurfaceVisible(bool visible) { | |
248 // TODO(piman) | |
249 NOTIMPLEMENTED(); | |
250 } | |
251 | |
252 uint32 CommandBufferClientImpl::CreateStreamTexture(uint32 texture_id) { | |
253 // TODO(piman) | |
254 NOTIMPLEMENTED(); | |
255 return 0; | |
256 } | |
257 | |
258 void CommandBufferClientImpl::DidDestroy() { | |
259 LostContext(gpu::error::kUnknown); | |
260 } | |
261 | |
262 void CommandBufferClientImpl::LostContext(int32_t lost_reason) { | |
263 last_state_.error = gpu::error::kLostContext; | |
264 last_state_.context_lost_reason = | |
265 static_cast<gpu::error::ContextLostReason>(lost_reason); | |
266 delegate_->ContextLost(); | |
267 } | |
268 | |
269 void CommandBufferClientImpl::OnConnectionError() { | |
270 LostContext(gpu::error::kUnknown); | |
271 } | |
272 | |
273 void CommandBufferClientImpl::TryUpdateState() { | |
274 if (last_state_.error == gpu::error::kNoError) | |
275 shared_state()->Read(&last_state_); | |
276 } | |
277 | |
278 void CommandBufferClientImpl::MakeProgressAndUpdateState() { | |
279 command_buffer_->MakeProgress(last_state_.get_offset); | |
280 | |
281 CommandBufferStatePtr state = sync_client_impl_->WaitForProgress(); | |
282 if (!state) { | |
283 VLOG(1) << "Channel encountered error while waiting for command buffer"; | |
284 // TODO(piman): is it ok for this to re-enter? | |
285 DidDestroy(); | |
286 return; | |
287 } | |
288 | |
289 if (state->generation - last_state_.generation < 0x80000000U) | |
290 last_state_ = state.To<State>(); | |
291 } | |
292 | |
293 } // namespace gles2 | |
294 } // namespace mojo | |
OLD | NEW |