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

#ifndef GPU_COMMAND_BUFFER_SERVICE_TEXTURE_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_TEXTURE_MANAGER_H_

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

#include <algorithm>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "build/build_config.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/memory_tracking.h"
#include "gpu/command_buffer/service/sampler_manager.h"
#include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
#include "gpu/command_buffer/service/texture_base.h"
#include "gpu/gpu_gles2_export.h"
#include "ui/gfx/geometry/rect.h"

namespace gl {
class GLImage;
class ProgressReporter;
}

namespace gpu {
class DecoderContext;
class ServiceDiscardableManager;

namespace gles2 {
struct ContextState;
struct DecoderFramebufferState;
class ErrorState;
class FeatureInfo;
class FramebufferManager;
class Texture;
class TextureManager;
class TextureRef;

// A ref-counted version of the TextureBase class that deletes the texture after
// all references have been released.
class GPU_GLES2_EXPORT TexturePassthrough final
    : public TextureBase,
      public base::RefCounted<TexturePassthrough>,
      public base::SupportsWeakPtr<TexturePassthrough> {
 public:
  TexturePassthrough(GLuint service_id, GLenum target);
  TexturePassthrough(GLuint service_id,
                     GLenum target,
                     GLenum internal_format,
                     GLsizei width,
                     GLsizei height,
                     GLsizei depth,
                     GLint border,
                     GLenum format,
                     GLenum type);

  TexturePassthrough(const TexturePassthrough&) = delete;
  TexturePassthrough& operator=(const TexturePassthrough&) = delete;

  // TextureBase implementation:
  TextureBase::Type GetType() const override;

  static TexturePassthrough* CheckedCast(TextureBase* texture);

  // Notify the texture that the context is lost and it shouldn't delete the
  // native GL texture in the destructor
  void MarkContextLost();

#if !BUILDFLAG(IS_ANDROID)
  void SetLevelImage(GLenum target, GLint level, gl::GLImage* image);
  gl::GLImage* GetLevelImage(GLenum target, GLint level) const;
#endif

#if BUILDFLAG(IS_ANDROID)
  void BindToServiceId(GLuint service_id);
#endif

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
  // Return true if and only if the decoder should BindTexImage / CopyTexImage
  // us before sampling.
  bool is_bind_pending() const { return is_bind_pending_; }
  void set_bind_pending() { is_bind_pending_ = true; }
  void clear_bind_pending() { is_bind_pending_ = false; }
#endif

  void SetEstimatedSize(size_t size);
  size_t estimated_size() const { return estimated_size_; }

 protected:
  ~TexturePassthrough() override;

 private:
  bool LevelInfoExists(GLenum target, GLint level, size_t* out_face_idx) const;

#if !BUILDFLAG(IS_ANDROID)
  void SetLevelImageInternal(GLenum target,
                             GLint level,
                             gl::GLImage* image,
                             GLuint service_id);
#endif

  friend class base::RefCounted<TexturePassthrough>;

  const GLuint owned_service_id_ = 0;

  bool have_context_;
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
  bool is_bind_pending_ = false;
#endif

  size_t estimated_size_ = 0;

  // Bound images divided into faces and then levels
  struct LevelInfo {
    LevelInfo();
    LevelInfo(const LevelInfo& rhs);
    ~LevelInfo();

    GLenum internal_format = 0;
    GLsizei width = 0;
    GLsizei height = 0;
    GLsizei depth = 0;
    GLint border = 0;
    GLenum format = 0;
    GLenum type = 0;

    scoped_refptr<gl::GLImage> image;
  };

  LevelInfo* GetLevelInfo(GLenum target, GLint level);

  std::vector<std::vector<LevelInfo>> level_images_;
};

// Info about Textures currently in the system.
// This class wraps a real GL texture, keeping track of its meta-data. It is
// jointly owned by possibly multiple TextureRef.
class GPU_GLES2_EXPORT Texture final : public TextureBase {
 public:
  enum ImageState {
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
    // If an image is associated with the texture and image state is UNBOUND,
    // then sampling out of the texture or using it as a target for drawing
    // will not read/write from/to the image.
    UNBOUND,
#endif
    // If image state is BOUND, then sampling from the texture will return the
    // contents of the image and using it as a target will modify the image.
    BOUND,
    // State when there is no image present.
    NOIMAGE,
  };

  struct CompatibilitySwizzle {
    GLenum format;
    GLenum dest_format;
    GLenum red;
    GLenum green;
    GLenum blue;
    GLenum alpha;
  };

  struct LevelInfo {
    LevelInfo();
    LevelInfo(const LevelInfo& rhs);
    ~LevelInfo();

    gfx::Rect cleared_rect;
    GLenum target = 0;
    GLint level = -1;
    GLenum internal_format = 0;
    GLsizei width = 0;
    GLsizei height = 0;
    GLsizei depth = 0;
    GLint border = 0;
    GLenum format = 0;
    GLenum type = 0;
    scoped_refptr<gl::GLImage> image;
    uint32_t estimated_size = 0;
    bool internal_workaround = false;

   private:
    friend class Texture;

    // Nothing outside of Texture should directly access the binding state of
    // the image; clients can use Texture::HasUnboundLevelImage().
    ImageState image_state = NOIMAGE;
  };

  explicit Texture(GLuint service_id);

  Texture(const Texture&) = delete;
  Texture& operator=(const Texture&) = delete;

  // TextureBase implementation:
  TextureBase::Type GetType() const override;

  static Texture* CheckedCast(TextureBase* texture);

  const SamplerState& sampler_state() const {
    return sampler_state_;
  }

  void set_min_filter(GLenum min_filter) {
    sampler_state_.min_filter = min_filter;
  }

  GLenum min_filter() const {
    return sampler_state_.min_filter;
  }

  void set_mag_filter(GLenum mag_filter) {
    sampler_state_.mag_filter = mag_filter;
  }

  GLenum mag_filter() const {
    return sampler_state_.mag_filter;
  }

  void set_wrap_r(GLenum wrap_r) { sampler_state_.wrap_r = wrap_r; }

  GLenum wrap_r() const {
    return sampler_state_.wrap_r;
  }

  void set_wrap_s(GLenum wrap_s) { sampler_state_.wrap_s = wrap_s; }

  GLenum wrap_s() const {
    return sampler_state_.wrap_s;
  }

  void set_wrap_t(GLenum wrap_t) { sampler_state_.wrap_t = wrap_t; }

  GLenum wrap_t() const {
    return sampler_state_.wrap_t;
  }

  GLenum usage() const {
    return usage_;
  }

  GLenum compare_func() const {
    return sampler_state_.compare_func;
  }

  GLenum compare_mode() const {
    return sampler_state_.compare_mode;
  }

  GLfloat max_lod() const {
    return sampler_state_.max_lod;
  }

  GLfloat min_lod() const {
    return sampler_state_.min_lod;
  }

  GLint base_level() const {
    return base_level_;
  }

  GLint max_level() const {
    return max_level_;
  }

  GLint unclamped_base_level() const { return unclamped_base_level_; }

  GLint unclamped_max_level() const { return unclamped_max_level_; }

  GLenum swizzle_r() const { return swizzle_r_; }

  GLenum swizzle_g() const { return swizzle_g_; }

  GLenum swizzle_b() const { return swizzle_b_; }

  GLenum swizzle_a() const { return swizzle_a_; }

  int num_uncleared_mips() const {
    return num_uncleared_mips_;
  }

  uint32_t estimated_size() const { return estimated_size_; }

  bool CanRenderTo(const FeatureInfo* feature_info, GLint level) const;

  bool SafeToRenderFrom() const {
    return cleared_;
  }

  // Get the width/height/depth for a particular level. Returns false if level
  // does not exist.
  // |depth| is optional and can be nullptr.
  bool GetLevelSize(
      GLint target, GLint level,
      GLsizei* width, GLsizei* height, GLsizei* depth) const;

  // Get the type of a level. Returns false if level does not exist.
  bool GetLevelType(
      GLint target, GLint level, GLenum* type, GLenum* internal_format) const;

  // Set an image that has already been bound for a particular level. If a
  // GLImage was previously set with BindToServiceId(), this will reset
  // |service_id_| back to |owned_service_id_|, removing the service id override
  // set by the BindToServiceId.
  void SetBoundLevelImage(GLenum target, GLint level, gl::GLImage* image);

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
  // Set an image that needs binding for a particular level. If a
  // GLImage was previously set with BindToServiceId(), this will reset
  // |service_id_| back to |owned_service_id_|, removing the service id
  // override set by the BindToServiceId.
  void SetUnboundLevelImage(GLenum target, GLint level, gl::GLImage* image);
#endif

  // Unset the image for a particular level. After this call, GetLevelImage()
  // will return nullptr.
  void UnsetLevelImage(GLenum target, GLint level);

#if BUILDFLAG(IS_ANDROID)
  // Overrides |service_id_| with a texture bound to
  // the stream texture. See SetStreamTextureServiceId() for the details of
  // how |service_id| is used.
  void BindToServiceId(GLuint service_id);
#endif

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
  // Marks the image for the given level as bound.
  void MarkLevelImageBound(GLenum target, GLint level);
#endif

  bool CompatibleWithSamplerUniformType(
      GLenum type,
      const SamplerState& sampler_state) const;

  // Get the image associated with a particular level. Returns NULL if level
  // does not exist.
  gl::GLImage* GetLevelImage(GLint target, GLint level) const;

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
  // Returns true iff (a) there is an image associated with the particular
  // level, and (b) the image is unbound.
  bool HasUnboundLevelImage(GLint target, GLint level) const;
#endif

  bool HasImages() const {
    return has_images_;
  }

  // Returns true of the given dimensions are inside the dimensions of the
  // level.
  bool ValidForTexture(
      GLint target,
      GLint level,
      GLint xoffset,
      GLint yoffset,
      GLint zoffset,
      GLsizei width,
      GLsizei height,
      GLsizei depth) const;

  bool IsValid() const {
    return !!target();
  }

  bool IsAttachedToFramebuffer() const {
    return framebuffer_attachment_count_ != 0;
  }

  void AttachToFramebuffer() {
    ++framebuffer_attachment_count_;
  }

  void DetachFromFramebuffer() {
    DCHECK_GT(framebuffer_attachment_count_, 0);
    --framebuffer_attachment_count_;
  }

  // |immutable| indicates that the GPU clients cannot modify the format or
  // dimensions of the texture object. This is an artificial restriction imposed
  // by the GPU service on its clients. |immutable_storage| indicates that the
  // storage for the texture is allocated using glTexStorage* functions and it
  // is equivalent to the definition of immutability as defined in OpenGL
  // specifications.
  void SetImmutable(bool immutable, bool immutable_storage);

  bool IsImmutable() const {
    return immutable_;
  }

  bool HasImmutableStorage() const { return immutable_storage_; }

  // Return 0 if it's not immutable.
  GLint GetImmutableLevels() const;

  // Get the cleared rectangle for a particular level. Returns an empty
  // rectangle if level does not exist.
  gfx::Rect GetLevelClearedRect(GLenum target, GLint level) const;

  // Marks a |rect| of a particular level as cleared.
  void SetLevelClearedRect(GLenum target,
                           GLint level,
                           const gfx::Rect& cleared_rect);

  // Whether a particular level/face is cleared.
  bool IsLevelCleared(GLenum target, GLint level) const;
  // Whether a particular level/face is partially cleared.
  bool IsLevelPartiallyCleared(GLenum target, GLint level) const;

  // Whether the texture has been defined
  bool IsDefined() const {
    return estimated_size() > 0;
  }

  // Initialize TEXTURE_MAX_ANISOTROPY to 1 if we haven't done so yet.
  void InitTextureMaxAnisotropyIfNeeded(GLenum target);

  void DumpLevelMemory(base::trace_event::ProcessMemoryDump* pmd,
                       uint64_t client_tracing_id,
                       const std::string& dump_name) const;

  void ApplyFormatWorkarounds(const FeatureInfo* feature_info);

  // In GLES2 "texture complete" means it has all required mips for filtering
  // down to a 1x1 pixel texture, they are in the correct order, they are all
  // the same format.
  bool texture_complete() const {
    DCHECK(!completeness_dirty_);
    return texture_complete_;
  }

  static bool ColorRenderable(const FeatureInfo* feature_info,
                              GLenum internal_format,
                              bool immutable);

  // Marks a particular level as cleared or uncleared.
  void SetLevelCleared(GLenum target, GLint level, bool cleared);

  void ApplyClampedBaseLevelAndMaxLevelToDriver();

  MemoryTypeTracker* GetMemTracker();

  // Returns GL_NONE on error.
  GLenum GetInternalFormatOfBaseLevel() const;

  void SetLightweightRef();

  void RemoveLightweightRef(bool have_context);

  // Set the info for a particular level.
  void 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);

  // Returns the LevelInfo for |target| and |level| if it's set, else nullptr.
  const LevelInfo* GetLevelInfo(GLint target, GLint level) const;

  // Sets the Texture's target
  // Parameters:
  //   target: GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP or
  //           GL_TEXTURE_EXTERNAL_OES or GL_TEXTURE_RECTANGLE_ARB
  //           GL_TEXTURE_2D_ARRAY or GL_TEXTURE_3D (for GLES3)
  //   max_levels: The maximum levels this type of target can have.
  void SetTarget(GLenum target, GLint max_levels);

  void SetCompatibilitySwizzle(const CompatibilitySwizzle* swizzle);

  bool NeedsMips() const {
    return sampler_state_.min_filter != GL_NEAREST &&
           sampler_state_.min_filter != GL_LINEAR;
  }

  size_t MaxValidMipLevel() const {
    DCHECK(!face_infos_.empty());
    return face_infos_[0].level_infos.size();
  }

 private:
  friend class MailboxManagerTest;
  friend class TextureManager;
  friend class TextureRef;
  friend class TextureTestHelper;
  FRIEND_TEST_ALL_PREFIXES(TextureMemoryTrackerTest, LightweightRef);

  ~Texture() override;
  void AddTextureRef(TextureRef* ref);
  void RemoveTextureRef(TextureRef* ref, bool have_context);
  void MaybeDeleteThis(bool have_context);

  // Condition on which this texture is renderable. Can be ONLY_IF_NPOT if it
  // depends on context support for non-power-of-two textures (i.e. will be
  // renderable if NPOT support is in the context, otherwise not, e.g. texture
  // with a NPOT level). ALWAYS means it doesn't depend on context features
  // (e.g. complete POT), NEVER means it's not renderable regardless (e.g.
  // incomplete).
  enum CanRenderCondition {
    CAN_RENDER_ALWAYS,
    CAN_RENDER_NEVER,
    CAN_RENDER_NEEDS_VALIDATION,
  };

  struct FaceInfo {
    FaceInfo();
    FaceInfo(const FaceInfo& other);
    ~FaceInfo();

    // This is relative to base_level and max_level of a texture.
    GLsizei num_mip_levels;
    // This contains slots for all levels starting at 0.
    std::vector<LevelInfo> level_infos;
  };

  // Helper for Set*LevelImage.
  void SetLevelImageInternal(GLenum target,
                             GLint level,
                             gl::GLImage* image,
                             ImageState state);

  // Returns NULL if the base level is not defined.
  const LevelInfo* GetBaseLevelInfo() const;

  // Causes us to report |service_id| as our service id, but does not delete
  // it when we are destroyed.  Will rebind any OES_EXTERNAL texture units to
  // our new service id in all contexts.  If |service_id| is zero, then we
  // revert to |owned_service_id_|.
  void SetStreamTextureServiceId(GLuint service_id);

  void MarkLevelAsInternalWorkaround(GLenum target, GLint level);

  // In GLES2 "cube complete" means all 6 faces level 0 are defined, all the
  // same format, all the same dimensions and all width = height.
  bool cube_complete() const {
    DCHECK(!completeness_dirty_);
    return cube_complete_;
  }

  // Whether or not this texture is a non-power-of-two texture.
  bool npot() const {
    return npot_;
  }

  // Updates the cleared flag for this texture by inspecting all the mips.
  void UpdateCleared();

  // Clears any renderable uncleared levels.
  // Returns false if a GL error was generated.
  bool ClearRenderableLevels(DecoderContext* decoder);

  // Clears the level.
  // Returns false if a GL error was generated.
  bool ClearLevel(DecoderContext* decoder, GLenum target, GLint level);

  // Sets a texture parameter.
  // TODO(gman): Expand to SetParameteriv,fv
  // Returns GL_NO_ERROR on success. Otherwise the error to generate.
  GLenum SetParameteri(
      const FeatureInfo* feature_info, GLenum pname, GLint param);
  GLenum SetParameterf(
      const FeatureInfo* feature_info, GLenum pname, GLfloat param);

  // Makes each of the mip levels as though they were generated.
  void MarkMipmapsGenerated();

  // True if this texture meets all the GLES2 criteria for rendering.
  // See section 3.8.2 of the GLES2 spec.
  bool CanRender(const FeatureInfo* feature_info) const;
  bool CanRenderWithSampler(const FeatureInfo* feature_info,
                            const SamplerState& sampler_state) const;

  // Returns true if mipmaps can be generated by GL.
  bool CanGenerateMipmaps(const FeatureInfo* feature_info) const;

  // Returns true if any of the texture dimensions are not a power of two.
  static bool TextureIsNPOT(GLsizei width, GLsizei height, GLsizei depth);

  // Returns true if texture face is complete relative to the first face.
  static bool 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);

  // Returns true if texture mip level is complete relative to base level.
  // Note that level_diff = level - base_level.
  static bool 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);

  static bool TextureFilterable(const FeatureInfo* feature_info,
                                GLenum internal_format,
                                GLenum type,
                                bool immutable);

  // Update info about this texture.
  void Update();

  // Appends a signature for the given level.
  void AddToSignature(
      const FeatureInfo* feature_info,
      GLenum target, GLint level, std::string* signature) const;

  // Updates the unsafe textures count in all the managers referencing this
  // texture.
  void UpdateSafeToRenderFrom(bool cleared);

  // Updates the uncleared mip count in all the managers referencing this
  // texture.
  void UpdateMipCleared(LevelInfo* info,
                        GLsizei width,
                        GLsizei height,
                        const gfx::Rect& cleared_rect);

  // Computes the CanRenderCondition flag.
  CanRenderCondition GetCanRenderCondition() const;

  // Updates the unrenderable texture count in all the managers referencing this
  // texture.
  void UpdateCanRenderCondition();

  // Updates the images count in all the managers referencing this
  // texture.
  void UpdateHasImages();

  // Increment the framebuffer state change count in all the managers
  // referencing this texture.
  void IncAllFramebufferStateChangeCount();

  void UpdateBaseLevel(GLint base_level, const FeatureInfo* feature_info);
  void UpdateMaxLevel(GLint max_level);
  void UpdateFaceNumMipLevels(size_t face_index,
                              GLint width,
                              GLint height,
                              GLint depth);
  void UpdateFaceNumMipLevels(size_t face_index);
  void UpdateNumMipLevels();

  // Increment the generation counter for all managers that have a reference to
  // this texture.
  void IncrementManagerServiceIdGeneration();

  // Return the service id of the texture that we will delete when we are
  // destroyed.
  GLuint owned_service_id() const { return owned_service_id_; }

  GLenum GetCompatibilitySwizzleForChannel(GLenum channel);

  // Info about each face and level of texture.
  std::vector<FaceInfo> face_infos_;

  // The texture refs that point to this Texture.
  typedef base::flat_set<TextureRef*> RefSet;
  RefSet refs_;
  bool has_lightweight_ref_ = false;

  // The single TextureRef that accounts for memory for this texture. Must be
  // one of refs_.
  raw_ptr<TextureRef> memory_tracking_ref_ = nullptr;

  // The id of the texture that we are responsible for deleting.  Normally, this
  // is the same as |service_id_|, unless a StreamTexture Image with its own
  // service id is bound. In that case the StreamTexture service id is
  // stored in |service_id_| and overrides the owned service id for all purposes
  // except deleting the texture name.
  GLuint owned_service_id_;

  // Whether all renderable mips of this texture have been cleared.
  bool cleared_ = true;

  int num_uncleared_mips_ = 0;
  int num_npot_faces_ = 0;

  // Texture parameters.
  SamplerState sampler_state_;
  GLenum usage_ = GL_NONE;
  GLint base_level_ = 0;
  GLint max_level_ = 1000;
  GLenum swizzle_r_ = GL_RED;
  GLenum swizzle_g_ = GL_GREEN;
  GLenum swizzle_b_ = GL_BLUE;
  GLenum swizzle_a_ = GL_ALPHA;

  GLint unclamped_base_level_ = 0;
  GLint unclamped_max_level_ = 1000;

  // The maximum level that has been set.
  GLint max_level_set_ = -1;

  // Whether or not this texture is "texture complete"
  bool texture_complete_ = false;

  // Whether or not this texture is "cube complete"
  bool cube_complete_ = false;

  // Whether mip levels, base_level, or max_level have changed and
  // texture_completeness_ and cube_completeness_ should be reverified.
  bool completeness_dirty_ = false;

  // Whether or not this texture is non-power-of-two
  bool npot_ = false;

  // Whether this texture has ever been bound.
  bool has_been_bound_ = false;

  // The number of framebuffers this texture is attached to.
  int framebuffer_attachment_count_ = 0;

  // Whether the texture is immutable and no further changes to the format
  // or dimensions of the texture object can be made.
  bool immutable_ = false;

  // Indicates that the storage for the texture is allocated using glTexStorage*
  // functions.
  bool immutable_storage_ = false;

  // Whether or not this texture has images.
  bool has_images_ = false;

  // Size in bytes this texture is assumed to take in memory.
  uint32_t estimated_size_ = 0;

  // Cache of the computed CanRenderCondition flag.
  CanRenderCondition can_render_condition_ = CAN_RENDER_ALWAYS;

  // Whether we have initialized TEXTURE_MAX_ANISOTROPY to 1.
  bool texture_max_anisotropy_initialized_ = false;

  raw_ptr<const CompatibilitySwizzle> compatibility_swizzle_ = nullptr;
};

// This class represents a texture in a client context group. It's mostly 1:1
// with a client id, though it can outlive the client id if it's still bound to
// a FBO or another context when destroyed.
// Multiple TextureRef can point to the same texture with cross-context sharing.
class GPU_GLES2_EXPORT TextureRef : public base::RefCounted<TextureRef> {
 public:
  TextureRef(TextureManager* manager, GLuint client_id, Texture* texture);

  TextureRef(const TextureRef&) = delete;
  TextureRef& operator=(const TextureRef&) = delete;

  static scoped_refptr<TextureRef> Create(TextureManager* manager,
                                          GLuint client_id,
                                          GLuint service_id);

  void AddObserver() { num_observers_++; }
  void RemoveObserver() { num_observers_--; }

  // TODO(ericrk): Remove this once the Texture itself is generated from and
  // owns the SharedImageRepresentation.
  void SetSharedImageRepresentation(
      std::unique_ptr<GLTextureImageRepresentation> shared_image);
  const Texture* texture() const { return texture_; }
  Texture* texture() { return texture_; }
  GLuint client_id() const { return client_id_; }
  GLuint service_id() const { return texture_->service_id(); }
  GLint num_observers() const { return num_observers_; }
  GLTextureImageRepresentation* shared_image() const {
    return shared_image_.get();
  }
  const std::unique_ptr<GLTextureImageRepresentation::ScopedAccess>&
  shared_image_scoped_access() const {
    return shared_image_scoped_access_;
  }

  bool BeginAccessSharedImage(GLenum mode);
  void EndAccessSharedImage();

  // When the TextureRef is destroyed, it will assume that the context has been
  // lost, regardless of the state of the TextureManager.
  void ForceContextLost();

 private:
  friend class base::RefCounted<TextureRef>;
  friend class Texture;
  friend class TextureManager;

  ~TextureRef();
  const TextureManager* manager() const { return manager_; }
  TextureManager* manager() { return manager_; }
  void reset_client_id() { client_id_ = 0; }

  raw_ptr<TextureManager> manager_;
  raw_ptr<Texture, DanglingUntriaged> texture_;
  GLuint client_id_;
  GLint num_observers_;
  bool force_context_lost_;

  std::unique_ptr<GLTextureImageRepresentation> shared_image_;
  std::unique_ptr<GLTextureImageRepresentation::ScopedAccess>
      shared_image_scoped_access_;
};

// Holds data that is per gles2_cmd_decoder, but is related to to the
// TextureManager.
struct DecoderTextureState {
  // total_texture_upload_time automatically initialized to 0 in default
  // constructor.
  explicit DecoderTextureState(const GpuDriverBugWorkarounds& workarounds);

  // This indicates all the following texSubImage*D calls that are part of the
  // failed texImage*D call should be ignored. The client calls have a lock
  // around them, so it will affect only a single texImage*D + texSubImage*D
  // group.
  bool tex_image_failed;

  bool force_cube_map_positive_x_allocation;
  bool force_cube_complete;
  bool force_int_or_srgb_cube_texture_complete;
  bool unpack_alignment_workaround_with_unpack_buffer;
  bool unpack_overlapping_rows_separately_unpack_buffer;
  bool unpack_image_height_workaround_with_unpack_buffer;
};

// This class keeps track of the textures and their sizes so we can do NPOT and
// texture complete checking.
//
// NOTE: To support shared resources an instance of this class will need to be
// shared by multiple DecoderContexts.
class GPU_GLES2_EXPORT TextureManager
    : public base::trace_event::MemoryDumpProvider {
 public:
  class GPU_GLES2_EXPORT DestructionObserver {
   public:
    DestructionObserver();

    DestructionObserver(const DestructionObserver&) = delete;
    DestructionObserver& operator=(const DestructionObserver&) = delete;

    virtual ~DestructionObserver();

    // Called in ~TextureManager.
    virtual void OnTextureManagerDestroying(TextureManager* manager) = 0;

    // Called via ~TextureRef.
    virtual void OnTextureRefDestroying(TextureRef* texture) = 0;
  };

  enum DefaultAndBlackTextures {
    kTexture2D,
    kTexture3D,
    kTexture2DArray,
    kCubeMap,
    kExternalOES,
    kRectangleARB,
    kNumDefaultTextures
  };

  TextureManager(MemoryTracker* memory_tracker,
                 FeatureInfo* feature_info,
                 GLsizei max_texture_size,
                 GLsizei max_cube_map_texture_size,
                 GLsizei max_rectangle_texture_size,
                 GLsizei max_3d_texture_size,
                 GLsizei max_array_texture_layers,
                 bool use_default_textures,
                 gl::ProgressReporter* progress_reporter,
                 ServiceDiscardableManager* discardable_manager);

  TextureManager(const TextureManager&) = delete;
  TextureManager& operator=(const TextureManager&) = delete;

  ~TextureManager() override;

  void AddFramebufferManager(FramebufferManager* framebuffer_manager);
  void RemoveFramebufferManager(FramebufferManager* framebuffer_manager);

  // Init the texture manager.
  void Initialize();

  void MarkContextLost();

  // Must call before destruction.
  void Destroy();

  // Returns the maximum number of levels.
  GLint MaxLevelsForTarget(GLenum target) const {
    switch (target) {
      case GL_TEXTURE_2D:
      case GL_TEXTURE_2D_ARRAY:
        return max_levels_;
      case GL_TEXTURE_RECTANGLE_ARB:
      case GL_TEXTURE_EXTERNAL_OES:
        return 1;
      case GL_TEXTURE_3D:
        return max_3d_levels_;
      default:
        return max_cube_map_levels_;
    }
  }

  // Returns the maximum size.
  GLsizei MaxSizeForTarget(GLenum target) const {
    switch (target) {
      case GL_TEXTURE_2D:
      case GL_TEXTURE_EXTERNAL_OES:
      case GL_TEXTURE_2D_ARRAY:
        return max_texture_size_;
      case GL_TEXTURE_RECTANGLE:
        return max_rectangle_texture_size_;
      case GL_TEXTURE_3D:
        return max_3d_texture_size_;
      default:
        return max_cube_map_texture_size_;
    }
  }

  GLsizei max_array_texture_layers() const {
    return max_array_texture_layers_;
  }

  // Returns the maxium number of levels a texture of the given size can have.
  static GLsizei ComputeMipMapCount(GLenum target,
                                    GLsizei width,
                                    GLsizei height,
                                    GLsizei depth);

  static GLenum ExtractFormatFromStorageFormat(GLenum internalformat);
  static GLenum ExtractTypeFromStorageFormat(GLenum internalformat);

  // Checks if a dimensions are valid for a given target.
  bool ValidForTarget(
      GLenum target, GLint level,
      GLsizei width, GLsizei height, GLsizei depth);
  bool ValidForTextureTarget(const Texture* texture,
                             GLint level,
                             GLsizei width,
                             GLsizei height,
                             GLsizei depth);

  // True if this texture meets all the GLES2 criteria for rendering.
  // See section 3.8.2 of the GLES2 spec.
  bool CanRender(const TextureRef* ref) const {
    return ref->texture()->CanRender(feature_info_.get());
  }

  bool CanRenderWithSampler(
      const TextureRef* ref, const SamplerState& sampler_state) const {
    return ref->texture()->CanRenderWithSampler(
        feature_info_.get(), sampler_state);
  }

  // Returns true if mipmaps can be generated by GL.
  bool CanGenerateMipmaps(const TextureRef* ref) const {
    return ref->texture()->CanGenerateMipmaps(feature_info_.get());
  }

  // Sets the Texture's target
  // Parameters:
  //   target: GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP
  //           GL_TEXTURE_2D_ARRAY or GL_TEXTURE_3D (for GLES3)
  //   max_levels: The maximum levels this type of target can have.
  void SetTarget(
      TextureRef* ref,
      GLenum target);

  // Set the info for a particular level in a TexureInfo.
  void 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);

  // Maps an existing texture into the texture manager, at a given client ID.
  TextureRef* Consume(GLuint client_id, Texture* texture);

  // Maps an existing SharedImage into the texture manager, at a given client
  // ID.
  TextureRef* ConsumeSharedImage(
      GLuint client_id,
      std::unique_ptr<GLTextureImageRepresentation> shared_image);

  // Sets |rect| of mip as cleared.
  void SetLevelClearedRect(TextureRef* ref,
                           GLenum target,
                           GLint level,
                           const gfx::Rect& cleared_rect);

  // Sets a mip as cleared.
  void SetLevelCleared(TextureRef* ref, GLenum target,
                       GLint level, bool cleared);

  // Sets a texture parameter of a Texture
  // Returns GL_NO_ERROR on success. Otherwise the error to generate.
  // TODO(gman): Expand to SetParameteriv,fv
  void SetParameteri(
      const char* function_name, ErrorState* error_state,
      TextureRef* ref, GLenum pname, GLint param);
  void SetParameterf(
      const char* function_name, ErrorState* error_state,
      TextureRef* ref, GLenum pname, GLfloat param);

  // Makes each of the mip levels as though they were generated.
  void MarkMipmapsGenerated(TextureRef* ref);

  // Clears any uncleared renderable levels.
  bool ClearRenderableLevels(DecoderContext* decoder, TextureRef* ref);

  // Clear a specific level.
  static bool ClearTextureLevel(DecoderContext* decoder,
                                TextureRef* ref,
                                GLenum target,
                                GLint level);

  static bool ClearTextureLevel(DecoderContext* decoder,
                                Texture* texture,
                                GLenum target,
                                GLint level);

  // Creates a new texture info.
  TextureRef* CreateTexture(GLuint client_id, GLuint service_id);

  // Gets the texture info for the given texture.
  TextureRef* GetTexture(GLuint client_id) const;

  // Takes the TextureRef for the given texture out of the texture manager.
  scoped_refptr<TextureRef> TakeTexture(GLuint client_id);

  // Returns a TextureRef to the texture manager.
  void ReturnTexture(scoped_refptr<TextureRef> texture_ref);

  // Removes a texture info.
  void RemoveTexture(GLuint client_id);

  // Gets a Texture for a given service id (note: it assumes the texture object
  // is still mapped in this TextureManager).
  Texture* GetTextureForServiceId(GLuint service_id) const;

  TextureRef* GetDefaultTextureInfo(GLenum target) {
    switch (target) {
      case GL_TEXTURE_2D:
        return default_textures_[kTexture2D].get();
      case GL_TEXTURE_3D:
        return default_textures_[kTexture3D].get();
      case GL_TEXTURE_2D_ARRAY:
        return default_textures_[kTexture2DArray].get();
      case GL_TEXTURE_CUBE_MAP:
        return default_textures_[kCubeMap].get();
      case GL_TEXTURE_EXTERNAL_OES:
        return default_textures_[kExternalOES].get();
      case GL_TEXTURE_RECTANGLE_ARB:
        return default_textures_[kRectangleARB].get();
      default:
        NOTREACHED();
        return nullptr;
    }
  }

  bool HaveUnsafeTextures() const {
    return num_unsafe_textures_ > 0;
  }

  bool HaveUnclearedMips() const {
    return num_uncleared_mips_ > 0;
  }

  bool HaveImages() const {
    return num_images_ > 0;
  }

  GLuint black_texture_id(GLenum target) const {
    switch (target) {
      case GL_SAMPLER_2D:
        return black_texture_ids_[kTexture2D];
      case GL_SAMPLER_3D:
        return black_texture_ids_[kTexture3D];
      case GL_SAMPLER_2D_ARRAY:
        return black_texture_ids_[kTexture2DArray];
      case GL_SAMPLER_CUBE:
        return black_texture_ids_[kCubeMap];
      case GL_SAMPLER_EXTERNAL_OES:
        return black_texture_ids_[kExternalOES];
      case GL_SAMPLER_2D_RECT_ARB:
        return black_texture_ids_[kRectangleARB];
      default:
        // The above covers ES 2, but ES 3 has many more sampler types. Rather
        // than create a texture for all of them, just use the 0 texture, which
        // should always be incomplete, and rely on the driver to return black
        // when sampling it. Hopefully ES 3 drivers are better about actually
        // returning black when sampling an incomplete texture.
        return 0;
    }
  }

  size_t mem_represented() const {
    return memory_type_tracker_->GetMemRepresented();
  }

  void SetBoundLevelImage(TextureRef* ref,
                          GLenum target,
                          GLint level,
                          gl::GLImage* image);

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
  void SetUnboundLevelImage(TextureRef* ref,
                            GLenum target,
                            GLint level,
                            gl::GLImage* image);
#endif

  void UnsetLevelImage(TextureRef* ref, GLenum target, GLint level);

  size_t GetSignatureSize() const;

  void AddToSignature(
      TextureRef* ref,
      GLenum target,
      GLint level,
      std::string* signature) const;

  void AddObserver(DestructionObserver* observer) {
    destruction_observers_.push_back(observer);
  }

  void RemoveObserver(DestructionObserver* observer) {
    for (unsigned int i = 0; i < destruction_observers_.size(); i++) {
      if (destruction_observers_[i] == observer) {
        std::swap(destruction_observers_[i], destruction_observers_.back());
        destruction_observers_.pop_back();
        return;
      }
    }
    NOTREACHED();
  }

  struct DoTexImageArguments {
    enum class CommandType {
      kTexImage2D,
      kTexImage3D,
    };

    GLenum target;
    GLint level;
    GLenum internal_format;
    GLsizei width;
    GLsizei height;
    GLsizei depth;
    GLint border;
    GLenum format;
    GLenum type;
    // `pixels` is not a raw_ptr<...> to avoid adding an out-of-line destructor.
    RAW_PTR_EXCLUSION const void* pixels;
    uint32_t pixels_size;
    uint32_t padding;
    CommandType command_type;
  };

  bool ValidateTexImage(ContextState* state,
                        ErrorState* error_state,
                        const char* function_name,
                        const DoTexImageArguments& args,
                        // Pointer to TextureRef filled in if validation
                        // successful. Presumes the pointer is valid.
                        TextureRef** texture_ref);

  void ValidateAndDoTexImage(DecoderTextureState* texture_state,
                             ContextState* state,
                             ErrorState* error_state,
                             DecoderFramebufferState* framebuffer_state,
                             const char* function_name,
                             const DoTexImageArguments& args);

  struct DoTexSubImageArguments {
    enum class CommandType {
      kTexSubImage2D,
      kTexSubImage3D,
    };

    GLenum target;
    GLint level;
    GLint xoffset;
    GLint yoffset;
    GLint zoffset;
    GLsizei width;
    GLsizei height;
    GLsizei depth;
    GLenum format;
    GLenum type;
    // `pixels` is not a raw_ptr<...> to avoid adding an out-of-line destructor.
    RAW_PTR_EXCLUSION const void* pixels;
    uint32_t pixels_size;
    uint32_t padding;
    CommandType command_type;
  };

  bool ValidateTexSubImage(ContextState* state,
                           ErrorState* error_state,
                           const char* function_name,
                           const DoTexSubImageArguments& args,
                           // Pointer to TextureRef filled in if validation
                           // successful. Presumes the pointer is valid.
                           TextureRef** texture_ref);

  void ValidateAndDoTexSubImage(DecoderContext* decoder,
                                DecoderTextureState* texture_state,
                                ContextState* state,
                                ErrorState* error_state,
                                DecoderFramebufferState* framebuffer_state,
                                const char* function_name,
                                const DoTexSubImageArguments& args);

  // TODO(kloveless): Make GetTexture* private once this is no longer called
  // from gles2_cmd_decoder.
  TextureRef* GetTextureInfoForTarget(ContextState* state, GLenum target);
  TextureRef* GetTextureInfoForTargetUnlessDefault(
      ContextState* state, GLenum target);

  // This function is used to validate TexImage2D and TexSubImage2D and their
  // variants. But internal_format only checked for callers of TexImage2D and
  // its variants (tex_image_call is true).
  bool ValidateTextureParameters(
    ErrorState* error_state, const char* function_name, bool tex_image_call,
    GLenum format, GLenum type, GLint internal_format, GLint level);

  // base::trace_event::MemoryDumpProvider implementation.
  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                    base::trace_event::ProcessMemoryDump* pmd) override;

  // Returns the union of |rect1| and |rect2| if one of the rectangles is empty,
  // contains the other rectangle or shares an edge with the other rectangle.
  // Part of the public interface because texture pixel data rectangle
  // operations are also implemented in decoder at the moment.
  static bool CombineAdjacentRects(const gfx::Rect& rect1,
                                   const gfx::Rect& rect2,
                                   gfx::Rect* result);

  // Get / set the current generation number of this manager.  This generation
  // number changes whenever the service_id of one or more Textures change.
  uint32_t GetServiceIdGeneration() const;
  void IncrementServiceIdGeneration();

  static const Texture::CompatibilitySwizzle* GetCompatibilitySwizzle(
      const gles2::FeatureInfo* feature_info,
      GLenum format);
  static GLenum AdjustTexInternalFormat(const gles2::FeatureInfo* feature_info,
                                        GLenum format,
                                        GLenum type);
  static GLenum AdjustTexFormat(const gles2::FeatureInfo* feature_info,
                                GLenum format);

  static GLenum AdjustTexStorageFormat(const gles2::FeatureInfo* feature_info,
                                       GLenum format);

  void WorkaroundCopyTexImageCubeMap(DecoderTextureState* texture_state,
                                     ContextState* state,
                                     ErrorState* error_state,
                                     DecoderFramebufferState* framebuffer_state,
                                     TextureRef* texture_ref,
                                     const char* function_name,
                                     const DoTexImageArguments& args) {
    DoCubeMapWorkaround(texture_state, state, error_state, framebuffer_state,
                        texture_ref, function_name, args);
  }

 private:
  friend class Texture;
  friend class TextureRef;

  // Helper for Initialize().
  scoped_refptr<TextureRef> CreateDefaultAndBlackTextures(
      GLenum target,
      GLuint* black_texture);

  void DoTexImage(DecoderTextureState* texture_state,
                  ContextState* state,
                  ErrorState* error_state,
                  DecoderFramebufferState* framebuffer_state,
                  const char* function_name,
                  TextureRef* texture_ref,
                  const DoTexImageArguments& args);

  // Reserve memory for the texture and set its attributes so it can be filled
  // with TexSubImage. The image contents are undefined after this function,
  // so make sure it's subsequently filled in its entirety.
  void ReserveTexImageToBeFilled(DecoderTextureState* texture_state,
                                 ContextState* state,
                                 ErrorState* error_state,
                                 DecoderFramebufferState* framebuffer_state,
                                 const char* function_name,
                                 TextureRef* texture_ref,
                                 const DoTexImageArguments& args);

  void DoTexSubImageWithAlignmentWorkaround(
      DecoderTextureState* texture_state,
      ContextState* state,
      const DoTexSubImageArguments& args);

  void DoTexSubImageRowByRowWorkaround(DecoderTextureState* texture_state,
                                       ContextState* state,
                                       const DoTexSubImageArguments& args,
                                       const PixelStoreParams& unpack_params);

  void DoTexSubImageLayerByLayerWorkaround(
      DecoderTextureState* texture_state,
      ContextState* state,
      const DoTexSubImageArguments& args,
      const PixelStoreParams& unpack_params);

  void DoCubeMapWorkaround(DecoderTextureState* texture_state,
                           ContextState* state,
                           ErrorState* error_state,
                           DecoderFramebufferState* framebuffer_state,
                           TextureRef* texture_ref,
                           const char* function_name,
                           const DoTexImageArguments& args);

  void StartTracking(TextureRef* texture);
  void StopTracking(TextureRef* texture);

  void UpdateSafeToRenderFrom(int delta);
  void UpdateUnclearedMips(int delta);
  void UpdateCanRenderCondition(Texture::CanRenderCondition old_condition,
                                Texture::CanRenderCondition new_condition);
  void UpdateNumImages(int delta);
  void IncFramebufferStateChangeCount();

  // Helper function called by OnMemoryDump.
  void DumpTextureRef(base::trace_event::ProcessMemoryDump* pmd,
                      TextureRef* ref);

  MemoryTypeTracker* GetMemTracker();
  std::unique_ptr<MemoryTypeTracker> memory_type_tracker_;
  raw_ptr<MemoryTracker> memory_tracker_;

  scoped_refptr<FeatureInfo> feature_info_;

  std::vector<FramebufferManager*> framebuffer_managers_;

  // Info for each texture in the system.
  typedef std::unordered_map<GLuint, scoped_refptr<TextureRef>> TextureMap;
  TextureMap textures_;

  GLsizei max_texture_size_;
  GLsizei max_cube_map_texture_size_;
  GLsizei max_rectangle_texture_size_;
  GLsizei max_3d_texture_size_;
  GLsizei max_array_texture_layers_;
  GLint max_levels_;
  GLint max_cube_map_levels_;
  GLint max_3d_levels_;

  const bool use_default_textures_;

  int num_unsafe_textures_;
  int num_uncleared_mips_;
  int num_images_;

  // Counts the number of Textures allocated with 'this' as its manager.
  // Allows to check no Texture will outlive this.
  unsigned int texture_count_;

  bool have_context_;

  // Black (0,0,0,1) textures for when non-renderable textures are used.
  // NOTE: There is no corresponding Texture for these textures.
  // TextureInfos are only for textures the client side can access.
  GLuint black_texture_ids_[kNumDefaultTextures];

  // The default textures for each target (texture name = 0)
  scoped_refptr<TextureRef> default_textures_[kNumDefaultTextures];

  std::vector<DestructionObserver*> destruction_observers_;

  uint32_t current_service_id_generation_;

  // Used to notify the watchdog thread of progress during destruction,
  // preventing time-outs when destruction takes a long time. May be null when
  // using in-process command buffer.
  raw_ptr<gl::ProgressReporter> progress_reporter_;

  raw_ptr<ServiceDiscardableManager> discardable_manager_;
};

}  // namespace gles2
}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_TEXTURE_MANAGER_H_
