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/context_state.h"
     10 #include "gpu/command_buffer/service/error_state.h"
     11 #include "gpu/command_buffer/service/feature_info.h"
     12 #include "gpu/command_buffer/service/framebuffer_manager.h"
     13 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
     14 #include "gpu/command_buffer/service/mailbox_manager.h"
     15 #include "gpu/command_buffer/service/memory_tracking.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 (unsigned int i = 0; i < destruction_observers_.size(); i++)
     70     destruction_observers_[i]->OnTextureManagerDestroying(this);
     71 
     72   DCHECK(textures_.empty());
     73 
     74   // If this triggers, that means something is keeping a reference to
     75   // a Texture belonging to this.
     76   CHECK_EQ(texture_count_, 0u);
     77 
     78   DCHECK_EQ(0, num_unrenderable_textures_);
     79   DCHECK_EQ(0, num_unsafe_textures_);
     80   DCHECK_EQ(0, num_uncleared_mips_);
     81   DCHECK_EQ(0, num_images_);
     82 }
     83 
     84 void TextureManager::Destroy(bool have_context) {
     85   have_context_ = have_context;
     86   textures_.clear();
     87   for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
     88     default_textures_[ii] = NULL;
     89   }
     90 
     91   if (have_context) {
     92     glDeleteTextures(arraysize(black_texture_ids_), black_texture_ids_);
     93   }
     94 
     95   DCHECK_EQ(0u, memory_tracker_managed_->GetMemRepresented());
     96   DCHECK_EQ(0u, memory_tracker_unmanaged_->GetMemRepresented());
     97 }
     98 
     99 Texture::Texture(GLuint service_id)
    100     : mailbox_manager_(NULL),
    101       memory_tracking_ref_(NULL),
    102       service_id_(service_id),
    103       cleared_(true),
    104       num_uncleared_mips_(0),
    105       target_(0),
    106       min_filter_(GL_NEAREST_MIPMAP_LINEAR),
    107       mag_filter_(GL_LINEAR),
    108       wrap_s_(GL_REPEAT),
    109       wrap_t_(GL_REPEAT),
    110       usage_(GL_NONE),
    111       pool_(GL_TEXTURE_POOL_UNMANAGED_CHROMIUM),
    112       max_level_set_(-1),
    113       texture_complete_(false),
    114       cube_complete_(false),
    115       npot_(false),
    116       has_been_bound_(false),
    117       framebuffer_attachment_count_(0),
    118       immutable_(false),
    119       has_images_(false),
    120       estimated_size_(0),
    121       can_render_condition_(CAN_RENDER_ALWAYS),
    122       texture_max_anisotropy_initialized_(false) {
    123 }
    124 
    125 Texture::~Texture() {
    126   if (mailbox_manager_)
    127     mailbox_manager_->TextureDeleted(this);
    128 }
    129 
    130 void Texture::AddTextureRef(TextureRef* ref) {
    131   DCHECK(refs_.find(ref) == refs_.end());
    132   refs_.insert(ref);
    133   if (!memory_tracking_ref_) {
    134     memory_tracking_ref_ = ref;
    135     GetMemTracker()->TrackMemAlloc(estimated_size());
    136   }
    137 }
    138 
    139 void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) {
    140   if (memory_tracking_ref_ == ref) {
    141     GetMemTracker()->TrackMemFree(estimated_size());
    142     memory_tracking_ref_ = NULL;
    143   }
    144   size_t result = refs_.erase(ref);
    145   DCHECK_EQ(result, 1u);
    146   if (refs_.empty()) {
    147     if (have_context) {
    148       GLuint id = service_id();
    149       glDeleteTextures(1, &id);
    150     }
    151     delete this;
    152   } else if (memory_tracking_ref_ == NULL) {
    153     // TODO(piman): tune ownership semantics for cross-context group shared
    154     // textures.
    155     memory_tracking_ref_ = *refs_.begin();
    156     GetMemTracker()->TrackMemAlloc(estimated_size());
    157   }
    158 }
    159 
    160 MemoryTypeTracker* Texture::GetMemTracker() {
    161   DCHECK(memory_tracking_ref_);
    162   return memory_tracking_ref_->manager()->GetMemTracker(pool_);
    163 }
    164 
    165 Texture::LevelInfo::LevelInfo()
    166     : cleared(true),
    167       target(0),
    168       level(-1),
    169       internal_format(0),
    170       width(0),
    171       height(0),
    172       depth(0),
    173       border(0),
    174       format(0),
    175       type(0),
    176       estimated_size(0) {
    177 }
    178 
    179 Texture::LevelInfo::LevelInfo(const LevelInfo& rhs)
    180     : cleared(rhs.cleared),
    181       target(rhs.target),
    182       level(rhs.level),
    183       internal_format(rhs.internal_format),
    184       width(rhs.width),
    185       height(rhs.height),
    186       depth(rhs.depth),
    187       border(rhs.border),
    188       format(rhs.format),
    189       type(rhs.type),
    190       image(rhs.image),
    191       estimated_size(rhs.estimated_size) {
    192 }
    193 
    194 Texture::LevelInfo::~LevelInfo() {
    195 }
    196 
    197 Texture::CanRenderCondition Texture::GetCanRenderCondition() const {
    198   if (target_ == 0)
    199     return CAN_RENDER_ALWAYS;
    200 
    201   if (target_ != GL_TEXTURE_EXTERNAL_OES) {
    202     if (level_infos_.empty()) {
    203       return CAN_RENDER_NEVER;
    204     }
    205 
    206     const Texture::LevelInfo& first_face = level_infos_[0][0];
    207     if (first_face.width == 0 ||
    208         first_face.height == 0 ||
    209         first_face.depth == 0) {
    210       return CAN_RENDER_NEVER;
    211     }
    212   }
    213 
    214   bool needs_mips = NeedsMips();
    215   if (needs_mips) {
    216     if (!texture_complete())
    217       return CAN_RENDER_NEVER;
    218     if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete())
    219       return CAN_RENDER_NEVER;
    220   }
    221 
    222   bool is_npot_compatible = !needs_mips &&
    223       wrap_s_ == GL_CLAMP_TO_EDGE &&
    224       wrap_t_ == GL_CLAMP_TO_EDGE;
    225 
    226   if (!is_npot_compatible) {
    227     if (target_ == GL_TEXTURE_RECTANGLE_ARB)
    228       return CAN_RENDER_NEVER;
    229     else if (npot())
    230       return CAN_RENDER_ONLY_IF_NPOT;
    231   }
    232 
    233   return CAN_RENDER_ALWAYS;
    234 }
    235 
    236 bool Texture::CanRender(const FeatureInfo* feature_info) const {
    237   switch (can_render_condition_) {
    238     case CAN_RENDER_ALWAYS:
    239       return true;
    240     case CAN_RENDER_NEVER:
    241       return false;
    242     case CAN_RENDER_ONLY_IF_NPOT:
    243       break;
    244   }
    245   return feature_info->feature_flags().npot_ok;
    246 }
    247 
    248 void Texture::AddToSignature(
    249     const FeatureInfo* feature_info,
    250     GLenum target,
    251     GLint level,
    252     std::string* signature) const {
    253   DCHECK(feature_info);
    254   DCHECK(signature);
    255   DCHECK_GE(level, 0);
    256   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
    257             level_infos_.size());
    258   DCHECK_LT(static_cast<size_t>(level),
    259             level_infos_[GLTargetToFaceIndex(target)].size());
    260   const Texture::LevelInfo& info =
    261       level_infos_[GLTargetToFaceIndex(target)][level];
    262   *signature += base::StringPrintf(
    263       "|Texture|target=%04x|level=%d|internal_format=%04x"
    264       "|width=%d|height=%d|depth=%d|border=%d|format=%04x|type=%04x"
    265       "|image=%d|canrender=%d|canrenderto=%d|npot_=%d"
    266       "|min_filter=%04x|mag_filter=%04x|wrap_s=%04x|wrap_t=%04x"
    267       "|usage=%04x",
    268       target, level, info.internal_format,
    269       info.width, info.height, info.depth, info.border,
    270       info.format, info.type, info.image.get() != NULL,
    271       CanRender(feature_info), CanRenderTo(), npot_,
    272       min_filter_, mag_filter_, wrap_s_, wrap_t_,
    273       usage_);
    274 }
    275 
    276 void Texture::SetMailboxManager(MailboxManager* mailbox_manager) {
    277   DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager);
    278   mailbox_manager_ = mailbox_manager;
    279 }
    280 
    281 bool Texture::MarkMipmapsGenerated(
    282     const FeatureInfo* feature_info) {
    283   if (!CanGenerateMipmaps(feature_info)) {
    284     return false;
    285   }
    286   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    287     const Texture::LevelInfo& info1 = level_infos_[ii][0];
    288     GLsizei width = info1.width;
    289     GLsizei height = info1.height;
    290     GLsizei depth = info1.depth;
    291     GLenum target = target_ == GL_TEXTURE_2D ? GL_TEXTURE_2D :
    292                                FaceIndexToGLTarget(ii);
    293     int num_mips =
    294         TextureManager::ComputeMipMapCount(target_, width, height, depth);
    295     for (int level = 1; level < num_mips; ++level) {
    296       width = std::max(1, width >> 1);
    297       height = std::max(1, height >> 1);
    298       depth = std::max(1, depth >> 1);
    299       SetLevelInfo(feature_info,
    300                    target,
    301                    level,
    302                    info1.internal_format,
    303                    width,
    304                    height,
    305                    depth,
    306                    info1.border,
    307                    info1.format,
    308                    info1.type,
    309                    true);
    310     }
    311   }
    312 
    313   return true;
    314 }
    315 
    316 void Texture::SetTarget(
    317     const FeatureInfo* feature_info, GLenum target, GLint max_levels) {
    318   DCHECK_EQ(0u, target_);  // you can only set this once.
    319   target_ = target;
    320   size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
    321   level_infos_.resize(num_faces);
    322   for (size_t ii = 0; ii < num_faces; ++ii) {
    323     level_infos_[ii].resize(max_levels);
    324   }
    325 
    326   if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) {
    327     min_filter_ = GL_LINEAR;
    328     wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE;
    329   }
    330 
    331   if (target == GL_TEXTURE_EXTERNAL_OES) {
    332     immutable_ = true;
    333   }
    334   Update(feature_info);
    335   UpdateCanRenderCondition();
    336 }
    337 
    338 bool Texture::CanGenerateMipmaps(
    339     const FeatureInfo* feature_info) const {
    340   if ((npot() && !feature_info->feature_flags().npot_ok) ||
    341       level_infos_.empty() ||
    342       target_ == GL_TEXTURE_EXTERNAL_OES ||
    343       target_ == GL_TEXTURE_RECTANGLE_ARB) {
    344     return false;
    345   }
    346 
    347   // Can't generate mips for depth or stencil textures.
    348   const Texture::LevelInfo& first = level_infos_[0][0];
    349   uint32 channels = GLES2Util::GetChannelsForFormat(first.format);
    350   if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) {
    351     return false;
    352   }
    353 
    354   // TODO(gman): Check internal_format, format and type.
    355   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    356     const LevelInfo& info = level_infos_[ii][0];
    357     if ((info.target == 0) || (info.width != first.width) ||
    358         (info.height != first.height) || (info.depth != 1) ||
    359         (info.format != first.format) ||
    360         (info.internal_format != first.internal_format) ||
    361         (info.type != first.type) ||
    362         feature_info->validators()->compressed_texture_format.IsValid(
    363             info.internal_format) ||
    364         info.image.get()) {
    365       return false;
    366     }
    367   }
    368   return true;
    369 }
    370 
    371 void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) {
    372   DCHECK_GE(level, 0);
    373   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
    374             level_infos_.size());
    375   DCHECK_LT(static_cast<size_t>(level),
    376             level_infos_[GLTargetToFaceIndex(target)].size());
    377   Texture::LevelInfo& info =
    378       level_infos_[GLTargetToFaceIndex(target)][level];
    379   UpdateMipCleared(&info, cleared);
    380   UpdateCleared();
    381 }
    382 
    383 void Texture::UpdateCleared() {
    384   if (level_infos_.empty()) {
    385     return;
    386   }
    387 
    388   const Texture::LevelInfo& first_face = level_infos_[0][0];
    389   int levels_needed = TextureManager::ComputeMipMapCount(
    390       target_, first_face.width, first_face.height, first_face.depth);
    391   bool cleared = true;
    392   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    393     for (GLint jj = 0; jj < levels_needed; ++jj) {
    394       const Texture::LevelInfo& info = level_infos_[ii][jj];
    395       if (info.width > 0 && info.height > 0 && info.depth > 0 &&
    396           !info.cleared) {
    397         cleared = false;
    398         break;
    399       }
    400     }
    401   }
    402 
    403   // If texture is uncleared and is attached to a framebuffer,
    404   // that framebuffer must be marked possibly incomplete.
    405   if (!cleared && IsAttachedToFramebuffer()) {
    406     IncAllFramebufferStateChangeCount();
    407   }
    408 
    409   UpdateSafeToRenderFrom(cleared);
    410 }
    411 
    412 void Texture::UpdateSafeToRenderFrom(bool cleared) {
    413   if (cleared_ == cleared)
    414     return;
    415   cleared_ = cleared;
    416   int delta = cleared ? -1 : +1;
    417   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    418     (*it)->manager()->UpdateSafeToRenderFrom(delta);
    419 }
    420 
    421 void Texture::UpdateMipCleared(LevelInfo* info, bool cleared) {
    422   if (info->cleared == cleared)
    423     return;
    424   info->cleared = cleared;
    425   int delta = cleared ? -1 : +1;
    426   num_uncleared_mips_ += delta;
    427   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    428     (*it)->manager()->UpdateUnclearedMips(delta);
    429 }
    430 
    431 void Texture::UpdateCanRenderCondition() {
    432   CanRenderCondition can_render_condition = GetCanRenderCondition();
    433   if (can_render_condition_ == can_render_condition)
    434     return;
    435   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    436     (*it)->manager()->UpdateCanRenderCondition(can_render_condition_,
    437                                                can_render_condition);
    438   can_render_condition_ = can_render_condition;
    439 }
    440 
    441 void Texture::UpdateHasImages() {
    442   if (level_infos_.empty())
    443     return;
    444 
    445   bool has_images = false;
    446   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    447     for (size_t jj = 0; jj < level_infos_[ii].size(); ++jj) {
    448       const Texture::LevelInfo& info = level_infos_[ii][jj];
    449       if (info.image.get() != NULL) {
    450         has_images = true;
    451         break;
    452       }
    453     }
    454   }
    455 
    456   if (has_images_ == has_images)
    457     return;
    458   has_images_ = has_images;
    459   int delta = has_images ? +1 : -1;
    460   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    461     (*it)->manager()->UpdateNumImages(delta);
    462 }
    463 
    464 void Texture::IncAllFramebufferStateChangeCount() {
    465   for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    466     (*it)->manager()->IncFramebufferStateChangeCount();
    467 }
    468 
    469 void Texture::SetLevelInfo(
    470     const FeatureInfo* feature_info,
    471     GLenum target,
    472     GLint level,
    473     GLenum internal_format,
    474     GLsizei width,
    475     GLsizei height,
    476     GLsizei depth,
    477     GLint border,
    478     GLenum format,
    479     GLenum type,
    480     bool cleared) {
    481   DCHECK_GE(level, 0);
    482   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
    483             level_infos_.size());
    484   DCHECK_LT(static_cast<size_t>(level),
    485             level_infos_[GLTargetToFaceIndex(target)].size());
    486   DCHECK_GE(width, 0);
    487   DCHECK_GE(height, 0);
    488   DCHECK_GE(depth, 0);
    489   Texture::LevelInfo& info =
    490       level_infos_[GLTargetToFaceIndex(target)][level];
    491   info.target = target;
    492   info.level = level;
    493   info.internal_format = internal_format;
    494   info.width = width;
    495   info.height = height;
    496   info.depth = depth;
    497   info.border = border;
    498   info.format = format;
    499   info.type = type;
    500   info.image = 0;
    501 
    502   estimated_size_ -= info.estimated_size;
    503   GLES2Util::ComputeImageDataSizes(
    504       width, height, format, type, 4, &info.estimated_size, NULL, NULL);
    505   estimated_size_ += info.estimated_size;
    506 
    507   UpdateMipCleared(&info, cleared);
    508   max_level_set_ = std::max(max_level_set_, level);
    509   Update(feature_info);
    510   UpdateCleared();
    511   UpdateCanRenderCondition();
    512   UpdateHasImages();
    513   if (IsAttachedToFramebuffer()) {
    514     // TODO(gman): If textures tracked which framebuffers they were attached to
    515     // we could just mark those framebuffers as not complete.
    516     IncAllFramebufferStateChangeCount();
    517   }
    518 }
    519 
    520 bool Texture::ValidForTexture(
    521     GLint target,
    522     GLint level,
    523     GLint xoffset,
    524     GLint yoffset,
    525     GLsizei width,
    526     GLsizei height,
    527     GLenum type) const {
    528   size_t face_index = GLTargetToFaceIndex(target);
    529   if (level >= 0 && face_index < level_infos_.size() &&
    530       static_cast<size_t>(level) < level_infos_[face_index].size()) {
    531     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
    532     int32 right;
    533     int32 top;
    534     return SafeAddInt32(xoffset, width, &right) &&
    535            SafeAddInt32(yoffset, height, &top) &&
    536            xoffset >= 0 &&
    537            yoffset >= 0 &&
    538            right <= info.width &&
    539            top <= info.height &&
    540            type == info.type;
    541   }
    542   return false;
    543 }
    544 
    545 bool Texture::GetLevelSize(
    546     GLint target, GLint level, GLsizei* width, GLsizei* height) const {
    547   DCHECK(width);
    548   DCHECK(height);
    549   size_t face_index = GLTargetToFaceIndex(target);
    550   if (level >= 0 && face_index < level_infos_.size() &&
    551       static_cast<size_t>(level) < level_infos_[face_index].size()) {
    552     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
    553     if (info.target != 0) {
    554       *width = info.width;
    555       *height = info.height;
    556       return true;
    557     }
    558   }
    559   return false;
    560 }
    561 
    562 bool Texture::GetLevelType(
    563     GLint target, GLint level, GLenum* type, GLenum* internal_format) const {
    564   DCHECK(type);
    565   DCHECK(internal_format);
    566   size_t face_index = GLTargetToFaceIndex(target);
    567   if (level >= 0 && face_index < level_infos_.size() &&
    568       static_cast<size_t>(level) < level_infos_[face_index].size()) {
    569     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
    570     if (info.target != 0) {
    571       *type = info.type;
    572       *internal_format = info.internal_format;
    573       return true;
    574     }
    575   }
    576   return false;
    577 }
    578 
    579 GLenum Texture::SetParameteri(
    580     const FeatureInfo* feature_info, GLenum pname, GLint param) {
    581   DCHECK(feature_info);
    582 
    583   if (target_ == GL_TEXTURE_EXTERNAL_OES ||
    584       target_ == GL_TEXTURE_RECTANGLE_ARB) {
    585     if (pname == GL_TEXTURE_MIN_FILTER &&
    586         (param != GL_NEAREST && param != GL_LINEAR))
    587       return GL_INVALID_ENUM;
    588     if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
    589         param != GL_CLAMP_TO_EDGE)
    590       return GL_INVALID_ENUM;
    591   }
    592 
    593   switch (pname) {
    594     case GL_TEXTURE_MIN_FILTER:
    595       if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) {
    596         return GL_INVALID_ENUM;
    597       }
    598       min_filter_ = param;
    599       break;
    600     case GL_TEXTURE_MAG_FILTER:
    601       if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) {
    602         return GL_INVALID_ENUM;
    603       }
    604       mag_filter_ = param;
    605       break;
    606     case GL_TEXTURE_POOL_CHROMIUM:
    607       if (!feature_info->validators()->texture_pool.IsValid(param)) {
    608         return GL_INVALID_ENUM;
    609       }
    610       GetMemTracker()->TrackMemFree(estimated_size());
    611       pool_ = param;
    612       GetMemTracker()->TrackMemAlloc(estimated_size());
    613       break;
    614     case GL_TEXTURE_WRAP_S:
    615       if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
    616         return GL_INVALID_ENUM;
    617       }
    618       wrap_s_ = param;
    619       break;
    620     case GL_TEXTURE_WRAP_T:
    621       if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
    622         return GL_INVALID_ENUM;
    623       }
    624       wrap_t_ = param;
    625       break;
    626     case GL_TEXTURE_MAX_ANISOTROPY_EXT:
    627       if (param < 1) {
    628         return GL_INVALID_VALUE;
    629       }
    630       break;
    631     case GL_TEXTURE_USAGE_ANGLE:
    632       if (!feature_info->validators()->texture_usage.IsValid(param)) {
    633         return GL_INVALID_ENUM;
    634       }
    635       usage_ = param;
    636       break;
    637     default:
    638       NOTREACHED();
    639       return GL_INVALID_ENUM;
    640   }
    641   Update(feature_info);
    642   UpdateCleared();
    643   UpdateCanRenderCondition();
    644   return GL_NO_ERROR;
    645 }
    646 
    647 GLenum Texture::SetParameterf(
    648     const FeatureInfo* feature_info, GLenum pname, GLfloat param) {
    649   switch (pname) {
    650     case GL_TEXTURE_MIN_FILTER:
    651     case GL_TEXTURE_MAG_FILTER:
    652     case GL_TEXTURE_POOL_CHROMIUM:
    653     case GL_TEXTURE_WRAP_S:
    654     case GL_TEXTURE_WRAP_T:
    655     case GL_TEXTURE_USAGE_ANGLE:
    656       {
    657         GLint iparam = static_cast<GLint>(param);
    658         return SetParameteri(feature_info, pname, iparam);
    659       }
    660     case GL_TEXTURE_MAX_ANISOTROPY_EXT:
    661       if (param < 1.f) {
    662         return GL_INVALID_VALUE;
    663       }
    664       break;
    665     default:
    666       NOTREACHED();
    667       return GL_INVALID_ENUM;
    668   }
    669   return GL_NO_ERROR;
    670 }
    671 
    672 void Texture::Update(const FeatureInfo* feature_info) {
    673   // Update npot status.
    674   // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
    675   npot_ = target_ == GL_TEXTURE_EXTERNAL_OES;
    676 
    677   if (level_infos_.empty()) {
    678     texture_complete_ = false;
    679     cube_complete_ = false;
    680     return;
    681   }
    682 
    683   // checks that the first mip of any face is npot.
    684   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    685     const Texture::LevelInfo& info = level_infos_[ii][0];
    686     if (GLES2Util::IsNPOT(info.width) ||
    687         GLES2Util::IsNPOT(info.height) ||
    688         GLES2Util::IsNPOT(info.depth)) {
    689       npot_ = true;
    690       break;
    691     }
    692   }
    693 
    694   // Update texture_complete and cube_complete status.
    695   const Texture::LevelInfo& first_face = level_infos_[0][0];
    696   int levels_needed = TextureManager::ComputeMipMapCount(
    697       target_, first_face.width, first_face.height, first_face.depth);
    698   texture_complete_ =
    699       max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0;
    700   cube_complete_ = (level_infos_.size() == 6) &&
    701                    (first_face.width == first_face.height);
    702 
    703   if (first_face.width == 0 || first_face.height == 0) {
    704     texture_complete_ = false;
    705   }
    706   if (first_face.type == GL_FLOAT &&
    707       !feature_info->feature_flags().enable_texture_float_linear &&
    708       (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
    709        mag_filter_ != GL_NEAREST)) {
    710     texture_complete_ = false;
    711   } else if (first_face.type == GL_HALF_FLOAT_OES &&
    712              !feature_info->feature_flags().enable_texture_half_float_linear &&
    713              (min_filter_ != GL_NEAREST_MIPMAP_NEAREST ||
    714               mag_filter_ != GL_NEAREST)) {
    715     texture_complete_ = false;
    716   }
    717   for (size_t ii = 0;
    718        ii < level_infos_.size() && (cube_complete_ || texture_complete_);
    719        ++ii) {
    720     const Texture::LevelInfo& level0 = level_infos_[ii][0];
    721     if (level0.target == 0 ||
    722         level0.width != first_face.width ||
    723         level0.height != first_face.height ||
    724         level0.depth != 1 ||
    725         level0.internal_format != first_face.internal_format ||
    726         level0.format != first_face.format ||
    727         level0.type != first_face.type) {
    728       cube_complete_ = false;
    729     }
    730     // Get level0 dimensions
    731     GLsizei width = level0.width;
    732     GLsizei height = level0.height;
    733     GLsizei depth = level0.depth;
    734     for (GLint jj = 1; jj < levels_needed; ++jj) {
    735       // compute required size for mip.
    736       width = std::max(1, width >> 1);
    737       height = std::max(1, height >> 1);
    738       depth = std::max(1, depth >> 1);
    739       const Texture::LevelInfo& info = level_infos_[ii][jj];
    740       if (info.target == 0 ||
    741           info.width != width ||
    742           info.height != height ||
    743           info.depth != depth ||
    744           info.internal_format != level0.internal_format ||
    745           info.format != level0.format ||
    746           info.type != level0.type) {
    747         texture_complete_ = false;
    748         break;
    749       }
    750     }
    751   }
    752 }
    753 
    754 bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
    755   DCHECK(decoder);
    756   if (cleared_) {
    757     return true;
    758   }
    759 
    760   const Texture::LevelInfo& first_face = level_infos_[0][0];
    761   int levels_needed = TextureManager::ComputeMipMapCount(
    762       target_, first_face.width, first_face.height, first_face.depth);
    763 
    764   for (size_t ii = 0; ii < level_infos_.size(); ++ii) {
    765     for (GLint jj = 0; jj < levels_needed; ++jj) {
    766       Texture::LevelInfo& info = level_infos_[ii][jj];
    767       if (info.target != 0) {
    768         if (!ClearLevel(decoder, info.target, jj)) {
    769           return false;
    770         }
    771       }
    772     }
    773   }
    774   UpdateSafeToRenderFrom(true);
    775   return true;
    776 }
    777 
    778 bool Texture::IsLevelCleared(GLenum target, GLint level) const {
    779   size_t face_index = GLTargetToFaceIndex(target);
    780   if (face_index >= level_infos_.size() ||
    781       level >= static_cast<GLint>(level_infos_[face_index].size())) {
    782     return true;
    783   }
    784 
    785   const Texture::LevelInfo& info = level_infos_[face_index][level];
    786 
    787   return info.cleared;
    788 }
    789 
    790 void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) {
    791   if (texture_max_anisotropy_initialized_)
    792     return;
    793   texture_max_anisotropy_initialized_ = true;
    794   GLfloat params[] = { 1.0f };
    795   glTexParameterfv(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, params);
    796 }
    797 
    798 bool Texture::ClearLevel(
    799     GLES2Decoder* decoder, GLenum target, GLint level) {
    800   DCHECK(decoder);
    801   size_t face_index = GLTargetToFaceIndex(target);
    802   if (face_index >= level_infos_.size() ||
    803       level >= static_cast<GLint>(level_infos_[face_index].size())) {
    804     return true;
    805   }
    806 
    807   Texture::LevelInfo& info = level_infos_[face_index][level];
    808 
    809   DCHECK(target == info.target);
    810 
    811   if (info.target == 0 ||
    812       info.cleared ||
    813       info.width == 0 ||
    814       info.height == 0 ||
    815       info.depth == 0) {
    816     return true;
    817   }
    818 
    819   // NOTE: It seems kind of gross to call back into the decoder for this
    820   // but only the decoder knows all the state (like unpack_alignment_) that's
    821   // needed to be able to call GL correctly.
    822   bool cleared = decoder->ClearLevel(
    823       service_id_, target_, info.target, info.level, info.internal_format,
    824       info.format, info.type, info.width, info.height, immutable_);
    825   UpdateMipCleared(&info, cleared);
    826   return info.cleared;
    827 }
    828 
    829 void Texture::SetLevelImage(
    830     const FeatureInfo* feature_info,
    831     GLenum target,
    832     GLint level,
    833     gfx::GLImage* image) {
    834   DCHECK_GE(level, 0);
    835   DCHECK_LT(static_cast<size_t>(GLTargetToFaceIndex(target)),
    836             level_infos_.size());
    837   DCHECK_LT(static_cast<size_t>(level),
    838             level_infos_[GLTargetToFaceIndex(target)].size());
    839   Texture::LevelInfo& info =
    840       level_infos_[GLTargetToFaceIndex(target)][level];
    841   DCHECK_EQ(info.target, target);
    842   DCHECK_EQ(info.level, level);
    843   info.image = image;
    844   UpdateCanRenderCondition();
    845   UpdateHasImages();
    846 }
    847 
    848 gfx::GLImage* Texture::GetLevelImage(GLint target, GLint level) const {
    849   if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES &&
    850       target != GL_TEXTURE_RECTANGLE_ARB) {
    851     return NULL;
    852   }
    853 
    854   size_t face_index = GLTargetToFaceIndex(target);
    855   if (level >= 0 && face_index < level_infos_.size() &&
    856       static_cast<size_t>(level) < level_infos_[face_index].size()) {
    857     const LevelInfo& info = level_infos_[GLTargetToFaceIndex(target)][level];
    858     if (info.target != 0) {
    859       return info.image.get();
    860     }
    861   }
    862   return 0;
    863 }
    864 
    865 void Texture::OnWillModifyPixels() {
    866   gfx::GLImage* image = GetLevelImage(target(), 0);
    867   if (image)
    868     image->WillModifyTexImage();
    869 }
    870 
    871 void Texture::OnDidModifyPixels() {
    872   gfx::GLImage* image = GetLevelImage(target(), 0);
    873   if (image)
    874     image->DidModifyTexImage();
    875 }
    876 
    877 TextureRef::TextureRef(TextureManager* manager,
    878                        GLuint client_id,
    879                        Texture* texture)
    880     : manager_(manager),
    881       texture_(texture),
    882       client_id_(client_id),
    883       num_observers_(0) {
    884   DCHECK(manager_);
    885   DCHECK(texture_);
    886   texture_->AddTextureRef(this);
    887   manager_->StartTracking(this);
    888 }
    889 
    890 scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager,
    891                                              GLuint client_id,
    892                                              GLuint service_id) {
    893   return new TextureRef(manager, client_id, new Texture(service_id));
    894 }
    895 
    896 TextureRef::~TextureRef() {
    897   manager_->StopTracking(this);
    898   texture_->RemoveTextureRef(this, manager_->have_context_);
    899   manager_ = NULL;
    900 }
    901 
    902 TextureManager::TextureManager(MemoryTracker* memory_tracker,
    903                                FeatureInfo* feature_info,
    904                                GLint max_texture_size,
    905                                GLint max_cube_map_texture_size,
    906                                bool use_default_textures)
    907     : memory_tracker_managed_(
    908           new MemoryTypeTracker(memory_tracker, MemoryTracker::kManaged)),
    909       memory_tracker_unmanaged_(
    910           new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)),
    911       feature_info_(feature_info),
    912       framebuffer_manager_(NULL),
    913       max_texture_size_(max_texture_size),
    914       max_cube_map_texture_size_(max_cube_map_texture_size),
    915       max_levels_(ComputeMipMapCount(GL_TEXTURE_2D,
    916                                      max_texture_size,
    917                                      max_texture_size,
    918                                      max_texture_size)),
    919       max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP,
    920                                               max_cube_map_texture_size,
    921                                               max_cube_map_texture_size,
    922                                               max_cube_map_texture_size)),
    923       use_default_textures_(use_default_textures),
    924       num_unrenderable_textures_(0),
    925       num_unsafe_textures_(0),
    926       num_uncleared_mips_(0),
    927       num_images_(0),
    928       texture_count_(0),
    929       have_context_(true) {
    930   for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
    931     black_texture_ids_[ii] = 0;
    932   }
    933 }
    934 
    935 bool TextureManager::Initialize() {
    936   // TODO(gman): The default textures have to be real textures, not the 0
    937   // texture because we simulate non shared resources on top of shared
    938   // resources and all contexts that share resource share the same default
    939   // texture.
    940   default_textures_[kTexture2D] = CreateDefaultAndBlackTextures(
    941       GL_TEXTURE_2D, &black_texture_ids_[kTexture2D]);
    942   default_textures_[kCubeMap] = CreateDefaultAndBlackTextures(
    943       GL_TEXTURE_CUBE_MAP, &black_texture_ids_[kCubeMap]);
    944 
    945   if (feature_info_->feature_flags().oes_egl_image_external) {
    946     default_textures_[kExternalOES] = CreateDefaultAndBlackTextures(
    947         GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]);
    948   }
    949 
    950   if (feature_info_->feature_flags().arb_texture_rectangle) {
    951     default_textures_[kRectangleARB] = CreateDefaultAndBlackTextures(
    952         GL_TEXTURE_RECTANGLE_ARB, &black_texture_ids_[kRectangleARB]);
    953   }
    954 
    955   return true;
    956 }
    957 
    958 scoped_refptr<TextureRef>
    959     TextureManager::CreateDefaultAndBlackTextures(
    960         GLenum target,
    961         GLuint* black_texture) {
    962   static uint8 black[] = {0, 0, 0, 255};
    963 
    964   // Sampling a texture not associated with any EGLImage sibling will return
    965   // black values according to the spec.
    966   bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES);
    967   bool needs_faces = (target == GL_TEXTURE_CUBE_MAP);
    968 
    969   // Make default textures and texture for replacing non-renderable textures.
    970   GLuint ids[2];
    971   const unsigned long num_ids = use_default_textures_ ? 2 : 1;
    972   glGenTextures(num_ids, ids);
    973   for (unsigned long ii = 0; ii < num_ids; ++ii) {
    974     glBindTexture(target, ids[ii]);
    975     if (needs_initialization) {
    976       if (needs_faces) {
    977         for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) {
    978           glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0,
    979                        GL_RGBA, GL_UNSIGNED_BYTE, black);
    980         }
    981       } else {
    982         glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
    983                      GL_UNSIGNED_BYTE, black);
    984       }
    985     }
    986   }
    987   glBindTexture(target, 0);
    988 
    989   scoped_refptr<TextureRef> default_texture;
    990   if (use_default_textures_) {
    991     default_texture = TextureRef::Create(this, 0, ids[1]);
    992     SetTarget(default_texture.get(), target);
    993     if (needs_faces) {
    994       for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
    995         SetLevelInfo(default_texture.get(),
    996                      GLES2Util::IndexToGLFaceTarget(ii),
    997                      0,
    998                      GL_RGBA,
    999                      1,
   1000                      1,
   1001                      1,
   1002                      0,
   1003                      GL_RGBA,
   1004                      GL_UNSIGNED_BYTE,
   1005                      true);
   1006       }
   1007     } else {
   1008       if (needs_initialization) {
   1009         SetLevelInfo(default_texture.get(),
   1010                      GL_TEXTURE_2D,
   1011                      0,
   1012                      GL_RGBA,
   1013                      1,
   1014                      1,
   1015                      1,
   1016                      0,
   1017                      GL_RGBA,
   1018                      GL_UNSIGNED_BYTE,
   1019                      true);
   1020       } else {
   1021         SetLevelInfo(default_texture.get(),
   1022                      GL_TEXTURE_EXTERNAL_OES,
   1023                      0,
   1024                      GL_RGBA,
   1025                      1,
   1026                      1,
   1027                      1,
   1028                      0,
   1029                      GL_RGBA,
   1030                      GL_UNSIGNED_BYTE,
   1031                      true);
   1032       }
   1033     }
   1034   }
   1035 
   1036   *black_texture = ids[0];
   1037   return default_texture;
   1038 }
   1039 
   1040 bool TextureManager::ValidForTarget(
   1041     GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) {
   1042   GLsizei max_size = MaxSizeForTarget(target) >> level;
   1043   return level >= 0 &&
   1044          width >= 0 &&
   1045          height >= 0 &&
   1046          depth >= 0 &&
   1047          level < MaxLevelsForTarget(target) &&
   1048          width <= max_size &&
   1049          height <= max_size &&
   1050          depth <= max_size &&
   1051          (level == 0 || feature_info_->feature_flags().npot_ok ||
   1052           (!GLES2Util::IsNPOT(width) &&
   1053            !GLES2Util::IsNPOT(height) &&
   1054            !GLES2Util::IsNPOT(depth))) &&
   1055          (target != GL_TEXTURE_CUBE_MAP || (width == height && depth == 1)) &&
   1056          (target != GL_TEXTURE_2D || (depth == 1));
   1057 }
   1058 
   1059 void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
   1060   DCHECK(ref);
   1061   ref->texture()
   1062       ->SetTarget(feature_info_.get(), target, MaxLevelsForTarget(target));
   1063 }
   1064 
   1065 void TextureManager::SetLevelCleared(TextureRef* ref,
   1066                                      GLenum target,
   1067                                      GLint level,
   1068                                      bool cleared) {
   1069   DCHECK(ref);
   1070   ref->texture()->SetLevelCleared(target, level, cleared);
   1071 }
   1072 
   1073 bool TextureManager::ClearRenderableLevels(
   1074     GLES2Decoder* decoder, TextureRef* ref) {
   1075   DCHECK(ref);
   1076   return ref->texture()->ClearRenderableLevels(decoder);
   1077 }
   1078 
   1079 bool TextureManager::ClearTextureLevel(
   1080     GLES2Decoder* decoder, TextureRef* ref,
   1081     GLenum target, GLint level) {
   1082   DCHECK(ref);
   1083   Texture* texture = ref->texture();
   1084   if (texture->num_uncleared_mips() == 0) {
   1085     return true;
   1086   }
   1087   bool result = texture->ClearLevel(decoder, target, level);
   1088   texture->UpdateCleared();
   1089   return result;
   1090 }
   1091 
   1092 void TextureManager::SetLevelInfo(
   1093     TextureRef* ref,
   1094     GLenum target,
   1095     GLint level,
   1096     GLenum internal_format,
   1097     GLsizei width,
   1098     GLsizei height,
   1099     GLsizei depth,
   1100     GLint border,
   1101     GLenum format,
   1102     GLenum type,
   1103     bool cleared) {
   1104   DCHECK(ref);
   1105   Texture* texture = ref->texture();
   1106 
   1107   texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
   1108   texture->SetLevelInfo(feature_info_.get(),
   1109                         target,
   1110                         level,
   1111                         internal_format,
   1112                         width,
   1113                         height,
   1114                         depth,
   1115                         border,
   1116                         format,
   1117                         type,
   1118                         cleared);
   1119   texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
   1120 }
   1121 
   1122 Texture* TextureManager::Produce(TextureRef* ref) {
   1123   DCHECK(ref);
   1124   return ref->texture();
   1125 }
   1126 
   1127 TextureRef* TextureManager::Consume(
   1128     GLuint client_id,
   1129     Texture* texture) {
   1130   DCHECK(client_id);
   1131   scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture));
   1132   bool result = textures_.insert(std::make_pair(client_id, ref)).second;
   1133   DCHECK(result);
   1134   return ref.get();
   1135 }
   1136 
   1137 void TextureManager::SetParameteri(
   1138     const char* function_name, ErrorState* error_state,
   1139     TextureRef* ref, GLenum pname, GLint param) {
   1140   DCHECK(error_state);
   1141   DCHECK(ref);
   1142   Texture* texture = ref->texture();
   1143   GLenum result = texture->SetParameteri(feature_info_.get(), pname, param);
   1144   if (result != GL_NO_ERROR) {
   1145     if (result == GL_INVALID_ENUM) {
   1146       ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
   1147           error_state, function_name, param, "param");
   1148     } else {
   1149       ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
   1150           error_state, result, function_name, pname, param);
   1151     }
   1152   } else {
   1153     // Texture tracking pools exist only for the command decoder, so
   1154     // do not pass them on to the native GL implementation.
   1155     if (pname != GL_TEXTURE_POOL_CHROMIUM) {
   1156       glTexParameteri(texture->target(), pname, param);
   1157     }
   1158   }
   1159 }
   1160 
   1161 void TextureManager::SetParameterf(
   1162     const char* function_name, ErrorState* error_state,
   1163     TextureRef* ref, GLenum pname, GLfloat param) {
   1164   DCHECK(error_state);
   1165   DCHECK(ref);
   1166   Texture* texture = ref->texture();
   1167   GLenum result = texture->SetParameterf(feature_info_.get(), pname, param);
   1168   if (result != GL_NO_ERROR) {
   1169     if (result == GL_INVALID_ENUM) {
   1170       ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
   1171           error_state, function_name, param, "param");
   1172     } else {
   1173       ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
   1174           error_state, result, function_name, pname, param);
   1175     }
   1176   } else {
   1177     // Texture tracking pools exist only for the command decoder, so
   1178     // do not pass them on to the native GL implementation.
   1179     if (pname != GL_TEXTURE_POOL_CHROMIUM) {
   1180       glTexParameterf(texture->target(), pname, param);
   1181     }
   1182   }
   1183 }
   1184 
   1185 bool TextureManager::MarkMipmapsGenerated(TextureRef* ref) {
   1186   DCHECK(ref);
   1187   Texture* texture = ref->texture();
   1188   texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
   1189   bool result = texture->MarkMipmapsGenerated(feature_info_.get());
   1190   texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
   1191   return result;
   1192 }
   1193 
   1194 TextureRef* TextureManager::CreateTexture(
   1195     GLuint client_id, GLuint service_id) {
   1196   DCHECK_NE(0u, service_id);
   1197   scoped_refptr<TextureRef> ref(TextureRef::Create(
   1198       this, client_id, service_id));
   1199   std::pair<TextureMap::iterator, bool> result =
   1200       textures_.insert(std::make_pair(client_id, ref));
   1201   DCHECK(result.second);
   1202   return ref.get();
   1203 }
   1204 
   1205 TextureRef* TextureManager::GetTexture(
   1206     GLuint client_id) const {
   1207   TextureMap::const_iterator it = textures_.find(client_id);
   1208   return it != textures_.end() ? it->second.get() : NULL;
   1209 }
   1210 
   1211 void TextureManager::RemoveTexture(GLuint client_id) {
   1212   TextureMap::iterator it = textures_.find(client_id);
   1213   if (it != textures_.end()) {
   1214     it->second->reset_client_id();
   1215     textures_.erase(it);
   1216   }
   1217 }
   1218 
   1219 void TextureManager::StartTracking(TextureRef* ref) {
   1220   Texture* texture = ref->texture();
   1221   ++texture_count_;
   1222   num_uncleared_mips_ += texture->num_uncleared_mips();
   1223   if (!texture->SafeToRenderFrom())
   1224     ++num_unsafe_textures_;
   1225   if (!texture->CanRender(feature_info_.get()))
   1226     ++num_unrenderable_textures_;
   1227   if (texture->HasImages())
   1228     ++num_images_;
   1229 }
   1230 
   1231 void TextureManager::StopTracking(TextureRef* ref) {
   1232   if (ref->num_observers()) {
   1233     for (unsigned int i = 0; i < destruction_observers_.size(); i++) {
   1234       destruction_observers_[i]->OnTextureRefDestroying(ref);
   1235     }
   1236     DCHECK_EQ(ref->num_observers(), 0);
   1237   }
   1238 
   1239   Texture* texture = ref->texture();
   1240 
   1241   --texture_count_;
   1242   if (texture->HasImages()) {
   1243     DCHECK_NE(0, num_images_);
   1244     --num_images_;
   1245   }
   1246   if (!texture->CanRender(feature_info_.get())) {
   1247     DCHECK_NE(0, num_unrenderable_textures_);
   1248     --num_unrenderable_textures_;
   1249   }
   1250   if (!texture->SafeToRenderFrom()) {
   1251     DCHECK_NE(0, num_unsafe_textures_);
   1252     --num_unsafe_textures_;
   1253   }
   1254   num_uncleared_mips_ -= texture->num_uncleared_mips();
   1255   DCHECK_GE(num_uncleared_mips_, 0);
   1256 }
   1257 
   1258 MemoryTypeTracker* TextureManager::GetMemTracker(GLenum tracking_pool) {
   1259   switch(tracking_pool) {
   1260     case GL_TEXTURE_POOL_MANAGED_CHROMIUM:
   1261       return memory_tracker_managed_.get();
   1262       break;
   1263     case GL_TEXTURE_POOL_UNMANAGED_CHROMIUM:
   1264       return memory_tracker_unmanaged_.get();
   1265       break;
   1266     default:
   1267       break;
   1268   }
   1269   NOTREACHED();
   1270   return NULL;
   1271 }
   1272 
   1273 Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const {
   1274   // This doesn't need to be fast. It's only used during slow queries.
   1275   for (TextureMap::const_iterator it = textures_.begin();
   1276        it != textures_.end(); ++it) {
   1277     Texture* texture = it->second->texture();
   1278     if (texture->service_id() == service_id)
   1279       return texture;
   1280   }
   1281   return NULL;
   1282 }
   1283 
   1284 GLsizei TextureManager::ComputeMipMapCount(GLenum target,
   1285                                            GLsizei width,
   1286                                            GLsizei height,
   1287                                            GLsizei depth) {
   1288   switch (target) {
   1289     case GL_TEXTURE_EXTERNAL_OES:
   1290       return 1;
   1291     default:
   1292       return 1 +
   1293              base::bits::Log2Floor(std::max(std::max(width, height), depth));
   1294   }
   1295 }
   1296 
   1297 void TextureManager::SetLevelImage(
   1298     TextureRef* ref,
   1299     GLenum target,
   1300     GLint level,
   1301     gfx::GLImage* image) {
   1302   DCHECK(ref);
   1303   ref->texture()->SetLevelImage(feature_info_.get(), target, level, image);
   1304 }
   1305 
   1306 void TextureManager::AddToSignature(
   1307     TextureRef* ref,
   1308     GLenum target,
   1309     GLint level,
   1310     std::string* signature) const {
   1311   ref->texture()->AddToSignature(feature_info_.get(), target, level, signature);
   1312 }
   1313 
   1314 void TextureManager::UpdateSafeToRenderFrom(int delta) {
   1315   num_unsafe_textures_ += delta;
   1316   DCHECK_GE(num_unsafe_textures_, 0);
   1317 }
   1318 
   1319 void TextureManager::UpdateUnclearedMips(int delta) {
   1320   num_uncleared_mips_ += delta;
   1321   DCHECK_GE(num_uncleared_mips_, 0);
   1322 }
   1323 
   1324 void TextureManager::UpdateCanRenderCondition(
   1325     Texture::CanRenderCondition old_condition,
   1326     Texture::CanRenderCondition new_condition) {
   1327   if (old_condition == Texture::CAN_RENDER_NEVER ||
   1328       (old_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
   1329        !feature_info_->feature_flags().npot_ok)) {
   1330     DCHECK_GT(num_unrenderable_textures_, 0);
   1331     --num_unrenderable_textures_;
   1332   }
   1333   if (new_condition == Texture::CAN_RENDER_NEVER ||
   1334       (new_condition == Texture::CAN_RENDER_ONLY_IF_NPOT &&
   1335        !feature_info_->feature_flags().npot_ok))
   1336     ++num_unrenderable_textures_;
   1337 }
   1338 
   1339 void TextureManager::UpdateNumImages(int delta) {
   1340   num_images_ += delta;
   1341   DCHECK_GE(num_images_, 0);
   1342 }
   1343 
   1344 void TextureManager::IncFramebufferStateChangeCount() {
   1345   if (framebuffer_manager_)
   1346     framebuffer_manager_->IncFramebufferStateChangeCount();
   1347 }
   1348 
   1349 bool TextureManager::ValidateFormatAndTypeCombination(
   1350     ErrorState* error_state, const char* function_name, GLenum format,
   1351     GLenum type) {
   1352   if (!feature_info_->GetTextureFormatValidator(format).IsValid(type)) {
   1353     ERRORSTATE_SET_GL_ERROR(
   1354         error_state, GL_INVALID_OPERATION, function_name,
   1355         (std::string("invalid type ") +
   1356          GLES2Util::GetStringEnum(type) + " for format " +
   1357          GLES2Util::GetStringEnum(format)).c_str());
   1358     return false;
   1359   }
   1360   return true;
   1361 }
   1362 
   1363 bool TextureManager::ValidateTextureParameters(
   1364     ErrorState* error_state, const char* function_name,
   1365     GLenum format, GLenum type, GLenum internal_format, GLint level) {
   1366   const Validators* validators = feature_info_->validators();
   1367   if (!validators->texture_format.IsValid(format)) {
   1368     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
   1369         error_state, function_name, format, "format");
   1370     return false;
   1371   }
   1372   if (!validators->pixel_type.IsValid(type)) {
   1373     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
   1374         error_state, function_name, type, "type");
   1375     return false;
   1376   }
   1377   if (format != internal_format &&
   1378       !((internal_format == GL_RGBA32F && format == GL_RGBA) ||
   1379         (internal_format == GL_RGB32F && format == GL_RGB))) {
   1380     ERRORSTATE_SET_GL_ERROR(
   1381         error_state, GL_INVALID_OPERATION, function_name,
   1382         "format != internalformat");
   1383     return false;
   1384   }
   1385   uint32 channels = GLES2Util::GetChannelsForFormat(format);
   1386   if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
   1387     ERRORSTATE_SET_GL_ERROR(
   1388         error_state, GL_INVALID_OPERATION, function_name,
   1389         (std::string("invalid format ") + GLES2Util::GetStringEnum(format) +
   1390          " for level != 0").c_str());
   1391     return false;
   1392   }
   1393   return ValidateFormatAndTypeCombination(error_state, function_name,
   1394       format, type);
   1395 }
   1396 
   1397 // Gets the texture id for a given target.
   1398 TextureRef* TextureManager::GetTextureInfoForTarget(
   1399     ContextState* state, GLenum target) {
   1400   TextureUnit& unit = state->texture_units[state->active_texture_unit];
   1401   TextureRef* texture = NULL;
   1402   switch (target) {
   1403     case GL_TEXTURE_2D:
   1404       texture = unit.bound_texture_2d.get();
   1405       break;
   1406     case GL_TEXTURE_CUBE_MAP:
   1407     case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   1408     case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   1409     case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   1410     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   1411     case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   1412     case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   1413       texture = unit.bound_texture_cube_map.get();
   1414       break;
   1415     case GL_TEXTURE_EXTERNAL_OES:
   1416       texture = unit.bound_texture_external_oes.get();
   1417       break;
   1418     case GL_TEXTURE_RECTANGLE_ARB:
   1419       texture = unit.bound_texture_rectangle_arb.get();
   1420       break;
   1421     default:
   1422       NOTREACHED();
   1423       return NULL;
   1424   }
   1425   return texture;
   1426 }
   1427 
   1428 TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault(
   1429     ContextState* state, GLenum target) {
   1430   TextureRef* texture = GetTextureInfoForTarget(state, target);
   1431   if (!texture)
   1432     return NULL;
   1433   if (texture == GetDefaultTextureInfo(target))
   1434     return NULL;
   1435   return texture;
   1436 }
   1437 
   1438 bool TextureManager::ValidateTexImage2D(
   1439     ContextState* state,
   1440     const char* function_name,
   1441     const DoTextImage2DArguments& args,
   1442     TextureRef** texture_ref) {
   1443   ErrorState* error_state = state->GetErrorState();
   1444   const Validators* validators = feature_info_->validators();
   1445   if (!validators->texture_target.IsValid(args.target)) {
   1446     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
   1447         error_state, function_name, args.target, "target");
   1448     return false;
   1449   }
   1450   if (!validators->texture_internal_format.IsValid(args.internal_format)) {
   1451     ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
   1452         error_state, function_name, args.internal_format,
   1453         "internalformat");
   1454     return false;
   1455   }
   1456   if (!ValidateTextureParameters(
   1457       error_state, function_name, args.format, args.type,
   1458       args.internal_format, args.level)) {
   1459     return false;
   1460   }
   1461   if (!ValidForTarget(args.target, args.level, args.width, args.height, 1) ||
   1462       args.border != 0) {
   1463     ERRORSTATE_SET_GL_ERROR(
   1464         error_state, GL_INVALID_VALUE, function_name,
   1465         "dimensions out of range");
   1466     return false;
   1467   }
   1468   if ((GLES2Util::GetChannelsForFormat(args.format) &
   1469        (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels) {
   1470     ERRORSTATE_SET_GL_ERROR(
   1471         error_state, GL_INVALID_OPERATION,
   1472         function_name, "can not supply data for depth or stencil textures");
   1473     return false;
   1474   }
   1475 
   1476   TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
   1477   if (!local_texture_ref) {
   1478     ERRORSTATE_SET_GL_ERROR(
   1479         error_state, GL_INVALID_OPERATION, function_name,
   1480         "unknown texture for target");
   1481     return false;
   1482   }
   1483   if (local_texture_ref->texture()->IsImmutable()) {
   1484     ERRORSTATE_SET_GL_ERROR(
   1485         error_state, GL_INVALID_OPERATION, function_name,
   1486         "texture is immutable");
   1487     return false;
   1488   }
   1489 
   1490   // TODO - verify that using the managed vs unmanaged does not matter.
   1491   // They both use the same MemoryTracker, and this call just re-routes
   1492   // to it.
   1493   if (!memory_tracker_managed_->EnsureGPUMemoryAvailable(args.pixels_size)) {
   1494     ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name,
   1495                             "out of memory");
   1496     return false;
   1497   }
   1498 
   1499   // Write the TextureReference since this is valid.
   1500   *texture_ref = local_texture_ref;
   1501   return true;
   1502 }
   1503 
   1504 void TextureManager::ValidateAndDoTexImage2D(
   1505     DecoderTextureState* texture_state,
   1506     ContextState* state,
   1507     DecoderFramebufferState* framebuffer_state,
   1508     const DoTextImage2DArguments& args) {
   1509   TextureRef* texture_ref;
   1510   if (!ValidateTexImage2D(state, "glTexImage2D", args, &texture_ref)) {
   1511     return;
   1512   }
   1513 
   1514   DoTexImage2D(texture_state, state->GetErrorState(), framebuffer_state,
   1515                texture_ref, args);
   1516 }
   1517 
   1518 void TextureManager::DoTexImage2D(
   1519     DecoderTextureState* texture_state,
   1520     ErrorState* error_state,
   1521     DecoderFramebufferState* framebuffer_state,
   1522     TextureRef* texture_ref,
   1523     const DoTextImage2DArguments& args) {
   1524   Texture* texture = texture_ref->texture();
   1525   GLsizei tex_width = 0;
   1526   GLsizei tex_height = 0;
   1527   GLenum tex_type = 0;
   1528   GLenum tex_format = 0;
   1529   bool level_is_same =
   1530       texture->GetLevelSize(args.target, args.level, &tex_width, &tex_height) &&
   1531       texture->GetLevelType(args.target, args.level, &tex_type, &tex_format) &&
   1532       args.width == tex_width && args.height == tex_height &&
   1533       args.type == tex_type && args.format == tex_format;
   1534 
   1535   if (level_is_same && !args.pixels) {
   1536     // Just set the level texture but mark the texture as uncleared.
   1537     SetLevelInfo(
   1538         texture_ref,
   1539         args.target, args.level, args.internal_format, args.width, args.height,
   1540         1, args.border, args.format, args.type, false);
   1541     texture_state->tex_image_2d_failed = false;
   1542     return;
   1543   }
   1544 
   1545   if (texture->IsAttachedToFramebuffer()) {
   1546     framebuffer_state->clear_state_dirty = true;
   1547   }
   1548 
   1549   if (texture_state->texsubimage2d_faster_than_teximage2d &&
   1550       level_is_same && args.pixels) {
   1551     {
   1552       ScopedTextureUploadTimer timer(texture_state);
   1553       glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height,
   1554                       args.format, args.type, args.pixels);
   1555     }
   1556     SetLevelCleared(texture_ref, args.target, args.level, true);
   1557     texture_state->tex_image_2d_failed = false;
   1558     return;
   1559   }
   1560 
   1561   ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, "glTexImage2D");
   1562   {
   1563     ScopedTextureUploadTimer timer(texture_state);
   1564     glTexImage2D(
   1565         args.target, args.level, args.internal_format, args.width, args.height,
   1566         args.border, args.format, args.type, args.pixels);
   1567   }
   1568   GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, "glTexImage2D");
   1569   if (error == GL_NO_ERROR) {
   1570     SetLevelInfo(
   1571         texture_ref,
   1572         args.target, args.level, args.internal_format, args.width, args.height,
   1573         1, args.border, args.format, args.type, args.pixels != NULL);
   1574     texture_state->tex_image_2d_failed = false;
   1575   }
   1576 }
   1577 
   1578 ScopedTextureUploadTimer::ScopedTextureUploadTimer(
   1579     DecoderTextureState* texture_state)
   1580     : texture_state_(texture_state),
   1581       begin_time_(base::TimeTicks::HighResNow()) {
   1582 }
   1583 
   1584 ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
   1585   texture_state_->texture_upload_count++;
   1586   texture_state_->total_texture_upload_time +=
   1587       base::TimeTicks::HighResNow() - begin_time_;
   1588 }
   1589 
   1590 }  // namespace gles2
   1591 }  // namespace gpu
   1592