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 8785679bd135233840b58f3e81ff2daf5c6579f3..5b13a990624f8390c8a80e00257b03c4ca2f7f88 100644 |
| --- a/gpu/command_buffer/service/texture_manager.cc |
| +++ b/gpu/command_buffer/service/texture_manager.cc |
| @@ -281,7 +281,6 @@ TextureManager::~TextureManager() { |
| DCHECK_EQ(0, num_unrenderable_textures_); |
| DCHECK_EQ(0, num_unsafe_textures_); |
| - DCHECK_EQ(0, num_uncleared_mips_); |
| DCHECK_EQ(0, num_images_); |
| } |
| @@ -305,7 +304,6 @@ Texture::Texture(GLuint service_id) |
| memory_tracking_ref_(NULL), |
| service_id_(service_id), |
| cleared_(true), |
| - num_uncleared_mips_(0), |
| num_npot_faces_(0), |
| target_(0), |
| min_filter_(GL_NEAREST_MIPMAP_LINEAR), |
| @@ -379,8 +377,7 @@ MemoryTypeTracker* Texture::GetMemTracker() { |
| } |
| Texture::LevelInfo::LevelInfo() |
| - : cleared(true), |
| - target(0), |
| + : target(0), |
| level(-1), |
| internal_format(0), |
| width(0), |
| @@ -393,7 +390,7 @@ Texture::LevelInfo::LevelInfo() |
| } |
| Texture::LevelInfo::LevelInfo(const LevelInfo& rhs) |
| - : cleared(rhs.cleared), |
| + : cleared_rect(rhs.cleared_rect), |
| target(rhs.target), |
| level(rhs.level), |
| internal_format(rhs.internal_format), |
| @@ -540,17 +537,9 @@ bool Texture::MarkMipmapsGenerated( |
| width = std::max(1, width >> 1); |
| height = std::max(1, height >> 1); |
| depth = std::max(1, depth >> 1); |
| - SetLevelInfo(feature_info, |
| - target, |
| - level, |
| - level0_info.internal_format, |
| - width, |
| - height, |
| - depth, |
| - level0_info.border, |
| - level0_info.format, |
| - level0_info.type, |
| - true); |
| + SetLevelInfo(feature_info, target, level, level0_info.internal_format, |
| + width, height, depth, level0_info.border, level0_info.format, |
| + level0_info.type, gfx::Rect(width, height)); |
| } |
| } |
| @@ -665,7 +654,9 @@ bool Texture::TextureMipComplete(const Texture::LevelInfo& level0_face, |
| return complete; |
| } |
| -void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { |
| +void Texture::SetLevelClearedRect(GLenum target, |
| + GLint level, |
| + const gfx::Rect& cleared_rect) { |
| DCHECK_GE(level, 0); |
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| DCHECK_LT(static_cast<size_t>(face_index), |
| @@ -674,43 +665,45 @@ void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { |
| face_infos_[face_index].level_infos.size()); |
| Texture::LevelInfo& info = |
| face_infos_[face_index].level_infos[level]; |
| - UpdateMipCleared(&info, cleared); |
| - UpdateCleared(); |
| + info.cleared_rect = cleared_rect; |
|
piman
2015/05/27 20:50:17
nit: could we have a DCHECK that cleared_rect only
reveman
2015/06/03 22:40:04
Done. By adding DCHECKs to the caller as we can't
|
| + UpdateSafeToRenderFrom(); |
| } |
| -void Texture::UpdateCleared() { |
| - if (face_infos_.empty()) { |
| - return; |
| - } |
| - |
| - const bool cleared = (num_uncleared_mips_ == 0); |
| +void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { |
| + DCHECK_GE(level, 0); |
| + size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| + DCHECK_LT(static_cast<size_t>(face_index), face_infos_.size()); |
| + DCHECK_LT(static_cast<size_t>(level), |
| + face_infos_[face_index].level_infos.size()); |
| + Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; |
| + info.cleared_rect = |
| + cleared ? gfx::Rect(info.width, info.height) : gfx::Rect(); |
| + UpdateSafeToRenderFrom(); |
| +} |
| - // If texture is uncleared and is attached to a framebuffer, |
| - // that framebuffer must be marked possibly incomplete. |
| - if (!cleared && IsAttachedToFramebuffer()) { |
| - IncAllFramebufferStateChangeCount(); |
| +void Texture::UpdateSafeToRenderFrom() { |
| + bool cleared = true; |
| + for (size_t ii = 0; ii < face_infos_.size(); ++ii) { |
| + for (size_t jj = 0; jj < face_infos_[ii].level_infos.size(); ++jj) { |
| + const Texture::LevelInfo& info = face_infos_[ii].level_infos[jj]; |
| + if (!info.cleared_rect.Contains(gfx::Rect(info.width, info.height))) { |
| + cleared = false; |
| + break; |
| + } |
| + } |
| } |
|
piman
2015/05/27 20:50:17
I worry about the extra tracking cost here. This i
reveman
2015/06/03 22:40:04
Done. However, this is a bit more complicated than
|
| - 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); |
| + // If texture is uncleared and is attached to a framebuffer, |
| + // that framebuffer must be marked possibly incomplete. |
| + if (!cleared && IsAttachedToFramebuffer()) |
| + IncAllFramebufferStateChangeCount(); |
| } |
| void Texture::UpdateCanRenderCondition() { |
| @@ -751,18 +744,17 @@ void Texture::IncAllFramebufferStateChangeCount() { |
| (*it)->manager()->IncFramebufferStateChangeCount(); |
| } |
| -void Texture::SetLevelInfo( |
| - const FeatureInfo* feature_info, |
| - GLenum target, |
| - GLint level, |
| - GLenum internal_format, |
| - GLsizei width, |
| - GLsizei height, |
| - GLsizei depth, |
| - GLint border, |
| - GLenum format, |
| - GLenum type, |
| - bool cleared) { |
| +void Texture::SetLevelInfo(const FeatureInfo* feature_info, |
| + GLenum target, |
| + GLint level, |
| + GLenum internal_format, |
| + GLsizei width, |
| + GLsizei height, |
| + GLsizei depth, |
| + GLint border, |
| + GLenum format, |
| + GLenum type, |
| + const gfx::Rect& cleared_rect) { |
| DCHECK_GE(level, 0); |
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| DCHECK_LT(static_cast<size_t>(face_index), |
| @@ -820,10 +812,10 @@ void Texture::SetLevelInfo( |
| width, height, 1, format, type, 4, &info.estimated_size, NULL, NULL); |
| estimated_size_ += info.estimated_size; |
| - UpdateMipCleared(&info, cleared); |
| + info.cleared_rect = cleared_rect; |
| max_level_set_ = std::max(max_level_set_, level); |
| Update(feature_info); |
| - UpdateCleared(); |
| + UpdateSafeToRenderFrom(); |
| UpdateCanRenderCondition(); |
| UpdateHasImages(); |
| if (IsAttachedToFramebuffer()) { |
| @@ -1000,7 +992,7 @@ GLenum Texture::SetParameteri( |
| return GL_INVALID_ENUM; |
| } |
| Update(feature_info); |
| - UpdateCleared(); |
| + UpdateSafeToRenderFrom(); |
| UpdateCanRenderCondition(); |
| return GL_NO_ERROR; |
| } |
| @@ -1142,10 +1134,22 @@ bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { |
| } |
| } |
| } |
| - UpdateSafeToRenderFrom(true); |
| + UpdateSafeToRenderFrom(); |
| return true; |
| } |
| +gfx::Rect Texture::GetLevelClearedRect(GLenum target, GLint level) const { |
| + size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| + if (face_index >= face_infos_.size() || |
| + level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) { |
| + return gfx::Rect(); |
| + } |
| + |
| + const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; |
| + |
| + return info.cleared_rect; |
| +} |
| + |
| bool Texture::IsLevelCleared(GLenum target, GLint level) const { |
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| if (face_index >= face_infos_.size() || |
| @@ -1155,7 +1159,7 @@ bool Texture::IsLevelCleared(GLenum target, GLint level) const { |
| const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level]; |
| - return info.cleared; |
| + return info.cleared_rect.Contains(gfx::Rect(info.width, info.height)); |
| } |
| void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) { |
| @@ -1180,21 +1184,40 @@ bool Texture::ClearLevel( |
| DCHECK(target == info.target); |
| if (info.target == 0 || |
| - info.cleared || |
| - info.width == 0 || |
| - info.height == 0 || |
| - info.depth == 0) { |
| + info.cleared_rect.Contains(gfx::Rect(info.width, info.height)) || |
| + info.width == 0 || info.height == 0 || info.depth == 0) { |
| return true; |
| } |
| - // 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. |
| - bool cleared = decoder->ClearLevel( |
| - this, info.target, info.level, info.internal_format, info.format, |
| - info.type, info.width, info.height, immutable_); |
| - UpdateMipCleared(&info, cleared); |
| - return info.cleared; |
| + // Clear all remaining sub regions. |
| + const int x[] = { |
| + 0, info.cleared_rect.x(), info.cleared_rect.right(), info.width}; |
| + const int y[] = { |
| + 0, info.cleared_rect.y(), info.cleared_rect.bottom(), info.height}; |
| + |
| + for (size_t j = 0; j < 3; ++j) { |
| + for (size_t i = 0; i < 3; ++i) { |
| + // Center of nine patch is already cleared. |
| + if (j == 1 && i == 1) |
| + continue; |
| + |
| + gfx::Rect rect(x[i], y[j], x[i + 1] - x[i], y[j + 1] - y[j]); |
| + if (rect.IsEmpty()) |
| + continue; |
| + |
| + // 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. |
| + bool cleared = decoder->ClearLevel(this, info.target, info.level, |
| + info.format, info.type, rect.x(), |
| + rect.y(), rect.width(), rect.height()); |
| + if (!cleared) |
| + return false; |
| + } |
| + } |
| + |
| + info.cleared_rect = gfx::Rect(info.width, info.height); |
| + return true; |
| } |
| void Texture::SetLevelImage( |
| @@ -1304,7 +1327,6 @@ TextureManager::TextureManager(MemoryTracker* memory_tracker, |
| use_default_textures_(use_default_textures), |
| num_unrenderable_textures_(0), |
| num_unsafe_textures_(0), |
| - num_uncleared_mips_(0), |
| num_images_(0), |
| texture_count_(0), |
| have_context_(true) { |
| @@ -1373,43 +1395,17 @@ scoped_refptr<TextureRef> |
| SetTarget(default_texture.get(), target); |
| if (needs_faces) { |
| for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { |
| - SetLevelInfo(default_texture.get(), |
| - GLES2Util::IndexToGLFaceTarget(ii), |
| - 0, |
| - GL_RGBA, |
| - 1, |
| - 1, |
| - 1, |
| - 0, |
| - GL_RGBA, |
| - GL_UNSIGNED_BYTE, |
| - true); |
| + SetLevelInfo(default_texture.get(), GLES2Util::IndexToGLFaceTarget(ii), |
| + 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, |
| + gfx::Rect(1, 1)); |
| } |
| } else { |
| if (needs_initialization) { |
| - SetLevelInfo(default_texture.get(), |
| - GL_TEXTURE_2D, |
| - 0, |
| - GL_RGBA, |
| - 1, |
| - 1, |
| - 1, |
| - 0, |
| - GL_RGBA, |
| - GL_UNSIGNED_BYTE, |
| - true); |
| + SetLevelInfo(default_texture.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, |
| + 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); |
| } else { |
| - SetLevelInfo(default_texture.get(), |
| - GL_TEXTURE_EXTERNAL_OES, |
| - 0, |
| - GL_RGBA, |
| - 1, |
| - 1, |
| - 1, |
| - 0, |
| - GL_RGBA, |
| - GL_UNSIGNED_BYTE, |
| - true); |
| + SetLevelInfo(default_texture.get(), GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA, |
| + 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1)); |
| } |
| } |
| } |
| @@ -1443,6 +1439,14 @@ void TextureManager::SetTarget(TextureRef* ref, GLenum target) { |
| ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target)); |
| } |
| +void TextureManager::SetLevelClearedRect(TextureRef* ref, |
| + GLenum target, |
| + GLint level, |
| + const gfx::Rect& cleared_rect) { |
| + DCHECK(ref); |
| + ref->texture()->SetLevelClearedRect(target, level, cleared_rect); |
| +} |
| + |
| void TextureManager::SetLevelCleared(TextureRef* ref, |
| GLenum target, |
| GLint level, |
| @@ -1462,41 +1466,33 @@ bool TextureManager::ClearTextureLevel( |
| GLenum target, GLint level) { |
| DCHECK(ref); |
| Texture* texture = ref->texture(); |
| - if (texture->num_uncleared_mips() == 0) { |
| + if (texture->SafeToRenderFrom()) { |
| return true; |
| } |
| bool result = texture->ClearLevel(decoder, target, level); |
| - texture->UpdateCleared(); |
| + texture->UpdateSafeToRenderFrom(); |
| return result; |
| } |
| -void TextureManager::SetLevelInfo( |
| - TextureRef* ref, |
| - GLenum target, |
| - GLint level, |
| - GLenum internal_format, |
| - GLsizei width, |
| - GLsizei height, |
| - GLsizei depth, |
| - GLint border, |
| - GLenum format, |
| - GLenum type, |
| - bool cleared) { |
| +void TextureManager::SetLevelInfo(TextureRef* ref, |
| + GLenum target, |
| + GLint level, |
| + GLenum internal_format, |
| + GLsizei width, |
| + GLsizei height, |
| + GLsizei depth, |
| + GLint border, |
| + GLenum format, |
| + GLenum type, |
| + const gfx::Rect& cleared_rect) { |
| + DCHECK(gfx::Rect(width, height).Contains(cleared_rect)); |
| DCHECK(ref); |
| Texture* texture = ref->texture(); |
| texture->GetMemTracker()->TrackMemFree(texture->estimated_size()); |
| - texture->SetLevelInfo(feature_info_.get(), |
| - target, |
| - level, |
| - internal_format, |
| - width, |
| - height, |
| - depth, |
| - border, |
| - format, |
| - type, |
| - cleared); |
| + texture->SetLevelInfo(feature_info_.get(), target, level, internal_format, |
| + width, height, depth, border, format, type, |
| + cleared_rect); |
| texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size()); |
| } |
| @@ -1600,7 +1596,6 @@ void TextureManager::RemoveTexture(GLuint client_id) { |
| void TextureManager::StartTracking(TextureRef* ref) { |
| Texture* texture = ref->texture(); |
| ++texture_count_; |
| - num_uncleared_mips_ += texture->num_uncleared_mips(); |
| if (!texture->SafeToRenderFrom()) |
| ++num_unsafe_textures_; |
| if (!texture->CanRender(feature_info_.get())) |
| @@ -1632,8 +1627,6 @@ void TextureManager::StopTracking(TextureRef* ref) { |
| DCHECK_NE(0, num_unsafe_textures_); |
| --num_unsafe_textures_; |
| } |
| - num_uncleared_mips_ -= texture->num_uncleared_mips(); |
| - DCHECK_GE(num_uncleared_mips_, 0); |
| } |
| MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) { |
| @@ -1701,11 +1694,6 @@ void TextureManager::UpdateSafeToRenderFrom(int 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) { |
| @@ -1940,10 +1928,9 @@ void TextureManager::DoTexImage2D( |
| if (level_is_same && !args.pixels) { |
| // Just set the level texture but mark the texture as uncleared. |
| - SetLevelInfo( |
| - texture_ref, |
| - args.target, args.level, args.internal_format, args.width, args.height, |
| - 1, args.border, args.format, args.type, false); |
| + SetLevelInfo(texture_ref, args.target, args.level, args.internal_format, |
| + args.width, args.height, 1, args.border, args.format, |
| + args.type, gfx::Rect()); |
| texture_state->tex_image_2d_failed = false; |
| return; |
| } |
| @@ -1974,9 +1961,9 @@ void TextureManager::DoTexImage2D( |
| GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glTexImage2D"); |
| if (error == GL_NO_ERROR) { |
| SetLevelInfo( |
| - texture_ref, |
| - args.target, args.level, args.internal_format, args.width, args.height, |
| - 1, args.border, args.format, args.type, args.pixels != NULL); |
| + texture_ref, args.target, args.level, args.internal_format, args.width, |
| + args.height, 1, args.border, args.format, args.type, |
| + args.pixels != NULL ? gfx::Rect(args.width, args.height) : gfx::Rect()); |
| texture_state->tex_image_2d_failed = false; |
| } |
| } |