// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/service/texture_manager.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <set>
#include <utility>

#include "base/bits.h"
#include "base/format_macros.h"
#include "base/lazy_instance.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/context_state.h"
#include "gpu/command_buffer/service/error_state.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/framebuffer_manager.h"
#include "gpu/command_buffer/service/gl_stream_texture_image.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_state_restorer.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/trace_util.h"

namespace gpu {
namespace gles2 {

namespace {

// This should contain everything to uniquely identify a Texture.
const char TextureTag[] = "|Texture|";
struct TextureSignature {
  GLenum target_;
  GLint level_;
  GLenum min_filter_;
  GLenum mag_filter_;
  GLenum wrap_r_;
  GLenum wrap_s_;
  GLenum wrap_t_;
  GLenum usage_;
  GLenum internal_format_;
  GLenum compare_func_;
  GLenum compare_mode_;
  GLsizei width_;
  GLsizei height_;
  GLsizei depth_;
  GLfloat max_lod_;
  GLfloat min_lod_;
  GLint base_level_;
  GLint border_;
  GLint max_level_;
  GLenum format_;
  GLenum type_;
  bool has_image_;
  bool can_render_;
  bool can_render_to_;
  bool npot_;
  bool emulating_rgb_;

  // Since we will be hashing this signature structure, the padding must be
  // zero initialized. Although the C++11 specifications specify that this is
  // true, we will use a constructor with a memset to further enforce it instead
  // of relying on compilers adhering to this deep dark corner specification.
  TextureSignature(GLenum target,
                   GLint level,
                   const SamplerState& sampler_state,
                   GLenum usage,
                   GLenum internal_format,
                   GLsizei width,
                   GLsizei height,
                   GLsizei depth,
                   GLint base_level,
                   GLint border,
                   GLint max_level,
                   GLenum format,
                   GLenum type,
                   bool has_image,
                   bool can_render,
                   bool can_render_to,
                   bool npot,
                   bool emulating_rgb) {
    memset(this, 0, sizeof(TextureSignature));
    target_ = target;
    level_ = level;
    min_filter_ = sampler_state.min_filter;
    mag_filter_ = sampler_state.mag_filter;
    wrap_r_ = sampler_state.wrap_r;
    wrap_s_ = sampler_state.wrap_s;
    wrap_t_ = sampler_state.wrap_t;
    usage_ = usage;
    internal_format_ = internal_format;
    compare_func_ = sampler_state.compare_func;
    compare_mode_ = sampler_state.compare_mode;
    width_ = width;
    height_ = height;
    depth_ = depth;
    max_lod_ = sampler_state.max_lod;
    min_lod_ = sampler_state.min_lod;
    base_level_ = base_level;
    border_ = border;
    max_level_ = max_level;
    format_ = format;
    type_ = type;
    has_image_ = has_image;
    can_render_ = can_render;
    can_render_to_ = can_render_to;
    npot_ = npot;
    emulating_rgb_ = emulating_rgb;
  }
};

class FormatTypeValidator {
 public:
  FormatTypeValidator() {
    static const FormatType kSupportedFormatTypes[] = {
        // ES2.
        {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE},
        {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
        {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE},
        {GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
        {GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1},
        {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE},
        {GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE},
        {GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE},
        // Exposed by GL_OES_texture_float and GL_OES_texture_half_float
        {GL_RGB, GL_RGB, GL_FLOAT},
        {GL_RGBA, GL_RGBA, GL_FLOAT},
        {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT},
        {GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT},
        {GL_ALPHA, GL_ALPHA, GL_FLOAT},
        {GL_RGB, GL_RGB, GL_HALF_FLOAT_OES},
        {GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES},
        {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES},
        {GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES},
        {GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES},
        // Exposed by GL_ANGLE_depth_texture
        {GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT},
        {GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT},
        {GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8},
        // Exposed by GL_EXT_sRGB
        {GL_SRGB, GL_SRGB, GL_UNSIGNED_BYTE},
        {GL_SRGB_ALPHA, GL_SRGB_ALPHA, GL_UNSIGNED_BYTE},
        // Exposed by GL_EXT_texture_format_BGRA8888
        {GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE},
        // Exposed by GL_EXT_texture_rg
        {GL_RED, GL_RED, GL_UNSIGNED_BYTE},
        {GL_RG, GL_RG, GL_UNSIGNED_BYTE},
        {GL_RED, GL_RED, GL_FLOAT},
        {GL_RG, GL_RG, GL_FLOAT},
        {GL_RED, GL_RED, GL_HALF_FLOAT_OES},
        {GL_RG, GL_RG, GL_HALF_FLOAT_OES},

        // ES3.
        {GL_R8, GL_RED, GL_UNSIGNED_BYTE},
        {GL_R8_SNORM, GL_RED, GL_BYTE},
        {GL_R16F, GL_RED, GL_HALF_FLOAT},
        {GL_R16F, GL_RED, GL_FLOAT},
        {GL_R32F, GL_RED, GL_FLOAT},
        {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE},
        {GL_R8I, GL_RED_INTEGER, GL_BYTE},
        {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT},
        {GL_R16I, GL_RED_INTEGER, GL_SHORT},
        {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT},
        {GL_R32I, GL_RED_INTEGER, GL_INT},
        {GL_RG8, GL_RG, GL_UNSIGNED_BYTE},
        {GL_RG8_SNORM, GL_RG, GL_BYTE},
        {GL_RG16F, GL_RG, GL_HALF_FLOAT},
        {GL_RG16F, GL_RG, GL_FLOAT},
        {GL_RG32F, GL_RG, GL_FLOAT},
        {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE},
        {GL_RG8I, GL_RG_INTEGER, GL_BYTE},
        {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT},
        {GL_RG16I, GL_RG_INTEGER, GL_SHORT},
        {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT},
        {GL_RG32I, GL_RG_INTEGER, GL_INT},
        {GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},
        {GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE},
        {GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE},
        {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
        {GL_RGB8_SNORM, GL_RGB, GL_BYTE},
        {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV},
        {GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT},
        {GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT},
        {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV},
        {GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT},
        {GL_RGB9_E5, GL_RGB, GL_FLOAT},
        {GL_RGB16F, GL_RGB, GL_HALF_FLOAT},
        {GL_RGB16F, GL_RGB, GL_FLOAT},
        {GL_RGB32F, GL_RGB, GL_FLOAT},
        {GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE},
        {GL_RGB8I, GL_RGB_INTEGER, GL_BYTE},
        {GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT},
        {GL_RGB16I, GL_RGB_INTEGER, GL_SHORT},
        {GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT},
        {GL_RGB32I, GL_RGB_INTEGER, GL_INT},
        {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
        {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE},
        {GL_RGBA8_SNORM, GL_RGBA, GL_BYTE},
        {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE},
        {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1},
        {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV},
        {GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE},
        {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4},
        {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV},
        {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT},
        {GL_RGBA16F, GL_RGBA, GL_FLOAT},
        {GL_RGBA32F, GL_RGBA, GL_FLOAT},
        {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE},
        {GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE},
        {GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV},
        {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT},
        {GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT},
        {GL_RGBA32I, GL_RGBA_INTEGER, GL_INT},
        {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT},
        {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT},
        {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT},
        {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT},
        {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT},
        {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8},
        {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL,
         GL_FLOAT_32_UNSIGNED_INT_24_8_REV},
    };

    for (size_t ii = 0; ii < arraysize(kSupportedFormatTypes); ++ii) {
      supported_combinations_.insert(kSupportedFormatTypes[ii]);
    }
  }

  // This may be accessed from multiple threads.
  bool IsValid(GLenum internal_format, GLenum format, GLenum type) const {
    FormatType query = { internal_format, format, type };
    return supported_combinations_.find(query) != supported_combinations_.end();
  }

 private:
  // TODO(zmo): once std::tuple is allowed, switch over to that.
  struct FormatType {
    GLenum internal_format;
    GLenum format;
    GLenum type;
  };

  struct FormatTypeCompare {
    bool operator() (const FormatType& lhs, const FormatType& rhs) const {
      return (lhs.internal_format < rhs.internal_format ||
              ((lhs.internal_format == rhs.internal_format) &&
               (lhs.format < rhs.format)) ||
              ((lhs.internal_format == rhs.internal_format) &&
               (lhs.format == rhs.format) &&
               (lhs.type < rhs.type)));
    }
  };

  // This class needs to be thread safe, so once supported_combinations_
  // are initialized in the constructor, it should never be modified later.
  std::set<FormatType, FormatTypeCompare> supported_combinations_;
};

static const Texture::CompatibilitySwizzle kSwizzledFormats[] = {
    {GL_ALPHA, GL_RED, GL_ZERO, GL_ZERO, GL_ZERO, GL_RED},
    {GL_LUMINANCE, GL_RED, GL_RED, GL_RED, GL_RED, GL_ONE},
    {GL_LUMINANCE_ALPHA, GL_RG, GL_RED, GL_RED, GL_RED, GL_GREEN},
};

// static
const Texture::CompatibilitySwizzle* GetCompatibilitySwizzle(GLenum format) {
  size_t count = arraysize(kSwizzledFormats);
  for (size_t i = 0; i < count; ++i) {
    if (kSwizzledFormats[i].format == format)
      return &kSwizzledFormats[i];
  }
  return nullptr;
}

GLenum GetSwizzleForChannel(GLenum channel,
                            const Texture::CompatibilitySwizzle* swizzle) {
  if (!swizzle)
    return channel;

  switch (channel) {
    case GL_ZERO:
      return GL_ZERO;
    case GL_ONE:
      return GL_ONE;
    case GL_RED:
      return swizzle->red;
    case GL_GREEN:
      return swizzle->green;
    case GL_BLUE:
      return swizzle->blue;
    case GL_ALPHA:
      return swizzle->alpha;
    default:
      NOTREACHED();
      return GL_NONE;
  }
}

// A 32-bit and 64-bit compatible way of converting a pointer to a GLuint.
GLuint ToGLuint(const void* ptr) {
  return static_cast<GLuint>(reinterpret_cast<size_t>(ptr));
}

base::LazyInstance<const FormatTypeValidator>::Leaky g_format_type_validator =
    LAZY_INSTANCE_INITIALIZER;

}  // namespace anonymous

TextureManager::DestructionObserver::DestructionObserver() {}

TextureManager::DestructionObserver::~DestructionObserver() {}

TextureManager::~TextureManager() {
  for (unsigned int i = 0; i < destruction_observers_.size(); i++)
    destruction_observers_[i]->OnTextureManagerDestroying(this);

  DCHECK(textures_.empty());

  // If this triggers, that means something is keeping a reference to
  // a Texture belonging to this.
  CHECK_EQ(texture_count_, 0u);

  DCHECK_EQ(0, num_unsafe_textures_);
  DCHECK_EQ(0, num_uncleared_mips_);
  DCHECK_EQ(0, num_images_);

  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);
}

void TextureManager::Destroy(bool have_context) {
  have_context_ = have_context;
  textures_.clear();
  for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
    default_textures_[ii] = NULL;
  }

  if (have_context) {
    glDeleteTextures(arraysize(black_texture_ids_), black_texture_ids_);
  }

  DCHECK_EQ(0u, memory_type_tracker_->GetMemRepresented());
}

TextureBase::TextureBase(GLuint service_id)
    : service_id_(service_id), mailbox_manager_(nullptr) {}

TextureBase::~TextureBase() {
  DCHECK_EQ(nullptr, mailbox_manager_);
}

void TextureBase::DeleteFromMailboxManager() {
  if (mailbox_manager_) {
    mailbox_manager_->TextureDeleted(this);
    mailbox_manager_ = nullptr;
  }
}

void TextureBase::SetMailboxManager(MailboxManager* mailbox_manager) {
  DCHECK(!mailbox_manager_ || mailbox_manager_ == mailbox_manager);
  mailbox_manager_ = mailbox_manager;
}

TexturePassthrough::TexturePassthrough(GLuint service_id)
    : TextureBase(service_id), have_context_(true) {}

TexturePassthrough::~TexturePassthrough() {
  DeleteFromMailboxManager();
  if (have_context_) {
    glDeleteTextures(1, &service_id_);
  }
}

void TexturePassthrough::MarkContextLost() {
  have_context_ = false;
}

Texture::Texture(GLuint service_id)
    : TextureBase(service_id),
      memory_tracking_ref_(NULL),
      owned_service_id_(service_id),
      cleared_(true),
      num_uncleared_mips_(0),
      num_npot_faces_(0),
      target_(0),
      usage_(GL_NONE),
      base_level_(0),
      max_level_(1000),
      swizzle_r_(GL_RED),
      swizzle_g_(GL_GREEN),
      swizzle_b_(GL_BLUE),
      swizzle_a_(GL_ALPHA),
      max_level_set_(-1),
      texture_complete_(false),
      texture_mips_dirty_(false),
      cube_complete_(false),
      npot_(false),
      has_been_bound_(false),
      framebuffer_attachment_count_(0),
      immutable_(false),
      has_images_(false),
      estimated_size_(0),
      can_render_condition_(CAN_RENDER_ALWAYS),
      texture_max_anisotropy_initialized_(false),
      compatibility_swizzle_(nullptr),
      emulating_rgb_(false) {}

Texture::~Texture() {
  DeleteFromMailboxManager();
}

void Texture::AddTextureRef(TextureRef* ref) {
  DCHECK(refs_.find(ref) == refs_.end());
  refs_.insert(ref);
  if (!memory_tracking_ref_) {
    memory_tracking_ref_ = ref;
    GetMemTracker()->TrackMemAlloc(estimated_size());
  }
}

void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) {
  if (memory_tracking_ref_ == ref) {
    GetMemTracker()->TrackMemFree(estimated_size());
    memory_tracking_ref_ = NULL;
  }
  size_t result = refs_.erase(ref);
  DCHECK_EQ(result, 1u);
  if (refs_.empty()) {
    if (have_context)
      glDeleteTextures(1, &owned_service_id_);
    delete this;
  } else if (memory_tracking_ref_ == NULL) {
    // TODO(piman): tune ownership semantics for cross-context group shared
    // textures.
    memory_tracking_ref_ = *refs_.begin();
    GetMemTracker()->TrackMemAlloc(estimated_size());
  }
}

MemoryTypeTracker* Texture::GetMemTracker() {
  DCHECK(memory_tracking_ref_);
  return memory_tracking_ref_->manager()->GetMemTracker();
}

Texture::LevelInfo::LevelInfo()
    : target(0),
      level(-1),
      internal_format(0),
      width(0),
      height(0),
      depth(0),
      border(0),
      format(0),
      type(0),
      image_state(UNBOUND),
      estimated_size(0),
      internal_workaround(false) {}

Texture::LevelInfo::LevelInfo(const LevelInfo& rhs)
    : cleared_rect(rhs.cleared_rect),
      target(rhs.target),
      level(rhs.level),
      internal_format(rhs.internal_format),
      width(rhs.width),
      height(rhs.height),
      depth(rhs.depth),
      border(rhs.border),
      format(rhs.format),
      type(rhs.type),
      image(rhs.image),
      image_state(rhs.image_state),
      estimated_size(rhs.estimated_size),
      internal_workaround(rhs.internal_workaround) {}

Texture::LevelInfo::~LevelInfo() {
}

Texture::FaceInfo::FaceInfo()
    : num_mip_levels(0) {
}

Texture::FaceInfo::FaceInfo(const FaceInfo& other) = default;

Texture::FaceInfo::~FaceInfo() {
}

Texture::CanRenderCondition Texture::GetCanRenderCondition() const {
  if (target_ == 0)
    return CAN_RENDER_ALWAYS;

  if (target_ != GL_TEXTURE_EXTERNAL_OES) {
    if (face_infos_.empty() ||
        static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size()) {
      return CAN_RENDER_NEVER;
    }
    const Texture::LevelInfo& first_face =
        face_infos_[0].level_infos[base_level_];
    if (first_face.width == 0 ||
        first_face.height == 0 ||
        first_face.depth == 0) {
      return CAN_RENDER_NEVER;
    }
  }

  if (target_ == GL_TEXTURE_CUBE_MAP && !cube_complete())
    return CAN_RENDER_NEVER;

  // Texture may be renderable, but it depends on the sampler it's used with,
  // the context that's using it, and the extensions available.
  return CAN_RENDER_NEEDS_VALIDATION;
}

bool Texture::CanRender(const FeatureInfo* feature_info) const {
  return CanRenderWithSampler(feature_info, sampler_state());
}

bool Texture::CanRenderWithSampler(const FeatureInfo* feature_info,
                                   const SamplerState& sampler_state) const {
  switch (can_render_condition_) {
    case CAN_RENDER_ALWAYS:
      return true;
    case CAN_RENDER_NEVER:
      return false;
    case CAN_RENDER_NEEDS_VALIDATION:
      break;
  }

  bool needs_mips = sampler_state.min_filter != GL_NEAREST &&
                    sampler_state.min_filter != GL_LINEAR;
  if (target_ == GL_TEXTURE_EXTERNAL_OES) {
    if (needs_mips) {
      return false;
    }
    if (sampler_state.wrap_s != GL_CLAMP_TO_EDGE ||
        sampler_state.wrap_t != GL_CLAMP_TO_EDGE) {
      return false;
    }
    return true;
  }

  if (needs_mips && !texture_complete()) {
    return false;
  }
  if ((sampler_state.min_filter != GL_NEAREST &&
       sampler_state.min_filter != GL_NEAREST_MIPMAP_NEAREST) ||
      sampler_state.mag_filter != GL_NEAREST) {
    DCHECK(!face_infos_.empty());
    DCHECK_LT(static_cast<size_t>(base_level_),
              face_infos_[0].level_infos.size());
    const Texture::LevelInfo& first_level =
        face_infos_[0].level_infos[base_level_];
    if ((GLES2Util::GetChannelsForFormat(first_level.internal_format) &
         (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 ||
        feature_info->validators()->compressed_texture_format.IsValid(
            first_level.internal_format)) {
      // TODO(zmo): The assumption that depth/stencil textures and compressed
      // textures are all filterable may not be true in the future.
    } else {
      if (!Texture::TextureFilterable(feature_info,
                                      first_level.internal_format,
                                      first_level.type)) {
        return false;
      }
    }
  }

  if (!feature_info->IsES3Enabled()) {
    bool is_npot_compatible = !needs_mips &&
        sampler_state.wrap_s == GL_CLAMP_TO_EDGE &&
        sampler_state.wrap_t == GL_CLAMP_TO_EDGE;

    if (!is_npot_compatible) {
      if (target_ == GL_TEXTURE_RECTANGLE_ARB)
        return false;
      else if (npot())
        return feature_info->feature_flags().npot_ok;
    }
  }

  return true;
}

void Texture::AddToSignature(
    const FeatureInfo* feature_info,
    GLenum target,
    GLint level,
    std::string* signature) const {
  DCHECK(feature_info);
  DCHECK(signature);
  DCHECK_GE(level, 0);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  DCHECK_LT(static_cast<size_t>(face_index),
            face_infos_.size());
  DCHECK_LT(static_cast<size_t>(level),
            face_infos_[face_index].level_infos.size());

  const Texture::LevelInfo& info =
      face_infos_[face_index].level_infos[level];

  TextureSignature signature_data(target,
                                  level,
                                  sampler_state_,
                                  usage_,
                                  info.internal_format,
                                  info.width,
                                  info.height,
                                  info.depth,
                                  base_level_,
                                  info.border,
                                  max_level_,
                                  info.format,
                                  info.type,
                                  info.image.get() != NULL,
                                  CanRender(feature_info),
                                  CanRenderTo(feature_info, level),
                                  npot_,
                                  emulating_rgb_);

  signature->append(TextureTag, sizeof(TextureTag));
  signature->append(reinterpret_cast<const char*>(&signature_data),
                    sizeof(signature_data));
}

void Texture::MarkMipmapsGenerated() {
  for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
    const Texture::FaceInfo& face_info = face_infos_[ii];
    const Texture::LevelInfo& level0_info = face_info.level_infos[base_level_];
    GLsizei width = level0_info.width;
    GLsizei height = level0_info.height;
    GLsizei depth = level0_info.depth;
    GLenum target = target_ == GL_TEXTURE_CUBE_MAP ?
        GLES2Util::IndexToGLFaceTarget(ii) : target_;

    const GLsizei num_mips = face_info.num_mip_levels;
    for (GLsizei level = base_level_ + 1;
         level < base_level_ + num_mips; ++level) {
      width = std::max(1, width >> 1);
      height = std::max(1, height >> 1);
      depth = target == GL_TEXTURE_2D_ARRAY ? depth : std::max(1, depth >> 1);
      SetLevelInfo(target, level, level0_info.internal_format,
                   width, height, depth, level0_info.border, level0_info.format,
                   level0_info.type, gfx::Rect(width, height));
    }
  }
}

void Texture::SetTarget(GLenum target, GLint max_levels) {
  DCHECK_EQ(0u, target_);  // you can only set this once.
  target_ = target;
  size_t num_faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
  face_infos_.resize(num_faces);
  for (size_t ii = 0; ii < num_faces; ++ii) {
    face_infos_[ii].level_infos.resize(max_levels);
  }

  if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) {
    sampler_state_.min_filter = GL_LINEAR;
    sampler_state_.wrap_s = sampler_state_.wrap_t = GL_CLAMP_TO_EDGE;
  }

  if (target == GL_TEXTURE_EXTERNAL_OES) {
    immutable_ = true;
  }
  Update();
  UpdateCanRenderCondition();
}

bool Texture::CanGenerateMipmaps(const FeatureInfo* feature_info) const {
  if ((npot() && !feature_info->feature_flags().npot_ok) ||
      face_infos_.empty() ||
      target_ == GL_TEXTURE_EXTERNAL_OES ||
      target_ == GL_TEXTURE_RECTANGLE_ARB) {
    return false;
  }

  if (static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size()) {
    return false;
  }

  // Can't generate mips for depth or stencil textures.
  const Texture::LevelInfo& base = face_infos_[0].level_infos[base_level_];
  uint32_t channels = GLES2Util::GetChannelsForFormat(base.format);
  if (channels & (GLES2Util::kDepth | GLES2Util::kStencil)) {
    return false;
  }

  if (!Texture::ColorRenderable(feature_info, base.internal_format) ||
      !Texture::TextureFilterable(
          feature_info, base.internal_format, base.type)) {
    return false;
  }

  for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
    const LevelInfo& info = face_infos_[ii].level_infos[base_level_];
    if ((info.target == 0) ||
        feature_info->validators()->compressed_texture_format.IsValid(
            info.internal_format) ||
        info.image.get()) {
      return false;
    }
  }
  if (face_infos_.size() == 6 && !cube_complete_) {
    return false;
  }
  return true;
}

bool Texture::TextureIsNPOT(GLsizei width,
                            GLsizei height,
                            GLsizei depth) {
  return (GLES2Util::IsNPOT(width) ||
          GLES2Util::IsNPOT(height) ||
          GLES2Util::IsNPOT(depth));
}

bool Texture::TextureFaceComplete(const Texture::LevelInfo& first_face,
                                  size_t face_index,
                                  GLenum target,
                                  GLenum internal_format,
                                  GLsizei width,
                                  GLsizei height,
                                  GLsizei depth,
                                  GLenum format,
                                  GLenum type) {
  bool complete = (target != 0 && depth == 1);
  if (face_index != 0) {
    complete &= (width == first_face.width &&
                 height == first_face.height &&
                 internal_format == first_face.internal_format &&
                 format == first_face.format &&
                 type == first_face.type);
  }
  return complete;
}

bool Texture::TextureMipComplete(const Texture::LevelInfo& base_level_face,
                                 GLenum target,
                                 GLint level_diff,
                                 GLenum internal_format,
                                 GLsizei width,
                                 GLsizei height,
                                 GLsizei depth,
                                 GLenum format,
                                 GLenum type) {
  bool complete = (target != 0);
  if (level_diff > 0) {
    const GLsizei mip_width = std::max(1, base_level_face.width >> level_diff);
    const GLsizei mip_height =
        std::max(1, base_level_face.height >> level_diff);
    const GLsizei mip_depth = target == GL_TEXTURE_2D_ARRAY ?
        base_level_face.depth :
        std::max(1, base_level_face.depth >> level_diff);

    complete &= (width == mip_width &&
                 height == mip_height &&
                 depth == mip_depth &&
                 internal_format == base_level_face.internal_format &&
                 format == base_level_face.format &&
                 type == base_level_face.type);
  }
  return complete;
}

// static
bool Texture::ColorRenderable(const FeatureInfo* feature_info,
                              GLenum internal_format) {
  if (feature_info->validators()->texture_unsized_internal_format.IsValid(
      internal_format)) {
    return true;
  }
  return feature_info->validators()->
      texture_sized_color_renderable_internal_format.IsValid(internal_format);
}

// static
bool Texture::TextureFilterable(const FeatureInfo* feature_info,
                                GLenum internal_format,
                                GLenum type) {
  if (feature_info->validators()->texture_unsized_internal_format.IsValid(
      internal_format)) {
    switch (type) {
      case GL_FLOAT:
        return feature_info->feature_flags().enable_texture_float_linear;
      case GL_HALF_FLOAT_OES:
        return feature_info->feature_flags().enable_texture_half_float_linear;
      default:
        // GL_HALF_FLOAT is ES3 only and should only be used with sized formats.
        return true;
    }
  }
  return feature_info->validators()->
      texture_sized_texture_filterable_internal_format.IsValid(internal_format);
}

void Texture::SetLevelClearedRect(GLenum target,
                                  GLint level,
                                  const gfx::Rect& cleared_rect) {
  DCHECK_GE(level, 0);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  DCHECK_LT(static_cast<size_t>(face_index),
            face_infos_.size());
  DCHECK_LT(static_cast<size_t>(level),
            face_infos_[face_index].level_infos.size());
  Texture::LevelInfo& info =
      face_infos_[face_index].level_infos[level];
  UpdateMipCleared(&info, info.width, info.height, cleared_rect);
  UpdateCleared();
}

void Texture::SetLevelCleared(GLenum target, GLint level, bool cleared) {
  DCHECK_GE(level, 0);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  DCHECK_LT(static_cast<size_t>(face_index), face_infos_.size());
  DCHECK_LT(static_cast<size_t>(level),
            face_infos_[face_index].level_infos.size());
  Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
  UpdateMipCleared(&info, info.width, info.height,
                   cleared ? gfx::Rect(info.width, info.height) : gfx::Rect());
  UpdateCleared();
}

void Texture::UpdateCleared() {
  if (face_infos_.empty()) {
    return;
  }

  const bool cleared = (num_uncleared_mips_ == 0);

  // If texture is uncleared and is attached to a framebuffer,
  // that framebuffer must be marked possibly incomplete.
  if (!cleared && IsAttachedToFramebuffer()) {
    IncAllFramebufferStateChangeCount();
  }

  UpdateSafeToRenderFrom(cleared);
}

void Texture::UpdateSafeToRenderFrom(bool cleared) {
  if (cleared_ == cleared)
    return;
  cleared_ = cleared;
  int delta = cleared ? -1 : +1;
  for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    (*it)->manager()->UpdateSafeToRenderFrom(delta);
}

void Texture::UpdateMipCleared(LevelInfo* info,
                               GLsizei width,
                               GLsizei height,
                               const gfx::Rect& cleared_rect) {
  bool was_cleared = info->cleared_rect == gfx::Rect(info->width, info->height);
  info->width = width;
  info->height = height;
  info->cleared_rect = cleared_rect;
  bool cleared = info->cleared_rect == gfx::Rect(info->width, info->height);
  if (cleared == was_cleared)
    return;
  int delta = cleared ? -1 : +1;
  num_uncleared_mips_ += delta;
  for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    (*it)->manager()->UpdateUnclearedMips(delta);
}

void Texture::UpdateCanRenderCondition() {
  can_render_condition_ = GetCanRenderCondition();
}

void Texture::UpdateHasImages() {
  if (face_infos_.empty())
    return;

  bool has_images = false;
  for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
    for (size_t jj = 0; jj < face_infos_[ii].level_infos.size(); ++jj) {
      const Texture::LevelInfo& info = face_infos_[ii].level_infos[jj];
      if (info.image.get() != NULL) {
        has_images = true;
        break;
      }
    }
  }

  if (has_images_ == has_images)
    return;
  has_images_ = has_images;
  int delta = has_images ? +1 : -1;
  for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    (*it)->manager()->UpdateNumImages(delta);
}

void Texture::UpdateEmulatingRGB() {
  for (const FaceInfo& face_info : face_infos_) {
    for (const LevelInfo& level_info : face_info.level_infos) {
      if (level_info.image && level_info.image->EmulatingRGB()) {
        emulating_rgb_ = true;
        return;
      }
    }
  }
  emulating_rgb_ = false;
}


void Texture::IncAllFramebufferStateChangeCount() {
  for (RefSet::iterator it = refs_.begin(); it != refs_.end(); ++it)
    (*it)->manager()->IncFramebufferStateChangeCount();
}

void Texture::UpdateBaseLevel(GLint base_level) {
  if (base_level_ == base_level)
    return;
  base_level_ = base_level;

  UpdateNumMipLevels();
}

void Texture::UpdateMaxLevel(GLint max_level) {
  if (max_level_ == max_level)
    return;
  max_level_ = max_level;

  UpdateNumMipLevels();
}

void Texture::UpdateNumMipLevels() {
  if (face_infos_.empty())
    return;

  for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
    Texture::FaceInfo& face_info = face_infos_[ii];
    if (static_cast<size_t>(base_level_) >= face_info.level_infos.size())
      continue;
    const Texture::LevelInfo& info = face_info.level_infos[base_level_];
    face_info.num_mip_levels = std::min(
        std::max(0, max_level_ - base_level_ + 1),
        TextureManager::ComputeMipMapCount(
            target_, info.width, info.height, info.depth));
  }

  // mipmap-completeness needs to be re-evaluated.
  texture_mips_dirty_ = true;
}

void Texture::SetLevelInfo(GLenum target,
                           GLint level,
                           GLenum internal_format,
                           GLsizei width,
                           GLsizei height,
                           GLsizei depth,
                           GLint border,
                           GLenum format,
                           GLenum type,
                           const gfx::Rect& cleared_rect) {
  DCHECK_GE(level, 0);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  DCHECK_LT(static_cast<size_t>(face_index),
            face_infos_.size());
  DCHECK_LT(static_cast<size_t>(level),
            face_infos_[face_index].level_infos.size());
  DCHECK_GE(width, 0);
  DCHECK_GE(height, 0);
  DCHECK_GE(depth, 0);
  Texture::LevelInfo& info =
      face_infos_[face_index].level_infos[level];

  // Update counters only if any attributes have changed. Counters are
  // comparisons between the old and new values so it must be done before any
  // assignment has been done to the LevelInfo.
  if (info.target != target ||
      info.internal_format != internal_format ||
      info.width != width ||
      info.height != height ||
      info.depth != depth ||
      info.format != format ||
      info.type != type) {
    if (level == base_level_) {
      // Calculate the mip level count.
      face_infos_[face_index].num_mip_levels = std::min(
          std::max(0, max_level_ - base_level_ + 1),
          TextureManager::ComputeMipMapCount(target_, width, height, depth));

      // Update NPOT face count for the first level.
      bool prev_npot = TextureIsNPOT(info.width, info.height, info.depth);
      bool now_npot = TextureIsNPOT(width, height, depth);
      if (prev_npot != now_npot)
        num_npot_faces_ += now_npot ? 1 : -1;
    }

    // Signify that at least one of the mips has changed.
    texture_mips_dirty_ = true;
  }

  info.target = target;
  info.level = level;
  info.internal_format = internal_format;
  info.depth = depth;
  info.border = border;
  info.format = format;
  info.type = type;
  info.image = 0;
  info.stream_texture_image = 0;
  info.image_state = UNBOUND;
  info.internal_workaround = false;

  UpdateMipCleared(&info, width, height, cleared_rect);

  estimated_size_ -= info.estimated_size;
  GLES2Util::ComputeImageDataSizes(
      width, height, depth, format, type, 4, &info.estimated_size, NULL, NULL);
  estimated_size_ += info.estimated_size;

  max_level_set_ = std::max(max_level_set_, level);
  Update();
  UpdateCleared();
  UpdateCanRenderCondition();
  UpdateHasImages();
  if (IsAttachedToFramebuffer()) {
    // TODO(gman): If textures tracked which framebuffers they were attached to
    // we could just mark those framebuffers as not complete.
    IncAllFramebufferStateChangeCount();
  }
}

void Texture::SetStreamTextureServiceId(GLuint service_id) {
  GLuint new_service_id = service_id ? service_id : owned_service_id_;

  // Take no action if this isn't an OES_EXTERNAL texture.
  if (target_ && target_ != GL_TEXTURE_EXTERNAL_OES)
    return;

  if (service_id_ != new_service_id) {
    service_id_ = new_service_id;
    IncrementManagerServiceIdGeneration();
    if (gl::GLContext* context = gl::GLContext::GetCurrent()) {
      // It would be preferable to pass in the decoder, and ask it to do this
      // instead.  However, there are several cases, such as TextureDefinition,
      // that show up without a clear context owner.  So, instead, we use the
      // current state's state restorer.
      if (gl::GLStateRestorer* restorer = context->GetGLStateRestorer())
        restorer->RestoreAllExternalTextureBindingsIfNeeded();
    }
  }
}

void Texture::MarkLevelAsInternalWorkaround(GLenum target, GLint level) {
  DCHECK_GE(level, 0);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  DCHECK_LT(static_cast<size_t>(face_index),
            face_infos_.size());
  DCHECK_LT(static_cast<size_t>(level),
            face_infos_[face_index].level_infos.size());
  Texture::LevelInfo& info =
      face_infos_[face_index].level_infos[level];
  info.internal_workaround = true;
}

bool Texture::ValidForTexture(
    GLint target,
    GLint level,
    GLint xoffset,
    GLint yoffset,
    GLint zoffset,
    GLsizei width,
    GLsizei height,
    GLsizei depth) const {
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  if (level >= 0 && face_index < face_infos_.size() &&
      static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
    const LevelInfo& info = face_infos_[face_index].level_infos[level];
    int32_t max_x;
    int32_t max_y;
    int32_t max_z;
    return SafeAddInt32(xoffset, width, &max_x) &&
           SafeAddInt32(yoffset, height, &max_y) &&
           SafeAddInt32(zoffset, depth, &max_z) &&
           xoffset >= 0 &&
           yoffset >= 0 &&
           zoffset >= 0 &&
           max_x <= info.width &&
           max_y <= info.height &&
           max_z <= info.depth;
  }
  return false;
}

bool Texture::GetLevelSize(
    GLint target, GLint level,
    GLsizei* width, GLsizei* height, GLsizei* depth) const {
  DCHECK(width);
  DCHECK(height);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  if (level >= 0 && face_index < face_infos_.size() &&
      static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
    const LevelInfo& info = face_infos_[face_index].level_infos[level];
    if (info.target != 0) {
      *width = info.width;
      *height = info.height;
      if (depth)
        *depth = info.depth;
      return true;
    }
  }
  return false;
}

bool Texture::GetLevelType(
    GLint target, GLint level, GLenum* type, GLenum* internal_format) const {
  DCHECK(type);
  DCHECK(internal_format);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  if (level >= 0 && face_index < face_infos_.size() &&
      static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
    const LevelInfo& info = face_infos_[face_index].level_infos[level];
    if (info.target != 0) {
      *type = info.type;
      *internal_format = info.internal_format;
      return true;
    }
  }
  return false;
}

GLenum Texture::SetParameteri(
    const FeatureInfo* feature_info, GLenum pname, GLint param) {
  DCHECK(feature_info);

  if (target_ == GL_TEXTURE_EXTERNAL_OES ||
      target_ == GL_TEXTURE_RECTANGLE_ARB) {
    if (pname == GL_TEXTURE_MIN_FILTER &&
        (param != GL_NEAREST && param != GL_LINEAR))
      return GL_INVALID_ENUM;
    if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
        param != GL_CLAMP_TO_EDGE)
      return GL_INVALID_ENUM;
  }

  switch (pname) {
    case GL_TEXTURE_MIN_LOD:
    case GL_TEXTURE_MAX_LOD:
      {
        GLfloat fparam = static_cast<GLfloat>(param);
        return SetParameterf(feature_info, pname, fparam);
      }
    case GL_TEXTURE_MIN_FILTER:
      if (!feature_info->validators()->texture_min_filter_mode.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      sampler_state_.min_filter = param;
      break;
    case GL_TEXTURE_MAG_FILTER:
      if (!feature_info->validators()->texture_mag_filter_mode.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      sampler_state_.mag_filter = param;
      break;
    case GL_TEXTURE_WRAP_R:
      if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      sampler_state_.wrap_r = param;
      break;
    case GL_TEXTURE_WRAP_S:
      if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      sampler_state_.wrap_s = param;
      break;
    case GL_TEXTURE_WRAP_T:
      if (!feature_info->validators()->texture_wrap_mode.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      sampler_state_.wrap_t = param;
      break;
    case GL_TEXTURE_COMPARE_FUNC:
      if (!feature_info->validators()->texture_compare_func.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      sampler_state_.compare_func = param;
      break;
    case GL_TEXTURE_COMPARE_MODE:
      if (!feature_info->validators()->texture_compare_mode.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      sampler_state_.compare_mode = param;
      break;
    case GL_TEXTURE_BASE_LEVEL:
      if (param < 0) {
        return GL_INVALID_VALUE;
      }
      UpdateBaseLevel(param);
      break;
    case GL_TEXTURE_MAX_LEVEL:
      if (param < 0) {
        return GL_INVALID_VALUE;
      }
      UpdateMaxLevel(param);
      break;
    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
      if (param < 1) {
        return GL_INVALID_VALUE;
      }
      break;
    case GL_TEXTURE_USAGE_ANGLE:
      if (!feature_info->validators()->texture_usage.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      usage_ = param;
      break;
    case GL_TEXTURE_SWIZZLE_R:
      if (!feature_info->validators()->texture_swizzle.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      swizzle_r_ = param;
      break;
    case GL_TEXTURE_SWIZZLE_G:
      if (!feature_info->validators()->texture_swizzle.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      swizzle_g_ = param;
      break;
    case GL_TEXTURE_SWIZZLE_B:
      if (!feature_info->validators()->texture_swizzle.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      swizzle_b_ = param;
      break;
    case GL_TEXTURE_SWIZZLE_A:
      if (!feature_info->validators()->texture_swizzle.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      swizzle_a_ = param;
      break;
    case GL_TEXTURE_IMMUTABLE_FORMAT:
    case GL_TEXTURE_IMMUTABLE_LEVELS:
      return GL_INVALID_ENUM;
    default:
      NOTREACHED();
      return GL_INVALID_ENUM;
  }
  Update();
  UpdateCleared();
  UpdateCanRenderCondition();
  return GL_NO_ERROR;
}

GLenum Texture::SetParameterf(
    const FeatureInfo* feature_info, GLenum pname, GLfloat param) {
  switch (pname) {
    case GL_TEXTURE_MIN_FILTER:
    case GL_TEXTURE_MAG_FILTER:
    case GL_TEXTURE_WRAP_R:
    case GL_TEXTURE_WRAP_S:
    case GL_TEXTURE_WRAP_T:
    case GL_TEXTURE_COMPARE_FUNC:
    case GL_TEXTURE_COMPARE_MODE:
    case GL_TEXTURE_BASE_LEVEL:
    case GL_TEXTURE_MAX_LEVEL:
    case GL_TEXTURE_USAGE_ANGLE:
      {
        GLint iparam = static_cast<GLint>(std::round(param));
        return SetParameteri(feature_info, pname, iparam);
      }
    case GL_TEXTURE_MIN_LOD:
      sampler_state_.min_lod = param;
      break;
    case GL_TEXTURE_MAX_LOD:
      sampler_state_.max_lod = param;
      break;
    case GL_TEXTURE_MAX_ANISOTROPY_EXT:
      if (param < 1.f) {
        return GL_INVALID_VALUE;
      }
      break;
    case GL_TEXTURE_IMMUTABLE_FORMAT:
    case GL_TEXTURE_IMMUTABLE_LEVELS:
      return GL_INVALID_ENUM;
    default:
      NOTREACHED();
      return GL_INVALID_ENUM;
  }
  return GL_NO_ERROR;
}

void Texture::Update() {
  // Update npot status.
  // Assume GL_TEXTURE_EXTERNAL_OES textures are npot, all others
  npot_ = (target_ == GL_TEXTURE_EXTERNAL_OES) || (num_npot_faces_ > 0);

  if (face_infos_.empty() ||
      static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size()) {
    texture_complete_ = false;
    cube_complete_ = false;
    return;
  }

  // Update texture_complete and cube_complete status.
  const Texture::FaceInfo& first_face = face_infos_[0];
  const Texture::LevelInfo& first_level = first_face.level_infos[base_level_];
  const GLsizei levels_needed = first_face.num_mip_levels;

  texture_complete_ =
      max_level_set_ >= (levels_needed - 1) && max_level_set_ >= 0;
  cube_complete_ = (face_infos_.size() == 6) &&
                   (first_level.width == first_level.height) &&
                   (first_level.width > 0);

  if (first_level.width == 0 || first_level.height == 0) {
    texture_complete_ = false;
  }

  bool texture_level0_complete = true;
  if (cube_complete_) {
    for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
      const Texture::LevelInfo& face_base_level =
          face_infos_[ii].level_infos[base_level_];
      if (face_base_level.internal_workaround ||
          !TextureFaceComplete(first_level,
                               ii,
                               face_base_level.target,
                               face_base_level.internal_format,
                               face_base_level.width,
                               face_base_level.height,
                               face_base_level.depth,
                               face_base_level.format,
                               face_base_level.type)) {
        texture_level0_complete = false;
        break;
      }
    }
  }
  cube_complete_ &= texture_level0_complete;

  bool texture_mips_complete = true;
  if (texture_complete_ && texture_mips_dirty_) {
    for (size_t ii = 0; ii < face_infos_.size() && texture_mips_complete;
         ++ii) {
      const Texture::FaceInfo& face_info = face_infos_[ii];
      const Texture::LevelInfo& base_level_info =
          face_info.level_infos[base_level_];
      for (GLsizei jj = 1; jj < levels_needed; ++jj) {
        const Texture::LevelInfo& level_info =
            face_infos_[ii].level_infos[base_level_ + jj];
        if (!TextureMipComplete(base_level_info,
                                level_info.target,
                                jj,  // level - base_level_
                                level_info.internal_format,
                                level_info.width,
                                level_info.height,
                                level_info.depth,
                                level_info.format,
                                level_info.type)) {
          texture_mips_complete = false;
          break;
        }
      }
    }
    texture_mips_dirty_ = false;
  }
  texture_complete_ &= texture_mips_complete;
}

bool Texture::ClearRenderableLevels(GLES2Decoder* decoder) {
  DCHECK(decoder);
  if (cleared_) {
    return true;
  }

  for (size_t ii = 0; ii < face_infos_.size(); ++ii) {
    const Texture::FaceInfo& face_info = face_infos_[ii];
    for (GLint jj = base_level_;
         jj < base_level_ + face_info.num_mip_levels; ++jj) {
      const Texture::LevelInfo& info = face_info.level_infos[jj];
      if (info.target != 0) {
        if (!ClearLevel(decoder, info.target, jj)) {
          return false;
        }
      }
    }
  }
  UpdateSafeToRenderFrom(true);
  return true;
}

GLint Texture::GetImmutableLevels() const {
  if (!immutable_)
    return 0;
  GLint levels = 0;
  if (immutable_) {
    DCHECK(face_infos_.size() > 0);
    for (size_t ii = 0; ii < face_infos_[0].level_infos.size(); ++ii) {
      const Texture::LevelInfo& info = face_infos_[0].level_infos[ii];
      if (info.target != 0)
        levels++;
    }
  }
  return levels;
}

gfx::Rect Texture::GetLevelClearedRect(GLenum target, GLint level) const {
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  if (face_index >= face_infos_.size() ||
      level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
    return gfx::Rect();
  }

  const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];

  return info.cleared_rect;
}

bool Texture::IsLevelCleared(GLenum target, GLint level) const {
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  if (face_index >= face_infos_.size() ||
      level < 0 ||
      level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
    return true;
  }
  const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
  return info.cleared_rect == gfx::Rect(info.width, info.height);
}

bool Texture::IsLevelPartiallyCleared(GLenum target, GLint level) const {
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  if (face_index >= face_infos_.size() ||
      level < 0 ||
      level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
    return false;
  }
  const Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
  return (info.cleared_rect != gfx::Rect(info.width, info.height) &&
          info.cleared_rect != gfx::Rect());
}

void Texture::InitTextureMaxAnisotropyIfNeeded(GLenum target) {
  if (texture_max_anisotropy_initialized_)
    return;
  texture_max_anisotropy_initialized_ = true;
  GLfloat params[] = { 1.0f };
  glTexParameterfv(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, params);
}

bool Texture::ClearLevel(
    GLES2Decoder* decoder, GLenum target, GLint level) {
  DCHECK(decoder);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  if (face_index >= face_infos_.size() || level < 0 ||
      level >= static_cast<GLint>(face_infos_[face_index].level_infos.size())) {
    return true;
  }

  Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];

  DCHECK(target == info.target);

  if (info.target == 0 ||
      info.cleared_rect == gfx::Rect(info.width, info.height) ||
      info.width == 0 || info.height == 0 || info.depth == 0) {
    return true;
  }

  if (info.target == GL_TEXTURE_3D || info.target == GL_TEXTURE_2D_ARRAY) {
    // For 3D textures, we always clear the entire texture.
    DCHECK(info.cleared_rect == gfx::Rect());
    bool cleared = decoder->ClearLevel3D(
        this, info.target, info.level,
        TextureManager::AdjustTexFormat(decoder->GetFeatureInfo(), info.format),
        info.type, info.width, info.height, info.depth);
    if (!cleared)
      return false;
  } else {
    if (decoder->IsCompressedTextureFormat(info.internal_format)) {
      // An uncleared level of a compressed texture can only occur when
      // allocating the texture with TexStorage2D. In this case the level
      // is cleared just before a call to CompressedTexSubImage2D, to avoid
      // having to clear a sub-rectangle of a compressed texture, which
      // would be problematic.
      DCHECK(IsImmutable());
      DCHECK(info.cleared_rect == gfx::Rect());
      bool cleared = decoder->ClearCompressedTextureLevel(
          this, info.target, info.level, info.internal_format,
          info.width, info.height);
      if (!cleared)
        return false;
    } else {
      // Clear all remaining sub regions.
      const int x[] = {
        0, info.cleared_rect.x(), info.cleared_rect.right(), info.width};
      const int y[] = {
        0, info.cleared_rect.y(), info.cleared_rect.bottom(), info.height};

      for (size_t j = 0; j < 3; ++j) {
        for (size_t i = 0; i < 3; ++i) {
          // Center of nine patch is already cleared.
          if (j == 1 && i == 1)
            continue;

          gfx::Rect rect(x[i], y[j], x[i + 1] - x[i], y[j + 1] - y[j]);
          if (rect.IsEmpty())
            continue;

          // NOTE: It seems kind of gross to call back into the decoder for this
          // but only the decoder knows all the state (like unpack_alignment_)
          // that's needed to be able to call GL correctly.
          bool cleared = decoder->ClearLevel(
              this, info.target, info.level,
              TextureManager::AdjustTexFormat(decoder->GetFeatureInfo(),
                                              info.format),
              info.type, rect.x(), rect.y(), rect.width(), rect.height());
          if (!cleared)
            return false;
        }
      }
    }
  }

  UpdateMipCleared(&info, info.width, info.height,
                   gfx::Rect(info.width, info.height));
  return true;
}

void Texture::SetLevelImageInternal(GLenum target,
                                    GLint level,
                                    gl::GLImage* image,
                                    GLStreamTextureImage* stream_texture_image,
                                    ImageState state) {
  DCHECK(!stream_texture_image || stream_texture_image == image);
  DCHECK_GE(level, 0);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  DCHECK_LT(static_cast<size_t>(face_index), face_infos_.size());
  DCHECK_LT(static_cast<size_t>(level),
            face_infos_[face_index].level_infos.size());
  Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
  DCHECK_EQ(info.target, target);
  DCHECK_EQ(info.level, level);
  info.image = image;
  info.stream_texture_image = stream_texture_image;
  info.image_state = state;

  UpdateCanRenderCondition();
  UpdateHasImages();
  UpdateEmulatingRGB();
}

void Texture::SetLevelImage(GLenum target,
                            GLint level,
                            gl::GLImage* image,
                            ImageState state) {
  SetStreamTextureServiceId(0);
  SetLevelImageInternal(target, level, image, nullptr, state);
}

void Texture::SetLevelStreamTextureImage(GLenum target,
                                         GLint level,
                                         GLStreamTextureImage* image,
                                         ImageState state,
                                         GLuint service_id) {
  SetStreamTextureServiceId(service_id);
  SetLevelImageInternal(target, level, image, image, state);
}

void Texture::SetLevelImageState(GLenum target, GLint level, ImageState state) {
  DCHECK_GE(level, 0);
  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  DCHECK_LT(static_cast<size_t>(face_index), face_infos_.size());
  DCHECK_LT(static_cast<size_t>(level),
            face_infos_[face_index].level_infos.size());
  Texture::LevelInfo& info = face_infos_[face_index].level_infos[level];
  DCHECK_EQ(info.target, target);
  DCHECK_EQ(info.level, level);
  info.image_state = state;
}

const Texture::LevelInfo* Texture::GetLevelInfo(GLint target,
                                                GLint level) const {
  if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES &&
      target != GL_TEXTURE_RECTANGLE_ARB) {
    return NULL;
  }

  size_t face_index = GLES2Util::GLTargetToFaceIndex(target);
  if (level >= 0 && face_index < face_infos_.size() &&
      static_cast<size_t>(level) < face_infos_[face_index].level_infos.size()) {
    const LevelInfo& info = face_infos_[face_index].level_infos[level];
    if (info.target != 0)
      return &info;
  }
  return NULL;
}

gl::GLImage* Texture::GetLevelImage(GLint target,
                                    GLint level,
                                    ImageState* state) const {
  const LevelInfo* info = GetLevelInfo(target, level);
  if (!info)
    return nullptr;

  if (state)
    *state = info->image_state;
  return info->image.get();
}

gl::GLImage* Texture::GetLevelImage(GLint target, GLint level) const {
  return GetLevelImage(target, level, nullptr);
}

GLStreamTextureImage* Texture::GetLevelStreamTextureImage(GLint target,
                                                          GLint level) const {
  const LevelInfo* info = GetLevelInfo(target, level);
  if (!info)
    return nullptr;

  return info->stream_texture_image.get();
}

void Texture::DumpLevelMemory(base::trace_event::ProcessMemoryDump* pmd,
                              uint64_t client_tracing_id,
                              const std::string& dump_name) const {
  for (uint32_t face_index = 0; face_index < face_infos_.size(); ++face_index) {
    const auto& level_infos = face_infos_[face_index].level_infos;
    for (uint32_t level_index = 0; level_index < level_infos.size();
         ++level_index) {
      // Skip levels with no size. Textures will have empty levels for all
      // potential mip levels which are not in use.
      if (!level_infos[level_index].estimated_size)
        continue;

      // If a level has a GLImage, ask the GLImage to dump itself.
      if (level_infos[level_index].image) {
        level_infos[level_index].image->OnMemoryDump(
            pmd, client_tracing_id,
            base::StringPrintf("%s/face_%d/level_%d", dump_name.c_str(),
                               face_index, level_index));
      }

      // If a level does not have a GLImage bound to it, then dump the
      // texture allocation also as the storage is not provided by the
      // GLImage in that case.
      if (level_infos[level_index].image_state != BOUND) {
        base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(
            base::StringPrintf("%s/face_%d/level_%d", dump_name.c_str(),
                               face_index, level_index));
        dump->AddScalar(
            base::trace_event::MemoryAllocatorDump::kNameSize,
            base::trace_event::MemoryAllocatorDump::kUnitsBytes,
            static_cast<uint64_t>(level_infos[level_index].estimated_size));
      }
    }
  }
}

bool Texture::CanRenderTo(const FeatureInfo* feature_info, GLint level) const {
  if (target_ == GL_TEXTURE_EXTERNAL_OES || target_ == 0)
    return false;
  DCHECK_LT(0u, face_infos_.size());
  // In GLES2, cube completeness is not required for framebuffer completeness.
  // However, it is required if command buffer is implemented on top of
  // recent OpenGL core versions or OpenGL ES 3.0+. Therefore, for consistency,
  // it is better to deviate from ES2 spec and require cube completeness all
  // the time.
  if (face_infos_.size() == 6 && !cube_complete_)
    return false;
  DCHECK(level >= 0 &&
         level < static_cast<GLint>(face_infos_[0].level_infos.size()));
  GLenum internal_format = face_infos_[0].level_infos[level].internal_format;
  bool color_renderable =
      ((feature_info->validators()->texture_unsized_internal_format.
            IsValid(internal_format) &&
        internal_format != GL_ALPHA &&
        internal_format != GL_LUMINANCE &&
        internal_format != GL_LUMINANCE_ALPHA &&
        internal_format != GL_SRGB_EXT) ||
       feature_info->validators()->
           texture_sized_color_renderable_internal_format.IsValid(
               internal_format));
  bool depth_renderable = feature_info->validators()->
      texture_depth_renderable_internal_format.IsValid(internal_format);
  bool stencil_renderable = feature_info->validators()->
      texture_stencil_renderable_internal_format.IsValid(internal_format);
  return (color_renderable || depth_renderable || stencil_renderable);
}

GLenum Texture::GetCompatibilitySwizzleForChannel(GLenum channel) {
  return GetSwizzleForChannel(channel, compatibility_swizzle_);
}

void Texture::SetCompatibilitySwizzle(const CompatibilitySwizzle* swizzle) {
  if (compatibility_swizzle_ == swizzle)
    return;

  compatibility_swizzle_ = swizzle;
  glTexParameteri(target_, GL_TEXTURE_SWIZZLE_R,
                  GetSwizzleForChannel(swizzle_r_, swizzle));
  glTexParameteri(target_, GL_TEXTURE_SWIZZLE_G,
                  GetSwizzleForChannel(swizzle_g_, swizzle));
  glTexParameteri(target_, GL_TEXTURE_SWIZZLE_B,
                  GetSwizzleForChannel(swizzle_b_, swizzle));
  glTexParameteri(target_, GL_TEXTURE_SWIZZLE_A,
                  GetSwizzleForChannel(swizzle_a_, swizzle));
}

void Texture::ApplyFormatWorkarounds(FeatureInfo* feature_info) {
  if (feature_info->gl_version_info().is_desktop_core_profile) {
    if (static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size())
      return;
    const Texture::LevelInfo& info = face_infos_[0].level_infos[base_level_];
    SetCompatibilitySwizzle(GetCompatibilitySwizzle(info.format));
  }
}

bool Texture::EmulatingRGB() {
  return emulating_rgb_;
}

TextureRef::TextureRef(TextureManager* manager,
                       GLuint client_id,
                       Texture* texture)
    : manager_(manager),
      texture_(texture),
      client_id_(client_id),
      num_observers_(0),
      force_context_lost_(false) {
  DCHECK(manager_);
  DCHECK(texture_);
  texture_->AddTextureRef(this);
  manager_->StartTracking(this);
}

scoped_refptr<TextureRef> TextureRef::Create(TextureManager* manager,
                                             GLuint client_id,
                                             GLuint service_id) {
  return new TextureRef(manager, client_id, new Texture(service_id));
}

TextureRef::~TextureRef() {
  manager_->StopTracking(this);
  texture_->RemoveTextureRef(
      this, force_context_lost_ ? false : manager_->have_context_);
  manager_ = NULL;
}

void TextureRef::ForceContextLost() {
  force_context_lost_ = true;
}

TextureManager::TextureManager(MemoryTracker* memory_tracker,
                               FeatureInfo* feature_info,
                               GLint max_texture_size,
                               GLint max_cube_map_texture_size,
                               GLint max_rectangle_texture_size,
                               GLint max_3d_texture_size,
                               GLint max_array_texture_layers,
                               bool use_default_textures)
    : memory_type_tracker_(new MemoryTypeTracker(memory_tracker)),
      memory_tracker_(memory_tracker),
      feature_info_(feature_info),
      framebuffer_manager_(NULL),
      max_texture_size_(max_texture_size),
      max_cube_map_texture_size_(max_cube_map_texture_size),
      max_rectangle_texture_size_(max_rectangle_texture_size),
      max_3d_texture_size_(max_3d_texture_size),
      max_array_texture_layers_(max_array_texture_layers),
      max_levels_(ComputeMipMapCount(GL_TEXTURE_2D,
                                     max_texture_size,
                                     max_texture_size,
                                     0)),
      max_cube_map_levels_(ComputeMipMapCount(GL_TEXTURE_CUBE_MAP,
                                              max_cube_map_texture_size,
                                              max_cube_map_texture_size,
                                              0)),
      max_3d_levels_(ComputeMipMapCount(GL_TEXTURE_3D,
                                        max_3d_texture_size,
                                        max_3d_texture_size,
                                        max_3d_texture_size)),
      use_default_textures_(use_default_textures),
      num_unsafe_textures_(0),
      num_uncleared_mips_(0),
      num_images_(0),
      texture_count_(0),
      have_context_(true),
      current_service_id_generation_(0) {
  for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
    black_texture_ids_[ii] = 0;
  }
}

bool TextureManager::Initialize() {
  // Reset PIXEL_UNPACK_BUFFER to avoid unrelated GL error on some GL drivers.
  if (feature_info_->gl_version_info().is_es3_capable) {
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
  }

  // TODO(gman): The default textures have to be real textures, not the 0
  // texture because we simulate non shared resources on top of shared
  // resources and all contexts that share resource share the same default
  // texture.
  default_textures_[kTexture2D] = CreateDefaultAndBlackTextures(
      GL_TEXTURE_2D, &black_texture_ids_[kTexture2D]);
  default_textures_[kCubeMap] = CreateDefaultAndBlackTextures(
      GL_TEXTURE_CUBE_MAP, &black_texture_ids_[kCubeMap]);

  if (feature_info_->IsES3Enabled()) {
    default_textures_[kTexture3D] = CreateDefaultAndBlackTextures(
        GL_TEXTURE_3D, &black_texture_ids_[kTexture3D]);
    default_textures_[kTexture2DArray] = CreateDefaultAndBlackTextures(
        GL_TEXTURE_2D_ARRAY, &black_texture_ids_[kTexture2DArray]);
  }

  if (feature_info_->feature_flags().oes_egl_image_external ||
      feature_info_->feature_flags().nv_egl_stream_consumer_external) {
    default_textures_[kExternalOES] = CreateDefaultAndBlackTextures(
        GL_TEXTURE_EXTERNAL_OES, &black_texture_ids_[kExternalOES]);
  }

  if (feature_info_->feature_flags().arb_texture_rectangle) {
    default_textures_[kRectangleARB] = CreateDefaultAndBlackTextures(
        GL_TEXTURE_RECTANGLE_ARB, &black_texture_ids_[kRectangleARB]);
  }

  // When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
  // so don't register a dump provider.
  if (memory_tracker_) {
    base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
        this, "gpu::TextureManager", base::ThreadTaskRunnerHandle::Get());
  }

  return true;
}

scoped_refptr<TextureRef>
    TextureManager::CreateDefaultAndBlackTextures(
        GLenum target,
        GLuint* black_texture) {
  static uint8_t black[] = {0, 0, 0, 255};

  // Sampling a texture not associated with any EGLImage sibling will return
  // black values according to the spec.
  bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES);
  bool needs_faces = (target == GL_TEXTURE_CUBE_MAP);
  bool is_3d_or_2d_array_target = (target == GL_TEXTURE_3D ||
      target == GL_TEXTURE_2D_ARRAY);

  // Make default textures and texture for replacing non-renderable textures.
  GLuint ids[2];
  const int num_ids = use_default_textures_ ? 2 : 1;
  glGenTextures(num_ids, ids);
  for (int ii = 0; ii < num_ids; ++ii) {
    glBindTexture(target, ids[ii]);
    if (needs_initialization) {
      if (needs_faces) {
        for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) {
          glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0,
                       GL_RGBA, GL_UNSIGNED_BYTE, black);
        }
      } else {
        if (is_3d_or_2d_array_target) {
          glTexImage3D(target, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA,
                       GL_UNSIGNED_BYTE, black);
        } else {
          glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
                       GL_UNSIGNED_BYTE, black);
        }
      }
    }
  }
  glBindTexture(target, 0);

  scoped_refptr<TextureRef> default_texture;
  if (use_default_textures_) {
    default_texture = TextureRef::Create(this, 0, ids[1]);
    SetTarget(default_texture.get(), target);
    if (needs_faces) {
      for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) {
        SetLevelInfo(default_texture.get(), GLES2Util::IndexToGLFaceTarget(ii),
                     0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                     gfx::Rect(1, 1));
      }
    } else {
      if (needs_initialization) {
        SetLevelInfo(default_texture.get(), GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1,
                     0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1));
      } else {
        SetLevelInfo(default_texture.get(), GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA,
                     1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(1, 1));
      }
    }
  }

  *black_texture = ids[0];
  return default_texture;
}

bool TextureManager::ValidForTarget(
    GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) {
  if (level < 0 || level >= MaxLevelsForTarget(target))
    return false;
  GLsizei max_size = MaxSizeForTarget(target) >> level;
  GLsizei max_depth =
      (target == GL_TEXTURE_2D_ARRAY ? max_array_texture_layers() : max_size);
  return width >= 0 &&
         height >= 0 &&
         depth >= 0 &&
         width <= max_size &&
         height <= max_size &&
         depth <= max_depth &&
         (level == 0 || feature_info_->feature_flags().npot_ok ||
          (!GLES2Util::IsNPOT(width) &&
           !GLES2Util::IsNPOT(height) &&
           !GLES2Util::IsNPOT(depth))) &&
         (target != GL_TEXTURE_CUBE_MAP || (width == height && depth == 1)) &&
         (target != GL_TEXTURE_2D || (depth == 1));
}

void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
  DCHECK(ref);
  ref->texture()->SetTarget(target, MaxLevelsForTarget(target));
}

void TextureManager::SetLevelClearedRect(TextureRef* ref,
                                         GLenum target,
                                         GLint level,
                                         const gfx::Rect& cleared_rect) {
  DCHECK(ref);
  ref->texture()->SetLevelClearedRect(target, level, cleared_rect);
}

void TextureManager::SetLevelCleared(TextureRef* ref,
                                     GLenum target,
                                     GLint level,
                                     bool cleared) {
  DCHECK(ref);
  ref->texture()->SetLevelCleared(target, level, cleared);
}

bool TextureManager::ClearRenderableLevels(
    GLES2Decoder* decoder, TextureRef* ref) {
  DCHECK(ref);
  return ref->texture()->ClearRenderableLevels(decoder);
}

bool TextureManager::ClearTextureLevel(
    GLES2Decoder* decoder, TextureRef* ref,
    GLenum target, GLint level) {
  DCHECK(ref);
  Texture* texture = ref->texture();
  if (texture->num_uncleared_mips() == 0) {
    return true;
  }
  bool result = texture->ClearLevel(decoder, target, level);
  texture->UpdateCleared();
  return result;
}

void TextureManager::SetLevelInfo(TextureRef* ref,
                                  GLenum target,
                                  GLint level,
                                  GLenum internal_format,
                                  GLsizei width,
                                  GLsizei height,
                                  GLsizei depth,
                                  GLint border,
                                  GLenum format,
                                  GLenum type,
                                  const gfx::Rect& cleared_rect) {
  DCHECK(gfx::Rect(width, height).Contains(cleared_rect));
  DCHECK(ref);
  Texture* texture = ref->texture();

  texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
  texture->SetLevelInfo(target, level, internal_format, width, height, depth,
                        border, format, type, cleared_rect);
  texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
}

Texture* TextureManager::Produce(TextureRef* ref) {
  DCHECK(ref);
  return ref->texture();
}

TextureRef* TextureManager::Consume(
    GLuint client_id,
    Texture* texture) {
  DCHECK(client_id);
  scoped_refptr<TextureRef> ref(new TextureRef(this, client_id, texture));
  bool result = textures_.insert(std::make_pair(client_id, ref)).second;
  DCHECK(result);
  return ref.get();
}

void TextureManager::SetParameteri(
    const char* function_name, ErrorState* error_state,
    TextureRef* ref, GLenum pname, GLint param) {
  DCHECK(error_state);
  DCHECK(ref);
  Texture* texture = ref->texture();
  GLenum result = texture->SetParameteri(feature_info_.get(), pname, param);
  if (result != GL_NO_ERROR) {
    if (result == GL_INVALID_ENUM) {
      ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
          error_state, function_name, param, "param");
    } else {
      ERRORSTATE_SET_GL_ERROR_INVALID_PARAMI(
          error_state, result, function_name, pname, param);
    }
  } else {
    switch (pname) {
      case GL_TEXTURE_SWIZZLE_R:
      case GL_TEXTURE_SWIZZLE_G:
      case GL_TEXTURE_SWIZZLE_B:
      case GL_TEXTURE_SWIZZLE_A:
        glTexParameteri(texture->target(), pname,
                        texture->GetCompatibilitySwizzleForChannel(param));
        break;
      default:
        glTexParameteri(texture->target(), pname, param);
        break;
    }
  }
}

void TextureManager::SetParameterf(
    const char* function_name, ErrorState* error_state,
    TextureRef* ref, GLenum pname, GLfloat param) {
  DCHECK(error_state);
  DCHECK(ref);
  Texture* texture = ref->texture();
  GLenum result = texture->SetParameterf(feature_info_.get(), pname, param);
  if (result != GL_NO_ERROR) {
    if (result == GL_INVALID_ENUM) {
      ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
          error_state, function_name, pname, "pname");
    } else {
      ERRORSTATE_SET_GL_ERROR_INVALID_PARAMF(
          error_state, result, function_name, pname, param);
    }
  } else {
    glTexParameterf(texture->target(), pname, param);
  }
}

void TextureManager::MarkMipmapsGenerated(TextureRef* ref) {
  DCHECK(ref);
  Texture* texture = ref->texture();
  texture->GetMemTracker()->TrackMemFree(texture->estimated_size());
  texture->MarkMipmapsGenerated();
  texture->GetMemTracker()->TrackMemAlloc(texture->estimated_size());
}

TextureRef* TextureManager::CreateTexture(
    GLuint client_id, GLuint service_id) {
  DCHECK_NE(0u, service_id);
  scoped_refptr<TextureRef> ref(TextureRef::Create(
      this, client_id, service_id));
  std::pair<TextureMap::iterator, bool> result =
      textures_.insert(std::make_pair(client_id, ref));
  DCHECK(result.second);
  return ref.get();
}

TextureRef* TextureManager::GetTexture(
    GLuint client_id) const {
  TextureMap::const_iterator it = textures_.find(client_id);
  return it != textures_.end() ? it->second.get() : NULL;
}

void TextureManager::RemoveTexture(GLuint client_id) {
  TextureMap::iterator it = textures_.find(client_id);
  if (it != textures_.end()) {
    it->second->reset_client_id();
    textures_.erase(it);
  }
}

void TextureManager::StartTracking(TextureRef* ref) {
  Texture* texture = ref->texture();
  ++texture_count_;
  num_uncleared_mips_ += texture->num_uncleared_mips();
  if (!texture->SafeToRenderFrom())
    ++num_unsafe_textures_;
  if (texture->HasImages())
    ++num_images_;
}

void TextureManager::StopTracking(TextureRef* ref) {
  if (ref->num_observers()) {
    for (unsigned int i = 0; i < destruction_observers_.size(); i++) {
      destruction_observers_[i]->OnTextureRefDestroying(ref);
    }
    DCHECK_EQ(ref->num_observers(), 0);
  }

  Texture* texture = ref->texture();

  --texture_count_;
  if (texture->HasImages()) {
    DCHECK_NE(0, num_images_);
    --num_images_;
  }
  if (!texture->SafeToRenderFrom()) {
    DCHECK_NE(0, num_unsafe_textures_);
    --num_unsafe_textures_;
  }
  num_uncleared_mips_ -= texture->num_uncleared_mips();
  DCHECK_GE(num_uncleared_mips_, 0);
}

MemoryTypeTracker* TextureManager::GetMemTracker() {
  return memory_type_tracker_.get();
}

Texture* TextureManager::GetTextureForServiceId(GLuint service_id) const {
  // This doesn't need to be fast. It's only used during slow queries.
  for (TextureMap::const_iterator it = textures_.begin();
       it != textures_.end(); ++it) {
    Texture* texture = it->second->texture();
    if (texture->service_id() == service_id)
      return texture;
  }
  return NULL;
}

GLsizei TextureManager::ComputeMipMapCount(GLenum target,
                                           GLsizei width,
                                           GLsizei height,
                                           GLsizei depth) {
  switch (target) {
    case GL_TEXTURE_EXTERNAL_OES:
    case GL_TEXTURE_RECTANGLE_ARB:
      return 1;
    case GL_TEXTURE_3D:
      return 1 +
             base::bits::Log2Floor(std::max(std::max(width, height), depth));
    default:
      return 1 +
             base::bits::Log2Floor(std::max(width, height));
  }
}

void TextureManager::SetLevelImage(TextureRef* ref,
                                   GLenum target,
                                   GLint level,
                                   gl::GLImage* image,
                                   Texture::ImageState state) {
  DCHECK(ref);
  ref->texture()->SetLevelImage(target, level, image, state);
}

void TextureManager::SetLevelStreamTextureImage(TextureRef* ref,
                                                GLenum target,
                                                GLint level,
                                                GLStreamTextureImage* image,
                                                Texture::ImageState state,
                                                GLuint service_id) {
  DCHECK(ref);
  ref->texture()->SetLevelStreamTextureImage(target, level, image, state,
                                             service_id);
}

void TextureManager::SetLevelImageState(TextureRef* ref,
                                        GLenum target,
                                        GLint level,
                                        Texture::ImageState state) {
  DCHECK(ref);
  ref->texture()->SetLevelImageState(target, level, state);
}

size_t TextureManager::GetSignatureSize() const {
  return sizeof(TextureTag) + sizeof(TextureSignature);
}

void TextureManager::AddToSignature(
    TextureRef* ref,
    GLenum target,
    GLint level,
    std::string* signature) const {
  ref->texture()->AddToSignature(feature_info_.get(), target, level, signature);
}

void TextureManager::UpdateSafeToRenderFrom(int delta) {
  num_unsafe_textures_ += delta;
  DCHECK_GE(num_unsafe_textures_, 0);
}

void TextureManager::UpdateUnclearedMips(int delta) {
  num_uncleared_mips_ += delta;
  DCHECK_GE(num_uncleared_mips_, 0);
}

void TextureManager::UpdateNumImages(int delta) {
  num_images_ += delta;
  DCHECK_GE(num_images_, 0);
}

void TextureManager::IncFramebufferStateChangeCount() {
  if (framebuffer_manager_)
    framebuffer_manager_->IncFramebufferStateChangeCount();
}

bool TextureManager::ValidateTextureParameters(
    ErrorState* error_state, const char* function_name, bool tex_image_call,
    GLenum format, GLenum type, GLint internal_format, GLint level) {
  const Validators* validators = feature_info_->validators();
  if (!validators->texture_format.IsValid(format)) {
    ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
        error_state, function_name, format, "format");
    return false;
  }
  if (!validators->pixel_type.IsValid(type)) {
    ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
        error_state, function_name, type, "type");
    return false;
  }
  // For TexSubImage calls, internal_format isn't part of the parameters.
  // So the validation is not necessary for TexSubImage.
  if (tex_image_call &&
      !validators->texture_internal_format.IsValid(internal_format)) {
    std::string msg = base::StringPrintf("invalid internal_format 0x%x",
                                         internal_format);
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name,
                             msg.c_str());
    return false;
  }
  if (!g_format_type_validator.Get().IsValid(internal_format, format, type)) {
    std::string msg = base::StringPrintf(
        "invalid internalformat/format/type combination 0x%x/0x%x/0x%x",
        internal_format, format, type);
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
                            msg.c_str());
    return false;
  }
  if (!feature_info_->IsES3Enabled()) {
    uint32_t channels = GLES2Util::GetChannelsForFormat(format);
    if ((channels & (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && level) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, function_name,
          (std::string("invalid format ") + GLES2Util::GetStringEnum(format) +
           " for level != 0").c_str());
      return false;
    }
  }
  return true;
}

// Gets the texture id for a given target.
TextureRef* TextureManager::GetTextureInfoForTarget(
    ContextState* state, GLenum target) {
  TextureUnit& unit = state->texture_units[state->active_texture_unit];
  TextureRef* texture = NULL;
  switch (target) {
    case GL_TEXTURE_2D:
      texture = unit.bound_texture_2d.get();
      break;
    case GL_TEXTURE_CUBE_MAP:
    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
      texture = unit.bound_texture_cube_map.get();
      break;
    case GL_TEXTURE_EXTERNAL_OES:
      texture = unit.bound_texture_external_oes.get();
      break;
    case GL_TEXTURE_RECTANGLE_ARB:
      texture = unit.bound_texture_rectangle_arb.get();
      break;
    case GL_TEXTURE_3D:
      texture = unit.bound_texture_3d.get();
      break;
    case GL_TEXTURE_2D_ARRAY:
      texture = unit.bound_texture_2d_array.get();
      break;
    default:
      NOTREACHED();
      return NULL;
  }
  return texture;
}

TextureRef* TextureManager::GetTextureInfoForTargetUnlessDefault(
    ContextState* state, GLenum target) {
  TextureRef* texture = GetTextureInfoForTarget(state, target);
  if (!texture)
    return NULL;
  if (texture == GetDefaultTextureInfo(target))
    return NULL;
  return texture;
}

bool TextureManager::ValidateTexImage(
    ContextState* state,
    const char* function_name,
    const DoTexImageArguments& args,
    TextureRef** texture_ref) {
  ErrorState* error_state = state->GetErrorState();
  const Validators* validators = feature_info_->validators();
  if (((args.command_type == DoTexImageArguments::kTexImage2D) &&
       !validators->texture_target.IsValid(args.target)) ||
      ((args.command_type == DoTexImageArguments::kTexImage3D) &&
       !validators->texture_3_d_target.IsValid(args.target))) {
    ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
        error_state, function_name, args.target, "target");
    return false;
  }
  // TODO(ccameron): Add a separate texture from |texture_target| for
  // [Compressed]Tex[Sub]Image2D and related functions.
  // http://crbug.com/536854
  if (args.target == GL_TEXTURE_RECTANGLE_ARB) {
    ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(
        error_state, function_name, args.target, "target");
    return false;
  }
  if (!ValidateTextureParameters(
      error_state, function_name, true, args.format, args.type,
      args.internal_format, args.level)) {
    return false;
  }
  if (!ValidForTarget(args.target, args.level,
                      args.width, args.height, args.depth) ||
      args.border != 0) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_VALUE, function_name,
        "dimensions out of range");
    return false;
  }
  if ((GLES2Util::GetChannelsForFormat(args.format) &
       (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels
      && !feature_info_->IsES3Enabled()) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_OPERATION,
        function_name, "can not supply data for depth or stencil textures");
    return false;
  }

  TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
  if (!local_texture_ref) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_OPERATION, function_name,
        "unknown texture for target");
    return false;
  }
  if (local_texture_ref->texture()->IsImmutable()) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_OPERATION, function_name,
        "texture is immutable");
    return false;
  }

  Buffer* buffer = state->bound_pixel_unpack_buffer.get();
  if (buffer) {
    if (buffer->GetMappedRange()) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, function_name,
          "pixel unpack buffer should not be mapped to client memory");
      return false;
    }
    base::CheckedNumeric<uint32_t> size = args.pixels_size;
    GLuint offset = ToGLuint(args.pixels);
    size += offset;
    if (!size.IsValid()) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_VALUE, function_name,
          "size + offset overflow");
      return false;
    }
    uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
    if (buffer_size < size.ValueOrDefault(0)) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, function_name,
          "pixel unpack buffer is not large enough");
      return false;
    }
    size_t type_size = GLES2Util::GetGLTypeSizeForTextures(args.type);
    DCHECK_LT(0u, type_size);
    if (offset % type_size != 0) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, function_name,
          "offset is not evenly divisible by elements");
      return false;
    }
  }

  if (!memory_type_tracker_->EnsureGPUMemoryAvailable(args.pixels_size)) {
    ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY, function_name,
                            "out of memory");
    return false;
  }

  // Write the TextureReference since this is valid.
  *texture_ref = local_texture_ref;
  return true;
}

void TextureManager::ValidateAndDoTexImage(
    DecoderTextureState* texture_state,
    ContextState* state,
    DecoderFramebufferState* framebuffer_state,
    const char* function_name,
    const DoTexImageArguments& args) {
  TextureRef* texture_ref;
  if (!ValidateTexImage(state, function_name, args, &texture_ref)) {
    return;
  }

  Buffer* buffer = state->bound_pixel_unpack_buffer.get();

  // ValidateTexImage is passed already.
  Texture* texture = texture_ref->texture();
  bool need_cube_map_workaround =
      !feature_info_->IsES3Enabled() &&
      texture->target() == GL_TEXTURE_CUBE_MAP &&
      (texture_state->force_cube_complete ||
       (texture_state->force_cube_map_positive_x_allocation &&
        args.target != GL_TEXTURE_CUBE_MAP_POSITIVE_X));
  if (need_cube_map_workaround && !buffer) {
    // TODO(zmo): The following code does not work with an unpack buffer bound.
    std::vector<GLenum> undefined_faces;
    if (texture_state->force_cube_complete) {
      int width = 0;
      int height = 0;
      for (unsigned i = 0; i < 6; i++) {
        GLenum target = static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i);
        bool defined = texture->GetLevelSize(
            target, args.level, &width, &height, nullptr);
        if (!defined && target != args.target)
          undefined_faces.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i);
      }
    } else {
      DCHECK(texture_state->force_cube_map_positive_x_allocation &&
             args.target != GL_TEXTURE_CUBE_MAP_POSITIVE_X);
      int width = 0;
      int height = 0;
      if (!texture->GetLevelSize(GL_TEXTURE_CUBE_MAP_POSITIVE_X, args.level,
                                 &width, &height, nullptr)) {
        undefined_faces.push_back(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
      }
    }
    if (!memory_type_tracker_->EnsureGPUMemoryAvailable(
            (undefined_faces.size() + 1) * args.pixels_size)) {
      ERRORSTATE_SET_GL_ERROR(state->GetErrorState(), GL_OUT_OF_MEMORY,
                              function_name, "out of memory");
      return;
    }
    DoTexImageArguments new_args = args;
    std::unique_ptr<char[]> zero(new char[args.pixels_size]);
    memset(zero.get(), 0, args.pixels_size);
    for (GLenum face : undefined_faces) {
      new_args.target = face;
      new_args.pixels = zero.get();
      DoTexImage(texture_state, state, framebuffer_state,
                 function_name, texture_ref, new_args);
      texture->MarkLevelAsInternalWorkaround(face, args.level);
    }
  }

  if (texture_state->unpack_overlapping_rows_separately_unpack_buffer &&
      buffer) {
    ContextState::Dimension dimension =
        (args.command_type == DoTexImageArguments::kTexImage3D)
            ? ContextState::k3D
            : ContextState::k2D;
    const PixelStoreParams unpack_params(state->GetUnpackParams(dimension));
    if (unpack_params.row_length != 0 &&
        unpack_params.row_length < args.width) {
      // The rows overlap in unpack memory. Upload the texture row by row to
      // work around driver bug.

      ReserveTexImageToBeFilled(texture_state, state, framebuffer_state,
                                function_name, texture_ref, args);

      DoTexSubImageArguments sub_args = {
          args.target, args.level, 0, 0, 0, args.width, args.height, args.depth,
          args.format, args.type, args.pixels, args.pixels_size, args.padding,
          args.command_type == DoTexImageArguments::kTexImage3D
              ? DoTexSubImageArguments::kTexSubImage3D
              : DoTexSubImageArguments::kTexSubImage2D};
      DoTexSubImageRowByRowWorkaround(texture_state, state, sub_args,
                                      unpack_params);

      SetLevelCleared(texture_ref, args.target, args.level, true);
      return;
    }
  }

  if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
    uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
    if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
      // In ValidateTexImage(), we already made sure buffer size is no less
      // than offset + pixels_size.
      ReserveTexImageToBeFilled(texture_state, state, framebuffer_state,
                                function_name, texture_ref, args);

      DoTexSubImageArguments sub_args = {
          args.target, args.level, 0, 0, 0, args.width, args.height, args.depth,
          args.format, args.type, args.pixels, args.pixels_size, args.padding,
          args.command_type == DoTexImageArguments::kTexImage3D ?
              DoTexSubImageArguments::kTexSubImage3D :
              DoTexSubImageArguments::kTexSubImage2D};
      DoTexSubImageWithAlignmentWorkaround(texture_state, state, sub_args);

      SetLevelCleared(texture_ref, args.target, args.level, true);
      return;
    }
  }
  DoTexImage(texture_state, state, framebuffer_state,
             function_name, texture_ref, args);
}

void TextureManager::ReserveTexImageToBeFilled(
    DecoderTextureState* texture_state,
    ContextState* state,
    DecoderFramebufferState* framebuffer_state,
    const char* function_name,
    TextureRef* texture_ref,
    const DoTexImageArguments& args) {
  Buffer* buffer = state->bound_pixel_unpack_buffer.get();
  glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
  state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, nullptr);
  DoTexImageArguments new_args = args;
  new_args.pixels = nullptr;
  // pixels_size might be incorrect, but it's not used in this case.
  DoTexImage(texture_state, state, framebuffer_state, function_name,
             texture_ref, new_args);
  glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->service_id());
  state->SetBoundBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
}

bool TextureManager::ValidateTexSubImage(ContextState* state,
                                         const char* function_name,
                                         const DoTexSubImageArguments& args,
                                         TextureRef** texture_ref) {
  ErrorState* error_state = state->GetErrorState();
  const Validators* validators = feature_info_->validators();

  if ((args.command_type == DoTexSubImageArguments::kTexSubImage2D &&
       !validators->texture_target.IsValid(args.target)) ||
      (args.command_type == DoTexSubImageArguments::kTexSubImage3D &&
       !validators->texture_3_d_target.IsValid(args.target))) {
    ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state, function_name,
                                         args.target, "target");
    return false;
  }
  DCHECK(args.width >= 0 && args.height >= 0 && args.depth >= 0);
  TextureRef* local_texture_ref = GetTextureInfoForTarget(state, args.target);
  if (!local_texture_ref) {
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
                            "unknown texture for target");
    return false;
  }
  Texture* texture = local_texture_ref->texture();
  GLenum current_type = 0;
  GLenum internal_format = 0;
  if (!texture->GetLevelType(args.target, args.level, &current_type,
                             &internal_format)) {
    std::string msg = base::StringPrintf(
        "level %d does not exist", args.level);
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
                            msg.c_str());
    return false;
  }
  if (!ValidateTextureParameters(error_state, function_name, false, args.format,
                                 args.type, internal_format, args.level)) {
    return false;
  }
  if (args.type != current_type && !feature_info_->IsES3Enabled()) {
    // It isn't explicitly required in the ES2 spec, but some drivers generate
    // an error. It is better to be consistent across drivers.
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
                            "type does not match type of texture.");
    return false;
  }
  if (!texture->ValidForTexture(args.target, args.level,
                                args.xoffset, args.yoffset, args.zoffset,
                                args.width, args.height, args.depth)) {
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name,
                            "bad dimensions.");
    return false;
  }
  if ((GLES2Util::GetChannelsForFormat(args.format) &
       (GLES2Util::kDepth | GLES2Util::kStencil)) != 0 &&
      !feature_info_->IsES3Enabled()) {
    ERRORSTATE_SET_GL_ERROR(
        error_state, GL_INVALID_OPERATION, function_name,
        "can not supply data for depth or stencil textures");
    return false;
  }

  Buffer* buffer = state->bound_pixel_unpack_buffer.get();
  if (buffer) {
    if (buffer->GetMappedRange()) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, function_name,
          "pixel unpack buffer should not be mapped to client memory");
      return error::kNoError;
    }
    base::CheckedNumeric<uint32_t> size = args.pixels_size;
    GLuint offset = ToGLuint(args.pixels);
    size += offset;
    if (!size.IsValid()) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_VALUE, function_name,
          "size + offset overflow");
      return error::kNoError;
    }
    uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
    if (buffer_size < size.ValueOrDefault(0)) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, function_name,
          "pixel unpack buffer is not large enough");
      return error::kNoError;
    }
    size_t type_size = GLES2Util::GetGLTypeSizeForTextures(args.type);
    DCHECK_LT(0u, type_size);
    if (offset % type_size != 0) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, function_name,
          "offset is not evenly divisible by elements");
      return error::kNoError;
    }
  }
  *texture_ref = local_texture_ref;
  return true;
}

void TextureManager::ValidateAndDoTexSubImage(
    GLES2Decoder* decoder,
    DecoderTextureState* texture_state,
    ContextState* state,
    DecoderFramebufferState* framebuffer_state,
    const char* function_name,
    const DoTexSubImageArguments& args) {
  ErrorState* error_state = state->GetErrorState();
  TextureRef* texture_ref;
  if (!ValidateTexSubImage(state, function_name, args, &texture_ref)) {
    return;
  }

  Texture* texture = texture_ref->texture();
  GLsizei tex_width = 0;
  GLsizei tex_height = 0;
  GLsizei tex_depth = 0;
  bool ok = texture->GetLevelSize(args.target, args.level, &tex_width,
                                  &tex_height, &tex_depth);
  DCHECK(ok);
  bool full_image;
  if (args.xoffset != 0 || args.yoffset != 0 || args.zoffset != 0 ||
      args.width != tex_width || args.height != tex_height ||
      args.depth != tex_depth) {
    gfx::Rect cleared_rect;
    if (args.command_type == DoTexSubImageArguments::kTexSubImage2D &&
        CombineAdjacentRects(
            texture->GetLevelClearedRect(args.target, args.level),
            gfx::Rect(args.xoffset, args.yoffset, args.width, args.height),
            &cleared_rect)) {
      DCHECK_GE(cleared_rect.size().GetArea(),
                texture->GetLevelClearedRect(args.target, args.level)
                    .size()
                    .GetArea());
      SetLevelClearedRect(texture_ref, args.target, args.level, cleared_rect);
    } else {
      // Otherwise clear part of texture level that is not already cleared.
      if (!ClearTextureLevel(decoder, texture_ref, args.target, args.level)) {
        ERRORSTATE_SET_GL_ERROR(error_state, GL_OUT_OF_MEMORY,
                                function_name, "dimensions too big");
        return;
      }
    }
    full_image = false;
  } else {
    SetLevelCleared(texture_ref, args.target, args.level, true);
    full_image = true;
  }

  Buffer* buffer = state->bound_pixel_unpack_buffer.get();

  if (texture_state->unpack_overlapping_rows_separately_unpack_buffer &&
      buffer) {
    ContextState::Dimension dimension =
        (args.command_type == DoTexSubImageArguments::kTexSubImage3D)
            ? ContextState::k3D
            : ContextState::k2D;
    const PixelStoreParams unpack_params(state->GetUnpackParams(dimension));
    if (unpack_params.row_length != 0 &&
        unpack_params.row_length < args.width) {
      // The rows overlap in unpack memory. Upload the texture row by row to
      // work around driver bug.
      DoTexSubImageRowByRowWorkaround(texture_state, state, args,
                                      unpack_params);
      return;
    }
  }

  if (texture_state->unpack_alignment_workaround_with_unpack_buffer && buffer) {
    uint32_t buffer_size = static_cast<uint32_t>(buffer->size());
    if (buffer_size - args.pixels_size - ToGLuint(args.pixels) < args.padding) {
      DoTexSubImageWithAlignmentWorkaround(texture_state, state, args);
      return;
    }
  }

  if (full_image && !texture_state->texsubimage_faster_than_teximage &&
      !texture->IsImmutable() && !texture->HasImages()) {
    ScopedTextureUploadTimer timer(texture_state);
    GLenum internal_format;
    GLenum tex_type;
    texture->GetLevelType(args.target, args.level, &tex_type, &internal_format);
    // NOTE: In OpenGL ES 2/3 border is always zero. If that changes we'll need
    // to look it up.
    if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) {
      glTexImage3D(
          args.target, args.level,
          AdjustTexInternalFormat(feature_info_.get(), internal_format),
          args.width, args.height, args.depth, 0,
          AdjustTexFormat(feature_info_.get(), args.format), args.type,
          args.pixels);
    } else {
      glTexImage2D(
          args.target, args.level,
          AdjustTexInternalFormat(feature_info_.get(), internal_format),
          args.width, args.height, 0,
          AdjustTexFormat(feature_info_.get(), args.format), args.type,
          args.pixels);
    }
  } else {
    ScopedTextureUploadTimer timer(texture_state);
    if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) {
      glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
                      args.zoffset, args.width, args.height, args.depth,
                      AdjustTexFormat(feature_info_.get(), args.format),
                      args.type, args.pixels);
    } else {
      glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset,
                      args.width, args.height,
                      AdjustTexFormat(feature_info_.get(), args.format),
                      args.type, args.pixels);
    }
  }
}

void TextureManager::DoTexSubImageWithAlignmentWorkaround(
    DecoderTextureState* texture_state,
    ContextState* state,
    const DoTexSubImageArguments& args) {
  DCHECK(state->bound_pixel_unpack_buffer.get());
  DCHECK(args.width > 0 && args.height > 0 && args.depth > 0);

  ScopedTextureUploadTimer timer(texture_state);
  uint32_t offset = ToGLuint(args.pixels);
  if (args.command_type == DoTexSubImageArguments::kTexSubImage2D) {
    PixelStoreParams params = state->GetUnpackParams(ContextState::k2D);
    if (args.height > 1) {
      glTexSubImage2D(args.target, args.level, args.xoffset, args.yoffset,
                      args.width, args.height - 1,
                      AdjustTexFormat(feature_info_.get(), args.format),
                      args.type, args.pixels);
      GLint actual_width = state->unpack_row_length > 0 ?
          state->unpack_row_length : args.width;
      uint32_t size;
      uint32_t padding;
      // No need to worry about integer overflow here.
      GLES2Util::ComputeImageDataSizesES3(actual_width, args.height - 1, 1,
                                          args.format, args.type,
                                          params,
                                          &size,
                                          nullptr, nullptr, nullptr,
                                          &padding);
      DCHECK_EQ(args.padding, padding);
      // Last row should be padded, not unpadded.
      offset += size + padding;
    }
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexSubImage2D(args.target, args.level, args.xoffset,
                    args.yoffset + args.height - 1, args.width, 1,
                    AdjustTexFormat(feature_info_.get(), args.format),
                    args.type, reinterpret_cast<const void*>(offset));
    glPixelStorei(GL_UNPACK_ALIGNMENT, state->unpack_alignment);
    {
      uint32_t size;
      GLES2Util::ComputeImageDataSizesES3(args.width, 1, 1,
                                          args.format, args.type,
                                          params,
                                          &size,
                                          nullptr, nullptr, nullptr, nullptr);
      offset += size;
    }
  } else {  // kTexSubImage3D
    PixelStoreParams params = state->GetUnpackParams(ContextState::k3D);
    GLint actual_width = state->unpack_row_length > 0 ?
        state->unpack_row_length : args.width;
    if (args.depth > 1) {
      glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
                      args.zoffset, args.width, args.height, args.depth - 1,
                      AdjustTexFormat(feature_info_.get(), args.format),
                      args.type, args.pixels);
      GLint actual_height = state->unpack_image_height > 0 ?
          state->unpack_image_height : args.height;
      uint32_t size;
      uint32_t padding;
      // No need to worry about integer overflow here.
      GLES2Util::ComputeImageDataSizesES3(actual_width, actual_height,
                                          args.depth - 1,
                                          args.format, args.type,
                                          params,
                                          &size,
                                          nullptr, nullptr, nullptr,
                                          &padding);
      DCHECK_EQ(args.padding, padding);
      // Last row should be padded, not unpadded.
      offset += size + padding;
    }
    if (args.height > 1) {
      glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
                      args.zoffset + args.depth - 1, args.width,
                      args.height - 1, 1,
                      AdjustTexFormat(feature_info_.get(), args.format),
                      args.type, reinterpret_cast<const void*>(offset));
      uint32_t size;
      uint32_t padding;
      // No need to worry about integer overflow here.
      GLES2Util::ComputeImageDataSizesES3(actual_width, args.height - 1, 1,
                                          args.format, args.type,
                                          params,
                                          &size,
                                          nullptr, nullptr, nullptr,
                                          &padding);
      DCHECK_EQ(args.padding, padding);
      // Last row should be padded, not unpadded.
      offset += size + padding;
    }
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexSubImage3D(args.target, args.level, args.xoffset,
                    args.yoffset + args.height - 1,
                    args.zoffset + args.depth - 1, args.width, 1, 1,
                    AdjustTexFormat(feature_info_.get(), args.format),
                    args.type, reinterpret_cast<const void*>(offset));
    glPixelStorei(GL_UNPACK_ALIGNMENT, state->unpack_alignment);
    {
      uint32_t size;
      GLES2Util::ComputeImageDataSizesES3(args.width, 1, 1,
                                          args.format, args.type,
                                          params,
                                          &size,
                                          nullptr, nullptr, nullptr, nullptr);
      offset += size;
    }
  }
  DCHECK_EQ(ToGLuint(args.pixels) + args.pixels_size, offset);
}

void TextureManager::DoTexSubImageRowByRowWorkaround(
    DecoderTextureState* texture_state,
    ContextState* state,
    const DoTexSubImageArguments& args,
    const PixelStoreParams& unpack_params) {
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  DCHECK_EQ(0, state->unpack_skip_pixels);
  DCHECK_EQ(0, state->unpack_skip_rows);
  DCHECK_EQ(0, state->unpack_skip_images);

  GLenum format = AdjustTexFormat(feature_info_.get(), args.format);

  GLsizei row_bytes = unpack_params.row_length *
                      GLES2Util::ComputeImageGroupSize(format, args.type);
  GLsizei alignment_diff = row_bytes % unpack_params.alignment;
  if (alignment_diff != 0) {
    row_bytes += unpack_params.alignment - alignment_diff;
  }
  DCHECK_EQ(0, row_bytes % unpack_params.alignment);
  if (args.command_type == DoTexSubImageArguments::kTexSubImage3D) {
    GLsizei image_height = args.height;
    if (unpack_params.image_height != 0) {
      image_height = unpack_params.image_height;
    }
    GLsizei image_bytes = row_bytes * image_height;
    for (GLsizei image = 0; image < args.depth; ++image) {
      GLsizei image_byte_offset = image * image_bytes;
      for (GLsizei row = 0; row < args.height; ++row) {
        GLsizei byte_offset = image_byte_offset + row * row_bytes;
        const GLubyte* row_pixels =
            reinterpret_cast<const GLubyte*>(args.pixels) + byte_offset;
        glTexSubImage3D(args.target, args.level, args.xoffset,
                        row + args.yoffset, image + args.zoffset, args.width, 1,
                        1, format, args.type, row_pixels);
      }
    }
  } else {
    for (GLsizei row = 0; row < args.height; ++row) {
      GLsizei byte_offset = row * row_bytes;
      const GLubyte* row_pixels =
          reinterpret_cast<const GLubyte*>(args.pixels) + byte_offset;
      glTexSubImage2D(args.target, args.level, args.xoffset, row + args.yoffset,
                      args.width, 1, format, args.type, row_pixels);
    }
  }

  // Restore unpack state
  glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_params.alignment);
  glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_params.row_length);
}

// static
GLenum TextureManager::AdjustTexInternalFormat(
    const gles2::FeatureInfo* feature_info,
    GLenum format) {
  if (feature_info->gl_version_info().is_desktop_core_profile) {
    const Texture::CompatibilitySwizzle* swizzle =
        GetCompatibilitySwizzle(format);
    if (swizzle)
      return swizzle->dest_format;
  }
  return format;
}

// static
GLenum TextureManager::AdjustTexFormat(const gles2::FeatureInfo* feature_info,
                                       GLenum format) {
  // TODO(bajones): GLES 3 allows for internal format and format to differ.
  // This logic may need to change as a result.
  if (!feature_info->gl_version_info().is_es) {
    if (format == GL_SRGB_EXT)
      return GL_RGB;
    if (format == GL_SRGB_ALPHA_EXT)
      return GL_RGBA;
  }
  if (feature_info->gl_version_info().is_desktop_core_profile) {
    const Texture::CompatibilitySwizzle* swizzle =
        GetCompatibilitySwizzle(format);
    if (swizzle)
      return swizzle->dest_format;
  }
  return format;
}

void TextureManager::DoTexImage(
    DecoderTextureState* texture_state,
    ContextState* state,
    DecoderFramebufferState* framebuffer_state,
    const char* function_name,
    TextureRef* texture_ref,
    const DoTexImageArguments& args) {
  ErrorState* error_state = state->GetErrorState();
  Texture* texture = texture_ref->texture();
  GLsizei tex_width = 0;
  GLsizei tex_height = 0;
  GLsizei tex_depth = 0;
  GLenum tex_type = 0;
  GLenum tex_internal_format = 0;
  bool level_is_same =
      texture->GetLevelSize(
          args.target, args.level, &tex_width, &tex_height, &tex_depth) &&
      args.width == tex_width && args.height == tex_height &&
      args.depth == tex_depth &&
      texture->GetLevelType(
          args.target, args.level, &tex_type, &tex_internal_format) &&
      args.type == tex_type && args.internal_format == tex_internal_format;

  bool unpack_buffer_bound =
      (state->bound_pixel_unpack_buffer.get() != nullptr);

  if (level_is_same && !args.pixels && !unpack_buffer_bound) {
    // Just set the level texture but mark the texture as uncleared.
    SetLevelInfo(
        texture_ref, args.target, args.level, args.internal_format, args.width,
        args.height, args.depth, args.border, args.format, args.type,
        gfx::Rect());
    texture_state->tex_image_failed = false;
    return;
  }

  if (texture->IsAttachedToFramebuffer()) {
    framebuffer_state->clear_state_dirty = true;
  }

  if (texture_state->texsubimage_faster_than_teximage &&
      level_is_same && args.pixels && !unpack_buffer_bound) {
    {
      ScopedTextureUploadTimer timer(texture_state);
      if (args.command_type == DoTexImageArguments::kTexImage3D) {
        glTexSubImage3D(args.target, args.level, 0, 0, 0, args.width,
                        args.height, args.depth,
                        AdjustTexFormat(feature_info_.get(), args.format),
                        args.type, args.pixels);
      } else {
        glTexSubImage2D(args.target, args.level, 0, 0, args.width, args.height,
                        AdjustTexFormat(feature_info_.get(), args.format),
                        args.type, args.pixels);
      }
    }
    SetLevelInfo(texture_ref, args.target, args.level, args.internal_format,
                 args.width, args.height, args.depth, args.border, args.format,
                 args.type, gfx::Rect(args.width, args.height));
    texture_state->tex_image_failed = false;
    return;
  }

  ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state, function_name);
  {
    ScopedTextureUploadTimer timer(texture_state);
    if (args.command_type == DoTexImageArguments::kTexImage3D) {
      glTexImage3D(
          args.target, args.level,
          AdjustTexInternalFormat(feature_info_.get(), args.internal_format),
          args.width, args.height, args.depth, args.border,
          AdjustTexFormat(feature_info_.get(), args.format), args.type,
          args.pixels);
    } else {
      glTexImage2D(
          args.target, args.level,
          AdjustTexInternalFormat(feature_info_.get(), args.internal_format),
          args.width, args.height, args.border,
          AdjustTexFormat(feature_info_.get(), args.format), args.type,
          args.pixels);
    }
  }
  GLenum error = ERRORSTATE_PEEK_GL_ERROR(error_state, function_name);
  if (args.command_type == DoTexImageArguments::kTexImage3D) {
    UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error_TexImage3D", error,
        GetAllGLErrors());
  } else {
    UMA_HISTOGRAM_CUSTOM_ENUMERATION("GPU.Error_TexImage2D", error,
        GetAllGLErrors());
  }
  if (error == GL_NO_ERROR) {
    bool set_as_cleared = (args.pixels != nullptr || unpack_buffer_bound);
    SetLevelInfo(
        texture_ref, args.target, args.level, args.internal_format, args.width,
        args.height, args.depth, args.border, args.format, args.type,
        set_as_cleared ? gfx::Rect(args.width, args.height) : gfx::Rect());
    texture->ApplyFormatWorkarounds(feature_info_.get());
    texture_state->tex_image_failed = false;
  }
}

bool TextureManager::CombineAdjacentRects(const gfx::Rect& rect1,
                                          const gfx::Rect& rect2,
                                          gfx::Rect* result) {
  // Return |rect2| if |rect1| is empty or |rect2| contains |rect1|.
  if (rect1.IsEmpty() || rect2.Contains(rect1)) {
    *result = rect2;
    return true;
  }

  // Return |rect1| if |rect2| is empty or |rect1| contains |rect2|.
  if (rect2.IsEmpty() || rect1.Contains(rect2)) {
    *result = rect1;
    return true;
  }

  // Return the union of |rect1| and |rect2| if they share an edge.
  if (rect1.SharesEdgeWith(rect2)) {
    *result = gfx::UnionRects(rect1, rect2);
    return true;
  }

  // Return false if it's not possible to combine |rect1| and |rect2|.
  return false;
}

ScopedTextureUploadTimer::ScopedTextureUploadTimer(
    DecoderTextureState* texture_state)
    : texture_state_(texture_state),
      begin_time_(base::TimeTicks::Now()) {
}

ScopedTextureUploadTimer::~ScopedTextureUploadTimer() {
  texture_state_->texture_upload_count++;
  texture_state_->total_texture_upload_time +=
      base::TimeTicks::Now() - begin_time_;
}

bool TextureManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                                  base::trace_event::ProcessMemoryDump* pmd) {
  for (const auto& resource : textures_) {
    // Only dump memory info for textures actually owned by this TextureManager.
    DumpTextureRef(pmd, resource.second.get());
  }

  // Also dump TextureManager internal textures, if allocated.
  for (int i = 0; i < kNumDefaultTextures; i++) {
    if (default_textures_[i]) {
      DumpTextureRef(pmd, default_textures_[i].get());
    }
  }

  return true;
}

void TextureManager::DumpTextureRef(base::trace_event::ProcessMemoryDump* pmd,
                                    TextureRef* ref) {
  uint32_t size = ref->texture()->estimated_size();

  // Ignore unallocated texture IDs.
  if (size == 0)
    return;

  std::string dump_name = base::StringPrintf(
      "gpu/gl/textures/share_group_%" PRIu64 "/texture_%d",
      memory_tracker_->ShareGroupTracingGUID(), ref->client_id());

  base::trace_event::MemoryAllocatorDump* dump =
      pmd->CreateAllocatorDump(dump_name);
  dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
                  base::trace_event::MemoryAllocatorDump::kUnitsBytes,
                  static_cast<uint64_t>(size));

  // Add the |client_guid| which expresses shared ownership with the client
  // process.
  auto client_guid = gl::GetGLTextureClientGUIDForTracing(
      memory_tracker_->ShareGroupTracingGUID(), ref->client_id());
  pmd->CreateSharedGlobalAllocatorDump(client_guid);
  pmd->AddOwnershipEdge(dump->guid(), client_guid);

  // Add a |service_guid| which expresses shared ownership between the various
  // |client_guid|s.
  // TODO(ericrk): May need to ensure uniqueness using GLShareGroup and
  // potentially cross-share-group sharing via EGLImages. crbug.com/512534
  auto service_guid = gl::GetGLTextureServiceGUIDForTracing(
      memory_tracker_->ShareGroupTracingGUID(), ref->texture()->service_id());
  pmd->CreateSharedGlobalAllocatorDump(service_guid);

  int importance = 0;  // Default importance.
  // The link to the memory tracking |client_id| is given a higher importance
  // than other refs.
  if (ref == ref->texture()->memory_tracking_ref_)
    importance = 2;

  pmd->AddOwnershipEdge(client_guid, service_guid, importance);

  // Dump all sub-levels held by the texture. They will appear below the main
  // gl/textures/client_X/texture_Y dump.
  ref->texture()->DumpLevelMemory(pmd, memory_tracker_->ClientTracingId(),
                                  dump_name);
}

GLenum TextureManager::ExtractFormatFromStorageFormat(GLenum internalformat) {
  switch (internalformat) {
    case GL_RED:
    case GL_R8:
    case GL_R8_SNORM:
    case GL_R16F:
    case GL_R32F:
      return GL_RED;
    case GL_R8UI:
    case GL_R8I:
    case GL_R16UI:
    case GL_R16I:
    case GL_R32UI:
    case GL_R32I:
      return GL_RED_INTEGER;
    case GL_RG:
    case GL_RG8:
    case GL_RG8_SNORM:
    case GL_RG16F:
    case GL_RG32F:
      return GL_RG;
    case GL_RG8UI:
    case GL_RG8I:
    case GL_RG16UI:
    case GL_RG16I:
    case GL_RG32UI:
    case GL_RG32I:
      return GL_RG_INTEGER;
    case GL_ATC_RGB_AMD:
    case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
    case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
    case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
    case GL_ETC1_RGB8_OES:
    case GL_RGB:
    case GL_RGB8:
    case GL_SRGB8:
    case GL_R11F_G11F_B10F:
    case GL_RGB565:
    case GL_RGB8_SNORM:
    case GL_RGB9_E5:
    case GL_RGB16F:
    case GL_RGB32F:
      return GL_RGB;
    case GL_RGB8UI:
    case GL_RGB8I:
    case GL_RGB16UI:
    case GL_RGB16I:
    case GL_RGB32UI:
    case GL_RGB32I:
      return GL_RGB_INTEGER;
    case GL_SRGB:
      return GL_SRGB;
    case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
    case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
    case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
    case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
    case GL_RGBA:
    case GL_RGBA8:
    case GL_SRGB8_ALPHA8:
    case GL_RGBA8_SNORM:
    case GL_RGBA4:
    case GL_RGB5_A1:
    case GL_RGB10_A2:
    case GL_RGBA16F:
    case GL_RGBA32F:
      return GL_RGBA;
    case GL_SRGB_ALPHA:
      return GL_SRGB_ALPHA;
    case GL_RGBA8UI:
    case GL_RGBA8I:
    case GL_RGB10_A2UI:
    case GL_RGBA16UI:
    case GL_RGBA16I:
    case GL_RGBA32UI:
    case GL_RGBA32I:
      return GL_RGBA_INTEGER;
    case GL_BGRA_EXT:
      return GL_BGRA_EXT;
    case GL_DEPTH_COMPONENT16:
    case GL_DEPTH_COMPONENT24:
    case GL_DEPTH_COMPONENT32F:
      return GL_DEPTH_COMPONENT;
    case GL_DEPTH24_STENCIL8:
    case GL_DEPTH32F_STENCIL8:
      return GL_DEPTH_STENCIL;
    case GL_LUMINANCE_ALPHA:
    case GL_LUMINANCE8_ALPHA8_EXT:
      return GL_LUMINANCE_ALPHA;
    case GL_LUMINANCE:
    case GL_LUMINANCE8_EXT:
      return GL_LUMINANCE;
    case GL_ALPHA:
    case GL_ALPHA8_EXT:
      return GL_ALPHA;
    case GL_ALPHA32F_EXT:
      return GL_ALPHA;
    case GL_LUMINANCE32F_EXT:
      return GL_LUMINANCE;
    case GL_LUMINANCE_ALPHA32F_EXT:
      return GL_LUMINANCE_ALPHA;
    case GL_ALPHA16F_EXT:
      return GL_ALPHA;
    case GL_LUMINANCE16F_EXT:
      return GL_LUMINANCE;
    case GL_LUMINANCE_ALPHA16F_EXT:
      return GL_LUMINANCE_ALPHA;
    case GL_BGRA8_EXT:
      return GL_BGRA_EXT;
    default:
      return GL_NONE;
  }
}

GLenum TextureManager::ExtractTypeFromStorageFormat(GLenum internalformat) {
  switch (internalformat) {
    case GL_RED:
    case GL_RG:
    case GL_RGB:
    case GL_SRGB:
    case GL_RGBA:
    case GL_BGRA_EXT:
    case GL_SRGB_ALPHA:
    case GL_LUMINANCE_ALPHA:
    case GL_LUMINANCE:
    case GL_ALPHA:
    case GL_R8:
      return GL_UNSIGNED_BYTE;
    case GL_R8_SNORM:
      return GL_BYTE;
    case GL_R16F:
      return GL_HALF_FLOAT;
    case GL_R32F:
      return GL_FLOAT;
    case GL_R8UI:
      return GL_UNSIGNED_BYTE;
    case GL_R8I:
      return GL_BYTE;
    case GL_R16UI:
      return GL_UNSIGNED_SHORT;
    case GL_R16I:
      return GL_SHORT;
    case GL_R32UI:
      return GL_UNSIGNED_INT;
    case GL_R32I:
      return GL_INT;
    case GL_RG8:
      return GL_UNSIGNED_BYTE;
    case GL_RG8_SNORM:
      return GL_BYTE;
    case GL_RG16F:
      return GL_HALF_FLOAT;
    case GL_RG32F:
      return GL_FLOAT;
    case GL_RG8UI:
      return GL_UNSIGNED_BYTE;
    case GL_RG8I:
      return GL_BYTE;
    case GL_RG16UI:
      return GL_UNSIGNED_SHORT;
    case GL_RG16I:
      return GL_SHORT;
    case GL_RG32UI:
      return GL_UNSIGNED_INT;
    case GL_RG32I:
      return GL_INT;
    case GL_RGB8:
    case GL_SRGB8:
      return GL_UNSIGNED_BYTE;
    case GL_R11F_G11F_B10F:
      return GL_UNSIGNED_INT_10F_11F_11F_REV;
    case GL_RGB565:
      return GL_UNSIGNED_SHORT_5_6_5;
    case GL_RGB8_SNORM:
      return GL_BYTE;
    case GL_RGB9_E5:
      return GL_UNSIGNED_INT_5_9_9_9_REV;
    case GL_RGB16F:
      return GL_HALF_FLOAT;
    case GL_RGB32F:
      return GL_FLOAT;
    case GL_RGB8UI:
      return GL_UNSIGNED_BYTE;
    case GL_RGB8I:
      return GL_BYTE;
    case GL_RGB16UI:
      return GL_UNSIGNED_SHORT;
    case GL_RGB16I:
      return GL_SHORT;
    case GL_RGB32UI:
      return GL_UNSIGNED_INT;
    case GL_RGB32I:
      return GL_INT;
    case GL_RGBA8:
      return GL_UNSIGNED_BYTE;
    case GL_SRGB8_ALPHA8:
      return GL_UNSIGNED_BYTE;
    case GL_RGBA8_SNORM:
      return GL_BYTE;
    case GL_RGBA4:
      return GL_UNSIGNED_SHORT_4_4_4_4;
    case GL_RGB10_A2:
      return GL_UNSIGNED_INT_2_10_10_10_REV;
    case GL_RGB5_A1:
      return GL_UNSIGNED_SHORT_5_5_5_1;
    case GL_RGBA16F:
      return GL_HALF_FLOAT;
    case GL_RGBA32F:
      return GL_FLOAT;
    case GL_RGBA8UI:
      return GL_UNSIGNED_BYTE;
    case GL_RGBA8I:
      return GL_BYTE;
    case GL_RGB10_A2UI:
      return GL_UNSIGNED_INT_2_10_10_10_REV;
    case GL_RGBA16UI:
      return GL_UNSIGNED_SHORT;
    case GL_RGBA16I:
      return GL_SHORT;
    case GL_RGBA32I:
      return GL_INT;
    case GL_RGBA32UI:
      return GL_UNSIGNED_INT;
    case GL_DEPTH_COMPONENT16:
      return GL_UNSIGNED_SHORT;
    case GL_DEPTH_COMPONENT24:
      return GL_UNSIGNED_INT;
    case GL_DEPTH_COMPONENT32F:
      return GL_FLOAT;
    case GL_DEPTH24_STENCIL8:
      return GL_UNSIGNED_INT_24_8;
    case GL_DEPTH32F_STENCIL8:
      return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
    case GL_LUMINANCE8_ALPHA8_EXT:
      return GL_UNSIGNED_BYTE;
    case GL_LUMINANCE8_EXT:
      return GL_UNSIGNED_BYTE;
    case GL_ALPHA8_EXT:
      return GL_UNSIGNED_BYTE;
    case GL_ALPHA32F_EXT:
      return GL_FLOAT;
    case GL_LUMINANCE32F_EXT:
      return GL_FLOAT;
    case GL_LUMINANCE_ALPHA32F_EXT:
      return GL_FLOAT;
    case GL_ALPHA16F_EXT:
      return GL_HALF_FLOAT_OES;
    case GL_LUMINANCE16F_EXT:
      return GL_HALF_FLOAT_OES;
    case GL_LUMINANCE_ALPHA16F_EXT:
      return GL_HALF_FLOAT_OES;
    case GL_BGRA8_EXT:
      return GL_UNSIGNED_BYTE;
    default:
      return GL_NONE;
  }
}

void Texture::IncrementManagerServiceIdGeneration() {
  for (auto* ref : refs_) {
    TextureManager* manager = ref->manager();
    manager->IncrementServiceIdGeneration();
  }
}

uint32_t TextureManager::GetServiceIdGeneration() const {
  return current_service_id_generation_;
}

void TextureManager::IncrementServiceIdGeneration() {
  current_service_id_generation_++;
}

}  // namespace gles2
}  // namespace gpu
