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