tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Texture.cpp (85913B)


      1 //
      2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63.
      8 
      9 #include "libANGLE/Texture.h"
     10 
     11 #include "common/mathutil.h"
     12 #include "common/utilities.h"
     13 #include "libANGLE/Config.h"
     14 #include "libANGLE/Context.h"
     15 #include "libANGLE/Image.h"
     16 #include "libANGLE/State.h"
     17 #include "libANGLE/Surface.h"
     18 #include "libANGLE/formatutils.h"
     19 #include "libANGLE/renderer/GLImplFactory.h"
     20 #include "libANGLE/renderer/TextureImpl.h"
     21 
     22 namespace gl
     23 {
     24 
     25 namespace
     26 {
     27 constexpr angle::SubjectIndex kBufferSubjectIndex = 2;
     28 static_assert(kBufferSubjectIndex != rx::kTextureImageImplObserverMessageIndex, "Index collision");
     29 static_assert(kBufferSubjectIndex != rx::kTextureImageSiblingMessageIndex, "Index collision");
     30 
     31 bool IsPointSampled(const SamplerState &samplerState)
     32 {
     33    return (samplerState.getMagFilter() == GL_NEAREST &&
     34            (samplerState.getMinFilter() == GL_NEAREST ||
     35             samplerState.getMinFilter() == GL_NEAREST_MIPMAP_NEAREST));
     36 }
     37 
     38 size_t GetImageDescIndex(TextureTarget target, size_t level)
     39 {
     40    return IsCubeMapFaceTarget(target) ? (level * 6 + CubeMapTextureTargetToFaceIndex(target))
     41                                       : level;
     42 }
     43 
     44 InitState DetermineInitState(const Context *context, Buffer *unpackBuffer, const uint8_t *pixels)
     45 {
     46    // Can happen in tests.
     47    if (!context || !context->isRobustResourceInitEnabled())
     48    {
     49        return InitState::Initialized;
     50    }
     51 
     52    return (!pixels && !unpackBuffer) ? InitState::MayNeedInit : InitState::Initialized;
     53 }
     54 }  // namespace
     55 
     56 GLenum ConvertToNearestFilterMode(GLenum filterMode)
     57 {
     58    switch (filterMode)
     59    {
     60        case GL_LINEAR:
     61            return GL_NEAREST;
     62        case GL_LINEAR_MIPMAP_NEAREST:
     63            return GL_NEAREST_MIPMAP_NEAREST;
     64        case GL_LINEAR_MIPMAP_LINEAR:
     65            return GL_NEAREST_MIPMAP_LINEAR;
     66        default:
     67            return filterMode;
     68    }
     69 }
     70 
     71 GLenum ConvertToNearestMipFilterMode(GLenum filterMode)
     72 {
     73    switch (filterMode)
     74    {
     75        case GL_LINEAR_MIPMAP_LINEAR:
     76            return GL_LINEAR_MIPMAP_NEAREST;
     77        case GL_NEAREST_MIPMAP_LINEAR:
     78            return GL_NEAREST_MIPMAP_NEAREST;
     79        default:
     80            return filterMode;
     81    }
     82 }
     83 
     84 bool IsMipmapSupported(const TextureType &type)
     85 {
     86    if (type == TextureType::_2DMultisample || type == TextureType::Buffer)
     87    {
     88        return false;
     89    }
     90    return true;
     91 }
     92 
     93 SwizzleState::SwizzleState()
     94    : swizzleRed(GL_RED), swizzleGreen(GL_GREEN), swizzleBlue(GL_BLUE), swizzleAlpha(GL_ALPHA)
     95 {}
     96 
     97 SwizzleState::SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha)
     98    : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
     99 {}
    100 
    101 bool SwizzleState::swizzleRequired() const
    102 {
    103    return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || swizzleBlue != GL_BLUE ||
    104           swizzleAlpha != GL_ALPHA;
    105 }
    106 
    107 bool SwizzleState::operator==(const SwizzleState &other) const
    108 {
    109    return swizzleRed == other.swizzleRed && swizzleGreen == other.swizzleGreen &&
    110           swizzleBlue == other.swizzleBlue && swizzleAlpha == other.swizzleAlpha;
    111 }
    112 
    113 bool SwizzleState::operator!=(const SwizzleState &other) const
    114 {
    115    return !(*this == other);
    116 }
    117 
    118 TextureState::TextureState(TextureType type)
    119    : mType(type),
    120      mSamplerState(SamplerState::CreateDefaultForTarget(type)),
    121      mSrgbOverride(SrgbOverride::Default),
    122      mBaseLevel(0),
    123      mMaxLevel(kInitialMaxLevel),
    124      mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
    125      mHasBeenBoundAsImage(false),
    126      mIs3DAndHasBeenBoundAs2DImage(false),
    127      mHasBeenBoundAsAttachment(false),
    128      mImmutableFormat(false),
    129      mImmutableLevels(0),
    130      mUsage(GL_NONE),
    131      mHasProtectedContent(false),
    132      mImageDescs((IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) * (type == TextureType::CubeMap ? 6 : 1)),
    133      mCropRect(0, 0, 0, 0),
    134      mGenerateMipmapHint(GL_FALSE),
    135      mInitState(InitState::Initialized),
    136      mCachedSamplerFormat(SamplerFormat::InvalidEnum),
    137      mCachedSamplerCompareMode(GL_NONE),
    138      mCachedSamplerFormatValid(false)
    139 {}
    140 
    141 TextureState::~TextureState() {}
    142 
    143 bool TextureState::swizzleRequired() const
    144 {
    145    return mSwizzleState.swizzleRequired();
    146 }
    147 
    148 GLuint TextureState::getEffectiveBaseLevel() const
    149 {
    150    if (mImmutableFormat)
    151    {
    152        // GLES 3.0.4 section 3.8.10
    153        return std::min(mBaseLevel, mImmutableLevels - 1);
    154    }
    155    // Some classes use the effective base level to index arrays with level data. By clamping the
    156    // effective base level to max levels these arrays need just one extra item to store properties
    157    // that should be returned for all out-of-range base level values, instead of needing special
    158    // handling for out-of-range base levels.
    159    return std::min(mBaseLevel, static_cast<GLuint>(IMPLEMENTATION_MAX_TEXTURE_LEVELS));
    160 }
    161 
    162 GLuint TextureState::getEffectiveMaxLevel() const
    163 {
    164    if (mImmutableFormat)
    165    {
    166        // GLES 3.0.4 section 3.8.10
    167        GLuint clampedMaxLevel = std::max(mMaxLevel, getEffectiveBaseLevel());
    168        clampedMaxLevel        = std::min(clampedMaxLevel, mImmutableLevels - 1);
    169        return clampedMaxLevel;
    170    }
    171    return mMaxLevel;
    172 }
    173 
    174 GLuint TextureState::getMipmapMaxLevel() const
    175 {
    176    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
    177    GLuint expectedMipLevels       = 0;
    178    if (mType == TextureType::_3D)
    179    {
    180        const int maxDim  = std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height),
    181                                     baseImageDesc.size.depth);
    182        expectedMipLevels = static_cast<GLuint>(log2(maxDim));
    183    }
    184    else
    185    {
    186        expectedMipLevels = static_cast<GLuint>(
    187            log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)));
    188    }
    189 
    190    return std::min<GLuint>(getEffectiveBaseLevel() + expectedMipLevels, getEffectiveMaxLevel());
    191 }
    192 
    193 bool TextureState::setBaseLevel(GLuint baseLevel)
    194 {
    195    if (mBaseLevel != baseLevel)
    196    {
    197        mBaseLevel = baseLevel;
    198        return true;
    199    }
    200    return false;
    201 }
    202 
    203 bool TextureState::setMaxLevel(GLuint maxLevel)
    204 {
    205    if (mMaxLevel != maxLevel)
    206    {
    207        mMaxLevel = maxLevel;
    208        return true;
    209    }
    210 
    211    return false;
    212 }
    213 
    214 // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
    215 // According to [OpenGL ES 3.0.5] section 3.8.13 Texture Completeness page 160 any
    216 // per-level checks begin at the base-level.
    217 // For OpenGL ES2 the base level is always zero.
    218 bool TextureState::isCubeComplete() const
    219 {
    220    ASSERT(mType == TextureType::CubeMap);
    221 
    222    angle::EnumIterator<TextureTarget> face = kCubeMapTextureTargetMin;
    223    const ImageDesc &baseImageDesc          = getImageDesc(*face, getEffectiveBaseLevel());
    224    if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
    225    {
    226        return false;
    227    }
    228 
    229    ++face;
    230 
    231    for (; face != kAfterCubeMapTextureTargetMax; ++face)
    232    {
    233        const ImageDesc &faceImageDesc = getImageDesc(*face, getEffectiveBaseLevel());
    234        if (faceImageDesc.size.width != baseImageDesc.size.width ||
    235            faceImageDesc.size.height != baseImageDesc.size.height ||
    236            !Format::SameSized(faceImageDesc.format, baseImageDesc.format))
    237        {
    238            return false;
    239        }
    240    }
    241 
    242    return true;
    243 }
    244 
    245 const ImageDesc &TextureState::getBaseLevelDesc() const
    246 {
    247    ASSERT(mType != TextureType::CubeMap || isCubeComplete());
    248    return getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
    249 }
    250 
    251 const ImageDesc &TextureState::getLevelZeroDesc() const
    252 {
    253    ASSERT(mType != TextureType::CubeMap || isCubeComplete());
    254    return getImageDesc(getBaseImageTarget(), 0);
    255 }
    256 
    257 void TextureState::setCrop(const Rectangle &rect)
    258 {
    259    mCropRect = rect;
    260 }
    261 
    262 const Rectangle &TextureState::getCrop() const
    263 {
    264    return mCropRect;
    265 }
    266 
    267 void TextureState::setGenerateMipmapHint(GLenum hint)
    268 {
    269    mGenerateMipmapHint = hint;
    270 }
    271 
    272 GLenum TextureState::getGenerateMipmapHint() const
    273 {
    274    return mGenerateMipmapHint;
    275 }
    276 
    277 SamplerFormat TextureState::computeRequiredSamplerFormat(const SamplerState &samplerState) const
    278 {
    279    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
    280    if ((baseImageDesc.format.info->format == GL_DEPTH_COMPONENT ||
    281         baseImageDesc.format.info->format == GL_DEPTH_STENCIL) &&
    282        samplerState.getCompareMode() != GL_NONE)
    283    {
    284        return SamplerFormat::Shadow;
    285    }
    286    else
    287    {
    288        switch (baseImageDesc.format.info->componentType)
    289        {
    290            case GL_UNSIGNED_NORMALIZED:
    291            case GL_SIGNED_NORMALIZED:
    292            case GL_FLOAT:
    293                return SamplerFormat::Float;
    294            case GL_INT:
    295                return SamplerFormat::Signed;
    296            case GL_UNSIGNED_INT:
    297                return SamplerFormat::Unsigned;
    298            default:
    299                return SamplerFormat::InvalidEnum;
    300        }
    301    }
    302 }
    303 
    304 bool TextureState::computeSamplerCompleteness(const SamplerState &samplerState,
    305                                              const State &state) const
    306 {
    307    // Buffer textures cannot be incomplete.
    308    if (mType == TextureType::Buffer)
    309    {
    310        return true;
    311    }
    312 
    313    // Check for all non-format-based completeness rules
    314    if (!computeSamplerCompletenessForCopyImage(samplerState, state))
    315    {
    316        return false;
    317    }
    318 
    319    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
    320 
    321    // According to es 3.1 spec, texture is justified as incomplete if sized internalformat is
    322    // unfilterable(table 20.11) and filter is not GL_NEAREST(8.16). The default value of minFilter
    323    // is NEAREST_MIPMAP_LINEAR and magFilter is LINEAR(table 20.11,). For multismaple texture,
    324    // filter state of multisample texture is ignored(11.1.3.3). So it shouldn't be judged as
    325    // incomplete texture. So, we ignore filtering for multisample texture completeness here.
    326    if (!IsMultisampled(mType) &&
    327        !baseImageDesc.format.info->filterSupport(state.getClientVersion(),
    328                                                  state.getExtensions()) &&
    329        !IsPointSampled(samplerState))
    330    {
    331        return false;
    332    }
    333 
    334    // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
    335    // The internalformat specified for the texture arrays is a sized internal depth or
    336    // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
    337    // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
    338    // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
    339    if (!IsMultisampled(mType) && baseImageDesc.format.info->depthBits > 0 &&
    340        state.getClientMajorVersion() >= 3)
    341    {
    342        // Note: we restrict this validation to sized types. For the OES_depth_textures
    343        // extension, due to some underspecification problems, we must allow linear filtering
    344        // for legacy compatibility with WebGL 1.
    345        // See http://crbug.com/649200
    346        if (samplerState.getCompareMode() == GL_NONE && baseImageDesc.format.info->sized)
    347        {
    348            if ((samplerState.getMinFilter() != GL_NEAREST &&
    349                 samplerState.getMinFilter() != GL_NEAREST_MIPMAP_NEAREST) ||
    350                samplerState.getMagFilter() != GL_NEAREST)
    351            {
    352                return false;
    353            }
    354        }
    355    }
    356 
    357    // OpenGLES 3.1 spec section 8.16 states that a texture is not mipmap complete if:
    358    // The internalformat specified for the texture is DEPTH_STENCIL format, the value of
    359    // DEPTH_STENCIL_TEXTURE_MODE is STENCIL_INDEX, and either the magnification filter is
    360    // not NEAREST or the minification filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
    361    // However, the ES 3.1 spec differs from the statement above, because it is incorrect.
    362    // See the issue at https://github.com/KhronosGroup/OpenGL-API/issues/33.
    363    // For multismaple texture, filter state of multisample texture is ignored(11.1.3.3).
    364    // So it shouldn't be judged as incomplete texture. So, we ignore filtering for multisample
    365    // texture completeness here.
    366    if (!IsMultisampled(mType) && baseImageDesc.format.info->depthBits > 0 &&
    367        mDepthStencilTextureMode == GL_STENCIL_INDEX)
    368    {
    369        if ((samplerState.getMinFilter() != GL_NEAREST &&
    370             samplerState.getMinFilter() != GL_NEAREST_MIPMAP_NEAREST) ||
    371            samplerState.getMagFilter() != GL_NEAREST)
    372        {
    373            return false;
    374        }
    375    }
    376 
    377    return true;
    378 }
    379 
    380 // CopyImageSubData has more lax rules for texture completeness: format-based completeness rules are
    381 // ignored, so a texture can still be considered complete even if it violates format-specific
    382 // conditions
    383 bool TextureState::computeSamplerCompletenessForCopyImage(const SamplerState &samplerState,
    384                                                          const State &state) const
    385 {
    386    // Buffer textures cannot be incomplete.
    387    if (mType == TextureType::Buffer)
    388    {
    389        return true;
    390    }
    391 
    392    if (!mImmutableFormat && mBaseLevel > mMaxLevel)
    393    {
    394        return false;
    395    }
    396    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
    397    if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
    398        baseImageDesc.size.depth == 0)
    399    {
    400        return false;
    401    }
    402    // The cases where the texture is incomplete because base level is out of range should be
    403    // handled by the above condition.
    404    ASSERT(mBaseLevel < IMPLEMENTATION_MAX_TEXTURE_LEVELS || mImmutableFormat);
    405 
    406    if (mType == TextureType::CubeMap && baseImageDesc.size.width != baseImageDesc.size.height)
    407    {
    408        return false;
    409    }
    410 
    411    bool npotSupport = state.getExtensions().textureNpotOES || state.getClientMajorVersion() >= 3;
    412    if (!npotSupport)
    413    {
    414        if ((samplerState.getWrapS() != GL_CLAMP_TO_EDGE &&
    415             samplerState.getWrapS() != GL_CLAMP_TO_BORDER && !isPow2(baseImageDesc.size.width)) ||
    416            (samplerState.getWrapT() != GL_CLAMP_TO_EDGE &&
    417             samplerState.getWrapT() != GL_CLAMP_TO_BORDER && !isPow2(baseImageDesc.size.height)))
    418        {
    419            return false;
    420        }
    421    }
    422 
    423    if (IsMipmapSupported(mType) && IsMipmapFiltered(samplerState.getMinFilter()))
    424    {
    425        if (!npotSupport)
    426        {
    427            if (!isPow2(baseImageDesc.size.width) || !isPow2(baseImageDesc.size.height))
    428            {
    429                return false;
    430            }
    431        }
    432 
    433        if (!computeMipmapCompleteness())
    434        {
    435            return false;
    436        }
    437    }
    438    else
    439    {
    440        if (mType == TextureType::CubeMap && !isCubeComplete())
    441        {
    442            return false;
    443        }
    444    }
    445 
    446    // From GL_OES_EGL_image_external_essl3: If state is present in a sampler object bound to a
    447    // texture unit that would have been rejected by a call to TexParameter* for the texture bound
    448    // to that unit, the behavior of the implementation is as if the texture were incomplete. For
    449    // example, if TEXTURE_WRAP_S or TEXTURE_WRAP_T is set to anything but CLAMP_TO_EDGE on the
    450    // sampler object bound to a texture unit and the texture bound to that unit is an external
    451    // texture and EXT_EGL_image_external_wrap_modes is not enabled, the texture will be considered
    452    // incomplete.
    453    // Sampler object state which does not affect sampling for the type of texture bound
    454    // to a texture unit, such as TEXTURE_WRAP_R for an external texture, does not affect
    455    // completeness.
    456    if (mType == TextureType::External)
    457    {
    458        if (!state.getExtensions().EGLImageExternalWrapModesEXT)
    459        {
    460            if (samplerState.getWrapS() != GL_CLAMP_TO_EDGE ||
    461                samplerState.getWrapT() != GL_CLAMP_TO_EDGE)
    462            {
    463                return false;
    464            }
    465        }
    466 
    467        if (samplerState.getMinFilter() != GL_LINEAR && samplerState.getMinFilter() != GL_NEAREST)
    468        {
    469            return false;
    470        }
    471    }
    472 
    473    return true;
    474 }
    475 
    476 bool TextureState::computeMipmapCompleteness() const
    477 {
    478    const GLuint maxLevel = getMipmapMaxLevel();
    479 
    480    for (GLuint level = getEffectiveBaseLevel(); level <= maxLevel; level++)
    481    {
    482        if (mType == TextureType::CubeMap)
    483        {
    484            for (TextureTarget face : AllCubeFaceTextureTargets())
    485            {
    486                if (!computeLevelCompleteness(face, level))
    487                {
    488                    return false;
    489                }
    490            }
    491        }
    492        else
    493        {
    494            if (!computeLevelCompleteness(NonCubeTextureTypeToTarget(mType), level))
    495            {
    496                return false;
    497            }
    498        }
    499    }
    500 
    501    return true;
    502 }
    503 
    504 bool TextureState::computeLevelCompleteness(TextureTarget target, size_t level) const
    505 {
    506    ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    507 
    508    if (mImmutableFormat)
    509    {
    510        return true;
    511    }
    512 
    513    const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
    514    if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
    515        baseImageDesc.size.depth == 0)
    516    {
    517        return false;
    518    }
    519 
    520    const ImageDesc &levelImageDesc = getImageDesc(target, level);
    521    if (levelImageDesc.size.width == 0 || levelImageDesc.size.height == 0 ||
    522        levelImageDesc.size.depth == 0)
    523    {
    524        return false;
    525    }
    526 
    527    if (!Format::SameSized(levelImageDesc.format, baseImageDesc.format))
    528    {
    529        return false;
    530    }
    531 
    532    ASSERT(level >= getEffectiveBaseLevel());
    533    const size_t relativeLevel = level - getEffectiveBaseLevel();
    534    if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> relativeLevel))
    535    {
    536        return false;
    537    }
    538 
    539    if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> relativeLevel))
    540    {
    541        return false;
    542    }
    543 
    544    if (mType == TextureType::_3D)
    545    {
    546        if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> relativeLevel))
    547        {
    548            return false;
    549        }
    550    }
    551    else if (IsArrayTextureType(mType))
    552    {
    553        if (levelImageDesc.size.depth != baseImageDesc.size.depth)
    554        {
    555            return false;
    556        }
    557    }
    558 
    559    return true;
    560 }
    561 
    562 TextureTarget TextureState::getBaseImageTarget() const
    563 {
    564    return mType == TextureType::CubeMap ? kCubeMapTextureTargetMin
    565                                         : NonCubeTextureTypeToTarget(mType);
    566 }
    567 
    568 GLuint TextureState::getEnabledLevelCount() const
    569 {
    570    GLuint levelCount      = 0;
    571    const GLuint baseLevel = getEffectiveBaseLevel();
    572    const GLuint maxLevel  = std::min(getEffectiveMaxLevel(), getMipmapMaxLevel());
    573 
    574    // The mip chain will have either one or more sequential levels, or max levels,
    575    // but not a sparse one.
    576    Optional<Extents> expectedSize;
    577    for (size_t enabledLevel = baseLevel; enabledLevel <= maxLevel; ++enabledLevel, ++levelCount)
    578    {
    579        // Note: for cube textures, we only check the first face.
    580        TextureTarget target     = TextureTypeToTarget(mType, 0);
    581        size_t descIndex         = GetImageDescIndex(target, enabledLevel);
    582        const Extents &levelSize = mImageDescs[descIndex].size;
    583 
    584        if (levelSize.empty())
    585        {
    586            break;
    587        }
    588        if (expectedSize.valid())
    589        {
    590            Extents newSize = expectedSize.value();
    591            newSize.width   = std::max(1, newSize.width >> 1);
    592            newSize.height  = std::max(1, newSize.height >> 1);
    593 
    594            if (!IsArrayTextureType(mType))
    595            {
    596                newSize.depth = std::max(1, newSize.depth >> 1);
    597            }
    598 
    599            if (newSize != levelSize)
    600            {
    601                break;
    602            }
    603        }
    604        expectedSize = levelSize;
    605    }
    606 
    607    return levelCount;
    608 }
    609 
    610 ImageDesc::ImageDesc()
    611    : ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized)
    612 {}
    613 
    614 ImageDesc::ImageDesc(const Extents &size, const Format &format, const InitState initState)
    615    : size(size), format(format), samples(0), fixedSampleLocations(GL_TRUE), initState(initState)
    616 {}
    617 
    618 ImageDesc::ImageDesc(const Extents &size,
    619                     const Format &format,
    620                     const GLsizei samples,
    621                     const bool fixedSampleLocations,
    622                     const InitState initState)
    623    : size(size),
    624      format(format),
    625      samples(samples),
    626      fixedSampleLocations(fixedSampleLocations),
    627      initState(initState)
    628 {}
    629 
    630 GLint ImageDesc::getMemorySize() const
    631 {
    632    // Assume allocated size is around width * height * depth * samples * pixelBytes
    633    angle::CheckedNumeric<GLint> levelSize = 1;
    634    levelSize *= format.info->pixelBytes;
    635    levelSize *= size.width;
    636    levelSize *= size.height;
    637    levelSize *= size.depth;
    638    levelSize *= std::max(samples, 1);
    639    return levelSize.ValueOrDefault(std::numeric_limits<GLint>::max());
    640 }
    641 
    642 const ImageDesc &TextureState::getImageDesc(TextureTarget target, size_t level) const
    643 {
    644    size_t descIndex = GetImageDescIndex(target, level);
    645    ASSERT(descIndex < mImageDescs.size());
    646    return mImageDescs[descIndex];
    647 }
    648 
    649 void TextureState::setImageDesc(TextureTarget target, size_t level, const ImageDesc &desc)
    650 {
    651    size_t descIndex = GetImageDescIndex(target, level);
    652    ASSERT(descIndex < mImageDescs.size());
    653    mImageDescs[descIndex] = desc;
    654    if (desc.initState == InitState::MayNeedInit)
    655    {
    656        mInitState = InitState::MayNeedInit;
    657    }
    658    else
    659    {
    660        // Scan for any uninitialized images. If there are none, set the init state of the entire
    661        // texture to initialized. The cost of the scan is only paid after doing image
    662        // initialization which is already very expensive.
    663        bool allImagesInitialized = true;
    664 
    665        for (const ImageDesc &initDesc : mImageDescs)
    666        {
    667            if (initDesc.initState == InitState::MayNeedInit)
    668            {
    669                allImagesInitialized = false;
    670                break;
    671            }
    672        }
    673 
    674        if (allImagesInitialized)
    675        {
    676            mInitState = InitState::Initialized;
    677        }
    678    }
    679 }
    680 
    681 // Note that an ImageIndex that represents an entire level of a cube map corresponds to 6
    682 // ImageDescs, so if the cube map is cube complete, we return the ImageDesc of the first cube
    683 // face, and we don't allow using this function when the cube map is not cube complete.
    684 const ImageDesc &TextureState::getImageDesc(const ImageIndex &imageIndex) const
    685 {
    686    if (imageIndex.isEntireLevelCubeMap())
    687    {
    688        ASSERT(isCubeComplete());
    689        const GLint levelIndex = imageIndex.getLevelIndex();
    690        return getImageDesc(kCubeMapTextureTargetMin, levelIndex);
    691    }
    692 
    693    return getImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex());
    694 }
    695 
    696 void TextureState::setImageDescChain(GLuint baseLevel,
    697                                     GLuint maxLevel,
    698                                     Extents baseSize,
    699                                     const Format &format,
    700                                     InitState initState)
    701 {
    702    for (GLuint level = baseLevel; level <= maxLevel; level++)
    703    {
    704        int relativeLevel = (level - baseLevel);
    705        Extents levelSize(std::max<int>(baseSize.width >> relativeLevel, 1),
    706                          std::max<int>(baseSize.height >> relativeLevel, 1),
    707                          (IsArrayTextureType(mType))
    708                              ? baseSize.depth
    709                              : std::max<int>(baseSize.depth >> relativeLevel, 1));
    710        ImageDesc levelInfo(levelSize, format, initState);
    711 
    712        if (mType == TextureType::CubeMap)
    713        {
    714            for (TextureTarget face : AllCubeFaceTextureTargets())
    715            {
    716                setImageDesc(face, level, levelInfo);
    717            }
    718        }
    719        else
    720        {
    721            setImageDesc(NonCubeTextureTypeToTarget(mType), level, levelInfo);
    722        }
    723    }
    724 }
    725 
    726 void TextureState::setImageDescChainMultisample(Extents baseSize,
    727                                                const Format &format,
    728                                                GLsizei samples,
    729                                                bool fixedSampleLocations,
    730                                                InitState initState)
    731 {
    732    ASSERT(mType == TextureType::_2DMultisample || mType == TextureType::_2DMultisampleArray);
    733    ImageDesc levelInfo(baseSize, format, samples, fixedSampleLocations, initState);
    734    setImageDesc(NonCubeTextureTypeToTarget(mType), 0, levelInfo);
    735 }
    736 
    737 void TextureState::clearImageDesc(TextureTarget target, size_t level)
    738 {
    739    setImageDesc(target, level, ImageDesc());
    740 }
    741 
    742 void TextureState::clearImageDescs()
    743 {
    744    for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
    745    {
    746        mImageDescs[descIndex] = ImageDesc();
    747    }
    748 }
    749 
    750 Texture::Texture(rx::GLImplFactory *factory, TextureID id, TextureType type)
    751    : RefCountObject(factory->generateSerial(), id),
    752      mState(type),
    753      mTexture(factory->createTexture(mState)),
    754      mImplObserver(this, rx::kTextureImageImplObserverMessageIndex),
    755      mBufferObserver(this, kBufferSubjectIndex),
    756      mBoundSurface(nullptr),
    757      mBoundStream(nullptr)
    758 {
    759    mImplObserver.bind(mTexture);
    760 
    761    // Initially assume the implementation is dirty.
    762    mDirtyBits.set(DIRTY_BIT_IMPLEMENTATION);
    763 }
    764 
    765 void Texture::onDestroy(const Context *context)
    766 {
    767    if (mBoundSurface)
    768    {
    769        ANGLE_SWALLOW_ERR(mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER));
    770        mBoundSurface = nullptr;
    771    }
    772    if (mBoundStream)
    773    {
    774        mBoundStream->releaseTextures();
    775        mBoundStream = nullptr;
    776    }
    777 
    778    egl::RefCountObjectReleaser<egl::Image> releaseImage;
    779    (void)orphanImages(context, &releaseImage);
    780 
    781    mState.mBuffer.set(context, nullptr, 0, 0);
    782 
    783    if (mTexture)
    784    {
    785        mTexture->onDestroy(context);
    786    }
    787 }
    788 
    789 Texture::~Texture()
    790 {
    791    SafeDelete(mTexture);
    792 }
    793 
    794 angle::Result Texture::setLabel(const Context *context, const std::string &label)
    795 {
    796    mState.mLabel = label;
    797    return mTexture->onLabelUpdate(context);
    798 }
    799 
    800 const std::string &Texture::getLabel() const
    801 {
    802    return mState.mLabel;
    803 }
    804 
    805 void Texture::setSwizzleRed(const Context *context, GLenum swizzleRed)
    806 {
    807    if (mState.mSwizzleState.swizzleRed != swizzleRed)
    808    {
    809        mState.mSwizzleState.swizzleRed = swizzleRed;
    810        signalDirtyState(DIRTY_BIT_SWIZZLE_RED);
    811    }
    812 }
    813 
    814 GLenum Texture::getSwizzleRed() const
    815 {
    816    return mState.mSwizzleState.swizzleRed;
    817 }
    818 
    819 void Texture::setSwizzleGreen(const Context *context, GLenum swizzleGreen)
    820 {
    821    if (mState.mSwizzleState.swizzleGreen != swizzleGreen)
    822    {
    823        mState.mSwizzleState.swizzleGreen = swizzleGreen;
    824        signalDirtyState(DIRTY_BIT_SWIZZLE_GREEN);
    825    }
    826 }
    827 
    828 GLenum Texture::getSwizzleGreen() const
    829 {
    830    return mState.mSwizzleState.swizzleGreen;
    831 }
    832 
    833 void Texture::setSwizzleBlue(const Context *context, GLenum swizzleBlue)
    834 {
    835    if (mState.mSwizzleState.swizzleBlue != swizzleBlue)
    836    {
    837        mState.mSwizzleState.swizzleBlue = swizzleBlue;
    838        signalDirtyState(DIRTY_BIT_SWIZZLE_BLUE);
    839    }
    840 }
    841 
    842 GLenum Texture::getSwizzleBlue() const
    843 {
    844    return mState.mSwizzleState.swizzleBlue;
    845 }
    846 
    847 void Texture::setSwizzleAlpha(const Context *context, GLenum swizzleAlpha)
    848 {
    849    if (mState.mSwizzleState.swizzleAlpha != swizzleAlpha)
    850    {
    851        mState.mSwizzleState.swizzleAlpha = swizzleAlpha;
    852        signalDirtyState(DIRTY_BIT_SWIZZLE_ALPHA);
    853    }
    854 }
    855 
    856 GLenum Texture::getSwizzleAlpha() const
    857 {
    858    return mState.mSwizzleState.swizzleAlpha;
    859 }
    860 
    861 void Texture::setMinFilter(const Context *context, GLenum minFilter)
    862 {
    863    if (mState.mSamplerState.setMinFilter(minFilter))
    864    {
    865        signalDirtyState(DIRTY_BIT_MIN_FILTER);
    866    }
    867 }
    868 
    869 GLenum Texture::getMinFilter() const
    870 {
    871    return mState.mSamplerState.getMinFilter();
    872 }
    873 
    874 void Texture::setMagFilter(const Context *context, GLenum magFilter)
    875 {
    876    if (mState.mSamplerState.setMagFilter(magFilter))
    877    {
    878        signalDirtyState(DIRTY_BIT_MAG_FILTER);
    879    }
    880 }
    881 
    882 GLenum Texture::getMagFilter() const
    883 {
    884    return mState.mSamplerState.getMagFilter();
    885 }
    886 
    887 void Texture::setWrapS(const Context *context, GLenum wrapS)
    888 {
    889    if (mState.mSamplerState.setWrapS(wrapS))
    890    {
    891        signalDirtyState(DIRTY_BIT_WRAP_S);
    892    }
    893 }
    894 
    895 GLenum Texture::getWrapS() const
    896 {
    897    return mState.mSamplerState.getWrapS();
    898 }
    899 
    900 void Texture::setWrapT(const Context *context, GLenum wrapT)
    901 {
    902    if (mState.mSamplerState.getWrapT() == wrapT)
    903        return;
    904    if (mState.mSamplerState.setWrapT(wrapT))
    905    {
    906        signalDirtyState(DIRTY_BIT_WRAP_T);
    907    }
    908 }
    909 
    910 GLenum Texture::getWrapT() const
    911 {
    912    return mState.mSamplerState.getWrapT();
    913 }
    914 
    915 void Texture::setWrapR(const Context *context, GLenum wrapR)
    916 {
    917    if (mState.mSamplerState.setWrapR(wrapR))
    918    {
    919        signalDirtyState(DIRTY_BIT_WRAP_R);
    920    }
    921 }
    922 
    923 GLenum Texture::getWrapR() const
    924 {
    925    return mState.mSamplerState.getWrapR();
    926 }
    927 
    928 void Texture::setMaxAnisotropy(const Context *context, float maxAnisotropy)
    929 {
    930    if (mState.mSamplerState.setMaxAnisotropy(maxAnisotropy))
    931    {
    932        signalDirtyState(DIRTY_BIT_MAX_ANISOTROPY);
    933    }
    934 }
    935 
    936 float Texture::getMaxAnisotropy() const
    937 {
    938    return mState.mSamplerState.getMaxAnisotropy();
    939 }
    940 
    941 void Texture::setMinLod(const Context *context, GLfloat minLod)
    942 {
    943    if (mState.mSamplerState.setMinLod(minLod))
    944    {
    945        signalDirtyState(DIRTY_BIT_MIN_LOD);
    946    }
    947 }
    948 
    949 GLfloat Texture::getMinLod() const
    950 {
    951    return mState.mSamplerState.getMinLod();
    952 }
    953 
    954 void Texture::setMaxLod(const Context *context, GLfloat maxLod)
    955 {
    956    if (mState.mSamplerState.setMaxLod(maxLod))
    957    {
    958        signalDirtyState(DIRTY_BIT_MAX_LOD);
    959    }
    960 }
    961 
    962 GLfloat Texture::getMaxLod() const
    963 {
    964    return mState.mSamplerState.getMaxLod();
    965 }
    966 
    967 void Texture::setCompareMode(const Context *context, GLenum compareMode)
    968 {
    969    if (mState.mSamplerState.setCompareMode(compareMode))
    970    {
    971        signalDirtyState(DIRTY_BIT_COMPARE_MODE);
    972    }
    973 }
    974 
    975 GLenum Texture::getCompareMode() const
    976 {
    977    return mState.mSamplerState.getCompareMode();
    978 }
    979 
    980 void Texture::setCompareFunc(const Context *context, GLenum compareFunc)
    981 {
    982    if (mState.mSamplerState.setCompareFunc(compareFunc))
    983    {
    984        signalDirtyState(DIRTY_BIT_COMPARE_FUNC);
    985    }
    986 }
    987 
    988 GLenum Texture::getCompareFunc() const
    989 {
    990    return mState.mSamplerState.getCompareFunc();
    991 }
    992 
    993 void Texture::setSRGBDecode(const Context *context, GLenum sRGBDecode)
    994 {
    995    if (mState.mSamplerState.setSRGBDecode(sRGBDecode))
    996    {
    997        signalDirtyState(DIRTY_BIT_SRGB_DECODE);
    998    }
    999 }
   1000 
   1001 GLenum Texture::getSRGBDecode() const
   1002 {
   1003    return mState.mSamplerState.getSRGBDecode();
   1004 }
   1005 
   1006 void Texture::setSRGBOverride(const Context *context, GLenum sRGBOverride)
   1007 {
   1008    SrgbOverride oldOverride = mState.mSrgbOverride;
   1009    mState.mSrgbOverride = (sRGBOverride == GL_SRGB) ? SrgbOverride::SRGB : SrgbOverride::Default;
   1010    if (mState.mSrgbOverride != oldOverride)
   1011    {
   1012        signalDirtyState(DIRTY_BIT_SRGB_OVERRIDE);
   1013    }
   1014 }
   1015 
   1016 GLenum Texture::getSRGBOverride() const
   1017 {
   1018    return (mState.mSrgbOverride == SrgbOverride::SRGB) ? GL_SRGB : GL_NONE;
   1019 }
   1020 
   1021 const SamplerState &Texture::getSamplerState() const
   1022 {
   1023    return mState.mSamplerState;
   1024 }
   1025 
   1026 angle::Result Texture::setBaseLevel(const Context *context, GLuint baseLevel)
   1027 {
   1028    if (mState.setBaseLevel(baseLevel))
   1029    {
   1030        ANGLE_TRY(mTexture->setBaseLevel(context, mState.getEffectiveBaseLevel()));
   1031        signalDirtyState(DIRTY_BIT_BASE_LEVEL);
   1032    }
   1033 
   1034    return angle::Result::Continue;
   1035 }
   1036 
   1037 GLuint Texture::getBaseLevel() const
   1038 {
   1039    return mState.mBaseLevel;
   1040 }
   1041 
   1042 void Texture::setMaxLevel(const Context *context, GLuint maxLevel)
   1043 {
   1044    if (mState.setMaxLevel(maxLevel))
   1045    {
   1046        signalDirtyState(DIRTY_BIT_MAX_LEVEL);
   1047    }
   1048 }
   1049 
   1050 GLuint Texture::getMaxLevel() const
   1051 {
   1052    return mState.mMaxLevel;
   1053 }
   1054 
   1055 void Texture::setDepthStencilTextureMode(const Context *context, GLenum mode)
   1056 {
   1057    if (mState.mDepthStencilTextureMode != mode)
   1058    {
   1059        mState.mDepthStencilTextureMode = mode;
   1060        signalDirtyState(DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE);
   1061    }
   1062 }
   1063 
   1064 GLenum Texture::getDepthStencilTextureMode() const
   1065 {
   1066    return mState.mDepthStencilTextureMode;
   1067 }
   1068 
   1069 bool Texture::getImmutableFormat() const
   1070 {
   1071    return mState.mImmutableFormat;
   1072 }
   1073 
   1074 GLuint Texture::getImmutableLevels() const
   1075 {
   1076    return mState.mImmutableLevels;
   1077 }
   1078 
   1079 void Texture::setUsage(const Context *context, GLenum usage)
   1080 {
   1081    mState.mUsage = usage;
   1082    signalDirtyState(DIRTY_BIT_USAGE);
   1083 }
   1084 
   1085 GLenum Texture::getUsage() const
   1086 {
   1087    return mState.mUsage;
   1088 }
   1089 
   1090 void Texture::setProtectedContent(Context *context, bool hasProtectedContent)
   1091 {
   1092    mState.mHasProtectedContent = hasProtectedContent;
   1093 }
   1094 
   1095 bool Texture::hasProtectedContent() const
   1096 {
   1097    return mState.mHasProtectedContent;
   1098 }
   1099 
   1100 const TextureState &Texture::getTextureState() const
   1101 {
   1102    return mState;
   1103 }
   1104 
   1105 const Extents &Texture::getExtents(TextureTarget target, size_t level) const
   1106 {
   1107    ASSERT(TextureTargetToType(target) == mState.mType);
   1108    return mState.getImageDesc(target, level).size;
   1109 }
   1110 
   1111 size_t Texture::getWidth(TextureTarget target, size_t level) const
   1112 {
   1113    ASSERT(TextureTargetToType(target) == mState.mType);
   1114    return mState.getImageDesc(target, level).size.width;
   1115 }
   1116 
   1117 size_t Texture::getHeight(TextureTarget target, size_t level) const
   1118 {
   1119    ASSERT(TextureTargetToType(target) == mState.mType);
   1120    return mState.getImageDesc(target, level).size.height;
   1121 }
   1122 
   1123 size_t Texture::getDepth(TextureTarget target, size_t level) const
   1124 {
   1125    ASSERT(TextureTargetToType(target) == mState.mType);
   1126    return mState.getImageDesc(target, level).size.depth;
   1127 }
   1128 
   1129 const Format &Texture::getFormat(TextureTarget target, size_t level) const
   1130 {
   1131    ASSERT(TextureTargetToType(target) == mState.mType);
   1132    return mState.getImageDesc(target, level).format;
   1133 }
   1134 
   1135 GLsizei Texture::getSamples(TextureTarget target, size_t level) const
   1136 {
   1137    ASSERT(TextureTargetToType(target) == mState.mType);
   1138    return mState.getImageDesc(target, level).samples;
   1139 }
   1140 
   1141 bool Texture::getFixedSampleLocations(TextureTarget target, size_t level) const
   1142 {
   1143    ASSERT(TextureTargetToType(target) == mState.mType);
   1144    return mState.getImageDesc(target, level).fixedSampleLocations;
   1145 }
   1146 
   1147 GLuint Texture::getMipmapMaxLevel() const
   1148 {
   1149    return mState.getMipmapMaxLevel();
   1150 }
   1151 
   1152 bool Texture::isMipmapComplete() const
   1153 {
   1154    return mState.computeMipmapCompleteness();
   1155 }
   1156 
   1157 egl::Surface *Texture::getBoundSurface() const
   1158 {
   1159    return mBoundSurface;
   1160 }
   1161 
   1162 egl::Stream *Texture::getBoundStream() const
   1163 {
   1164    return mBoundStream;
   1165 }
   1166 
   1167 GLint Texture::getMemorySize() const
   1168 {
   1169    GLint implSize = mTexture->getMemorySize();
   1170    if (implSize > 0)
   1171    {
   1172        return implSize;
   1173    }
   1174 
   1175    angle::CheckedNumeric<GLint> size = 0;
   1176    for (const ImageDesc &imageDesc : mState.mImageDescs)
   1177    {
   1178        size += imageDesc.getMemorySize();
   1179    }
   1180    return size.ValueOrDefault(std::numeric_limits<GLint>::max());
   1181 }
   1182 
   1183 GLint Texture::getLevelMemorySize(TextureTarget target, GLint level) const
   1184 {
   1185    GLint implSize = mTexture->getLevelMemorySize(target, level);
   1186    if (implSize > 0)
   1187    {
   1188        return implSize;
   1189    }
   1190 
   1191    return mState.getImageDesc(target, level).getMemorySize();
   1192 }
   1193 
   1194 void Texture::signalDirtyStorage(InitState initState)
   1195 {
   1196    mState.mInitState = initState;
   1197    invalidateCompletenessCache();
   1198    mState.mCachedSamplerFormatValid = false;
   1199    onStateChange(angle::SubjectMessage::SubjectChanged);
   1200 }
   1201 
   1202 void Texture::signalDirtyState(size_t dirtyBit)
   1203 {
   1204    mDirtyBits.set(dirtyBit);
   1205    invalidateCompletenessCache();
   1206    mState.mCachedSamplerFormatValid = false;
   1207 
   1208    if (dirtyBit == DIRTY_BIT_BASE_LEVEL || dirtyBit == DIRTY_BIT_MAX_LEVEL)
   1209    {
   1210        onStateChange(angle::SubjectMessage::SubjectChanged);
   1211    }
   1212    else
   1213    {
   1214        onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
   1215    }
   1216 }
   1217 
   1218 angle::Result Texture::setImage(Context *context,
   1219                                const PixelUnpackState &unpackState,
   1220                                Buffer *unpackBuffer,
   1221                                TextureTarget target,
   1222                                GLint level,
   1223                                GLenum internalFormat,
   1224                                const Extents &size,
   1225                                GLenum format,
   1226                                GLenum type,
   1227                                const uint8_t *pixels)
   1228 {
   1229    ASSERT(TextureTargetToType(target) == mState.mType);
   1230 
   1231    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1232    ANGLE_TRY(releaseTexImageInternal(context));
   1233 
   1234    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1235    ANGLE_TRY(orphanImages(context, &releaseImage));
   1236 
   1237    ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
   1238 
   1239    ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size, format, type, unpackState,
   1240                                 unpackBuffer, pixels));
   1241 
   1242    InitState initState = DetermineInitState(context, unpackBuffer, pixels);
   1243    mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));
   1244 
   1245    ANGLE_TRY(handleMipmapGenerationHint(context, level));
   1246 
   1247    signalDirtyStorage(initState);
   1248 
   1249    return angle::Result::Continue;
   1250 }
   1251 
   1252 angle::Result Texture::setSubImage(Context *context,
   1253                                   const PixelUnpackState &unpackState,
   1254                                   Buffer *unpackBuffer,
   1255                                   TextureTarget target,
   1256                                   GLint level,
   1257                                   const Box &area,
   1258                                   GLenum format,
   1259                                   GLenum type,
   1260                                   const uint8_t *pixels)
   1261 {
   1262    ASSERT(TextureTargetToType(target) == mState.mType);
   1263 
   1264    ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
   1265    ANGLE_TRY(ensureSubImageInitialized(context, index, area));
   1266 
   1267    ANGLE_TRY(mTexture->setSubImage(context, index, area, format, type, unpackState, unpackBuffer,
   1268                                    pixels));
   1269 
   1270    ANGLE_TRY(handleMipmapGenerationHint(context, level));
   1271 
   1272    onStateChange(angle::SubjectMessage::ContentsChanged);
   1273 
   1274    return angle::Result::Continue;
   1275 }
   1276 
   1277 angle::Result Texture::setCompressedImage(Context *context,
   1278                                          const PixelUnpackState &unpackState,
   1279                                          TextureTarget target,
   1280                                          GLint level,
   1281                                          GLenum internalFormat,
   1282                                          const Extents &size,
   1283                                          size_t imageSize,
   1284                                          const uint8_t *pixels)
   1285 {
   1286    ASSERT(TextureTargetToType(target) == mState.mType);
   1287 
   1288    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1289    ANGLE_TRY(releaseTexImageInternal(context));
   1290 
   1291    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1292    ANGLE_TRY(orphanImages(context, &releaseImage));
   1293 
   1294    ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
   1295 
   1296    ANGLE_TRY(mTexture->setCompressedImage(context, index, internalFormat, size, unpackState,
   1297                                           imageSize, pixels));
   1298 
   1299    Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
   1300 
   1301    InitState initState = DetermineInitState(context, unpackBuffer, pixels);
   1302    mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat), initState));
   1303    signalDirtyStorage(initState);
   1304 
   1305    return angle::Result::Continue;
   1306 }
   1307 
   1308 angle::Result Texture::setCompressedSubImage(const Context *context,
   1309                                             const PixelUnpackState &unpackState,
   1310                                             TextureTarget target,
   1311                                             GLint level,
   1312                                             const Box &area,
   1313                                             GLenum format,
   1314                                             size_t imageSize,
   1315                                             const uint8_t *pixels)
   1316 {
   1317    ASSERT(TextureTargetToType(target) == mState.mType);
   1318 
   1319    ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
   1320    ANGLE_TRY(ensureSubImageInitialized(context, index, area));
   1321 
   1322    ANGLE_TRY(mTexture->setCompressedSubImage(context, index, area, format, unpackState, imageSize,
   1323                                              pixels));
   1324 
   1325    onStateChange(angle::SubjectMessage::ContentsChanged);
   1326 
   1327    return angle::Result::Continue;
   1328 }
   1329 
   1330 angle::Result Texture::copyImage(Context *context,
   1331                                 TextureTarget target,
   1332                                 GLint level,
   1333                                 const Rectangle &sourceArea,
   1334                                 GLenum internalFormat,
   1335                                 Framebuffer *source)
   1336 {
   1337    ASSERT(TextureTargetToType(target) == mState.mType);
   1338 
   1339    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1340    ANGLE_TRY(releaseTexImageInternal(context));
   1341 
   1342    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1343    ANGLE_TRY(orphanImages(context, &releaseImage));
   1344 
   1345    ImageIndex index = ImageIndex::MakeFromTarget(target, level, 1);
   1346 
   1347    const InternalFormat &internalFormatInfo =
   1348        GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
   1349 
   1350    // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
   1351    // other pixels untouched. For safety in robust resource initialization, assume that that
   1352    // clipping is going to occur when computing the region for which to ensure initialization. If
   1353    // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
   1354    // going to be set during the copy operation.
   1355    Box destBox;
   1356    bool forceCopySubImage = false;
   1357    if (context->isRobustResourceInitEnabled())
   1358    {
   1359        const FramebufferAttachment *sourceReadAttachment = source->getReadColorAttachment();
   1360        Extents fbSize                                    = sourceReadAttachment->getSize();
   1361        // Force using copySubImage when the source area is out of bounds AND
   1362        // we're not copying to and from the same texture
   1363        forceCopySubImage = ((sourceArea.x < 0) || (sourceArea.y < 0) ||
   1364                             ((sourceArea.x + sourceArea.width) > fbSize.width) ||
   1365                             ((sourceArea.y + sourceArea.height) > fbSize.height)) &&
   1366                            (sourceReadAttachment->getResource() != this);
   1367        Rectangle clippedArea;
   1368        if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
   1369        {
   1370            const Offset clippedOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y,
   1371                                       0);
   1372            destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
   1373                          clippedArea.height, 1);
   1374        }
   1375    }
   1376 
   1377    InitState initState = DetermineInitState(context, nullptr, nullptr);
   1378 
   1379    // If we need to initialize the destination texture we split the call into a create call,
   1380    // an initializeContents call, and then a copySubImage call. This ensures the destination
   1381    // texture exists before we try to clear it.
   1382    Extents size(sourceArea.width, sourceArea.height, 1);
   1383    if (forceCopySubImage || doesSubImageNeedInit(context, index, destBox))
   1384    {
   1385        ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size,
   1386                                     internalFormatInfo.format, internalFormatInfo.type,
   1387                                     PixelUnpackState(), nullptr, nullptr));
   1388        mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormatInfo), initState));
   1389        ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
   1390        ANGLE_TRY(mTexture->copySubImage(context, index, Offset(), sourceArea, source));
   1391    }
   1392    else
   1393    {
   1394        ANGLE_TRY(mTexture->copyImage(context, index, sourceArea, internalFormat, source));
   1395    }
   1396 
   1397    mState.setImageDesc(target, level,
   1398                        ImageDesc(size, Format(internalFormatInfo), InitState::Initialized));
   1399 
   1400    ANGLE_TRY(handleMipmapGenerationHint(context, level));
   1401 
   1402    // Because this could affect the texture storage we might need to init other layers/levels.
   1403    signalDirtyStorage(initState);
   1404 
   1405    return angle::Result::Continue;
   1406 }
   1407 
   1408 angle::Result Texture::copySubImage(Context *context,
   1409                                    const ImageIndex &index,
   1410                                    const Offset &destOffset,
   1411                                    const Rectangle &sourceArea,
   1412                                    Framebuffer *source)
   1413 {
   1414    ASSERT(TextureTargetToType(index.getTarget()) == mState.mType);
   1415 
   1416    // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
   1417    // other pixels untouched. For safety in robust resource initialization, assume that that
   1418    // clipping is going to occur when computing the region for which to ensure initialization. If
   1419    // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
   1420    // going to be set during the copy operation. Note that this assumes that
   1421    // ensureSubImageInitialized ensures initialization of the entire destination texture, and not
   1422    // just a sub-region.
   1423    Box destBox;
   1424    if (context->isRobustResourceInitEnabled())
   1425    {
   1426        Extents fbSize = source->getReadColorAttachment()->getSize();
   1427        Rectangle clippedArea;
   1428        if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
   1429        {
   1430            const Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
   1431                                       destOffset.y + clippedArea.y - sourceArea.y, 0);
   1432            destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
   1433                          clippedArea.height, 1);
   1434        }
   1435    }
   1436 
   1437    ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
   1438 
   1439    ANGLE_TRY(mTexture->copySubImage(context, index, destOffset, sourceArea, source));
   1440    ANGLE_TRY(handleMipmapGenerationHint(context, index.getLevelIndex()));
   1441 
   1442    onStateChange(angle::SubjectMessage::ContentsChanged);
   1443 
   1444    return angle::Result::Continue;
   1445 }
   1446 
   1447 angle::Result Texture::copyRenderbufferSubData(Context *context,
   1448                                               const gl::Renderbuffer *srcBuffer,
   1449                                               GLint srcLevel,
   1450                                               GLint srcX,
   1451                                               GLint srcY,
   1452                                               GLint srcZ,
   1453                                               GLint dstLevel,
   1454                                               GLint dstX,
   1455                                               GLint dstY,
   1456                                               GLint dstZ,
   1457                                               GLsizei srcWidth,
   1458                                               GLsizei srcHeight,
   1459                                               GLsizei srcDepth)
   1460 {
   1461    ANGLE_TRY(mTexture->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY, srcZ,
   1462                                                dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
   1463                                                srcDepth));
   1464 
   1465    signalDirtyStorage(InitState::Initialized);
   1466 
   1467    return angle::Result::Continue;
   1468 }
   1469 
   1470 angle::Result Texture::copyTextureSubData(Context *context,
   1471                                          const gl::Texture *srcTexture,
   1472                                          GLint srcLevel,
   1473                                          GLint srcX,
   1474                                          GLint srcY,
   1475                                          GLint srcZ,
   1476                                          GLint dstLevel,
   1477                                          GLint dstX,
   1478                                          GLint dstY,
   1479                                          GLint dstZ,
   1480                                          GLsizei srcWidth,
   1481                                          GLsizei srcHeight,
   1482                                          GLsizei srcDepth)
   1483 {
   1484    ANGLE_TRY(mTexture->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
   1485                                           dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
   1486                                           srcDepth));
   1487 
   1488    signalDirtyStorage(InitState::Initialized);
   1489 
   1490    return angle::Result::Continue;
   1491 }
   1492 
   1493 angle::Result Texture::copyTexture(Context *context,
   1494                                   TextureTarget target,
   1495                                   GLint level,
   1496                                   GLenum internalFormat,
   1497                                   GLenum type,
   1498                                   GLint sourceLevel,
   1499                                   bool unpackFlipY,
   1500                                   bool unpackPremultiplyAlpha,
   1501                                   bool unpackUnmultiplyAlpha,
   1502                                   Texture *source)
   1503 {
   1504    ASSERT(TextureTargetToType(target) == mState.mType);
   1505    ASSERT(source->getType() != TextureType::CubeMap);
   1506 
   1507    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1508    ANGLE_TRY(releaseTexImageInternal(context));
   1509 
   1510    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1511    ANGLE_TRY(orphanImages(context, &releaseImage));
   1512 
   1513    // Initialize source texture.
   1514    // Note: we don't have a way to notify which portions of the image changed currently.
   1515    ANGLE_TRY(source->ensureInitialized(context));
   1516 
   1517    ImageIndex index = ImageIndex::MakeFromTarget(target, level, ImageIndex::kEntireLevel);
   1518 
   1519    ANGLE_TRY(mTexture->copyTexture(context, index, internalFormat, type, sourceLevel, unpackFlipY,
   1520                                    unpackPremultiplyAlpha, unpackUnmultiplyAlpha, source));
   1521 
   1522    const auto &sourceDesc =
   1523        source->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
   1524    const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
   1525    mState.setImageDesc(
   1526        target, level,
   1527        ImageDesc(sourceDesc.size, Format(internalFormatInfo), InitState::Initialized));
   1528 
   1529    signalDirtyStorage(InitState::Initialized);
   1530 
   1531    return angle::Result::Continue;
   1532 }
   1533 
   1534 angle::Result Texture::copySubTexture(const Context *context,
   1535                                      TextureTarget target,
   1536                                      GLint level,
   1537                                      const Offset &destOffset,
   1538                                      GLint sourceLevel,
   1539                                      const Box &sourceBox,
   1540                                      bool unpackFlipY,
   1541                                      bool unpackPremultiplyAlpha,
   1542                                      bool unpackUnmultiplyAlpha,
   1543                                      Texture *source)
   1544 {
   1545    ASSERT(TextureTargetToType(target) == mState.mType);
   1546 
   1547    // Ensure source is initialized.
   1548    ANGLE_TRY(source->ensureInitialized(context));
   1549 
   1550    Box destBox(destOffset.x, destOffset.y, destOffset.z, sourceBox.width, sourceBox.height,
   1551                sourceBox.depth);
   1552    ImageIndex index = ImageIndex::MakeFromTarget(target, level, sourceBox.depth);
   1553    ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
   1554 
   1555    ANGLE_TRY(mTexture->copySubTexture(context, index, destOffset, sourceLevel, sourceBox,
   1556                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
   1557                                       source));
   1558 
   1559    onStateChange(angle::SubjectMessage::ContentsChanged);
   1560 
   1561    return angle::Result::Continue;
   1562 }
   1563 
   1564 angle::Result Texture::copyCompressedTexture(Context *context, const Texture *source)
   1565 {
   1566    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1567    ANGLE_TRY(releaseTexImageInternal(context));
   1568 
   1569    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1570    ANGLE_TRY(orphanImages(context, &releaseImage));
   1571 
   1572    ANGLE_TRY(mTexture->copyCompressedTexture(context, source));
   1573 
   1574    ASSERT(source->getType() != TextureType::CubeMap && getType() != TextureType::CubeMap);
   1575    const auto &sourceDesc =
   1576        source->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), 0);
   1577    mState.setImageDesc(NonCubeTextureTypeToTarget(getType()), 0, sourceDesc);
   1578 
   1579    return angle::Result::Continue;
   1580 }
   1581 
   1582 angle::Result Texture::setStorage(Context *context,
   1583                                  TextureType type,
   1584                                  GLsizei levels,
   1585                                  GLenum internalFormat,
   1586                                  const Extents &size)
   1587 {
   1588    ASSERT(type == mState.mType);
   1589 
   1590    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1591    ANGLE_TRY(releaseTexImageInternal(context));
   1592 
   1593    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1594    ANGLE_TRY(orphanImages(context, &releaseImage));
   1595 
   1596    mState.mImmutableFormat = true;
   1597    mState.mImmutableLevels = static_cast<GLuint>(levels);
   1598    mState.clearImageDescs();
   1599    InitState initState = DetermineInitState(context, nullptr, nullptr);
   1600    mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
   1601                             initState);
   1602 
   1603    ANGLE_TRY(mTexture->setStorage(context, type, levels, internalFormat, size));
   1604 
   1605    // Changing the texture to immutable can trigger a change in the base and max levels:
   1606    // GLES 3.0.4 section 3.8.10 pg 158:
   1607    // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
   1608    // clamped to the range[levelbase;levels].
   1609    mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
   1610    mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
   1611 
   1612    signalDirtyStorage(initState);
   1613 
   1614    return angle::Result::Continue;
   1615 }
   1616 
   1617 angle::Result Texture::setImageExternal(Context *context,
   1618                                        TextureTarget target,
   1619                                        GLint level,
   1620                                        GLenum internalFormat,
   1621                                        const Extents &size,
   1622                                        GLenum format,
   1623                                        GLenum type)
   1624 {
   1625    ASSERT(TextureTargetToType(target) == mState.mType);
   1626 
   1627    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1628    ANGLE_TRY(releaseTexImageInternal(context));
   1629 
   1630    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1631    ANGLE_TRY(orphanImages(context, &releaseImage));
   1632 
   1633    ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
   1634 
   1635    ANGLE_TRY(mTexture->setImageExternal(context, index, internalFormat, size, format, type));
   1636 
   1637    InitState initState = InitState::Initialized;
   1638    mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));
   1639 
   1640    ANGLE_TRY(handleMipmapGenerationHint(context, level));
   1641 
   1642    signalDirtyStorage(initState);
   1643 
   1644    return angle::Result::Continue;
   1645 }
   1646 
   1647 angle::Result Texture::setStorageMultisample(Context *context,
   1648                                             TextureType type,
   1649                                             GLsizei samplesIn,
   1650                                             GLint internalFormat,
   1651                                             const Extents &size,
   1652                                             bool fixedSampleLocations)
   1653 {
   1654    ASSERT(type == mState.mType);
   1655 
   1656    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1657    ANGLE_TRY(releaseTexImageInternal(context));
   1658 
   1659    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1660    ANGLE_TRY(orphanImages(context, &releaseImage));
   1661 
   1662    // Potentially adjust "samples" to a supported value
   1663    const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
   1664    GLsizei samples               = formatCaps.getNearestSamples(samplesIn);
   1665 
   1666    mState.mImmutableFormat = true;
   1667    mState.mImmutableLevels = static_cast<GLuint>(1);
   1668    mState.clearImageDescs();
   1669    InitState initState = DetermineInitState(context, nullptr, nullptr);
   1670    mState.setImageDescChainMultisample(size, Format(internalFormat), samples, fixedSampleLocations,
   1671                                        initState);
   1672 
   1673    ANGLE_TRY(mTexture->setStorageMultisample(context, type, samples, internalFormat, size,
   1674                                              fixedSampleLocations));
   1675    signalDirtyStorage(initState);
   1676 
   1677    return angle::Result::Continue;
   1678 }
   1679 
   1680 angle::Result Texture::setStorageExternalMemory(Context *context,
   1681                                                TextureType type,
   1682                                                GLsizei levels,
   1683                                                GLenum internalFormat,
   1684                                                const Extents &size,
   1685                                                MemoryObject *memoryObject,
   1686                                                GLuint64 offset,
   1687                                                GLbitfield createFlags,
   1688                                                GLbitfield usageFlags,
   1689                                                const void *imageCreateInfoPNext)
   1690 {
   1691    ASSERT(type == mState.mType);
   1692 
   1693    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1694    ANGLE_TRY(releaseTexImageInternal(context));
   1695 
   1696    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1697    ANGLE_TRY(orphanImages(context, &releaseImage));
   1698 
   1699    ANGLE_TRY(mTexture->setStorageExternalMemory(context, type, levels, internalFormat, size,
   1700                                                 memoryObject, offset, createFlags, usageFlags,
   1701                                                 imageCreateInfoPNext));
   1702 
   1703    mState.mImmutableFormat = true;
   1704    mState.mImmutableLevels = static_cast<GLuint>(levels);
   1705    mState.clearImageDescs();
   1706    mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
   1707                             InitState::Initialized);
   1708 
   1709    // Changing the texture to immutable can trigger a change in the base and max levels:
   1710    // GLES 3.0.4 section 3.8.10 pg 158:
   1711    // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
   1712    // clamped to the range[levelbase;levels].
   1713    mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
   1714    mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
   1715 
   1716    signalDirtyStorage(InitState::Initialized);
   1717 
   1718    return angle::Result::Continue;
   1719 }
   1720 
   1721 angle::Result Texture::generateMipmap(Context *context)
   1722 {
   1723    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1724    ANGLE_TRY(releaseTexImageInternal(context));
   1725 
   1726    // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
   1727    // is not mip complete.
   1728    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1729    if (!isMipmapComplete())
   1730    {
   1731        ANGLE_TRY(orphanImages(context, &releaseImage));
   1732    }
   1733 
   1734    const GLuint baseLevel = mState.getEffectiveBaseLevel();
   1735    const GLuint maxLevel  = mState.getMipmapMaxLevel();
   1736 
   1737    if (maxLevel <= baseLevel)
   1738    {
   1739        return angle::Result::Continue;
   1740    }
   1741 
   1742    // If any dimension is zero, this is a no-op:
   1743    //
   1744    // > Otherwise, if level_base is not defined, or if any dimension is zero, all mipmap levels are
   1745    // > left unchanged. This is not an error.
   1746    const ImageDesc &baseImageInfo = mState.getImageDesc(mState.getBaseImageTarget(), baseLevel);
   1747    if (baseImageInfo.size.empty())
   1748    {
   1749        return angle::Result::Continue;
   1750    }
   1751 
   1752    // Clear the base image(s) immediately if needed
   1753    if (context->isRobustResourceInitEnabled())
   1754    {
   1755        ImageIndexIterator it =
   1756            ImageIndexIterator::MakeGeneric(mState.mType, baseLevel, baseLevel + 1,
   1757                                            ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
   1758        while (it.hasNext())
   1759        {
   1760            const ImageIndex index = it.next();
   1761            const ImageDesc &desc  = mState.getImageDesc(index.getTarget(), index.getLevelIndex());
   1762 
   1763            if (desc.initState == InitState::MayNeedInit)
   1764            {
   1765                ANGLE_TRY(initializeContents(context, GL_NONE, index));
   1766            }
   1767        }
   1768    }
   1769 
   1770    ANGLE_TRY(syncState(context, Command::GenerateMipmap));
   1771    ANGLE_TRY(mTexture->generateMipmap(context));
   1772 
   1773    // Propagate the format and size of the base mip to the smaller ones. Cube maps are guaranteed
   1774    // to have faces of the same size and format so any faces can be picked.
   1775    mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format,
   1776                             InitState::Initialized);
   1777 
   1778    signalDirtyStorage(InitState::Initialized);
   1779 
   1780    return angle::Result::Continue;
   1781 }
   1782 
   1783 angle::Result Texture::bindTexImageFromSurface(Context *context, egl::Surface *surface)
   1784 {
   1785    ASSERT(surface);
   1786 
   1787    if (mBoundSurface)
   1788    {
   1789        ANGLE_TRY(releaseTexImageFromSurface(context));
   1790    }
   1791 
   1792    mBoundSurface = surface;
   1793 
   1794    // Set the image info to the size and format of the surface
   1795    ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle);
   1796    Extents size(surface->getWidth(), surface->getHeight(), 1);
   1797    ImageDesc desc(size, surface->getBindTexImageFormat(), InitState::Initialized);
   1798    mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0, desc);
   1799    mState.mHasProtectedContent = surface->hasProtectedContent();
   1800 
   1801    ANGLE_TRY(mTexture->bindTexImage(context, surface));
   1802 
   1803    signalDirtyStorage(InitState::Initialized);
   1804    return angle::Result::Continue;
   1805 }
   1806 
   1807 angle::Result Texture::releaseTexImageFromSurface(const Context *context)
   1808 {
   1809    ASSERT(mBoundSurface);
   1810    mBoundSurface = nullptr;
   1811    ANGLE_TRY(mTexture->releaseTexImage(context));
   1812 
   1813    // Erase the image info for level 0
   1814    ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle);
   1815    mState.clearImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0);
   1816    mState.mHasProtectedContent = false;
   1817    signalDirtyStorage(InitState::Initialized);
   1818    return angle::Result::Continue;
   1819 }
   1820 
   1821 void Texture::bindStream(egl::Stream *stream)
   1822 {
   1823    ASSERT(stream);
   1824 
   1825    // It should not be possible to bind a texture already bound to another stream
   1826    ASSERT(mBoundStream == nullptr);
   1827 
   1828    mBoundStream = stream;
   1829 
   1830    ASSERT(mState.mType == TextureType::External);
   1831 }
   1832 
   1833 void Texture::releaseStream()
   1834 {
   1835    ASSERT(mBoundStream);
   1836    mBoundStream = nullptr;
   1837 }
   1838 
   1839 angle::Result Texture::acquireImageFromStream(const Context *context,
   1840                                              const egl::Stream::GLTextureDescription &desc)
   1841 {
   1842    ASSERT(mBoundStream != nullptr);
   1843    ANGLE_TRY(mTexture->setImageExternal(context, mState.mType, mBoundStream, desc));
   1844 
   1845    Extents size(desc.width, desc.height, 1);
   1846    mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0,
   1847                        ImageDesc(size, Format(desc.internalFormat), InitState::Initialized));
   1848    signalDirtyStorage(InitState::Initialized);
   1849    return angle::Result::Continue;
   1850 }
   1851 
   1852 angle::Result Texture::releaseImageFromStream(const Context *context)
   1853 {
   1854    ASSERT(mBoundStream != nullptr);
   1855    ANGLE_TRY(mTexture->setImageExternal(context, mState.mType, nullptr,
   1856                                         egl::Stream::GLTextureDescription()));
   1857 
   1858    // Set to incomplete
   1859    mState.clearImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0);
   1860    signalDirtyStorage(InitState::Initialized);
   1861    return angle::Result::Continue;
   1862 }
   1863 
   1864 angle::Result Texture::releaseTexImageInternal(Context *context)
   1865 {
   1866    if (mBoundSurface)
   1867    {
   1868        // Notify the surface
   1869        egl::Error eglErr = mBoundSurface->releaseTexImageFromTexture(context);
   1870        // TODO(jmadill): Remove this once refactor is complete. http://anglebug.com/3041
   1871        if (eglErr.isError())
   1872        {
   1873            context->handleError(GL_INVALID_OPERATION, "Error releasing tex image from texture",
   1874                                 __FILE__, ANGLE_FUNCTION, __LINE__);
   1875        }
   1876 
   1877        // Then, call the same method as from the surface
   1878        ANGLE_TRY(releaseTexImageFromSurface(context));
   1879    }
   1880    return angle::Result::Continue;
   1881 }
   1882 
   1883 angle::Result Texture::setEGLImageTargetImpl(Context *context,
   1884                                             TextureType type,
   1885                                             GLuint levels,
   1886                                             egl::Image *imageTarget)
   1887 {
   1888    ASSERT(type == mState.mType);
   1889 
   1890    // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
   1891    ANGLE_TRY(releaseTexImageInternal(context));
   1892 
   1893    egl::RefCountObjectReleaser<egl::Image> releaseImage;
   1894    ANGLE_TRY(orphanImages(context, &releaseImage));
   1895 
   1896    setTargetImage(context, imageTarget);
   1897 
   1898    auto initState = imageTarget->sourceInitState();
   1899 
   1900    mState.clearImageDescs();
   1901    mState.setImageDescChain(0, levels - 1, imageTarget->getExtents(), imageTarget->getFormat(),
   1902                             initState);
   1903    mState.mHasProtectedContent = imageTarget->hasProtectedContent();
   1904 
   1905    ANGLE_TRY(mTexture->setEGLImageTarget(context, type, imageTarget));
   1906 
   1907    signalDirtyStorage(initState);
   1908 
   1909    return angle::Result::Continue;
   1910 }
   1911 
   1912 angle::Result Texture::setEGLImageTarget(Context *context,
   1913                                         TextureType type,
   1914                                         egl::Image *imageTarget)
   1915 {
   1916    ASSERT(type == TextureType::_2D || type == TextureType::External ||
   1917           type == TextureType::_2DArray);
   1918 
   1919    return setEGLImageTargetImpl(context, type, 1u, imageTarget);
   1920 }
   1921 
   1922 angle::Result Texture::setStorageEGLImageTarget(Context *context,
   1923                                                TextureType type,
   1924                                                egl::Image *imageTarget,
   1925                                                const GLint *attrib_list)
   1926 {
   1927    ASSERT(type == TextureType::External || type == TextureType::_3D || type == TextureType::_2D ||
   1928           type == TextureType::_2DArray || type == TextureType::CubeMap ||
   1929           type == TextureType::CubeMapArray);
   1930 
   1931    ANGLE_TRY(setEGLImageTargetImpl(context, type, imageTarget->getLevelCount(), imageTarget));
   1932 
   1933    mState.mImmutableLevels = imageTarget->getLevelCount();
   1934    mState.mImmutableFormat = true;
   1935 
   1936    // Changing the texture to immutable can trigger a change in the base and max levels:
   1937    // GLES 3.0.4 section 3.8.10 pg 158:
   1938    // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
   1939    // clamped to the range[levelbase;levels].
   1940    mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
   1941    mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
   1942 
   1943    return angle::Result::Continue;
   1944 }
   1945 
   1946 Extents Texture::getAttachmentSize(const ImageIndex &imageIndex) const
   1947 {
   1948    // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
   1949    // we only allow querying ImageDesc on a complete cube map, and this ImageDesc is exactly the
   1950    // one that belongs to the first face of the cube map.
   1951    if (imageIndex.isEntireLevelCubeMap())
   1952    {
   1953        // A cube map texture is cube complete if the following conditions all hold true:
   1954        // - The levelbase arrays of each of the six texture images making up the cube map have
   1955        //   identical, positive, and square dimensions.
   1956        if (!mState.isCubeComplete())
   1957        {
   1958            return Extents();
   1959        }
   1960    }
   1961 
   1962    return mState.getImageDesc(imageIndex).size;
   1963 }
   1964 
   1965 Format Texture::getAttachmentFormat(GLenum /*binding*/, const ImageIndex &imageIndex) const
   1966 {
   1967    // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
   1968    // we only allow querying ImageDesc on a complete cube map, and this ImageDesc is exactly the
   1969    // one that belongs to the first face of the cube map.
   1970    if (imageIndex.isEntireLevelCubeMap())
   1971    {
   1972        // A cube map texture is cube complete if the following conditions all hold true:
   1973        // - The levelbase arrays were each specified with the same effective internal format.
   1974        if (!mState.isCubeComplete())
   1975        {
   1976            return Format::Invalid();
   1977        }
   1978    }
   1979    return mState.getImageDesc(imageIndex).format;
   1980 }
   1981 
   1982 GLsizei Texture::getAttachmentSamples(const ImageIndex &imageIndex) const
   1983 {
   1984    // We do not allow querying TextureTarget by an ImageIndex that represents an entire level of a
   1985    // cube map (See comments in function TextureTypeToTarget() in ImageIndex.cpp).
   1986    if (imageIndex.isEntireLevelCubeMap())
   1987    {
   1988        return 0;
   1989    }
   1990 
   1991    return getSamples(imageIndex.getTarget(), imageIndex.getLevelIndex());
   1992 }
   1993 
   1994 bool Texture::isRenderable(const Context *context,
   1995                           GLenum binding,
   1996                           const ImageIndex &imageIndex) const
   1997 {
   1998    if (isEGLImageTarget())
   1999    {
   2000        return ImageSibling::isRenderable(context, binding, imageIndex);
   2001    }
   2002 
   2003    // Surfaces bound to textures are always renderable. This avoids issues with surfaces with ES3+
   2004    // formats not being renderable when bound to textures in ES2 contexts.
   2005    if (mBoundSurface)
   2006    {
   2007        return true;
   2008    }
   2009 
   2010    return getAttachmentFormat(binding, imageIndex)
   2011        .info->textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
   2012 }
   2013 
   2014 bool Texture::getAttachmentFixedSampleLocations(const ImageIndex &imageIndex) const
   2015 {
   2016    // We do not allow querying TextureTarget by an ImageIndex that represents an entire level of a
   2017    // cube map (See comments in function TextureTypeToTarget() in ImageIndex.cpp).
   2018    if (imageIndex.isEntireLevelCubeMap())
   2019    {
   2020        return true;
   2021    }
   2022 
   2023    // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
   2024    // the same for all attached textures.
   2025    return getFixedSampleLocations(imageIndex.getTarget(), imageIndex.getLevelIndex());
   2026 }
   2027 
   2028 void Texture::setBorderColor(const Context *context, const ColorGeneric &color)
   2029 {
   2030    mState.mSamplerState.setBorderColor(color);
   2031    signalDirtyState(DIRTY_BIT_BORDER_COLOR);
   2032 }
   2033 
   2034 const ColorGeneric &Texture::getBorderColor() const
   2035 {
   2036    return mState.mSamplerState.getBorderColor();
   2037 }
   2038 
   2039 GLint Texture::getRequiredTextureImageUnits(const Context *context) const
   2040 {
   2041    // Only external texture types can return non-1.
   2042    if (mState.mType != TextureType::External)
   2043    {
   2044        return 1;
   2045    }
   2046 
   2047    return mTexture->getRequiredExternalTextureImageUnits(context);
   2048 }
   2049 
   2050 void Texture::setCrop(const Rectangle &rect)
   2051 {
   2052    mState.setCrop(rect);
   2053 }
   2054 
   2055 const Rectangle &Texture::getCrop() const
   2056 {
   2057    return mState.getCrop();
   2058 }
   2059 
   2060 void Texture::setGenerateMipmapHint(GLenum hint)
   2061 {
   2062    mState.setGenerateMipmapHint(hint);
   2063 }
   2064 
   2065 GLenum Texture::getGenerateMipmapHint() const
   2066 {
   2067    return mState.getGenerateMipmapHint();
   2068 }
   2069 
   2070 angle::Result Texture::setBuffer(const gl::Context *context,
   2071                                 gl::Buffer *buffer,
   2072                                 GLenum internalFormat)
   2073 {
   2074    // Use 0 to indicate that the size is taken from whatever size the buffer has when the texture
   2075    // buffer is used.
   2076    return setBufferRange(context, buffer, internalFormat, 0, 0);
   2077 }
   2078 
   2079 angle::Result Texture::setBufferRange(const gl::Context *context,
   2080                                      gl::Buffer *buffer,
   2081                                      GLenum internalFormat,
   2082                                      GLintptr offset,
   2083                                      GLsizeiptr size)
   2084 {
   2085    mState.mImmutableFormat = true;
   2086    mState.mBuffer.set(context, buffer, offset, size);
   2087    ANGLE_TRY(mTexture->setBuffer(context, internalFormat));
   2088 
   2089    mState.clearImageDescs();
   2090    if (buffer == nullptr)
   2091    {
   2092        mBufferObserver.reset();
   2093        InitState initState = DetermineInitState(context, nullptr, nullptr);
   2094        signalDirtyStorage(initState);
   2095        return angle::Result::Continue;
   2096    }
   2097 
   2098    size = GetBoundBufferAvailableSize(mState.mBuffer);
   2099 
   2100    mState.mImmutableLevels           = static_cast<GLuint>(1);
   2101    InternalFormat internalFormatInfo = GetSizedInternalFormatInfo(internalFormat);
   2102    Format format(internalFormat);
   2103    Extents extents(static_cast<GLuint>(size / internalFormatInfo.pixelBytes), 1, 1);
   2104    InitState initState = buffer->initState();
   2105    mState.setImageDesc(TextureTarget::Buffer, 0, ImageDesc(extents, format, initState));
   2106 
   2107    signalDirtyStorage(initState);
   2108 
   2109    // Observe modifications to the buffer, so that extents can be updated.
   2110    mBufferObserver.bind(buffer);
   2111 
   2112    return angle::Result::Continue;
   2113 }
   2114 
   2115 const OffsetBindingPointer<Buffer> &Texture::getBuffer() const
   2116 {
   2117    return mState.mBuffer;
   2118 }
   2119 
   2120 void Texture::onAttach(const Context *context, rx::Serial framebufferSerial)
   2121 {
   2122    addRef();
   2123 
   2124    // Duplicates allowed for multiple attachment points. See the comment in the header.
   2125    mBoundFramebufferSerials.push_back(framebufferSerial);
   2126 
   2127    if (!mState.mHasBeenBoundAsAttachment)
   2128    {
   2129        mDirtyBits.set(DIRTY_BIT_BOUND_AS_ATTACHMENT);
   2130        mState.mHasBeenBoundAsAttachment = true;
   2131    }
   2132 }
   2133 
   2134 void Texture::onDetach(const Context *context, rx::Serial framebufferSerial)
   2135 {
   2136    // Erase first instance. If there are multiple bindings, leave the others.
   2137    ASSERT(isBoundToFramebuffer(framebufferSerial));
   2138    mBoundFramebufferSerials.remove_and_permute(framebufferSerial);
   2139 
   2140    release(context);
   2141 }
   2142 
   2143 GLuint Texture::getId() const
   2144 {
   2145    return id().value;
   2146 }
   2147 
   2148 GLuint Texture::getNativeID() const
   2149 {
   2150    return mTexture->getNativeID();
   2151 }
   2152 
   2153 angle::Result Texture::syncState(const Context *context, Command source)
   2154 {
   2155    ASSERT(hasAnyDirtyBit() || source == Command::GenerateMipmap);
   2156    ANGLE_TRY(mTexture->syncState(context, mDirtyBits, source));
   2157    mDirtyBits.reset();
   2158    mState.mInitState = InitState::Initialized;
   2159    return angle::Result::Continue;
   2160 }
   2161 
   2162 rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
   2163 {
   2164    return mTexture;
   2165 }
   2166 
   2167 bool Texture::isSamplerComplete(const Context *context, const Sampler *optionalSampler)
   2168 {
   2169    const auto &samplerState =
   2170        optionalSampler ? optionalSampler->getSamplerState() : mState.mSamplerState;
   2171    const auto &contextState = context->getState();
   2172 
   2173    if (contextState.getContextID() != mCompletenessCache.context ||
   2174        !mCompletenessCache.samplerState.sameCompleteness(samplerState))
   2175    {
   2176        mCompletenessCache.context      = context->getState().getContextID();
   2177        mCompletenessCache.samplerState = samplerState;
   2178        mCompletenessCache.samplerComplete =
   2179            mState.computeSamplerCompleteness(samplerState, contextState);
   2180    }
   2181 
   2182    return mCompletenessCache.samplerComplete;
   2183 }
   2184 
   2185 // CopyImageSubData requires that we ignore format-based completeness rules
   2186 bool Texture::isSamplerCompleteForCopyImage(const Context *context,
   2187                                            const Sampler *optionalSampler) const
   2188 {
   2189    const gl::SamplerState &samplerState =
   2190        optionalSampler ? optionalSampler->getSamplerState() : mState.mSamplerState;
   2191    const gl::State &contextState = context->getState();
   2192    return mState.computeSamplerCompletenessForCopyImage(samplerState, contextState);
   2193 }
   2194 
   2195 Texture::SamplerCompletenessCache::SamplerCompletenessCache()
   2196    : context({0}), samplerState(), samplerComplete(false)
   2197 {}
   2198 
   2199 void Texture::invalidateCompletenessCache() const
   2200 {
   2201    mCompletenessCache.context = {0};
   2202 }
   2203 
   2204 angle::Result Texture::ensureInitialized(const Context *context)
   2205 {
   2206    if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
   2207    {
   2208        return angle::Result::Continue;
   2209    }
   2210 
   2211    bool anyDirty = false;
   2212 
   2213    ImageIndexIterator it =
   2214        ImageIndexIterator::MakeGeneric(mState.mType, 0, IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1,
   2215                                        ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
   2216    while (it.hasNext())
   2217    {
   2218        const ImageIndex index = it.next();
   2219        ImageDesc &desc =
   2220            mState.mImageDescs[GetImageDescIndex(index.getTarget(), index.getLevelIndex())];
   2221        if (desc.initState == InitState::MayNeedInit && !desc.size.empty())
   2222        {
   2223            ASSERT(mState.mInitState == InitState::MayNeedInit);
   2224            ANGLE_TRY(initializeContents(context, GL_NONE, index));
   2225            desc.initState = InitState::Initialized;
   2226            anyDirty       = true;
   2227        }
   2228    }
   2229    if (anyDirty)
   2230    {
   2231        signalDirtyStorage(InitState::Initialized);
   2232    }
   2233    mState.mInitState = InitState::Initialized;
   2234 
   2235    return angle::Result::Continue;
   2236 }
   2237 
   2238 InitState Texture::initState(GLenum /*binding*/, const ImageIndex &imageIndex) const
   2239 {
   2240    // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
   2241    // we need to check all the related ImageDescs.
   2242    if (imageIndex.isEntireLevelCubeMap())
   2243    {
   2244        const GLint levelIndex = imageIndex.getLevelIndex();
   2245        for (TextureTarget cubeFaceTarget : AllCubeFaceTextureTargets())
   2246        {
   2247            if (mState.getImageDesc(cubeFaceTarget, levelIndex).initState == InitState::MayNeedInit)
   2248            {
   2249                return InitState::MayNeedInit;
   2250            }
   2251        }
   2252        return InitState::Initialized;
   2253    }
   2254 
   2255    return mState.getImageDesc(imageIndex).initState;
   2256 }
   2257 
   2258 void Texture::setInitState(GLenum binding, const ImageIndex &imageIndex, InitState initState)
   2259 {
   2260    // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
   2261    // we need to update all the related ImageDescs.
   2262    if (imageIndex.isEntireLevelCubeMap())
   2263    {
   2264        const GLint levelIndex = imageIndex.getLevelIndex();
   2265        for (TextureTarget cubeFaceTarget : AllCubeFaceTextureTargets())
   2266        {
   2267            setInitState(binding, ImageIndex::MakeCubeMapFace(cubeFaceTarget, levelIndex),
   2268                         initState);
   2269        }
   2270    }
   2271    else
   2272    {
   2273        ImageDesc newDesc = mState.getImageDesc(imageIndex);
   2274        newDesc.initState = initState;
   2275        mState.setImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex(), newDesc);
   2276    }
   2277 }
   2278 
   2279 void Texture::setInitState(InitState initState)
   2280 {
   2281    for (ImageDesc &imageDesc : mState.mImageDescs)
   2282    {
   2283        // Only modify defined images, undefined images will remain in the initialized state
   2284        if (!imageDesc.size.empty())
   2285        {
   2286            imageDesc.initState = initState;
   2287        }
   2288    }
   2289    mState.mInitState = initState;
   2290 }
   2291 
   2292 bool Texture::doesSubImageNeedInit(const Context *context,
   2293                                   const ImageIndex &imageIndex,
   2294                                   const Box &area) const
   2295 {
   2296    if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
   2297    {
   2298        return false;
   2299    }
   2300 
   2301    // Pre-initialize the texture contents if necessary.
   2302    const ImageDesc &desc = mState.getImageDesc(imageIndex);
   2303    if (desc.initState != InitState::MayNeedInit)
   2304    {
   2305        return false;
   2306    }
   2307 
   2308    ASSERT(mState.mInitState == InitState::MayNeedInit);
   2309    return !area.coversSameExtent(desc.size);
   2310 }
   2311 
   2312 angle::Result Texture::ensureSubImageInitialized(const Context *context,
   2313                                                 const ImageIndex &imageIndex,
   2314                                                 const Box &area)
   2315 {
   2316    if (doesSubImageNeedInit(context, imageIndex, area))
   2317    {
   2318        // NOTE: do not optimize this to only initialize the passed area of the texture, or the
   2319        // initialization logic in copySubImage will be incorrect.
   2320        ANGLE_TRY(initializeContents(context, GL_NONE, imageIndex));
   2321    }
   2322    // Note: binding is ignored for textures.
   2323    setInitState(GL_NONE, imageIndex, InitState::Initialized);
   2324    return angle::Result::Continue;
   2325 }
   2326 
   2327 angle::Result Texture::handleMipmapGenerationHint(Context *context, int level)
   2328 {
   2329    if (getGenerateMipmapHint() == GL_TRUE && level == 0)
   2330    {
   2331        ANGLE_TRY(generateMipmap(context));
   2332    }
   2333 
   2334    return angle::Result::Continue;
   2335 }
   2336 
   2337 void Texture::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
   2338 {
   2339    switch (message)
   2340    {
   2341        case angle::SubjectMessage::ContentsChanged:
   2342            if (index != kBufferSubjectIndex)
   2343            {
   2344                // ContentsChange originates from TextureStorage11::resolveAndReleaseTexture
   2345                // which resolves the underlying multisampled texture if it exists and so
   2346                // Texture will signal dirty storage to invalidate its own cache and the
   2347                // attached framebuffer's cache.
   2348                signalDirtyStorage(InitState::Initialized);
   2349            }
   2350            break;
   2351        case angle::SubjectMessage::DirtyBitsFlagged:
   2352            signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
   2353 
   2354            // Notify siblings that we are dirty.
   2355            if (index == rx::kTextureImageImplObserverMessageIndex)
   2356            {
   2357                notifySiblings(message);
   2358            }
   2359            break;
   2360        case angle::SubjectMessage::SubjectChanged:
   2361            mState.mInitState = InitState::MayNeedInit;
   2362            signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
   2363            onStateChange(angle::SubjectMessage::ContentsChanged);
   2364 
   2365            // Notify siblings that we are dirty.
   2366            if (index == rx::kTextureImageImplObserverMessageIndex)
   2367            {
   2368                notifySiblings(message);
   2369            }
   2370            else if (index == kBufferSubjectIndex)
   2371            {
   2372                const gl::Buffer *buffer = mState.mBuffer.get();
   2373                ASSERT(buffer != nullptr);
   2374 
   2375                // Update cached image desc based on buffer size.
   2376                GLsizeiptr size = GetBoundBufferAvailableSize(mState.mBuffer);
   2377 
   2378                ImageDesc desc          = mState.getImageDesc(TextureTarget::Buffer, 0);
   2379                const GLuint pixelBytes = desc.format.info->pixelBytes;
   2380                desc.size.width         = static_cast<GLuint>(size / pixelBytes);
   2381 
   2382                mState.setImageDesc(TextureTarget::Buffer, 0, desc);
   2383            }
   2384            break;
   2385        case angle::SubjectMessage::StorageReleased:
   2386            // When the TextureStorage is released, it needs to update the
   2387            // RenderTargetCache of the Framebuffer attaching this Texture.
   2388            // This is currently only for D3D back-end. See http://crbug.com/1234829
   2389            if (index == rx::kTextureImageImplObserverMessageIndex)
   2390            {
   2391                onStateChange(angle::SubjectMessage::StorageReleased);
   2392            }
   2393            break;
   2394        case angle::SubjectMessage::SubjectMapped:
   2395        case angle::SubjectMessage::SubjectUnmapped:
   2396        case angle::SubjectMessage::BindingChanged:
   2397            ASSERT(index == kBufferSubjectIndex);
   2398            break;
   2399        case angle::SubjectMessage::InitializationComplete:
   2400            ASSERT(index == rx::kTextureImageImplObserverMessageIndex);
   2401            setInitState(InitState::Initialized);
   2402            break;
   2403        case angle::SubjectMessage::InternalMemoryAllocationChanged:
   2404            // Need to mark the texture dirty to give the back end a chance to handle the new
   2405            // buffer. For example, the Vulkan back end needs to create a new buffer view that
   2406            // points to the newly allocated buffer and update the texture descriptor set.
   2407            signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
   2408            break;
   2409        default:
   2410            UNREACHABLE();
   2411            break;
   2412    }
   2413 }
   2414 
   2415 GLenum Texture::getImplementationColorReadFormat(const Context *context) const
   2416 {
   2417    return mTexture->getColorReadFormat(context);
   2418 }
   2419 
   2420 GLenum Texture::getImplementationColorReadType(const Context *context) const
   2421 {
   2422    return mTexture->getColorReadType(context);
   2423 }
   2424 
   2425 bool Texture::isCompressedFormatEmulated(const Context *context,
   2426                                         TextureTarget target,
   2427                                         GLint level) const
   2428 {
   2429    if (!getFormat(target, level).info->compressed)
   2430    {
   2431        // If it isn't compressed, the remaining logic won't work
   2432        return false;
   2433    }
   2434 
   2435    GLenum implFormat = getImplementationColorReadFormat(context);
   2436 
   2437    // Check against the list of formats used to emulate compressed textures
   2438    return IsEmulatedCompressedFormat(implFormat);
   2439 }
   2440 
   2441 angle::Result Texture::getTexImage(const Context *context,
   2442                                   const PixelPackState &packState,
   2443                                   Buffer *packBuffer,
   2444                                   TextureTarget target,
   2445                                   GLint level,
   2446                                   GLenum format,
   2447                                   GLenum type,
   2448                                   void *pixels)
   2449 {
   2450    // No-op if the image level is empty.
   2451    if (getExtents(target, level).empty())
   2452    {
   2453        return angle::Result::Continue;
   2454    }
   2455 
   2456    return mTexture->getTexImage(context, packState, packBuffer, target, level, format, type,
   2457                                 pixels);
   2458 }
   2459 
   2460 angle::Result Texture::getCompressedTexImage(const Context *context,
   2461                                             const PixelPackState &packState,
   2462                                             Buffer *packBuffer,
   2463                                             TextureTarget target,
   2464                                             GLint level,
   2465                                             void *pixels)
   2466 {
   2467    // No-op if the image level is empty.
   2468    if (getExtents(target, level).empty())
   2469    {
   2470        return angle::Result::Continue;
   2471    }
   2472 
   2473    return mTexture->getCompressedTexImage(context, packState, packBuffer, target, level, pixels);
   2474 }
   2475 
   2476 void Texture::onBindAsImageTexture()
   2477 {
   2478    if (!mState.mHasBeenBoundAsImage)
   2479    {
   2480        mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
   2481        mState.mHasBeenBoundAsImage = true;
   2482    }
   2483 }
   2484 
   2485 void Texture::onBind3DTextureAs2DImage()
   2486 {
   2487    if (!mState.mIs3DAndHasBeenBoundAs2DImage)
   2488    {
   2489        mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
   2490        mState.mIs3DAndHasBeenBoundAs2DImage = true;
   2491    }
   2492 }
   2493 
   2494 }  // namespace gl