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