| Index: gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
|
| diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
|
| index 61db3b68413dde50d864b6d0ea5ce7218fed71b4..50758276f720bce1f463e1558d872de17b3d3813 100644
|
| --- a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
|
| +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
|
| @@ -9,6 +9,7 @@
|
| #include "base/debug/trace_event_synthetic_delay.h"
|
| #include "base/lazy_instance.h"
|
| #include "base/memory/weak_ptr.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| #include "ui/gl/scoped_binders.h"
|
|
|
| namespace gpu {
|
| @@ -17,6 +18,20 @@ namespace {
|
|
|
| static uint64 g_next_pixel_transfer_state_id = 1;
|
|
|
| +static const uint64 kNotificationTask = 0;
|
| +static const uint64 kSuspendTask = 1;
|
| +
|
| +uint64 NextPixelTransferStateId() {
|
| + g_next_pixel_transfer_state_id++;
|
| + switch (g_next_pixel_transfer_state_id) {
|
| + case kNotificationTask:
|
| + case kSuspendTask:
|
| + return NextPixelTransferStateId();
|
| + default:
|
| + return g_next_pixel_transfer_state_id;
|
| + }
|
| +}
|
| +
|
| void PerformNotifyCompletion(
|
| AsyncMemoryParams mem_params,
|
| scoped_refptr<AsyncPixelTransferCompletionObserver> observer) {
|
| @@ -36,6 +51,10 @@ class AsyncPixelTransferDelegateIdle
|
| AsyncPixelTransferManagerIdle::SharedState* state,
|
| GLuint texture_id,
|
| const AsyncTexImage2DParams& define_params);
|
| + AsyncPixelTransferDelegateIdle(
|
| + AsyncPixelTransferManagerIdle::SharedState* state,
|
| + GLuint texture_id,
|
| + const AsyncCompressedTexImage2DParams& define_params);
|
| ~AsyncPixelTransferDelegateIdle() override;
|
|
|
| // Implement AsyncPixelTransferDelegate:
|
| @@ -44,6 +63,13 @@ class AsyncPixelTransferDelegateIdle
|
| const base::Closure& bind_callback) override;
|
| void AsyncTexSubImage2D(const AsyncTexSubImage2DParams& tex_params,
|
| const AsyncMemoryParams& mem_params) override;
|
| + void AsyncCompressedTexImage2D(
|
| + const AsyncCompressedTexImage2DParams& tex_params,
|
| + const AsyncMemoryParams& mem_params,
|
| + const base::Closure& bind_callback) override;
|
| + void AsyncCompressedTexSubImage2D(
|
| + const AsyncCompressedTexSubImage2DParams& tex_params,
|
| + const AsyncMemoryParams& mem_params) override;
|
| bool TransferIsInProgress() override;
|
| void WaitForTransferCompletion() override;
|
|
|
| @@ -53,11 +79,21 @@ class AsyncPixelTransferDelegateIdle
|
| const base::Closure& bind_callback);
|
| void PerformAsyncTexSubImage2D(AsyncTexSubImage2DParams tex_params,
|
| AsyncMemoryParams mem_params);
|
| + void PerformAsyncCompressedTexImage2D(
|
| + AsyncCompressedTexImage2DParams tex_params,
|
| + AsyncMemoryParams mem_params,
|
| + const base::Closure& bind_callback);
|
| + void PerformAsyncCompressedTexSubImage2D(
|
| + AsyncCompressedTexSubImage2DParams tex_params,
|
| + AsyncMemoryParams mem_params);
|
|
|
| uint64 id_;
|
| GLuint texture_id_;
|
| bool transfer_in_progress_;
|
| - AsyncTexImage2DParams define_params_;
|
| + union {
|
| + AsyncTexImage2DParams define_params_;
|
| + AsyncCompressedTexImage2DParams compressed_define_params_;
|
| + };
|
|
|
| // Safe to hold a raw pointer because SharedState is owned by the Manager
|
| // which owns the Delegate.
|
| @@ -70,12 +106,23 @@ AsyncPixelTransferDelegateIdle::AsyncPixelTransferDelegateIdle(
|
| AsyncPixelTransferManagerIdle::SharedState* shared_state,
|
| GLuint texture_id,
|
| const AsyncTexImage2DParams& define_params)
|
| - : id_(g_next_pixel_transfer_state_id++),
|
| + : id_(NextPixelTransferStateId()),
|
| texture_id_(texture_id),
|
| transfer_in_progress_(false),
|
| define_params_(define_params),
|
| shared_state_(shared_state) {}
|
|
|
| +AsyncPixelTransferDelegateIdle::AsyncPixelTransferDelegateIdle(
|
| + AsyncPixelTransferManagerIdle::SharedState* shared_state,
|
| + GLuint texture_id,
|
| + const AsyncCompressedTexImage2DParams& define_params)
|
| + : id_(NextPixelTransferStateId()),
|
| + texture_id_(texture_id),
|
| + transfer_in_progress_(false),
|
| + compressed_define_params_(define_params),
|
| + shared_state_(shared_state) {
|
| +}
|
| +
|
| AsyncPixelTransferDelegateIdle::~AsyncPixelTransferDelegateIdle() {}
|
|
|
| void AsyncPixelTransferDelegateIdle::AsyncTexImage2D(
|
| @@ -114,6 +161,37 @@ void AsyncPixelTransferDelegateIdle::AsyncTexSubImage2D(
|
| transfer_in_progress_ = true;
|
| }
|
|
|
| +void AsyncPixelTransferDelegateIdle::AsyncCompressedTexImage2D(
|
| + const AsyncCompressedTexImage2DParams& tex_params,
|
| + const AsyncMemoryParams& mem_params,
|
| + const base::Closure& bind_callback) {
|
| + TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage");
|
| + DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
|
| +
|
| + shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task(
|
| + id_, this,
|
| + base::Bind(
|
| + &AsyncPixelTransferDelegateIdle::PerformAsyncCompressedTexImage2D,
|
| + AsWeakPtr(), tex_params, mem_params, bind_callback)));
|
| +
|
| + transfer_in_progress_ = true;
|
| +}
|
| +
|
| +void AsyncPixelTransferDelegateIdle::AsyncCompressedTexSubImage2D(
|
| + const AsyncCompressedTexSubImage2DParams& tex_params,
|
| + const AsyncMemoryParams& mem_params) {
|
| + TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage");
|
| + DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
|
| +
|
| + shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task(
|
| + id_, this,
|
| + base::Bind(
|
| + &AsyncPixelTransferDelegateIdle::PerformAsyncCompressedTexSubImage2D,
|
| + AsWeakPtr(), tex_params, mem_params)));
|
| +
|
| + transfer_in_progress_ = true;
|
| +}
|
| +
|
| bool AsyncPixelTransferDelegateIdle::TransferIsInProgress() {
|
| return transfer_in_progress_;
|
| }
|
| @@ -223,6 +301,74 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D(
|
| base::TimeTicks::HighResNow() - begin_time;
|
| }
|
|
|
| +void AsyncPixelTransferDelegateIdle::PerformAsyncCompressedTexImage2D(
|
| + AsyncCompressedTexImage2DParams tex_params,
|
| + AsyncMemoryParams mem_params,
|
| + const base::Closure& bind_callback) {
|
| + TRACE_EVENT2("gpu", "PerformAsyncCompressedTexImage2D", "width",
|
| + tex_params.width, "height", tex_params.height);
|
| +
|
| + void* data = mem_params.GetDataAddress();
|
| +
|
| + base::TimeTicks begin_time(base::TimeTicks::HighResNow());
|
| + gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
|
| +
|
| + {
|
| + TRACE_EVENT0("gpu", "glCompressedTexImage2D");
|
| + glCompressedTexImage2D(tex_params.target, tex_params.level,
|
| + tex_params.internal_format, tex_params.width,
|
| + tex_params.height, tex_params.border,
|
| + tex_params.image_size, data);
|
| + }
|
| +
|
| + TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage");
|
| + transfer_in_progress_ = false;
|
| + shared_state_->texture_upload_count++;
|
| + shared_state_->total_texture_upload_time +=
|
| + base::TimeTicks::HighResNow() - begin_time;
|
| +
|
| + // The texture is already fully bound so just call it now.
|
| + bind_callback.Run();
|
| +}
|
| +
|
| +void AsyncPixelTransferDelegateIdle::PerformAsyncCompressedTexSubImage2D(
|
| + AsyncCompressedTexSubImage2DParams tex_params,
|
| + AsyncMemoryParams mem_params) {
|
| + TRACE_EVENT2("gpu", "PerformAsyncCompressedTexSubImage2D", "width",
|
| + tex_params.width, "height", tex_params.height);
|
| +
|
| + void* data = mem_params.GetDataAddress();
|
| +
|
| + base::TimeTicks begin_time(base::TimeTicks::HighResNow());
|
| + gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
|
| +
|
| + // If it's a full texture update, use glCompressedTexImage2D as it's faster.
|
| + if (tex_params.xoffset == 0 && tex_params.yoffset == 0 &&
|
| + tex_params.target == compressed_define_params_.target &&
|
| + tex_params.level == compressed_define_params_.level &&
|
| + tex_params.width == compressed_define_params_.width &&
|
| + tex_params.height == compressed_define_params_.height) {
|
| + TRACE_EVENT0("gpu", "glCompressedTexImage2D");
|
| + glCompressedTexImage2D(
|
| + compressed_define_params_.target, compressed_define_params_.level,
|
| + compressed_define_params_.internal_format,
|
| + compressed_define_params_.width, compressed_define_params_.height,
|
| + compressed_define_params_.border, tex_params.image_size, data);
|
| + } else {
|
| + TRACE_EVENT0("gpu", "glCompressedTexSubImage2D");
|
| + glCompressedTexSubImage2D(tex_params.target, tex_params.level,
|
| + tex_params.xoffset, tex_params.yoffset,
|
| + tex_params.width, tex_params.height,
|
| + tex_params.format, tex_params.image_size, data);
|
| + }
|
| +
|
| + TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage");
|
| + transfer_in_progress_ = false;
|
| + shared_state_->texture_upload_count++;
|
| + shared_state_->total_texture_upload_time +=
|
| + base::TimeTicks::HighResNow() - begin_time;
|
| +}
|
| +
|
| AsyncPixelTransferManagerIdle::Task::Task(
|
| uint64 transfer_id,
|
| AsyncPixelTransferDelegate* delegate,
|
| @@ -242,7 +388,7 @@ AsyncPixelTransferManagerIdle::SharedState::~SharedState() {}
|
| void AsyncPixelTransferManagerIdle::SharedState::ProcessNotificationTasks() {
|
| while (!tasks.empty()) {
|
| // Stop when we reach a pixel transfer task.
|
| - if (tasks.front().transfer_id)
|
| + if (tasks.front().transfer_id > kSuspendTask)
|
| return;
|
|
|
| tasks.front().task.Run();
|
| @@ -269,7 +415,7 @@ void AsyncPixelTransferManagerIdle::AsyncNotifyCompletion(
|
| }
|
|
|
| shared_state_.tasks.push_back(
|
| - Task(0, // 0 transfer_id for notification tasks.
|
| + Task(kNotificationTask,
|
| NULL,
|
| base::Bind(
|
| &PerformNotifyCompletion,
|
| @@ -289,8 +435,16 @@ void AsyncPixelTransferManagerIdle::ProcessMorePendingTransfers() {
|
| if (shared_state_.tasks.empty())
|
| return;
|
|
|
| - // First task should always be a pixel transfer task.
|
| - DCHECK(shared_state_.tasks.front().transfer_id);
|
| + // Suspend uploads until waitables have been signalled.
|
| + while (!suspend_waitables_.empty()) {
|
| + if (!suspend_waitables_.front()->IsSignaled())
|
| + return;
|
| + else
|
| + suspend_waitables_.erase(suspend_waitables_.begin());
|
| + }
|
| +
|
| + // First task should always be a pixel transfer task or a suspend task.
|
| + DCHECK_NE(shared_state_.tasks.front().transfer_id, kNotificationTask);
|
| shared_state_.tasks.front().task.Run();
|
| shared_state_.tasks.pop_front();
|
|
|
| @@ -310,6 +464,32 @@ void AsyncPixelTransferManagerIdle::WaitAllAsyncTexImage2D() {
|
| task.delegate->WaitForTransferCompletion();
|
| }
|
|
|
| +void AsyncPixelTransferManagerIdle::DoSuspendUploads(
|
| + scoped_ptr<base::WaitableEvent> waitable) {
|
| + suspend_waitables_.push_back(waitable.release());
|
| +}
|
| +
|
| +void AsyncPixelTransferManagerIdle::SuspendUploads(
|
| + base::WaitableEvent* waitable) {
|
| + shared_state_.tasks.push_back(
|
| + Task(kSuspendTask,
|
| + NULL,
|
| + base::Bind(&AsyncPixelTransferManagerIdle::DoSuspendUploads,
|
| + base::Unretained(this),
|
| + base::Passed(
|
| + scoped_ptr<base::WaitableEvent>(waitable)))));
|
| +}
|
| +
|
| +void AsyncPixelTransferManagerIdle::SignalWhenUploadsCompleted(
|
| + base::WaitableEvent* waitable) {
|
| + shared_state_.tasks.push_back(
|
| + Task(kNotificationTask,
|
| + NULL,
|
| + base::Bind(&base::WaitableEvent::Signal,
|
| + // WaitableEvent owned by waiter.
|
| + base::Unretained(waitable))));
|
| +}
|
| +
|
| AsyncPixelTransferDelegate*
|
| AsyncPixelTransferManagerIdle::CreatePixelTransferDelegateImpl(
|
| gles2::TextureRef* ref,
|
| @@ -319,4 +499,12 @@ AsyncPixelTransferManagerIdle::CreatePixelTransferDelegateImpl(
|
| define_params);
|
| }
|
|
|
| +AsyncPixelTransferDelegate*
|
| +AsyncPixelTransferManagerIdle::CreatePixelTransferDelegateImpl(
|
| + gles2::TextureRef* ref,
|
| + const AsyncCompressedTexImage2DParams& define_params) {
|
| + return new AsyncPixelTransferDelegateIdle(&shared_state_, ref->service_id(),
|
| + define_params);
|
| +}
|
| +
|
| } // namespace gpu
|
|
|