Home | History | Annotate | Download | only in service
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "gpu/command_buffer/service/texture_manager.h"
      6 #include "base/bits.h"
      7 #include "base/strings/stringprintf.h"
      8 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
      9 #include "gpu/command_buffer/service/error_state.h"
     10 #include "gpu/command_buffer/service/feature_info.h"
     11 #include "gpu/command_buffer/service/framebuffer_manager.h"
     12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
     13 #include "gpu/command_buffer/service/mailbox_manager.h"
     14 #include "gpu/command_buffer/service/memory_tracking.h"
     15 #include "gpu/command_buffer/service/stream_texture_manager.h"
     16 
     17 namespace gpu {
     18 namespace gles2 {
     19 
     20 static size_t GLTargetToFaceIndex(GLenum target) {
     21   switch (target) {
     22     case GL_TEXTURE_2D:
     23     case GL_TEXTURE_EXTERNAL_OES:
     24     case GL_TEXTURE_RECTANGLE_ARB:
     25       return 0;
     26     case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
     27       return 0;
     28     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
     29       return 1;
     30     case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
     31       return 2;
     32     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
     33       return 3;
     34     case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
     35       return 4;
     36     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
     37       return 5;
     38     default:
     39       NOTREACHED();
     40       return 0;
     41   }
     42 }
     43 
     44 static size_t FaceIndexToGLTarget(size_t index) {
     45   switch (index) {
     46     case 0:
     47       return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
     48     case 1:
     49       return GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
     50     case 2:
     51       return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
     52     case 3:
     53       return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
     54     case 4:
     55       return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
     56     case 5:
     57       return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
     58     default:
     59       NOTREACHED();
     60       return 0;
     61   }
     62 }
     63 
     64 TextureManager::DestructionObserver::DestructionObserver() {}
     65 
     66 TextureManager::DestructionObserver::~DestructionObserver() {}
     67 
     68 TextureManager::~TextureManager() {
     69   FOR_EACH_OBSERVER(DestructionObserver,
     70                     destruction_observers_,
     71                     OnTextureManagerDestroying(this));
     72 
     73   DCHECK(textures_.empty());
     74 
     75   // If this triggers, that means something is keeping a reference to
     76   // a Texture belonging to this.
     77   CHECK_EQ(texture_count_, 0u);
     78 
     79   DCHECK_EQ(0, num_unrenderable_textures_);
     80   DCHECK_EQ(0, num_unsafe_textures_);
     81   DCHECK_EQ(0, num_uncleared_mips_);
     82   DCHECK_EQ(0, num_images_);
     83 }
     84 
     85 void TextureManager::Destroy(bool have_context) {
     86   have_context_ = have_context;
     87   textures_.clear();
     88   for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
     89     default_textures_[ii] = NULL;
     90   }
     91 
     92   if (have_context) {
     93     glDeleteTextures(arraysize(black_texture_ids_), black_texture_ids_);
     94   }
     95 
     96   DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented());
     97   DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented());
     98 }
     99 
    100 Texture::Texture(GLuint service_id)
    101     : mailbox_manager_(NULL),
    102       memory_tracking_ref_(NULL),
    103       service_id_(service_id),
    104       cleared_(true),
    105       num_uncleared_mips_(0),
    106       target_(0),
    107       min_filter_(GL_NEAREST_MIPMAP_LINEAR),
    108       mag_filter_(GL_LINEAR),
    109       wrap_s_(GL_REPEAT),
    110       wrap_t_(GL_REPEAT),
    111       usage_(GL_NONE),
    112       pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM),
    113       max_level_set_(-1),
    114       texture_complete_(false),
    115       cube_complete_(false),
    116       npot_(false),
    117       has_been_bound_(false),
    118       framebuffer_attachment_count_(0),
    119       stream_texture_(false),
    120       immutable_(false),
    121       has_images_(false),
    122       estimated_size_(0),
    123       can_render_condition_(CAN_RENDER_ALWAYS) {
    124 }
    125 
    126 Texture::~Texture() {
    127   if (mailbox_manager_)
    128     mailbox_manager_->TextureDeleted(this);
    129 }
    130 
    131 void Texture::AddTextureRef(TextureRef* ref) {
    132   DCHECK(refs_.find(ref) == refs_.end());
    133   refs_.insert(ref);
    134   if (!memory_tracking_ref_) {
    135     memory_tracking_ref_ = ref;
    136     GetMemTracker()->TrackMemAlloc(estimated_size());
    137   }
    138 }
    139 
    140 void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) {
    141   if (memory_tracking_ref_ == ref) {
    142     GetMemTracker()->TrackMemFree(estimated_size());
    143     memory_tracking_ref_ = NULL;
    144   }
    145   size_t result = refs_.erase(ref);
    146   DCHECK_EQ(result, 1u);
    147   if (refs_.empty()) {
    148     if (have_context) {
    149       GLuint id = service_id();
    150       glDeleteTextures(1, &id);
    151     }
    152     delete this;
    153   } else if (memory_tracking_ref_ == NULL) {
    154     // TODO(piman): tune ownership semantics for cross-context group shared
    155     // textures.
    156     memory_tracking_ref_ = *refs_.begin();
    157     GetMemTracker()->TrackMemAlloc(estimated_size());
    158   }
    159 }
    160 
    161 MemoryTypeTracker* Texture::GetMemTracker() {
    162   DCHECK(memory_tracking_ref_);
    163   return memory_tracking_ref_->manager()->GetMemTracker(pool_);
    164 }
    165 
    166 Texture::LevelInfo::LevelInfo()
    167     : cleared(true),
    168       target(0),
    169       level(-1),
    170       internal_format(0),
    171       width(0),
    172       height(0),
    173       depth(0),
    174       border(0),
    175       format(0),
    176       type(0),
    177       estimated_size(0) {
    178 }
    179 
    180 Texture::LevelInfo::LevelInfo(const LevelInfo& rhs)
    181     : cleared(rhs.cleared),
    182       target(rhs.target),
    183       level(rhs.level),
    184       internal_format(rhs.internal_format),
    185       width(rhs.width),
    186       height(rhs.height),
    187       depth(rhs.depth),
    188       border(rhs.border),
    189       format(rhs.format),
    190       type(rhs.type),
    191       image(rhs.image),
    192       estimated_size(rhs.estimated_size) {
    193 }
    194 
    195 Texture::LevelInfo::~LevelInfo() {
    196 }
    197 
    198 Texture::CanRenderCondition Texture::GetCanRenderCondition() const {
    199   if (target_ == 0)
    200     return CAN_RENDER_ALWAYS;
    201 
    202   if (target_ == GL_TEXTURE_EXTERNAL_OES) {
    203     if (!IsStreamTexture()) {
    204       return CAN_RENDER_NEVER;
    205     }
    206   } else {
    207     if (level_infos_.empty()) {
    208       return CAN_RENDER_NEVER;
    209     }
    210 
    211     const Texture::LevelInfo& first_face = level_infos_[0][0];
    212     if (first_face.width == 0 ||
    213         first_face.height == 0 ||
    214         first_face.depth == 0) {
    215       return CAN_RENDER_NEVER;
    216     }
    217   }
    218 
    219   bool needs_mips = NeedsMips();
    220   if (needs_mips) {
    221     if (!texture_complete())
    222       return CAN_RENDER_NEVER;
    223     if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete())
    224       return CAN_RENDER_NEVER;
    225   }
    226 
    227   bool is_npot_compatible = !needs_mips &&
    228       wrap_s_ == GL_CLAMP_TO_EDGE &&
    229       wrap_t_ == GL_CLAMP_TO_EDGE;
    230 
    231   if (!is_npot_compatible) {
    232     if (target_ == GL_TEXTURE_RECTANGLE_ARB)
    233       return CAN_RENDER_NEVER;
    234     else if (npot())
    235       return CAN_RENDER_ONLY_IF_NPOT;
    236   }
    237 
    238   return CAN_RENDER_ALWAYS;
    239 }
    240 
    241 bool Texture::CanRender(const FeatureInfo* feature_info) const {
    242   switch (can_render_condition_) {
    243     case CAN_RENDER_ALWAYS:
    244       return true;
    245     case CAN_RENDER_NEVER:
    246       return false;
    247     case CAN_RENDER_ONLY_IF_NPOT:
    248       break;
    249   }
    250   return feature_info->feature_flags().npot_ok;
    251 }
    252 
    253 void Texture::AddToSignature(
    254     const FeatureInfo* feature_info,
    255     GLenum target,
    256     GLint level,
    257     std::string* signature) const {
    258   DCHECK(feature_info);
    259   DCHECK(signature);
    260   DCHECK_GE(level, 0);
    261   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
    262             level_infos_.size());
    263   DCHECK_LT(static_cast<size_t>(level),
    264             level_infos_[GLTargetToFaceIndex(target)].size());
    265   const Texture::LevelInfo& info =
    266       level_infos_[GLTargetToFaceIndex(target)][level];
    267   *signature += base::StringPrintf(
    268       "|Texture|target=%04x|level=%d|internal_format=%04x"
    269       "|width=%d|height=%d|depth=%d|border=%d|format=%04x|type=%04x"
    270       "|image=%d|canrender=%d|canrenderto=%d|npot_=%d"
    271       "|min_filter=%04x|mag_filter=%04x|wrap_s=%04x|wrap_t=%04x"
    272       "|usage=%04x",
    273       target, level, info.internal_format,
    274       info.width, info.height, info.depth, info.border,
    275       info.format, info.type, info.image.get() != NULL,
    276       CanRender(feature_info), CanRenderTo(), npot_,
    277       min_filter_, mag_filter_, wrap_s_, wrap_t_,
    278       usage_);
    279 }
    280 
    281 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) {
    282   DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager);
    283   mailbox_manager_ = mailbox_manager;
    284 }
    285 
    286 bool Texture::MarkMipmapsGenerated(
    287     const FeatureInfo* feature_info) {
    288   if (!CanGenerateMipmaps(feature_info)) {
    289     return false;
    290   }
    291   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    292     const Texture::LevelInfo& info1 = level_infos_[ii][0];
    293     GLsizei width = info1.width;
    294     GLsizei height = info1.height;
    295     GLsizei depth = info1.depth;
    296     GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D :
    297                                FaceIndexToGLTarget(ii);
    298     int num_mips = TextureManager::ComputeMipMapCount(width, height, depth);
    299     for (int level = 1; level < num_mips; ++level) {
    300       width = std::max(1, width >> 1);
    301       height = std::max(1, height >> 1);
    302       depth = std::max(1, depth >> 1);
    303       SetLevelInfo(feature_info,
    304                    target,
    305                    level,
    306                    info1.internal_format,
    307                    width,
    308                    height,
    309                    depth,
    310                    info1.border,
    311                    info1.format,
    312                    info1.type,
    313                    true);
    314     }
    315   }
    316 
    317   return true;
    318 }
    319 
    320 void Texture::SetTarget(
    321     const FeatureInfo* feature_info, GLenum target, GLint max_levels) {
    322   DCHECK_EQ(0u, target_);  // you can only set this once.
    323   target_ = target;
    324   size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
    325   level_infos_.resize(num_faces);
    326   for (size_t ii = 0; ii < num_faces; ++ii) {
    327     level_infos_[ii].resize(max_levels);
    328   }
    329 
    330   if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) {
    331     min_filter_ = GL_LINEAR;
    332     wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE;
    333   }
    334 
    335   if (target == GL_TEXTURE_EXTERNAL_OES) {
    336     immutable_ = true;
    337   }
    338   Update(feature_info);
    339   UpdateCanRenderCondition();
    340 }
    341 
    342 bool Texture::CanGenerateMipmaps(
    343     const FeatureInfo* feature_info) const {
    344   if ((npot() && !feature_info->feature_flags().npot_ok) ||
    345       level_infos_.empty() ||
    346       target_ == GL_TEXTURE_EXTERNAL_OES ||
    347       target_ == GL_TEXTURE_RECTANGLE_ARB) {
    348     return false;
    349   }
    350 
    351   // Can't generate mips for depth or stencil textures.
    352   const Texture::LevelInfo& first = level_infos_[0][0];
    353   uint32 channels = GLES2Util::GetChannelsForFormat(first.format);
    354   if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) {
    355     return false;
    356   }
    357 
    358   // TODO(gman): Check internal_format, format and type.
    359   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    360     const LevelInfo& info = level_infos_[ii][0];
    361     if ((info.target == 0) || (info.width != first.width) ||
    362         (info.height != first.height) || (info.depth != 1) ||
    363         (info.format != first.format) ||
    364         (info.internal_format != first.internal_format) ||
    365         (info.type != first.type) ||
    366         feature_info->validators()->compressed_texture_format.IsValid(
    367             info.internal_format) ||
    368         info.image.get()) {
    369       return false;
    370     }
    371   }
    372   return true;
    373 }
    374 
    375 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) {
    376   DCHECK_GE(level, 0);
    377   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
    378             level_infos_.size());
    379   DCHECK_LT(static_cast<size_t>(level),
    380             level_infos_[GLTargetToFaceIndex(target)].size());
    381   Texture::LevelInfo& info =
    382       level_infos_[GLTargetToFaceIndex(target)][level];
    383   UpdateMipCleared(&info, cleared);
    384   UpdateCleared();
    385 }
    386 
    387 void Texture::UpdateCleared() {
    388   if (level_infos_.empty()) {
    389     return;
    390   }
    391 
    392   const Texture::LevelInfo& first_face = level_infos_[0][0];
    393   int levels_needed = TextureManager::ComputeMipMapCount(
    394       first_face.width, first_face.height, first_face.depth);
    395   bool cleared = true;
    396   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    397     for (GLint jj = 0; jj < levels_needed; ++jj) {
    398       const Texture::LevelInfo& info = level_infos_[ii][jj];
    399       if (info.width > 0 && info.height > 0 && info.depth > 0 &&
    400           !info.cleared) {
    401         cleared = false;
    402         break;
    403       }
    404     }
    405   }
    406   UpdateSafeToRenderFrom(cleared);
    407 }
    408 
    409 void Texture::UpdateSafeToRenderFrom(bool cleared) {
    410   if (cleared_ == cleared)
    411     return;
    412   cleared_ = cleared;
    413   int delta = cleared ? -1 : +1;
    414   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    415     (*it)->manager()->UpdateSafeToRenderFrom(delta);
    416 }
    417 
    418 void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) {
    419   if (info->cleared == cleared)
    420     return;
    421   info->cleared = cleared;
    422   int delta = cleared ? -1 : +1;
    423   num_uncleared_mips_ += delta;
    424   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    425     (*it)->manager()->UpdateUnclearedMips(delta);
    426 }
    427 
    428 void Texture::UpdateCanRenderCondition() {
    429   CanRenderCondition can_render_condition = GetCanRenderCondition();
    430   if (can_render_condition_ == can_render_condition)
    431     return;
    432   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    433     (*it)->manager()->UpdateCanRenderCondition(can_render_condition_,
    434                                                can_render_condition);
    435   can_render_condition_ = can_render_condition;
    436 }
    437 
    438 void Texture::UpdateHasImages() {
    439   if (level_infos_.empty())
    440     return;
    441 
    442   bool has_images = false;
    443   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    444     for (size_t jj = 0; jj < level_infos_[ii].size(); ++jj) {
    445       const Texture::LevelInfo& info = level_infos_[ii][jj];
    446       if (info.image.get() != NULL) {
    447         has_images = true;
    448         break;
    449       }
    450     }
    451   }
    452 
    453   if (has_images_ == has_images)
    454     return;
    455   has_images_ = has_images;
    456   int delta = has_images ? +1 : -1;
    457   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    458     (*it)->manager()->UpdateNumImages(delta);
    459 }
    460 
    461 void Texture::IncAllFramebufferStateChangeCount() {
    462   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    463     (*it)->manager()->IncFramebufferStateChangeCount();
    464 }
    465 
    466 void Texture::SetLevelInfo(
    467     const FeatureInfo* feature_info,
    468     GLenum target,
    469     GLint level,
    470     GLenum internal_format,
    471     GLsizei width,
    472     GLsizei height,
    473     GLsizei depth,
    474     GLint border,
    475     GLenum format,
    476     GLenum type,
    477     bool cleared) {
    478   DCHECK_GE(level, 0);
    479   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
    480             level_infos_.size());
    481   DCHECK_LT(static_cast<size_t>(level),
    482             level_infos_[GLTargetToFaceIndex(target)].size());
    483   DCHECK_GE(width, 0);
    484   DCHECK_GE(height, 0);
    485   DCHECK_GE(depth, 0);
    486   Texture::LevelInfo& info =
    487       level_infos_[GLTargetToFaceIndex(target)][level];
    488   info.target = target;
    489   info.level = level;
    490   info.internal_format = internal_format;
    491   info.width = width;
    492   info.height = height;
    493   info.depth = depth;
    494   info.border = border;
    495   info.format = format;
    496   info.type = type;
    497   info.image = 0;
    498 
    499   estimated_size_ -= info.estimated_size;
    500   GLES2Util::ComputeImageDataSizes(
    501       width, height, format, type, 4, &info.estimated_size, NULL, NULL);
    502   estimated_size_ += info.estimated_size;
    503 
    504   UpdateMipCleared(&info, cleared);
    505   max_level_set_ = std::max(max_level_set_, level);
    506   Update(feature_info);
    507   UpdateCleared();
    508   UpdateCanRenderCondition();
    509   UpdateHasImages();
    510   if (IsAttachedToFramebuffer()) {
    511     // TODO(gman): If textures tracked which framebuffers they were attached to
    512     // we could just mark those framebuffers as not complete.
    513     IncAllFramebufferStateChangeCount();
    514   }
    515 }
    516 
    517 bool Texture::ValidForTexture(
    518     GLint target,
    519     GLint level,
    520     GLint xoffset,
    521     GLint yoffset,
    522     GLsizei width,
    523     GLsizei height,
    524     GLenum format,
    525     GLenum type) const {
    526   size_t face_index = GLTargetToFaceIndex(target);
    527   if (level >= 0 && face_index < level_infos_.size() &&
    528       static_cast<size_t>(level) < level_infos_[face_index].size()) {
    529     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
    530     int32 right;
    531     int32 top;
    532     return SafeAddInt32(xoffset, width, &right) &&
    533            SafeAddInt32(yoffset, height, &top) &&
    534            xoffset >= 0 &&
    535            yoffset >= 0 &&
    536            right <= info.width &&
    537            top <= info.height &&
    538            format == info.internal_format &&
    539            type == info.type;
    540   }
    541   return false;
    542 }
    543 
    544 bool Texture::GetLevelSize(
    545     GLint target, GLint level, GLsizei* width, GLsizei* height) const {
    546   DCHECK(width);
    547   DCHECK(height);
    548   size_t face_index = GLTargetToFaceIndex(target);
    549   if (level >= 0 && face_index < level_infos_.size() &&
    550       static_cast<size_t>(level) < level_infos_[face_index].size()) {
    551     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
    552     if (info.target != 0) {
    553       *width = info.width;
    554       *height = info.height;
    555       return true;
    556     }
    557   }
    558   return false;
    559 }
    560 
    561 bool Texture::GetLevelType(
    562     GLint target, GLint level, GLenum* type, GLenum* internal_format) const {
    563   DCHECK(type);
    564   DCHECK(internal_format);
    565   size_t face_index = GLTargetToFaceIndex(target);
    566   if (level >= 0 && face_index < level_infos_.size() &&
    567       static_cast<size_t>(level) < level_infos_[face_index].size()) {
    568     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
    569     if (info.target != 0) {
    570       *type = info.type;
    571       *internal_format = info.internal_format;
    572       return true;
    573     }
    574   }
    575   return false;
    576 }
    577 
    578 GLenum Texture::SetParameter(
    579     const FeatureInfo* feature_info, GLenum pname, GLint param) {
    580   DCHECK(feature_info);
    581 
    582   if (target_ == GL_TEXTURE_EXTERNAL_OES ||
    583       target_ == GL_TEXTURE_RECTANGLE_ARB) {
    584     if (pname == GL_TEXTURE_MIN_FILTER &&
    585         (param != GL_NEAREST && param != GL_LINEAR))
    586       return GL_INVALID_ENUM;
    587     if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
    588         param != GL_CLAMP_TO_EDGE)
    589       return GL_INVALID_ENUM;
    590   }
    591 
    592   switch (pname) {
    593     case GL_TEXTURE_MIN_FILTER:
    594       if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) {
    595         return GL_INVALID_ENUM;
    596       }
    597       min_filter_ = param;
    598       break;
    599     case GL_TEXTURE_MAG_FILTER:
    600       if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) {
    601         return GL_INVALID_ENUM;
    602       }
    603       mag_filter_ = param;
    604       break;
    605     case GL_TEXTURE_POOL_CHROMIUM:
    606       if (!feature_info->validators()->texture_pool.IsValid(param)) {
    607         return GL_INVALID_ENUM;
    608       }
    609       GetMemTracker()->TrackMemFree(estimated_size());
    610       pool_ = param;
    611       GetMemTracker()->TrackMemAlloc(estimated_size());
    612       break;
    613     case GL_TEXTURE_WRAP_S:
    614       if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
    615         return GL_INVALID_ENUM;
    616       }
    617       wrap_s_ = param;
    618       break;
    619     case GL_TEXTURE_WRAP_T:
    620       if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
    621         return GL_INVALID_ENUM;
    622       }
    623       wrap_t_ = param;
    624       break;
    625     case GL_TEXTURE_MAX_ANISOTROPY_EXT:
    626       if (param < 1) {
    627         return GL_INVALID_VALUE;
    628       }
    629       break;
    630     case GL_TEXTURE_USAGE_ANGLE:
    631       if (!feature_info->validators()->texture_usage.IsValid(param)) {
    632         return GL_INVALID_ENUM;
    633       }
    634       usage_ = param;
    635       break;
    636     default:
    637       NOTREACHED();
    638       return GL_INVALID_ENUM;
    639   }
    640   Update(feature_info);
    641   UpdateCleared();
    642   UpdateCanRenderCondition();
    643   return GL_NO_ERROR;
    644 }
    645 
    646 void Texture::Update(const FeatureInfo* feature_info) {
    647   // Update npot status.
    648   // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
    649   npot_ = target_ == GL_TEXTURE_EXTERNAL_OES;
    650 
    651   if (level_infos_.empty()) {
    652     texture_complete_ = false;
    653     cube_complete_ = false;
    654     return;
    655   }
    656 
    657   // checks that the first mip of any face is npot.
    658   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    659     const Texture::LevelInfo& info = level_infos_[ii][0];
    660     if (GLES2Util::IsNPOT(info.width) ||
    661         GLES2Util::IsNPOT(info.height) ||
    662         GLES2Util::IsNPOT(info.depth)) {
    663       npot_ = true;
    664       break;
    665     }
    666   }
    667 
    668   // Update texture_complete and cube_complete status.
    669   const Texture::LevelInfo& first_face = level_infos_[0][0];
    670   int levels_needed = TextureManager::ComputeMipMapCount(
    671       first_face.width, first_face.height, first_face.depth);
    672   texture_complete_ =
    673       max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0;
    674   cube_complete_ = (level_infos_.size() == 6) &&
    675                    (first_face.width == first_face.height);
    676 
    677   if (first_face.width == 0 || first_face.height == 0) {
    678     texture_complete_ = false;
    679   }
    680   if (first_face.type == GL_FLOAT &&
    681       !feature_info->feature_flags().enable_texture_float_linear &&
    682       (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
    683        mag_filter_ != GL_NEAREST)) {
    684     texture_complete_ = false;
    685   } else if (first_face.type == GL_HALF_FLOAT_OES &&
    686              !feature_info->feature_flags().enable_texture_half_float_linear &&
    687              (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
    688               mag_filter_ != GL_NEAREST)) {
    689     texture_complete_ = false;
    690   }
    691   for (size_t ii = 0;
    692        ii < level_infos_.size() && (cube_complete_ || texture_complete_);
    693        ++ii) {
    694     const Texture::LevelInfo& level0 = level_infos_[ii][0];
    695     if (level0.target == 0 ||
    696         level0.width != first_face.width ||
    697         level0.height != first_face.height ||
    698         level0.depth != 1 ||
    699         level0.internal_format != first_face.internal_format ||
    700         level0.format != first_face.format ||
    701         level0.type != first_face.type) {
    702       cube_complete_ = false;
    703     }
    704     // Get level0 dimensions
    705     GLsizei width = level0.width;
    706     GLsizei height = level0.height;
    707     GLsizei depth = level0.depth;
    708     for (GLint jj = 1; jj < levels_needed; ++jj) {
    709       // compute required size for mip.
    710       width = std::max(1, width >> 1);
    711       height = std::max(1, height >> 1);
    712       depth = std::max(1, depth >> 1);
    713       const Texture::LevelInfo& info = level_infos_[ii][jj];
    714       if (info.target == 0 ||
    715           info.width != width ||
    716           info.height != height ||
    717           info.depth != depth ||
    718           info.internal_format != level0.internal_format ||
    719           info.format != level0.format ||
    720           info.type != level0.type) {
    721         texture_complete_ = false;
    722         break;
    723       }
    724     }
    725   }
    726 }
    727 
    728 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
    729   DCHECK(decoder);
    730   if (cleared_) {
    731     return true;
    732   }
    733 
    734   const Texture::LevelInfo& first_face = level_infos_[0][0];
    735   int levels_needed = TextureManager::ComputeMipMapCount(
    736       first_face.width, first_face.height, first_face.depth);
    737 
    738   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    739     for (GLint jj = 0; jj < levels_needed; ++jj) {
    740       Texture::LevelInfo& info = level_infos_[ii][jj];
    741       if (info.target != 0) {
    742         if (!ClearLevel(decoder, info.target, jj)) {
    743           return false;
    744         }
    745       }
    746     }
    747   }
    748   UpdateSafeToRenderFrom(true);
    749   return true;
    750 }
    751 
    752 bool Texture::IsLevelCleared(GLenum target, GLint level) const {
    753   size_t face_index = GLTargetToFaceIndex(target);
    754   if (face_index >= level_infos_.size() ||
    755       level >= static_cast<GLint>(level_infos_[face_index].size())) {
    756     return true;
    757   }
    758 
    759   const Texture::LevelInfo& info = level_infos_[face_index][level];
    760 
    761   return info.cleared;
    762 }
    763 
    764 bool Texture::ClearLevel(
    765     GLES2Decoder* decoder, GLenum target, GLint level) {
    766   DCHECK(decoder);
    767   size_t face_index = GLTargetToFaceIndex(target);
    768   if (face_index >= level_infos_.size() ||
    769       level >= static_cast<GLint>(level_infos_[face_index].size())) {
    770     return true;
    771   }
    772 
    773   Texture::LevelInfo& info = level_infos_[face_index][level];
    774 
    775   DCHECK(target == info.target);
    776 
    777   if (info.target == 0 ||
    778       info.cleared ||
    779       info.width == 0 ||
    780       info.height == 0 ||
    781       info.depth == 0) {
    782     return true;
    783   }
    784 
    785   // NOTE: It seems kind of gross to call back into the decoder for this
    786   // but only the decoder knows all the state (like unpack_alignment_) that's
    787   // needed to be able to call GL correctly.
    788   bool cleared = decoder->ClearLevel(
    789       service_id_, target_, info.target, info.level, info.format, info.type,
    790       info.width, info.height, immutable_);
    791   UpdateMipCleared(&info, cleared);
    792   return info.cleared;
    793 }
    794 
    795 void Texture::SetLevelImage(
    796     const FeatureInfo* feature_info,
    797     GLenum target,
    798     GLint level,
    799     gfx::GLImage* image) {
    800   DCHECK_GE(level, 0);
    801   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
    802             level_infos_.size());
    803   DCHECK_LT(static_cast<size_t>(level),
    804             level_infos_[GLTargetToFaceIndex(target)].size());
    805   Texture::LevelInfo& info =
    806       level_infos_[GLTargetToFaceIndex(target)][level];
    807   DCHECK_EQ(info.target, target);
    808   DCHECK_EQ(info.level, level);
    809   info.image = image;
    810   UpdateCanRenderCondition();
    811   UpdateHasImages();
    812 }
    813 
    814 gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const {
    815   size_t face_index = GLTargetToFaceIndex(target);
    816   if (level >= 0 && face_index < level_infos_.size() &&
    817       static_cast<size_t>(level) < level_infos_[face_index].size()) {
    818     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
    819     if (info.target != 0) {
    820       return info.image.get();
    821     }
    822   }
    823   return 0;
    824 }
    825 
    826 
    827 TextureRef::TextureRef(TextureManager* manager,
    828                        GLuint client_id,
    829                        Texture* texture)
    830     : manager_(manager),
    831       texture_(texture),
    832       client_id_(client_id),
    833       is_stream_texture_owner_(false) {
    834   DCHECK(manager_);
    835   DCHECK(texture_);
    836   texture_->AddTextureRef(this);
    837   manager_->StartTracking(this);
    838 }
    839 
    840 scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager,
    841                                              GLuint client_id,
    842                                              GLuint service_id) {
    843   return new TextureRef(manager, client_id, new Texture(service_id));
    844 }
    845 
    846 TextureRef::~TextureRef() {
    847   manager_->StopTracking(this);
    848   texture_->RemoveTextureRef(this, manager_->have_context_);
    849   manager_ = NULL;
    850 }
    851 
    852 TextureManager::TextureManager(
    853     MemoryTracker* memory_tracker,
    854     FeatureInfo* feature_info,
    855     GLint max_texture_size,
    856     GLint max_cube_map_texture_size)
    857     : memory_tracker_managed_(
    858           new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)),
    859       memory_tracker_unmanaged_(
    860           new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)),
    861       feature_info_(feature_info),
    862       framebuffer_manager_(NULL),
    863       stream_texture_manager_(NULL),
    864       max_texture_size_(max_texture_size),
    865       max_cube_map_texture_size_(max_cube_map_texture_size),
    866       max_levels_(ComputeMipMapCount(max_texture_size,
    867                                      max_texture_size,
    868                                      max_texture_size)),
    869       max_cube_map_levels_(ComputeMipMapCount(max_cube_map_texture_size,
    870                                               max_cube_map_texture_size,
    871                                               max_cube_map_texture_size)),
    872       num_unrenderable_textures_(0),
    873       num_unsafe_textures_(0),
    874       num_uncleared_mips_(0),
    875       num_images_(0),
    876       texture_count_(0),
    877       have_context_(true) {
    878   for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
    879     black_texture_ids_[ii] = 0;
    880   }
    881 }
    882 
    883 bool TextureManager::Initialize() {
    884   // TODO(gman): The default textures have to be real textures, not the 0
    885   // texture because we simulate non shared resources on top of shared
    886   // resources and all contexts that share resource share the same default
    887   // texture.
    888   default_textures_[kTexture2D] = CreateDefaultAndBlackTextures(
    889       GL_TEXTURE_2D, &black_texture_ids_[kTexture2D]);
    890   default_textures_[kCubeMap] = CreateDefaultAndBlackTextures(
    891       GL_TEXTURE_CUBE_MAP, &black_texture_ids_[kCubeMap]);
    892 
    893   if (feature_info_->feature_flags().oes_egl_image_external) {
    894     default_textures_[kExternalOES] = CreateDefaultAndBlackTextures(
    895         GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]);
    896   }
    897 
    898   if (feature_info_->feature_flags().arb_texture_rectangle) {
    899     default_textures_[kRectangleARB] = CreateDefaultAndBlackTextures(
    900         GL_TEXTURE_RECTANGLE_ARB, &black_texture_ids_[kRectangleARB]);
    901   }
    902 
    903   return true;
    904 }
    905 
    906 scoped_refptr<TextureRef>
    907     TextureManager::CreateDefaultAndBlackTextures(
    908         GLenum target,
    909         GLuint* black_texture) {
    910   static uint8 black[] = {0, 0, 0, 255};
    911 
    912   // Sampling a texture not associated with any EGLImage sibling will return
    913   // black values according to the spec.
    914   bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES);
    915   bool needs_faces = (target == GL_TEXTURE_CUBE_MAP);
    916 
    917   // Make default textures and texture for replacing non-renderable textures.
    918   GLuint ids[2];
    919   glGenTextures(arraysize(ids), ids);
    920   for (unsigned long ii = 0; ii < arraysize(ids); ++ii) {
    921     glBindTexture(target, ids[ii]);
    922     if (needs_initialization) {
    923       if (needs_faces) {
    924         for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) {
    925           glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0,
    926                        GL_RGBA, GL_UNSIGNED_BYTE, black);
    927         }
    928       } else {
    929         glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
    930                      GL_UNSIGNED_BYTE, black);
    931       }
    932     }
    933   }
    934   glBindTexture(target, 0);
    935 
    936   scoped_refptr<TextureRef> default_texture(
    937       TextureRef::Create(this, 0, ids[1]));
    938   SetTarget(default_texture.get(), target);
    939   if (needs_faces) {
    940     for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
    941       SetLevelInfo(default_texture.get(),
    942                    GLES2Util::IndexToGLFaceTarget(ii),
    943                    0,
    944                    GL_RGBA,
    945                    1,
    946                    1,
    947                    1,
    948                    0,
    949                    GL_RGBA,
    950                    GL_UNSIGNED_BYTE,
    951                    true);
    952     }
    953   } else {
    954     if (needs_initialization) {
    955       SetLevelInfo(default_texture.get(),
    956                    GL_TEXTURE_2D,
    957                    0,
    958                    GL_RGBA,
    959                    1,
    960                    1,
    961                    1,
    962                    0,
    963                    GL_RGBA,
    964                    GL_UNSIGNED_BYTE,
    965                    true);
    966     } else {
    967       SetLevelInfo(default_texture.get(),
    968                    GL_TEXTURE_EXTERNAL_OES,
    969                    0,
    970                    GL_RGBA,
    971                    1,
    972                    1,
    973                    1,
    974                    0,
    975                    GL_RGBA,
    976                    GL_UNSIGNED_BYTE,
    977                    true);
    978     }
    979   }
    980 
    981   *black_texture = ids[0];
    982   return default_texture;
    983 }
    984 
    985 bool TextureManager::ValidForTarget(
    986     GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) {
    987   GLsizei max_size = MaxSizeForTarget(target) >> level;
    988   return level >= 0 &&
    989          width >= 0 &&
    990          height >= 0 &&
    991          depth >= 0 &&
    992          level < MaxLevelsForTarget(target) &&
    993          width <= max_size &&
    994          height <= max_size &&
    995          depth <= max_size &&
    996          (level == 0 || feature_info_->feature_flags().npot_ok ||
    997           (!GLES2Util::IsNPOT(width) &&
    998            !GLES2Util::IsNPOT(height) &&
    999            !GLES2Util::IsNPOT(depth))) &&
   1000          (target != GL_TEXTURE_CUBE_MAP || (width == height && depth == 1)) &&
   1001          (target != GL_TEXTURE_2D || (depth == 1));
   1002 }
   1003 
   1004 void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
   1005   DCHECK(ref);
   1006   ref->texture()
   1007       ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target));
   1008 }
   1009 
   1010 void TextureManager::SetStreamTexture(TextureRef* ref, bool stream_texture) {
   1011   DCHECK(ref);
   1012   // Only the owner can mark as non-stream texture.
   1013   DCHECK_EQ(stream_texture, !ref->is_stream_texture_owner_);
   1014   ref->texture()->SetStreamTexture(stream_texture);
   1015   ref->set_is_stream_texture_owner(stream_texture);
   1016 }
   1017 
   1018 bool TextureManager::IsStreamTextureOwner(TextureRef* ref) {
   1019   DCHECK(ref);
   1020   return ref->is_stream_texture_owner();
   1021 }
   1022 
   1023 void TextureManager::SetLevelCleared(TextureRef* ref,
   1024                                      GLenum target,
   1025                                      GLint level,
   1026                                      bool cleared) {
   1027   DCHECK(ref);
   1028   ref->texture()->SetLevelCleared(target, level, cleared);
   1029 }
   1030 
   1031 bool TextureManager::ClearRenderableLevels(
   1032     GLES2Decoder* decoder, TextureRef* ref) {
   1033   DCHECK(ref);
   1034   return ref->texture()->ClearRenderableLevels(decoder);
   1035 }
   1036 
   1037 bool TextureManager::ClearTextureLevel(
   1038     GLES2Decoder* decoder, TextureRef* ref,
   1039     GLenum target, GLint level) {
   1040   DCHECK(ref);
   1041   Texture* texture = ref->texture();
   1042   if (texture->num_uncleared_mips() == 0) {
   1043     return true;
   1044   }
   1045   bool result = texture->ClearLevel(decoder, target, level);
   1046   texture->UpdateCleared();
   1047   return result;
   1048 }
   1049 
   1050 void TextureManager::SetLevelInfo(
   1051     TextureRef* ref,
   1052     GLenum target,
   1053     GLint level,
   1054     GLenum internal_format,
   1055     GLsizei width,
   1056     GLsizei height,
   1057     GLsizei depth,
   1058     GLint border,
   1059     GLenum format,
   1060     GLenum type,
   1061     bool cleared) {
   1062   DCHECK(ref);
   1063   Texture* texture = ref->texture();
   1064 
   1065   texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
   1066   texture->SetLevelInfo(feature_info_.get(),
   1067                         target,
   1068                         level,
   1069                         internal_format,
   1070                         width,
   1071                         height,
   1072                         depth,
   1073                         border,
   1074                         format,
   1075                         type,
   1076                         cleared);
   1077   texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
   1078 }
   1079 
   1080 Texture* TextureManager::Produce(TextureRef* ref) {
   1081   DCHECK(ref);
   1082   return ref->texture();
   1083 }
   1084 
   1085 TextureRef* TextureManager::Consume(
   1086     GLuint client_id,
   1087     Texture* texture) {
   1088   DCHECK(client_id);
   1089   scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture));
   1090   bool result = textures_.insert(std::make_pair(client_id, ref)).second;
   1091   DCHECK(result);
   1092   return ref.get();
   1093 }
   1094 
   1095 void TextureManager::SetParameter(
   1096     const char* function_name, ErrorState* error_state,
   1097     TextureRef* ref, GLenum pname, GLint param) {
   1098   DCHECK(error_state);
   1099   DCHECK(ref);
   1100   Texture* texture = ref->texture();
   1101   GLenum result = texture->SetParameter(feature_info_.get(), pname, param);
   1102   if (result != GL_NO_ERROR) {
   1103     if (result == GL_INVALID_ENUM) {
   1104       ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
   1105           error_state, function_name, param, "param");
   1106     } else {
   1107       ERRORSTATE_SET_GL_ERROR_INVALID_PARAM(
   1108           error_state, result, function_name, pname, static_cast<GLint>(param));
   1109     }
   1110   } else {
   1111     // Texture tracking pools exist only for the command decoder, so
   1112     // do not pass them on to the native GL implementation.
   1113     if (pname != GL_TEXTURE_POOL_CHROMIUM) {
   1114       glTexParameteri(texture->target(), pname, param);
   1115     }
   1116   }
   1117 }
   1118 
   1119 bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) {
   1120   DCHECK(ref);
   1121   Texture* texture = ref->texture();
   1122   texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
   1123   bool result = texture->MarkMipmapsGenerated(feature_info_.get());
   1124   texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
   1125   return result;
   1126 }
   1127 
   1128 TextureRef* TextureManager::CreateTexture(
   1129     GLuint client_id, GLuint service_id) {
   1130   DCHECK_NE(0u, service_id);
   1131   scoped_refptr<TextureRef> ref(TextureRef::Create(
   1132       this, client_id, service_id));
   1133   std::pair<TextureMap::iterator, bool> result =
   1134       textures_.insert(std::make_pair(client_id, ref));
   1135   DCHECK(result.second);
   1136   return ref.get();
   1137 }
   1138 
   1139 TextureRef* TextureManager::GetTexture(
   1140     GLuint client_id) const {
   1141   TextureMap::const_iterator it = textures_.find(client_id);
   1142   return it != textures_.end() ? it->second.get() : NULL;
   1143 }
   1144 
   1145 void TextureManager::RemoveTexture(GLuint client_id) {
   1146   TextureMap::iterator it = textures_.find(client_id);
   1147   if (it != textures_.end()) {
   1148     it->second->reset_client_id();
   1149     textures_.erase(it);
   1150   }
   1151 }
   1152 
   1153 void TextureManager::StartTracking(TextureRef* ref) {
   1154   Texture* texture = ref->texture();
   1155   ++texture_count_;
   1156   num_uncleared_mips_ += texture->num_uncleared_mips();
   1157   if (!texture->SafeToRenderFrom())
   1158     ++num_unsafe_textures_;
   1159   if (!texture->CanRender(feature_info_.get()))
   1160     ++num_unrenderable_textures_;
   1161   if (texture->HasImages())
   1162     ++num_images_;
   1163 }
   1164 
   1165 void TextureManager::StopTracking(TextureRef* ref) {
   1166   FOR_EACH_OBSERVER(DestructionObserver,
   1167                     destruction_observers_,
   1168                     OnTextureRefDestroying(ref));
   1169 
   1170   Texture* texture = ref->texture();
   1171   if (ref->is_stream_texture_owner_ && stream_texture_manager_) {
   1172     DCHECK(texture->IsStreamTexture());
   1173     stream_texture_manager_->DestroyStreamTexture(texture->service_id());
   1174   }
   1175 
   1176   --texture_count_;
   1177   if (texture->HasImages()) {
   1178     DCHECK_NE(0, num_images_);
   1179     --num_images_;
   1180   }
   1181   if (!texture->CanRender(feature_info_.get())) {
   1182     DCHECK_NE(0, num_unrenderable_textures_);
   1183     --num_unrenderable_textures_;
   1184   }
   1185   if (!texture->SafeToRenderFrom()) {
   1186     DCHECK_NE(0, num_unsafe_textures_);
   1187     --num_unsafe_textures_;
   1188   }
   1189   num_uncleared_mips_ -= texture->num_uncleared_mips();
   1190   DCHECK_GE(num_uncleared_mips_, 0);
   1191 }
   1192 
   1193 MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) {
   1194   switch(tracking_pool) {
   1195     case GL_TEXTURE_POOL_MANAGED_CHROMIUM:
   1196       return memory_tracker_managed_.get();
   1197       break;
   1198     case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM:
   1199       return memory_tracker_unmanaged_.get();
   1200       break;
   1201     default:
   1202       break;
   1203   }
   1204   NOTREACHED();
   1205   return NULL;
   1206 }
   1207 
   1208 Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const {
   1209   // This doesn't need to be fast. It's only used during slow queries.
   1210   for (TextureMap::const_iterator it = textures_.begin();
   1211        it != textures_.end(); ++it) {
   1212     Texture* texture = it->second->texture();
   1213     if (texture->service_id() == service_id)
   1214       return texture;
   1215   }
   1216   return NULL;
   1217 }
   1218 
   1219 GLsizei TextureManager::ComputeMipMapCount(
   1220     GLsizei width, GLsizei height, GLsizei depth) {
   1221   return 1 + base::bits::Log2Floor(std::max(std::max(width, height), depth));
   1222 }
   1223 
   1224 void TextureManager::SetLevelImage(
   1225     TextureRef* ref,
   1226     GLenum target,
   1227     GLint level,
   1228     gfx::GLImage* image) {
   1229   DCHECK(ref);
   1230   ref->texture()->SetLevelImage(feature_info_.get(), target, level, image);
   1231 }
   1232 
   1233 void TextureManager::AddToSignature(
   1234     TextureRef* ref,
   1235     GLenum target,
   1236     GLint level,
   1237     std::string* signature) const {
   1238   ref->texture()->AddToSignature(feature_info_.get(), target, level, signature);
   1239 }
   1240 
   1241 void TextureManager::UpdateSafeToRenderFrom(int delta) {
   1242   num_unsafe_textures_ += delta;
   1243   DCHECK_GE(num_unsafe_textures_, 0);
   1244 }
   1245 
   1246 void TextureManager::UpdateUnclearedMips(int delta) {
   1247   num_uncleared_mips_ += delta;
   1248   DCHECK_GE(num_uncleared_mips_, 0);
   1249 }
   1250 
   1251 void TextureManager::UpdateCanRenderCondition(
   1252     Texture::CanRenderCondition old_condition,
   1253     Texture::CanRenderCondition new_condition) {
   1254   if (old_condition == Texture::CAN_RENDER_NEVER ||
   1255       (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
   1256        !feature_info_->feature_flags().npot_ok)) {
   1257     DCHECK_GT(num_unrenderable_textures_, 0);
   1258     --num_unrenderable_textures_;
   1259   }
   1260   if (new_condition == Texture::CAN_RENDER_NEVER ||
   1261       (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
   1262        !feature_info_->feature_flags().npot_ok))
   1263     ++num_unrenderable_textures_;
   1264 }
   1265 
   1266 void TextureManager::UpdateNumImages(int delta) {
   1267   num_images_ += delta;
   1268   DCHECK_GE(num_images_, 0);
   1269 }
   1270 
   1271 void TextureManager::IncFramebufferStateChangeCount() {
   1272   if (framebuffer_manager_)
   1273     framebuffer_manager_->IncFramebufferStateChangeCount();
   1274 }
   1275 
   1276 }  // namespace gles2
   1277 }  // namespace gpu
   1278