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 acc63d779c8f0ee8bf5868015d09ddbb2ee5a416..08fe659d6fa4cbf1e92aa87f1f3de53b2c012c7a 100644 |
| --- a/gpu/command_buffer/service/texture_manager.cc |
| +++ b/gpu/command_buffer/service/texture_manager.cc |
| @@ -128,6 +128,9 @@ Texture::Texture(GLuint service_id) |
| service_id_(service_id), |
| cleared_(true), |
| num_uncleared_mips_(0), |
| + num_npot_faces_(0), |
| + num_complete_faces_(0), |
| + num_incomplete_mips_(0), |
| target_(0), |
| min_filter_(GL_NEAREST_MIPMAP_LINEAR), |
| mag_filter_(GL_LINEAR), |
| @@ -329,8 +332,8 @@ bool Texture::MarkMipmapsGenerated( |
| GLsizei depth = info1.depth; |
| GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D : |
| GLES2Util::IndexToGLFaceTarget(ii); |
| - int num_mips = |
| - TextureManager::ComputeMipMapCount(target_, width, height, depth); |
| + |
| + const int num_mips = num_mip_levels_[ii]; |
| for (int level = 1; level < num_mips; ++level) { |
| width = std::max(1, width >> 1); |
| height = std::max(1, height >> 1); |
| @@ -361,6 +364,7 @@ void Texture::SetTarget( |
| for (size_t ii = 0; ii < num_faces; ++ii) { |
| level_infos_[ii].resize(max_levels); |
| } |
| + num_mip_levels_.resize(num_faces); |
| if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) { |
| min_filter_ = GL_LINEAR; |
| @@ -407,6 +411,59 @@ bool Texture::CanGenerateMipmaps( |
| return true; |
| } |
| +bool Texture::TextureIsNPOT(GLsizei width, |
| + GLsizei height, |
| + GLsizei depth) { |
| + return (GLES2Util::IsNPOT(width) || |
| + GLES2Util::IsNPOT(height) || |
| + GLES2Util::IsNPOT(depth)); |
| +} |
| + |
| +bool Texture::TextureFaceComplete(const Texture::LevelInfo& first_face, |
| + size_t face_index, |
| + GLenum target, |
| + GLenum internal_format, |
| + GLsizei width, |
| + GLsizei height, |
| + GLsizei depth, |
| + GLenum format, |
| + GLenum type) { |
| + bool complete = (target != 0 && depth == 1); |
| + if (face_index != 0) { |
| + complete &= (width == first_face.width && |
| + height == first_face.height && |
| + internal_format == first_face.internal_format && |
| + format == first_face.format && |
| + type == first_face.type); |
| + } |
| + return complete; |
| +} |
| + |
| +bool Texture::TextureMipComplete(const Texture::LevelInfo& level0_face, |
| + GLenum target, |
| + GLint level, |
| + GLenum internal_format, |
| + GLsizei width, |
| + GLsizei height, |
| + GLsizei depth, |
| + GLenum format, |
| + GLenum type) { |
| + bool complete = (target != 0); |
| + if (level != 0) { |
| + const GLsizei mip_width = std::max(1, level0_face.width >> level); |
| + const GLsizei mip_height = std::max(1, level0_face.height >> level); |
| + const GLsizei mip_depth = std::max(1, level0_face.depth >> level); |
|
vmiura
2014/10/07 00:13:03
Do we need to handle the case of width/height/dept
David Yen
2014/10/09 20:20:16
That check is already done before this function is
|
| + |
| + complete &= (width == mip_width && |
| + height == mip_height && |
| + depth == mip_depth && |
| + internal_format == level0_face.internal_format && |
| + format == level0_face.format && |
| + type == level0_face.type); |
| + } |
| + return complete; |
| +} |
| + |
| void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) { |
| DCHECK_GE(level, 0); |
| size_t face_index = GLES2Util::GLTargetToFaceIndex(target); |
| @@ -516,6 +573,89 @@ void Texture::SetLevelInfo( |
| DCHECK_GE(depth, 0); |
| Texture::LevelInfo& info = |
| level_infos_[face_index][level]; |
| + |
| + // Update counters only if any attributes have changed. Counters are |
| + // comparisons between the old and new values so it must be done before any |
| + // assignment has been done to the LevelInfo. |
| + if (info.target != target || |
| + info.internal_format != internal_format || |
| + info.width != width || |
| + info.height != height || |
| + info.depth != depth || |
| + info.format != format || |
| + info.type != type) { |
| + if (level == 0) { |
| + // Calculate the mip level count. |
| + num_mip_levels_[face_index] = TextureManager::ComputeMipMapCount( |
| + target_, width, height, depth); |
| + |
| + // Update NPOT face count for the first level. |
| + bool prev_npot = TextureIsNPOT(info.width, info.height, info.depth); |
| + bool now_npot = TextureIsNPOT(width, height, depth); |
| + if (prev_npot != now_npot) |
| + num_npot_faces_ += now_npot ? 1 : -1; |
| + |
| + // Update number of complete faces. |
| + const Texture::LevelInfo& first_face = level_infos_[0][0]; |
| + for (size_t i = face_index; i < level_infos_.size(); ++i) { |
|
vmiura
2014/10/07 00:13:03
I think this compares face 0 to itself, so I think
David Yen
2014/10/09 20:20:16
No longer relevant, using dirty bit now.
|
| + bool prev_face_status = TextureFaceComplete(first_face, |
| + face_index, |
| + info.target, |
| + info.internal_format, |
| + info.width, |
| + info.height, |
| + info.depth, |
| + info.format, |
| + info.type); |
| + bool new_face_status = TextureFaceComplete(first_face, |
| + face_index, |
| + target, |
| + internal_format, |
| + width, |
| + height, |
| + depth, |
| + format, |
| + type); |
| + if (prev_face_status != new_face_status) |
| + num_complete_faces_ += new_face_status ? 1 : -1; |
| + |
| + // Only need to validate all faces if the first face is changing. |
| + if (face_index != 0) |
| + break; |
| + } |
| + } |
| + |
| + // Update incomplete mip counter. |
| + const Texture::LevelInfo& level0_face = level_infos_[face_index][0]; |
| + const GLsizei num_mip_levels = num_mip_levels_[face_index]; |
|
vmiura
2014/10/07 00:13:03
If num_mip_levels changes, for example decreasing,
David Yen
2014/10/09 20:20:16
No longer relevant, using dirty bit now.
|
| + for (GLsizei i = static_cast<GLsizei>(level); i < num_mip_levels; ++i) { |
| + bool prev_mip_status = TextureMipComplete(level0_face, |
| + info.target, |
| + i, |
| + info.internal_format, |
| + info.width, |
| + info.height, |
| + info.depth, |
| + info.format, |
| + info.type); |
| + bool new_mip_status = TextureMipComplete(level0_face, |
| + target, |
| + i, |
| + internal_format, |
| + width, |
| + height, |
| + depth, |
| + format, |
| + type); |
| + if (prev_mip_status != new_mip_status) |
| + num_incomplete_mips_ += new_mip_status ? -1 : 1; |
|
vmiura
2014/10/07 00:13:03
As above, I'm not sure we will count correctly whe
David Yen
2014/10/09 20:20:16
No longer relevant, using dirty bit now.
|
| + |
| + // Only need to validate all faces if the first face is changing. |
| + if (face_index != 0) |
| + break; |
| + } |
| + } |
| + |
| info.target = target; |
| info.level = level; |
| info.internal_format = internal_format; |
| @@ -700,7 +840,7 @@ GLenum Texture::SetParameterf( |
| void Texture::Update(const FeatureInfo* feature_info) { |
| // Update npot status. |
| // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others |
| - npot_ = target_ == GL_TEXTURE_EXTERNAL_OES; |
| + npot_ = (target_ == GL_TEXTURE_EXTERNAL_OES) || (num_npot_faces_ > 0); |
| if (level_infos_.empty()) { |
| texture_complete_ = false; |
| @@ -708,74 +848,29 @@ void Texture::Update(const FeatureInfo* feature_info) { |
| return; |
| } |
| - // checks that the first mip of any face is npot. |
| - for (size_t ii = 0; ii < level_infos_.size(); ++ii) { |
| - const Texture::LevelInfo& info = level_infos_[ii][0]; |
| - if (GLES2Util::IsNPOT(info.width) || |
| - GLES2Util::IsNPOT(info.height) || |
| - GLES2Util::IsNPOT(info.depth)) { |
| - npot_ = true; |
| - break; |
| - } |
| - } |
| - |
| // Update texture_complete and cube_complete status. |
| const Texture::LevelInfo& first_face = level_infos_[0][0]; |
| - int levels_needed = TextureManager::ComputeMipMapCount( |
| - target_, first_face.width, first_face.height, first_face.depth); |
| + int levels_needed = num_mip_levels_[0]; |
| texture_complete_ = |
| max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0; |
| cube_complete_ = (level_infos_.size() == 6) && |
| - (first_face.width == first_face.height); |
| + (first_face.width == first_face.height) && |
| + (num_complete_faces_ == 6); |
| if (first_face.width == 0 || first_face.height == 0) { |
| texture_complete_ = false; |
| - } |
| - if (first_face.type == GL_FLOAT && |
| - !feature_info->feature_flags().enable_texture_float_linear && |
| - (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || |
| - mag_filter_ != GL_NEAREST)) { |
| + } else if (first_face.type == GL_FLOAT && |
| + !feature_info->feature_flags().enable_texture_float_linear && |
| + (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || |
| + mag_filter_ != GL_NEAREST)) { |
| texture_complete_ = false; |
| } else if (first_face.type == GL_HALF_FLOAT_OES && |
| !feature_info->feature_flags().enable_texture_half_float_linear && |
| (min_filter_ != GL_NEAREST_MIPMAP_NEAREST || |
| mag_filter_ != GL_NEAREST)) { |
| texture_complete_ = false; |
| - } |
| - for (size_t ii = 0; |
| - ii < level_infos_.size() && (cube_complete_ || texture_complete_); |
| - ++ii) { |
| - const Texture::LevelInfo& level0 = level_infos_[ii][0]; |
| - if (level0.target == 0 || |
| - level0.width != first_face.width || |
| - level0.height != first_face.height || |
| - level0.depth != 1 || |
| - level0.internal_format != first_face.internal_format || |
| - level0.format != first_face.format || |
| - level0.type != first_face.type) { |
| - cube_complete_ = false; |
| - } |
| - // Get level0 dimensions |
| - GLsizei width = level0.width; |
| - GLsizei height = level0.height; |
| - GLsizei depth = level0.depth; |
| - for (GLint jj = 1; jj < levels_needed; ++jj) { |
| - // compute required size for mip. |
| - width = std::max(1, width >> 1); |
| - height = std::max(1, height >> 1); |
| - depth = std::max(1, depth >> 1); |
| - const Texture::LevelInfo& info = level_infos_[ii][jj]; |
| - if (info.target == 0 || |
| - info.width != width || |
| - info.height != height || |
| - info.depth != depth || |
| - info.internal_format != level0.internal_format || |
| - info.format != level0.format || |
| - info.type != level0.type) { |
| - texture_complete_ = false; |
| - break; |
| - } |
| - } |
| + } else if (num_incomplete_mips_ > 0) { |
| + texture_complete_ = false; |
| } |
| } |
| @@ -786,8 +881,7 @@ bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) { |
| } |
| const Texture::LevelInfo& first_face = level_infos_[0][0]; |
| - int levels_needed = TextureManager::ComputeMipMapCount( |
| - target_, first_face.width, first_face.height, first_face.depth); |
| + int levels_needed = num_mip_levels_[0]; |
| for (size_t ii = 0; ii < level_infos_.size(); ++ii) { |
| for (GLint jj = 0; jj < levels_needed; ++jj) { |