OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gl/async_pixel_transfer_delegate_android.h" | 5 #include "ui/gl/async_pixel_transfer_delegate_android.h" |
6 | 6 |
7 #include <sys/resource.h> | 7 #include <sys/resource.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
147 } | 147 } |
148 | 148 |
149 void BindTransfer(AsyncTexImage2DParams* bound_params) { | 149 void BindTransfer(AsyncTexImage2DParams* bound_params) { |
150 DCHECK(bound_params); | 150 DCHECK(bound_params); |
151 DCHECK(needs_late_bind_); | 151 DCHECK(needs_late_bind_); |
152 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); | 152 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); |
153 *bound_params = late_bind_define_params_; | 153 *bound_params = late_bind_define_params_; |
154 needs_late_bind_ = false; | 154 needs_late_bind_ = false; |
155 } | 155 } |
156 | 156 |
157 // Completion callbacks. | 157 protected: |
158 void TexImage2DCompleted() { | |
159 needs_late_bind_ = true; | |
160 transfer_in_progress_ = false; | |
161 } | |
162 void TexSubImage2DCompleted() { | |
163 transfer_in_progress_ = false; | |
164 } | |
165 | |
166 protected: | |
167 friend class base::RefCountedThreadSafe<TransferStateInternal>; | 158 friend class base::RefCountedThreadSafe<TransferStateInternal>; |
168 friend class AsyncPixelTransferDelegateAndroid; | 159 friend class AsyncPixelTransferDelegateAndroid; |
169 | 160 |
170 virtual ~TransferStateInternal() { | 161 virtual ~TransferStateInternal() { |
171 if (egl_image_) { | 162 if (egl_image_) { |
172 EGLDisplay display = eglGetCurrentDisplay(); | 163 EGLDisplay display = eglGetCurrentDisplay(); |
173 eglDestroyImageKHR(display, egl_image_); | 164 eglDestroyImageKHR(display, egl_image_); |
174 } | 165 } |
175 } | 166 } |
176 | 167 |
177 // The 'real' texture. | 168 // The 'real' texture. |
178 GLuint texture_id_; | 169 GLuint texture_id_; |
179 | 170 |
180 // Indicates there is a new EGLImage and the 'real' | 171 // Indicates there is a new EGLImage and the 'real' |
181 // texture needs to be bound to it as an EGLImage target. | 172 // texture needs to be bound to it as an EGLImage target. |
182 bool needs_late_bind_; | 173 bool needs_late_bind_; |
183 | 174 |
184 // Definition params for texture that needs binding. | 175 // Definition params for texture that needs binding. |
185 AsyncTexImage2DParams late_bind_define_params_; | 176 AsyncTexImage2DParams late_bind_define_params_; |
186 | 177 |
187 // Indicates that an async transfer is in progress. | 178 // Indicates that an async transfer is in progress. |
188 bool transfer_in_progress_; | 179 bool transfer_in_progress_; |
189 | 180 |
190 // It would be nice if we could just create a new EGLImage for | 181 // It would be nice if we could just create a new EGLImage for |
191 // every upload, but I found that didn't work, so this stores | 182 // every upload, but I found that didn't work, so this stores |
192 // one for the lifetime of the texture. | 183 // one for the lifetime of the texture. |
193 EGLImageKHR egl_image_; | 184 EGLImageKHR egl_image_; |
185 | |
186 // Time spent performing last transfer. | |
187 base::TimeDelta last_transfer_time_; | |
194 }; | 188 }; |
195 | 189 |
196 // Android needs thread-safe ref-counting, so this just wraps | 190 // Android needs thread-safe ref-counting, so this just wraps |
197 // an internal thread-safe ref-counted state object. | 191 // an internal thread-safe ref-counted state object. |
198 class AsyncTransferStateAndroid : public AsyncPixelTransferState { | 192 class AsyncTransferStateAndroid : public AsyncPixelTransferState { |
199 public: | 193 public: |
200 explicit AsyncTransferStateAndroid(GLuint texture_id) | 194 explicit AsyncTransferStateAndroid(GLuint texture_id) |
201 : internal_(new TransferStateInternal(texture_id)) { | 195 : internal_(new TransferStateInternal(texture_id)) { |
202 } | 196 } |
203 virtual ~AsyncTransferStateAndroid() {} | 197 virtual ~AsyncTransferStateAndroid() {} |
204 virtual bool TransferIsInProgress() { | 198 virtual bool TransferIsInProgress() { |
205 return internal_->TransferIsInProgress(); | 199 return internal_->TransferIsInProgress(); |
206 } | 200 } |
207 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) { | 201 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) { |
208 internal_->BindTransfer(bound_params); | 202 internal_->BindTransfer(bound_params); |
209 } | 203 } |
210 scoped_refptr<TransferStateInternal> internal_; | 204 scoped_refptr<TransferStateInternal> internal_; |
211 }; | 205 }; |
212 | 206 |
213 // Class which handles async pixel transfers on Android (using | 207 // Class which handles async pixel transfers on Android (using |
214 // EGLImageKHR and another upload thread) | 208 // EGLImageKHR and another upload thread) |
215 class AsyncPixelTransferDelegateAndroid : public AsyncPixelTransferDelegate { | 209 class AsyncPixelTransferDelegateAndroid : public AsyncPixelTransferDelegate { |
216 public: | 210 public: |
217 AsyncPixelTransferDelegateAndroid() {} | 211 AsyncPixelTransferDelegateAndroid(); |
218 virtual ~AsyncPixelTransferDelegateAndroid() {} | 212 virtual ~AsyncPixelTransferDelegateAndroid(); |
219 | 213 |
220 // implement AsyncPixelTransferDelegate: | 214 // implement AsyncPixelTransferDelegate: |
221 virtual void AsyncNotifyCompletion( | 215 virtual void AsyncNotifyCompletion( |
222 const base::Closure& task) OVERRIDE; | 216 const base::Closure& task) OVERRIDE; |
223 virtual void AsyncTexImage2D( | 217 virtual void AsyncTexImage2D( |
224 AsyncPixelTransferState* state, | 218 AsyncPixelTransferState* state, |
225 const AsyncTexImage2DParams& tex_params, | 219 const AsyncTexImage2DParams& tex_params, |
226 const AsyncMemoryParams& mem_params) OVERRIDE; | 220 const AsyncMemoryParams& mem_params) OVERRIDE; |
227 virtual void AsyncTexSubImage2D( | 221 virtual void AsyncTexSubImage2D( |
228 AsyncPixelTransferState* state, | 222 AsyncPixelTransferState* state, |
229 const AsyncTexSubImage2DParams& tex_params, | 223 const AsyncTexSubImage2DParams& tex_params, |
230 const AsyncMemoryParams& mem_params) OVERRIDE; | 224 const AsyncMemoryParams& mem_params) OVERRIDE; |
225 virtual uint32 GetTextureUploadCount() OVERRIDE; | |
226 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; | |
231 | 227 |
232 private: | 228 private: |
233 // implement AsyncPixelTransferDelegate: | 229 // implement AsyncPixelTransferDelegate: |
234 virtual AsyncPixelTransferState* | 230 virtual AsyncPixelTransferState* |
235 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; | 231 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; |
236 | 232 |
237 base::MessageLoopProxy* transfer_message_loop_proxy() { | 233 base::MessageLoopProxy* transfer_message_loop_proxy() { |
238 return g_transfer_thread.Pointer()->message_loop_proxy(); | 234 return g_transfer_thread.Pointer()->message_loop_proxy(); |
239 } | 235 } |
236 | |
237 void AsyncTexImage2DCompleted(scoped_refptr<TransferStateInternal> state); | |
238 void AsyncTexSubImage2DCompleted(scoped_refptr<TransferStateInternal> state); | |
239 | |
240 static void PerformAsyncTexImage2D( | 240 static void PerformAsyncTexImage2D( |
241 TransferStateInternal* state, | 241 TransferStateInternal* state, |
242 AsyncTexImage2DParams tex_params, | 242 AsyncTexImage2DParams tex_params, |
243 AsyncMemoryParams mem_params); | 243 base::SharedMemory* shared_memory, |
epenner
2012/12/22 03:22:42
Is there no way to keep this as one parameter? No
epenner
2012/12/22 20:48:17
Hmm, could we just pass a "Safe" shared memory par
reveman
2012/12/22 21:56:24
I guess we could do that. I removed shared_memory_
| |
244 uint32 shared_memory_size, | |
245 uint32 shared_memory_data_offset, | |
246 uint32 shared_memory_data_size); | |
244 static void PerformAsyncTexSubImage2D( | 247 static void PerformAsyncTexSubImage2D( |
245 TransferStateInternal* state, | 248 TransferStateInternal* state, |
246 AsyncTexSubImage2DParams tex_params, | 249 AsyncTexSubImage2DParams tex_params, |
247 AsyncMemoryParams mem_params); | 250 base::SharedMemory* shared_memory, |
251 uint32 shared_memory_size, | |
252 uint32 shared_memory_data_offset, | |
253 uint32 shared_memory_data_size); | |
254 | |
255 int texture_upload_count_; | |
256 base::TimeDelta total_texture_upload_time_; | |
248 | 257 |
249 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateAndroid); | 258 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateAndroid); |
250 }; | 259 }; |
251 | 260 |
252 // We only used threaded uploads when we can: | 261 // We only used threaded uploads when we can: |
253 // - Create EGLImages out of OpenGL textures (EGL_KHR_gl_texture_2D_image) | 262 // - Create EGLImages out of OpenGL textures (EGL_KHR_gl_texture_2D_image) |
254 // - Bind EGLImages to OpenGL textures (GL_OES_EGL_image) | 263 // - Bind EGLImages to OpenGL textures (GL_OES_EGL_image) |
255 // - Use fences (to test for upload completion). | 264 // - Use fences (to test for upload completion). |
256 scoped_ptr<AsyncPixelTransferDelegate> | 265 scoped_ptr<AsyncPixelTransferDelegate> |
257 AsyncPixelTransferDelegate::Create(gfx::GLContext* context) { | 266 AsyncPixelTransferDelegate::Create(gfx::GLContext* context) { |
(...skipping 11 matching lines...) Expand all Loading... | |
269 static_cast<AsyncPixelTransferDelegate*>( | 278 static_cast<AsyncPixelTransferDelegate*>( |
270 new AsyncPixelTransferDelegateAndroid())); | 279 new AsyncPixelTransferDelegateAndroid())); |
271 } else { | 280 } else { |
272 LOG(INFO) << "Async pixel transfers not supported"; | 281 LOG(INFO) << "Async pixel transfers not supported"; |
273 return make_scoped_ptr( | 282 return make_scoped_ptr( |
274 static_cast<AsyncPixelTransferDelegate*>( | 283 static_cast<AsyncPixelTransferDelegate*>( |
275 new AsyncPixelTransferDelegateStub())); | 284 new AsyncPixelTransferDelegateStub())); |
276 } | 285 } |
277 } | 286 } |
278 | 287 |
288 AsyncPixelTransferDelegateAndroid::AsyncPixelTransferDelegateAndroid() | |
289 : texture_upload_count_(0) { | |
290 } | |
291 | |
292 AsyncPixelTransferDelegateAndroid::~AsyncPixelTransferDelegateAndroid() { | |
293 } | |
294 | |
279 AsyncPixelTransferState* | 295 AsyncPixelTransferState* |
280 AsyncPixelTransferDelegateAndroid:: | 296 AsyncPixelTransferDelegateAndroid:: |
281 CreateRawPixelTransferState(GLuint texture_id) { | 297 CreateRawPixelTransferState(GLuint texture_id) { |
282 return static_cast<AsyncPixelTransferState*>( | 298 return static_cast<AsyncPixelTransferState*>( |
283 new AsyncTransferStateAndroid(texture_id)); | 299 new AsyncTransferStateAndroid(texture_id)); |
284 } | 300 } |
285 | 301 |
286 namespace { | 302 namespace { |
287 // Dummy function to measure completion on | 303 // Dummy function to measure completion on |
288 // the upload thread. | 304 // the upload thread. |
289 void NoOp() {} | 305 void NoOp() {} |
290 } // namespace | 306 } // namespace |
291 | 307 |
292 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( | 308 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( |
293 const base::Closure& task) { | 309 const base::Closure& task) { |
294 // Post a no-op task to the upload thread followed | 310 // Post a no-op task to the upload thread followed |
295 // by a reply to the callback. The reply will then occur after | 311 // by a reply to the callback. The reply will then occur after |
296 // all async transfers are complete. | 312 // all async transfers are complete. |
297 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 313 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
298 base::Bind(&NoOp), task); | 314 base::Bind(&NoOp), task); |
299 } | 315 } |
300 | 316 |
301 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( | 317 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( |
302 AsyncPixelTransferState* transfer_state, | 318 AsyncPixelTransferState* transfer_state, |
303 const AsyncTexImage2DParams& tex_params, | 319 const AsyncTexImage2DParams& tex_params, |
304 const AsyncMemoryParams& mem_params) { | 320 const AsyncMemoryParams& mem_params) { |
305 TransferStateInternal* state = | 321 scoped_refptr<TransferStateInternal> state = |
306 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 322 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
307 DCHECK(mem_params.shared_memory); | 323 DCHECK(mem_params.shared_memory); |
308 DCHECK(state); | 324 DCHECK(state); |
309 DCHECK(state->texture_id_); | 325 DCHECK(state->texture_id_); |
310 DCHECK(!state->needs_late_bind_); | 326 DCHECK(!state->needs_late_bind_); |
311 DCHECK(!state->transfer_in_progress_); | 327 DCHECK(!state->transfer_in_progress_); |
312 DCHECK_EQ(state->egl_image_, EGL_NO_IMAGE_KHR); | 328 DCHECK_EQ(state->egl_image_, EGL_NO_IMAGE_KHR); |
313 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 329 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
314 DCHECK_EQ(tex_params.level, 0); | 330 DCHECK_EQ(tex_params.level, 0); |
315 | 331 |
316 // Mark the transfer in progress and save define params for lazy binding. | 332 // Mark the transfer in progress and save define params for lazy binding. |
317 state->transfer_in_progress_ = true; | 333 state->transfer_in_progress_ = true; |
318 state->late_bind_define_params_ = tex_params; | 334 state->late_bind_define_params_ = tex_params; |
319 | 335 |
320 // Duplicate the shared memory so there are no way we can get | 336 // Duplicate the shared memory so there are no way we can get |
321 // a use-after-free of the raw pixels. | 337 // a use-after-free of the raw pixels. |
322 // TODO: Could we pass an own pointer of the new SharedMemory to the task? | |
323 AsyncMemoryParams duped_mem = mem_params; | |
324 duped_mem.shared_memory = DuplicateSharedMemory(mem_params.shared_memory, | |
325 mem_params.shm_size); | |
326 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 338 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
327 base::Bind( | 339 base::Bind( |
328 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D, | 340 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D, |
329 base::Unretained(state), // This is referenced in reply below. | 341 base::Unretained(state.get()), // This is referenced in reply below. |
330 tex_params, | 342 tex_params, |
331 duped_mem), | 343 base::Owned(DuplicateSharedMemory(mem_params.shared_memory, |
344 mem_params.shm_size)), | |
345 mem_params.shm_size, | |
346 mem_params.shm_data_offset, | |
347 mem_params.shm_data_size), | |
332 base::Bind( | 348 base::Bind( |
333 &TransferStateInternal::TexImage2DCompleted, | 349 &AsyncPixelTransferDelegateAndroid::AsyncTexImage2DCompleted, |
350 base::Unretained(this), | |
epenner
2012/12/22 03:22:42
I don't think it's safe to pass this pointer as is
reveman
2012/12/22 21:56:24
added support for weak pointer in latest patch. it
| |
334 state)); | 351 state)); |
335 } | 352 } |
336 | 353 |
337 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2D( | 354 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2D( |
338 AsyncPixelTransferState* transfer_state, | 355 AsyncPixelTransferState* transfer_state, |
339 const AsyncTexSubImage2DParams& tex_params, | 356 const AsyncTexSubImage2DParams& tex_params, |
340 const AsyncMemoryParams& mem_params) { | 357 const AsyncMemoryParams& mem_params) { |
341 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", | 358 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", |
342 "width", tex_params.width, | 359 "width", tex_params.width, |
343 "height", tex_params.height); | 360 "height", tex_params.height); |
344 TransferStateInternal* state = | 361 scoped_refptr<TransferStateInternal> state = |
345 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 362 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
346 DCHECK(state->texture_id_); | 363 DCHECK(state->texture_id_); |
347 DCHECK(!state->transfer_in_progress_); | 364 DCHECK(!state->transfer_in_progress_); |
348 DCHECK(mem_params.shared_memory); | 365 DCHECK(mem_params.shared_memory); |
349 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 366 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
350 DCHECK_EQ(tex_params.level, 0); | 367 DCHECK_EQ(tex_params.level, 0); |
351 | 368 |
352 // Mark the transfer in progress. | 369 // Mark the transfer in progress. |
353 state->transfer_in_progress_ = true; | 370 state->transfer_in_progress_ = true; |
354 | 371 |
(...skipping 12 matching lines...) Expand all Loading... | |
367 state->egl_image_ = eglCreateImageKHR( | 384 state->egl_image_ = eglCreateImageKHR( |
368 egl_display, | 385 egl_display, |
369 egl_context, | 386 egl_context, |
370 egl_target, | 387 egl_target, |
371 egl_buffer, | 388 egl_buffer, |
372 egl_attrib_list); | 389 egl_attrib_list); |
373 } | 390 } |
374 | 391 |
375 // Duplicate the shared memory so there are no way we can get | 392 // Duplicate the shared memory so there are no way we can get |
376 // a use-after-free of the raw pixels. | 393 // a use-after-free of the raw pixels. |
377 // TODO: Could we pass an own pointer of the new SharedMemory to the task? | |
378 AsyncMemoryParams duped_mem = mem_params; | |
379 duped_mem.shared_memory = DuplicateSharedMemory(mem_params.shared_memory, | |
380 mem_params.shm_size); | |
381 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 394 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
382 base::Bind( | 395 base::Bind( |
383 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D, | 396 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D, |
384 base::Unretained(state), // This is referenced in reply below. | 397 base::Unretained(state.get()), // This is referenced in reply below. |
385 tex_params, | 398 tex_params, |
386 duped_mem), | 399 base::Owned(DuplicateSharedMemory(mem_params.shared_memory, |
400 mem_params.shm_size)), | |
401 mem_params.shm_size, | |
402 mem_params.shm_data_offset, | |
403 mem_params.shm_data_size), | |
387 base::Bind( | 404 base::Bind( |
388 &TransferStateInternal::TexSubImage2DCompleted, | 405 &AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2DCompleted, |
406 base::Unretained(this), | |
389 state)); | 407 state)); |
390 } | 408 } |
391 | 409 |
410 uint32 AsyncPixelTransferDelegateAndroid::GetTextureUploadCount() { | |
411 return texture_upload_count_; | |
412 } | |
413 | |
414 base::TimeDelta AsyncPixelTransferDelegateAndroid::GetTotalTextureUploadTime() { | |
415 return total_texture_upload_time_; | |
416 } | |
417 | |
418 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2DCompleted( | |
419 scoped_refptr<TransferStateInternal> state) { | |
420 state->needs_late_bind_ = true; | |
421 state->transfer_in_progress_ = false; | |
422 } | |
423 | |
424 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2DCompleted( | |
425 scoped_refptr<TransferStateInternal> state) { | |
426 state->transfer_in_progress_ = false; | |
427 texture_upload_count_++; | |
428 total_texture_upload_time_ += state->last_transfer_time_; | |
429 } | |
430 | |
392 namespace { | 431 namespace { |
393 void WaitForGlFence() { | 432 void WaitForGlFence() { |
394 // Uploads usually finish on the CPU, but just in case add a fence | 433 // Uploads usually finish on the CPU, but just in case add a fence |
395 // and guarantee the upload has completed. The flush bit is set to | 434 // and guarantee the upload has completed. The flush bit is set to |
396 // insure we don't wait forever. | 435 // insure we don't wait forever. |
397 | 436 |
398 EGLDisplay display = eglGetCurrentDisplay(); | 437 EGLDisplay display = eglGetCurrentDisplay(); |
399 EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); | 438 EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); |
400 EGLint flags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR; | 439 EGLint flags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR; |
401 EGLTimeKHR time = EGL_FOREVER_KHR; | 440 EGLTimeKHR time = EGL_FOREVER_KHR; |
402 | 441 |
403 // This fence is basically like calling glFinish, which is fine if | 442 // This fence is basically like calling glFinish, which is fine if |
404 // uploads occur on the CPU. If some upload work occurs on the GPU, | 443 // uploads occur on the CPU. If some upload work occurs on the GPU, |
405 // we may want to delay blocking on the fence. | 444 // we may want to delay blocking on the fence. |
406 eglClientWaitSyncKHR(display, fence, flags, time); | 445 eglClientWaitSyncKHR(display, fence, flags, time); |
407 eglDestroySyncKHR(display, fence); | 446 eglDestroySyncKHR(display, fence); |
408 } | 447 } |
409 } // namespace | 448 } // namespace |
410 | 449 |
411 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D( | 450 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D( |
412 TransferStateInternal* state, | 451 TransferStateInternal* state, |
413 AsyncTexImage2DParams tex_params, | 452 AsyncTexImage2DParams tex_params, |
414 AsyncMemoryParams mem_params) { | 453 base::SharedMemory* shared_memory, |
415 // TODO(epenner): This is just to insure it is deleted. Could bind() do this? | 454 uint32 shared_memory_size, |
416 scoped_ptr<SharedMemory> shared_memory = | 455 uint32 shared_memory_data_offset, |
417 make_scoped_ptr(mem_params.shared_memory); | 456 uint32 shared_memory_data_size) { |
418 | 457 void* data = GetAddress(shared_memory, |
419 void* data = GetAddress(mem_params.shared_memory, | 458 shared_memory_size, |
420 mem_params.shm_size, | 459 shared_memory_data_offset, |
421 mem_params.shm_data_offset, | 460 shared_memory_data_size); |
422 mem_params.shm_data_size); | |
423 | 461 |
424 // In texImage2D, we do everything on the upload thread. This is | 462 // In texImage2D, we do everything on the upload thread. This is |
425 // because texImage2D can incur CPU allocation cost, and it also | 463 // because texImage2D can incur CPU allocation cost, and it also |
426 // 'orphans' any previous EGLImage bound to the texture. | 464 // 'orphans' any previous EGLImage bound to the texture. |
427 DCHECK_EQ(0, tex_params.level); | 465 DCHECK_EQ(0, tex_params.level); |
428 DCHECK_EQ(EGL_NO_IMAGE_KHR, state->egl_image_); | 466 DCHECK_EQ(EGL_NO_IMAGE_KHR, state->egl_image_); |
429 TRACE_EVENT2("gpu", "performAsyncTexImage2D", | 467 TRACE_EVENT2("gpu", "performAsyncTexImage2D", |
430 "width", tex_params.width, | 468 "width", tex_params.width, |
431 "height", tex_params.height); | 469 "height", tex_params.height); |
432 | 470 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 WaitForGlFence(); | 506 WaitForGlFence(); |
469 | 507 |
470 // We can delete this thread's texture as the real texture | 508 // We can delete this thread's texture as the real texture |
471 // now contains the data. | 509 // now contains the data. |
472 glDeleteTextures(1, &temp_texture); | 510 glDeleteTextures(1, &temp_texture); |
473 } | 511 } |
474 | 512 |
475 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D( | 513 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D( |
476 TransferStateInternal* state, | 514 TransferStateInternal* state, |
477 AsyncTexSubImage2DParams tex_params, | 515 AsyncTexSubImage2DParams tex_params, |
478 AsyncMemoryParams mem_params) { | 516 base::SharedMemory* shared_memory, |
479 // TODO(epenner): This is just to insure it is deleted. Could bind() do this? | 517 uint32 shared_memory_size, |
480 scoped_ptr<SharedMemory> shared_memory = | 518 uint32 shared_memory_data_offset, |
481 make_scoped_ptr(mem_params.shared_memory); | 519 uint32 shared_memory_data_size) { |
482 | 520 void* data = GetAddress(shared_memory, |
483 void* data = GetAddress(mem_params.shared_memory, | 521 shared_memory_size, |
484 mem_params.shm_size, | 522 shared_memory_data_offset, |
485 mem_params.shm_data_offset, | 523 shared_memory_data_size); |
486 mem_params.shm_data_size); | |
487 | 524 |
488 // For a texSubImage, the texture must already have been | 525 // For a texSubImage, the texture must already have been |
489 // created on the main thread, along with EGLImageKHR. | 526 // created on the main thread, along with EGLImageKHR. |
490 DCHECK_NE(EGL_NO_IMAGE_KHR, state->egl_image_); | 527 DCHECK_NE(EGL_NO_IMAGE_KHR, state->egl_image_); |
491 DCHECK_EQ(0, tex_params.level); | 528 DCHECK_EQ(0, tex_params.level); |
492 TRACE_EVENT2("gpu", "performAsyncTexSubImage2D", | 529 TRACE_EVENT2("gpu", "performAsyncTexSubImage2D", |
493 "width", tex_params.width, | 530 "width", tex_params.width, |
494 "height", tex_params.height); | 531 "height", tex_params.height); |
495 | 532 |
533 base::TimeTicks begin_time(base::TimeTicks::HighResNow()); | |
496 // Create a texture from the image and upload to it. | 534 // Create a texture from the image and upload to it. |
497 GLuint temp_texture = 0; | 535 GLuint temp_texture = 0; |
498 glGenTextures(1, &temp_texture); | 536 glGenTextures(1, &temp_texture); |
499 glActiveTexture(GL_TEXTURE0); | 537 glActiveTexture(GL_TEXTURE0); |
500 glBindTexture(GL_TEXTURE_2D, temp_texture); | 538 glBindTexture(GL_TEXTURE_2D, temp_texture); |
501 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, state->egl_image_); | 539 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, state->egl_image_); |
502 { | 540 { |
503 TRACE_EVENT0("gpu", "performAsyncTexSubImage2D glTexSubImage2D"); | 541 TRACE_EVENT0("gpu", "performAsyncTexSubImage2D glTexSubImage2D"); |
504 glTexSubImage2D( | 542 glTexSubImage2D( |
505 GL_TEXTURE_2D, | 543 GL_TEXTURE_2D, |
506 tex_params.level, | 544 tex_params.level, |
507 tex_params.xoffset, | 545 tex_params.xoffset, |
508 tex_params.yoffset, | 546 tex_params.yoffset, |
509 tex_params.width, | 547 tex_params.width, |
510 tex_params.height, | 548 tex_params.height, |
511 tex_params.format, | 549 tex_params.format, |
512 tex_params.type, | 550 tex_params.type, |
513 data); | 551 data); |
514 } | 552 } |
515 WaitForGlFence(); | 553 WaitForGlFence(); |
516 | 554 |
517 // We can delete this thread's texture as the real texture | 555 // We can delete this thread's texture as the real texture |
518 // now contains the data. | 556 // now contains the data. |
519 glDeleteTextures(1, &temp_texture); | 557 glDeleteTextures(1, &temp_texture); |
558 state->last_transfer_time_ = base::TimeTicks::HighResNow() - begin_time; | |
520 } | 559 } |
521 | 560 |
522 } // namespace gfx | 561 } // namespace gfx |
OLD | NEW |