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
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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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::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 @@
bool GLES2DecoderImpl::ValidateAsyncTransfer(
const char* function_name,
- Texture* texture,
+ TextureRef* texture_ref,
GLenum target,
GLint level,
const void * data) {
@@ -10119,7 +10135,8 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
&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 @@
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;
}