//
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63.

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/Texture.h"

#include "common/mathutil.h"
#include "common/utilities.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
#include "libANGLE/Image.h"
#include "libANGLE/State.h"
#include "libANGLE/Surface.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/TextureImpl.h"

namespace gl
{

namespace
{
constexpr angle::SubjectIndex kBufferSubjectIndex = 2;
static_assert(kBufferSubjectIndex != rx::kTextureImageImplObserverMessageIndex, "Index collision");
static_assert(kBufferSubjectIndex != rx::kTextureImageSiblingMessageIndex, "Index collision");

bool IsPointSampled(const SamplerState &samplerState)
{
    return (samplerState.getMagFilter() == GL_NEAREST &&
            (samplerState.getMinFilter() == GL_NEAREST ||
             samplerState.getMinFilter() == GL_NEAREST_MIPMAP_NEAREST));
}

size_t GetImageDescIndex(TextureTarget target, size_t level)
{
    return IsCubeMapFaceTarget(target) ? (level * 6 + CubeMapTextureTargetToFaceIndex(target))
                                       : level;
}

InitState DetermineInitState(const Context *context, Buffer *unpackBuffer, const uint8_t *pixels)
{
    // Can happen in tests.
    if (!context || !context->isRobustResourceInitEnabled())
    {
        return InitState::Initialized;
    }

    return (!pixels && !unpackBuffer) ? InitState::MayNeedInit : InitState::Initialized;
}
}  // namespace

GLenum ConvertToNearestFilterMode(GLenum filterMode)
{
    switch (filterMode)
    {
        case GL_LINEAR:
            return GL_NEAREST;
        case GL_LINEAR_MIPMAP_NEAREST:
            return GL_NEAREST_MIPMAP_NEAREST;
        case GL_LINEAR_MIPMAP_LINEAR:
            return GL_NEAREST_MIPMAP_LINEAR;
        default:
            return filterMode;
    }
}

GLenum ConvertToNearestMipFilterMode(GLenum filterMode)
{
    switch (filterMode)
    {
        case GL_LINEAR_MIPMAP_LINEAR:
            return GL_LINEAR_MIPMAP_NEAREST;
        case GL_NEAREST_MIPMAP_LINEAR:
            return GL_NEAREST_MIPMAP_NEAREST;
        default:
            return filterMode;
    }
}

bool IsMipmapSupported(const TextureType &type)
{
    switch (type)
    {
        case TextureType::_2DMultisample:
        case TextureType::_2DMultisampleArray:
        case TextureType::Buffer:
            return false;
        default:
            return true;
    }
}

SwizzleState::SwizzleState()
    : swizzleRed(GL_RED), swizzleGreen(GL_GREEN), swizzleBlue(GL_BLUE), swizzleAlpha(GL_ALPHA)
{}

SwizzleState::SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha)
    : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
{}

bool SwizzleState::swizzleRequired() const
{
    return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || swizzleBlue != GL_BLUE ||
           swizzleAlpha != GL_ALPHA;
}

bool SwizzleState::operator==(const SwizzleState &other) const
{
    return swizzleRed == other.swizzleRed && swizzleGreen == other.swizzleGreen &&
           swizzleBlue == other.swizzleBlue && swizzleAlpha == other.swizzleAlpha;
}

bool SwizzleState::operator!=(const SwizzleState &other) const
{
    return !(*this == other);
}

TextureState::TextureState(TextureType type)
    : mType(type),
      mSamplerState(SamplerState::CreateDefaultForTarget(type)),
      mSrgbOverride(SrgbOverride::Default),
      mBaseLevel(0),
      mMaxLevel(kInitialMaxLevel),
      mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
      mIsInternalIncompleteTexture(false),
      mIsExternalMemoryTexture(false),
      mHasBeenBoundAsImage(false),
      mHasBeenBoundAsAttachment(false),
      mHasBeenBoundToMSRTTFramebuffer(false),
      mHasBeenBoundAsSourceOfEglImage(false),
      mImmutableFormat(false),
      mImmutableLevels(0),
      mUsage(GL_NONE),
      mHasProtectedContent(false),
      mRenderabilityValidation(true),
      mTilingMode(gl::TilingMode::Optimal),
      mImageDescs((IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) * (type == TextureType::CubeMap ? 6 : 1)),
      mCropRect(0, 0, 0, 0),
      mGenerateMipmapHint(GL_FALSE),
      mInitState(InitState::Initialized),
      mCachedSamplerFormat(SamplerFormat::InvalidEnum),
      mCachedSamplerCompareMode(GL_NONE),
      mCachedSamplerFormatValid(false),
      mCompressionFixedRate(GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT),
      mAstcDecodePrecision(GL_RGBA16F)
{}

TextureState::~TextureState() {}

bool TextureState::swizzleRequired() const
{
    return mSwizzleState.swizzleRequired();
}

GLuint TextureState::getEffectiveBaseLevel() const
{
    if (mImmutableFormat)
    {
        // GLES 3.0.4 section 3.8.10
        return std::min(mBaseLevel, mImmutableLevels - 1);
    }
    // Some classes use the effective base level to index arrays with level data. By clamping the
    // effective base level to max levels these arrays need just one extra item to store properties
    // that should be returned for all out-of-range base level values, instead of needing special
    // handling for out-of-range base levels.
    return std::min(mBaseLevel, static_cast<GLuint>(IMPLEMENTATION_MAX_TEXTURE_LEVELS));
}

GLuint TextureState::getEffectiveMaxLevel() const
{
    if (mImmutableFormat)
    {
        // GLES 3.0.4 section 3.8.10
        GLuint clampedMaxLevel = std::max(mMaxLevel, getEffectiveBaseLevel());
        clampedMaxLevel        = std::min(clampedMaxLevel, mImmutableLevels - 1);
        return clampedMaxLevel;
    }
    if (IsMipmapSupported(mType) && IsMipmapFiltered(mSamplerState.getMinFilter()))
    {
        return mMaxLevel;
    }
    else
    {
        return std::max(mMaxLevel, mBaseLevel);
    }
}

GLuint TextureState::getMipmapMaxLevel() const
{
    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
    GLuint expectedMipLevels       = 0;
    if (mType == TextureType::_3D)
    {
        const int maxDim = std::max(
            {baseImageDesc.size.width, baseImageDesc.size.height, baseImageDesc.size.depth});
        expectedMipLevels = static_cast<GLuint>(log2(maxDim));
    }
    else
    {
        expectedMipLevels = static_cast<GLuint>(
            log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)));
    }

    return std::min<GLuint>(getEffectiveBaseLevel() + expectedMipLevels, getEffectiveMaxLevel());
}

bool TextureState::setBaseLevel(GLuint baseLevel)
{
    if (mBaseLevel != baseLevel)
    {
        mBaseLevel = baseLevel;
        return true;
    }
    return false;
}

bool TextureState::setASTCDecodePrecision(GLenum astcDecodePrecision)
{
    if (mAstcDecodePrecision != astcDecodePrecision)
    {
        mAstcDecodePrecision = astcDecodePrecision;
        return true;
    }
    return false;
}

GLenum TextureState::getASTCDecodePrecision() const
{
    return mAstcDecodePrecision;
}

bool TextureState::setMaxLevel(GLuint maxLevel)
{
    if (mMaxLevel != maxLevel)
    {
        mMaxLevel = maxLevel;
        return true;
    }

    return false;
}

// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
// According to [OpenGL ES 3.0.5] section 3.8.13 Texture Completeness page 160 any
// per-level checks begin at the base-level.
// For OpenGL ES2 the base level is always zero.
bool TextureState::isCubeComplete() const
{
    ASSERT(mType == TextureType::CubeMap);

    angle::EnumIterator<TextureTarget> face = kCubeMapTextureTargetMin;
    const ImageDesc &baseImageDesc          = getImageDesc(*face, getEffectiveBaseLevel());
    if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
    {
        return false;
    }

    ++face;

    for (; face != kAfterCubeMapTextureTargetMax; ++face)
    {
        const ImageDesc &faceImageDesc = getImageDesc(*face, getEffectiveBaseLevel());
        if (faceImageDesc.size.width != baseImageDesc.size.width ||
            faceImageDesc.size.height != baseImageDesc.size.height ||
            !Format::SameSized(faceImageDesc.format, baseImageDesc.format))
        {
            return false;
        }
    }

    return true;
}

const ImageDesc &TextureState::getBaseLevelDesc() const
{
    ASSERT(mType != TextureType::CubeMap || isCubeComplete());
    return getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
}

const ImageDesc &TextureState::getLevelZeroDesc() const
{
    ASSERT(mType != TextureType::CubeMap || isCubeComplete());
    return getImageDesc(getBaseImageTarget(), 0);
}

void TextureState::setCrop(const Rectangle &rect)
{
    mCropRect = rect;
}

const Rectangle &TextureState::getCrop() const
{
    return mCropRect;
}

void TextureState::setGenerateMipmapHint(GLenum hint)
{
    mGenerateMipmapHint = hint;
}

GLenum TextureState::getGenerateMipmapHint() const
{
    return mGenerateMipmapHint;
}

SamplerFormat TextureState::computeRequiredSamplerFormat(const SamplerState &samplerState) const
{
    const InternalFormat &info =
        *getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel()).format.info;
    if ((info.format == GL_DEPTH_COMPONENT ||
         (info.format == GL_DEPTH_STENCIL && mDepthStencilTextureMode == GL_DEPTH_COMPONENT)) &&
        samplerState.getCompareMode() != GL_NONE)
    {
        return SamplerFormat::Shadow;
    }
    else if (info.format == GL_STENCIL_INDEX ||
             (info.format == GL_DEPTH_STENCIL && mDepthStencilTextureMode == GL_STENCIL_INDEX))
    {
        return SamplerFormat::Unsigned;
    }
    else
    {
        switch (info.componentType)
        {
            case GL_UNSIGNED_NORMALIZED:
            case GL_SIGNED_NORMALIZED:
            case GL_FLOAT:
                return SamplerFormat::Float;
            case GL_INT:
                return SamplerFormat::Signed;
            case GL_UNSIGNED_INT:
                return SamplerFormat::Unsigned;
            default:
                return SamplerFormat::InvalidEnum;
        }
    }
}

bool TextureState::computeSamplerCompleteness(const SamplerState &samplerState,
                                              const State &state) const
{
    // Buffer textures cannot be incomplete. But if they are, the spec says -
    //
    //     If no buffer object is bound to the buffer texture,
    //     the results of the texel access are undefined.
    //
    // Mark as incomplete so we use the default IncompleteTexture instead
    if (mType == TextureType::Buffer)
    {
        return mBuffer.get() != nullptr;
    }

    // Check for all non-format-based completeness rules
    if (!computeSamplerCompletenessForCopyImage(samplerState, state))
    {
        return false;
    }

    // OpenGL ES 3.2, Sections 8.8 and 11.1.3.3
    // Multisample textures do not have mipmaps and filter state is ignored.
    if (IsMultisampled(mType))
    {
        return true;
    }

    // OpenGL ES 3.2, Section 8.17
    // A texture is complete unless either the magnification filter is not NEAREST,
    // or the minification filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST; and any of
    if (IsPointSampled(samplerState))
    {
        return true;
    }

    const InternalFormat *info =
        getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel()).format.info;

    // The effective internal format specified for the texture images
    // is a sized internal color format that is not texture-filterable.
    if (!info->isDepthOrStencil())
    {
        return info->filterSupport(state.getClientVersion(), state.getExtensions());
    }

    // The effective internal format specified for the texture images
    // is a sized internal depth or depth and stencil format (see table 8.11),
    // and the value of TEXTURE_COMPARE_MODE is NONE.
    if (info->depthBits > 0 && samplerState.getCompareMode() == GL_NONE)
    {
        // Note: we restrict this validation to sized types. For the OES_depth_textures
        // extension, due to some underspecification problems, we must allow linear filtering
        // for legacy compatibility with WebGL 1.0.
        // See http://crbug.com/649200
        if (state.getClientVersion() >= ES_3_0 && info->sized)
        {
            return false;
        }
    }

    if (info->stencilBits > 0)
    {
        if (info->depthBits > 0)
        {
            // The internal format of the texture is DEPTH_STENCIL,
            // and the value of DEPTH_STENCIL_TEXTURE_MODE for the
            // texture is STENCIL_INDEX.
            if (mDepthStencilTextureMode == GL_STENCIL_INDEX)
            {
                return false;
            }
        }
        else
        {
            // The internal format is STENCIL_INDEX.
            return false;
        }
    }

    return true;
}

// CopyImageSubData has more lax rules for texture completeness: format-based completeness rules are
// ignored, so a texture can still be considered complete even if it violates format-specific
// conditions
bool TextureState::computeSamplerCompletenessForCopyImage(const SamplerState &samplerState,
                                                          const State &state) const
{
    // Buffer textures cannot be incomplete. But if they are, the spec says -
    //
    //     If no buffer object is bound to the buffer texture,
    //     the results of the texel access are undefined.
    //
    // Mark as incomplete so we use the default IncompleteTexture instead
    if (mType == TextureType::Buffer)
    {
        return mBuffer.get() != nullptr;
    }

    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
    if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
        baseImageDesc.size.depth == 0)
    {
        return false;
    }
    // The cases where the texture is incomplete because base level is out of range should be
    // handled by the above condition.
    ASSERT(mBaseLevel < IMPLEMENTATION_MAX_TEXTURE_LEVELS || mImmutableFormat);

    if (mType == TextureType::CubeMap && baseImageDesc.size.width != baseImageDesc.size.height)
    {
        return false;
    }

    bool npotSupport = state.getExtensions().textureNpotOES || state.getClientVersion() >= ES_3_0;
    if (!npotSupport)
    {
        if ((samplerState.getWrapS() != GL_CLAMP_TO_EDGE &&
             samplerState.getWrapS() != GL_CLAMP_TO_BORDER && !isPow2(baseImageDesc.size.width)) ||
            (samplerState.getWrapT() != GL_CLAMP_TO_EDGE &&
             samplerState.getWrapT() != GL_CLAMP_TO_BORDER && !isPow2(baseImageDesc.size.height)))
        {
            return false;
        }
    }

    if (IsMipmapSupported(mType) && IsMipmapFiltered(samplerState.getMinFilter()))
    {
        if (!npotSupport)
        {
            if (!isPow2(baseImageDesc.size.width) || !isPow2(baseImageDesc.size.height))
            {
                return false;
            }
        }

        if (!computeMipmapCompleteness())
        {
            return false;
        }
    }
    else
    {
        if (mType == TextureType::CubeMap && !isCubeComplete())
        {
            return false;
        }
    }

    // From GL_OES_EGL_image_external_essl3: If state is present in a sampler object bound to a
    // texture unit that would have been rejected by a call to TexParameter* for the texture bound
    // to that unit, the behavior of the implementation is as if the texture were incomplete. For
    // example, if TEXTURE_WRAP_S or TEXTURE_WRAP_T is set to anything but CLAMP_TO_EDGE on the
    // sampler object bound to a texture unit and the texture bound to that unit is an external
    // texture and EXT_EGL_image_external_wrap_modes is not enabled, the texture will be considered
    // incomplete.
    // Sampler object state which does not affect sampling for the type of texture bound
    // to a texture unit, such as TEXTURE_WRAP_R for an external texture, does not affect
    // completeness.
    if (mType == TextureType::External)
    {
        if (!state.getExtensions().EGLImageExternalWrapModesEXT)
        {
            if (samplerState.getWrapS() != GL_CLAMP_TO_EDGE ||
                samplerState.getWrapT() != GL_CLAMP_TO_EDGE)
            {
                return false;
            }
        }

        if (samplerState.getMinFilter() != GL_LINEAR && samplerState.getMinFilter() != GL_NEAREST)
        {
            return false;
        }
    }

    return true;
}

bool TextureState::computeMipmapCompleteness() const
{
    const GLuint maxLevel  = getMipmapMaxLevel();
    const GLuint baseLevel = getEffectiveBaseLevel();
    if (baseLevel > maxLevel)
    {
        return false;
    }

    for (GLuint level = getEffectiveBaseLevel(); level <= maxLevel; level++)
    {
        if (mType == TextureType::CubeMap)
        {
            for (TextureTarget face : AllCubeFaceTextureTargets())
            {
                if (!computeLevelCompleteness(face, level))
                {
                    return false;
                }
            }
        }
        else
        {
            if (!computeLevelCompleteness(NonCubeTextureTypeToTarget(mType), level))
            {
                return false;
            }
        }
    }

    return true;
}

bool TextureState::computeLevelCompleteness(TextureTarget target, size_t level) const
{
    ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);

    if (mImmutableFormat)
    {
        return true;
    }

    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
    if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
        baseImageDesc.size.depth == 0)
    {
        return false;
    }

    const ImageDesc &levelImageDesc = getImageDesc(target, level);
    if (levelImageDesc.size.width == 0 || levelImageDesc.size.height == 0 ||
        levelImageDesc.size.depth == 0)
    {
        return false;
    }

    if (!Format::SameSized(levelImageDesc.format, baseImageDesc.format))
    {
        return false;
    }

    ASSERT(level >= getEffectiveBaseLevel());
    const size_t relativeLevel = level - getEffectiveBaseLevel();
    if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> relativeLevel))
    {
        return false;
    }

    if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> relativeLevel))
    {
        return false;
    }

    if (mType == TextureType::_3D)
    {
        if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> relativeLevel))
        {
            return false;
        }
    }
    else if (IsArrayTextureType(mType))
    {
        if (levelImageDesc.size.depth != baseImageDesc.size.depth)
        {
            return false;
        }
    }

    return true;
}

TextureTarget TextureState::getBaseImageTarget() const
{
    return mType == TextureType::CubeMap ? kCubeMapTextureTargetMin
                                         : NonCubeTextureTypeToTarget(mType);
}

GLuint TextureState::getEnabledLevelCount() const
{
    GLuint levelCount      = 0;
    const GLuint baseLevel = getEffectiveBaseLevel();
    GLuint maxLevel        = getMipmapMaxLevel();

    // In edge case where base level > max level, make sure to get at least one level.
    maxLevel = std::max(baseLevel, maxLevel);

    // Note: for cube textures, we only check the first face.
    TextureTarget target         = TextureTypeToTarget(mType, 0);
    const Format &expectedFormat = mImageDescs[GetImageDescIndex(target, baseLevel)].format;

    // The mip chain will have either one or more sequential levels, or max levels,
    // but not a sparse one.
    Optional<Extents> expectedSize;
    for (size_t enabledLevel = baseLevel; enabledLevel <= maxLevel; ++enabledLevel, ++levelCount)
    {
        size_t descIndex         = GetImageDescIndex(target, enabledLevel);
        const Extents &levelSize = mImageDescs[descIndex].size;
        const Format &levelFormat = mImageDescs[descIndex].format;

        if (levelSize.empty())
        {
            break;
        }
        if (expectedSize.valid())
        {
            Extents newSize = expectedSize.value();
            newSize.width   = std::max(1, newSize.width >> 1);
            newSize.height  = std::max(1, newSize.height >> 1);

            if (!IsArrayTextureType(mType))
            {
                newSize.depth = std::max(1, newSize.depth >> 1);
            }

            if (newSize != levelSize)
            {
                break;
            }
        }
        // If the texture is bound without mipmap filtering, the max level could be incompatible
        // with the base level while respecifying image storage. In this case, we check the sized
        // internal format for the compatibility and enable only the effective level when it has
        // changed compared to the previous image.
        if (!Format::SameSized(expectedFormat, levelFormat))
        {
            break;
        }
        expectedSize = levelSize;
    }

    return levelCount;
}

ImageDesc::ImageDesc()
    : ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized)
{}

ImageDesc::ImageDesc(const Extents &size, const Format &format, const InitState initState)
    : size(size), format(format), samples(0), fixedSampleLocations(GL_TRUE), initState(initState)
{}

ImageDesc::ImageDesc(const Extents &size,
                     const Format &format,
                     const GLsizei samples,
                     const bool fixedSampleLocations,
                     const InitState initState)
    : size(size),
      format(format),
      samples(samples),
      fixedSampleLocations(fixedSampleLocations),
      initState(initState)
{}

GLint ImageDesc::getMemorySize() const
{
    // Assume allocated size is around width * height * depth * samples * pixelBytes
    angle::CheckedNumeric<GLint> levelSize = 1;
    levelSize *= format.info->pixelBytes;
    levelSize *= size.width;
    levelSize *= size.height;
    levelSize *= size.depth;
    levelSize *= std::max(samples, 1);
    return levelSize.ValueOrDefault(std::numeric_limits<GLint>::max());
}

const ImageDesc &TextureState::getImageDesc(TextureTarget target, size_t level) const
{
    size_t descIndex = GetImageDescIndex(target, level);
    ASSERT(descIndex < mImageDescs.size());
    return mImageDescs[descIndex];
}

void TextureState::setImageDesc(TextureTarget target, size_t level, const ImageDesc &desc)
{
    size_t descIndex = GetImageDescIndex(target, level);
    ASSERT(descIndex < mImageDescs.size());
    mImageDescs[descIndex] = desc;
    if (desc.initState == InitState::MayNeedInit)
    {
        mInitState = InitState::MayNeedInit;
    }
    else
    {
        // Scan for any uninitialized images. If there are none, set the init state of the entire
        // texture to initialized. The cost of the scan is only paid after doing image
        // initialization which is already very expensive.
        bool allImagesInitialized = true;

        for (const ImageDesc &initDesc : mImageDescs)
        {
            if (initDesc.initState == InitState::MayNeedInit)
            {
                allImagesInitialized = false;
                break;
            }
        }

        if (allImagesInitialized)
        {
            mInitState = InitState::Initialized;
        }
    }
}

// Note that an ImageIndex that represents an entire level of a cube map corresponds to 6
// ImageDescs, so if the cube map is cube complete, we return the ImageDesc of the first cube
// face, and we don't allow using this function when the cube map is not cube complete.
const ImageDesc &TextureState::getImageDesc(const ImageIndex &imageIndex) const
{
    if (imageIndex.isEntireLevelCubeMap())
    {
        ASSERT(isCubeComplete());
        const GLint levelIndex = imageIndex.getLevelIndex();
        return getImageDesc(kCubeMapTextureTargetMin, levelIndex);
    }

    return getImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex());
}

void TextureState::setImageDescChain(GLuint baseLevel,
                                     GLuint maxLevel,
                                     Extents baseSize,
                                     const Format &format,
                                     InitState initState)
{
    for (GLuint level = baseLevel; level <= maxLevel; level++)
    {
        int relativeLevel = (level - baseLevel);
        Extents levelSize(std::max<int>(baseSize.width >> relativeLevel, 1),
                          std::max<int>(baseSize.height >> relativeLevel, 1),
                          (IsArrayTextureType(mType))
                              ? baseSize.depth
                              : std::max<int>(baseSize.depth >> relativeLevel, 1));
        ImageDesc levelInfo(levelSize, format, initState);

        if (mType == TextureType::CubeMap)
        {
            for (TextureTarget face : AllCubeFaceTextureTargets())
            {
                setImageDesc(face, level, levelInfo);
            }
        }
        else
        {
            setImageDesc(NonCubeTextureTypeToTarget(mType), level, levelInfo);
        }
    }
}

void TextureState::setImageDescChainMultisample(Extents baseSize,
                                                const Format &format,
                                                GLsizei samples,
                                                bool fixedSampleLocations,
                                                InitState initState)
{
    ASSERT(mType == TextureType::_2DMultisample || mType == TextureType::_2DMultisampleArray);
    ImageDesc levelInfo(baseSize, format, samples, fixedSampleLocations, initState);
    setImageDesc(NonCubeTextureTypeToTarget(mType), 0, levelInfo);
}

void TextureState::clearImageDesc(TextureTarget target, size_t level)
{
    setImageDesc(target, level, ImageDesc());
}

void TextureState::clearImageDescs()
{
    for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
    {
        mImageDescs[descIndex] = ImageDesc();
    }
}

TextureBufferContentsObservers::TextureBufferContentsObservers(Texture *texture) : mTexture(texture)
{}

void TextureBufferContentsObservers::enableForBuffer(Buffer *buffer)
{
    buffer->addContentsObserver(mTexture);
}

void TextureBufferContentsObservers::disableForBuffer(Buffer *buffer)
{
    buffer->removeContentsObserver(mTexture);
}

Texture::Texture(rx::GLImplFactory *factory, TextureID id, TextureType type)
    : RefCountObject(factory->generateSerial(), id),
      mState(type),
      mTexture(factory->createTexture(mState)),
      mImplObserver(this, rx::kTextureImageImplObserverMessageIndex),
      mBufferObserver(this, kBufferSubjectIndex),
      mBoundSurface(nullptr),
      mBoundStream(nullptr),
      mBufferContentsObservers(this)
{
    mImplObserver.bind(mTexture);
    if (mTexture)
    {
        mTexture->setContentsObservers(&mBufferContentsObservers);
    }

    // Initially assume the implementation is dirty.
    mDirtyBits.set(DIRTY_BIT_IMPLEMENTATION);
}

void Texture::onDestroy(const Context *context)
{
    onStateChange(angle::SubjectMessage::TextureIDDeleted);

    if (mBoundSurface)
    {
        ANGLE_SWALLOW_ERR(mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER));
        mBoundSurface = nullptr;
    }
    if (mBoundStream)
    {
        mBoundStream->releaseTextures();
        mBoundStream = nullptr;
    }

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    (void)orphanImages(context, &releaseImage);

    mState.mBuffer.set(context, nullptr, 0, 0);

    if (mTexture)
    {
        mTexture->onDestroy(context);
    }
}

Texture::~Texture()
{
    SafeDelete(mTexture);
}

angle::Result Texture::setLabel(const Context *context, const std::string &label)
{
    mState.mLabel = label;
    return mTexture->onLabelUpdate(context);
}

const std::string &Texture::getLabel() const
{
    return mState.mLabel;
}

void Texture::setSwizzleRed(const Context *context, GLenum swizzleRed)
{
    if (mState.mSwizzleState.swizzleRed != swizzleRed)
    {
        mState.mSwizzleState.swizzleRed = swizzleRed;
        signalDirtyState(DIRTY_BIT_SWIZZLE_RED);
    }
}

GLenum Texture::getSwizzleRed() const
{
    return mState.mSwizzleState.swizzleRed;
}

void Texture::setSwizzleGreen(const Context *context, GLenum swizzleGreen)
{
    if (mState.mSwizzleState.swizzleGreen != swizzleGreen)
    {
        mState.mSwizzleState.swizzleGreen = swizzleGreen;
        signalDirtyState(DIRTY_BIT_SWIZZLE_GREEN);
    }
}

GLenum Texture::getSwizzleGreen() const
{
    return mState.mSwizzleState.swizzleGreen;
}

void Texture::setSwizzleBlue(const Context *context, GLenum swizzleBlue)
{
    if (mState.mSwizzleState.swizzleBlue != swizzleBlue)
    {
        mState.mSwizzleState.swizzleBlue = swizzleBlue;
        signalDirtyState(DIRTY_BIT_SWIZZLE_BLUE);
    }
}

GLenum Texture::getSwizzleBlue() const
{
    return mState.mSwizzleState.swizzleBlue;
}

void Texture::setSwizzleAlpha(const Context *context, GLenum swizzleAlpha)
{
    if (mState.mSwizzleState.swizzleAlpha != swizzleAlpha)
    {
        mState.mSwizzleState.swizzleAlpha = swizzleAlpha;
        signalDirtyState(DIRTY_BIT_SWIZZLE_ALPHA);
    }
}

GLenum Texture::getSwizzleAlpha() const
{
    return mState.mSwizzleState.swizzleAlpha;
}

void Texture::setMinFilter(const Context *context, GLenum minFilter)
{
    if (mState.mSamplerState.setMinFilter(minFilter))
    {
        signalDirtyState(DIRTY_BIT_MIN_FILTER);
    }
}

GLenum Texture::getMinFilter() const
{
    return mState.mSamplerState.getMinFilter();
}

void Texture::setMagFilter(const Context *context, GLenum magFilter)
{
    if (mState.mSamplerState.setMagFilter(magFilter))
    {
        signalDirtyState(DIRTY_BIT_MAG_FILTER);
    }
}

GLenum Texture::getMagFilter() const
{
    return mState.mSamplerState.getMagFilter();
}

void Texture::setWrapS(const Context *context, GLenum wrapS)
{
    if (mState.mSamplerState.setWrapS(wrapS))
    {
        signalDirtyState(DIRTY_BIT_WRAP_S);
    }
}

GLenum Texture::getWrapS() const
{
    return mState.mSamplerState.getWrapS();
}

void Texture::setWrapT(const Context *context, GLenum wrapT)
{
    if (mState.mSamplerState.getWrapT() == wrapT)
        return;
    if (mState.mSamplerState.setWrapT(wrapT))
    {
        signalDirtyState(DIRTY_BIT_WRAP_T);
    }
}

GLenum Texture::getWrapT() const
{
    return mState.mSamplerState.getWrapT();
}

void Texture::setWrapR(const Context *context, GLenum wrapR)
{
    if (mState.mSamplerState.setWrapR(wrapR))
    {
        signalDirtyState(DIRTY_BIT_WRAP_R);
    }
}

GLenum Texture::getWrapR() const
{
    return mState.mSamplerState.getWrapR();
}

void Texture::setMaxAnisotropy(const Context *context, float maxAnisotropy)
{
    if (mState.mSamplerState.setMaxAnisotropy(maxAnisotropy))
    {
        signalDirtyState(DIRTY_BIT_MAX_ANISOTROPY);
    }
}

float Texture::getMaxAnisotropy() const
{
    return mState.mSamplerState.getMaxAnisotropy();
}

void Texture::setMinLod(const Context *context, GLfloat minLod)
{
    if (mState.mSamplerState.setMinLod(minLod))
    {
        signalDirtyState(DIRTY_BIT_MIN_LOD);
    }
}

GLfloat Texture::getMinLod() const
{
    return mState.mSamplerState.getMinLod();
}

void Texture::setMaxLod(const Context *context, GLfloat maxLod)
{
    if (mState.mSamplerState.setMaxLod(maxLod))
    {
        signalDirtyState(DIRTY_BIT_MAX_LOD);
    }
}

GLfloat Texture::getMaxLod() const
{
    return mState.mSamplerState.getMaxLod();
}

void Texture::setCompareMode(const Context *context, GLenum compareMode)
{
    if (mState.mSamplerState.setCompareMode(compareMode))
    {
        signalDirtyState(DIRTY_BIT_COMPARE_MODE);
    }
}

GLenum Texture::getCompareMode() const
{
    return mState.mSamplerState.getCompareMode();
}

void Texture::setASTCDecodePrecision(const Context *context, GLenum astcDecodePrecision)
{
    if (mState.setASTCDecodePrecision(astcDecodePrecision))
    {
        signalDirtyState(DIRTY_BIT_ASTC_DECODE_PRECISION);
    }
}

GLenum Texture::getASTCDecodePrecision() const
{
    return mState.getASTCDecodePrecision();
}

void Texture::setCompareFunc(const Context *context, GLenum compareFunc)
{
    if (mState.mSamplerState.setCompareFunc(compareFunc))
    {
        signalDirtyState(DIRTY_BIT_COMPARE_FUNC);
    }
}

GLenum Texture::getCompareFunc() const
{
    return mState.mSamplerState.getCompareFunc();
}

void Texture::setSRGBDecode(const Context *context, GLenum sRGBDecode)
{
    if (mState.mSamplerState.setSRGBDecode(sRGBDecode))
    {
        signalDirtyState(DIRTY_BIT_SRGB_DECODE);
    }
}

GLenum Texture::getSRGBDecode() const
{
    return mState.mSamplerState.getSRGBDecode();
}

void Texture::setSRGBOverride(const Context *context, GLenum sRGBOverride)
{
    SrgbOverride oldOverride = mState.mSrgbOverride;
    mState.mSrgbOverride = (sRGBOverride == GL_SRGB) ? SrgbOverride::SRGB : SrgbOverride::Default;
    if (mState.mSrgbOverride != oldOverride)
    {
        signalDirtyState(DIRTY_BIT_SRGB_OVERRIDE);
    }
}

GLenum Texture::getSRGBOverride() const
{
    return (mState.mSrgbOverride == SrgbOverride::SRGB) ? GL_SRGB : GL_NONE;
}

const SamplerState &Texture::getSamplerState() const
{
    return mState.mSamplerState;
}

angle::Result Texture::setBaseLevel(const Context *context, GLuint baseLevel)
{
    if (mState.setBaseLevel(baseLevel))
    {
        ANGLE_TRY(mTexture->setBaseLevel(context, mState.getEffectiveBaseLevel()));
        signalDirtyState(DIRTY_BIT_BASE_LEVEL);
    }

    return angle::Result::Continue;
}

GLuint Texture::getBaseLevel() const
{
    return mState.mBaseLevel;
}

void Texture::setMaxLevel(const Context *context, GLuint maxLevel)
{
    if (mState.setMaxLevel(maxLevel))
    {
        signalDirtyState(DIRTY_BIT_MAX_LEVEL);
    }
}

GLuint Texture::getMaxLevel() const
{
    return mState.mMaxLevel;
}

void Texture::setDepthStencilTextureMode(const Context *context, GLenum mode)
{
    if (mState.mDepthStencilTextureMode != mode)
    {
        mState.mDepthStencilTextureMode = mode;
        signalDirtyState(DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE);
    }
}

GLenum Texture::getDepthStencilTextureMode() const
{
    return mState.mDepthStencilTextureMode;
}

bool Texture::getImmutableFormat() const
{
    return mState.mImmutableFormat;
}

GLuint Texture::getImmutableLevels() const
{
    return mState.mImmutableLevels;
}

void Texture::setUsage(const Context *context, GLenum usage)
{
    mState.mUsage = usage;
    signalDirtyState(DIRTY_BIT_USAGE);
}

GLenum Texture::getUsage() const
{
    return mState.mUsage;
}

void Texture::setProtectedContent(Context *context, bool hasProtectedContent)
{
    mState.mHasProtectedContent = hasProtectedContent;
}

bool Texture::hasProtectedContent() const
{
    return mState.mHasProtectedContent;
}

void Texture::setRenderabilityValidation(Context *context, bool renderabilityValidation)
{
    mState.mRenderabilityValidation = renderabilityValidation;
    signalDirtyState(DIRTY_BIT_RENDERABILITY_VALIDATION_ANGLE);
}

void Texture::setTilingMode(Context *context, GLenum tilingMode)
{
    mState.mTilingMode = gl::FromGLenum<gl::TilingMode>(tilingMode);
}

GLenum Texture::getTilingMode() const
{
    return gl::ToGLenum(mState.mTilingMode);
}

const TextureState &Texture::getTextureState() const
{
    return mState;
}

const Extents &Texture::getExtents(TextureTarget target, size_t level) const
{
    ASSERT(TextureTargetToType(target) == mState.mType);
    return mState.getImageDesc(target, level).size;
}

size_t Texture::getWidth(TextureTarget target, size_t level) const
{
    ASSERT(TextureTargetToType(target) == mState.mType);
    return mState.getImageDesc(target, level).size.width;
}

size_t Texture::getHeight(TextureTarget target, size_t level) const
{
    ASSERT(TextureTargetToType(target) == mState.mType);
    return mState.getImageDesc(target, level).size.height;
}

size_t Texture::getDepth(TextureTarget target, size_t level) const
{
    ASSERT(TextureTargetToType(target) == mState.mType);
    return mState.getImageDesc(target, level).size.depth;
}

const Format &Texture::getFormat(TextureTarget target, size_t level) const
{
    ASSERT(TextureTargetToType(target) == mState.mType);
    return mState.getImageDesc(target, level).format;
}

GLsizei Texture::getSamples(TextureTarget target, size_t level) const
{
    ASSERT(TextureTargetToType(target) == mState.mType);
    return mState.getImageDesc(target, level).samples;
}

bool Texture::getFixedSampleLocations(TextureTarget target, size_t level) const
{
    ASSERT(TextureTargetToType(target) == mState.mType);
    return mState.getImageDesc(target, level).fixedSampleLocations;
}

GLuint Texture::getMipmapMaxLevel() const
{
    return mState.getMipmapMaxLevel();
}

bool Texture::isMipmapComplete() const
{
    return mState.computeMipmapCompleteness();
}

GLuint Texture::getFoveatedFeatureBits() const
{
    return mState.mFoveationState.getFoveatedFeatureBits();
}

void Texture::setFoveatedFeatureBits(const GLuint features)
{
    mState.mFoveationState.setFoveatedFeatureBits(features);
}

bool Texture::isFoveationEnabled() const
{
    return (mState.mFoveationState.getFoveatedFeatureBits() & GL_FOVEATION_ENABLE_BIT_QCOM);
}

GLuint Texture::getSupportedFoveationFeatures() const
{
    return mState.mFoveationState.getSupportedFoveationFeatures();
}

GLfloat Texture::getMinPixelDensity() const
{
    return mState.mFoveationState.getMinPixelDensity();
}

void Texture::setMinPixelDensity(const GLfloat density)
{
    mState.mFoveationState.setMinPixelDensity(density);
}

void Texture::setFocalPoint(uint32_t layer,
                            uint32_t focalPointIndex,
                            float focalX,
                            float focalY,
                            float gainX,
                            float gainY,
                            float foveaArea)
{
    gl::FocalPoint newFocalPoint(focalX, focalY, gainX, gainY, foveaArea);
    if (mState.mFoveationState.getFocalPoint(layer, focalPointIndex) == newFocalPoint)
    {
        // Nothing to do, early out.
        return;
    }

    mState.mFoveationState.setFocalPoint(layer, focalPointIndex, newFocalPoint);
    mState.mFoveationState.setFoveatedFeatureBits(GL_FOVEATION_ENABLE_BIT_QCOM);
    onStateChange(angle::SubjectMessage::FoveatedRenderingStateChanged);
}

const FocalPoint &Texture::getFocalPoint(uint32_t layer, uint32_t focalPoint) const
{
    return mState.mFoveationState.getFocalPoint(layer, focalPoint);
}

egl::Surface *Texture::getBoundSurface() const
{
    return mBoundSurface;
}

egl::Stream *Texture::getBoundStream() const
{
    return mBoundStream;
}

GLint Texture::getMemorySize() const
{
    GLint implSize = mTexture->getMemorySize();
    if (implSize > 0)
    {
        return implSize;
    }

    angle::CheckedNumeric<GLint> size = 0;
    for (const ImageDesc &imageDesc : mState.mImageDescs)
    {
        size += imageDesc.getMemorySize();
    }
    return size.ValueOrDefault(std::numeric_limits<GLint>::max());
}

GLint Texture::getLevelMemorySize(TextureTarget target, GLint level) const
{
    GLint implSize = mTexture->getLevelMemorySize(target, level);
    if (implSize > 0)
    {
        return implSize;
    }

    return mState.getImageDesc(target, level).getMemorySize();
}

void Texture::signalDirtyStorage(InitState initState)
{
    mState.mInitState = initState;
    invalidateCompletenessCache();
    mState.mCachedSamplerFormatValid = false;
    onStateChange(angle::SubjectMessage::SubjectChanged);
}

void Texture::signalDirtyState(size_t dirtyBit)
{
    mDirtyBits.set(dirtyBit);
    invalidateCompletenessCache();
    mState.mCachedSamplerFormatValid = false;

    if (dirtyBit == DIRTY_BIT_BASE_LEVEL || dirtyBit == DIRTY_BIT_MAX_LEVEL)
    {
        onStateChange(angle::SubjectMessage::SubjectChanged);
    }
    else
    {
        onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
    }
}

angle::Result Texture::setImage(Context *context,
                                const PixelUnpackState &unpackState,
                                Buffer *unpackBuffer,
                                TextureTarget target,
                                GLint level,
                                GLenum internalFormat,
                                const Extents &size,
                                GLenum format,
                                GLenum type,
                                const uint8_t *pixels)
{
    ASSERT(TextureTargetToType(target) == mState.mType);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);

    ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size, format, type, unpackState,
                                 unpackBuffer, pixels));

    InitState initState = DetermineInitState(context, unpackBuffer, pixels);
    mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));

    ANGLE_TRY(handleMipmapGenerationHint(context, level));

    signalDirtyStorage(initState);

    return angle::Result::Continue;
}

angle::Result Texture::setSubImage(Context *context,
                                   const PixelUnpackState &unpackState,
                                   Buffer *unpackBuffer,
                                   TextureTarget target,
                                   GLint level,
                                   const Box &area,
                                   GLenum format,
                                   GLenum type,
                                   const uint8_t *pixels)
{
    ASSERT(TextureTargetToType(target) == mState.mType);

    ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
    ANGLE_TRY(ensureSubImageInitialized(context, index, area));

    ANGLE_TRY(mTexture->setSubImage(context, index, area, format, type, unpackState, unpackBuffer,
                                    pixels));

    ANGLE_TRY(handleMipmapGenerationHint(context, level));

    onStateChange(angle::SubjectMessage::ContentsChanged);

    return angle::Result::Continue;
}

angle::Result Texture::setCompressedImage(Context *context,
                                          const PixelUnpackState &unpackState,
                                          TextureTarget target,
                                          GLint level,
                                          GLenum internalFormat,
                                          const Extents &size,
                                          size_t imageSize,
                                          const uint8_t *pixels)
{
    ASSERT(TextureTargetToType(target) == mState.mType);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);

    ANGLE_TRY(mTexture->setCompressedImage(context, index, internalFormat, size, unpackState,
                                           imageSize, pixels));

    Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);

    InitState initState = DetermineInitState(context, unpackBuffer, pixels);
    mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat), initState));
    signalDirtyStorage(initState);

    return angle::Result::Continue;
}

angle::Result Texture::setCompressedSubImage(const Context *context,
                                             const PixelUnpackState &unpackState,
                                             TextureTarget target,
                                             GLint level,
                                             const Box &area,
                                             GLenum format,
                                             size_t imageSize,
                                             const uint8_t *pixels)
{
    ASSERT(TextureTargetToType(target) == mState.mType);

    ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
    ANGLE_TRY(ensureSubImageInitialized(context, index, area));

    ANGLE_TRY(mTexture->setCompressedSubImage(context, index, area, format, unpackState, imageSize,
                                              pixels));

    onStateChange(angle::SubjectMessage::ContentsChanged);

    return angle::Result::Continue;
}

angle::Result Texture::copyImage(Context *context,
                                 TextureTarget target,
                                 GLint level,
                                 const Rectangle &sourceArea,
                                 GLenum internalFormat,
                                 Framebuffer *source)
{
    ASSERT(TextureTargetToType(target) == mState.mType);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    ImageIndex index = ImageIndex::MakeFromTarget(target, level, 1);

    const InternalFormat &internalFormatInfo =
        GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);

    // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
    // other pixels untouched. For safety in robust resource initialization, assume that that
    // clipping is going to occur when computing the region for which to ensure initialization. If
    // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
    // going to be set during the copy operation.
    Box destBox;
    bool forceCopySubImage = false;
    if (context->isRobustResourceInitEnabled())
    {
        const FramebufferAttachment *sourceReadAttachment = source->getReadColorAttachment();
        Extents fbSize                                    = sourceReadAttachment->getSize();
        // Force using copySubImage when the source area is out of bounds AND
        // we're not copying to and from the same texture
        forceCopySubImage = ((sourceArea.x < 0) || (sourceArea.y < 0) ||
                             ((sourceArea.x + sourceArea.width) > fbSize.width) ||
                             ((sourceArea.y + sourceArea.height) > fbSize.height)) &&
                            (sourceReadAttachment->getResource() != this);
        Rectangle clippedArea;
        if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
        {
            const Offset clippedOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y,
                                       0);
            destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
                          clippedArea.height, 1);
        }
    }

    InitState initState = DetermineInitState(context, nullptr, nullptr);

    // If we need to initialize the destination texture we split the call into a create call,
    // an initializeContents call, and then a copySubImage call. This ensures the destination
    // texture exists before we try to clear it.
    Extents size(sourceArea.width, sourceArea.height, 1);
    if (forceCopySubImage || doesSubImageNeedInit(context, index, destBox))
    {
        ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size,
                                     internalFormatInfo.format, internalFormatInfo.type,
                                     PixelUnpackState(), nullptr, nullptr));
        mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormatInfo), initState));
        ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
        ANGLE_TRY(mTexture->copySubImage(context, index, Offset(), sourceArea, source));
    }
    else
    {
        ANGLE_TRY(mTexture->copyImage(context, index, sourceArea, internalFormat, source));
    }

    mState.setImageDesc(target, level,
                        ImageDesc(size, Format(internalFormatInfo), InitState::Initialized));

    ANGLE_TRY(handleMipmapGenerationHint(context, level));

    // Because this could affect the texture storage we might need to init other layers/levels.
    signalDirtyStorage(initState);

    return angle::Result::Continue;
}

angle::Result Texture::copySubImage(Context *context,
                                    const ImageIndex &index,
                                    const Offset &destOffset,
                                    const Rectangle &sourceArea,
                                    Framebuffer *source)
{
    ASSERT(TextureTargetToType(index.getTarget()) == mState.mType);

    // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
    // other pixels untouched. For safety in robust resource initialization, assume that that
    // clipping is going to occur when computing the region for which to ensure initialization. If
    // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
    // going to be set during the copy operation. Note that this assumes that
    // ensureSubImageInitialized ensures initialization of the entire destination texture, and not
    // just a sub-region.
    Box destBox;
    if (context->isRobustResourceInitEnabled())
    {
        Extents fbSize = source->getReadColorAttachment()->getSize();
        Rectangle clippedArea;
        if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
        {
            const Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
                                       destOffset.y + clippedArea.y - sourceArea.y, 0);
            destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
                          clippedArea.height, 1);
        }
    }

    ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));

    ANGLE_TRY(mTexture->copySubImage(context, index, destOffset, sourceArea, source));
    ANGLE_TRY(handleMipmapGenerationHint(context, index.getLevelIndex()));

    onStateChange(angle::SubjectMessage::ContentsChanged);

    return angle::Result::Continue;
}

angle::Result Texture::copyRenderbufferSubData(Context *context,
                                               const gl::Renderbuffer *srcBuffer,
                                               GLint srcLevel,
                                               GLint srcX,
                                               GLint srcY,
                                               GLint srcZ,
                                               GLint dstLevel,
                                               GLint dstX,
                                               GLint dstY,
                                               GLint dstZ,
                                               GLsizei srcWidth,
                                               GLsizei srcHeight,
                                               GLsizei srcDepth)
{
    ANGLE_TRY(mTexture->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY, srcZ,
                                                dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
                                                srcDepth));

    signalDirtyStorage(InitState::Initialized);

    return angle::Result::Continue;
}

angle::Result Texture::copyTextureSubData(Context *context,
                                          const gl::Texture *srcTexture,
                                          GLint srcLevel,
                                          GLint srcX,
                                          GLint srcY,
                                          GLint srcZ,
                                          GLint dstLevel,
                                          GLint dstX,
                                          GLint dstY,
                                          GLint dstZ,
                                          GLsizei srcWidth,
                                          GLsizei srcHeight,
                                          GLsizei srcDepth)
{
    ANGLE_TRY(mTexture->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
                                           dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
                                           srcDepth));

    signalDirtyStorage(InitState::Initialized);

    return angle::Result::Continue;
}

angle::Result Texture::copyTexture(Context *context,
                                   TextureTarget target,
                                   GLint level,
                                   GLenum internalFormat,
                                   GLenum type,
                                   GLint sourceLevel,
                                   bool unpackFlipY,
                                   bool unpackPremultiplyAlpha,
                                   bool unpackUnmultiplyAlpha,
                                   Texture *source)
{
    ASSERT(TextureTargetToType(target) == mState.mType);
    ASSERT(source->getType() != TextureType::CubeMap);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    // Initialize source texture.
    // Note: we don't have a way to notify which portions of the image changed currently.
    ANGLE_TRY(source->ensureInitialized(context));

    ImageIndex index = ImageIndex::MakeFromTarget(target, level, ImageIndex::kEntireLevel);

    ANGLE_TRY(mTexture->copyTexture(context, index, internalFormat, type, sourceLevel, unpackFlipY,
                                    unpackPremultiplyAlpha, unpackUnmultiplyAlpha, source));

    const auto &sourceDesc =
        source->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
    const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
    mState.setImageDesc(
        target, level,
        ImageDesc(sourceDesc.size, Format(internalFormatInfo), InitState::Initialized));

    signalDirtyStorage(InitState::Initialized);

    return angle::Result::Continue;
}

angle::Result Texture::copySubTexture(const Context *context,
                                      TextureTarget target,
                                      GLint level,
                                      const Offset &destOffset,
                                      GLint sourceLevel,
                                      const Box &sourceBox,
                                      bool unpackFlipY,
                                      bool unpackPremultiplyAlpha,
                                      bool unpackUnmultiplyAlpha,
                                      Texture *source)
{
    ASSERT(TextureTargetToType(target) == mState.mType);

    // Ensure source is initialized.
    ANGLE_TRY(source->ensureInitialized(context));

    Box destBox(destOffset.x, destOffset.y, destOffset.z, sourceBox.width, sourceBox.height,
                sourceBox.depth);
    ImageIndex index = ImageIndex::MakeFromTarget(target, level, sourceBox.depth);
    ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));

    ANGLE_TRY(mTexture->copySubTexture(context, index, destOffset, sourceLevel, sourceBox,
                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
                                       source));

    onStateChange(angle::SubjectMessage::ContentsChanged);

    return angle::Result::Continue;
}

angle::Result Texture::copyCompressedTexture(Context *context, const Texture *source)
{
    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    ANGLE_TRY(mTexture->copyCompressedTexture(context, source));

    ASSERT(source->getType() != TextureType::CubeMap && getType() != TextureType::CubeMap);
    const auto &sourceDesc =
        source->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), 0);
    mState.setImageDesc(NonCubeTextureTypeToTarget(getType()), 0, sourceDesc);

    return angle::Result::Continue;
}

angle::Result Texture::setStorage(Context *context,
                                  TextureType type,
                                  GLsizei levels,
                                  GLenum internalFormat,
                                  const Extents &size)
{
    ASSERT(type == mState.mType);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    mState.mImmutableFormat = true;
    mState.mImmutableLevels = static_cast<GLuint>(levels);
    mState.clearImageDescs();
    InitState initState = DetermineInitState(context, nullptr, nullptr);
    mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
                             initState);

    ANGLE_TRY(mTexture->setStorage(context, type, levels, internalFormat, size));

    // Changing the texture to immutable can trigger a change in the base and max levels:
    // GLES 3.0.4 section 3.8.10 pg 158:
    // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
    // clamped to the range[levelbase;levels].
    mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
    mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);

    signalDirtyStorage(initState);

    return angle::Result::Continue;
}

angle::Result Texture::setImageExternal(Context *context,
                                        TextureTarget target,
                                        GLint level,
                                        GLenum internalFormat,
                                        const Extents &size,
                                        GLenum format,
                                        GLenum type)
{
    ASSERT(TextureTargetToType(target) == mState.mType);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);

    ANGLE_TRY(mTexture->setImageExternal(context, index, internalFormat, size, format, type));

    InitState initState = InitState::Initialized;
    mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));

    ANGLE_TRY(handleMipmapGenerationHint(context, level));

    signalDirtyStorage(initState);

    return angle::Result::Continue;
}

angle::Result Texture::setStorageMultisample(Context *context,
                                             TextureType type,
                                             GLsizei samplesIn,
                                             GLint internalFormat,
                                             const Extents &size,
                                             bool fixedSampleLocations)
{
    ASSERT(type == mState.mType);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    // Potentially adjust "samples" to a supported value
    const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
    GLsizei samples               = formatCaps.sampleCounts.getNearestSamples(samplesIn);

    mState.mImmutableFormat = true;
    mState.mImmutableLevels = static_cast<GLuint>(1);
    mState.clearImageDescs();
    InitState initState = DetermineInitState(context, nullptr, nullptr);
    mState.setImageDescChainMultisample(size, Format(internalFormat), samples, fixedSampleLocations,
                                        initState);

    ANGLE_TRY(mTexture->setStorageMultisample(context, type, samples, internalFormat, size,
                                              fixedSampleLocations));
    signalDirtyStorage(initState);

    return angle::Result::Continue;
}

angle::Result Texture::setStorageExternalMemory(Context *context,
                                                TextureType type,
                                                GLsizei levels,
                                                GLenum internalFormat,
                                                const Extents &size,
                                                MemoryObject *memoryObject,
                                                GLuint64 offset,
                                                GLbitfield createFlags,
                                                GLbitfield usageFlags,
                                                const void *imageCreateInfoPNext)
{
    ASSERT(type == mState.mType);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    ANGLE_TRY(mTexture->setStorageExternalMemory(context, type, levels, internalFormat, size,
                                                 memoryObject, offset, createFlags, usageFlags,
                                                 imageCreateInfoPNext));

    mState.mIsExternalMemoryTexture = true;
    mState.mImmutableFormat = true;
    mState.mImmutableLevels = static_cast<GLuint>(levels);
    mState.clearImageDescs();
    mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
                             InitState::Initialized);

    // Changing the texture to immutable can trigger a change in the base and max levels:
    // GLES 3.0.4 section 3.8.10 pg 158:
    // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
    // clamped to the range[levelbase;levels].
    mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
    mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);

    signalDirtyStorage(InitState::Initialized);

    return angle::Result::Continue;
}

angle::Result Texture::setStorageAttribs(Context *context,
                                         TextureType type,
                                         GLsizei levels,
                                         GLenum internalFormat,
                                         const Extents &size,
                                         const GLint *attribList)
{
    ASSERT(type == mState.mType);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    mState.mImmutableFormat = true;
    mState.mImmutableLevels = static_cast<GLuint>(levels);
    mState.clearImageDescs();
    InitState initState = DetermineInitState(context, nullptr, nullptr);
    mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
                             initState);

    if (nullptr != attribList && GL_SURFACE_COMPRESSION_EXT == *attribList)
    {
        attribList++;
        if (nullptr != attribList && GL_NONE != *attribList)
        {
            mState.mCompressionFixedRate = *attribList;
        }
    }

    ANGLE_TRY(mTexture->setStorageAttribs(context, type, levels, internalFormat, size, attribList));

    // Changing the texture to immutable can trigger a change in the base and max levels:
    // GLES 3.0.4 section 3.8.10 pg 158:
    // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
    // clamped to the range[levelbase;levels].
    mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
    mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);

    signalDirtyStorage(initState);

    return angle::Result::Continue;
}

GLint Texture::getImageCompressionRate(const Context *context) const
{
    return mTexture->getImageCompressionRate(context);
}

GLint Texture::getFormatSupportedCompressionRates(const Context *context,
                                                  GLenum internalformat,
                                                  GLsizei bufSize,
                                                  GLint *rates) const
{
    return mTexture->getFormatSupportedCompressionRates(context, internalformat, bufSize, rates);
}

angle::Result Texture::generateMipmap(Context *context)
{
    // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
    // is not mip complete.
    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    if (!isMipmapComplete())
    {
        ANGLE_TRY(orphanImages(context, &releaseImage));
    }

    const GLuint baseLevel = mState.getEffectiveBaseLevel();
    const GLuint maxLevel  = mState.getMipmapMaxLevel();

    if (maxLevel <= baseLevel)
    {
        return angle::Result::Continue;
    }

    // If any dimension is zero, this is a no-op:
    //
    // > Otherwise, if level_base is not defined, or if any dimension is zero, all mipmap levels are
    // > left unchanged. This is not an error.
    const ImageDesc &baseImageInfo = mState.getImageDesc(mState.getBaseImageTarget(), baseLevel);
    if (baseImageInfo.size.empty())
    {
        return angle::Result::Continue;
    }

    // Clear the base image(s) immediately if needed
    if (context->isRobustResourceInitEnabled())
    {
        ImageIndexIterator it =
            ImageIndexIterator::MakeGeneric(mState.mType, baseLevel, baseLevel + 1,
                                            ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
        while (it.hasNext())
        {
            const ImageIndex index = it.next();
            const ImageDesc &desc  = mState.getImageDesc(index.getTarget(), index.getLevelIndex());

            if (desc.initState == InitState::MayNeedInit)
            {
                ANGLE_TRY(initializeContents(context, GL_NONE, index));
            }
        }
    }

    ANGLE_TRY(syncState(context, Command::GenerateMipmap));
    ANGLE_TRY(mTexture->generateMipmap(context));

    // Propagate the format and size of the base mip to the smaller ones. Cube maps are guaranteed
    // to have faces of the same size and format so any faces can be picked.
    mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format,
                             InitState::Initialized);

    // Disconnect the texture from the surface
    releaseTexImageInternalNoRedefinition(context);
    mBoundSurface = nullptr;

    signalDirtyStorage(InitState::Initialized);

    return angle::Result::Continue;
}

angle::Result Texture::clearImage(Context *context,
                                  GLint level,
                                  GLenum format,
                                  GLenum type,
                                  const uint8_t *data)
{
    ANGLE_TRY(mTexture->clearImage(context, level, format, type, data));

    ANGLE_TRY(handleMipmapGenerationHint(context, level));

    ImageIndexIterator it = ImageIndexIterator::MakeGeneric(
        mState.mType, level, level + 1, ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
    while (it.hasNext())
    {
        const ImageIndex index = it.next();
        setInitState(GL_NONE, index, InitState::Initialized);
    }

    onStateChange(angle::SubjectMessage::ContentsChanged);

    return angle::Result::Continue;
}

angle::Result Texture::clearSubImage(Context *context,
                                     GLint level,
                                     const Box &area,
                                     GLenum format,
                                     GLenum type,
                                     const uint8_t *data)
{
    const ImageIndexIterator allImagesIterator = ImageIndexIterator::MakeGeneric(
        mState.mType, level, level + 1, area.z, area.z + area.depth);

    ImageIndexIterator initImagesIterator = allImagesIterator;
    while (initImagesIterator.hasNext())
    {
        const ImageIndex index     = initImagesIterator.next();
        const Box cubeFlattenedBox = index.getType() == TextureType::CubeMap
                                         ? Box(area.x, area.y, 0, area.width, area.height, 1)
                                         : area;
        ANGLE_TRY(ensureSubImageInitialized(context, index, cubeFlattenedBox));
    }

    ANGLE_TRY(mTexture->clearSubImage(context, level, area, format, type, data));

    ANGLE_TRY(handleMipmapGenerationHint(context, level));

    onStateChange(angle::SubjectMessage::ContentsChanged);

    return angle::Result::Continue;
}

angle::Result Texture::bindTexImageFromSurface(Context *context, egl::Surface *surface)
{
    ASSERT(surface);
    ASSERT(!mBoundSurface);
    mBoundSurface = surface;

    // Set the image info to the size and format of the surface
    ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle);
    ImageDesc desc(surface->getSize(), surface->getBindTexImageFormat(), InitState::Initialized);
    mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0, desc);
    mState.mHasProtectedContent = surface->hasProtectedContent();

    ANGLE_TRY(mTexture->bindTexImage(context, surface));

    signalDirtyStorage(InitState::Initialized);
    return angle::Result::Continue;
}

angle::Result Texture::releaseTexImageFromSurface(const Context *context)
{
    ASSERT(mBoundSurface);
    mBoundSurface = nullptr;
    ANGLE_TRY(mTexture->releaseTexImage(context));

    // Erase the image info for level 0
    ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle);
    mState.clearImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0);
    mState.mHasProtectedContent = false;
    signalDirtyStorage(InitState::Initialized);
    return angle::Result::Continue;
}

void Texture::bindStream(egl::Stream *stream)
{
    ASSERT(stream);

    // It should not be possible to bind a texture already bound to another stream
    ASSERT(mBoundStream == nullptr);

    mBoundStream = stream;

    ASSERT(mState.mType == TextureType::External);
}

void Texture::releaseStream()
{
    ASSERT(mBoundStream);
    mBoundStream = nullptr;
}

angle::Result Texture::acquireImageFromStream(const Context *context,
                                              const egl::Stream::GLTextureDescription &desc)
{
    ASSERT(mBoundStream != nullptr);
    ANGLE_TRY(mTexture->setImageExternal(context, mState.mType, mBoundStream, desc));

    Extents size(desc.width, desc.height, 1);
    mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0,
                        ImageDesc(size, Format(desc.internalFormat), InitState::Initialized));
    signalDirtyStorage(InitState::Initialized);
    return angle::Result::Continue;
}

angle::Result Texture::releaseImageFromStream(const Context *context)
{
    ASSERT(mBoundStream != nullptr);
    ANGLE_TRY(mTexture->setImageExternal(context, mState.mType, nullptr,
                                         egl::Stream::GLTextureDescription()));

    // Set to incomplete
    mState.clearImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0);
    signalDirtyStorage(InitState::Initialized);
    return angle::Result::Continue;
}

void Texture::releaseTexImageInternalNoRedefinition(Context *context)
{
    if (mBoundSurface)
    {
        // Notify the surface
        egl::Error eglErr = mBoundSurface->releaseTexImageFromTexture(context);
        // TODO(jmadill): Remove this once refactor is complete. http://anglebug.com/42261727
        if (eglErr.isError())
        {
            context->handleError(GL_INVALID_OPERATION, "Error releasing tex image from texture",
                                 __FILE__, ANGLE_FUNCTION, __LINE__);
        }
    }
}

angle::Result Texture::releaseTexImageInternal(Context *context)
{
    releaseTexImageInternalNoRedefinition(context);

    // Then, call the same method as from the surface
    if (mBoundSurface)
    {
        ANGLE_TRY(releaseTexImageFromSurface(context));
    }
    return angle::Result::Continue;
}

angle::Result Texture::setEGLImageTargetImpl(Context *context,
                                             TextureType type,
                                             GLuint levels,
                                             egl::Image *imageTarget)
{
    ASSERT(type == mState.mType);

    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
    ANGLE_TRY(releaseTexImageInternal(context));

    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    ANGLE_TRY(orphanImages(context, &releaseImage));

    setTargetImage(context, imageTarget);

    auto initState = imageTarget->sourceInitState();

    mState.clearImageDescs();
    mState.setImageDescChain(0, levels - 1, imageTarget->getExtents(), imageTarget->getFormat(),
                             initState);
    mState.mHasProtectedContent = imageTarget->hasProtectedContent();

    ANGLE_TRY(mTexture->setEGLImageTarget(context, type, imageTarget));

    signalDirtyStorage(initState);

    return angle::Result::Continue;
}

angle::Result Texture::setEGLImageTarget(Context *context,
                                         TextureType type,
                                         egl::Image *imageTarget)
{
    ASSERT(type == TextureType::_2D || type == TextureType::External ||
           type == TextureType::_2DArray);

    return setEGLImageTargetImpl(context, type, 1u, imageTarget);
}

angle::Result Texture::setStorageEGLImageTarget(Context *context,
                                                TextureType type,
                                                egl::Image *imageTarget,
                                                const GLint *attrib_list)
{
    ASSERT(type == TextureType::External || type == TextureType::_3D || type == TextureType::_2D ||
           type == TextureType::_2DArray || type == TextureType::CubeMap ||
           type == TextureType::CubeMapArray);

    ANGLE_TRY(setEGLImageTargetImpl(context, type, imageTarget->getLevelCount(), imageTarget));

    mState.mImmutableLevels = imageTarget->getLevelCount();
    mState.mImmutableFormat = true;

    // Changing the texture to immutable can trigger a change in the base and max levels:
    // GLES 3.0.4 section 3.8.10 pg 158:
    // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
    // clamped to the range[levelbase;levels].
    mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
    mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);

    return angle::Result::Continue;
}

Extents Texture::getAttachmentSize(const ImageIndex &imageIndex) const
{
    // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
    // we only allow querying ImageDesc on a complete cube map, and this ImageDesc is exactly the
    // one that belongs to the first face of the cube map.
    if (imageIndex.isEntireLevelCubeMap())
    {
        // A cube map texture is cube complete if the following conditions all hold true:
        // - The levelbase arrays of each of the six texture images making up the cube map have
        //   identical, positive, and square dimensions.
        if (!mState.isCubeComplete())
        {
            return Extents();
        }
    }

    return mState.getImageDesc(imageIndex).size;
}

Format Texture::getAttachmentFormat(GLenum /*binding*/, const ImageIndex &imageIndex) const
{
    // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
    // we only allow querying ImageDesc on a complete cube map, and this ImageDesc is exactly the
    // one that belongs to the first face of the cube map.
    if (imageIndex.isEntireLevelCubeMap())
    {
        // A cube map texture is cube complete if the following conditions all hold true:
        // - The levelbase arrays were each specified with the same effective internal format.
        if (!mState.isCubeComplete())
        {
            return Format::Invalid();
        }
    }
    return mState.getImageDesc(imageIndex).format;
}

GLsizei Texture::getAttachmentSamples(const ImageIndex &imageIndex) const
{
    // We do not allow querying TextureTarget by an ImageIndex that represents an entire level of a
    // cube map (See comments in function TextureTypeToTarget() in ImageIndex.cpp).
    if (imageIndex.isEntireLevelCubeMap())
    {
        return 0;
    }

    return getSamples(imageIndex.getTarget(), imageIndex.getLevelIndex());
}

bool Texture::isRenderable(const Context *context,
                           GLenum binding,
                           const ImageIndex &imageIndex) const
{
    if (isEGLImageTarget())
    {
        return ImageSibling::isRenderable(context, binding, imageIndex);
    }

    // Surfaces bound to textures are always renderable. This avoids issues with surfaces with ES3+
    // formats not being renderable when bound to textures in ES2 contexts.
    if (mBoundSurface)
    {
        return true;
    }

    // Skip the renderability checks if it is set via glTexParameteri and current
    // context is less than GLES3. Note that we should not skip the check if the
    // texture is not renderable at all. Otherwise we would end up rendering to
    // textures like compressed textures that are not really renderable.
    if (context->getImplementation()
            ->getNativeTextureCaps()
            .get(getAttachmentFormat(binding, imageIndex).info->sizedInternalFormat)
            .textureAttachment &&
        !mState.renderabilityValidation() && context->getClientVersion() < ES_3_0)
    {
        return true;
    }

    return getAttachmentFormat(binding, imageIndex)
        .info->textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
}

bool Texture::getAttachmentFixedSampleLocations(const ImageIndex &imageIndex) const
{
    // We do not allow querying TextureTarget by an ImageIndex that represents an entire level of a
    // cube map (See comments in function TextureTypeToTarget() in ImageIndex.cpp).
    if (imageIndex.isEntireLevelCubeMap())
    {
        return true;
    }

    // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
    // the same for all attached textures.
    return getFixedSampleLocations(imageIndex.getTarget(), imageIndex.getLevelIndex());
}

void Texture::setBorderColor(const Context *context, const ColorGeneric &color)
{
    mState.mSamplerState.setBorderColor(color);
    signalDirtyState(DIRTY_BIT_BORDER_COLOR);
}

const ColorGeneric &Texture::getBorderColor() const
{
    return mState.mSamplerState.getBorderColor();
}

GLint Texture::getRequiredTextureImageUnits(const Context *context) const
{
    // Only external texture types can return non-1.
    if (mState.mType != TextureType::External)
    {
        return 1;
    }

    return mTexture->getRequiredExternalTextureImageUnits(context);
}

void Texture::setCrop(const Rectangle &rect)
{
    mState.setCrop(rect);
}

const Rectangle &Texture::getCrop() const
{
    return mState.getCrop();
}

void Texture::setGenerateMipmapHint(GLenum hint)
{
    mState.setGenerateMipmapHint(hint);
}

GLenum Texture::getGenerateMipmapHint() const
{
    return mState.getGenerateMipmapHint();
}

angle::Result Texture::setBuffer(const gl::Context *context,
                                 gl::Buffer *buffer,
                                 GLenum internalFormat)
{
    // Use 0 to indicate that the size is taken from whatever size the buffer has when the texture
    // buffer is used.
    return setBufferRange(context, buffer, internalFormat, 0, 0);
}

angle::Result Texture::setBufferRange(const gl::Context *context,
                                      gl::Buffer *buffer,
                                      GLenum internalFormat,
                                      GLintptr offset,
                                      GLsizeiptr size)
{
    mState.mImmutableFormat = true;
    mState.mBuffer.set(context, buffer, offset, size);
    ANGLE_TRY(mTexture->setBuffer(context, internalFormat));

    mState.clearImageDescs();
    if (buffer == nullptr)
    {
        mBufferObserver.reset();
        InitState initState = DetermineInitState(context, nullptr, nullptr);
        signalDirtyStorage(initState);
        return angle::Result::Continue;
    }

    size = GetBoundBufferAvailableSize(mState.mBuffer);

    mState.mImmutableLevels           = static_cast<GLuint>(1);
    InternalFormat internalFormatInfo = GetSizedInternalFormatInfo(internalFormat);
    Format format(internalFormat);
    Extents extents(static_cast<GLuint>(size / internalFormatInfo.pixelBytes), 1, 1);
    InitState initState = buffer->initState();
    mState.setImageDesc(TextureTarget::Buffer, 0, ImageDesc(extents, format, initState));

    signalDirtyStorage(initState);

    // Observe modifications to the buffer, so that extents can be updated.
    mBufferObserver.bind(buffer);

    return angle::Result::Continue;
}

const OffsetBindingPointer<Buffer> &Texture::getBuffer() const
{
    return mState.mBuffer;
}

void Texture::onAttach(const Context *context, rx::UniqueSerial framebufferSerial)
{
    addRef();

    // Duplicates allowed for multiple attachment points. See the comment in the header.
    mBoundFramebufferSerials.push_back(framebufferSerial);

    if (!mState.mHasBeenBoundAsAttachment)
    {
        mDirtyBits.set(DIRTY_BIT_BOUND_AS_ATTACHMENT);
        mState.mHasBeenBoundAsAttachment = true;
    }
}

void Texture::onDetach(const Context *context, rx::UniqueSerial framebufferSerial)
{
    // Erase first instance. If there are multiple bindings, leave the others.
    ASSERT(isBoundToFramebuffer(framebufferSerial));
    mBoundFramebufferSerials.remove_and_permute(framebufferSerial);

    release(context);
}

GLuint Texture::getId() const
{
    return id().value;
}

GLuint Texture::getNativeID() const
{
    return mTexture->getNativeID();
}

angle::Result Texture::syncState(const Context *context, Command source)
{
    ASSERT(hasAnyDirtyBit() || source == Command::GenerateMipmap);
    ANGLE_TRY(mTexture->syncState(context, mDirtyBits, source));
    mDirtyBits.reset();
    mState.mInitState = InitState::Initialized;
    return angle::Result::Continue;
}

rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
{
    return mTexture;
}

bool Texture::isSamplerComplete(const Context *context, const Sampler *optionalSampler)
{
    const auto &samplerState =
        optionalSampler ? optionalSampler->getSamplerState() : mState.mSamplerState;
    const auto &contextState = context->getState();

    if (contextState.getContextID() != mCompletenessCache.context ||
        !mCompletenessCache.samplerState.sameCompleteness(samplerState))
    {
        mCompletenessCache.context      = context->getState().getContextID();
        mCompletenessCache.samplerState = samplerState;
        mCompletenessCache.samplerComplete =
            mState.computeSamplerCompleteness(samplerState, contextState);
    }

    return mCompletenessCache.samplerComplete;
}

// CopyImageSubData requires that we ignore format-based completeness rules
bool Texture::isSamplerCompleteForCopyImage(const Context *context,
                                            const Sampler *optionalSampler) const
{
    const gl::SamplerState &samplerState =
        optionalSampler ? optionalSampler->getSamplerState() : mState.mSamplerState;
    const gl::State &contextState = context->getState();
    return mState.computeSamplerCompletenessForCopyImage(samplerState, contextState);
}

Texture::SamplerCompletenessCache::SamplerCompletenessCache()
    : context({0}), samplerState(), samplerComplete(false)
{}

void Texture::invalidateCompletenessCache() const
{
    mCompletenessCache.context = {0};
}

angle::Result Texture::ensureInitialized(const Context *context)
{
    if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
    {
        return angle::Result::Continue;
    }

    bool anyDirty = false;

    ImageIndexIterator it =
        ImageIndexIterator::MakeGeneric(mState.mType, 0, IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1,
                                        ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
    while (it.hasNext())
    {
        const ImageIndex index = it.next();
        ImageDesc &desc =
            mState.mImageDescs[GetImageDescIndex(index.getTarget(), index.getLevelIndex())];
        if (desc.initState == InitState::MayNeedInit && !desc.size.empty())
        {
            ASSERT(mState.mInitState == InitState::MayNeedInit);
            ANGLE_TRY(initializeContents(context, GL_NONE, index));
            desc.initState = InitState::Initialized;
            anyDirty       = true;
        }
    }
    if (anyDirty)
    {
        signalDirtyStorage(InitState::Initialized);
    }
    mState.mInitState = InitState::Initialized;

    return angle::Result::Continue;
}

InitState Texture::initState(GLenum /*binding*/, const ImageIndex &imageIndex) const
{
    // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
    // we need to check all the related ImageDescs.
    if (imageIndex.isEntireLevelCubeMap())
    {
        const GLint levelIndex = imageIndex.getLevelIndex();
        for (TextureTarget cubeFaceTarget : AllCubeFaceTextureTargets())
        {
            if (mState.getImageDesc(cubeFaceTarget, levelIndex).initState == InitState::MayNeedInit)
            {
                return InitState::MayNeedInit;
            }
        }
        return InitState::Initialized;
    }

    return mState.getImageDesc(imageIndex).initState;
}

void Texture::setInitState(GLenum binding, const ImageIndex &imageIndex, InitState initState)
{
    // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
    // we need to update all the related ImageDescs.
    if (imageIndex.isEntireLevelCubeMap())
    {
        const GLint levelIndex = imageIndex.getLevelIndex();
        for (TextureTarget cubeFaceTarget : AllCubeFaceTextureTargets())
        {
            setInitState(binding, ImageIndex::MakeCubeMapFace(cubeFaceTarget, levelIndex),
                         initState);
        }
    }
    else
    {
        ImageDesc newDesc = mState.getImageDesc(imageIndex);
        newDesc.initState = initState;
        mState.setImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex(), newDesc);
    }
}

void Texture::setInitState(InitState initState)
{
    for (ImageDesc &imageDesc : mState.mImageDescs)
    {
        // Only modify defined images, undefined images will remain in the initialized state
        if (!imageDesc.size.empty())
        {
            imageDesc.initState = initState;
        }
    }
    mState.mInitState = initState;
}

bool Texture::isEGLImageSource(const ImageIndex &index) const
{
    for (const egl::Image *sourceImage : getSiblingSourcesOf())
    {
        if (sourceImage->getSourceImageIndex() == index)
        {
            return true;
        }
    }
    return false;
}

bool Texture::doesSubImageNeedInit(const Context *context,
                                   const ImageIndex &imageIndex,
                                   const Box &area) const
{
    if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
    {
        return false;
    }

    // Pre-initialize the texture contents if necessary.
    const ImageDesc &desc = mState.getImageDesc(imageIndex);
    if (desc.initState != InitState::MayNeedInit)
    {
        return false;
    }

    ASSERT(mState.mInitState == InitState::MayNeedInit);
    return !area.coversSameExtent(desc.size);
}

angle::Result Texture::ensureSubImageInitialized(const Context *context,
                                                 const ImageIndex &imageIndex,
                                                 const Box &area)
{
    if (doesSubImageNeedInit(context, imageIndex, area))
    {
        // NOTE: do not optimize this to only initialize the passed area of the texture, or the
        // initialization logic in copySubImage will be incorrect.
        ANGLE_TRY(initializeContents(context, GL_NONE, imageIndex));
    }
    // Note: binding is ignored for textures.
    setInitState(GL_NONE, imageIndex, InitState::Initialized);
    return angle::Result::Continue;
}

angle::Result Texture::handleMipmapGenerationHint(Context *context, int level)
{
    if (getGenerateMipmapHint() == GL_TRUE && level == 0)
    {
        ANGLE_TRY(generateMipmap(context));
    }

    return angle::Result::Continue;
}

void Texture::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
    switch (message)
    {
        case angle::SubjectMessage::DirtyBitsFlagged:
            signalDirtyState(DIRTY_BIT_IMPLEMENTATION);

            // Notify siblings that we are dirty.
            if (index == rx::kTextureImageImplObserverMessageIndex)
            {
                notifySiblings(message);
            }
            break;
        case angle::SubjectMessage::SubjectChanged:
            mState.mInitState = InitState::MayNeedInit;
            signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
            onStateChange(angle::SubjectMessage::ContentsChanged);

            // Notify siblings that we are dirty.
            if (index == rx::kTextureImageImplObserverMessageIndex)
            {
                notifySiblings(message);
            }
            else if (index == kBufferSubjectIndex)
            {
                const gl::Buffer *buffer = mState.mBuffer.get();
                ASSERT(buffer != nullptr);

                // Update cached image desc based on buffer size.
                GLsizeiptr size = GetBoundBufferAvailableSize(mState.mBuffer);

                ImageDesc desc          = mState.getImageDesc(TextureTarget::Buffer, 0);
                const GLuint pixelBytes = desc.format.info->pixelBytes;
                desc.size.width         = static_cast<GLuint>(size / pixelBytes);

                mState.setImageDesc(TextureTarget::Buffer, 0, desc);
            }
            break;
        case angle::SubjectMessage::StorageReleased:
            // When the TextureStorage is released, it needs to update the
            // RenderTargetCache of the Framebuffer attaching this Texture.
            // This is currently only for D3D back-end. See http://crbug.com/1234829
            if (index == rx::kTextureImageImplObserverMessageIndex)
            {
                onStateChange(angle::SubjectMessage::StorageReleased);
            }
            break;
        case angle::SubjectMessage::SubjectMapped:
        case angle::SubjectMessage::SubjectUnmapped:
        case angle::SubjectMessage::BindingChanged:
        {
            ASSERT(index == kBufferSubjectIndex);
            gl::Buffer *buffer = mState.mBuffer.get();
            ASSERT(buffer != nullptr);
            if (buffer->hasContentsObserver(this))
            {
                onBufferContentsChange();
            }
        }
        break;
        case angle::SubjectMessage::InitializationComplete:
            ASSERT(index == rx::kTextureImageImplObserverMessageIndex);
            setInitState(InitState::Initialized);
            break;
        case angle::SubjectMessage::InternalMemoryAllocationChanged:
            // Need to mark the texture dirty to give the back end a chance to handle the new
            // buffer. For example, the Vulkan back end needs to create a new buffer view that
            // points to the newly allocated buffer and update the texture descriptor set.
            signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
            break;
        default:
            UNREACHABLE();
            break;
    }
}

void Texture::onBufferContentsChange()
{
    mState.mInitState = InitState::MayNeedInit;
    signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
    onStateChange(angle::SubjectMessage::ContentsChanged);
}

void Texture::onBindToMSRTTFramebuffer()
{
    mState.mHasBeenBoundToMSRTTFramebuffer = true;
}

GLenum Texture::getImplementationColorReadFormat(const Context *context) const
{
    return mTexture->getColorReadFormat(context);
}

GLenum Texture::getImplementationColorReadType(const Context *context) const
{
    return mTexture->getColorReadType(context);
}

angle::Result Texture::getTexImage(const Context *context,
                                   const PixelPackState &packState,
                                   Buffer *packBuffer,
                                   TextureTarget target,
                                   GLint level,
                                   GLenum format,
                                   GLenum type,
                                   void *pixels)
{
    // No-op if the image level is empty.
    if (getExtents(target, level).empty())
    {
        return angle::Result::Continue;
    }

    return mTexture->getTexImage(context, packState, packBuffer, target, level, format, type,
                                 pixels);
}

angle::Result Texture::getCompressedTexImage(const Context *context,
                                             const PixelPackState &packState,
                                             Buffer *packBuffer,
                                             TextureTarget target,
                                             GLint level,
                                             void *pixels)
{
    // No-op if the image level is empty.
    if (getExtents(target, level).empty())
    {
        return angle::Result::Continue;
    }

    return mTexture->getCompressedTexImage(context, packState, packBuffer, target, level, pixels);
}

void Texture::onBindAsImageTexture()
{
    if (!mState.mHasBeenBoundAsImage)
    {
        mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
        mState.mHasBeenBoundAsImage = true;
    }
}

void Texture::onBindAsEglImageSource()
{
    mState.mHasBeenBoundAsSourceOfEglImage = true;
}

}  // namespace gl
