Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(577)

Unified Diff: ui/gl/async_pixel_transfer_delegate_idle.cc

Issue 12040049: gpu: Implement idle async pixel transfers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add DCHECKs to ensure idle async uploads are only used with GL_TEXTURE_2D target Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/gl/async_pixel_transfer_delegate_idle.h ('k') | ui/gl/async_pixel_transfer_delegate_stub.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gl/async_pixel_transfer_delegate_idle.cc
diff --git a/ui/gl/async_pixel_transfer_delegate_idle.cc b/ui/gl/async_pixel_transfer_delegate_idle.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9c721e58092d2b3edb8a1624b6eba64271e6fb11
--- /dev/null
+++ b/ui/gl/async_pixel_transfer_delegate_idle.cc
@@ -0,0 +1,328 @@
+// Copyright (c) 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 "ui/gl/async_pixel_transfer_delegate_idle.h"
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "base/lazy_instance.h"
+#include "base/message_loop.h"
+#include "base/process_util.h"
+#include "base/shared_memory.h"
+#include "build/build_config.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/safe_shared_memory_pool.h"
+#include "ui/gl/scoped_make_current.h"
+
+using base::SharedMemory;
+using base::SharedMemoryHandle;
+
+namespace gfx {
+
+namespace {
+
+// Gets the address of the data from shared memory.
+void* GetAddress(SharedMemory* shared_memory, uint32 shm_data_offset) {
+ // Memory bounds have already been validated, so there
+ // are just DCHECKS here.
+ DCHECK(shared_memory);
+ DCHECK(shared_memory->memory());
+ return static_cast<int8*>(shared_memory->memory()) + shm_data_offset;
+}
+
+base::LazyInstance<SafeSharedMemoryPool> g_safe_shared_memory_pool =
+ LAZY_INSTANCE_INITIALIZER;
+
+SafeSharedMemoryPool* safe_shared_memory_pool() {
+ return g_safe_shared_memory_pool.Pointer();
+}
+
+static uint64 g_next_pixel_transfer_state_id = 1;
+
+} // namespace
+
+#if !defined(OS_ANDROID)
+scoped_ptr<AsyncPixelTransferDelegate>
+ AsyncPixelTransferDelegate::Create(gfx::GLContext* context) {
+ return AsyncPixelTransferDelegateIdle::Create(context);
+}
+#endif
+
+scoped_ptr<AsyncPixelTransferDelegate>
+ AsyncPixelTransferDelegateIdle::Create(gfx::GLContext* context) {
+ return make_scoped_ptr(
+ static_cast<AsyncPixelTransferDelegate*>(
+ new AsyncPixelTransferDelegateIdle()));
+}
+
+class AsyncPixelTransferStateIdle : public AsyncPixelTransferState {
+ public:
+ typedef base::Callback<void(GLuint)> TransferCallback;
+
+ explicit AsyncPixelTransferStateIdle(GLuint texture_id)
+ : id_(g_next_pixel_transfer_state_id++),
+ texture_id_(texture_id),
+ transfer_in_progress_(false) {
+ }
+ virtual ~AsyncPixelTransferStateIdle() {}
+
+ // Overridden from gfx::AsyncPixelTransferState:
+ virtual bool TransferIsInProgress() OVERRIDE {
+ return transfer_in_progress_;
+ }
+
+ uint64 id() const { return id_; }
+
+ void set_transfer_in_progress(bool transfer_in_progress) {
+ transfer_in_progress_ = transfer_in_progress;
+ }
+
+ void PerformTransfer(const TransferCallback& callback) {
+ DCHECK(texture_id_);
+ DCHECK(transfer_in_progress_);
+ callback.Run(texture_id_);
+ transfer_in_progress_ = false;
+ }
+
+ private:
+ uint64 id_;
+ GLuint texture_id_;
+ bool transfer_in_progress_;
+};
+
+AsyncPixelTransferDelegateIdle::Transfer::Transfer(
+ uint64 id, const base::Closure& task)
+ : id(id),
+ task(task) {
+}
+
+AsyncPixelTransferDelegateIdle::Transfer::~Transfer() {}
+
+AsyncPixelTransferDelegateIdle::AsyncPixelTransferDelegateIdle()
+ : texture_upload_count_(0) {
+}
+
+AsyncPixelTransferDelegateIdle::~AsyncPixelTransferDelegateIdle() {
+}
+
+AsyncPixelTransferState*
+ AsyncPixelTransferDelegateIdle::CreateRawPixelTransferState(
+ GLuint texture_id,
+ const AsyncTexImage2DParams& define_params) {
+ return new AsyncPixelTransferStateIdle(texture_id);
+}
+
+bool AsyncPixelTransferDelegateIdle::BindCompletedAsyncTransfers() {
+ // Everything is already bound.
+ return false;
+}
+
+void AsyncPixelTransferDelegateIdle::AsyncNotifyCompletion(
+ const AsyncMemoryParams& mem_params,
+ const CompletionCallback& callback) {
+ if (transfers_.empty()) {
+ callback.Run(mem_params);
+ return;
+ }
+
+ transfers_.back().notifications.push(
+ base::Bind(
+ &AsyncPixelTransferDelegateIdle::PerformNotifyCompletion,
+ AsWeakPtr(),
+ mem_params,
+ base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
+ mem_params.shared_memory,
+ mem_params.shm_size)),
+ callback));
+}
+
+void AsyncPixelTransferDelegateIdle::AsyncTexImage2D(
+ AsyncPixelTransferState* transfer_state,
+ const AsyncTexImage2DParams& tex_params,
+ const AsyncMemoryParams& mem_params,
+ const base::Closure& bind_callback) {
+ AsyncPixelTransferStateIdle* state =
+ static_cast<AsyncPixelTransferStateIdle*>(transfer_state);
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
+ DCHECK(mem_params.shared_memory);
+ DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
+ mem_params.shm_size);
+ DCHECK(state);
+
+ transfers_.push_back(
+ Transfer(
+ state->id(),
+ base::Bind(
+ &AsyncPixelTransferStateIdle::PerformTransfer,
+ base::AsWeakPtr(state),
+ base::Bind(
+ &AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D,
+ AsWeakPtr(),
+ tex_params,
+ mem_params,
+ bind_callback,
+ base::Owned(new ScopedSafeSharedMemory(
+ safe_shared_memory_pool(),
+ mem_params.shared_memory,
+ mem_params.shm_size))))));
+
+ state->set_transfer_in_progress(true);
+}
+
+void AsyncPixelTransferDelegateIdle::AsyncTexSubImage2D(
+ AsyncPixelTransferState* transfer_state,
+ const AsyncTexSubImage2DParams& tex_params,
+ const AsyncMemoryParams& mem_params) {
+ AsyncPixelTransferStateIdle* state =
+ static_cast<AsyncPixelTransferStateIdle*>(transfer_state);
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
+ DCHECK(mem_params.shared_memory);
+ DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
+ mem_params.shm_size);
+ DCHECK(state);
+
+ transfers_.push_back(
+ Transfer(
+ state->id(),
+ base::Bind(
+ &AsyncPixelTransferStateIdle::PerformTransfer,
+ base::AsWeakPtr(state),
+ base::Bind(
+ &AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D,
+ AsWeakPtr(),
+ tex_params,
+ mem_params,
+ base::Owned(new ScopedSafeSharedMemory(
+ safe_shared_memory_pool(),
+ mem_params.shared_memory,
+ mem_params.shm_size))))));
+
+ state->set_transfer_in_progress(true);
+}
+
+void AsyncPixelTransferDelegateIdle::WaitForTransferCompletion(
+ AsyncPixelTransferState* transfer_state) {
+ AsyncPixelTransferStateIdle* state =
+ static_cast<AsyncPixelTransferStateIdle*>(transfer_state);
+ DCHECK(state);
+
+ for (std::list<Transfer>::iterator iter = transfers_.begin();
+ iter != transfers_.end(); ++iter) {
+ if (iter->id != state->id())
+ continue;
+
+ ProcessTransfer(*iter);
+ transfers_.erase(iter);
+ break;
+ }
+}
+
+uint32 AsyncPixelTransferDelegateIdle::GetTextureUploadCount() {
+ return texture_upload_count_;
+}
+
+base::TimeDelta AsyncPixelTransferDelegateIdle::GetTotalTextureUploadTime() {
+ return total_texture_upload_time_;
+}
+
+bool AsyncPixelTransferDelegateIdle::ProcessMorePendingTransfers() {
+ if (transfers_.empty())
+ return false;
+
+ ProcessTransfer(transfers_.front());
+ transfers_.pop_front();
+ return true;
+}
+
+bool AsyncPixelTransferDelegateIdle::NeedsProcessMorePendingTransfers() {
+ return !transfers_.empty();
+}
+
+void AsyncPixelTransferDelegateIdle::ProcessTransfer(Transfer& transfer) {
+ transfer.task.Run();
+ while (!transfer.notifications.empty()) {
+ transfer.notifications.front().Run();
+ transfer.notifications.pop();
+ }
+}
+
+void AsyncPixelTransferDelegateIdle::PerformNotifyCompletion(
+ AsyncMemoryParams mem_params,
+ ScopedSafeSharedMemory* safe_shared_memory,
+ const CompletionCallback& callback) {
+ TRACE_EVENT0("gpu", "PerformNotifyCompletion");
+ gfx::AsyncMemoryParams safe_mem_params = mem_params;
+ safe_mem_params.shared_memory = safe_shared_memory->shared_memory();
+ callback.Run(safe_mem_params);
+}
+
+void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D(
+ AsyncTexImage2DParams tex_params,
+ AsyncMemoryParams mem_params,
+ const base::Closure& bind_callback,
+ ScopedSafeSharedMemory* safe_shared_memory,
+ GLuint texture_id) {
+ TRACE_EVENT2("gpu", "PerformAsyncTexImage2D",
+ "width", tex_params.width,
+ "height", tex_params.height);
+
+ void* data = GetAddress(safe_shared_memory->shared_memory(),
+ mem_params.shm_data_offset);
+
+ glBindTexture(tex_params.target, texture_id);
+
+ {
+ TRACE_EVENT0("gpu", "glTexImage2D");
+ glTexImage2D(
+ tex_params.target,
+ tex_params.level,
+ tex_params.internal_format,
+ tex_params.width,
+ tex_params.height,
+ tex_params.border,
+ tex_params.format,
+ tex_params.type,
+ data);
+ }
+
+ // The texture is already fully bound so just call it now.
+ bind_callback.Run();
+}
+
+void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D(
+ AsyncTexSubImage2DParams tex_params,
+ AsyncMemoryParams mem_params,
+ ScopedSafeSharedMemory* safe_shared_memory,
+ GLuint texture_id) {
+ TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D",
+ "width", tex_params.width,
+ "height", tex_params.height);
+
+ void* data = GetAddress(safe_shared_memory->shared_memory(),
+ mem_params.shm_data_offset);
+
+ base::TimeTicks begin_time(base::TimeTicks::HighResNow());
+ glBindTexture(tex_params.target, texture_id);
+
+ {
+ TRACE_EVENT0("gpu", "glTexSubImage2D");
+ glTexSubImage2D(
+ tex_params.target,
+ tex_params.level,
+ tex_params.xoffset,
+ tex_params.yoffset,
+ tex_params.width,
+ tex_params.height,
+ tex_params.format,
+ tex_params.type,
+ data);
+ }
+
+ texture_upload_count_++;
+ total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time;
+}
+
+} // namespace gfx
« no previous file with comments | « ui/gl/async_pixel_transfer_delegate_idle.h ('k') | ui/gl/async_pixel_transfer_delegate_stub.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698