Index: ui/gl/async_pixel_transfer_delegate_android.cc |
diff --git a/ui/gl/async_pixel_transfer_delegate_android.cc b/ui/gl/async_pixel_transfer_delegate_android.cc |
index a594c9468e341848f22f4bd2c7a1c5326d2a7247..a1c7eb260ef4d7da1b9c9185834b41edde9277f6 100644 |
--- a/ui/gl/async_pixel_transfer_delegate_android.cc |
+++ b/ui/gl/async_pixel_transfer_delegate_android.cc |
@@ -13,6 +13,7 @@ |
#include "base/memory/ref_counted.h" |
#include "base/process_util.h" |
#include "base/shared_memory.h" |
+#include "base/synchronization/waitable_event.h" |
#include "base/threading/thread.h" |
#include "build/build_config.h" |
#include "ui/gl/async_pixel_transfer_delegate.h" |
@@ -33,32 +34,6 @@ namespace gfx { |
namespace { |
-// Quick and dirty Atomic flag, that we use for |
-// marking completion from the upload thread. |
-class AtomicFlag { |
- public: |
- AtomicFlag() { |
- base::subtle::Acquire_Store(&value_, 0); |
- } |
- void Set() { |
- base::subtle::Atomic32 old_value = base::subtle::Acquire_CompareAndSwap( |
- &value_, 0, 1); |
- DCHECK_EQ(old_value, 0); |
- } |
- void Unset() { |
- base::subtle::Atomic32 old_value = base::subtle::Release_CompareAndSwap( |
- &value_, 1, 0); |
- DCHECK_EQ(old_value, 1); |
- } |
- bool IsSet() { |
- return base::subtle::Acquire_Load(&value_) == 1; |
- } |
- private: |
- base::subtle::Atomic32 value_; |
- DISALLOW_COPY_AND_ASSIGN(AtomicFlag); |
-}; |
- |
- |
class TextureUploadStats |
: public base::RefCountedThreadSafe<TextureUploadStats> { |
public: |
@@ -213,6 +188,7 @@ class TransferStateInternal |
: texture_id_(texture_id), |
thread_texture_id_(0), |
needs_late_bind_(false), |
+ transfer_completion_(true, true), |
egl_image_(EGL_NO_IMAGE_KHR), |
wait_for_uploads_(wait_for_uploads), |
use_image_preserved_(use_image_preserved) { |
@@ -222,7 +198,7 @@ class TransferStateInternal |
// Implement AsyncPixelTransferState: |
bool TransferIsInProgress() { |
- return transfer_in_progress_.IsSet(); |
+ return !transfer_completion_.IsSignaled(); |
} |
void BindTransfer(AsyncTexImage2DParams* bound_params) { |
@@ -294,11 +270,15 @@ class TransferStateInternal |
} |
void MarkAsTransferIsInProgress() { |
- transfer_in_progress_.Set(); |
+ transfer_completion_.Reset(); |
} |
void MarkAsCompleted() { |
- transfer_in_progress_.Unset(); |
+ transfer_completion_.Signal(); |
+ } |
+ |
+ void WaitForTransferCompletion() { |
+ transfer_completion_.Wait(); |
} |
protected: |
@@ -334,7 +314,7 @@ class TransferStateInternal |
AsyncTexImage2DParams late_bind_define_params_; |
// Indicates that an async transfer is in progress. |
- AtomicFlag transfer_in_progress_; |
+ base::WaitableEvent transfer_completion_; |
// It would be nice if we could just create a new EGLImage for |
// every upload, but I found that didn't work, so this stores |
@@ -358,10 +338,10 @@ class AsyncTransferStateAndroid : public AsyncPixelTransferState { |
use_image_preserved)) { |
} |
virtual ~AsyncTransferStateAndroid() {} |
- virtual bool TransferIsInProgress() { |
+ virtual bool TransferIsInProgress() OVERRIDE { |
return internal_->TransferIsInProgress(); |
} |
- virtual void BindTransfer(AsyncTexImage2DParams* bound_params) { |
+ virtual void BindTransfer(AsyncTexImage2DParams* bound_params) OVERRIDE { |
internal_->BindTransfer(bound_params); |
} |
scoped_refptr<TransferStateInternal> internal_; |
@@ -388,6 +368,8 @@ class AsyncPixelTransferDelegateAndroid |
AsyncPixelTransferState* state, |
const AsyncTexSubImage2DParams& tex_params, |
const AsyncMemoryParams& mem_params) OVERRIDE; |
+ virtual void WaitForTransferCompletion( |
+ AsyncPixelTransferState* state) OVERRIDE; |
virtual uint32 GetTextureUploadCount() OVERRIDE; |
virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; |
@@ -504,6 +486,32 @@ void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( |
callback)); |
} |
+void AsyncPixelTransferDelegateAndroid::WaitForTransferCompletion( |
+ AsyncPixelTransferState* transfer_state) { |
+ TRACE_EVENT0("gpu", "WaitForTransferCompletion"); |
+ scoped_refptr<TransferStateInternal> state = |
+ static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
+ DCHECK(state); |
+ DCHECK(state->texture_id_); |
+ |
+ if (state->TransferIsInProgress()) { |
+ // TODO(epenner): Move thread priorities to base. (crbug.com/170549) |
+ int default_nice_value = 0; // Default priority. |
+ int idle_nice_value = 10; // Idle priority. |
+ setpriority(PRIO_PROCESS, |
+ g_transfer_thread.Pointer()->thread_id(), |
+ default_nice_value); |
+ |
+ state->WaitForTransferCompletion(); |
+ DCHECK(!state->TransferIsInProgress()); |
+ |
+ // TODO(epenner): Move thread priorities to base. (crbug.com/170549) |
+ setpriority(PRIO_PROCESS, |
+ g_transfer_thread.Pointer()->thread_id(), |
+ idle_nice_value); |
+ } |
+} |
+ |
void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( |
AsyncPixelTransferState* transfer_state, |
const AsyncTexImage2DParams& tex_params, |