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; |
} |
} |