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 <string> | 7 #include <string> |
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" |
11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
14 #include "base/process_util.h" | 14 #include "base/process_util.h" |
15 #include "base/shared_memory.h" | 15 #include "base/shared_memory.h" |
| 16 #include "base/synchronization/waitable_event.h" |
16 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
17 #include "build/build_config.h" | 18 #include "build/build_config.h" |
18 #include "ui/gl/async_pixel_transfer_delegate.h" | 19 #include "ui/gl/async_pixel_transfer_delegate.h" |
19 #include "ui/gl/async_pixel_transfer_delegate_stub.h" | 20 #include "ui/gl/async_pixel_transfer_delegate_stub.h" |
20 #include "ui/gl/egl_util.h" | 21 #include "ui/gl/egl_util.h" |
21 #include "ui/gl/gl_bindings.h" | 22 #include "ui/gl/gl_bindings.h" |
22 #include "ui/gl/gl_context.h" | 23 #include "ui/gl/gl_context.h" |
23 #include "ui/gl/gl_surface_egl.h" | 24 #include "ui/gl/gl_surface_egl.h" |
24 #include "ui/gl/safe_shared_memory_pool.h" | 25 #include "ui/gl/safe_shared_memory_pool.h" |
25 | 26 |
26 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) | 27 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) |
27 #include <sys/resource.h> | 28 #include <sys/resource.h> |
28 | 29 |
29 using base::SharedMemory; | 30 using base::SharedMemory; |
30 using base::SharedMemoryHandle; | 31 using base::SharedMemoryHandle; |
31 | 32 |
32 namespace gfx { | 33 namespace gfx { |
33 | 34 |
34 namespace { | 35 namespace { |
35 | 36 |
36 // Quick and dirty Atomic flag, that we use for | |
37 // marking completion from the upload thread. | |
38 class AtomicFlag { | |
39 public: | |
40 AtomicFlag() { | |
41 base::subtle::Acquire_Store(&value_, 0); | |
42 } | |
43 void Set() { | |
44 base::subtle::Atomic32 old_value = base::subtle::Acquire_CompareAndSwap( | |
45 &value_, 0, 1); | |
46 DCHECK_EQ(old_value, 0); | |
47 } | |
48 void Unset() { | |
49 base::subtle::Atomic32 old_value = base::subtle::Release_CompareAndSwap( | |
50 &value_, 1, 0); | |
51 DCHECK_EQ(old_value, 1); | |
52 } | |
53 bool IsSet() { | |
54 return base::subtle::Acquire_Load(&value_) == 1; | |
55 } | |
56 private: | |
57 base::subtle::Atomic32 value_; | |
58 DISALLOW_COPY_AND_ASSIGN(AtomicFlag); | |
59 }; | |
60 | |
61 | |
62 class TextureUploadStats | 37 class TextureUploadStats |
63 : public base::RefCountedThreadSafe<TextureUploadStats> { | 38 : public base::RefCountedThreadSafe<TextureUploadStats> { |
64 public: | 39 public: |
65 TextureUploadStats() : texture_upload_count_(0) {} | 40 TextureUploadStats() : texture_upload_count_(0) {} |
66 | 41 |
67 void AddUpload(base::TimeDelta transfer_time) { | 42 void AddUpload(base::TimeDelta transfer_time) { |
68 base::AutoLock scoped_lock(lock_); | 43 base::AutoLock scoped_lock(lock_); |
69 texture_upload_count_++; | 44 texture_upload_count_++; |
70 total_texture_upload_time_ += transfer_time; | 45 total_texture_upload_time_ += transfer_time; |
71 } | 46 } |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 // else accessed only on the main thread. | 181 // else accessed only on the main thread. |
207 class TransferStateInternal | 182 class TransferStateInternal |
208 : public base::RefCountedThreadSafe<TransferStateInternal> { | 183 : public base::RefCountedThreadSafe<TransferStateInternal> { |
209 public: | 184 public: |
210 explicit TransferStateInternal(GLuint texture_id, | 185 explicit TransferStateInternal(GLuint texture_id, |
211 bool wait_for_uploads, | 186 bool wait_for_uploads, |
212 bool use_image_preserved) | 187 bool use_image_preserved) |
213 : texture_id_(texture_id), | 188 : texture_id_(texture_id), |
214 thread_texture_id_(0), | 189 thread_texture_id_(0), |
215 needs_late_bind_(false), | 190 needs_late_bind_(false), |
| 191 transfer_completion_(true, true), |
216 egl_image_(EGL_NO_IMAGE_KHR), | 192 egl_image_(EGL_NO_IMAGE_KHR), |
217 wait_for_uploads_(wait_for_uploads), | 193 wait_for_uploads_(wait_for_uploads), |
218 use_image_preserved_(use_image_preserved) { | 194 use_image_preserved_(use_image_preserved) { |
219 static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0}; | 195 static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0}; |
220 late_bind_define_params_ = zero_params; | 196 late_bind_define_params_ = zero_params; |
221 } | 197 } |
222 | 198 |
223 // Implement AsyncPixelTransferState: | 199 // Implement AsyncPixelTransferState: |
224 bool TransferIsInProgress() { | 200 bool TransferIsInProgress() { |
225 return transfer_in_progress_.IsSet(); | 201 return !transfer_completion_.IsSignaled(); |
226 } | 202 } |
227 | 203 |
228 void BindTransfer(AsyncTexImage2DParams* bound_params) { | 204 void BindTransfer(AsyncTexImage2DParams* bound_params) { |
229 TRACE_EVENT2("gpu", "BindAsyncTransfer glEGLImageTargetTexture2DOES", | 205 TRACE_EVENT2("gpu", "BindAsyncTransfer glEGLImageTargetTexture2DOES", |
230 "width", late_bind_define_params_.width, | 206 "width", late_bind_define_params_.width, |
231 "height", late_bind_define_params_.height); | 207 "height", late_bind_define_params_.height); |
232 DCHECK(bound_params); | 208 DCHECK(bound_params); |
233 DCHECK(texture_id_); | 209 DCHECK(texture_id_); |
234 *bound_params = late_bind_define_params_; | 210 *bound_params = late_bind_define_params_; |
235 if (!needs_late_bind_) | 211 if (!needs_late_bind_) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 // GPU action that needs to occur. We could use fences and try | 263 // GPU action that needs to occur. We could use fences and try |
288 // to do this less often. However, on older drivers fences are | 264 // to do this less often. However, on older drivers fences are |
289 // not always reliable (eg. Mali-400 just blocks forever). | 265 // not always reliable (eg. Mali-400 just blocks forever). |
290 if (wait_for_uploads_) { | 266 if (wait_for_uploads_) { |
291 TRACE_EVENT0("gpu", "glFinish"); | 267 TRACE_EVENT0("gpu", "glFinish"); |
292 glFinish(); | 268 glFinish(); |
293 } | 269 } |
294 } | 270 } |
295 | 271 |
296 void MarkAsTransferIsInProgress() { | 272 void MarkAsTransferIsInProgress() { |
297 transfer_in_progress_.Set(); | 273 transfer_completion_.Reset(); |
298 } | 274 } |
299 | 275 |
300 void MarkAsCompleted() { | 276 void MarkAsCompleted() { |
301 transfer_in_progress_.Unset(); | 277 transfer_completion_.Signal(); |
| 278 } |
| 279 |
| 280 void WaitForTransferCompletion() { |
| 281 transfer_completion_.Wait(); |
302 } | 282 } |
303 | 283 |
304 protected: | 284 protected: |
305 friend class base::RefCountedThreadSafe<TransferStateInternal>; | 285 friend class base::RefCountedThreadSafe<TransferStateInternal>; |
306 friend class AsyncPixelTransferDelegateAndroid; | 286 friend class AsyncPixelTransferDelegateAndroid; |
307 | 287 |
308 static void DeleteTexture(GLuint id) { | 288 static void DeleteTexture(GLuint id) { |
309 glDeleteTextures(1, &id); | 289 glDeleteTextures(1, &id); |
310 } | 290 } |
311 | 291 |
(...skipping 15 matching lines...) Expand all Loading... |
327 GLuint thread_texture_id_; | 307 GLuint thread_texture_id_; |
328 | 308 |
329 // Indicates there is a new EGLImage and the 'real' | 309 // Indicates there is a new EGLImage and the 'real' |
330 // texture needs to be bound to it as an EGLImage target. | 310 // texture needs to be bound to it as an EGLImage target. |
331 bool needs_late_bind_; | 311 bool needs_late_bind_; |
332 | 312 |
333 // Definition params for texture that needs binding. | 313 // Definition params for texture that needs binding. |
334 AsyncTexImage2DParams late_bind_define_params_; | 314 AsyncTexImage2DParams late_bind_define_params_; |
335 | 315 |
336 // Indicates that an async transfer is in progress. | 316 // Indicates that an async transfer is in progress. |
337 AtomicFlag transfer_in_progress_; | 317 base::WaitableEvent transfer_completion_; |
338 | 318 |
339 // It would be nice if we could just create a new EGLImage for | 319 // It would be nice if we could just create a new EGLImage for |
340 // every upload, but I found that didn't work, so this stores | 320 // every upload, but I found that didn't work, so this stores |
341 // one for the lifetime of the texture. | 321 // one for the lifetime of the texture. |
342 EGLImageKHR egl_image_; | 322 EGLImageKHR egl_image_; |
343 | 323 |
344 // Customize when we block on fences (these are work-arounds). | 324 // Customize when we block on fences (these are work-arounds). |
345 bool wait_for_uploads_; | 325 bool wait_for_uploads_; |
346 bool use_image_preserved_; | 326 bool use_image_preserved_; |
347 }; | 327 }; |
348 | 328 |
349 // Android needs thread-safe ref-counting, so this just wraps | 329 // Android needs thread-safe ref-counting, so this just wraps |
350 // an internal thread-safe ref-counted state object. | 330 // an internal thread-safe ref-counted state object. |
351 class AsyncTransferStateAndroid : public AsyncPixelTransferState { | 331 class AsyncTransferStateAndroid : public AsyncPixelTransferState { |
352 public: | 332 public: |
353 explicit AsyncTransferStateAndroid(GLuint texture_id, | 333 explicit AsyncTransferStateAndroid(GLuint texture_id, |
354 bool wait_for_uploads, | 334 bool wait_for_uploads, |
355 bool use_image_preserved) | 335 bool use_image_preserved) |
356 : internal_(new TransferStateInternal(texture_id, | 336 : internal_(new TransferStateInternal(texture_id, |
357 wait_for_uploads, | 337 wait_for_uploads, |
358 use_image_preserved)) { | 338 use_image_preserved)) { |
359 } | 339 } |
360 virtual ~AsyncTransferStateAndroid() {} | 340 virtual ~AsyncTransferStateAndroid() {} |
361 virtual bool TransferIsInProgress() { | 341 virtual bool TransferIsInProgress() OVERRIDE { |
362 return internal_->TransferIsInProgress(); | 342 return internal_->TransferIsInProgress(); |
363 } | 343 } |
364 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) { | 344 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) OVERRIDE { |
365 internal_->BindTransfer(bound_params); | 345 internal_->BindTransfer(bound_params); |
366 } | 346 } |
367 scoped_refptr<TransferStateInternal> internal_; | 347 scoped_refptr<TransferStateInternal> internal_; |
368 }; | 348 }; |
369 | 349 |
370 // Class which handles async pixel transfers on Android (using | 350 // Class which handles async pixel transfers on Android (using |
371 // EGLImageKHR and another upload thread) | 351 // EGLImageKHR and another upload thread) |
372 class AsyncPixelTransferDelegateAndroid | 352 class AsyncPixelTransferDelegateAndroid |
373 : public AsyncPixelTransferDelegate, | 353 : public AsyncPixelTransferDelegate, |
374 public base::SupportsWeakPtr<AsyncPixelTransferDelegateAndroid> { | 354 public base::SupportsWeakPtr<AsyncPixelTransferDelegateAndroid> { |
375 public: | 355 public: |
376 AsyncPixelTransferDelegateAndroid(); | 356 AsyncPixelTransferDelegateAndroid(); |
377 virtual ~AsyncPixelTransferDelegateAndroid(); | 357 virtual ~AsyncPixelTransferDelegateAndroid(); |
378 | 358 |
379 // implement AsyncPixelTransferDelegate: | 359 // implement AsyncPixelTransferDelegate: |
380 virtual void AsyncNotifyCompletion( | 360 virtual void AsyncNotifyCompletion( |
381 const AsyncMemoryParams& mem_params, | 361 const AsyncMemoryParams& mem_params, |
382 const CompletionCallback& callback) OVERRIDE; | 362 const CompletionCallback& callback) OVERRIDE; |
383 virtual void AsyncTexImage2D( | 363 virtual void AsyncTexImage2D( |
384 AsyncPixelTransferState* state, | 364 AsyncPixelTransferState* state, |
385 const AsyncTexImage2DParams& tex_params, | 365 const AsyncTexImage2DParams& tex_params, |
386 const AsyncMemoryParams& mem_params) OVERRIDE; | 366 const AsyncMemoryParams& mem_params) OVERRIDE; |
387 virtual void AsyncTexSubImage2D( | 367 virtual void AsyncTexSubImage2D( |
388 AsyncPixelTransferState* state, | 368 AsyncPixelTransferState* state, |
389 const AsyncTexSubImage2DParams& tex_params, | 369 const AsyncTexSubImage2DParams& tex_params, |
390 const AsyncMemoryParams& mem_params) OVERRIDE; | 370 const AsyncMemoryParams& mem_params) OVERRIDE; |
| 371 virtual void WaitForTransferCompletion( |
| 372 AsyncPixelTransferState* state) OVERRIDE; |
391 virtual uint32 GetTextureUploadCount() OVERRIDE; | 373 virtual uint32 GetTextureUploadCount() OVERRIDE; |
392 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; | 374 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; |
393 | 375 |
394 private: | 376 private: |
395 // implement AsyncPixelTransferDelegate: | 377 // implement AsyncPixelTransferDelegate: |
396 virtual AsyncPixelTransferState* | 378 virtual AsyncPixelTransferState* |
397 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; | 379 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; |
398 | 380 |
399 static void PerformNotifyCompletion( | 381 static void PerformNotifyCompletion( |
400 AsyncMemoryParams mem_params, | 382 AsyncMemoryParams mem_params, |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 FROM_HERE, | 479 FROM_HERE, |
498 base::Bind(&AsyncPixelTransferDelegateAndroid::PerformNotifyCompletion, | 480 base::Bind(&AsyncPixelTransferDelegateAndroid::PerformNotifyCompletion, |
499 mem_params, | 481 mem_params, |
500 base::Owned( | 482 base::Owned( |
501 new ScopedSafeSharedMemory(safe_shared_memory_pool(), | 483 new ScopedSafeSharedMemory(safe_shared_memory_pool(), |
502 mem_params.shared_memory, | 484 mem_params.shared_memory, |
503 mem_params.shm_size)), | 485 mem_params.shm_size)), |
504 callback)); | 486 callback)); |
505 } | 487 } |
506 | 488 |
| 489 void AsyncPixelTransferDelegateAndroid::WaitForTransferCompletion( |
| 490 AsyncPixelTransferState* transfer_state) { |
| 491 TRACE_EVENT0("gpu", "WaitForTransferCompletion"); |
| 492 scoped_refptr<TransferStateInternal> state = |
| 493 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
| 494 DCHECK(state); |
| 495 DCHECK(state->texture_id_); |
| 496 |
| 497 if (state->TransferIsInProgress()) { |
| 498 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) |
| 499 int default_nice_value = 0; // Default priority. |
| 500 int idle_nice_value = 10; // Idle priority. |
| 501 setpriority(PRIO_PROCESS, |
| 502 g_transfer_thread.Pointer()->thread_id(), |
| 503 default_nice_value); |
| 504 |
| 505 state->WaitForTransferCompletion(); |
| 506 DCHECK(!state->TransferIsInProgress()); |
| 507 |
| 508 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) |
| 509 setpriority(PRIO_PROCESS, |
| 510 g_transfer_thread.Pointer()->thread_id(), |
| 511 idle_nice_value); |
| 512 } |
| 513 } |
| 514 |
507 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( | 515 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( |
508 AsyncPixelTransferState* transfer_state, | 516 AsyncPixelTransferState* transfer_state, |
509 const AsyncTexImage2DParams& tex_params, | 517 const AsyncTexImage2DParams& tex_params, |
510 const AsyncMemoryParams& mem_params) { | 518 const AsyncMemoryParams& mem_params) { |
511 scoped_refptr<TransferStateInternal> state = | 519 scoped_refptr<TransferStateInternal> state = |
512 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 520 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
513 DCHECK(mem_params.shared_memory); | 521 DCHECK(mem_params.shared_memory); |
514 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 522 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
515 mem_params.shm_size); | 523 mem_params.shm_size); |
516 DCHECK(state); | 524 DCHECK(state); |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 if (texture_upload_stats_) { | 834 if (texture_upload_stats_) { |
827 texture_upload_stats_->AddUpload( | 835 texture_upload_stats_->AddUpload( |
828 base::TimeTicks::HighResNow() - begin_time); | 836 base::TimeTicks::HighResNow() - begin_time); |
829 } | 837 } |
830 | 838 |
831 DCHECK(CHECK_GL()); | 839 DCHECK(CHECK_GL()); |
832 return true; | 840 return true; |
833 } | 841 } |
834 | 842 |
835 } // namespace gfx | 843 } // namespace gfx |
OLD | NEW |