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

Unified Diff: ui/gl/async_pixel_transfer_delegate_stub.cc

Issue 12040049: gpu: Implement idle async pixel transfers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase and prevent starvation 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
Index: ui/gl/async_pixel_transfer_delegate_stub.cc
diff --git a/ui/gl/async_pixel_transfer_delegate_stub.cc b/ui/gl/async_pixel_transfer_delegate_stub.cc
index 093cb116b28e3a3247861c0be2d3b9e27e1c83e3..8294460667465efadcbe1a0bc81b1af320d33e20 100644
--- a/ui/gl/async_pixel_transfer_delegate_stub.cc
+++ b/ui/gl/async_pixel_transfer_delegate_stub.cc
@@ -4,29 +4,43 @@
#include "ui/gl/async_pixel_transfer_delegate_stub.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_size,
- uint32 shm_data_offset,
- uint32 shm_data_size) {
+void* GetAddress(SharedMemory* shared_memory, uint32 shm_data_offset) {
// Memory bounds have already been validated, so there
// is just DCHECKS here.
DCHECK(shared_memory);
DCHECK(shared_memory->memory());
- DCHECK_LE(shm_data_offset + shm_data_size, shm_size);
return static_cast<int8*>(shared_memory->memory()) + shm_data_offset;
}
-} // namespace
-namespace gfx {
+base::LazyInstance<SafeSharedMemoryPool> g_safe_shared_memory_pool =
+ LAZY_INSTANCE_INITIALIZER;
+
+SafeSharedMemoryPool* safe_shared_memory_pool() {
+ return g_safe_shared_memory_pool.Pointer();
+}
+
+} // namespace
#if !defined(OS_ANDROID)
scoped_ptr<AsyncPixelTransferDelegate>
@@ -42,26 +56,74 @@ scoped_ptr<AsyncPixelTransferDelegate>
new AsyncPixelTransferDelegateStub()));
}
-AsyncTransferStateStub::AsyncTransferStateStub(GLuint texture_id) {
- static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0};
- late_bind_define_params_ = zero_params;
- needs_late_bind_ = false;
-}
+// Class which holds async pixel transfers state.
+class TransferStateInternalStub
+ : public base::RefCounted<TransferStateInternalStub> {
+ public:
+ explicit TransferStateInternalStub(GLuint texture_id)
+ : texture_id_(texture_id),
+ needs_late_bind_(false),
+ transfer_in_progress_(false) {
+ static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0};
+ late_bind_define_params_ = zero_params;
+ }
-AsyncTransferStateStub::~AsyncTransferStateStub() {
-}
+ // Implement AsyncPixelTransferState:
+ bool TransferIsInProgress() {
+ return transfer_in_progress_;
+ }
-bool AsyncTransferStateStub::TransferIsInProgress() {
- return false;
-}
+ void BindTransfer(AsyncTexImage2DParams* bound_params) {
+ DCHECK(bound_params);
+ DCHECK(needs_late_bind_);
+ *bound_params = late_bind_define_params_;
+ needs_late_bind_ = false;
+ }
+
+ protected:
+ friend class base::RefCounted<TransferStateInternalStub>;
+ friend class AsyncPixelTransferDelegateStub;
+
+ virtual ~TransferStateInternalStub() {}
-void AsyncTransferStateStub::BindTransfer(AsyncTexImage2DParams* out_params) {
- DCHECK(out_params);
- DCHECK(needs_late_bind_);
- *out_params = late_bind_define_params_;
- needs_late_bind_ = false;
+ GLuint texture_id_;
+
+ // Indicates there is a new EGLImage and the 'real'
Sami 2013/03/07 16:57:19 No EGLImages here :)
reveman 2013/03/07 20:21:04 Done.
+ // texture needs to be bound to it as an EGLImage target.
+ bool needs_late_bind_;
+
+ // Definition params for texture that needs binding.
+ AsyncTexImage2DParams late_bind_define_params_;
+
+ // Indicates that an async transfer is in progress.
+ bool transfer_in_progress_;
+};
+
+// This just wraps an internal ref-counted state object.
+class AsyncTransferStateStub : public AsyncPixelTransferState {
+ public:
+ explicit AsyncTransferStateStub(GLuint texture_id)
+ : internal_(new TransferStateInternalStub(texture_id)) {
+ }
+ virtual ~AsyncTransferStateStub() {}
+ virtual bool TransferIsInProgress() {
+ return internal_->TransferIsInProgress();
Sami 2013/03/07 16:57:19 Nit: indent by 2.
reveman 2013/03/07 20:21:04 Done.
+ }
+ virtual void BindTransfer(AsyncTexImage2DParams* bound_params) {
+ internal_->BindTransfer(bound_params);
Sami 2013/03/07 16:57:19 Ditto.
reveman 2013/03/07 20:21:04 Done.
+ }
+ scoped_refptr<TransferStateInternalStub> internal_;
+};
+
+AsyncPixelTransferDelegateStub::Transfer::Transfer(
+ TransferStateInternalStub* state,
+ const base::Closure& task)
+ : state(state),
+ task(task) {
}
+AsyncPixelTransferDelegateStub::Transfer::~Transfer() {}
+
AsyncPixelTransferDelegateStub::AsyncPixelTransferDelegateStub()
: texture_upload_count_(0) {
}
@@ -79,69 +141,102 @@ AsyncPixelTransferState*
void AsyncPixelTransferDelegateStub::AsyncNotifyCompletion(
const AsyncMemoryParams& mem_params,
const CompletionCallback& callback) {
- callback.Run(mem_params);
+ if (transfers_.empty()) {
+ callback.Run(mem_params);
+ return;
+ }
+
+ transfers_.back().notifications.push(
+ base::Bind(
+ &AsyncPixelTransferDelegateStub::PerformNotifyCompletion,
+ AsWeakPtr(),
+ mem_params,
+ base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
+ mem_params.shared_memory,
+ mem_params.shm_size)),
+ callback));
}
void AsyncPixelTransferDelegateStub::AsyncTexImage2D(
AsyncPixelTransferState* transfer_state,
const AsyncTexImage2DParams& tex_params,
const AsyncMemoryParams& mem_params) {
- // Save the define params to return later during deferred
- // binding of the transfer texture.
- DCHECK(transfer_state);
- AsyncTransferStateStub* state =
- static_cast<AsyncTransferStateStub*>(transfer_state);
- // We don't actually need a late bind since this stub does
- // everything synchronously, but this tries to be similar
- // as an async implementation.
+ scoped_refptr<TransferStateInternalStub> state =
+ static_cast<AsyncTransferStateStub*>(transfer_state)->internal_.get();
+ DCHECK(mem_params.shared_memory);
+ DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
+ mem_params.shm_size);
+ DCHECK(state);
+ DCHECK(state->texture_id_);
+ DCHECK(!state->needs_late_bind_);
+
+ // Mark the transfer in progress and save define params for lazy binding.
state->needs_late_bind_ = true;
state->late_bind_define_params_ = tex_params;
- void* data = GetAddress(mem_params.shared_memory,
- mem_params.shm_size,
- mem_params.shm_data_offset,
- mem_params.shm_data_size);
- 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);
+
+ transfers_.push_back(
+ Transfer(
+ state.get(),
+ base::Bind(
+ &AsyncPixelTransferDelegateStub::PerformAsyncTexImage2D,
+ AsWeakPtr(),
+ state,
+ tex_params,
+ mem_params,
+ base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
+ mem_params.shared_memory,
+ mem_params.shm_size)))));
+
+ state->transfer_in_progress_ = true;
}
void AsyncPixelTransferDelegateStub::AsyncTexSubImage2D(
AsyncPixelTransferState* transfer_state,
const AsyncTexSubImage2DParams& tex_params,
const AsyncMemoryParams& mem_params) {
- void* data = GetAddress(mem_params.shared_memory,
- mem_params.shm_size,
- mem_params.shm_data_offset,
- mem_params.shm_data_size);
- DCHECK(transfer_state);
- AsyncTransferStateStub* state =
- static_cast<AsyncTransferStateStub*>(transfer_state);
+ scoped_refptr<TransferStateInternalStub> state =
+ static_cast<AsyncTransferStateStub*>(transfer_state)->internal_.get();
+ DCHECK(mem_params.shared_memory);
+ DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
+ mem_params.shm_size);
+ DCHECK(state);
+ DCHECK(state->texture_id_);
DCHECK(!state->needs_late_bind_);
- base::TimeTicks begin_time(base::TimeTicks::HighResNow());
- 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;
+
+ transfers_.push_back(
+ Transfer(
+ state.get(),
+ base::Bind(
+ &AsyncPixelTransferDelegateStub::PerformAsyncTexSubImage2D,
+ AsWeakPtr(),
+ state,
+ tex_params,
+ mem_params,
+ base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
+ mem_params.shared_memory,
+ mem_params.shm_size)))));
+
+ state->transfer_in_progress_ = true;
}
void AsyncPixelTransferDelegateStub::WaitForTransferCompletion(
- AsyncPixelTransferState* state) {
- // Already done.
+ AsyncPixelTransferState* transfer_state) {
+ scoped_refptr<TransferStateInternalStub> state =
+ static_cast<AsyncTransferStateStub*>(transfer_state)->internal_.get();
+
+ for (std::list<Transfer>::iterator iter = transfers_.begin();
+ iter != transfers_.end(); ++iter) {
+ if (iter->state.get() != state)
+ continue;
+
+ iter->task.Run();
Sami 2013/03/07 16:57:19 Neat! Is it worth wrapping this bit into PerformT
reveman 2013/03/07 20:21:04 Done. Added ProcessTransfer.
+ while (!iter->notifications.empty()) {
+ iter->notifications.front().Run();
+ iter->notifications.pop();
+ }
+ transfers_.erase(iter);
+ break;
+ }
}
uint32 AsyncPixelTransferDelegateStub::GetTextureUploadCount() {
@@ -152,5 +247,101 @@ base::TimeDelta AsyncPixelTransferDelegateStub::GetTotalTextureUploadTime() {
return total_texture_upload_time_;
}
+void AsyncPixelTransferDelegateStub::ProcessPendingTransfers() {
+ if (transfers_.empty())
+ return;
+
+ transfers_.front().task.Run();
+ while (!transfers_.front().notifications.empty()) {
+ transfers_.front().notifications.front().Run();
+ transfers_.front().notifications.pop();
+ }
+ transfers_.pop_front();
+}
+
+bool AsyncPixelTransferDelegateStub::HasPendingTransfers() {
+ return !transfers_.empty();
+}
+
+void AsyncPixelTransferDelegateStub::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 AsyncPixelTransferDelegateStub::PerformAsyncTexImage2D(
+ scoped_refptr<TransferStateInternalStub> state,
+ AsyncTexImage2DParams tex_params,
+ AsyncMemoryParams mem_params,
+ ScopedSafeSharedMemory* safe_shared_memory) {
+ TRACE_EVENT2("gpu", "PerformAsyncTexImage2D",
+ "width", tex_params.width,
+ "height", tex_params.height);
+ DCHECK_EQ(0, tex_params.level);
+
+ void* data = GetAddress(safe_shared_memory->shared_memory(),
+ mem_params.shm_data_offset);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, state->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);
+ }
+
+ state->transfer_in_progress_ = false;
+}
+
+void AsyncPixelTransferDelegateStub::PerformAsyncTexSubImage2D(
+ scoped_refptr<TransferStateInternalStub> state,
+ AsyncTexSubImage2DParams tex_params,
+ AsyncMemoryParams mem_params,
+ ScopedSafeSharedMemory* safe_shared_memory) {
+ TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D",
+ "width", tex_params.width,
+ "height", tex_params.height);
+ DCHECK_EQ(0, tex_params.level);
+
+ void* data = GetAddress(safe_shared_memory->shared_memory(),
+ mem_params.shm_data_offset);
+
+ base::TimeTicks begin_time(base::TimeTicks::HighResNow());
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, state->texture_id_);
+
+ {
+ 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);
+ }
+
+ texture_upload_count_++;
+ total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time;
+
+ state->transfer_in_progress_ = false;
+}
+
} // namespace gfx
« ui/gl/async_pixel_transfer_delegate_stub.h ('K') | « ui/gl/async_pixel_transfer_delegate_stub.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698