summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-31 01:58:47 +0000
committerbacker@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-31 01:58:47 +0000
commit85a4ac2bf72b313cfe248b2c1a56cfc34ead0511 (patch)
tree40ead6a3efc34e8833e126a8fd321200369f7f91 /gpu
parentcae0fbf4b29460ae2c3c5320ec5354fa0a49322e (diff)
downloadchromium_src-85a4ac2bf72b313cfe248b2c1a56cfc34ead0511.zip
chromium_src-85a4ac2bf72b313cfe248b2c1a56cfc34ead0511.tar.gz
chromium_src-85a4ac2bf72b313cfe248b2c1a56cfc34ead0511.tar.bz2
GPU: Make AsyncPixelTransferState per context rather than per context group.
Introduces a per context AsyncPixelTransferManager that owns the AsyncPixelTransferStates. In order to scope these to the lifetime of a Texture, a gles::gpu::TextureManager::DestructionObserver interface was added. BUG=240504 Review URL: https://chromiumcodereview.appspot.com/16126004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203305 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_delegate.h11
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_delegate_egl.cc4
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_delegate_idle.cc3
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_delegate_mock.cc1
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h3
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc12
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_delegate_stub.cc4
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_delegate_sync.cc4
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_manager.cc72
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_manager.h83
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc87
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.h6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_mock.h5
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc102
-rw-r--r--gpu/command_buffer/service/texture_manager.cc21
-rw-r--r--gpu/command_buffer/service/texture_manager.h50
-rw-r--r--gpu/command_buffer_service.gypi2
17 files changed, 370 insertions, 100 deletions
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate.h b/gpu/command_buffer/service/async_pixel_transfer_delegate.h
index b21a63b..f90e2af 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate.h
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate.h
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/callback.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
@@ -74,18 +75,20 @@ class AsyncPixelTransferUploadStats
// AsyncPixelTransferState holds the resources required to do async
// transfers on one texture. It should stay alive for the lifetime
// of the texture to allow multiple transfers.
-class GPU_EXPORT AsyncPixelTransferState :
- public base::SupportsWeakPtr<AsyncPixelTransferState> {
+class GPU_EXPORT AsyncPixelTransferState
+ : public base::RefCounted<AsyncPixelTransferState>,
+ public base::SupportsWeakPtr<AsyncPixelTransferState> {
public:
- virtual ~AsyncPixelTransferState();
-
// Returns true if there is a transfer in progress.
virtual bool TransferIsInProgress() = 0;
protected:
AsyncPixelTransferState();
+ virtual ~AsyncPixelTransferState();
private:
+ friend class base::RefCounted<AsyncPixelTransferState>;
+
DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferState);
};
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.cc
index c56f72a..246acb4 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_egl.cc
@@ -393,7 +393,6 @@ class AsyncTransferStateImpl : public AsyncPixelTransferState {
wait_for_creation,
use_image_preserved)) {
}
- virtual ~AsyncTransferStateImpl() {}
virtual bool TransferIsInProgress() OVERRIDE {
return internal_->TransferIsInProgress();
@@ -404,6 +403,9 @@ class AsyncTransferStateImpl : public AsyncPixelTransferState {
}
scoped_refptr<TransferStateInternal> internal_;
+
+ private:
+ virtual ~AsyncTransferStateImpl() {}
};
} // namespace
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_idle.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_idle.cc
index f4a3e48..d8bf916 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_idle.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_idle.cc
@@ -32,7 +32,6 @@ class AsyncPixelTransferStateImpl : public AsyncPixelTransferState {
texture_id_(texture_id),
transfer_in_progress_(false) {
}
- virtual ~AsyncPixelTransferStateImpl() {}
// Implement AsyncPixelTransferState:
virtual bool TransferIsInProgress() OVERRIDE {
@@ -53,6 +52,8 @@ class AsyncPixelTransferStateImpl : public AsyncPixelTransferState {
}
private:
+ virtual ~AsyncPixelTransferStateImpl() {}
+
uint64 id_;
GLuint texture_id_;
bool transfer_in_progress_;
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.cc
index 2affd24..17d2b65 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.cc
@@ -10,6 +10,7 @@ MockAsyncPixelTransferState::MockAsyncPixelTransferState() {
}
MockAsyncPixelTransferState::~MockAsyncPixelTransferState() {
+ Destroy();
}
MockAsyncPixelTransferDelegate::MockAsyncPixelTransferDelegate() {
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h b/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h
index 146eaa4..f16934c 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h
@@ -15,6 +15,9 @@ class MockAsyncPixelTransferState : public AsyncPixelTransferState {
public:
MockAsyncPixelTransferState();
+ // Called in ~MockAsyncPixelTransferState.
+ MOCK_METHOD0(Destroy, void());
+
// Implement AsyncPixelTransferState.
MOCK_METHOD0(TransferIsInProgress, bool());
MOCK_METHOD1(BindTransfer, void(AsyncTexImage2DParams* level_params));
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc
index a71bd66..7a9c1a9 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_share_group.cc
@@ -305,12 +305,6 @@ class AsyncTransferStateImpl : public AsyncPixelTransferState {
const AsyncTexImage2DParams& define_params)
: internal_(new TransferStateInternal(texture_id, define_params)) {}
- virtual ~AsyncTransferStateImpl() {
- TRACE_EVENT0("gpu", " ~AsyncTransferStateImpl");
- base::AutoLock locked(*internal_->upload_lock());
- internal_->cancel_upload_flag()->Set();
- }
-
virtual bool TransferIsInProgress() OVERRIDE {
return internal_->TransferIsInProgress();
}
@@ -318,6 +312,12 @@ class AsyncTransferStateImpl : public AsyncPixelTransferState {
TransferStateInternal* internal() { return internal_.get(); }
private:
+ virtual ~AsyncTransferStateImpl() {
+ TRACE_EVENT0("gpu", " ~AsyncTransferStateImpl");
+ base::AutoLock locked(*internal_->upload_lock());
+ internal_->cancel_upload_flag()->Set();
+ }
+
scoped_refptr<TransferStateInternal> internal_;
};
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_stub.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_stub.cc
index 474e245..5bd7db9 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_stub.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_stub.cc
@@ -11,12 +11,14 @@ namespace {
class AsyncPixelTransferStateImpl : public AsyncPixelTransferState {
public:
AsyncPixelTransferStateImpl() {}
- virtual ~AsyncPixelTransferStateImpl() {}
// Implement AsyncPixelTransferState:
virtual bool TransferIsInProgress() OVERRIDE {
return false;
}
+
+ private:
+ virtual ~AsyncPixelTransferStateImpl() {}
};
} // namespace
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate_sync.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate_sync.cc
index dd132a6..6eb58f2 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate_sync.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate_sync.cc
@@ -11,12 +11,14 @@ namespace {
class AsyncPixelTransferStateImpl : public AsyncPixelTransferState {
public:
AsyncPixelTransferStateImpl() {}
- virtual ~AsyncPixelTransferStateImpl() {}
// Implement AsyncPixelTransferState:
virtual bool TransferIsInProgress() OVERRIDE {
return false;
}
+
+ private:
+ virtual ~AsyncPixelTransferStateImpl() {}
};
} // namespace
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager.cc b/gpu/command_buffer/service/async_pixel_transfer_manager.cc
new file mode 100644
index 0000000..92ecfd6
--- /dev/null
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager.cc
@@ -0,0 +1,72 @@
+// 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.h"
+
+#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
+
+namespace gpu {
+
+AsyncPixelTransferManager::AsyncPixelTransferManager(
+ gles2::TextureManager* manager,
+ gfx::GLContext* context)
+ : manager_(manager),
+ delegate_(AsyncPixelTransferDelegate::Create(context)) {
+ manager_->AddObserver(this);
+}
+
+AsyncPixelTransferManager::~AsyncPixelTransferManager() {
+ if (manager_)
+ manager_->RemoveObserver(this);
+}
+
+AsyncPixelTransferState* AsyncPixelTransferManager::CreatePixelTransferState(
+ gles2::TextureRef* ref,
+ const AsyncTexImage2DParams& define_params) {
+ DCHECK(!GetPixelTransferState(ref));
+ AsyncPixelTransferState* state = delegate_->CreatePixelTransferState(
+ ref->texture()->service_id(), define_params);
+ state_map_[ref] = state;
+ return state;
+}
+
+AsyncPixelTransferState*
+AsyncPixelTransferManager::GetPixelTransferState(
+ gles2::TextureRef* ref) {
+ TextureToStateMap::iterator it = state_map_.find(ref);
+ if (it == state_map_.end()) {
+ return NULL;
+ } else {
+ return it->second;
+ }
+}
+
+void AsyncPixelTransferManager::ClearPixelTransferStateForTest(
+ gles2::TextureRef* ref) {
+ TextureToStateMap::iterator it = state_map_.find(ref);
+ if (it != state_map_.end())
+ state_map_.erase(it);
+}
+
+bool AsyncPixelTransferManager::AsyncTransferIsInProgress(
+ gles2::TextureRef* ref) {
+ AsyncPixelTransferState* state = GetPixelTransferState(ref);
+ return state && state->TransferIsInProgress();
+}
+
+void AsyncPixelTransferManager::OnTextureManagerDestroying(
+ gles2::TextureManager* manager) {
+ // TextureManager should outlive AsyncPixelTransferManager.
+ NOTREACHED();
+ manager_ = NULL;
+}
+
+void AsyncPixelTransferManager::OnTextureRefDestroying(
+ gles2::TextureRef* texture) {
+ TextureToStateMap::iterator it = state_map_.find(texture);
+ if (it != state_map_.end())
+ state_map_.erase(it);
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager.h b/gpu/command_buffer/service/async_pixel_transfer_manager.h
new file mode 100644
index 0000000..2f61099
--- /dev/null
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager.h
@@ -0,0 +1,83 @@
+// 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.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_ASYNC_PIXEL_TRANSFER_MANAGER_H_
+#define GPU_COMMAND_BUFFER_SERVICE_ASYNC_PIXEL_TRANSFER_MANAGER_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/hash_tables.h"
+#include "base/memory/ref_counted.h"
+#include "gpu/command_buffer/service/texture_manager.h"
+#include "gpu/gpu_export.h"
+
+#if defined(COMPILER_GCC)
+namespace BASE_HASH_NAMESPACE {
+template <>
+ struct hash<gpu::gles2::TextureRef*> {
+ size_t operator()(gpu::gles2::TextureRef* ptr) const {
+ return hash<size_t>()(reinterpret_cast<size_t>(ptr));
+ }
+};
+} // namespace BASE_HASH_NAMESPACE
+#endif // COMPILER
+
+namespace gfx {
+class GLContext;
+}
+
+namespace gpu {
+class AsyncPixelTransferDelegate;
+class AsyncPixelTransferState;
+struct AsyncTexImage2DParams;
+
+class GPU_EXPORT AsyncPixelTransferManager
+ : public gles2::TextureManager::DestructionObserver {
+ public:
+ AsyncPixelTransferManager(gles2::TextureManager* texture_manager_,
+ gfx::GLContext* context);
+ virtual ~AsyncPixelTransferManager();
+
+ AsyncPixelTransferDelegate* GetAsyncPixelTransferDelegate() {
+ return delegate_.get();
+ }
+
+ void SetAsyncPixelTransferDelegateForTest(
+ AsyncPixelTransferDelegate* delegate) {
+ delegate_ = make_scoped_ptr(delegate);
+ }
+
+ AsyncPixelTransferState* CreatePixelTransferState(
+ gles2::TextureRef* ref,
+ const AsyncTexImage2DParams& define_params);
+
+ AsyncPixelTransferState* GetPixelTransferState(
+ gles2::TextureRef* ref);
+
+ void ClearPixelTransferStateForTest(gles2::TextureRef* ref);
+
+ bool AsyncTransferIsInProgress(gles2::TextureRef* ref);
+
+ // gles2::TextureRef::DestructionObserver implementation:
+ virtual void OnTextureManagerDestroying(gles2::TextureManager* manager)
+ OVERRIDE;
+ virtual void OnTextureRefDestroying(gles2::TextureRef* texture) OVERRIDE;
+
+ private:
+ gles2::TextureManager* manager_;
+
+ scoped_ptr<AsyncPixelTransferDelegate> delegate_;
+
+ typedef base::hash_map<gles2::TextureRef*,
+ scoped_refptr<AsyncPixelTransferState> >
+ TextureToStateMap;
+ TextureToStateMap state_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferManager);
+};
+
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_ASYNC_PIXEL_TRANSFER_MANAGER_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 28d3b57..6bfcc18 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -56,6 +56,7 @@
#include "gpu/command_buffer/service/vertex_attrib_manager.h"
#include "gpu/command_buffer/service/vertex_array_manager.h"
#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
+#include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_implementation.h"
@@ -574,8 +575,11 @@ class GLES2DecoderImpl : public GLES2Decoder {
virtual AsyncPixelTransferDelegate*
GetAsyncPixelTransferDelegate() OVERRIDE;
- virtual void SetAsyncPixelTransferDelegate(
+ virtual void SetAsyncPixelTransferDelegateForTest(
AsyncPixelTransferDelegate* delegate) OVERRIDE;
+ virtual AsyncPixelTransferManager*
+ GetAsyncPixelTransferManager() OVERRIDE;
+ virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
void ProcessFinishedAsyncTransfers();
virtual bool GetServiceTextureId(uint32 client_texture_id,
@@ -820,7 +824,7 @@ class GLES2DecoderImpl : public GLES2Decoder {
// Extra validation for async tex(Sub)Image2D.
bool ValidateAsyncTransfer(
const char* function_name,
- Texture* texture,
+ TextureRef* texture_ref,
GLenum target,
GLint level,
const void * data);
@@ -1632,7 +1636,7 @@ class GLES2DecoderImpl : public GLES2Decoder {
ShaderCacheCallback shader_cache_callback_;
StreamTextureManager* stream_texture_manager_;
- scoped_ptr<AsyncPixelTransferDelegate> async_pixel_transfer_delegate_;
+ scoped_ptr<AsyncPixelTransferManager> async_pixel_transfer_manager_;
// The format of the back buffer_
GLenum back_buffer_color_format_;
@@ -2471,9 +2475,8 @@ bool GLES2DecoderImpl::Initialize(
if (!offscreen)
context_->SetSafeToForceGpuSwitch();
- // Create a delegate to perform async pixel transfers.
- async_pixel_transfer_delegate_.reset(
- AsyncPixelTransferDelegate::Create(context.get()));
+ async_pixel_transfer_manager_.reset(
+ new AsyncPixelTransferManager(texture_manager(), context.get()));
return true;
}
@@ -2789,7 +2792,7 @@ void GLES2DecoderImpl::ProcessFinishedAsyncTransfers() {
// from the client, as the client may have recieved an async
// completion while issuing those commands.
// "DidFlushStart" would be ideal if we had such a callback.
- async_pixel_transfer_delegate_->BindCompletedAsyncTransfers();
+ GetAsyncPixelTransferDelegate()->BindCompletedAsyncTransfers();
}
void GLES2DecoderImpl::ReleaseCurrent() {
@@ -3053,12 +3056,21 @@ void GLES2DecoderImpl::SetStreamTextureManager(StreamTextureManager* manager) {
AsyncPixelTransferDelegate*
GLES2DecoderImpl::GetAsyncPixelTransferDelegate() {
- return async_pixel_transfer_delegate_.get();
+ return async_pixel_transfer_manager_->GetAsyncPixelTransferDelegate();
}
-void GLES2DecoderImpl::SetAsyncPixelTransferDelegate(
+void GLES2DecoderImpl::SetAsyncPixelTransferDelegateForTest(
AsyncPixelTransferDelegate* delegate) {
- async_pixel_transfer_delegate_ = make_scoped_ptr(delegate);
+ async_pixel_transfer_manager_->SetAsyncPixelTransferDelegateForTest(delegate);
+}
+
+AsyncPixelTransferManager*
+ GLES2DecoderImpl::GetAsyncPixelTransferManager() {
+ return async_pixel_transfer_manager_.get();
+}
+
+void GLES2DecoderImpl::ResetAsyncPixelTransferManagerForTest() {
+ async_pixel_transfer_manager_.reset();
}
bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
@@ -3073,12 +3085,12 @@ bool GLES2DecoderImpl::GetServiceTextureId(uint32 client_texture_id,
uint32 GLES2DecoderImpl::GetTextureUploadCount() {
return texture_upload_count_ +
- async_pixel_transfer_delegate_->GetTextureUploadCount();
+ GetAsyncPixelTransferDelegate()->GetTextureUploadCount();
}
base::TimeDelta GLES2DecoderImpl::GetTotalTextureUploadTime() {
return total_texture_upload_time_ +
- async_pixel_transfer_delegate_->GetTotalTextureUploadTime();
+ GetAsyncPixelTransferDelegate()->GetTotalTextureUploadTime();
}
base::TimeDelta GLES2DecoderImpl::GetTotalProcessingCommandsTime() {
@@ -3190,6 +3202,10 @@ void GLES2DecoderImpl::Destroy(bool have_context) {
offscreen_resolved_frame_buffer_.reset();
offscreen_resolved_color_texture_.reset();
+ // Should destroy the transfer manager before the texture manager held
+ // by the context group.
+ async_pixel_transfer_manager_.reset();
+
if (group_) {
group_->Destroy(this, have_context);
group_ = NULL;
@@ -8095,7 +8111,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D(
GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
return;
}
- if (texture->AsyncTransferIsInProgress()) {
+ if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glCopyTexSubImage2D", "async upload pending for texture");
@@ -8231,7 +8247,7 @@ bool GLES2DecoderImpl::ValidateTexSubImage2D(
function_name, "type does not match type of texture.");
return false;
}
- if (texture->AsyncTransferIsInProgress()) {
+ if (async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
function_name, "async upload pending for texture");
@@ -9096,13 +9112,13 @@ bool GLES2DecoderImpl::ProcessPendingQueries() {
}
bool GLES2DecoderImpl::HasMoreIdleWork() {
- return async_pixel_transfer_delegate_->NeedsProcessMorePendingTransfers();
+ return GetAsyncPixelTransferDelegate()->NeedsProcessMorePendingTransfers();
}
void GLES2DecoderImpl::PerformIdleWork() {
- if (!async_pixel_transfer_delegate_->NeedsProcessMorePendingTransfers())
+ if (!GetAsyncPixelTransferDelegate()->NeedsProcessMorePendingTransfers())
return;
- async_pixel_transfer_delegate_->ProcessMorePendingTransfers();
+ GetAsyncPixelTransferDelegate()->ProcessMorePendingTransfers();
ProcessFinishedAsyncTransfers();
}
@@ -10099,7 +10115,7 @@ void GLES2DecoderImpl::DoDrawBuffersEXT(
bool GLES2DecoderImpl::ValidateAsyncTransfer(
const char* function_name,
- Texture* texture,
+ TextureRef* texture_ref,
GLenum target,
GLint level,
const void * data) {
@@ -10119,7 +10135,8 @@ bool GLES2DecoderImpl::ValidateAsyncTransfer(
return false;
}
// We only support one async transfer in progress.
- if (!texture || texture->AsyncTransferIsInProgress()) {
+ if (!texture_ref ||
+ async_pixel_transfer_manager_->AsyncTransferIsInProgress(texture_ref)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
function_name, "transfer already in progress");
@@ -10170,7 +10187,7 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
TextureRef* texture_ref = GetTextureInfoForTarget(target);
Texture* texture = texture_ref->texture();
if (!ValidateAsyncTransfer(
- "glAsyncTexImage2DCHROMIUM", texture, target, level, pixels))
+ "glAsyncTexImage2DCHROMIUM", texture_ref, target, level, pixels))
return error::kNoError;
// Don't allow async redefinition of a textures.
@@ -10205,16 +10222,13 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
// Set up the async state if needed, and make the texture
// immutable so the async state stays valid. The level info
// is set up lazily when the transfer completes.
- DCHECK(!texture->GetAsyncTransferState());
- texture_ref->SetAsyncTransferState(
- make_scoped_ptr(
- async_pixel_transfer_delegate_->CreatePixelTransferState(
- texture->service_id(),
- tex_params)));
+ AsyncPixelTransferState* state =
+ async_pixel_transfer_manager_->CreatePixelTransferState(texture_ref,
+ tex_params);
texture->SetImmutable(true);
- async_pixel_transfer_delegate_->AsyncTexImage2D(
- texture->GetAsyncTransferState(),
+ GetAsyncPixelTransferDelegate()->AsyncTexImage2D(
+ state,
tex_params,
mem_params,
base::Bind(&TextureManager::SetLevelInfoFromParams,
@@ -10261,7 +10275,7 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
TextureRef* texture_ref = GetTextureInfoForTarget(target);
Texture* texture = texture_ref->texture();
if (!ValidateAsyncTransfer(
- "glAsyncTexSubImage2DCHROMIUM", texture, target, level, pixels))
+ "glAsyncTexSubImage2DCHROMIUM", texture_ref, target, level, pixels))
return error::kNoError;
// Guarantee async textures are always 'cleared' as follows:
@@ -10293,7 +10307,8 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
width, height, format, type};
AsyncMemoryParams mem_params = {shared_memory, shm_size,
shm_data_offset, shm_data_size};
- AsyncPixelTransferState* state = texture->GetAsyncTransferState();
+ AsyncPixelTransferState* state =
+ async_pixel_transfer_manager_->GetPixelTransferState(texture_ref);
if (!state) {
// TODO(epenner): We may want to enforce exclusive use
// of async APIs in which case this should become an error,
@@ -10306,14 +10321,12 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM(
&define_params.internal_format);
// Set up the async state if needed, and make the texture
// immutable so the async state stays valid.
- state = async_pixel_transfer_delegate_->CreatePixelTransferState(
- texture->service_id(),
- define_params);
- texture_ref->SetAsyncTransferState(make_scoped_ptr(state));
+ state = async_pixel_transfer_manager_->CreatePixelTransferState(
+ texture_ref, define_params);
texture->SetImmutable(true);
}
- async_pixel_transfer_delegate_->AsyncTexSubImage2D(
+ GetAsyncPixelTransferDelegate()->AsyncTexSubImage2D(
state, tex_params, mem_params);
return error::kNoError;
}
@@ -10336,14 +10349,14 @@ error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM(
return error::kNoError;
}
AsyncPixelTransferState* state =
- texture_ref->texture()->GetAsyncTransferState();
+ async_pixel_transfer_manager_->GetPixelTransferState(texture_ref);
if (!state) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
"glWaitAsyncTexImage2DCHROMIUM", "No async transfer started");
return error::kNoError;
}
- async_pixel_transfer_delegate_->WaitForTransferCompletion(state);
+ GetAsyncPixelTransferDelegate()->WaitForTransferCompletion(state);
ProcessFinishedAsyncTransfers();
return error::kNoError;
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 86d4801..65ebe76 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -26,6 +26,7 @@ class GLSurface;
namespace gpu {
class AsyncPixelTransferDelegate;
+class AsyncPixelTransferManager;
class StreamTextureManager;
namespace gles2 {
@@ -179,9 +180,12 @@ class GPU_EXPORT GLES2Decoder : public base::SupportsWeakPtr<GLES2Decoder>,
// Interface to performing async pixel transfers.
virtual AsyncPixelTransferDelegate* GetAsyncPixelTransferDelegate() = 0;
- virtual void SetAsyncPixelTransferDelegate(
+ virtual void SetAsyncPixelTransferDelegateForTest(
AsyncPixelTransferDelegate* delegate) = 0;
+ virtual AsyncPixelTransferManager* GetAsyncPixelTransferManager() = 0;
+ virtual void ResetAsyncPixelTransferManagerForTest() = 0;
+
// Get the service texture ID corresponding to a client texture ID.
// If no such record is found then return false.
virtual bool GetServiceTextureId(uint32 client_texture_id,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 3f714bd..ded5e4b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -73,8 +73,11 @@ class MockGLES2Decoder : public GLES2Decoder {
MOCK_METHOD1(SetStreamTextureManager, void(StreamTextureManager*));
MOCK_METHOD0(GetAsyncPixelTransferDelegate,
AsyncPixelTransferDelegate*());
- MOCK_METHOD1(SetAsyncPixelTransferDelegate,
+ MOCK_METHOD1(SetAsyncPixelTransferDelegateForTest,
void(AsyncPixelTransferDelegate*));
+ MOCK_METHOD0(GetAsyncPixelTransferManager,
+ AsyncPixelTransferManager*());
+ MOCK_METHOD0(ResetAsyncPixelTransferManagerForTest, void());
MOCK_METHOD3(DoCommand, error::Error(unsigned int command,
unsigned int arg_count,
const void* cmd_data));
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index c2413d1..b4baf8b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -9,6 +9,7 @@
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/common/id_allocator.h"
#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h"
+#include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gl_surface_mock.h"
@@ -8082,7 +8083,7 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
// Set a mock Async delegate
StrictMock<gpu::MockAsyncPixelTransferDelegate>* delegate =
new StrictMock<gpu::MockAsyncPixelTransferDelegate>;
- decoder_->SetAsyncPixelTransferDelegate(delegate);
+ decoder_->SetAsyncPixelTransferDelegateForTest(delegate);
StrictMock<gpu::MockAsyncPixelTransferState>* state = NULL;
// Tex(Sub)Image2D upload commands.
@@ -8096,7 +8097,8 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
wait_cmd.Init(GL_TEXTURE_2D);
// No transfer state exists initially.
- EXPECT_FALSE(texture->GetAsyncTransferState());
+ EXPECT_FALSE(decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
base::Closure bind_callback;
@@ -8113,7 +8115,8 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
// Command succeeds.
EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- EXPECT_TRUE(texture->GetAsyncTransferState());
+ EXPECT_TRUE(decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
EXPECT_TRUE(texture->IsImmutable());
// The texture is safe but the level has not been defined yet.
EXPECT_TRUE(texture->SafeToRenderFrom());
@@ -8125,7 +8128,8 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
// Command fails.
EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
- EXPECT_TRUE(texture->GetAsyncTransferState());
+ EXPECT_TRUE(decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
EXPECT_TRUE(texture->IsImmutable());
EXPECT_TRUE(texture->SafeToRenderFrom());
}
@@ -8149,7 +8153,8 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
}
// AsyncTexSubImage2D
- texture_ref->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
+ decoder_->GetAsyncPixelTransferManager()
+ ->ClearPixelTransferStateForTest(texture_ref);
texture->SetImmutable(false);
{
// Create transfer state since it doesn't exist.
@@ -8162,7 +8167,8 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
// Command succeeds.
EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- EXPECT_TRUE(texture->GetAsyncTransferState());
+ EXPECT_TRUE(decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
EXPECT_TRUE(texture->IsImmutable());
EXPECT_TRUE(texture->SafeToRenderFrom());
}
@@ -8177,7 +8183,8 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
// Command succeeds.
EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- EXPECT_TRUE(texture->GetAsyncTransferState());
+ EXPECT_TRUE(decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
EXPECT_TRUE(texture->IsImmutable());
EXPECT_TRUE(texture->SafeToRenderFrom());
}
@@ -8189,23 +8196,33 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
// No async call, command fails.
EXPECT_EQ(error::kNoError, ExecuteCmd(texsubimage_cmd));
EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
- EXPECT_TRUE(texture->GetAsyncTransferState());
+ EXPECT_TRUE(decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
EXPECT_TRUE(texture->IsImmutable());
EXPECT_TRUE(texture->SafeToRenderFrom());
}
+ // Delete state on DeleteTexture.
+ {
+ EXPECT_CALL(*state, Destroy()).RetiresOnSaturation();
+ DoDeleteTexture(client_texture_id_, kServiceTextureId);
+ EXPECT_FALSE(
+ decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
+ state = NULL;
+ }
+
// WaitAsyncTexImage2D
{
// Get a fresh texture since the existing texture cannot be respecified
// asynchronously and AsyncTexSubImage2D does not involved binding.
EXPECT_CALL(*gl_, GenTextures(1, _))
.WillOnce(SetArgumentPointee<1>(kServiceTextureId));
- texture_ref->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
- DoDeleteTexture(client_texture_id_, kServiceTextureId);
DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
texture_ref = GetTexture(client_texture_id_);
texture = texture_ref->texture();
- texture_ref->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
+ decoder_->GetAsyncPixelTransferManager()
+ ->ClearPixelTransferStateForTest(texture_ref);
texture->SetImmutable(false);
// Create transfer state since it doesn't exist.
EXPECT_CALL(*delegate, CreatePixelTransferState(kServiceTextureId, _))
@@ -8217,7 +8234,9 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
// Start async transfer.
EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd));
EXPECT_EQ(GL_NO_ERROR, GetGLError());
- EXPECT_TRUE(texture->GetAsyncTransferState());
+ EXPECT_TRUE(decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
+
EXPECT_TRUE(texture->IsImmutable());
// Wait for completion.
EXPECT_CALL(*delegate, WaitForTransferCompletion(state));
@@ -8226,8 +8245,63 @@ TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransfers) {
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
- decoder_->SetAsyncPixelTransferDelegate(NULL);
- texture_ref->SetAsyncTransferState(scoped_ptr<AsyncPixelTransferState>());
+ decoder_->SetAsyncPixelTransferDelegateForTest(NULL);
+ decoder_->GetAsyncPixelTransferManager()
+ ->ClearPixelTransferStateForTest(texture_ref);
+}
+
+TEST_F(GLES2DecoderManualInitTest, AsyncPixelTransferManager) {
+ InitDecoder(
+ "GL_CHROMIUM_async_pixel_transfers", // extensions
+ false, false, false, // has alpha/depth/stencil
+ false, false, false, // request alpha/depth/stencil
+ true); // bind generates resource
+
+ // Set up the texture.
+ DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId);
+ TextureRef* texture_ref = GetTexture(client_texture_id_);
+
+ // Set a mock Async delegate.
+ StrictMock<gpu::MockAsyncPixelTransferDelegate>* delegate =
+ new StrictMock<gpu::MockAsyncPixelTransferDelegate>;
+ decoder_->SetAsyncPixelTransferDelegateForTest(delegate);
+ StrictMock<gpu::MockAsyncPixelTransferState>* state = NULL;
+
+ AsyncTexImage2DCHROMIUM teximage_cmd;
+ teximage_cmd.Init(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, kSharedMemoryId, kSharedMemoryOffset);
+
+ // No transfer state exists initially.
+ EXPECT_FALSE(decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
+
+ // Create state on AsyncTexImage2D.
+ {
+ EXPECT_CALL(*delegate, CreatePixelTransferState(kServiceTextureId, _))
+ .WillOnce(
+ Return(state = new StrictMock<gpu::MockAsyncPixelTransferState>))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*delegate, AsyncTexImage2D(state, _, _, _))
+ .RetiresOnSaturation();
+
+ // Command succeeds.
+ EXPECT_EQ(error::kNoError, ExecuteCmd(teximage_cmd));
+ EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ }
+
+ // State is cached.
+ EXPECT_EQ(state,
+ decoder_->GetAsyncPixelTransferManager()->GetPixelTransferState(
+ texture_ref));
+
+ // Delete state on manager teardown.
+ {
+ EXPECT_CALL(*state, Destroy()).RetiresOnSaturation();
+ decoder_->ResetAsyncPixelTransferManagerForTest();
+
+ // Texture ref still valid.
+ EXPECT_EQ(texture_ref, GetTexture(client_texture_id_));
+ }
}
namespace {
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
index 9e67849..f878df3 100644
--- a/gpu/command_buffer/service/texture_manager.cc
+++ b/gpu/command_buffer/service/texture_manager.cc
@@ -60,7 +60,15 @@ static size_t FaceIndexToGLTarget(size_t index) {
}
}
+TextureManager::DestructionObserver::DestructionObserver() {}
+
+TextureManager::DestructionObserver::~DestructionObserver() {}
+
TextureManager::~TextureManager() {
+ FOR_EACH_OBSERVER(DestructionObserver,
+ destruction_observers_,
+ OnTextureManagerDestroying(this));
+
DCHECK(textures_.empty());
// If this triggers, that means something is keeping a reference to
@@ -432,15 +440,6 @@ void Texture::IncAllFramebufferStateChangeCount() {
(*it)->manager()->IncFramebufferStateChangeCount();
}
-AsyncPixelTransferState* Texture::GetAsyncTransferState() const {
- for (RefSet::const_iterator it = refs_.begin(); it != refs_.end(); ++it) {
- AsyncPixelTransferState* state = (*it)->async_transfer_state();
- if (state)
- return state;
- }
- return NULL;
-}
-
void Texture::SetLevelInfo(
const FeatureInfo* feature_info,
GLenum target,
@@ -1097,6 +1096,10 @@ void TextureManager::StartTracking(TextureRef* ref) {
}
void TextureManager::StopTracking(TextureRef* ref) {
+ FOR_EACH_OBSERVER(DestructionObserver,
+ destruction_observers_,
+ OnTextureRefDestroying(ref));
+
Texture* texture = ref->texture();
--texture_count_;
if (!texture->CanRender(feature_info_)) {
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
index ec0b5a6..2d4640e 100644
--- a/gpu/command_buffer/service/texture_manager.h
+++ b/gpu/command_buffer/service/texture_manager.h
@@ -13,6 +13,7 @@
#include "base/hash_tables.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
#include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/memory_tracking.h"
@@ -144,15 +145,6 @@ class GPU_EXPORT Texture {
return stream_texture_;
}
- // Gets the async transfer state for this texture. Note: the transfer state is
- // owned by a single TextureRef.
- AsyncPixelTransferState* GetAsyncTransferState() const;
-
- bool AsyncTransferIsInProgress() {
- AsyncPixelTransferState* state = GetAsyncTransferState();
- return state && state->TransferIsInProgress();
- }
-
void SetImmutable(bool immutable) {
immutable_ = immutable;
}
@@ -411,15 +403,6 @@ class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> {
GLuint client_id() const { return client_id_; }
GLuint service_id() const { return texture_->service_id(); }
- // Sets the async transfer state for this texture. Only a single TextureRef
- // can set this on a given texture at any time.
- // NOTE: this should be per-context rather than per-texture. crbug.com/240504
- void SetAsyncTransferState(
- scoped_ptr<AsyncPixelTransferState> state) {
- DCHECK(!state || !texture_->GetAsyncTransferState());
- async_transfer_state_ = state.Pass();
- }
-
private:
friend class base::RefCounted<TextureRef>;
friend class Texture;
@@ -428,18 +411,12 @@ class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> {
~TextureRef();
const TextureManager* manager() const { return manager_; }
TextureManager* manager() { return manager_; }
- AsyncPixelTransferState* async_transfer_state() const {
- return async_transfer_state_.get();
- }
void reset_client_id() { client_id_ = 0; }
TextureManager* manager_;
Texture* texture_;
GLuint client_id_;
- // State to facilitate async transfers on this texture.
- scoped_ptr<AsyncPixelTransferState> async_transfer_state_;
-
DISALLOW_COPY_AND_ASSIGN(TextureRef);
};
@@ -450,6 +427,21 @@ class GPU_EXPORT TextureRef : public base::RefCounted<TextureRef> {
// shared by multiple GLES2Decoders.
class GPU_EXPORT TextureManager {
public:
+ class GPU_EXPORT DestructionObserver {
+ public:
+ DestructionObserver();
+ virtual ~DestructionObserver();
+
+ // Called in ~TextureManager.
+ virtual void OnTextureManagerDestroying(TextureManager* manager) = 0;
+
+ // Called via ~TextureRef.
+ virtual void OnTextureRefDestroying(TextureRef* texture) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
+ };
+
enum DefaultAndBlackTextures {
kTexture2D,
kCubeMap,
@@ -654,6 +646,14 @@ class GPU_EXPORT TextureManager {
GLint level,
std::string* signature) const;
+ void AddObserver(DestructionObserver* observer) {
+ destruction_observers_.AddObserver(observer);
+ }
+
+ void RemoveObserver(DestructionObserver* observer) {
+ destruction_observers_.RemoveObserver(observer);
+ }
+
private:
friend class Texture;
friend class TextureRef;
@@ -707,6 +707,8 @@ class GPU_EXPORT TextureManager {
// The default textures for each target (texture name = 0)
scoped_refptr<TextureRef> default_textures_[kNumDefaultTextures];
+ ObserverList<DestructionObserver> destruction_observers_;
+
DISALLOW_COPY_AND_ASSIGN(TextureManager);
};
diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi
index 8895526..9dc5efd 100644
--- a/gpu/command_buffer_service.gypi
+++ b/gpu/command_buffer_service.gypi
@@ -39,6 +39,8 @@
'command_buffer/service/async_pixel_transfer_delegate_sync.cc',
'command_buffer/service/async_pixel_transfer_delegate_sync.h',
'command_buffer/service/async_pixel_transfer_delegate_win.cc',
+ 'command_buffer/service/async_pixel_transfer_manager.cc',
+ 'command_buffer/service/async_pixel_transfer_manager.h',
'command_buffer/service/buffer_manager.h',
'command_buffer/service/buffer_manager.cc',
'command_buffer/service/cmd_buffer_engine.h',