Index: gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc |
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc |
deleted file mode 100644 |
index 86eb71803cf078b1b662c45f46a00f221ab74a68..0000000000000000000000000000000000000000 |
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc |
+++ /dev/null |
@@ -1,549 +0,0 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "gpu/command_buffer/service/async_pixel_transfer_manager_share_group.h" |
- |
-#include <list> |
- |
-#include "base/bind.h" |
-#include "base/lazy_instance.h" |
-#include "base/location.h" |
-#include "base/logging.h" |
-#include "base/memory/ref_counted.h" |
-#include "base/memory/weak_ptr.h" |
-#include "base/single_thread_task_runner.h" |
-#include "base/synchronization/cancellation_flag.h" |
-#include "base/synchronization/lock.h" |
-#include "base/synchronization/waitable_event.h" |
-#include "base/threading/thread.h" |
-#include "base/threading/thread_checker.h" |
-#include "base/trace_event/trace_event.h" |
-#include "base/trace_event/trace_event_synthetic_delay.h" |
-#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" |
-#include "ui/gl/gl_bindings.h" |
-#include "ui/gl/gl_context.h" |
-#include "ui/gl/gl_surface.h" |
-#include "ui/gl/gpu_preference.h" |
-#include "ui/gl/scoped_binders.h" |
- |
-namespace gpu { |
- |
-namespace { |
- |
-const char kAsyncTransferThreadName[] = "AsyncTransferThread"; |
- |
-void PerformNotifyCompletion( |
- AsyncMemoryParams mem_params, |
- scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { |
- TRACE_EVENT0("gpu", "PerformNotifyCompletion"); |
- observer->DidComplete(mem_params); |
-} |
- |
-// TODO(backer): Factor out common thread scheduling logic from the EGL and |
-// ShareGroup implementations. http://crbug.com/239889 |
-class TransferThread : public base::Thread { |
- public: |
- TransferThread() |
- : base::Thread(kAsyncTransferThreadName), |
- initialized_(false) { |
- base::Thread::Options options; |
-#if defined(OS_ANDROID) || defined(OS_LINUX) |
- options.priority = base::ThreadPriority::BACKGROUND; |
-#endif |
- StartWithOptions(options); |
- } |
- |
- ~TransferThread() override { |
- // The only instance of this class was declared leaky. |
- NOTREACHED(); |
- } |
- |
- void InitializeOnMainThread(gfx::GLContext* parent_context) { |
- TRACE_EVENT0("gpu", "TransferThread::InitializeOnMainThread"); |
- if (initialized_) |
- return; |
- |
- base::WaitableEvent wait_for_init(true, false); |
- task_runner()->PostTask( |
- FROM_HERE, |
- base::Bind(&TransferThread::InitializeOnTransferThread, |
- base::Unretained(this), base::Unretained(parent_context), |
- &wait_for_init)); |
- wait_for_init.Wait(); |
- } |
- |
- void CleanUp() override { |
- surface_ = NULL; |
- context_ = NULL; |
- } |
- |
- private: |
- bool initialized_; |
- |
- scoped_refptr<gfx::GLSurface> surface_; |
- scoped_refptr<gfx::GLContext> context_; |
- |
- void InitializeOnTransferThread(gfx::GLContext* parent_context, |
- base::WaitableEvent* caller_wait) { |
- TRACE_EVENT0("gpu", "InitializeOnTransferThread"); |
- |
- if (!parent_context) { |
- LOG(ERROR) << "No parent context provided."; |
- caller_wait->Signal(); |
- return; |
- } |
- |
- surface_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1)); |
- if (!surface_.get()) { |
- LOG(ERROR) << "Unable to create GLSurface"; |
- caller_wait->Signal(); |
- return; |
- } |
- |
- // TODO(backer): This is coded for integrated GPUs. For discrete GPUs |
- // we would probably want to use a PBO texture upload for a true async |
- // upload (that would hopefully be optimized as a DMA transfer by the |
- // driver). |
- context_ = gfx::GLContext::CreateGLContext(parent_context->share_group(), |
- surface_.get(), |
- gfx::PreferIntegratedGpu); |
- if (!context_.get()) { |
- LOG(ERROR) << "Unable to create GLContext."; |
- caller_wait->Signal(); |
- return; |
- } |
- |
- context_->MakeCurrent(surface_.get()); |
- initialized_ = true; |
- caller_wait->Signal(); |
- } |
- |
- DISALLOW_COPY_AND_ASSIGN(TransferThread); |
-}; |
- |
-base::LazyInstance<TransferThread>::Leaky |
- g_transfer_thread = LAZY_INSTANCE_INITIALIZER; |
- |
-base::SingleThreadTaskRunner* transfer_task_runner() { |
- return g_transfer_thread.Pointer()->task_runner().get(); |
-} |
- |
-class PendingTask : public base::RefCountedThreadSafe<PendingTask> { |
- public: |
- explicit PendingTask(const base::Closure& task) |
- : task_(task), task_pending_(true, false) {} |
- |
- bool TryRun() { |
- // This is meant to be called on the main thread where the texture |
- // is already bound. |
- DCHECK(checker_.CalledOnValidThread()); |
- if (task_lock_.Try()) { |
- // Only run once. |
- if (!task_.is_null()) |
- task_.Run(); |
- task_.Reset(); |
- |
- task_lock_.Release(); |
- task_pending_.Signal(); |
- return true; |
- } |
- return false; |
- } |
- |
- void BindAndRun(GLuint texture_id) { |
- // This is meant to be called on the upload thread where we don't have to |
- // restore the previous texture binding. |
- DCHECK(!checker_.CalledOnValidThread()); |
- base::AutoLock locked(task_lock_); |
- if (!task_.is_null()) { |
- glBindTexture(GL_TEXTURE_2D, texture_id); |
- task_.Run(); |
- task_.Reset(); |
- glBindTexture(GL_TEXTURE_2D, 0); |
- // Flush for synchronization between threads. |
- glFlush(); |
- task_pending_.Signal(); |
- } |
- } |
- |
- void Cancel() { |
- base::AutoLock locked(task_lock_); |
- task_.Reset(); |
- task_pending_.Signal(); |
- } |
- |
- bool TaskIsInProgress() { |
- return !task_pending_.IsSignaled(); |
- } |
- |
- void WaitForTask() { |
- task_pending_.Wait(); |
- } |
- |
- private: |
- friend class base::RefCountedThreadSafe<PendingTask>; |
- |
- virtual ~PendingTask() {} |
- |
- base::ThreadChecker checker_; |
- |
- base::Lock task_lock_; |
- base::Closure task_; |
- base::WaitableEvent task_pending_; |
- |
- DISALLOW_COPY_AND_ASSIGN(PendingTask); |
-}; |
- |
-// Class which holds async pixel transfers state. |
-// The texture_id is accessed by either thread, but everything |
-// else accessed only on the main thread. |
-class TransferStateInternal |
- : public base::RefCountedThreadSafe<TransferStateInternal> { |
- public: |
- TransferStateInternal(GLuint texture_id, |
- const AsyncTexImage2DParams& define_params) |
- : texture_id_(texture_id), define_params_(define_params) {} |
- |
- bool TransferIsInProgress() { |
- return pending_upload_task_.get() && |
- pending_upload_task_->TaskIsInProgress(); |
- } |
- |
- void BindTransfer() { |
- TRACE_EVENT2("gpu", "BindAsyncTransfer", |
- "width", define_params_.width, |
- "height", define_params_.height); |
- DCHECK(texture_id_); |
- |
- glBindTexture(GL_TEXTURE_2D, texture_id_); |
- bind_callback_.Run(); |
- } |
- |
- void WaitForTransferCompletion() { |
- TRACE_EVENT0("gpu", "WaitForTransferCompletion"); |
- DCHECK(pending_upload_task_.get()); |
- if (!pending_upload_task_->TryRun()) { |
- pending_upload_task_->WaitForTask(); |
- } |
- pending_upload_task_ = NULL; |
- } |
- |
- void CancelUpload() { |
- TRACE_EVENT0("gpu", "CancelUpload"); |
- if (pending_upload_task_.get()) |
- pending_upload_task_->Cancel(); |
- pending_upload_task_ = NULL; |
- } |
- |
- void ScheduleAsyncTexImage2D( |
- const AsyncTexImage2DParams tex_params, |
- const AsyncMemoryParams mem_params, |
- scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats, |
- const base::Closure& bind_callback) { |
- TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); |
- pending_upload_task_ = new PendingTask(base::Bind( |
- &TransferStateInternal::PerformAsyncTexImage2D, |
- this, |
- tex_params, |
- mem_params, |
- texture_upload_stats)); |
- transfer_task_runner()->PostTask( |
- FROM_HERE, base::Bind(&PendingTask::BindAndRun, pending_upload_task_, |
- texture_id_)); |
- |
- // Save the late bind callback, so we can notify the client when it is |
- // bound. |
- bind_callback_ = bind_callback; |
- } |
- |
- void ScheduleAsyncTexSubImage2D( |
- AsyncTexSubImage2DParams tex_params, |
- AsyncMemoryParams mem_params, |
- scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { |
- TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); |
- pending_upload_task_ = new PendingTask(base::Bind( |
- &TransferStateInternal::PerformAsyncTexSubImage2D, |
- this, |
- tex_params, |
- mem_params, |
- texture_upload_stats)); |
- transfer_task_runner()->PostTask( |
- FROM_HERE, base::Bind(&PendingTask::BindAndRun, pending_upload_task_, |
- texture_id_)); |
- } |
- |
- private: |
- friend class base::RefCountedThreadSafe<TransferStateInternal>; |
- |
- virtual ~TransferStateInternal() { |
- } |
- |
- void PerformAsyncTexImage2D( |
- AsyncTexImage2DParams tex_params, |
- AsyncMemoryParams mem_params, |
- scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { |
- TRACE_EVENT2("gpu", |
- "PerformAsyncTexImage", |
- "width", |
- tex_params.width, |
- "height", |
- tex_params.height); |
- DCHECK_EQ(0, tex_params.level); |
- |
- base::TimeTicks begin_time; |
- if (texture_upload_stats.get()) |
- begin_time = base::TimeTicks::Now(); |
- |
- void* data = mem_params.GetDataAddress(); |
- |
- { |
- TRACE_EVENT0("gpu", "glTexImage2D"); |
- glTexImage2D(GL_TEXTURE_2D, |
- tex_params.level, |
- tex_params.internal_format, |
- tex_params.width, |
- tex_params.height, |
- tex_params.border, |
- tex_params.format, |
- tex_params.type, |
- data); |
- TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage"); |
- } |
- |
- if (texture_upload_stats.get()) { |
- texture_upload_stats->AddUpload(base::TimeTicks::Now() - begin_time); |
- } |
- } |
- |
- void PerformAsyncTexSubImage2D( |
- AsyncTexSubImage2DParams tex_params, |
- AsyncMemoryParams mem_params, |
- scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { |
- TRACE_EVENT2("gpu", |
- "PerformAsyncTexSubImage2D", |
- "width", |
- tex_params.width, |
- "height", |
- tex_params.height); |
- DCHECK_EQ(0, tex_params.level); |
- |
- base::TimeTicks begin_time; |
- if (texture_upload_stats.get()) |
- begin_time = base::TimeTicks::Now(); |
- |
- void* data = mem_params.GetDataAddress(); |
- { |
- TRACE_EVENT0("gpu", "glTexSubImage2D"); |
- glTexSubImage2D(GL_TEXTURE_2D, |
- tex_params.level, |
- tex_params.xoffset, |
- tex_params.yoffset, |
- tex_params.width, |
- tex_params.height, |
- tex_params.format, |
- tex_params.type, |
- data); |
- TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage"); |
- } |
- |
- if (texture_upload_stats.get()) { |
- texture_upload_stats->AddUpload(base::TimeTicks::Now() - begin_time); |
- } |
- } |
- |
- scoped_refptr<PendingTask> pending_upload_task_; |
- |
- GLuint texture_id_; |
- |
- // Definition params for texture that needs binding. |
- AsyncTexImage2DParams define_params_; |
- |
- // Callback to invoke when AsyncTexImage2D is complete |
- // and the client can safely use the texture. This occurs |
- // during BindCompletedAsyncTransfers(). |
- base::Closure bind_callback_; |
-}; |
- |
-} // namespace |
- |
-class AsyncPixelTransferDelegateShareGroup |
- : public AsyncPixelTransferDelegate, |
- public base::SupportsWeakPtr<AsyncPixelTransferDelegateShareGroup> { |
- public: |
- AsyncPixelTransferDelegateShareGroup( |
- AsyncPixelTransferManagerShareGroup::SharedState* shared_state, |
- GLuint texture_id, |
- const AsyncTexImage2DParams& define_params); |
- ~AsyncPixelTransferDelegateShareGroup() override; |
- |
- void BindTransfer() { state_->BindTransfer(); } |
- |
- // Implement AsyncPixelTransferDelegate: |
- void AsyncTexImage2D(const AsyncTexImage2DParams& tex_params, |
- const AsyncMemoryParams& mem_params, |
- const base::Closure& bind_callback) override; |
- void AsyncTexSubImage2D(const AsyncTexSubImage2DParams& tex_params, |
- const AsyncMemoryParams& mem_params) override; |
- bool TransferIsInProgress() override; |
- void WaitForTransferCompletion() override; |
- |
- private: |
- // A raw pointer is safe because the SharedState is owned by the Manager, |
- // which owns this Delegate. |
- AsyncPixelTransferManagerShareGroup::SharedState* shared_state_; |
- scoped_refptr<TransferStateInternal> state_; |
- |
- DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateShareGroup); |
-}; |
- |
-AsyncPixelTransferDelegateShareGroup::AsyncPixelTransferDelegateShareGroup( |
- AsyncPixelTransferManagerShareGroup::SharedState* shared_state, |
- GLuint texture_id, |
- const AsyncTexImage2DParams& define_params) |
- : shared_state_(shared_state), |
- state_(new TransferStateInternal(texture_id, define_params)) {} |
- |
-AsyncPixelTransferDelegateShareGroup::~AsyncPixelTransferDelegateShareGroup() { |
- TRACE_EVENT0("gpu", " ~AsyncPixelTransferDelegateShareGroup"); |
- state_->CancelUpload(); |
-} |
- |
-bool AsyncPixelTransferDelegateShareGroup::TransferIsInProgress() { |
- return state_->TransferIsInProgress(); |
-} |
- |
-void AsyncPixelTransferDelegateShareGroup::WaitForTransferCompletion() { |
- if (state_->TransferIsInProgress()) { |
- state_->WaitForTransferCompletion(); |
- DCHECK(!state_->TransferIsInProgress()); |
- } |
- |
- // Fast track the BindTransfer, if applicable. |
- for (AsyncPixelTransferManagerShareGroup::SharedState::TransferQueue::iterator |
- iter = shared_state_->pending_allocations.begin(); |
- iter != shared_state_->pending_allocations.end(); |
- ++iter) { |
- if (iter->get() != this) |
- continue; |
- |
- shared_state_->pending_allocations.erase(iter); |
- BindTransfer(); |
- break; |
- } |
-} |
- |
-void AsyncPixelTransferDelegateShareGroup::AsyncTexImage2D( |
- const AsyncTexImage2DParams& tex_params, |
- const AsyncMemoryParams& mem_params, |
- const base::Closure& bind_callback) { |
- DCHECK(!state_->TransferIsInProgress()); |
- DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
- DCHECK_EQ(tex_params.level, 0); |
- |
- shared_state_->pending_allocations.push_back(AsWeakPtr()); |
- state_->ScheduleAsyncTexImage2D(tex_params, |
- mem_params, |
- shared_state_->texture_upload_stats, |
- bind_callback); |
-} |
- |
-void AsyncPixelTransferDelegateShareGroup::AsyncTexSubImage2D( |
- const AsyncTexSubImage2DParams& tex_params, |
- const AsyncMemoryParams& mem_params) { |
- TRACE_EVENT2("gpu", "AsyncTexSubImage2D", |
- "width", tex_params.width, |
- "height", tex_params.height); |
- DCHECK(!state_->TransferIsInProgress()); |
- DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
- DCHECK_EQ(tex_params.level, 0); |
- |
- state_->ScheduleAsyncTexSubImage2D( |
- tex_params, mem_params, shared_state_->texture_upload_stats); |
-} |
- |
-AsyncPixelTransferManagerShareGroup::SharedState::SharedState() |
- // TODO(reveman): Skip this if --enable-gpu-benchmarking is not present. |
- : texture_upload_stats(new AsyncPixelTransferUploadStats) {} |
- |
-AsyncPixelTransferManagerShareGroup::SharedState::~SharedState() {} |
- |
-AsyncPixelTransferManagerShareGroup::AsyncPixelTransferManagerShareGroup( |
- gfx::GLContext* context) { |
- g_transfer_thread.Pointer()->InitializeOnMainThread(context); |
-} |
- |
-AsyncPixelTransferManagerShareGroup::~AsyncPixelTransferManagerShareGroup() {} |
- |
-void AsyncPixelTransferManagerShareGroup::BindCompletedAsyncTransfers() { |
- scoped_ptr<gfx::ScopedTextureBinder> texture_binder; |
- |
- while (!shared_state_.pending_allocations.empty()) { |
- if (!shared_state_.pending_allocations.front().get()) { |
- shared_state_.pending_allocations.pop_front(); |
- continue; |
- } |
- AsyncPixelTransferDelegateShareGroup* delegate = |
- shared_state_.pending_allocations.front().get(); |
- // Terminate early, as all transfers finish in order, currently. |
- if (delegate->TransferIsInProgress()) |
- break; |
- |
- if (!texture_binder) |
- texture_binder.reset(new gfx::ScopedTextureBinder(GL_TEXTURE_2D, 0)); |
- |
- // Used to set tex info from the gles2 cmd decoder once upload has |
- // finished (it'll bind the texture and call a callback). |
- delegate->BindTransfer(); |
- |
- shared_state_.pending_allocations.pop_front(); |
- } |
-} |
- |
-void AsyncPixelTransferManagerShareGroup::AsyncNotifyCompletion( |
- const AsyncMemoryParams& mem_params, |
- AsyncPixelTransferCompletionObserver* observer) { |
- // Post a PerformNotifyCompletion task to the upload thread. This task |
- // will run after all async transfers are complete. |
- transfer_task_runner()->PostTask( |
- FROM_HERE, base::Bind(&PerformNotifyCompletion, mem_params, |
- make_scoped_refptr(observer))); |
-} |
- |
-uint32 AsyncPixelTransferManagerShareGroup::GetTextureUploadCount() { |
- return shared_state_.texture_upload_stats->GetStats(NULL); |
-} |
- |
-base::TimeDelta |
-AsyncPixelTransferManagerShareGroup::GetTotalTextureUploadTime() { |
- base::TimeDelta total_texture_upload_time; |
- shared_state_.texture_upload_stats->GetStats(&total_texture_upload_time); |
- return total_texture_upload_time; |
-} |
- |
-void AsyncPixelTransferManagerShareGroup::ProcessMorePendingTransfers() { |
-} |
- |
-bool AsyncPixelTransferManagerShareGroup::NeedsProcessMorePendingTransfers() { |
- return false; |
-} |
- |
-void AsyncPixelTransferManagerShareGroup::WaitAllAsyncTexImage2D() { |
- if (shared_state_.pending_allocations.empty()) |
- return; |
- |
- AsyncPixelTransferDelegateShareGroup* delegate = |
- shared_state_.pending_allocations.back().get(); |
- if (delegate) |
- delegate->WaitForTransferCompletion(); |
-} |
- |
-AsyncPixelTransferDelegate* |
-AsyncPixelTransferManagerShareGroup::CreatePixelTransferDelegateImpl( |
- gles2::TextureRef* ref, |
- const AsyncTexImage2DParams& define_params) { |
- return new AsyncPixelTransferDelegateShareGroup( |
- &shared_state_, ref->service_id(), define_params); |
-} |
- |
-} // namespace gpu |