diff options
Diffstat (limited to 'chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc')
-rw-r--r-- | chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc | 733 |
1 files changed, 0 insertions, 733 deletions
diff --git a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc b/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc deleted file mode 100644 index 6e1c3e7c61e..00000000000 --- a/chromium/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc +++ /dev/null @@ -1,733 +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_egl.h" - -#include <list> -#include <string> - -#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/single_thread_task_runner.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.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_context.h" -#include "ui/gl/gl_surface_egl.h" -#include "ui/gl/scoped_binders.h" - -namespace gpu { - -namespace { - -bool CheckErrors(const char* file, int line) { - EGLint eglerror; - GLenum glerror; - bool success = true; - while ((eglerror = eglGetError()) != EGL_SUCCESS) { - LOG(ERROR) << "Async transfer EGL error at " - << file << ":" << line << " " << eglerror; - success = false; - } - while ((glerror = glGetError()) != GL_NO_ERROR) { - LOG(ERROR) << "Async transfer OpenGL error at " - << file << ":" << line << " " << glerror; - success = false; - } - return success; -} -#define CHECK_GL() CheckErrors(__FILE__, __LINE__) - -const char kAsyncTransferThreadName[] = "AsyncTransferThread"; - -// Regular glTexImage2D call. -void DoTexImage2D(const AsyncTexImage2DParams& tex_params, void* data) { - 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); -} - -// Regular glTexSubImage2D call. -void DoTexSubImage2D(const AsyncTexSubImage2DParams& tex_params, void* data) { - 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); -} - -// Full glTexSubImage2D call, from glTexImage2D params. -void DoFullTexSubImage2D(const AsyncTexImage2DParams& tex_params, void* data) { - glTexSubImage2D( - GL_TEXTURE_2D, tex_params.level, - 0, 0, tex_params.width, tex_params.height, - tex_params.format, tex_params.type, data); -} - -void SetGlParametersForEglImageTexture() { - // These params are needed for EGLImage creation to succeed on several - // Android devices. I couldn't find this requirement in the EGLImage - // extension spec, but several devices fail without it. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -} - -void PerformNotifyCompletion( - AsyncMemoryParams mem_params, - scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { - TRACE_EVENT0("gpu", "PerformNotifyCompletion"); - observer->DidComplete(mem_params); -} - -class TransferThread : public base::Thread { - public: - TransferThread() : base::Thread(kAsyncTransferThreadName) { - base::Thread::Options options; -#if defined(OS_ANDROID) - options.priority = base::ThreadPriority::BACKGROUND; -#endif - StartWithOptions(options); - } - ~TransferThread() override { Stop(); } - - void Init() override { - gfx::GLShareGroup* share_group = NULL; - surface_ = new gfx::PbufferGLSurfaceEGL(gfx::Size(1, 1)); - surface_->Initialize(); - context_ = gfx::GLContext::CreateGLContext( - share_group, surface_.get(), gfx::PreferDiscreteGpu); - bool is_current = context_->MakeCurrent(surface_.get()); - DCHECK(is_current); - } - - void CleanUp() override { - surface_ = NULL; - context_->ReleaseCurrent(surface_.get()); - context_ = NULL; - } - - private: - scoped_refptr<gfx::GLContext> context_; - scoped_refptr<gfx::GLSurface> surface_; - - DISALLOW_COPY_AND_ASSIGN(TransferThread); -}; - -base::LazyInstance<TransferThread> - g_transfer_thread = LAZY_INSTANCE_INITIALIZER; - -base::SingleThreadTaskRunner* transfer_task_runner() { - return g_transfer_thread.Pointer()->task_runner().get(); -} - -// Class which holds async pixel transfers state (EGLImage). -// The EGLImage 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, - bool wait_for_uploads, - bool wait_for_creation, - bool use_image_preserved) - : texture_id_(texture_id), - thread_texture_id_(0), - transfer_completion_(true, true), - egl_image_(EGL_NO_IMAGE_KHR), - wait_for_uploads_(wait_for_uploads), - wait_for_creation_(wait_for_creation), - use_image_preserved_(use_image_preserved) { - define_params_ = define_params; - } - - bool TransferIsInProgress() { - return !transfer_completion_.IsSignaled(); - } - - void BindTransfer() { - TRACE_EVENT2("gpu", "BindAsyncTransfer glEGLImageTargetTexture2DOES", - "width", define_params_.width, - "height", define_params_.height); - DCHECK(texture_id_); - if (EGL_NO_IMAGE_KHR == egl_image_) - return; - - glBindTexture(GL_TEXTURE_2D, texture_id_); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); - bind_callback_.Run(); - - DCHECK(CHECK_GL()); - } - - void CreateEglImage(GLuint texture_id) { - TRACE_EVENT0("gpu", "eglCreateImageKHR"); - DCHECK(texture_id); - DCHECK_EQ(egl_image_, EGL_NO_IMAGE_KHR); - - EGLDisplay egl_display = eglGetCurrentDisplay(); - EGLContext egl_context = eglGetCurrentContext(); - EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; - EGLClientBuffer egl_buffer = - reinterpret_cast<EGLClientBuffer>(texture_id); - - EGLint image_preserved = use_image_preserved_ ? EGL_TRUE : EGL_FALSE; - EGLint egl_attrib_list[] = { - EGL_GL_TEXTURE_LEVEL_KHR, 0, // mip-level. - EGL_IMAGE_PRESERVED_KHR, image_preserved, - EGL_NONE - }; - egl_image_ = eglCreateImageKHR( - egl_display, - egl_context, - egl_target, - egl_buffer, - egl_attrib_list); - - DLOG_IF(ERROR, EGL_NO_IMAGE_KHR == egl_image_) - << "eglCreateImageKHR failed"; - } - - void CreateEglImageOnUploadThread() { - CreateEglImage(thread_texture_id_); - } - - void CreateEglImageOnMainThreadIfNeeded() { - if (egl_image_ == EGL_NO_IMAGE_KHR) { - CreateEglImage(texture_id_); - if (wait_for_creation_) { - TRACE_EVENT0("gpu", "glFinish creation"); - glFinish(); - } - } - } - - void WaitForLastUpload() { - // This glFinish is just a safe-guard for if uploads have some - // GPU action that needs to occur. We could use fences and try - // to do this less often. However, on older drivers fences are - // not always reliable (eg. Mali-400 just blocks forever). - if (wait_for_uploads_) { - TRACE_EVENT0("gpu", "glFinish"); - glFinish(); - } - } - - void MarkAsTransferIsInProgress() { - TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); - transfer_completion_.Reset(); - } - - void MarkAsCompleted() { - TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage"); - transfer_completion_.Signal(); - } - - void WaitForTransferCompletion() { - TRACE_EVENT0("gpu", "WaitForTransferCompletion"); - // TODO(backer): Deschedule the channel rather than blocking the main GPU - // thread (crbug.com/240265). - transfer_completion_.Wait(); - } - - 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(!thread_texture_id_); - DCHECK_EQ(0, tex_params.level); - if (EGL_NO_IMAGE_KHR != egl_image_) { - MarkAsCompleted(); - return; - } - - void* data = mem_params.GetDataAddress(); - - base::TimeTicks begin_time; - if (texture_upload_stats.get()) - begin_time = base::TimeTicks::Now(); - - { - TRACE_EVENT0("gpu", "glTexImage2D no data"); - glGenTextures(1, &thread_texture_id_); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, thread_texture_id_); - - SetGlParametersForEglImageTexture(); - - // If we need to use image_preserved, we pass the data with - // the allocation. Otherwise we use a NULL allocation to - // try to avoid any costs associated with creating the EGLImage. - if (use_image_preserved_) - DoTexImage2D(tex_params, data); - else - DoTexImage2D(tex_params, NULL); - } - - CreateEglImageOnUploadThread(); - - { - TRACE_EVENT0("gpu", "glTexSubImage2D with data"); - - // If we didn't use image_preserved, we haven't uploaded - // the data yet, so we do this with a full texSubImage. - if (!use_image_preserved_) - DoFullTexSubImage2D(tex_params, data); - } - - WaitForLastUpload(); - MarkAsCompleted(); - - DCHECK(CHECK_GL()); - 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_NE(EGL_NO_IMAGE_KHR, egl_image_); - DCHECK_EQ(0, tex_params.level); - - void* data = mem_params.GetDataAddress(); - - base::TimeTicks begin_time; - if (texture_upload_stats.get()) - begin_time = base::TimeTicks::Now(); - - if (!thread_texture_id_) { - TRACE_EVENT0("gpu", "glEGLImageTargetTexture2DOES"); - glGenTextures(1, &thread_texture_id_); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, thread_texture_id_); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); - } else { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, thread_texture_id_); - } - { - TRACE_EVENT0("gpu", "glTexSubImage2D"); - DoTexSubImage2D(tex_params, data); - } - WaitForLastUpload(); - MarkAsCompleted(); - - DCHECK(CHECK_GL()); - if (texture_upload_stats.get()) { - texture_upload_stats->AddUpload(base::TimeTicks::Now() - begin_time); - } - } - - protected: - friend class base::RefCountedThreadSafe<TransferStateInternal>; - friend class gpu::AsyncPixelTransferDelegateEGL; - - static void DeleteTexture(GLuint id) { - glDeleteTextures(1, &id); - } - - virtual ~TransferStateInternal() { - if (egl_image_ != EGL_NO_IMAGE_KHR) { - EGLDisplay display = eglGetCurrentDisplay(); - eglDestroyImageKHR(display, egl_image_); - } - if (thread_texture_id_) { - transfer_task_runner()->PostTask( - FROM_HERE, base::Bind(&DeleteTexture, thread_texture_id_)); - } - } - - // The 'real' texture. - GLuint texture_id_; - - // The EGLImage sibling on the upload thread. - GLuint thread_texture_id_; - - // Definition params for texture that needs binding. - AsyncTexImage2DParams define_params_; - - // Indicates that an async transfer is 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 - // one for the lifetime of the texture. - EGLImageKHR egl_image_; - - // Callback to invoke when AsyncTexImage2D is complete - // and the client can safely use the texture. This occurs - // during BindCompletedAsyncTransfers(). - base::Closure bind_callback_; - - // Customize when we block on fences (these are work-arounds). - bool wait_for_uploads_; - bool wait_for_creation_; - bool use_image_preserved_; -}; - -} // namespace - -// Class which handles async pixel transfers using EGLImageKHR and another -// upload thread -class AsyncPixelTransferDelegateEGL - : public AsyncPixelTransferDelegate, - public base::SupportsWeakPtr<AsyncPixelTransferDelegateEGL> { - public: - AsyncPixelTransferDelegateEGL( - AsyncPixelTransferManagerEGL::SharedState* shared_state, - GLuint texture_id, - const AsyncTexImage2DParams& define_params); - ~AsyncPixelTransferDelegateEGL() 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: - // Returns true if a work-around was used. - bool WorkAroundAsyncTexImage2D( - const AsyncTexImage2DParams& tex_params, - const AsyncMemoryParams& mem_params, - const base::Closure& bind_callback); - bool WorkAroundAsyncTexSubImage2D( - const AsyncTexSubImage2DParams& tex_params, - const AsyncMemoryParams& mem_params); - - // A raw pointer is safe because the SharedState is owned by the Manager, - // which owns this Delegate. - AsyncPixelTransferManagerEGL::SharedState* shared_state_; - scoped_refptr<TransferStateInternal> state_; - - DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateEGL); -}; - -AsyncPixelTransferDelegateEGL::AsyncPixelTransferDelegateEGL( - AsyncPixelTransferManagerEGL::SharedState* shared_state, - GLuint texture_id, - const AsyncTexImage2DParams& define_params) - : shared_state_(shared_state) { - // We can't wait on uploads on imagination (it can take 200ms+). - // In practice, they are complete when the CPU glTexSubImage2D completes. - bool wait_for_uploads = !shared_state_->is_imagination; - - // Qualcomm runs into texture corruption problems if the same texture is - // uploaded to with both async and normal uploads. Synchronize after EGLImage - // creation on the main thread as a work-around. - bool wait_for_creation = shared_state_->is_qualcomm; - - // Qualcomm has a race when using image_preserved=FALSE, - // which can result in black textures even after the first upload. - // Since using FALSE is mainly for performance (to avoid layout changes), - // but Qualcomm itself doesn't seem to get any performance benefit, - // we just using image_preservedd=TRUE on Qualcomm as a work-around. - bool use_image_preserved = - shared_state_->is_qualcomm || shared_state_->is_imagination; - - state_ = new TransferStateInternal(texture_id, - define_params, - wait_for_uploads, - wait_for_creation, - use_image_preserved); -} - -AsyncPixelTransferDelegateEGL::~AsyncPixelTransferDelegateEGL() {} - -bool AsyncPixelTransferDelegateEGL::TransferIsInProgress() { - return state_->TransferIsInProgress(); -} - -void AsyncPixelTransferDelegateEGL::WaitForTransferCompletion() { - if (state_->TransferIsInProgress()) { - state_->WaitForTransferCompletion(); - DCHECK(!state_->TransferIsInProgress()); - } -} - -void AsyncPixelTransferDelegateEGL::AsyncTexImage2D( - const AsyncTexImage2DParams& tex_params, - const AsyncMemoryParams& mem_params, - const base::Closure& bind_callback) { - if (WorkAroundAsyncTexImage2D(tex_params, mem_params, bind_callback)) - return; - - DCHECK(!state_->TransferIsInProgress()); - DCHECK_EQ(state_->egl_image_, EGL_NO_IMAGE_KHR); - DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); - DCHECK_EQ(tex_params.level, 0); - - // Mark the transfer in progress and save the late bind - // callback, so we can notify the client when it is bound. - shared_state_->pending_allocations.push_back(AsWeakPtr()); - state_->bind_callback_ = bind_callback; - - // Mark the transfer in progress. - state_->MarkAsTransferIsInProgress(); - - // Duplicate the shared memory so there is no way we can get - // a use-after-free of the raw pixels. - transfer_task_runner()->PostTask( - FROM_HERE, - base::Bind(&TransferStateInternal::PerformAsyncTexImage2D, state_, - tex_params, mem_params, shared_state_->texture_upload_stats)); - - DCHECK(CHECK_GL()); -} - -void AsyncPixelTransferDelegateEGL::AsyncTexSubImage2D( - const AsyncTexSubImage2DParams& tex_params, - const AsyncMemoryParams& mem_params) { - TRACE_EVENT2("gpu", "AsyncTexSubImage2D", - "width", tex_params.width, - "height", tex_params.height); - if (WorkAroundAsyncTexSubImage2D(tex_params, mem_params)) - return; - DCHECK(!state_->TransferIsInProgress()); - DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); - DCHECK_EQ(tex_params.level, 0); - - // Mark the transfer in progress. - state_->MarkAsTransferIsInProgress(); - - // If this wasn't async allocated, we don't have an EGLImage yet. - // Create the EGLImage if it hasn't already been created. - state_->CreateEglImageOnMainThreadIfNeeded(); - - // Duplicate the shared memory so there are no way we can get - // a use-after-free of the raw pixels. - transfer_task_runner()->PostTask( - FROM_HERE, - base::Bind(&TransferStateInternal::PerformAsyncTexSubImage2D, state_, - tex_params, mem_params, shared_state_->texture_upload_stats)); - - DCHECK(CHECK_GL()); -} - -namespace { -bool IsPowerOfTwo (unsigned int x) { - return ((x != 0) && !(x & (x - 1))); -} - -bool IsMultipleOfEight(unsigned int x) { - return (x & 7) == 0; -} - -bool DimensionsSupportImgFastPath(int width, int height) { - // Multiple of eight, but not a power of two. - return IsMultipleOfEight(width) && - IsMultipleOfEight(height) && - !(IsPowerOfTwo(width) && - IsPowerOfTwo(height)); -} -} // namespace - -// It is very difficult to stream uploads on Imagination GPUs: -// - glTexImage2D defers a swizzle/stall until draw-time -// - glTexSubImage2D will sleep for 16ms on a good day, and 100ms -// or longer if OpenGL is in heavy use by another thread. -// The one combination that avoids these problems requires: -// a.) Allocations/Uploads must occur on different threads/contexts. -// b.) Texture size must be non-power-of-two. -// When using a+b, uploads will be incorrect/corrupt unless: -// c.) Texture size must be a multiple-of-eight. -// -// To achieve a.) we allocate synchronously on the main thread followed -// by uploading on the upload thread. When b/c are not true we fall back -// on purely synchronous allocation/upload on the main thread. - -bool AsyncPixelTransferDelegateEGL::WorkAroundAsyncTexImage2D( - const AsyncTexImage2DParams& tex_params, - const AsyncMemoryParams& mem_params, - const base::Closure& bind_callback) { - if (!shared_state_->is_imagination) - return false; - - // On imagination we allocate synchronously all the time, even - // if the dimensions support fast uploads. This is for part a.) - // above, so allocations occur on a different thread/context as uploads. - void* data = mem_params.GetDataAddress(); - SetGlParametersForEglImageTexture(); - - { - TRACE_EVENT0("gpu", "glTexImage2D with data"); - DoTexImage2D(tex_params, data); - } - - // The allocation has already occured, so mark it as finished - // and ready for binding. - CHECK(!state_->TransferIsInProgress()); - - // If the dimensions support fast async uploads, create the - // EGLImage for future uploads. The late bind should not - // be needed since the EGLImage was created from the main thread - // texture, but this is required to prevent an imagination driver crash. - if (DimensionsSupportImgFastPath(tex_params.width, tex_params.height)) { - state_->CreateEglImageOnMainThreadIfNeeded(); - shared_state_->pending_allocations.push_back(AsWeakPtr()); - state_->bind_callback_ = bind_callback; - } - - DCHECK(CHECK_GL()); - return true; -} - -bool AsyncPixelTransferDelegateEGL::WorkAroundAsyncTexSubImage2D( - const AsyncTexSubImage2DParams& tex_params, - const AsyncMemoryParams& mem_params) { - if (!shared_state_->is_imagination) - return false; - - // If the dimensions support fast async uploads, we can use the - // normal async upload path for uploads. - if (DimensionsSupportImgFastPath(tex_params.width, tex_params.height)) - return false; - - // Fall back on a synchronous stub as we don't have a known fast path. - // Also, older ICS drivers crash when we do any glTexSubImage2D on the - // same thread. To work around this we do glTexImage2D instead. Since - // we didn't create an EGLImage for this texture (see above), this is - // okay, but it limits this API to full updates for now. - DCHECK(!state_->egl_image_); - DCHECK_EQ(tex_params.xoffset, 0); - DCHECK_EQ(tex_params.yoffset, 0); - DCHECK_EQ(state_->define_params_.width, tex_params.width); - DCHECK_EQ(state_->define_params_.height, tex_params.height); - DCHECK_EQ(state_->define_params_.level, tex_params.level); - DCHECK_EQ(state_->define_params_.format, tex_params.format); - DCHECK_EQ(state_->define_params_.type, tex_params.type); - - void* data = mem_params.GetDataAddress(); - base::TimeTicks begin_time; - if (shared_state_->texture_upload_stats.get()) - begin_time = base::TimeTicks::Now(); - { - TRACE_EVENT0("gpu", "glTexSubImage2D"); - // Note we use define_params_ instead of tex_params. - // The DCHECKs above verify this is always the same. - DoTexImage2D(state_->define_params_, data); - } - if (shared_state_->texture_upload_stats.get()) { - shared_state_->texture_upload_stats - ->AddUpload(base::TimeTicks::Now() - begin_time); - } - - DCHECK(CHECK_GL()); - return true; -} - -AsyncPixelTransferManagerEGL::SharedState::SharedState() - // TODO(reveman): Skip this if --enable-gpu-benchmarking is not present. - : texture_upload_stats(new AsyncPixelTransferUploadStats) { - const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); - if (vendor) { - is_imagination = - std::string(vendor).find("Imagination") != std::string::npos; - is_qualcomm = std::string(vendor).find("Qualcomm") != std::string::npos; - } -} - -AsyncPixelTransferManagerEGL::SharedState::~SharedState() {} - -AsyncPixelTransferManagerEGL::AsyncPixelTransferManagerEGL() {} - -AsyncPixelTransferManagerEGL::~AsyncPixelTransferManagerEGL() {} - -void AsyncPixelTransferManagerEGL::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; - } - AsyncPixelTransferDelegateEGL* 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)); - - // If the transfer is finished, bind it to the texture - // and remove it from pending list. - delegate->BindTransfer(); - shared_state_.pending_allocations.pop_front(); - } -} - -void AsyncPixelTransferManagerEGL::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 AsyncPixelTransferManagerEGL::GetTextureUploadCount() { - return shared_state_.texture_upload_stats->GetStats(NULL); -} - -base::TimeDelta AsyncPixelTransferManagerEGL::GetTotalTextureUploadTime() { - base::TimeDelta total_texture_upload_time; - shared_state_.texture_upload_stats->GetStats(&total_texture_upload_time); - return total_texture_upload_time; -} - -void AsyncPixelTransferManagerEGL::ProcessMorePendingTransfers() { -} - -bool AsyncPixelTransferManagerEGL::NeedsProcessMorePendingTransfers() { - return false; -} - -void AsyncPixelTransferManagerEGL::WaitAllAsyncTexImage2D() { - if (shared_state_.pending_allocations.empty()) - return; - - AsyncPixelTransferDelegateEGL* delegate = - shared_state_.pending_allocations.back().get(); - if (delegate) - delegate->WaitForTransferCompletion(); -} - -AsyncPixelTransferDelegate* -AsyncPixelTransferManagerEGL::CreatePixelTransferDelegateImpl( - gles2::TextureRef* ref, - const AsyncTexImage2DParams& define_params) { - return new AsyncPixelTransferDelegateEGL( - &shared_state_, ref->service_id(), define_params); -} - -} // namespace gpu |