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 2596dca2129b4db8679640043ff5209214f4aecb..c7150ee98eee936d0c174cd9246505cbc691eefe 100644 |
--- a/gpu/command_buffer/service/texture_manager.cc |
+++ b/gpu/command_buffer/service/texture_manager.cc |
@@ -379,8 +379,7 @@ MemoryTypeTracker* Texture::GetMemTracker() { |
} |
Texture::LevelInfo::LevelInfo() |
- : cleared(true), |
- target(0), |
+ : target(0), |
level(-1), |
internal_format(0), |
width(0), |
@@ -393,7 +392,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 +539,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 +656,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,7 +667,19 @@ 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); |
+ UpdateMipCleared(&info, info.width, info.height, cleared_rect); |
+ UpdateCleared(); |
+} |
+ |
+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]; |
+ UpdateMipCleared(&info, info.width, info.height, |
+ cleared ? gfx::Rect(info.width, info.height) : gfx::Rect()); |
UpdateCleared(); |
} |
@@ -703,10 +708,17 @@ void Texture::UpdateSafeToRenderFrom(bool cleared) { |
(*it)->manager()->UpdateSafeToRenderFrom(delta); |
} |
-void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) { |
- if (info->cleared == cleared) |
+void Texture::UpdateMipCleared(LevelInfo* info, |
+ GLsizei width, |
+ GLsizei height, |
+ const gfx::Rect& cleared_rect) { |
+ bool was_cleared = info->cleared_rect == gfx::Rect(info->width, info->height); |
+ info->width = width; |
+ info->height = height; |
+ info->cleared_rect = cleared_rect; |
+ bool cleared = info->cleared_rect == gfx::Rect(info->width, info->height); |
+ if (cleared == was_cleared) |
return; |
- info->cleared = cleared; |
int delta = cleared ? -1 : +1; |
num_uncleared_mips_ += delta; |
for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it) |
@@ -751,18 +763,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), |
@@ -807,20 +818,19 @@ void Texture::SetLevelInfo( |
info.target = target; |
info.level = level; |
info.internal_format = internal_format; |
- info.width = width; |
- info.height = height; |
info.depth = depth; |
info.border = border; |
info.format = format; |
info.type = type; |
info.image = 0; |
+ UpdateMipCleared(&info, width, height, cleared_rect); |
+ |
estimated_size_ -= info.estimated_size; |
GLES2Util::ComputeImageDataSizes( |
width, height, 1, format, type, 4, &info.estimated_size, NULL, NULL); |
estimated_size_ += info.estimated_size; |
- UpdateMipCleared(&info, cleared); |
max_level_set_ = std::max(max_level_set_, level); |
Update(feature_info); |
UpdateCleared(); |
@@ -1146,6 +1156,18 @@ bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { |
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 +1177,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 == gfx::Rect(info.width, info.height); |
} |
void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) { |
@@ -1180,21 +1202,41 @@ 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 == 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; |
+ } |
+ } |
+ |
+ UpdateMipCleared(&info, info.width, info.height, |
+ gfx::Rect(info.width, info.height)); |
+ return true; |
} |
void Texture::SetLevelImage( |
@@ -1373,43 +1415,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 +1459,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, |
@@ -1470,33 +1494,25 @@ bool TextureManager::ClearTextureLevel( |
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()); |
} |
@@ -1947,10 +1963,9 @@ void TextureManager::DoTexImage( |
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, |
- args.depth, args.border, args.format, args.type, false); |
+ SetLevelInfo(texture_ref, args.target, args.level, args.internal_format, |
+ args.width, args.height, args.depth, args.border, args.format, |
+ args.type, gfx::Rect()); |
texture_state->tex_image_failed = false; |
return; |
} |
@@ -1993,9 +2008,9 @@ void TextureManager::DoTexImage( |
GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name); |
if (error == GL_NO_ERROR) { |
SetLevelInfo( |
- texture_ref, |
- args.target, args.level, args.internal_format, args.width, args.height, |
- args.depth, args.border, args.format, args.type, args.pixels != NULL); |
+ texture_ref, args.target, args.level, args.internal_format, args.width, |
+ args.height, args.depth, args.border, args.format, args.type, |
+ args.pixels != NULL ? gfx::Rect(args.width, args.height) : gfx::Rect()); |
texture_state->tex_image_failed = false; |
} |
} |