| 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 |