// 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 <tuple>
#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/decoder_context.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/mailbox_manager.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/progress_reporter.h"
#include "gpu/command_buffer/service/service_discardable_manager.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"

using base::trace_event::MemoryAllocatorDump;
using base::trace_event::MemoryDumpLevelOfDetail;

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},

        // 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},

        // Exposed by GL_APPLE_texture_format_BGRA8888 for TexStorage*
        // TODO(kainino): this actually exposes it for (Copy)TexImage* as well,
        // which is incorrect. crbug.com/663086
        {GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE},

        // Exposed by GL_APPLE_texture_format_BGRA8888 and
        // GL_EXT_texture_format_BGRA8888
        {GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE},

        // Exposed by GL_EXT_texture_norm16
        {GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT},
    };

    static const FormatType kSupportedFormatTypesES2Only[] = {
        // 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_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},

        // Exposed by GL_EXT_texture_norm16
        {GL_RED, GL_RED, GL_UNSIGNED_SHORT},
    };

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

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

  // This may be accessed from multiple threads.
  bool IsValid(ContextType context_type, GLenum internal_format, GLenum format,
               GLenum type) const {
    FormatType query = { internal_format, format, type };
    if (supported_combinations_.find(query) != supported_combinations_.end()) {
      return true;
    }
    if (context_type == CONTEXT_TYPE_OPENGLES2 ||
        context_type == CONTEXT_TYPE_WEBGL1) {
      if (supported_combinations_es2_only_.find(query) !=
          supported_combinations_es2_only_.end()) {
        return true;
      }
    }
    return false;
  }

 private:
  // FormatType is a tuple of <internal_format, format, type>
  typedef std::tuple<GLenum, GLenum, GLenum> FormatType;
  struct FormatTypeCompare {
    bool operator() (const FormatType& lhs, const FormatType& rhs) const {
      return (std::get<0>(lhs) < std::get<0>(rhs) ||
              ((std::get<0>(lhs) == std::get<0>(rhs)) &&
               (std::get<1>(lhs) < std::get<1>(rhs))) ||
              ((std::get<0>(lhs) == std::get<0>(rhs)) &&
               (std::get<1>(lhs) == std::get<1>(rhs)) &&
               (std::get<2>(lhs) < std::get<2>(rhs))));
    }
  };

  // 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_;
  std::set<FormatType, FormatTypeCompare> supported_combinations_es2_only_;
};

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},
};

const Texture::CompatibilitySwizzle* GetCompatibilitySwizzleInternal(
    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;
  }
}

bool SizedFormatAvailable(const FeatureInfo* feature_info,
                          bool immutable,
                          GLenum internal_format) {
  if (immutable)
    return true;

  if (feature_info->feature_flags().ext_texture_norm16 &&
      internal_format == GL_R16_EXT) {
    return true;
  }

  if ((feature_info->feature_flags().chromium_image_ycbcr_420v &&
       internal_format == GL_RGB_YCBCR_420V_CHROMIUM) ||
      (feature_info->feature_flags().chromium_image_ycbcr_422 &&
       internal_format == GL_RGB_YCBCR_422_CHROMIUM)) {
    return true;
  }

  if (internal_format == GL_RGB10_A2_EXT &&
      (feature_info->feature_flags().chromium_image_xr30 ||
       feature_info->feature_flags().chromium_image_xb30)) {
    return true;
  }

  // TODO(dshwang): check if it's possible to remove
  // CHROMIUM_color_buffer_float_rgb. crbug.com/329605
  if (feature_info->feature_flags().chromium_color_buffer_float_rgb &&
      internal_format == GL_RGB32F) {
    return true;
  }
  if (feature_info->feature_flags().chromium_color_buffer_float_rgba &&
      internal_format == GL_RGBA32F) {
    return true;
  }
  // RGBA16F textures created as WebGL 2 backbuffers (in GLES3 contexts) may be
  // shared with compositor GLES2 contexts for compositing.
  // https://crbug.com/777750
  if (feature_info->feature_flags().enable_texture_half_float_linear &&
      internal_format == GL_RGBA16F) {
    return true;
  }
  return feature_info->IsWebGL2OrES3Context();
}

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

class ScopedResetPixelUnpackBuffer{
 public:
  explicit ScopedResetPixelUnpackBuffer(ContextState* state)
      : buffer_(nullptr) {
    buffer_ = state->bound_pixel_unpack_buffer.get();
    if (buffer_) {
      glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    }
  }

  ~ScopedResetPixelUnpackBuffer() {
    if (buffer_) {
      glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer_->service_id());
    }
  }

 private:
    Buffer* buffer_;
};

class ScopedMemTrackerChange {
 public:
  explicit ScopedMemTrackerChange(Texture* texture)
      : texture_(texture),
        previous_tracker_(texture->GetMemTracker()),
        previous_size_(texture->estimated_size()) {}
  ~ScopedMemTrackerChange() {
    MemoryTypeTracker* new_tracker = texture_->GetMemTracker();
    uint32_t new_size = texture_->estimated_size();
    if ((new_tracker == previous_tracker_) && (new_size == previous_size_))
      return;
    if (previous_tracker_)
      previous_tracker_->TrackMemFree(previous_size_);
    if (new_tracker)
      new_tracker->TrackMemAlloc(new_size);
  }

 private:
  Texture* texture_;
  MemoryTypeTracker* previous_tracker_;
  uint32_t previous_size_;
};

}  // namespace anonymous

DecoderTextureState::DecoderTextureState(
    const GpuDriverBugWorkarounds& workarounds)
    : tex_image_failed(false),
      texsubimage_faster_than_teximage(
          workarounds.texsubimage_faster_than_teximage),
      force_cube_map_positive_x_allocation(
          workarounds.force_cube_map_positive_x_allocation),
      force_cube_complete(workarounds.force_cube_complete),
      force_int_or_srgb_cube_texture_complete(
          workarounds.force_int_or_srgb_cube_texture_complete),
      unpack_alignment_workaround_with_unpack_buffer(
          workarounds.unpack_alignment_workaround_with_unpack_buffer),
      unpack_overlapping_rows_separately_unpack_buffer(
          workarounds.unpack_overlapping_rows_separately_unpack_buffer),
      unpack_image_height_workaround_with_unpack_buffer(
          workarounds.unpack_image_height_workaround_with_unpack_buffer) {}

TextureManager::DestructionObserver::DestructionObserver() = default;

TextureManager::DestructionObserver::~DestructionObserver() = default;

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::MarkContextLost() {
  have_context_ = false;
}

void TextureManager::Destroy() {
  // Retreive any outstanding unlocked textures from the discardable manager so
  // we can clean them up here.
  discardable_manager_->OnTextureManagerDestruction(this);

  while (!textures_.empty()) {
    textures_.erase(textures_.begin());
    if (progress_reporter_)
      progress_reporter_->ReportProgress();
  }
  for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
    default_textures_[ii] = NULL;
    if (progress_reporter_)
      progress_reporter_->ReportProgress();
  }

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

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

TexturePassthrough::TexturePassthrough(GLuint service_id, GLenum target)
    : TextureBase(service_id),
      have_context_(true),
      level_images_(target == GL_TEXTURE_CUBE_MAP ? 6 : 1) {
  TextureBase::SetTarget(target);
}

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

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

void TexturePassthrough::SetLevelImage(GLenum target,
                                       GLint level,
                                       gl::GLImage* image) {
  size_t face_idx = GLES2Util::GLTargetToFaceIndex(target);
  DCHECK(face_idx < level_images_.size());
  DCHECK(level >= 0);

  // Don't allocate space for the images until needed
  if (static_cast<GLint>(level_images_[face_idx].size()) <= level) {
    level_images_[face_idx].resize(level + 1);
  }

  level_images_[face_idx][level] = image;
}

gl::GLImage* TexturePassthrough::GetLevelImage(GLenum target,
                                               GLint level) const {
  if (GLES2Util::GLFaceTargetToTextureTarget(target) != target_) {
    return nullptr;
  }

  size_t face_idx = GLES2Util::GLTargetToFaceIndex(target);
  DCHECK(face_idx < level_images_.size());
  DCHECK(level >= 0);

  if (static_cast<GLint>(level_images_[face_idx].size()) <= level) {
    return nullptr;
  }

  return level_images_[face_idx][level].get();
}

Texture::Texture(GLuint service_id)
    : TextureBase(service_id),
      owned_service_id_(service_id) {}

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

void Texture::AddTextureRef(TextureRef* ref) {
  DCHECK(refs_.find(ref) == refs_.end());
  refs_.insert(ref);
  ScopedMemTrackerChange change(this);
  if (!memory_tracking_ref_)
    memory_tracking_ref_ = ref;
}

void Texture::RemoveTextureRef(TextureRef* ref, bool have_context) {
  {
    ScopedMemTrackerChange change(this);
    if (memory_tracking_ref_ == ref)
      memory_tracking_ref_ = nullptr;
    size_t result = refs_.erase(ref);
    DCHECK_EQ(result, 1u);
    if (!memory_tracking_ref_ && !refs_.empty())
      memory_tracking_ref_ = *refs_.begin();
  }
  MaybeDeleteThis(have_context);
}

void Texture::SetLightweightRef(MemoryTypeTracker* tracker) {
  DCHECK(!lightweight_ref_);
  DCHECK(tracker);
  ScopedMemTrackerChange change(this);
  lightweight_ref_ = tracker;
}

void Texture::RemoveLightweightRef(bool have_context) {
  DCHECK(lightweight_ref_);
  {
    ScopedMemTrackerChange change(this);
    lightweight_ref_ = nullptr;
  }
  MaybeDeleteThis(have_context);
}

void Texture::MaybeDeleteThis(bool have_context) {
  if (!refs_.empty() || lightweight_ref_)
    return;
  if (have_context)
    glDeleteTextures(1, &owned_service_id_);
  delete this;
}

MemoryTypeTracker* Texture::GetMemTracker() {
  if (lightweight_ref_)
    return lightweight_ref_;
  else if (memory_tracking_ref_)
    return memory_tracking_ref_->manager()->GetMemTracker();
  else
    return nullptr;
}

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() = default;

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

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

Texture::FaceInfo::~FaceInfo() = default;

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) {
      if (sampler_state.compare_mode == GL_NONE) {
        // In ES2 with OES_depth_texture, such limitation isn't specified.
        if (feature_info->IsWebGL2OrES3Context()) {
          return false;
        }
      }
    } else if (feature_info->validators()->compressed_texture_format.IsValid(
        first_level.internal_format)) {
      // TODO(zmo): The assumption that 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, immutable_)) {
        return false;
      }
    }
  }

  if (!feature_info->IsWebGL2OrES3Context()) {
    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) {
  TextureBase::SetTarget(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;
  }

  // According to the OpenGL extension spec EXT_sRGB.txt, EXT_SRGB is based on
  // ES 2.0 and generateMipmap is not allowed if texture format is SRGB_EXT or
  // SRGB_ALPHA_EXT.
  if (feature_info->IsWebGL1OrES2Context() &&
      (base.format == GL_SRGB_EXT || base.format == GL_SRGB_ALPHA_EXT)) {
    return false;
  }

  if (!feature_info->validators()->texture_unsized_internal_format.IsValid(
      base.internal_format)) {
    if (!Texture::ColorRenderable(feature_info, base.internal_format,
                                  immutable_) ||
        !Texture::TextureFilterable(feature_info, base.internal_format,
                                    base.type,
                                    immutable_)) {
      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,
                              bool immutable) {
  if (feature_info->validators()->texture_unsized_internal_format.IsValid(
      internal_format)) {
    return internal_format != GL_ALPHA && internal_format != GL_LUMINANCE &&
           internal_format != GL_LUMINANCE_ALPHA &&
           internal_format != GL_SRGB_EXT;
  }

  return SizedFormatAvailable(feature_info, immutable, internal_format) &&
         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,
                                bool immutable) {
  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 SizedFormatAvailable(feature_info, immutable, internal_format) &&
         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;

  GLint base_level = base_level_;
  GLint max_level = max_level_;
  if (immutable_) {
    GLint levels = GetImmutableLevels();
    DCHECK_LE(1, levels);
    DCHECK_LE(0, base_level_);
    base_level = std::min(base_level_, levels - 1);
    max_level = std::max(base_level, max_level_);
    max_level = std::min(max_level, levels - 1);
  }
  GLint max_num_mip_levels = std::max(0, max_level - base_level + 1);
  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(
        max_num_mip_levels, TextureManager::ComputeMipMapCount(
                                target_, info.width, info.height, info.depth));
  }

  // mipmap-completeness needs to be re-evaluated.
  completeness_dirty_ = true;
  Update();
  UpdateCanRenderCondition();
}

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 || info.internal_workaround) {
    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.
    completeness_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);

  {
    ScopedMemTrackerChange change(this);
    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;
  completeness_dirty_ = true;
  Update();
  UpdateCanRenderCondition();
}

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 xoffset >= 0 &&
           yoffset >= 0 &&
           zoffset >= 0 &&
           width >= 0 &&
           height >= 0 &&
           depth >= 0 &&
           SafeAddInt32(xoffset, width, &max_x) &&
           SafeAddInt32(yoffset, height, &max_y) &&
           SafeAddInt32(zoffset, depth, &max_z) &&
           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_SRGB_DECODE_EXT:
      if (!feature_info->validators()->texture_srgb_decode_ext.IsValid(param)) {
        return GL_INVALID_ENUM;
      }
      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:
    case GL_TEXTURE_SWIZZLE_R:
    case GL_TEXTURE_SWIZZLE_G:
    case GL_TEXTURE_SWIZZLE_B:
    case GL_TEXTURE_SWIZZLE_A: {
      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 (!completeness_dirty_)
    return;

  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_) {
    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_complete_ &= texture_mips_complete;
  completeness_dirty_ = false;
}

bool Texture::ClearRenderableLevels(DecoderContext* 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;
}

void Texture::SetImmutable(bool immutable) {
  if (immutable_ == immutable)
    return;
  immutable_ = immutable;

  UpdateNumMipLevels();
}

GLint Texture::GetImmutableLevels() const {
  if (!immutable_)
    return 0;
  GLint levels = 0;
  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(DecoderContext* 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;

      std::string level_dump_name = base::StringPrintf(
          "%s/face_%d/level_%d", dump_name.c_str(), face_index, level_index);

      // If a level has a GLImage, ask the GLImage to dump itself.
      // 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) {
        level_infos[level_index].image->OnMemoryDump(pmd, client_tracing_id,
                                                     level_dump_name);
      } else {
        MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(level_dump_name);
        dump->AddScalar(
            MemoryAllocatorDump::kNameSize, 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()));
  if (level > base_level_ && !texture_complete()) {
    return false;
  }
  GLenum internal_format = face_infos_[0].level_infos[level].internal_format;
  bool color_renderable = ColorRenderable(feature_info, internal_format,
                                          immutable_);
  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(GetCompatibilitySwizzleInternal(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,
                               ProgressReporter* progress_reporter,
                               ServiceDiscardableManager* discardable_manager)
    : memory_type_tracker_(new MemoryTypeTracker(memory_tracker)),
      memory_tracker_(memory_tracker),
      feature_info_(feature_info),
      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),
      progress_reporter_(progress_reporter),
      discardable_manager_(discardable_manager) {
  for (int ii = 0; ii < kNumDefaultTextures; ++ii) {
    black_texture_ids_[ii] = 0;
  }
}

void TextureManager::AddFramebufferManager(
    FramebufferManager* framebuffer_manager) {
  framebuffer_managers_.push_back(framebuffer_manager);
}

void TextureManager::RemoveFramebufferManager(
    FramebufferManager* framebuffer_manager) {
  for (unsigned int i = 0; i < framebuffer_managers_.size(); ++i) {
    if (framebuffer_managers_[i] == framebuffer_manager) {
      std::swap(framebuffer_managers_[i], framebuffer_managers_.back());
      framebuffer_managers_.pop_back();
      return;
    }
  }
  NOTREACHED();
}

void 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_->IsWebGL2OrES3Context()) {
    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());
  }
}

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(DecoderContext* decoder,
                                           TextureRef* ref) {
  DCHECK(ref);
  return ref->texture()->ClearRenderableLevels(decoder);
}

bool TextureManager::ClearTextureLevel(DecoderContext* 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->SetLevelInfo(target, level, internal_format, width, height, depth,
                        border, format, type, cleared_rect);
  discardable_manager_->OnTextureSizeChanged(ref->client_id(), this,
                                             texture->estimated_size());
}

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);
  ref->texture()->MarkMipmapsGenerated();
}

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;
}

scoped_refptr<TextureRef> TextureManager::TakeTexture(GLuint client_id) {
  auto it = textures_.find(client_id);
  if (it == textures_.end())
    return nullptr;

  scoped_refptr<TextureRef> ref = it->second;
  textures_.erase(it);
  return ref;
}

void TextureManager::ReturnTexture(scoped_refptr<TextureRef> texture_ref) {
  GLuint client_id = texture_ref->client_id();
  // If we've generated a replacement texture due to "bind generates resource",
  // behavior, just delete the resource being returned.
  TextureMap::iterator it = textures_.find(client_id);
  if (it != textures_.end()) {
    // Reset the client id so it doesn't interfere with the generated resource.
    texture_ref->reset_client_id();
    return;
  }

  textures_.emplace(client_id, std::move(texture_ref));
}

void TextureManager::RemoveTexture(GLuint client_id) {
  TextureMap::iterator it = textures_.find(client_id);
  if (it != textures_.end()) {
    discardable_manager_->OnTextureDeleted(client_id, this);
    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);

  if (ref->client_id())
    discardable_manager_->OnTextureDeleted(ref->client_id(), this);
}

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() {
  for (unsigned int i = 0; i < framebuffer_managers_.size(); ++i) {
    framebuffer_managers_[i]->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 = std::string("invalid internal_format ") +
        GLES2Util::GetStringEnum(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(feature_info_->context_type(),
                                             internal_format, format, type)) {
    std::string msg = std::string(
        "invalid internalformat/format/type combination ") +
        GLES2Util::GetStringEnum(internal_format) + std::string("/") +
        GLES2Util::GetStringEnum(format) + std::string("/") +
        GLES2Util::GetStringEnum(type);
    ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
                            msg.c_str());
    return false;
  }
  if (!feature_info_->IsWebGL2OrES3Context()) {
    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 (feature_info_->IsWebGL1OrES2Context()) {
    switch (args.format) {
      case GL_DEPTH_COMPONENT:
      case GL_DEPTH_STENCIL:
        if (args.target != GL_TEXTURE_2D) {
          ERRORSTATE_SET_GL_ERROR(
              error_state, GL_INVALID_OPERATION, function_name,
              "invalid target for depth/stencil textures");
          return false;
        }
        break;
      default:
        break;
    }
  }
  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_->IsWebGL2OrES3Context()) {
    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;
    }
    if (buffer->IsBoundForTransformFeedbackAndOther()) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, function_name,
          "pixel unpack buffer is simultaneously bound for transform feedback");
      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 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;
    }
  }

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

void TextureManager::DoCubeMapWorkaround(
    DecoderTextureState* texture_state,
    ContextState* state,
    DecoderFramebufferState* framebuffer_state,
    TextureRef* texture_ref,
    const char* function_name,
    const DoTexImageArguments& args) {
  std::vector<GLenum> undefined_faces;
  Texture* texture = texture_ref->texture();
  if (texture_state->force_cube_complete ||
      texture_state->force_int_or_srgb_cube_texture_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(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);
    }
  }
  DoTexImageArguments new_args = args;
  std::unique_ptr<char[]> zero(new char[args.pixels_size]);
  memset(zero.get(), 0, args.pixels_size);
  // Need to clear PIXEL_UNPACK_BUFFER and UNPACK params for data uploading.
  state->PushTextureUnpackState();
  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);
  }
  state->RestoreUnpackState();
}

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_->IsWebGL2OrES3Context() &&
      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));
  // Force integer or srgb cube map texture complete, see crbug.com/712117.
  need_cube_map_workaround =
      need_cube_map_workaround ||
      (texture->target() == GL_TEXTURE_CUBE_MAP &&
       texture_state->force_int_or_srgb_cube_texture_complete &&
       (GLES2Util::IsIntegerFormat(args.internal_format) ||
        GLES2Util::GetColorEncodingFromInternalFormat(args.internal_format) ==
            GL_SRGB));

  if (need_cube_map_workaround && !buffer) {
    DoCubeMapWorkaround(texture_state, state, framebuffer_state,
                        texture_ref, function_name, args);
  }

  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 (args.command_type == DoTexImageArguments::kTexImage3D &&
      texture_state->unpack_image_height_workaround_with_unpack_buffer &&
      buffer) {
    ContextState::Dimension dimension = ContextState::k3D;
    const PixelStoreParams unpack_params(state->GetUnpackParams(dimension));
    if (unpack_params.image_height != 0 &&
        unpack_params.image_height != args.height) {
      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,
          DoTexSubImageArguments::kTexSubImage3D};
      DoTexSubImageLayerByLayerWorkaround(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 &&
      args.width && args.height && args.depth) {
    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_->IsWebGL2OrES3Context()) {
    // 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_->IsWebGL2OrES3Context()) {
    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 false;
    }
    if (buffer->IsBoundForTransformFeedbackAndOther()) {
      ERRORSTATE_SET_GL_ERROR(
          error_state, GL_INVALID_OPERATION, function_name,
          "pixel unpack buffer is simultaneously bound for transform feedback");
      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 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;
    }
  } else {
    if (!args.pixels && args.pixels_size) {
      // This isn't in the spec, but the spec would define dereferencing NULL
      // here. Fail instead.
      ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_OPERATION, function_name,
                              "non-empty rect without valid data");
      return false;
    }
  }
  *texture_ref = local_texture_ref;
  return true;
}

void TextureManager::ValidateAndDoTexSubImage(
    DecoderContext* decoder,
    DecoderTextureState* texture_state,
    ContextState* state,
    DecoderFramebufferState* framebuffer_state,
    const char* function_name,
    const DoTexSubImageArguments& args) {
  TRACE_EVENT0("gpu", "TextureManager::ValidateAndDoTexSubImage");
  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) {
      TRACE_EVENT0("gpu", "RowByRowWorkaround");
      // 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 (args.command_type == DoTexSubImageArguments::kTexSubImage3D &&
      texture_state->unpack_image_height_workaround_with_unpack_buffer &&
      buffer) {
    ContextState::Dimension dimension = ContextState::k3D;
    const PixelStoreParams unpack_params(state->GetUnpackParams(dimension));
    if (unpack_params.image_height != 0 &&
        unpack_params.image_height != args.height) {
      TRACE_EVENT0("gpu", "LayerByLayerWorkaround");
      DoTexSubImageLayerByLayerWorkaround(texture_state, state, args,
                                          unpack_params);
      return;
    }
  }

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

  if (full_image && !texture_state->texsubimage_faster_than_teximage &&
      !texture->IsImmutable() && !texture->HasImages()) {
    TRACE_EVENT0("gpu", "FullImage");
    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 {
    TRACE_EVENT0("gpu", "SubImage");
    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);

  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);
}

void TextureManager::DoTexSubImageLayerByLayerWorkaround(
    DecoderTextureState* texture_state,
    ContextState* state,
    const DoTexSubImageArguments& args,
    const PixelStoreParams& unpack_params) {
  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);

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

  GLsizei row_length =
      unpack_params.row_length ? unpack_params.row_length : args.width;
  GLsizei row_bytes =
      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);

  // process the texture layer by layer
  GLsizei image_height = unpack_params.image_height;
  GLsizei image_bytes = row_bytes * image_height;
  const GLubyte* image_pixels = reinterpret_cast<const GLubyte*>(args.pixels);
  for (GLsizei image = 0; image < args.depth - 1; ++image) {
    glTexSubImage3D(args.target, args.level, args.xoffset, args.yoffset,
                    image + args.zoffset, args.width, args.height, 1, format,
                    args.type, image_pixels);

    image_pixels += image_bytes;
  }

  // Process the last image row by row
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  const GLubyte* row_pixels = image_pixels;
  for (GLsizei row = 0; row < args.height; ++row) {
    glTexSubImage3D(args.target, args.level, args.xoffset, row + args.yoffset,
                    args.depth - 1 + args.zoffset, args.width, 1, 1, format,
                    args.type, row_pixels);
    row_pixels += row_bytes;
  }
  // Restore unpack state
  glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_params.alignment);
  glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, unpack_params.image_height);
}

// static
const Texture::CompatibilitySwizzle* TextureManager::GetCompatibilitySwizzle(
    const gles2::FeatureInfo* feature_info,
    GLenum format) {
  if (feature_info->gl_version_info().is_desktop_core_profile) {
    return GetCompatibilitySwizzleInternal(format);
  } else {
    return nullptr;
  }
}

// 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 =
        GetCompatibilitySwizzleInternal(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 =
        GetCompatibilitySwizzleInternal(format);
    if (swizzle)
      return swizzle->dest_format;
  }
  return format;
}

// static
GLenum TextureManager::AdjustTexStorageFormat(
    const gles2::FeatureInfo* feature_info,
    GLenum format) {
  // We need to emulate luminance/alpha on core profile only.
  if (feature_info->gl_version_info().is_desktop_core_profile) {
    switch (format) {
      case GL_ALPHA8_EXT:
        return GL_R8_EXT;
      case GL_LUMINANCE8_EXT:
        return GL_R8_EXT;
      case GL_LUMINANCE8_ALPHA8_EXT:
        return GL_RG8_EXT;
      case GL_ALPHA16F_EXT:
        return GL_R16F_EXT;
      case GL_LUMINANCE16F_EXT:
        return GL_R16F_EXT;
      case GL_LUMINANCE_ALPHA16F_EXT:
        return GL_RG16F_EXT;
      case GL_ALPHA32F_EXT:
        return GL_R32F_EXT;
      case GL_LUMINANCE32F_EXT:
        return GL_R32F_EXT;
      case GL_LUMINANCE_ALPHA32F_EXT:
        return GL_RG32F_EXT;
    }
  }
  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) {
    {
      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);
  {
    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;
}

bool TextureManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                                  base::trace_event::ProcessMemoryDump* pmd) {
  if (args.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND) {
    std::string dump_name =
        base::StringPrintf("gpu/gl/textures/share_group_0x%" PRIX64,
                           memory_tracker_->ShareGroupTracingGUID());
    MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
    dump->AddScalar(MemoryAllocatorDump::kNameSize,
                    MemoryAllocatorDump::kUnitsBytes, mem_represented());

    // Early out, no need for more detail in a BACKGROUND dump.
    return true;
  }

  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_0x%" PRIX64 "/texture_0x%" PRIX32,
      memory_tracker_->ShareGroupTracingGUID(), ref->client_id());

  MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name);
  dump->AddScalar(MemoryAllocatorDump::kNameSize,
                  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_COMPRESSED_R11_EAC:
    case GL_COMPRESSED_SIGNED_R11_EAC:
    case GL_RED:
    case GL_R8:
    case GL_R8_SNORM:
    case GL_R16F:
    case GL_R32F:
    case GL_R16_EXT:
      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_COMPRESSED_RG11_EAC:
    case GL_COMPRESSED_SIGNED_RG11_EAC:
    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_RGB8_ETC2:
    case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
    case GL_COMPRESSED_SRGB8_ETC2:
    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_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    case GL_COMPRESSED_RGBA8_ETC2_EAC:
    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_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
    case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    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:
    case GL_BGRA8_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;
    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_R16_EXT:
      return GL_UNSIGNED_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
