Chromium Code Reviews| Index: gpu/command_buffer/service/texture_manager.cc |
| diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc |
| index d64ac251d68cd82ebb2a21bb69054f245280d569..292ff3dd06f214d4ddffb7fff1fb7c5ab7e27d6f 100644 |
| --- a/gpu/command_buffer/service/texture_manager.cc |
| +++ b/gpu/command_buffer/service/texture_manager.cc |
| @@ -8,6 +8,7 @@ |
| #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| #include "gpu/command_buffer/service/error_state.h" |
| #include "gpu/command_buffer/service/feature_info.h" |
| +#include "gpu/command_buffer/service/framebuffer_manager.h" |
| #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| #include "gpu/command_buffer/service/mailbox_manager.h" |
| #include "gpu/command_buffer/service/memory_tracking.h" |
| @@ -87,10 +88,9 @@ void TextureManager::Destroy(bool have_context) { |
| DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented()); |
| } |
| -Texture::Texture(TextureManager* manager, GLuint service_id) |
| - : manager_(manager), |
| +Texture::Texture(GLuint service_id) |
| + : memory_tracking_ref_(NULL), |
| service_id_(service_id), |
| - deleted_(false), |
| cleared_(true), |
| num_uncleared_mips_(0), |
| target_(0), |
| @@ -109,24 +109,48 @@ Texture::Texture(TextureManager* manager, GLuint service_id) |
| owned_(true), |
| stream_texture_(false), |
| immutable_(false), |
| - estimated_size_(0) { |
| - if (manager_) { |
| - manager_->StartTracking(this); |
| - } |
| + estimated_size_(0), |
| + can_render_condition_(CAN_RENDER_NEVER) { |
| } |
| Texture::~Texture() { |
| - if (manager_) { |
| - if (owned_ && manager_->have_context_) { |
| +} |
| + |
| +void Texture::AddTextureRef(TextureRef* ref) { |
| + DCHECK(refs_.find(ref) == refs_.end()); |
| + refs_.insert(ref); |
| + if (!memory_tracking_ref_) { |
| + memory_tracking_ref_ = ref; |
| + GetMemTracker()->TrackMemAlloc(estimated_size()); |
| + } |
| +} |
| + |
| +void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) { |
| + if (memory_tracking_ref_ == ref) { |
| + GetMemTracker()->TrackMemFree(estimated_size()); |
| + memory_tracking_ref_ = NULL; |
| + } |
| + size_t result = refs_.erase(ref); |
| + DCHECK_EQ(result, 1u); |
| + if (refs_.empty()) { |
| + if (owned_ && have_context) { |
| GLuint id = service_id(); |
| glDeleteTextures(1, &id); |
| } |
| - MarkAsDeleted(); |
| - manager_->StopTracking(this); |
| - manager_ = NULL; |
| + delete this; |
| + } else if (memory_tracking_ref_ == NULL) { |
| + // TODO(piman): tune ownership semantics for cross-context group shared |
| + // textures. |
| + memory_tracking_ref_ = *refs_.begin(); |
| + GetMemTracker()->TrackMemAlloc(estimated_size()); |
| } |
| } |
| +MemoryTypeTracker* Texture::GetMemTracker() { |
| + DCHECK(memory_tracking_ref_); |
| + return memory_tracking_ref_->manager()->GetMemTracker(pool_); |
| +} |
| + |
| Texture::LevelInfo::LevelInfo() |
| : cleared(true), |
| target(0), |
| @@ -159,26 +183,42 @@ Texture::LevelInfo::LevelInfo(const LevelInfo& rhs) |
| Texture::LevelInfo::~LevelInfo() { |
| } |
| -bool Texture::CanRender(const FeatureInfo* feature_info) const { |
| - if (target_ == 0) { |
| - return false; |
| - } |
| +Texture::CanRenderCondition Texture::GetCanRenderCondition() const { |
|
piman
2013/05/14 01:34:50
Note: this function should encode the logic that w
|
| + if (target_ == 0) |
| + return CAN_RENDER_NEVER; |
| + |
| bool needs_mips = NeedsMips(); |
| - if ((npot() && !feature_info->feature_flags().npot_ok) || |
| - (target_ == GL_TEXTURE_RECTANGLE_ARB)) { |
| - return !needs_mips && |
| - wrap_s_ == GL_CLAMP_TO_EDGE && |
| - wrap_t_ == GL_CLAMP_TO_EDGE; |
| - } |
| if (needs_mips) { |
| - if (target_ == GL_TEXTURE_2D) { |
| - return texture_complete(); |
| - } else { |
| - return texture_complete() && cube_complete(); |
| - } |
| - } else { |
| - return true; |
| + if (!texture_complete()) |
| + return CAN_RENDER_NEVER; |
| + if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete()) |
| + return CAN_RENDER_NEVER; |
| + } |
| + |
| + bool is_npot_compatible = !needs_mips && |
| + wrap_s_ == GL_CLAMP_TO_EDGE && |
| + wrap_t_ == GL_CLAMP_TO_EDGE; |
| + |
| + if (!is_npot_compatible) { |
| + if (target_ == GL_TEXTURE_RECTANGLE_ARB) |
| + return CAN_RENDER_NEVER; |
| + else if (npot()) |
| + return CAN_RENDER_ONLY_IF_NPOT; |
| + } |
| + |
| + return CAN_RENDER_ALWAYS; |
| +} |
| + |
| +bool Texture::CanRender(const FeatureInfo* feature_info) const { |
| + switch (can_render_condition_) { |
| + case CAN_RENDER_ALWAYS: |
| + return true; |
| + case CAN_RENDER_NEVER: |
| + return false; |
| + case CAN_RENDER_ONLY_IF_NPOT: |
| + break; |
| } |
| + return feature_info->feature_flags().npot_ok; |
| } |
| void Texture::AddToSignature( |
| @@ -260,6 +300,7 @@ void Texture::SetTarget(GLenum target, GLint max_levels) { |
| if (target == GL_TEXTURE_EXTERNAL_OES) { |
| immutable_ = true; |
| } |
| + UpdateCanRenderCondition(); |
| } |
| bool Texture::CanGenerateMipmaps( |
| @@ -305,13 +346,7 @@ void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { |
| level_infos_[GLTargetToFaceIndex(target)].size()); |
| Texture::LevelInfo& info = |
| level_infos_[GLTargetToFaceIndex(target)][level]; |
| - if (!info.cleared) { |
| - DCHECK_NE(0, num_uncleared_mips_); |
| - --num_uncleared_mips_; |
| - } else { |
| - ++num_uncleared_mips_; |
| - } |
| - info.cleared = cleared; |
| + UpdateMipCleared(&info, cleared); |
| UpdateCleared(); |
| } |
| @@ -323,17 +358,61 @@ void Texture::UpdateCleared() { |
| const Texture::LevelInfo& first_face = level_infos_[0][0]; |
| int levels_needed = TextureManager::ComputeMipMapCount( |
| first_face.width, first_face.height, first_face.depth); |
| - cleared_ = true; |
| + bool cleared = true; |
| for (size_t ii = 0; ii < level_infos_.size(); ++ii) { |
| for (GLint jj = 0; jj < levels_needed; ++jj) { |
| const Texture::LevelInfo& info = level_infos_[ii][jj]; |
| if (info.width > 0 && info.height > 0 && info.depth > 0 && |
| !info.cleared) { |
| - cleared_ = false; |
| - return; |
| + cleared = false; |
| + break; |
| } |
| } |
| } |
| + UpdateSafeToRenderFrom(cleared); |
| +} |
| + |
| +void Texture::UpdateSafeToRenderFrom(bool cleared) { |
| + if (cleared_ == cleared) |
| + return; |
| + cleared_ = cleared; |
| + int delta = cleared ? -1 : +1; |
| + for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) |
| + (*it)->manager()->UpdateSafeToRenderFrom(delta); |
| +} |
| + |
| +void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) { |
| + if (info->cleared == cleared) |
| + return; |
| + info->cleared = cleared; |
| + int delta = cleared ? -1 : +1; |
| + num_uncleared_mips_ += delta; |
| + for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) |
| + (*it)->manager()->UpdateUnclearedMips(delta); |
| +} |
| + |
| +void Texture::UpdateCanRenderCondition() { |
| + CanRenderCondition can_render_condition = GetCanRenderCondition(); |
| + if (can_render_condition_ == can_render_condition) |
| + return; |
| + for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) |
| + (*it)->manager()->UpdateCanRenderCondition(can_render_condition_, |
| + can_render_condition); |
| + can_render_condition_ = can_render_condition; |
| +} |
| + |
| +void Texture::IncAllFramebufferStateChangeCount() { |
| + for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) |
| + (*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( |
| @@ -374,17 +453,16 @@ void Texture::SetLevelInfo( |
| width, height, format, type, 4, &info.estimated_size, NULL, NULL); |
| estimated_size_ += info.estimated_size; |
| - if (!info.cleared) { |
| - DCHECK_NE(0, num_uncleared_mips_); |
| - --num_uncleared_mips_; |
| - } |
| - info.cleared = cleared; |
| - if (!info.cleared) { |
| - ++num_uncleared_mips_; |
| - } |
| + UpdateMipCleared(&info, cleared); |
| max_level_set_ = std::max(max_level_set_, level); |
| Update(feature_info); |
| UpdateCleared(); |
| + UpdateCanRenderCondition(); |
| + if (IsAttachedToFramebuffer()) { |
| + // TODO(gman): If textures tracked which framebuffers they were attached to |
| + // we could just mark those framebuffers as not complete. |
| + IncAllFramebufferStateChangeCount(); |
| + } |
| } |
| bool Texture::ValidForTexture( |
| @@ -479,9 +557,9 @@ GLenum Texture::SetParameter( |
| if (!feature_info->validators()->texture_pool.IsValid(param)) { |
| return GL_INVALID_ENUM; |
| } |
| - manager_->GetMemTracker(pool_)->TrackMemFree(estimated_size()); |
| + GetMemTracker()->TrackMemFree(estimated_size()); |
| pool_ = param; |
| - manager_->GetMemTracker(pool_)->TrackMemAlloc(estimated_size()); |
| + GetMemTracker()->TrackMemAlloc(estimated_size()); |
| break; |
| case GL_TEXTURE_WRAP_S: |
| if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) { |
| @@ -512,6 +590,7 @@ GLenum Texture::SetParameter( |
| } |
| Update(feature_info); |
| UpdateCleared(); |
| + UpdateCanRenderCondition(); |
| return GL_NO_ERROR; |
| } |
| @@ -598,7 +677,7 @@ void Texture::Update(const FeatureInfo* feature_info) { |
| bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { |
| DCHECK(decoder); |
| - if (SafeToRenderFrom()) { |
| + if (cleared_) { |
| return true; |
| } |
| @@ -616,7 +695,7 @@ bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { |
| } |
| } |
| } |
| - cleared_ = true; |
| + UpdateSafeToRenderFrom(true); |
| return true; |
| } |
| @@ -653,18 +732,13 @@ bool Texture::ClearLevel( |
| return true; |
| } |
| - DCHECK_NE(0, num_uncleared_mips_); |
| - --num_uncleared_mips_; |
| - |
| // NOTE: It seems kind of gross to call back into the decoder for this |
| // but only the decoder knows all the state (like unpack_alignment_) that's |
| // needed to be able to call GL correctly. |
| - info.cleared = decoder->ClearLevel( |
| + bool cleared = decoder->ClearLevel( |
| service_id_, target_, info.target, info.level, info.format, info.type, |
| info.width, info.height, immutable_); |
| - if (!info.cleared) { |
| - ++num_uncleared_mips_; |
| - } |
| + UpdateMipCleared(&info, cleared); |
| return info.cleared; |
| } |
| @@ -683,6 +757,7 @@ void Texture::SetLevelImage( |
| DCHECK_EQ(info.target, target); |
| DCHECK_EQ(info.level, level); |
| info.image = image; |
| + UpdateCanRenderCondition(); |
| } |
| gfx::GLImage* Texture::GetLevelImage( |
| @@ -698,6 +773,28 @@ gfx::GLImage* Texture::GetLevelImage( |
| return 0; |
| } |
| + |
| +TextureRef::TextureRef(TextureManager* manager, Texture* texture) |
| + : manager_(manager), |
| + texture_(texture) { |
| + DCHECK(manager_); |
| + DCHECK(texture_); |
| + texture_->AddTextureRef(this); |
| + manager_->StartTracking(this); |
| +} |
| + |
| +scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager, |
| + GLuint service_id) { |
| + return new TextureRef(manager, new Texture(service_id)); |
| +} |
| + |
| +TextureRef::~TextureRef() { |
| + manager_->StopTracking(this); |
| + texture_->RemoveTextureRef(this, manager_->have_context_); |
| + manager_ = NULL; |
| +} |
| + |
| + |
| TextureManager::TextureManager( |
| MemoryTracker* memory_tracker, |
| FeatureInfo* feature_info, |
| @@ -708,6 +805,7 @@ TextureManager::TextureManager( |
| memory_tracker_unmanaged_( |
| new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)), |
| feature_info_(feature_info), |
| + framebuffer_manager_(NULL), |
| max_texture_size_(max_texture_size), |
| max_cube_map_texture_size_(max_cube_map_texture_size), |
| max_levels_(ComputeMipMapCount(max_texture_size, |
| @@ -749,7 +847,7 @@ bool TextureManager::Initialize() { |
| return true; |
| } |
| -scoped_refptr<Texture> |
| +scoped_refptr<TextureRef> |
| TextureManager::CreateDefaultAndBlackTextures( |
| GLenum target, |
| GLuint* black_texture) { |
| @@ -779,10 +877,7 @@ scoped_refptr<Texture> |
| } |
| glBindTexture(target, 0); |
| - // Since we are manually setting up these textures |
| - // we need to manually manipulate some of the their bookkeeping. |
| - ++num_unrenderable_textures_; |
| - scoped_refptr<Texture> default_texture(new Texture(this, ids[1])); |
| + scoped_refptr<TextureRef> default_texture(TextureRef::Create(this, ids[1])); |
| SetTarget(default_texture, target); |
| if (needs_faces) { |
| for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { |
| @@ -825,78 +920,40 @@ bool TextureManager::ValidForTarget( |
| (target != GL_TEXTURE_2D || (depth == 1)); |
| } |
| -void TextureManager::SetTarget(Texture* texture, GLenum target) { |
| - DCHECK(texture); |
| - if (!texture->CanRender(feature_info_)) { |
| - DCHECK_NE(0, num_unrenderable_textures_); |
| - --num_unrenderable_textures_; |
| - } |
| - texture->SetTarget(target, MaxLevelsForTarget(target)); |
| - if (!texture->CanRender(feature_info_)) { |
| - ++num_unrenderable_textures_; |
| - } |
| +void TextureManager::SetTarget(TextureRef* ref, GLenum target) { |
| + DCHECK(ref); |
| + ref->texture()->SetTarget(target, MaxLevelsForTarget(target)); |
| } |
| -void TextureManager::SetLevelCleared(Texture* texture, |
| +void TextureManager::SetLevelCleared(TextureRef* ref, |
| GLenum target, |
| GLint level, |
| bool cleared) { |
| - DCHECK(texture); |
| - if (!texture->SafeToRenderFrom()) { |
| - DCHECK_NE(0, num_unsafe_textures_); |
| - --num_unsafe_textures_; |
| - } |
| - num_uncleared_mips_ -= texture->num_uncleared_mips(); |
| - DCHECK_GE(num_uncleared_mips_, 0); |
| - texture->SetLevelCleared(target, level, cleared); |
| - num_uncleared_mips_ += texture->num_uncleared_mips(); |
| - if (!texture->SafeToRenderFrom()) { |
| - ++num_unsafe_textures_; |
| - } |
| + DCHECK(ref); |
| + ref->texture()->SetLevelCleared(target, level, cleared); |
| } |
| bool TextureManager::ClearRenderableLevels( |
| - GLES2Decoder* decoder,Texture* texture) { |
| - DCHECK(texture); |
| - if (texture->SafeToRenderFrom()) { |
| - return true; |
| - } |
| - DCHECK_NE(0, num_unsafe_textures_); |
| - --num_unsafe_textures_; |
| - num_uncleared_mips_ -= texture->num_uncleared_mips(); |
| - DCHECK_GE(num_uncleared_mips_, 0); |
| - bool result = texture->ClearRenderableLevels(decoder); |
| - num_uncleared_mips_ += texture->num_uncleared_mips(); |
| - if (!texture->SafeToRenderFrom()) { |
| - ++num_unsafe_textures_; |
| - } |
| - return result; |
| + GLES2Decoder* decoder, TextureRef* ref) { |
| + DCHECK(ref); |
| + return ref->texture()->ClearRenderableLevels(decoder); |
| } |
| bool TextureManager::ClearTextureLevel( |
| - GLES2Decoder* decoder,Texture* texture, |
| + GLES2Decoder* decoder, TextureRef* ref, |
| GLenum target, GLint level) { |
| - DCHECK(texture); |
| + DCHECK(ref); |
| + Texture* texture = ref->texture(); |
| if (texture->num_uncleared_mips() == 0) { |
| return true; |
| } |
| - num_uncleared_mips_ -= texture->num_uncleared_mips(); |
| - DCHECK_GE(num_uncleared_mips_, 0); |
| - if (!texture->SafeToRenderFrom()) { |
| - DCHECK_NE(0, num_unsafe_textures_); |
| - --num_unsafe_textures_; |
| - } |
| bool result = texture->ClearLevel(decoder, target, level); |
| texture->UpdateCleared(); |
| - num_uncleared_mips_ += texture->num_uncleared_mips(); |
| - if (!texture->SafeToRenderFrom()) { |
| - ++num_unsafe_textures_; |
| - } |
| return result; |
| } |
| void TextureManager::SetLevelInfo( |
| - Texture* texture, |
| + TextureRef* ref, |
| GLenum target, |
| GLint level, |
| GLenum internal_format, |
| @@ -907,34 +964,19 @@ void TextureManager::SetLevelInfo( |
| GLenum format, |
| GLenum type, |
| bool cleared) { |
| - DCHECK(texture); |
| - if (!texture->CanRender(feature_info_)) { |
| - DCHECK_NE(0, num_unrenderable_textures_); |
| - --num_unrenderable_textures_; |
| - } |
| - if (!texture->SafeToRenderFrom()) { |
| - DCHECK_NE(0, num_unsafe_textures_); |
| - --num_unsafe_textures_; |
| - } |
| - num_uncleared_mips_ -= texture->num_uncleared_mips(); |
| - DCHECK_GE(num_uncleared_mips_, 0); |
| + DCHECK(ref); |
| + Texture* texture = ref->texture(); |
| - GetMemTracker(texture->pool_)->TrackMemFree(texture->estimated_size()); |
| + texture->GetMemTracker()->TrackMemFree(texture->estimated_size()); |
| texture->SetLevelInfo( |
| feature_info_, target, level, internal_format, width, height, depth, |
| border, format, type, cleared); |
| - GetMemTracker(texture->pool_)->TrackMemAlloc(texture->estimated_size()); |
| - |
| - num_uncleared_mips_ += texture->num_uncleared_mips(); |
| - if (!texture->CanRender(feature_info_)) { |
| - ++num_unrenderable_textures_; |
| - } |
| - if (!texture->SafeToRenderFrom()) { |
| - ++num_unsafe_textures_; |
| - } |
| + texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size()); |
| } |
| -TextureDefinition* TextureManager::Save(Texture* texture) { |
| +TextureDefinition* TextureManager::Save(TextureRef* ref) { |
| + DCHECK(ref); |
| + Texture* texture = ref->texture(); |
| DCHECK(texture->owned_); |
| if (texture->IsAttachedToFramebuffer()) |
| @@ -960,7 +1002,7 @@ TextureDefinition* TextureManager::Save(Texture* texture) { |
| level_info.type, |
| level_info.cleared)); |
| - SetLevelInfo(texture, |
| + SetLevelInfo(ref, |
| target, |
| level, |
| GL_RGBA, |
| @@ -999,8 +1041,10 @@ TextureDefinition* TextureManager::Save(Texture* texture) { |
| bool TextureManager::Restore( |
| const char* function_name, |
| GLES2Decoder* decoder, |
| - Texture* texture, |
| + TextureRef* ref, |
| TextureDefinition* definition) { |
| + DCHECK(ref); |
| + Texture* texture = ref->texture(); |
| DCHECK(texture->owned_); |
| scoped_ptr<TextureDefinition> scoped_definition(definition); |
| @@ -1028,7 +1072,7 @@ bool TextureManager::Restore( |
| const TextureDefinition::LevelInfo& level_info = |
| level <= new_max_level ? definition->level_infos()[face][level] |
| : TextureDefinition::LevelInfo(); |
| - SetLevelInfo(texture, |
| + SetLevelInfo(ref, |
| target, |
| level, |
| level_info.internal_format, |
| @@ -1048,19 +1092,18 @@ bool TextureManager::Restore( |
| glBindTexture(texture->target(), texture->service_id()); |
| texture->SetImmutable(definition->immutable()); |
| texture->SetStreamTexture(definition->stream_texture()); |
| - |
| ErrorState* error_state = decoder->GetErrorState(); |
| - SetParameter(function_name, error_state, texture, GL_TEXTURE_MIN_FILTER, |
| + SetParameter(function_name, error_state, ref, GL_TEXTURE_MIN_FILTER, |
| definition->min_filter()); |
| - SetParameter(function_name, error_state, texture, GL_TEXTURE_MAG_FILTER, |
| + SetParameter(function_name, error_state, ref, GL_TEXTURE_MAG_FILTER, |
| definition->mag_filter()); |
| - SetParameter(function_name, error_state, texture, GL_TEXTURE_WRAP_S, |
| + SetParameter(function_name, error_state, ref, GL_TEXTURE_WRAP_S, |
| definition->wrap_s()); |
| - SetParameter(function_name, error_state, texture, GL_TEXTURE_WRAP_T, |
| + SetParameter(function_name, error_state, ref, GL_TEXTURE_WRAP_T, |
| definition->wrap_t()); |
| if (feature_info_->validators()->texture_parameter.IsValid( |
| GL_TEXTURE_USAGE_ANGLE)) { |
| - SetParameter(function_name, error_state, texture, GL_TEXTURE_USAGE_ANGLE, |
| + SetParameter(function_name, error_state, ref, GL_TEXTURE_USAGE_ANGLE, |
| definition->usage()); |
| } |
| @@ -1069,17 +1112,10 @@ bool TextureManager::Restore( |
| void TextureManager::SetParameter( |
| const char* function_name, ErrorState* error_state, |
| - Texture* texture, GLenum pname, GLint param) { |
| + TextureRef* ref, GLenum pname, GLint param) { |
| DCHECK(error_state); |
| - DCHECK(texture); |
| - if (!texture->CanRender(feature_info_)) { |
| - DCHECK_NE(0, num_unrenderable_textures_); |
| - --num_unrenderable_textures_; |
| - } |
| - if (!texture->SafeToRenderFrom()) { |
| - DCHECK_NE(0, num_unsafe_textures_); |
| - --num_unsafe_textures_; |
| - } |
| + DCHECK(ref); |
| + Texture* texture = ref->texture(); |
| GLenum result = texture->SetParameter(feature_info_, pname, param); |
| if (result != GL_NO_ERROR) { |
| if (result == GL_INVALID_ENUM) { |
| @@ -1096,59 +1132,28 @@ void TextureManager::SetParameter( |
| glTexParameteri(texture->target(), pname, param); |
| } |
| } |
| - |
| - if (!texture->CanRender(feature_info_)) { |
| - ++num_unrenderable_textures_; |
| - } |
| - if (!texture->SafeToRenderFrom()) { |
| - ++num_unsafe_textures_; |
| - } |
| } |
| -bool TextureManager::MarkMipmapsGenerated(Texture* texture) { |
| - DCHECK(texture); |
| - if (!texture->CanRender(feature_info_)) { |
| - DCHECK_NE(0, num_unrenderable_textures_); |
| - --num_unrenderable_textures_; |
| - } |
| - if (!texture->SafeToRenderFrom()) { |
| - DCHECK_NE(0, num_unsafe_textures_); |
| - --num_unsafe_textures_; |
| - } |
| - num_uncleared_mips_ -= texture->num_uncleared_mips(); |
| - DCHECK_GE(num_uncleared_mips_, 0); |
| - GetMemTracker(texture->pool_)->TrackMemFree(texture->estimated_size()); |
| +bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) { |
| + DCHECK(ref); |
| + Texture* texture = ref->texture(); |
| + texture->GetMemTracker()->TrackMemFree(texture->estimated_size()); |
| bool result = texture->MarkMipmapsGenerated(feature_info_); |
| - GetMemTracker(texture->pool_)->TrackMemAlloc(texture->estimated_size()); |
| - |
| - num_uncleared_mips_ += texture->num_uncleared_mips(); |
| - if (!texture->CanRender(feature_info_)) { |
| - ++num_unrenderable_textures_; |
| - } |
| - if (!texture->SafeToRenderFrom()) { |
| - ++num_unsafe_textures_; |
| - } |
| + texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size()); |
| return result; |
| } |
| -Texture* TextureManager::CreateTexture( |
| +TextureRef* TextureManager::CreateTexture( |
| GLuint client_id, GLuint service_id) { |
| DCHECK_NE(0u, service_id); |
| - scoped_refptr<Texture> texture(new Texture(this, service_id)); |
| + scoped_refptr<TextureRef> ref(TextureRef::Create(this, service_id)); |
| std::pair<TextureMap::iterator, bool> result = |
| - textures_.insert(std::make_pair(client_id, texture)); |
| + textures_.insert(std::make_pair(client_id, ref)); |
| DCHECK(result.second); |
| - if (!texture->CanRender(feature_info_)) { |
| - ++num_unrenderable_textures_; |
| - } |
| - if (!texture->SafeToRenderFrom()) { |
| - ++num_unsafe_textures_; |
| - } |
| - num_uncleared_mips_ += texture->num_uncleared_mips(); |
| - return texture.get(); |
| + return ref.get(); |
| } |
| -Texture* TextureManager::GetTexture( |
| +TextureRef* TextureManager::GetTexture( |
| GLuint client_id) const { |
| TextureMap::const_iterator it = textures_.find(client_id); |
| return it != textures_.end() ? it->second : NULL; |
| @@ -1157,17 +1162,24 @@ Texture* TextureManager::GetTexture( |
| void TextureManager::RemoveTexture(GLuint client_id) { |
| TextureMap::iterator it = textures_.find(client_id); |
| if (it != textures_.end()) { |
| - Texture* texture = it->second; |
| - texture->MarkAsDeleted(); |
| textures_.erase(it); |
| } |
| } |
| -void TextureManager::StartTracking(Texture* /* texture */) { |
| +void TextureManager::StartTracking(TextureRef* ref) { |
| + Texture* texture = ref->texture(); |
| ++texture_count_; |
| + num_uncleared_mips_ += texture->num_uncleared_mips(); |
| + if (!texture->SafeToRenderFrom()) { |
| + DCHECK_NE(0, num_unsafe_textures_); |
| + ++num_unsafe_textures_; |
| + } |
| + if (!texture->CanRender(feature_info_)) |
| + ++num_unrenderable_textures_; |
| } |
| -void TextureManager::StopTracking(Texture* texture) { |
| +void TextureManager::StopTracking(TextureRef* ref) { |
| + Texture* texture = ref->texture(); |
| --texture_count_; |
| if (!texture->CanRender(feature_info_)) { |
| DCHECK_NE(0, num_unrenderable_textures_); |
| @@ -1179,7 +1191,6 @@ void TextureManager::StopTracking(Texture* texture) { |
| } |
| num_uncleared_mips_ -= texture->num_uncleared_mips(); |
| DCHECK_GE(num_uncleared_mips_, 0); |
| - GetMemTracker(texture->pool_)->TrackMemFree(texture->estimated_size()); |
| } |
| MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) { |
| @@ -1201,7 +1212,7 @@ bool TextureManager::GetClientId(GLuint service_id, GLuint* client_id) const { |
| // This doesn't need to be fast. It's only used during slow queries. |
| for (TextureMap::const_iterator it = textures_.begin(); |
| it != textures_.end(); ++it) { |
| - if (it->second->service_id() == service_id) { |
| + if (it->second->texture()->service_id() == service_id) { |
| *client_id = it->first; |
| return true; |
| } |
| @@ -1215,34 +1226,51 @@ GLsizei TextureManager::ComputeMipMapCount( |
| } |
| void TextureManager::SetLevelImage( |
| - Texture* texture, |
| + TextureRef* ref, |
| GLenum target, |
| GLint level, |
| gfx::GLImage* image) { |
| - DCHECK(texture); |
| - if (!texture->CanRender(feature_info_)) { |
| - DCHECK_NE(0, num_unrenderable_textures_); |
| - --num_unrenderable_textures_; |
| - } |
| - if (!texture->SafeToRenderFrom()) { |
| - DCHECK_NE(0, num_unsafe_textures_); |
| - --num_unsafe_textures_; |
| - } |
| - texture->SetLevelImage(feature_info_, target, level, image); |
| - if (!texture->CanRender(feature_info_)) { |
| - ++num_unrenderable_textures_; |
| - } |
| - if (!texture->SafeToRenderFrom()) { |
| - ++num_unsafe_textures_; |
| - } |
| + DCHECK(ref); |
| + ref->texture()->SetLevelImage(feature_info_, target, level, image); |
| } |
| void TextureManager::AddToSignature( |
| - Texture* texture, |
| + TextureRef* ref, |
| GLenum target, |
| GLint level, |
| std::string* signature) const { |
| - texture->AddToSignature(feature_info_.get(), target, level, signature); |
| + ref->texture()->AddToSignature(feature_info_.get(), target, level, signature); |
| +} |
| + |
| +void TextureManager::UpdateSafeToRenderFrom(int delta) { |
| + num_unsafe_textures_ += delta; |
| + DCHECK_GE(num_unsafe_textures_, 0); |
| +} |
| + |
| +void TextureManager::UpdateUnclearedMips(int delta) { |
| + num_uncleared_mips_ += delta; |
| + DCHECK_GE(num_uncleared_mips_, 0); |
| +} |
| + |
| +void TextureManager::UpdateCanRenderCondition( |
| + Texture::CanRenderCondition old_condition, |
| + Texture::CanRenderCondition new_condition) { |
| + if (old_condition == Texture::CAN_RENDER_NEVER || |
| + (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT && |
| + !feature_info_->feature_flags().npot_ok)) { |
| + DCHECK_GT(num_unrenderable_textures_, 0); |
| + --num_unrenderable_textures_; |
| + } |
| + if (new_condition == Texture::CAN_RENDER_NEVER || |
| + (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT && |
| + !feature_info_->feature_flags().npot_ok)) |
| + ++num_unrenderable_textures_; |
| +} |
| + |
| +void TextureManager::IncFramebufferStateChangeCount() { |
| + if (framebuffer_manager_) |
| + framebuffer_manager_->IncFramebufferStateChangeCount(); |
| + |
| } |
| } // namespace gles2 |