Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(538)

Unified Diff: gpu/command_buffer/service/texture_manager.cc

Issue 1154053002: gpu: Use a rectangle to keep track of the cleared area of each texture level. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: v2 Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
}
}
« no previous file with comments | « gpu/command_buffer/service/texture_manager.h ('k') | gpu/command_buffer/service/texture_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698