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

// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends.

#include "libANGLE/renderer/d3d/TextureD3D.h"

#include "common/mathutil.h"
#include "common/utilities.h"
#include "libANGLE/Buffer.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/Image.h"
#include "libANGLE/Surface.h"
#include "libANGLE/Texture.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/d3d/BufferD3D.h"
#include "libANGLE/renderer/d3d/ContextD3D.h"
#include "libANGLE/renderer/d3d/EGLImageD3D.h"
#include "libANGLE/renderer/d3d/ImageD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/TextureStorage.h"

namespace rx
{

namespace
{

angle::Result GetUnpackPointer(const gl::Context *context,
                               const gl::PixelUnpackState &unpack,
                               gl::Buffer *unpackBuffer,
                               const uint8_t *pixels,
                               ptrdiff_t layerOffset,
                               const uint8_t **pointerOut)
{
    if (unpackBuffer)
    {
        // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not
        // supported
        ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);

        // TODO: this is the only place outside of renderer that asks for a buffers raw data.
        // This functionality should be moved into renderer and the getData method of BufferImpl
        // removed.
        BufferD3D *bufferD3D = GetImplAs<BufferD3D>(unpackBuffer);
        ASSERT(bufferD3D);
        const uint8_t *bufferData = nullptr;
        ANGLE_TRY(bufferD3D->getData(context, &bufferData));
        *pointerOut = bufferData + offset;
    }
    else
    {
        *pointerOut = pixels;
    }

    // Offset the pointer for 2D array layer (if it's valid)
    if (*pointerOut != nullptr)
    {
        *pointerOut += layerOffset;
    }

    return angle::Result::Continue;
}

bool IsRenderTargetUsage(GLenum usage)
{
    return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
}
}  // namespace

TextureD3D::TextureD3D(const gl::TextureState &state, RendererD3D *renderer)
    : TextureImpl(state),
      mRenderer(renderer),
      mDirtyImages(true),
      mImmutable(false),
      mTexStorage(nullptr),
      mTexStorageObserverBinding(this, kTextureStorageObserverMessageIndex),
      mBaseLevel(0)
{}

TextureD3D::~TextureD3D()
{
    ASSERT(!mTexStorage);
}

angle::Result TextureD3D::getNativeTexture(const gl::Context *context, TextureStorage **outStorage)
{
    // ensure the underlying texture is created
    ANGLE_TRY(initializeStorage(context, false));

    if (mTexStorage)
    {
        ANGLE_TRY(updateStorage(context));
    }

    ASSERT(outStorage);

    *outStorage = mTexStorage;
    return angle::Result::Continue;
}

angle::Result TextureD3D::getImageAndSyncFromStorage(const gl::Context *context,
                                                     const gl::ImageIndex &index,
                                                     ImageD3D **outImage)
{
    ImageD3D *image = getImage(index);
    if (mTexStorage && mTexStorage->isRenderTarget())
    {
        ANGLE_TRY(image->copyFromTexStorage(context, index, mTexStorage));
        mDirtyImages = true;
    }
    *outImage = image;
    return angle::Result::Continue;
}

GLint TextureD3D::getLevelZeroWidth() const
{
    ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelWidth())) > getBaseLevel());
    return getBaseLevelWidth() << mBaseLevel;
}

GLint TextureD3D::getLevelZeroHeight() const
{
    ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelHeight())) > getBaseLevel());
    return getBaseLevelHeight() << mBaseLevel;
}

GLint TextureD3D::getLevelZeroDepth() const
{
    return getBaseLevelDepth();
}

GLint TextureD3D::getBaseLevelWidth() const
{
    const ImageD3D *baseImage = getBaseLevelImage();
    return (baseImage ? baseImage->getWidth() : 0);
}

GLint TextureD3D::getBaseLevelHeight() const
{
    const ImageD3D *baseImage = getBaseLevelImage();
    return (baseImage ? baseImage->getHeight() : 0);
}

GLint TextureD3D::getBaseLevelDepth() const
{
    const ImageD3D *baseImage = getBaseLevelImage();
    return (baseImage ? baseImage->getDepth() : 0);
}

// Note: "base level image" is loosely defined to be any image from the base level,
// where in the base of 2D array textures and cube maps there are several. Don't use
// the base level image for anything except querying texture format and size.
GLenum TextureD3D::getBaseLevelInternalFormat() const
{
    const ImageD3D *baseImage = getBaseLevelImage();
    return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
}

angle::Result TextureD3D::setStorage(const gl::Context *context,
                                     gl::TextureType type,
                                     size_t levels,
                                     GLenum internalFormat,
                                     const gl::Extents &size)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D::setStorageMultisample(const gl::Context *context,
                                                gl::TextureType type,
                                                GLsizei samples,
                                                GLint internalformat,
                                                const gl::Extents &size,
                                                bool fixedSampleLocations)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D::setStorageExternalMemory(const gl::Context *context,
                                                   gl::TextureType type,
                                                   size_t levels,
                                                   GLenum internalFormat,
                                                   const gl::Extents &size,
                                                   gl::MemoryObject *memoryObject,
                                                   GLuint64 offset)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
{
    if (!mRenderer->getFeatures().setDataFasterThanImageUpload.enabled)
    {
        return false;
    }

    if (image->isDirty())
    {
        return false;
    }

    gl::InternalFormat internalFormat = gl::GetSizedInternalFormatInfo(image->getInternalFormat());

    // We can only handle full updates for depth-stencil textures, so to avoid complications
    // disable them entirely.
    if (internalFormat.depthBits > 0 || internalFormat.stencilBits > 0)
    {
        return false;
    }

    // TODO(jmadill): Handle compressed internal formats
    return (mTexStorage && !internalFormat.compressed);
}

angle::Result TextureD3D::setImageImpl(const gl::Context *context,
                                       const gl::ImageIndex &index,
                                       GLenum type,
                                       const gl::PixelUnpackState &unpack,
                                       const uint8_t *pixels,
                                       ptrdiff_t layerOffset)
{
    ImageD3D *image          = getImage(index);
    gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
    ASSERT(image);

    // No-op
    if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
    {
        return angle::Result::Continue;
    }

    // We no longer need the "GLenum format" parameter to TexImage to determine what data format
    // "pixels" contains. From our image internal format we know how many channels to expect, and
    // "type" gives the format of pixel's components.
    const uint8_t *pixelData = nullptr;
    ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));

    if (pixelData != nullptr)
    {
        if (shouldUseSetData(image))
        {
            ANGLE_TRY(
                mTexStorage->setData(context, index, image, nullptr, type, unpack, pixelData));
        }
        else
        {
            gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(),
                                  image->getDepth());
            ANGLE_TRY(image->loadData(context, fullImageArea, unpack, type, pixelData,
                                      index.usesTex3D()));
        }

        mDirtyImages = true;
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D::subImage(const gl::Context *context,
                                   const gl::ImageIndex &index,
                                   const gl::Box &area,
                                   GLenum format,
                                   GLenum type,
                                   const gl::PixelUnpackState &unpack,
                                   gl::Buffer *unpackBuffer,
                                   const uint8_t *pixels,
                                   ptrdiff_t layerOffset)
{
    // CPU readback & copy where direct GPU copy is not supported
    const uint8_t *pixelData = nullptr;
    ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));

    if (pixelData != nullptr)
    {
        ImageD3D *image = getImage(index);
        ASSERT(image);

        if (shouldUseSetData(image))
        {
            return mTexStorage->setData(context, index, image, &area, type, unpack, pixelData);
        }

        ANGLE_TRY(image->loadData(context, area, unpack, type, pixelData, index.usesTex3D()));
        ANGLE_TRY(commitRegion(context, index, area));
        mDirtyImages = true;
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D::setCompressedImageImpl(const gl::Context *context,
                                                 const gl::ImageIndex &index,
                                                 const gl::PixelUnpackState &unpack,
                                                 const uint8_t *pixels,
                                                 ptrdiff_t layerOffset)
{
    ImageD3D *image = getImage(index);
    ASSERT(image);

    if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
    {
        return angle::Result::Continue;
    }

    // We no longer need the "GLenum format" parameter to TexImage to determine what data format
    // "pixels" contains. From our image internal format we know how many channels to expect, and
    // "type" gives the format of pixel's components.
    const uint8_t *pixelData = nullptr;
    gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
    ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));

    if (pixelData != nullptr)
    {
        gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
        ANGLE_TRY(image->loadCompressedData(context, fullImageArea, pixelData));

        mDirtyImages = true;
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D::subImageCompressed(const gl::Context *context,
                                             const gl::ImageIndex &index,
                                             const gl::Box &area,
                                             GLenum format,
                                             const gl::PixelUnpackState &unpack,
                                             const uint8_t *pixels,
                                             ptrdiff_t layerOffset)
{
    const uint8_t *pixelData = nullptr;
    gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
    ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));

    if (pixelData != nullptr)
    {
        ImageD3D *image = getImage(index);
        ASSERT(image);

        ANGLE_TRY(image->loadCompressedData(context, area, pixelData));

        mDirtyImages = true;
    }

    return angle::Result::Continue;
}

bool TextureD3D::isFastUnpackable(const gl::Buffer *unpackBuffer, GLenum sizedInternalFormat)
{
    return unpackBuffer != nullptr &&
           mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
}

angle::Result TextureD3D::fastUnpackPixels(const gl::Context *context,
                                           const gl::PixelUnpackState &unpack,
                                           const uint8_t *pixels,
                                           const gl::Box &destArea,
                                           GLenum sizedInternalFormat,
                                           GLenum type,
                                           RenderTargetD3D *destRenderTarget)
{
    bool check = (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 ||
                  unpack.skipImages != 0);
    ANGLE_CHECK(GetImplAs<ContextD3D>(context), !check,
                "Unimplemented pixel store parameters in fastUnpackPixels", GL_INVALID_OPERATION);

    // No-op
    if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
    {
        return angle::Result::Continue;
    }

    // In order to perform the fast copy through the shader, we must have the right format, and be
    // able to create a render target.
    ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));

    uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);

    ANGLE_TRY(mRenderer->fastCopyBufferToTexture(context, unpack, static_cast<unsigned int>(offset),
                                                 destRenderTarget, sizedInternalFormat, type,
                                                 destArea));

    return angle::Result::Continue;
}

GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
{
    // To save memory, do not use mipmaps with STARBOARD -- this configuration
    // only uses bilinear filtering at most, so mipmaps aren't needed.
#if !defined(STARBOARD)
    if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) ||
        mRenderer->getNativeExtensions().textureNPOT)
    {
        // Maximum number of levels
        return gl::log2(std::max(std::max(width, height), depth)) + 1;
    }
    else
#endif
    {
        // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
        return 1;
    }
}

TextureStorage *TextureD3D::getStorage()
{
    ASSERT(mTexStorage);
    return mTexStorage;
}

ImageD3D *TextureD3D::getBaseLevelImage() const
{
    if (mBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    {
        return nullptr;
    }
    return getImage(getImageIndex(mBaseLevel, 0));
}

angle::Result TextureD3D::setImageExternal(const gl::Context *context,
                                           gl::TextureType type,
                                           egl::Stream *stream,
                                           const egl::Stream::GLTextureDescription &desc)
{
    // Only external images can accept external textures
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D::generateMipmap(const gl::Context *context)
{
    const GLuint baseLevel = mState.getEffectiveBaseLevel();
    const GLuint maxLevel  = mState.getMipmapMaxLevel();
    ASSERT(maxLevel > baseLevel);  // Should be checked before calling this.

    if (mTexStorage && mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
    {
        // Switch to using the mipmapped texture.
        TextureStorage *textureStorage = nullptr;
        ANGLE_TRY(getNativeTexture(context, &textureStorage));
        ANGLE_TRY(textureStorage->useLevelZeroWorkaroundTexture(context, false));
    }

    // Set up proper mipmap chain in our Image array.
    ANGLE_TRY(initMipmapImages(context));

    if (mTexStorage && mTexStorage->supportsNativeMipmapFunction())
    {
        ANGLE_TRY(updateStorage(context));

        // Generate the mipmap chain using the ad-hoc DirectX function.
        ANGLE_TRY(mRenderer->generateMipmapUsingD3D(context, mTexStorage, mState));
    }
    else
    {
        // Generate the mipmap chain, one level at a time.
        ANGLE_TRY(generateMipmapUsingImages(context, maxLevel));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D::generateMipmapUsingImages(const gl::Context *context,
                                                    const GLuint maxLevel)
{
    // We know that all layers have the same dimension, for the texture to be complete
    GLint layerCount = static_cast<GLint>(getLayerCount(mBaseLevel));

    // When making mipmaps with the setData workaround enabled, the texture storage has
    // the image data already. For non-render-target storage, we have to pull it out into
    // an image layer.
    if (mRenderer->getFeatures().setDataFasterThanImageUpload.enabled && mTexStorage)
    {
        if (!mTexStorage->isRenderTarget())
        {
            // Copy from the storage mip 0 to Image mip 0
            for (GLint layer = 0; layer < layerCount; ++layer)
            {
                gl::ImageIndex srcIndex = getImageIndex(mBaseLevel, layer);

                ImageD3D *image = getImage(srcIndex);
                ANGLE_TRY(image->copyFromTexStorage(context, srcIndex, mTexStorage));
            }
        }
        else
        {
            ANGLE_TRY(updateStorage(context));
        }
    }

    // TODO: Decouple this from zeroMaxLodWorkaround. This is a 9_3 restriction, unrelated to
    // zeroMaxLodWorkaround. The restriction is because Feature Level 9_3 can't create SRVs on
    // individual levels of the texture. As a result, even if the storage is a rendertarget, we
    // can't use the GPU to generate the mipmaps without further work. The D3D9 renderer works
    // around this by copying each level of the texture into its own single-layer GPU texture (in
    // Blit9::boxFilter). Feature Level 9_3 could do something similar, or it could continue to use
    // CPU-side mipmap generation, or something else.
    bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget() &&
                              !(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled));

    for (GLint layer = 0; layer < layerCount; ++layer)
    {
        for (GLuint mip = mBaseLevel + 1; mip <= maxLevel; ++mip)
        {
            ASSERT(getLayerCount(mip) == layerCount);

            gl::ImageIndex sourceIndex = getImageIndex(mip - 1, layer);
            gl::ImageIndex destIndex   = getImageIndex(mip, layer);

            if (renderableStorage)
            {
                // GPU-side mipmapping
                ANGLE_TRY(mTexStorage->generateMipmap(context, sourceIndex, destIndex));
            }
            else
            {
                // CPU-side mipmapping
                ANGLE_TRY(
                    mRenderer->generateMipmap(context, getImage(destIndex), getImage(sourceIndex)));
            }
        }
    }

    mDirtyImages = true;

    if (mTexStorage)
    {
        ANGLE_TRY(updateStorage(context));
    }

    return angle::Result::Continue;
}

bool TextureD3D::isBaseImageZeroSize() const
{
    ImageD3D *baseImage = getBaseLevelImage();

    if (!baseImage || baseImage->getWidth() <= 0 || baseImage->getHeight() <= 0)
    {
        return true;
    }

    if (baseImage->getType() == gl::TextureType::_3D && baseImage->getDepth() <= 0)
    {
        return true;
    }

    if (baseImage->getType() == gl::TextureType::_2DArray && getLayerCount(getBaseLevel()) <= 0)
    {
        return true;
    }

    return false;
}

angle::Result TextureD3D::ensureRenderTarget(const gl::Context *context)
{
    ANGLE_TRY(initializeStorage(context, true));

    // initializeStorage can fail with NoError if the texture is not complete. This is not
    // an error for incomplete sampling, but it is a big problem for rendering.
    if (!mTexStorage)
    {
        ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
        return angle::Result::Stop;
    }

    if (!isBaseImageZeroSize())
    {
        ASSERT(mTexStorage);
        if (!mTexStorage->isRenderTarget())
        {
            TexStoragePointer newRenderTargetStorage(context);
            ANGLE_TRY(createCompleteStorage(true, &newRenderTargetStorage));

            ANGLE_TRY(mTexStorage->copyToStorage(context, newRenderTargetStorage.get()));
            ANGLE_TRY(setCompleteTexStorage(context, newRenderTargetStorage.get()));
            newRenderTargetStorage.release();
            // If this texture is used in compute shader, we should invalidate this texture so that
            // the UAV/SRV is rebound again with this new texture storage in next dispatch call.
            mTexStorage->invalidateTextures();
        }
    }

    return angle::Result::Continue;
}

bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const
{
    if (index.getType() == gl::TextureType::_2DMultisample ||
        index.getType() == gl::TextureType::_2DMultisampleArray)
    {
        ASSERT(index.getType() != gl::TextureType::_2DMultisampleArray || index.hasLayer());
        return true;
    }

    ImageD3D *image = getImage(index);
    ASSERT(image);
    bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0)));
    return (image->isRenderableFormat() && levelsComplete);
}

angle::Result TextureD3D::commitRegion(const gl::Context *context,
                                       const gl::ImageIndex &index,
                                       const gl::Box &region)
{
    if (mTexStorage)
    {
        ASSERT(isValidIndex(index));
        ImageD3D *image = getImage(index);
        ANGLE_TRY(image->copyToStorage(context, mTexStorage, index, region));
        image->markClean();
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D::getAttachmentRenderTarget(const gl::Context *context,
                                                    GLenum binding,
                                                    const gl::ImageIndex &imageIndex,
                                                    GLsizei samples,
                                                    FramebufferAttachmentRenderTarget **rtOut)
{
    RenderTargetD3D *rtD3D = nullptr;
    ANGLE_TRY(getRenderTarget(context, imageIndex, samples, &rtD3D));
    *rtOut = static_cast<FramebufferAttachmentRenderTarget *>(rtD3D);
    return angle::Result::Continue;
}

angle::Result TextureD3D::setBaseLevel(const gl::Context *context, GLuint baseLevel)
{
    const int oldStorageWidth  = std::max(1, getLevelZeroWidth());
    const int oldStorageHeight = std::max(1, getLevelZeroHeight());
    const int oldStorageDepth  = std::max(1, getLevelZeroDepth());
    const int oldStorageFormat = getBaseLevelInternalFormat();
    mBaseLevel                 = baseLevel;

    // When the base level changes, the texture storage might not be valid anymore, since it could
    // have been created based on the dimensions of the previous specified level range.
    const int newStorageWidth  = std::max(1, getLevelZeroWidth());
    const int newStorageHeight = std::max(1, getLevelZeroHeight());
    const int newStorageDepth  = std::max(1, getLevelZeroDepth());
    const int newStorageFormat = getBaseLevelInternalFormat();
    if (mTexStorage &&
        (newStorageWidth != oldStorageWidth || newStorageHeight != oldStorageHeight ||
         newStorageDepth != oldStorageDepth || newStorageFormat != oldStorageFormat))
    {
        markAllImagesDirty();
        ANGLE_TRY(releaseTexStorage(context));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D::syncState(const gl::Context *context,
                                    const gl::Texture::DirtyBits &dirtyBits)
{
    // This could be improved using dirty bits.
    return angle::Result::Continue;
}

angle::Result TextureD3D::releaseTexStorage(const gl::Context *context)
{
    if (!mTexStorage)
    {
        return angle::Result::Continue;
    }

    auto err = mTexStorage->onDestroy(context);
    SafeDelete(mTexStorage);
    return err;
}

void TextureD3D::onDestroy(const gl::Context *context)
{
    (void)releaseTexStorage(context);
}

angle::Result TextureD3D::initializeContents(const gl::Context *context,
                                             const gl::ImageIndex &imageIndex)
{
    ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
    gl::ImageIndex index   = imageIndex;

    // Special case for D3D11 3D textures. We can't create render targets for individual layers of a
    // 3D texture, so force the clear to the entire mip. There shouldn't ever be a case where we
    // would lose existing data.
    if (index.getType() == gl::TextureType::_3D)
    {
        index = gl::ImageIndex::Make3D(index.getLevelIndex(), gl::ImageIndex::kEntireLevel);
    }
    else if (index.getType() == gl::TextureType::_2DArray && !index.hasLayer())
    {
        std::array<GLint, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> tempLayerCounts;

        GLint levelIndex            = index.getLevelIndex();
        tempLayerCounts[levelIndex] = getLayerCount(levelIndex);
        gl::ImageIndexIterator iterator =
            gl::ImageIndexIterator::Make2DArray(levelIndex, levelIndex + 1, tempLayerCounts.data());
        while (iterator.hasNext())
        {
            ANGLE_TRY(initializeContents(context, iterator.next()));
        }
        return angle::Result::Continue;
    }
    else if (index.getType() == gl::TextureType::_2DMultisampleArray && !index.hasLayer())
    {
        std::array<GLint, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> tempLayerCounts;

        ASSERT(index.getLevelIndex() == 0);
        tempLayerCounts[0] = getLayerCount(0);
        gl::ImageIndexIterator iterator =
            gl::ImageIndexIterator::Make2DMultisampleArray(tempLayerCounts.data());
        while (iterator.hasNext())
        {
            ANGLE_TRY(initializeContents(context, iterator.next()));
        }
        return angle::Result::Continue;
    }

    // Force image clean.
    ImageD3D *image = getImage(index);
    if (image)
    {
        image->markClean();
    }

    // Fast path: can use a render target clear.
    // We don't use the fast path with the zero max lod workaround because it would introduce a race
    // between the rendertarget and the staging images.
    const angle::FeaturesD3D &features = mRenderer->getFeatures();
    bool shouldUseClear                = (image == nullptr);
    if (canCreateRenderTargetForImage(index) && !features.zeroMaxLodWorkaround.enabled &&
        (shouldUseClear || features.allowClearForRobustResourceInit.enabled))
    {
        ANGLE_TRY(ensureRenderTarget(context));
        ASSERT(mTexStorage);
        RenderTargetD3D *renderTarget = nullptr;
        ANGLE_TRY(mTexStorage->getRenderTarget(context, index, 0, &renderTarget));
        ANGLE_TRY(mRenderer->initRenderTarget(context, renderTarget));
        return angle::Result::Continue;
    }

    ASSERT(image != nullptr);

    // Slow path: non-renderable texture or the texture levels aren't set up.
    const auto &formatInfo = gl::GetSizedInternalFormatInfo(image->getInternalFormat());

    GLuint imageBytes = 0;
    ANGLE_CHECK_GL_MATH(contextD3D, formatInfo.computeRowPitch(formatInfo.type, image->getWidth(),
                                                               1, 0, &imageBytes));
    imageBytes *= image->getHeight() * image->getDepth();

    gl::PixelUnpackState zeroDataUnpackState;
    zeroDataUnpackState.alignment = 1;

    angle::MemoryBuffer *zeroBuffer = nullptr;
    ANGLE_CHECK_GL_ALLOC(contextD3D, context->getZeroFilledBuffer(imageBytes, &zeroBuffer));

    if (shouldUseSetData(image))
    {
        ANGLE_TRY(mTexStorage->setData(context, index, image, nullptr, formatInfo.type,
                                       zeroDataUnpackState, zeroBuffer->data()));
    }
    else
    {
        gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
        ANGLE_TRY(image->loadData(context, fullImageArea, zeroDataUnpackState, formatInfo.type,
                                  zeroBuffer->data(), false));

        // Force an update to the tex storage so we avoid problems with subImage and dirty regions.
        if (mTexStorage)
        {
            ANGLE_TRY(commitRegion(context, index, fullImageArea));
            image->markClean();
        }
        else
        {
            mDirtyImages = true;
        }
    }
    return angle::Result::Continue;
}

GLsizei TextureD3D::getRenderToTextureSamples()
{
    if (mTexStorage)
    {
        return mTexStorage->getRenderToTextureSamples();
    }
    return 0;
}

void TextureD3D::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
    onStateChange(message);
}

TextureD3D_2D::TextureD3D_2D(const gl::TextureState &state, RendererD3D *renderer)
    : TextureD3D(state, renderer)
{
    mEGLImageTarget = false;
    for (auto &image : mImageArray)
    {
        image.reset(renderer->createImage());
    }
}

void TextureD3D_2D::onDestroy(const gl::Context *context)
{
    // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
    // for some of their data. If TextureStorage is deleted before the Images, then their data will
    // be wastefully copied back from the GPU before we delete the Images.
    for (auto &image : mImageArray)
    {
        image.reset();
    }
    return TextureD3D::onDestroy(context);
}

TextureD3D_2D::~TextureD3D_2D() {}

ImageD3D *TextureD3D_2D::getImage(int level, int layer) const
{
    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(layer == 0);
    return mImageArray[level].get();
}

ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
{
    ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(!index.hasLayer());
    ASSERT(index.getType() == gl::TextureType::_2D);
    return mImageArray[index.getLevelIndex()].get();
}

GLsizei TextureD3D_2D::getLayerCount(int level) const
{
    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    return 1;
}

GLsizei TextureD3D_2D::getWidth(GLint level) const
{
    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
        return mImageArray[level]->getWidth();
    else
        return 0;
}

GLsizei TextureD3D_2D::getHeight(GLint level) const
{
    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
        return mImageArray[level]->getHeight();
    else
        return 0;
}

GLenum TextureD3D_2D::getInternalFormat(GLint level) const
{
    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
        return mImageArray[level]->getInternalFormat();
    else
        return GL_NONE;
}

bool TextureD3D_2D::isDepth(GLint level) const
{
    return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}

bool TextureD3D_2D::isSRGB(GLint level) const
{
    return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).colorEncoding == GL_SRGB;
}

angle::Result TextureD3D_2D::setImage(const gl::Context *context,
                                      const gl::ImageIndex &index,
                                      GLenum internalFormat,
                                      const gl::Extents &size,
                                      GLenum format,
                                      GLenum type,
                                      const gl::PixelUnpackState &unpack,
                                      const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2D && size.depth == 1);

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);

    bool fastUnpacked = false;

    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
                            size, false));

    // Attempt a fast gpu copy of the pixel data to the surface
    gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
    if (mTexStorage)
    {
        ANGLE_TRY(mTexStorage->releaseMultisampledTexStorageForLevel(index.getLevelIndex()));
    }
    if (isFastUnpackable(unpackBuffer, internalFormatInfo.sizedInternalFormat) &&
        isLevelComplete(index.getLevelIndex()))
    {
        // Will try to create RT storage if it does not exist
        RenderTargetD3D *destRenderTarget = nullptr;
        ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget));

        gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()),
                         1);

        ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea,
                                   internalFormatInfo.sizedInternalFormat, type, destRenderTarget));

        // Ensure we don't overwrite our newly initialized data
        mImageArray[index.getLevelIndex()]->markClean();

        fastUnpacked = true;
    }

    if (!fastUnpacked)
    {
        ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::setSubImage(const gl::Context *context,
                                         const gl::ImageIndex &index,
                                         const gl::Box &area,
                                         GLenum format,
                                         GLenum type,
                                         const gl::PixelUnpackState &unpack,
                                         gl::Buffer *unpackBuffer,
                                         const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2D && area.depth == 1 && area.z == 0);

    GLenum mipFormat = getInternalFormat(index.getLevelIndex());
    if (mTexStorage)
    {
        ANGLE_TRY(mTexStorage->releaseMultisampledTexStorageForLevel(index.getLevelIndex()));
    }
    if (isFastUnpackable(unpackBuffer, mipFormat) && isLevelComplete(index.getLevelIndex()))
    {
        RenderTargetD3D *renderTarget = nullptr;
        ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &renderTarget));
        ASSERT(!mImageArray[index.getLevelIndex()]->isDirty());

        return fastUnpackPixels(context, unpack, pixels, area, mipFormat, type, renderTarget);
    }
    else
    {
        return TextureD3D::subImage(context, index, area, format, type, unpack, unpackBuffer,
                                    pixels, 0);
    }
}

angle::Result TextureD3D_2D::setCompressedImage(const gl::Context *context,
                                                const gl::ImageIndex &index,
                                                GLenum internalFormat,
                                                const gl::Extents &size,
                                                const gl::PixelUnpackState &unpack,
                                                size_t imageSize,
                                                const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2D && size.depth == 1);

    // compressed formats don't have separate sized internal formats-- we can just use the
    // compressed format directly
    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormat, size, false));

    return setCompressedImageImpl(context, index, unpack, pixels, 0);
}

angle::Result TextureD3D_2D::setCompressedSubImage(const gl::Context *context,
                                                   const gl::ImageIndex &index,
                                                   const gl::Box &area,
                                                   GLenum format,
                                                   const gl::PixelUnpackState &unpack,
                                                   size_t imageSize,
                                                   const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2D && area.depth == 1 && area.z == 0);
    ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));

    return commitRegion(context, index, area);
}

angle::Result TextureD3D_2D::copyImage(const gl::Context *context,
                                       const gl::ImageIndex &index,
                                       const gl::Rectangle &sourceArea,
                                       GLenum internalFormat,
                                       gl::Framebuffer *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2D);

    const gl::InternalFormat &internalFormatInfo =
        gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
    gl::Extents sourceExtents(sourceArea.width, sourceArea.height, 1);
    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
                            sourceExtents, false));

    gl::Extents fbSize = source->getReadColorAttachment()->getSize();

    // Does the read area extend beyond the framebuffer?
    bool outside = sourceArea.x < 0 || sourceArea.y < 0 ||
                   sourceArea.x + sourceArea.width > fbSize.width ||
                   sourceArea.y + sourceArea.height > fbSize.height;

    // WebGL requires that pixels that would be outside the framebuffer are treated as zero values,
    // so clear the mip level to 0 prior to making the copy if any pixel would be sampled outside.
    // Same thing for robust resource init.
    if (outside &&
        (context->getExtensions().webglCompatibility || context->isRobustResourceInitEnabled()))
    {
        ANGLE_TRY(initializeContents(context, index));
    }

    gl::Rectangle clippedArea;
    if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
    {
        // Empty source area, nothing to do.
        return angle::Result::Continue;
    }

    gl::Offset destOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y, 0);

    // If the zero max LOD workaround is active, then we can't sample from individual layers of the
    // framebuffer in shaders, so we should use the non-rendering copy path.
    if (!canCreateRenderTargetForImage(index) ||
        mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
    {
        ANGLE_TRY(mImageArray[index.getLevelIndex()]->copyFromFramebuffer(context, destOffset,
                                                                          clippedArea, source));
        mDirtyImages = true;
    }
    else
    {
        ANGLE_TRY(ensureRenderTarget(context));

        if (clippedArea.width != 0 && clippedArea.height != 0 &&
            isValidLevel(index.getLevelIndex()))
        {
            ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
            ANGLE_TRY(mRenderer->copyImage2D(context, source, clippedArea, internalFormat,
                                             destOffset, mTexStorage, index.getLevelIndex()));
        }
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::copySubImage(const gl::Context *context,
                                          const gl::ImageIndex &index,
                                          const gl::Offset &destOffset,
                                          const gl::Rectangle &sourceArea,
                                          gl::Framebuffer *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2D && destOffset.z == 0);

    gl::Extents fbSize = source->getReadColorAttachment()->getSize();
    gl::Rectangle clippedArea;
    if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
    {
        return angle::Result::Continue;
    }
    const gl::Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
                                   destOffset.y + clippedArea.y - sourceArea.y, 0);

    // can only make our texture storage to a render target if level 0 is defined (with a width &
    // height) and the current level we're copying to is defined (with appropriate format, width &
    // height)

    // If the zero max LOD workaround is active, then we can't sample from individual layers of the
    // framebuffer in shaders, so we should use the non-rendering copy path.
    if (!canCreateRenderTargetForImage(index) ||
        mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
    {
        ANGLE_TRY(mImageArray[index.getLevelIndex()]->copyFromFramebuffer(context, clippedOffset,
                                                                          clippedArea, source));
        mDirtyImages = true;
    }
    else
    {
        ANGLE_TRY(ensureRenderTarget(context));

        if (isValidLevel(index.getLevelIndex()))
        {
            ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
            ANGLE_TRY(mRenderer->copyImage2D(context, source, clippedArea,
                                             gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
                                             clippedOffset, mTexStorage, index.getLevelIndex()));
        }
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::copyTexture(const gl::Context *context,
                                         const gl::ImageIndex &index,
                                         GLenum internalFormat,
                                         GLenum type,
                                         size_t sourceLevel,
                                         bool unpackFlipY,
                                         bool unpackPremultiplyAlpha,
                                         bool unpackUnmultiplyAlpha,
                                         const gl::Texture *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2D);

    gl::TextureType sourceType = source->getType();

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
    gl::Extents size(
        static_cast<int>(source->getWidth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
        static_cast<int>(source->getHeight(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
        1);
    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
                            size, false));

    gl::Box sourceBox(0, 0, 0, size.width, size.height, 1);
    gl::Offset destOffset(0, 0, 0);

    if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(index))
    {
        ANGLE_TRY(ensureRenderTarget(context));
        ASSERT(isValidLevel(index.getLevelIndex()));
        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));

        ANGLE_TRY(mRenderer->copyTexture(
            context, source, static_cast<GLint>(sourceLevel), gl::TextureTarget::_2D, sourceBox,
            internalFormatInfo.format, internalFormatInfo.type, destOffset, mTexStorage,
            index.getTarget(), index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha,
            unpackUnmultiplyAlpha));
    }
    else
    {
        gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
        TextureD3D *sourceD3D           = GetImplAs<TextureD3D>(source);
        ImageD3D *sourceImage           = nullptr;
        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));

        ImageD3D *destImage = nullptr;
        ANGLE_TRY(getImageAndSyncFromStorage(context, index, &destImage));

        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));

        mDirtyImages = true;

        gl::Box destRegion(destOffset, size);
        ANGLE_TRY(commitRegion(context, index, destRegion));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::copySubTexture(const gl::Context *context,
                                            const gl::ImageIndex &index,
                                            const gl::Offset &destOffset,
                                            size_t sourceLevel,
                                            const gl::Box &sourceBox,
                                            bool unpackFlipY,
                                            bool unpackPremultiplyAlpha,
                                            bool unpackUnmultiplyAlpha,
                                            const gl::Texture *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2D);

    if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(index))
    {
        ANGLE_TRY(ensureRenderTarget(context));
        ASSERT(isValidLevel(index.getLevelIndex()));
        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));

        const gl::InternalFormat &internalFormatInfo =
            gl::GetSizedInternalFormatInfo(getInternalFormat(index.getLevelIndex()));
        ANGLE_TRY(mRenderer->copyTexture(
            context, source, static_cast<GLint>(sourceLevel), gl::TextureTarget::_2D, sourceBox,
            internalFormatInfo.format, internalFormatInfo.type, destOffset, mTexStorage,
            index.getTarget(), index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha,
            unpackUnmultiplyAlpha));
    }
    else
    {
        gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
        TextureD3D *sourceD3D           = GetImplAs<TextureD3D>(source);
        ImageD3D *sourceImage           = nullptr;
        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));

        ImageD3D *destImage = nullptr;
        ANGLE_TRY(getImageAndSyncFromStorage(context, index, &destImage));

        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));

        mDirtyImages = true;

        gl::Box destRegion(destOffset.x, destOffset.y, 0, sourceBox.width, sourceBox.height, 1);
        ANGLE_TRY(commitRegion(context, index, destRegion));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::copyCompressedTexture(const gl::Context *context,
                                                   const gl::Texture *source)
{
    gl::TextureTarget sourceTarget = NonCubeTextureTypeToTarget(source->getType());
    GLint sourceLevel              = 0;

    GLint destLevel = 0;

    GLenum sizedInternalFormat =
        source->getFormat(sourceTarget, sourceLevel).info->sizedInternalFormat;
    gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
                     static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
    ANGLE_TRY(redefineImage(context, destLevel, sizedInternalFormat, size, false));

    ANGLE_TRY(initializeStorage(context, false));
    ASSERT(mTexStorage);

    ANGLE_TRY(
        mRenderer->copyCompressedTexture(context, source, sourceLevel, mTexStorage, destLevel));

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::setStorage(const gl::Context *context,
                                        gl::TextureType type,
                                        size_t levels,
                                        GLenum internalFormat,
                                        const gl::Extents &size)
{
    ASSERT(type == gl::TextureType::_2D && size.depth == 1);

    for (size_t level = 0; level < levels; level++)
    {
        gl::Extents levelSize(std::max(1, size.width >> level), std::max(1, size.height >> level),
                              1);
        ANGLE_TRY(redefineImage(context, level, internalFormat, levelSize, true));
    }

    for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
    {
        ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true));
    }

    // TODO(geofflang): Verify storage creation had no errors
    bool renderTarget = IsRenderTargetUsage(mState.getUsage());
    TexStoragePointer storage(context);
    storage.reset(mRenderer->createTextureStorage2D(internalFormat, renderTarget, size.width,
                                                    size.height, static_cast<int>(levels), false));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    ANGLE_TRY(updateStorage(context));

    mImmutable = true;

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
    GLenum internalformat = surface->getConfig()->renderTargetFormat;

    gl::Extents size(surface->getWidth(), surface->getHeight(), 1);
    ANGLE_TRY(redefineImage(context, 0, internalformat, size, true));

    ANGLE_TRY(releaseTexStorage(context));

    SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
    ASSERT(surfaceD3D);

    if (surfaceD3D->getSwapChain() == nullptr)
        mTexStorage = mRenderer->createTextureStorage2D(
            surfaceD3D->getD3DTexture(), surfaceD3D->getBindChroma());
    else
        mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain());
    mEGLImageTarget = false;

    mDirtyImages = false;
    mImageArray[0]->markClean();

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::releaseTexImage(const gl::Context *context)
{
    if (mTexStorage)
    {
        ANGLE_TRY(releaseTexStorage(context));
    }

    for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    {
        ANGLE_TRY(redefineImage(context, i, GL_NONE, gl::Extents(0, 0, 1), true));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::setEGLImageTarget(const gl::Context *context,
                                               gl::TextureType type,
                                               egl::Image *image)
{
    EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);

    // Set the properties of the base mip level from the EGL image
    const auto &format = image->getFormat();
    gl::Extents size(static_cast<int>(image->getWidth()), static_cast<int>(image->getHeight()), 1);
    ANGLE_TRY(redefineImage(context, 0, format.info->sizedInternalFormat, size, true));

    // Clear all other images.
    for (size_t level = 1; level < mImageArray.size(); level++)
    {
        ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true));
    }

    ANGLE_TRY(releaseTexStorage(context));
    mImageArray[0]->markClean();

    // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
    RenderTargetD3D *renderTargetD3D = nullptr;
    ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D));

    mTexStorage     = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);
    mEGLImageTarget = true;

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::initMipmapImages(const gl::Context *context)
{
    const GLuint baseLevel = mState.getEffectiveBaseLevel();
    const GLuint maxLevel  = mState.getMipmapMaxLevel();
    // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
    // levels.
    for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
    {
        gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
                              std::max(getLevelZeroHeight() >> level, 1), 1);

        ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
    }
    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::getRenderTarget(const gl::Context *context,
                                             const gl::ImageIndex &index,
                                             GLsizei samples,
                                             RenderTargetD3D **outRT)
{
    ASSERT(!index.hasLayer());

    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget(context));
    ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));

    return mTexStorage->getRenderTarget(context, index, samples, outRT);
}

bool TextureD3D_2D::isValidLevel(int level) const
{
    return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false);
}

bool TextureD3D_2D::isLevelComplete(int level) const
{
    if (isImmutable())
    {
        return true;
    }

    GLsizei width  = getLevelZeroWidth();
    GLsizei height = getLevelZeroHeight();

    if (width <= 0 || height <= 0)
    {
        return false;
    }

    // The base image level is complete if the width and height are positive
    if (level == static_cast<int>(getBaseLevel()))
    {
        return true;
    }

    ASSERT(level >= 0 && level <= static_cast<int>(mImageArray.size()) &&
           mImageArray[level] != nullptr);
    ImageD3D *image = mImageArray[level].get();

    if (image->getInternalFormat() != getBaseLevelInternalFormat())
    {
        return false;
    }

    if (image->getWidth() != std::max(1, width >> level))
    {
        return false;
    }

    if (image->getHeight() != std::max(1, height >> level))
    {
        return false;
    }

    return true;
}

bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const
{
    return isLevelComplete(index.getLevelIndex());
}

// Constructs a native texture resource from the texture images
angle::Result TextureD3D_2D::initializeStorage(const gl::Context *context, bool renderTarget)
{
    // Only initialize the first time this texture is used as a render target or shader resource
    if (mTexStorage)
    {
        return angle::Result::Continue;
    }

    // do not attempt to create storage for nonexistant data
    if (!isLevelComplete(getBaseLevel()))
    {
        return angle::Result::Continue;
    }

    bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));

    TexStoragePointer storage(context);
    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    ASSERT(mTexStorage);

    // flush image data to the storage
    ANGLE_TRY(updateStorage(context));

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::createCompleteStorage(bool renderTarget,
                                                   TexStoragePointer *outStorage) const
{
    GLsizei width         = getLevelZeroWidth();
    GLsizei height        = getLevelZeroHeight();
    GLenum internalFormat = getBaseLevelInternalFormat();

    ASSERT(width > 0 && height > 0);

    // use existing storage level count, when previously specified by TexStorage*D
    GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));

    bool hintLevelZeroOnly = false;
    if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
    {
        // If any of the CPU images (levels >= 1) are dirty, then the textureStorage2D should use
        // the mipped texture to begin with. Otherwise, it should use the level-zero-only texture.
        hintLevelZeroOnly = true;
        for (int level = 1; level < levels && hintLevelZeroOnly; level++)
        {
            hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(level));
        }
    }

    // TODO(geofflang): Determine if the texture creation succeeded
    outStorage->reset(mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height,
                                                        levels, hintLevelZeroOnly));

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::setCompleteTexStorage(const gl::Context *context,
                                                   TextureStorage *newCompleteTexStorage)
{
    if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
    {
        for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
        {
            ANGLE_TRY(
                mImageArray[level]->setManagedSurface2D(context, newCompleteTexStorage, level));
        }
    }

    ANGLE_TRY(releaseTexStorage(context));
    mTexStorage = newCompleteTexStorage;
    mTexStorageObserverBinding.bind(mTexStorage);

    mDirtyImages = true;

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::updateStorage(const gl::Context *context)
{
    if (!mDirtyImages)
    {
        return angle::Result::Continue;
    }

    ASSERT(mTexStorage != nullptr);
    GLint storageLevels = mTexStorage->getLevelCount();
    for (int level = 0; level < storageLevels; level++)
    {
        if (mImageArray[level]->isDirty() && isLevelComplete(level))
        {
            ANGLE_TRY(updateStorageLevel(context, level));
        }
    }

    mDirtyImages = false;
    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::updateStorageLevel(const gl::Context *context, int level)
{
    ASSERT(level <= static_cast<int>(mImageArray.size()) && mImageArray[level] != nullptr);
    ASSERT(isLevelComplete(level));

    if (mImageArray[level]->isDirty())
    {
        gl::ImageIndex index = gl::ImageIndex::Make2D(level);
        gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
        ANGLE_TRY(commitRegion(context, index, region));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2D::redefineImage(const gl::Context *context,
                                           size_t level,
                                           GLenum internalformat,
                                           const gl::Extents &size,
                                           bool forceRelease)
{
    ASSERT(size.depth == 1);

    // If there currently is a corresponding storage texture image, it has these parameters
    const int storageWidth     = std::max(1, getLevelZeroWidth() >> level);
    const int storageHeight    = std::max(1, getLevelZeroHeight() >> level);
    const GLenum storageFormat = getBaseLevelInternalFormat();

    mImageArray[level]->redefine(gl::TextureType::_2D, internalformat, size, forceRelease);
    mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();

    if (mTexStorage)
    {
        const size_t storageLevels = mTexStorage->getLevelCount();

        // If the storage was from an EGL image, copy it back into local images to preserve it
        // while orphaning
        if (level != 0 && mEGLImageTarget)
        {
            ANGLE_TRY(mImageArray[0]->copyFromTexStorage(context, gl::ImageIndex::Make2D(0),
                                                         mTexStorage));
        }

        if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
            size.height != storageHeight ||
            internalformat != storageFormat)  // Discard mismatched storage
        {
            ANGLE_TRY(releaseTexStorage(context));
            markAllImagesDirty();
        }
    }

    // Can't be an EGL image target after being redefined
    mEGLImageTarget = false;

    return angle::Result::Continue;
}

gl::ImageIndexIterator TextureD3D_2D::imageIterator() const
{
    return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
}

gl::ImageIndex TextureD3D_2D::getImageIndex(GLint mip, GLint /*layer*/) const
{
    // "layer" does not apply to 2D Textures.
    return gl::ImageIndex::Make2D(mip);
}

bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const
{
    return (mTexStorage && index.getType() == gl::TextureType::_2D && index.getLevelIndex() >= 0 &&
            index.getLevelIndex() < mTexStorage->getLevelCount());
}

void TextureD3D_2D::markAllImagesDirty()
{
    for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    {
        mImageArray[i]->markDirty();
    }
    mDirtyImages = true;
}

TextureD3D_Cube::TextureD3D_Cube(const gl::TextureState &state, RendererD3D *renderer)
    : TextureD3D(state, renderer)
{
    for (auto &face : mImageArray)
    {
        for (auto &image : face)
        {
            image.reset(renderer->createImage());
        }
    }
}

void TextureD3D_Cube::onDestroy(const gl::Context *context)
{
    // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
    // for some of their data. If TextureStorage is deleted before the Images, then their data will
    // be wastefully copied back from the GPU before we delete the Images.
    for (auto &face : mImageArray)
    {
        for (auto &image : face)
        {
            image.reset();
        }
    }
    return TextureD3D::onDestroy(context);
}

TextureD3D_Cube::~TextureD3D_Cube() {}

ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const
{
    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(layer >= 0 && static_cast<size_t>(layer) < gl::kCubeFaceCount);
    return mImageArray[layer][level].get();
}

ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
{
    ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(gl::IsCubeMapFaceTarget(index.getTarget()));
    return mImageArray[index.cubeMapFaceIndex()][index.getLevelIndex()].get();
}

GLsizei TextureD3D_Cube::getLayerCount(int level) const
{
    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    return gl::kCubeFaceCount;
}

GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const
{
    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
        return mImageArray[layer][level]->getInternalFormat();
    else
        return GL_NONE;
}

bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const
{
    return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
}

bool TextureD3D_Cube::isSRGB(GLint level, GLint layer) const
{
    return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).colorEncoding == GL_SRGB;
}

angle::Result TextureD3D_Cube::setEGLImageTarget(const gl::Context *context,
                                                 gl::TextureType type,
                                                 egl::Image *image)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::setImage(const gl::Context *context,
                                        const gl::ImageIndex &index,
                                        GLenum internalFormat,
                                        const gl::Extents &size,
                                        GLenum format,
                                        GLenum type,
                                        const gl::PixelUnpackState &unpack,
                                        const uint8_t *pixels)
{
    ASSERT(size.depth == 1);

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
    ANGLE_TRY(redefineImage(context, index.cubeMapFaceIndex(), index.getLevelIndex(),
                            internalFormatInfo.sizedInternalFormat, size, false));

    return setImageImpl(context, index, type, unpack, pixels, 0);
}

angle::Result TextureD3D_Cube::setSubImage(const gl::Context *context,
                                           const gl::ImageIndex &index,
                                           const gl::Box &area,
                                           GLenum format,
                                           GLenum type,
                                           const gl::PixelUnpackState &unpack,
                                           gl::Buffer *unpackBuffer,
                                           const uint8_t *pixels)
{
    ASSERT(area.depth == 1 && area.z == 0);
    return TextureD3D::subImage(context, index, area, format, type, unpack, unpackBuffer, pixels,
                                0);
}

angle::Result TextureD3D_Cube::setCompressedImage(const gl::Context *context,
                                                  const gl::ImageIndex &index,
                                                  GLenum internalFormat,
                                                  const gl::Extents &size,
                                                  const gl::PixelUnpackState &unpack,
                                                  size_t imageSize,
                                                  const uint8_t *pixels)
{
    ASSERT(size.depth == 1);

    // compressed formats don't have separate sized internal formats-- we can just use the
    // compressed format directly
    ANGLE_TRY(redefineImage(context, index.cubeMapFaceIndex(), index.getLevelIndex(),
                            internalFormat, size, false));

    return setCompressedImageImpl(context, index, unpack, pixels, 0);
}

angle::Result TextureD3D_Cube::setCompressedSubImage(const gl::Context *context,
                                                     const gl::ImageIndex &index,
                                                     const gl::Box &area,
                                                     GLenum format,
                                                     const gl::PixelUnpackState &unpack,
                                                     size_t imageSize,
                                                     const uint8_t *pixels)
{
    ASSERT(area.depth == 1 && area.z == 0);

    ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
    return commitRegion(context, index, area);
}

angle::Result TextureD3D_Cube::copyImage(const gl::Context *context,
                                         const gl::ImageIndex &index,
                                         const gl::Rectangle &sourceArea,
                                         GLenum internalFormat,
                                         gl::Framebuffer *source)
{
    GLint faceIndex = index.cubeMapFaceIndex();
    const gl::InternalFormat &internalFormatInfo =
        gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);

    gl::Extents size(sourceArea.width, sourceArea.height, 1);
    ANGLE_TRY(redefineImage(context, faceIndex, index.getLevelIndex(),
                            internalFormatInfo.sizedInternalFormat, size, false));

    gl::Extents fbSize = source->getReadColorAttachment()->getSize();

    // Does the read area extend beyond the framebuffer?
    bool outside = sourceArea.x < 0 || sourceArea.y < 0 ||
                   sourceArea.x + sourceArea.width > fbSize.width ||
                   sourceArea.y + sourceArea.height > fbSize.height;

    // WebGL requires that pixels that would be outside the framebuffer are treated as zero values,
    // so clear the mip level to 0 prior to making the copy if any pixel would be sampled outside.
    // Same thing for robust resource init.
    if (outside &&
        (context->getExtensions().webglCompatibility || context->isRobustResourceInitEnabled()))
    {
        ANGLE_TRY(initializeContents(context, index));
    }

    gl::Rectangle clippedArea;
    if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
    {
        // Empty source area, nothing to do.
        return angle::Result::Continue;
    }

    gl::Offset destOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y, 0);

    // If the zero max LOD workaround is active, then we can't sample from individual layers of the
    // framebuffer in shaders, so we should use the non-rendering copy path.
    if (!canCreateRenderTargetForImage(index) ||
        mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
    {
        ANGLE_TRY(mImageArray[faceIndex][index.getLevelIndex()]->copyFromFramebuffer(
            context, destOffset, clippedArea, source));
        mDirtyImages = true;
    }
    else
    {
        ANGLE_TRY(ensureRenderTarget(context));

        ASSERT(size.width == size.height);

        if (size.width > 0 && isValidFaceLevel(faceIndex, index.getLevelIndex()))
        {
            ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
            ANGLE_TRY(mRenderer->copyImageCube(context, source, clippedArea, internalFormat,
                                               destOffset, mTexStorage, index.getTarget(),
                                               index.getLevelIndex()));
        }
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::copySubImage(const gl::Context *context,
                                            const gl::ImageIndex &index,
                                            const gl::Offset &destOffset,
                                            const gl::Rectangle &sourceArea,
                                            gl::Framebuffer *source)
{
    gl::Extents fbSize = source->getReadColorAttachment()->getSize();
    gl::Rectangle clippedArea;
    if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
    {
        return angle::Result::Continue;
    }
    const gl::Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
                                   destOffset.y + clippedArea.y - sourceArea.y, 0);

    GLint faceIndex = index.cubeMapFaceIndex();

    // If the zero max LOD workaround is active, then we can't sample from individual layers of the
    // framebuffer in shaders, so we should use the non-rendering copy path.
    if (!canCreateRenderTargetForImage(index) ||
        mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
    {
        ANGLE_TRY(mImageArray[faceIndex][index.getLevelIndex()]->copyFromFramebuffer(
            context, clippedOffset, clippedArea, source));
        mDirtyImages = true;
    }
    else
    {
        ANGLE_TRY(ensureRenderTarget(context));
        if (isValidFaceLevel(faceIndex, index.getLevelIndex()))
        {
            ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
            ANGLE_TRY(mRenderer->copyImageCube(
                context, source, clippedArea, gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
                clippedOffset, mTexStorage, index.getTarget(), index.getLevelIndex()));
        }
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::copyTexture(const gl::Context *context,
                                           const gl::ImageIndex &index,
                                           GLenum internalFormat,
                                           GLenum type,
                                           size_t sourceLevel,
                                           bool unpackFlipY,
                                           bool unpackPremultiplyAlpha,
                                           bool unpackUnmultiplyAlpha,
                                           const gl::Texture *source)
{
    ASSERT(gl::IsCubeMapFaceTarget(index.getTarget()));

    gl::TextureTarget sourceTarget = NonCubeTextureTypeToTarget(source->getType());

    GLint faceIndex = index.cubeMapFaceIndex();

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
    gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
                     static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
    ANGLE_TRY(redefineImage(context, faceIndex, index.getLevelIndex(),
                            internalFormatInfo.sizedInternalFormat, size, false));

    gl::Box sourceBox(0, 0, 0, size.width, size.height, 1);
    gl::Offset destOffset(0, 0, 0);

    if (!isSRGB(index.getLevelIndex(), faceIndex) && canCreateRenderTargetForImage(index))
    {

        ANGLE_TRY(ensureRenderTarget(context));
        ASSERT(isValidFaceLevel(faceIndex, index.getLevelIndex()));
        ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));

        ANGLE_TRY(mRenderer->copyTexture(
            context, source, static_cast<GLint>(sourceLevel), gl::TextureTarget::_2D, sourceBox,
            internalFormatInfo.format, internalFormatInfo.type, destOffset, mTexStorage,
            index.getTarget(), index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha,
            unpackUnmultiplyAlpha));
    }
    else
    {
        gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
        TextureD3D *sourceD3D           = GetImplAs<TextureD3D>(source);
        ImageD3D *sourceImage           = nullptr;
        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));

        ImageD3D *destImage = nullptr;
        ANGLE_TRY(getImageAndSyncFromStorage(context, index, &destImage));

        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));

        mDirtyImages = true;

        gl::Box destRegion(destOffset, size);
        ANGLE_TRY(commitRegion(context, index, destRegion));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::copySubTexture(const gl::Context *context,
                                              const gl::ImageIndex &index,
                                              const gl::Offset &destOffset,
                                              size_t sourceLevel,
                                              const gl::Box &sourceBox,
                                              bool unpackFlipY,
                                              bool unpackPremultiplyAlpha,
                                              bool unpackUnmultiplyAlpha,
                                              const gl::Texture *source)
{
    ASSERT(gl::IsCubeMapFaceTarget(index.getTarget()));

    GLint faceIndex = index.cubeMapFaceIndex();

    if (!isSRGB(index.getLevelIndex(), faceIndex) && canCreateRenderTargetForImage(index))
    {
        ANGLE_TRY(ensureRenderTarget(context));
        ASSERT(isValidFaceLevel(faceIndex, index.getLevelIndex()));
        ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));

        const gl::InternalFormat &internalFormatInfo =
            gl::GetSizedInternalFormatInfo(getInternalFormat(index.getLevelIndex(), faceIndex));
        ANGLE_TRY(mRenderer->copyTexture(
            context, source, static_cast<GLint>(sourceLevel), gl::TextureTarget::_2D, sourceBox,
            internalFormatInfo.format, internalFormatInfo.type, destOffset, mTexStorage,
            index.getTarget(), index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha,
            unpackUnmultiplyAlpha));
    }
    else
    {
        gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(static_cast<GLint>(sourceLevel));
        TextureD3D *sourceD3D           = GetImplAs<TextureD3D>(source);
        ImageD3D *sourceImage           = nullptr;
        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));

        ImageD3D *destImage = nullptr;
        ANGLE_TRY(getImageAndSyncFromStorage(context, index, &destImage));

        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));

        mDirtyImages = true;

        gl::Box destRegion(destOffset.x, destOffset.y, 0, sourceBox.width, sourceBox.height, 1);
        ANGLE_TRY(commitRegion(context, index, destRegion));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::setStorage(const gl::Context *context,
                                          gl::TextureType type,
                                          size_t levels,
                                          GLenum internalFormat,
                                          const gl::Extents &size)
{
    ASSERT(size.width == size.height);
    ASSERT(size.depth == 1);

    for (size_t level = 0; level < levels; level++)
    {
        GLsizei mipSize = std::max(1, size.width >> level);
        for (size_t faceIndex = 0; faceIndex < gl::kCubeFaceCount; faceIndex++)
        {
            mImageArray[faceIndex][level]->redefine(gl::TextureType::CubeMap, internalFormat,
                                                    gl::Extents(mipSize, mipSize, 1), true);
        }
    }

    for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
    {
        for (size_t faceIndex = 0; faceIndex < gl::kCubeFaceCount; faceIndex++)
        {
            mImageArray[faceIndex][level]->redefine(gl::TextureType::CubeMap, GL_NONE,
                                                    gl::Extents(0, 0, 0), true);
        }
    }

    // TODO(geofflang): Verify storage creation had no errors
    bool renderTarget = IsRenderTargetUsage(mState.getUsage());

    TexStoragePointer storage(context);
    storage.reset(mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width,
                                                      static_cast<int>(levels), false));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    ANGLE_TRY(updateStorage(context));

    mImmutable = true;

    return angle::Result::Continue;
}

// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool TextureD3D_Cube::isCubeComplete() const
{
    int baseWidth     = getBaseLevelWidth();
    int baseHeight    = getBaseLevelHeight();
    GLenum baseFormat = getBaseLevelInternalFormat();

    if (baseWidth <= 0 || baseWidth != baseHeight)
    {
        return false;
    }

    for (size_t faceIndex = 1; faceIndex < gl::kCubeFaceCount; faceIndex++)
    {
        const ImageD3D &faceBaseImage = *mImageArray[faceIndex][getBaseLevel()];

        if (faceBaseImage.getWidth() != baseWidth || faceBaseImage.getHeight() != baseHeight ||
            faceBaseImage.getInternalFormat() != baseFormat)
        {
            return false;
        }
    }

    return true;
}

angle::Result TextureD3D_Cube::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::releaseTexImage(const gl::Context *context)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::initMipmapImages(const gl::Context *context)
{
    const GLuint baseLevel = mState.getEffectiveBaseLevel();
    const GLuint maxLevel  = mState.getMipmapMaxLevel();
    // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
    // levels.
    for (int faceIndex = 0; faceIndex < static_cast<int>(gl::kCubeFaceCount); faceIndex++)
    {
        for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
        {
            int faceLevelSize =
                (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1));
            ANGLE_TRY(redefineImage(context, faceIndex, level,
                                    mImageArray[faceIndex][baseLevel]->getInternalFormat(),
                                    gl::Extents(faceLevelSize, faceLevelSize, 1), false));
        }
    }
    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::getRenderTarget(const gl::Context *context,
                                               const gl::ImageIndex &index,
                                               GLsizei samples,
                                               RenderTargetD3D **outRT)
{
    ASSERT(gl::IsCubeMapFaceTarget(index.getTarget()));

    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget(context));
    ANGLE_TRY(updateStorageFaceLevel(context, index.cubeMapFaceIndex(), index.getLevelIndex()));

    return mTexStorage->getRenderTarget(context, index, samples, outRT);
}

angle::Result TextureD3D_Cube::initializeStorage(const gl::Context *context, bool renderTarget)
{
    // Only initialize the first time this texture is used as a render target or shader resource
    if (mTexStorage)
    {
        return angle::Result::Continue;
    }

    // do not attempt to create storage for nonexistant data
    if (!isFaceLevelComplete(0, getBaseLevel()))
    {
        return angle::Result::Continue;
    }

    bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));

    TexStoragePointer storage(context);
    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    ASSERT(mTexStorage);

    // flush image data to the storage
    ANGLE_TRY(updateStorage(context));

    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::createCompleteStorage(bool renderTarget,
                                                     TexStoragePointer *outStorage) const
{
    GLsizei size = getLevelZeroWidth();

    ASSERT(size > 0);

    // use existing storage level count, when previously specified by TexStorage*D
    GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1));

    bool hintLevelZeroOnly = false;
    if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
    {
        // If any of the CPU images (levels >= 1) are dirty, then the textureStorage should use the
        // mipped texture to begin with. Otherwise, it should use the level-zero-only texture.
        hintLevelZeroOnly = true;
        for (int faceIndex = 0;
             faceIndex < static_cast<int>(gl::kCubeFaceCount) && hintLevelZeroOnly; faceIndex++)
        {
            for (int level = 1; level < levels && hintLevelZeroOnly; level++)
            {
                hintLevelZeroOnly = !(mImageArray[faceIndex][level]->isDirty() &&
                                      isFaceLevelComplete(faceIndex, level));
            }
        }
    }

    // TODO (geofflang): detect if storage creation succeeded
    outStorage->reset(mRenderer->createTextureStorageCube(
        getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly));

    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::setCompleteTexStorage(const gl::Context *context,
                                                     TextureStorage *newCompleteTexStorage)
{
    if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
    {
        for (int faceIndex = 0; faceIndex < static_cast<int>(gl::kCubeFaceCount); faceIndex++)
        {
            for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
            {
                ANGLE_TRY(mImageArray[faceIndex][level]->setManagedSurfaceCube(
                    context, newCompleteTexStorage, faceIndex, level));
            }
        }
    }

    ANGLE_TRY(releaseTexStorage(context));
    mTexStorage = newCompleteTexStorage;
    mTexStorageObserverBinding.bind(mTexStorage);

    mDirtyImages = true;
    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::updateStorage(const gl::Context *context)
{
    if (!mDirtyImages)
    {
        return angle::Result::Continue;
    }

    ASSERT(mTexStorage != nullptr);
    GLint storageLevels = mTexStorage->getLevelCount();
    for (int face = 0; face < static_cast<int>(gl::kCubeFaceCount); face++)
    {
        for (int level = 0; level < storageLevels; level++)
        {
            if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level))
            {
                ANGLE_TRY(updateStorageFaceLevel(context, face, level));
            }
        }
    }

    mDirtyImages = false;
    return angle::Result::Continue;
}

bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const
{
    return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
}

bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const
{
    if (getBaseLevel() >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    {
        return false;
    }
    ASSERT(level >= 0 && static_cast<size_t>(faceIndex) < gl::kCubeFaceCount &&
           level < static_cast<int>(mImageArray[faceIndex].size()) &&
           mImageArray[faceIndex][level] != nullptr);

    if (isImmutable())
    {
        return true;
    }

    int levelZeroSize = getLevelZeroWidth();

    if (levelZeroSize <= 0)
    {
        return false;
    }

    // Check that non-zero levels are consistent with the base level.
    const ImageD3D *faceLevelImage = mImageArray[faceIndex][level].get();

    if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
    {
        return false;
    }

    if (faceLevelImage->getWidth() != std::max(1, levelZeroSize >> level))
    {
        return false;
    }

    return true;
}

bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const
{
    return isFaceLevelComplete(index.cubeMapFaceIndex(), index.getLevelIndex());
}

angle::Result TextureD3D_Cube::updateStorageFaceLevel(const gl::Context *context,
                                                      int faceIndex,
                                                      int level)
{
    ASSERT(level >= 0 && static_cast<size_t>(faceIndex) < gl::kCubeFaceCount &&
           level < static_cast<int>(mImageArray[faceIndex].size()) &&
           mImageArray[faceIndex][level] != nullptr);
    ImageD3D *image = mImageArray[faceIndex][level].get();

    if (image->isDirty())
    {
        gl::TextureTarget faceTarget = gl::CubeFaceIndexToTextureTarget(faceIndex);
        gl::ImageIndex index         = gl::ImageIndex::MakeCubeMapFace(faceTarget, level);
        gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
        ANGLE_TRY(commitRegion(context, index, region));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_Cube::redefineImage(const gl::Context *context,
                                             int faceIndex,
                                             GLint level,
                                             GLenum internalformat,
                                             const gl::Extents &size,
                                             bool forceRelease)
{
    // If there currently is a corresponding storage texture image, it has these parameters
    const int storageWidth     = std::max(1, getLevelZeroWidth() >> level);
    const int storageHeight    = std::max(1, getLevelZeroHeight() >> level);
    const GLenum storageFormat = getBaseLevelInternalFormat();

    mImageArray[faceIndex][level]->redefine(gl::TextureType::CubeMap, internalformat, size,
                                            forceRelease);
    mDirtyImages = mDirtyImages || mImageArray[faceIndex][level]->isDirty();

    if (mTexStorage)
    {
        const int storageLevels = mTexStorage->getLevelCount();

        if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
            size.height != storageHeight ||
            internalformat != storageFormat)  // Discard mismatched storage
        {
            markAllImagesDirty();
            ANGLE_TRY(releaseTexStorage(context));
        }
    }

    return angle::Result::Continue;
}

gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const
{
    return gl::ImageIndexIterator::MakeCube(0, mTexStorage->getLevelCount());
}

gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const
{
    // The "layer" of the image index corresponds to the cube face
    return gl::ImageIndex::MakeCubeMapFace(gl::CubeFaceIndexToTextureTarget(layer), mip);
}

bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const
{
    return (mTexStorage && index.getType() == gl::TextureType::CubeMap &&
            gl::IsCubeMapFaceTarget(index.getTarget()) && index.getLevelIndex() >= 0 &&
            index.getLevelIndex() < mTexStorage->getLevelCount());
}

void TextureD3D_Cube::markAllImagesDirty()
{
    for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
    {
        for (size_t dirtyFace = 0; dirtyFace < gl::kCubeFaceCount; dirtyFace++)
        {
            mImageArray[dirtyFace][dirtyLevel]->markDirty();
        }
    }
    mDirtyImages = true;
}

TextureD3D_3D::TextureD3D_3D(const gl::TextureState &state, RendererD3D *renderer)
    : TextureD3D(state, renderer)
{
    for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
    {
        mImageArray[i].reset(renderer->createImage());
    }
}

void TextureD3D_3D::onDestroy(const gl::Context *context)
{
    // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
    // for some of their data. If TextureStorage is deleted before the Images, then their data will
    // be wastefully copied back from the GPU before we delete the Images.
    for (auto &image : mImageArray)
    {
        image.reset();
    }
    return TextureD3D::onDestroy(context);
}

TextureD3D_3D::~TextureD3D_3D() {}

ImageD3D *TextureD3D_3D::getImage(int level, int layer) const
{
    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(layer == 0);
    return mImageArray[level].get();
}

ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
{
    ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(!index.hasLayer());
    ASSERT(index.getType() == gl::TextureType::_3D);
    return mImageArray[index.getLevelIndex()].get();
}

GLsizei TextureD3D_3D::getLayerCount(int level) const
{
    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    return 1;
}

GLsizei TextureD3D_3D::getWidth(GLint level) const
{
    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
        return mImageArray[level]->getWidth();
    else
        return 0;
}

GLsizei TextureD3D_3D::getHeight(GLint level) const
{
    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
        return mImageArray[level]->getHeight();
    else
        return 0;
}

GLsizei TextureD3D_3D::getDepth(GLint level) const
{
    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
        return mImageArray[level]->getDepth();
    else
        return 0;
}

GLenum TextureD3D_3D::getInternalFormat(GLint level) const
{
    if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
        return mImageArray[level]->getInternalFormat();
    else
        return GL_NONE;
}

bool TextureD3D_3D::isDepth(GLint level) const
{
    return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}

bool TextureD3D_3D::isSRGB(GLint level) const
{
    return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).colorEncoding == GL_SRGB;
}

angle::Result TextureD3D_3D::setEGLImageTarget(const gl::Context *context,
                                               gl::TextureType type,
                                               egl::Image *image)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::setImage(const gl::Context *context,
                                      const gl::ImageIndex &index,
                                      GLenum internalFormat,
                                      const gl::Extents &size,
                                      GLenum format,
                                      GLenum type,
                                      const gl::PixelUnpackState &unpack,
                                      const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_3D);
    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);

    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
                            size, false));

    bool fastUnpacked = false;

    // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
    gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
    if (isFastUnpackable(unpackBuffer, internalFormatInfo.sizedInternalFormat) && !size.empty() &&
        isLevelComplete(index.getLevelIndex()))
    {
        // Will try to create RT storage if it does not exist
        RenderTargetD3D *destRenderTarget = nullptr;
        ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget));

        gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()),
                         getDepth(index.getLevelIndex()));

        ANGLE_TRY(fastUnpackPixels(context, unpack, pixels, destArea,
                                   internalFormatInfo.sizedInternalFormat, type, destRenderTarget));

        // Ensure we don't overwrite our newly initialized data
        mImageArray[index.getLevelIndex()]->markClean();

        fastUnpacked = true;
    }

    if (!fastUnpacked)
    {
        ANGLE_TRY(setImageImpl(context, index, type, unpack, pixels, 0));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::setSubImage(const gl::Context *context,
                                         const gl::ImageIndex &index,
                                         const gl::Box &area,
                                         GLenum format,
                                         GLenum type,
                                         const gl::PixelUnpackState &unpack,
                                         gl::Buffer *unpackBuffer,
                                         const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_3D);

    // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
    GLenum mipFormat = getInternalFormat(index.getLevelIndex());
    if (isFastUnpackable(unpackBuffer, mipFormat) && isLevelComplete(index.getLevelIndex()))
    {
        RenderTargetD3D *destRenderTarget = nullptr;
        ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget));
        ASSERT(!mImageArray[index.getLevelIndex()]->isDirty());

        return fastUnpackPixels(context, unpack, pixels, area, mipFormat, type, destRenderTarget);
    }
    else
    {
        return TextureD3D::subImage(context, index, area, format, type, unpack, unpackBuffer,
                                    pixels, 0);
    }
}

angle::Result TextureD3D_3D::setCompressedImage(const gl::Context *context,
                                                const gl::ImageIndex &index,
                                                GLenum internalFormat,
                                                const gl::Extents &size,
                                                const gl::PixelUnpackState &unpack,
                                                size_t imageSize,
                                                const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_3D);

    // compressed formats don't have separate sized internal formats-- we can just use the
    // compressed format directly
    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormat, size, false));

    return setCompressedImageImpl(context, index, unpack, pixels, 0);
}

angle::Result TextureD3D_3D::setCompressedSubImage(const gl::Context *context,
                                                   const gl::ImageIndex &index,
                                                   const gl::Box &area,
                                                   GLenum format,
                                                   const gl::PixelUnpackState &unpack,
                                                   size_t imageSize,
                                                   const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_3D);

    ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
    return commitRegion(context, index, area);
}

angle::Result TextureD3D_3D::copyImage(const gl::Context *context,
                                       const gl::ImageIndex &index,
                                       const gl::Rectangle &sourceArea,
                                       GLenum internalFormat,
                                       gl::Framebuffer *source)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::copySubImage(const gl::Context *context,
                                          const gl::ImageIndex &index,
                                          const gl::Offset &destOffset,
                                          const gl::Rectangle &sourceArea,
                                          gl::Framebuffer *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_3D);

    gl::Extents fbSize = source->getReadColorAttachment()->getSize();
    gl::Rectangle clippedSourceArea;
    if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
                       &clippedSourceArea))
    {
        return angle::Result::Continue;
    }
    const gl::Offset clippedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
                                       destOffset.y + clippedSourceArea.y - sourceArea.y,
                                       destOffset.z);

    // Currently, copying directly to the storage is not possible because it's not possible to
    // create an SRV from a single layer of a 3D texture.  Instead, make sure the image is up to
    // date before the copy and then copy back to the storage afterwards if needed.
    // TODO: Investigate 3D blits in D3D11.

    bool syncTexStorage = mTexStorage && isLevelComplete(index.getLevelIndex());
    if (syncTexStorage)
    {
        ANGLE_TRY(
            mImageArray[index.getLevelIndex()]->copyFromTexStorage(context, index, mTexStorage));
    }
    ANGLE_TRY(mImageArray[index.getLevelIndex()]->copyFromFramebuffer(context, clippedDestOffset,
                                                                      clippedSourceArea, source));
    mDirtyImages = true;

    if (syncTexStorage)
    {
        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::copyTexture(const gl::Context *context,
                                         const gl::ImageIndex &index,
                                         GLenum internalFormat,
                                         GLenum type,
                                         size_t sourceLevel,
                                         bool unpackFlipY,
                                         bool unpackPremultiplyAlpha,
                                         bool unpackUnmultiplyAlpha,
                                         const gl::Texture *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_3D);

    gl::TextureType sourceType = source->getType();

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
    gl::Extents size(
        static_cast<int>(source->getWidth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
        static_cast<int>(source->getHeight(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
        static_cast<int>(source->getDepth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)));

    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
                            size, false));

    gl::Box sourceBox(0, 0, 0, size.width, size.height, size.depth);
    gl::Offset destOffset(0, 0, 0);
    gl::ImageIndex destIndex = gl::ImageIndex::Make3D(static_cast<GLint>(index.getLevelIndex()));

    if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(destIndex))
    {
        ANGLE_TRY(ensureRenderTarget(context));
        ASSERT(isValidLevel(index.getLevelIndex()));
        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));

        ANGLE_TRY(mRenderer->copyTexture(
            context, source, static_cast<GLint>(sourceLevel), gl::TextureTarget::_3D, sourceBox,
            internalFormatInfo.format, internalFormatInfo.type, destOffset, mTexStorage,
            index.getTarget(), index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha,
            unpackUnmultiplyAlpha));
    }
    else
    {
        gl::ImageIndex sourceIndex = gl::ImageIndex::Make3D(static_cast<GLint>(sourceLevel));
        ImageD3D *sourceImage      = nullptr;
        ImageD3D *destImage        = nullptr;
        TextureD3D *sourceD3D      = GetImplAs<TextureD3D>(source);

        ANGLE_TRY(getImageAndSyncFromStorage(context, destIndex, &destImage));
        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceIndex, &sourceImage));

        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));

        mDirtyImages = true;

        gl::Box destRegion(0, 0, 0, sourceBox.width, sourceBox.height, sourceBox.depth);
        ANGLE_TRY(commitRegion(context, destIndex, destRegion));
    }

    return angle::Result::Continue;
}
angle::Result TextureD3D_3D::copySubTexture(const gl::Context *context,
                                            const gl::ImageIndex &index,
                                            const gl::Offset &destOffset,
                                            size_t sourceLevel,
                                            const gl::Box &sourceBox,
                                            bool unpackFlipY,
                                            bool unpackPremultiplyAlpha,
                                            bool unpackUnmultiplyAlpha,
                                            const gl::Texture *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_3D);

    gl::ImageIndex destIndex = gl::ImageIndex::Make3D(static_cast<GLint>(index.getLevelIndex()));

    if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(destIndex))
    {
        ANGLE_TRY(ensureRenderTarget(context));
        ASSERT(isValidLevel(index.getLevelIndex()));
        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));

        const gl::InternalFormat &internalFormatInfo =
            gl::GetSizedInternalFormatInfo(getInternalFormat(index.getLevelIndex()));
        ANGLE_TRY(mRenderer->copyTexture(
            context, source, static_cast<GLint>(sourceLevel), gl::TextureTarget::_3D, sourceBox,
            internalFormatInfo.format, internalFormatInfo.type, destOffset, mTexStorage,
            index.getTarget(), index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha,
            unpackUnmultiplyAlpha));
    }
    else
    {
        gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make3D(static_cast<GLint>(sourceLevel));
        TextureD3D *sourceD3D           = GetImplAs<TextureD3D>(source);
        ImageD3D *sourceImage           = nullptr;
        ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));

        ImageD3D *destImage = nullptr;
        ANGLE_TRY(getImageAndSyncFromStorage(context, destIndex, &destImage));

        ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
                                       unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));

        mDirtyImages = true;

        gl::Box destRegion(destOffset.x, destOffset.y, destOffset.z, sourceBox.width,
                           sourceBox.height, sourceBox.depth);
        ANGLE_TRY(commitRegion(context, destIndex, destRegion));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::setStorage(const gl::Context *context,
                                        gl::TextureType type,
                                        size_t levels,
                                        GLenum internalFormat,
                                        const gl::Extents &size)
{
    ASSERT(type == gl::TextureType::_3D);

    for (size_t level = 0; level < levels; level++)
    {
        gl::Extents levelSize(std::max(1, size.width >> level), std::max(1, size.height >> level),
                              std::max(1, size.depth >> level));
        mImageArray[level]->redefine(gl::TextureType::_3D, internalFormat, levelSize, true);
    }

    for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
    {
        mImageArray[level]->redefine(gl::TextureType::_3D, GL_NONE, gl::Extents(0, 0, 0), true);
    }

    // TODO(geofflang): Verify storage creation had no errors
    bool renderTarget = IsRenderTargetUsage(mState.getUsage());
    TexStoragePointer storage(context);
    storage.reset(mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width,
                                                    size.height, size.depth,
                                                    static_cast<int>(levels)));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    ANGLE_TRY(updateStorage(context));

    mImmutable = true;

    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::releaseTexImage(const gl::Context *context)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::initMipmapImages(const gl::Context *context)
{
    const GLuint baseLevel = mState.getEffectiveBaseLevel();
    const GLuint maxLevel  = mState.getMipmapMaxLevel();
    // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
    // levels.
    for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
    {
        gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
                              std::max(getLevelZeroHeight() >> level, 1),
                              std::max(getLevelZeroDepth() >> level, 1));
        ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::getRenderTarget(const gl::Context *context,
                                             const gl::ImageIndex &index,
                                             GLsizei samples,
                                             RenderTargetD3D **outRT)
{
    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget(context));

    if (index.hasLayer())
    {
        ANGLE_TRY(updateStorage(context));
    }
    else
    {
        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
    }

    return mTexStorage->getRenderTarget(context, index, samples, outRT);
}

angle::Result TextureD3D_3D::initializeStorage(const gl::Context *context, bool renderTarget)
{
    // Only initialize the first time this texture is used as a render target or shader resource
    if (mTexStorage)
    {
        return angle::Result::Continue;
    }

    // do not attempt to create storage for nonexistant data
    if (!isLevelComplete(getBaseLevel()))
    {
        return angle::Result::Continue;
    }

    bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));

    TexStoragePointer storage(context);
    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    ASSERT(mTexStorage);

    // flush image data to the storage
    ANGLE_TRY(updateStorage(context));

    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::createCompleteStorage(bool renderTarget,
                                                   TexStoragePointer *outStorage) const
{
    GLsizei width         = getLevelZeroWidth();
    GLsizei height        = getLevelZeroHeight();
    GLsizei depth         = getLevelZeroDepth();
    GLenum internalFormat = getBaseLevelInternalFormat();

    ASSERT(width > 0 && height > 0 && depth > 0);

    // use existing storage level count, when previously specified by TexStorage*D
    GLint levels =
        (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));

    // TODO: Verify creation of the storage succeeded
    outStorage->reset(mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height,
                                                        depth, levels));

    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::setCompleteTexStorage(const gl::Context *context,
                                                   TextureStorage *newCompleteTexStorage)
{
    ANGLE_TRY(releaseTexStorage(context));
    mTexStorage = newCompleteTexStorage;
    mTexStorageObserverBinding.bind(mTexStorage);
    mDirtyImages = true;

    // We do not support managed 3D storage, as that is D3D9/ES2-only
    ASSERT(!mTexStorage->isManaged());

    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::updateStorage(const gl::Context *context)
{
    if (!mDirtyImages)
    {
        return angle::Result::Continue;
    }

    ASSERT(mTexStorage != nullptr);
    GLint storageLevels = mTexStorage->getLevelCount();
    for (int level = 0; level < storageLevels; level++)
    {
        if (mImageArray[level]->isDirty() && isLevelComplete(level))
        {
            ANGLE_TRY(updateStorageLevel(context, level));
        }
    }

    mDirtyImages = false;
    return angle::Result::Continue;
}

bool TextureD3D_3D::isValidLevel(int level) const
{
    return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
}

bool TextureD3D_3D::isLevelComplete(int level) const
{
    ASSERT(level >= 0 && level < static_cast<int>(mImageArray.size()) &&
           mImageArray[level] != nullptr);

    if (isImmutable())
    {
        return true;
    }

    GLsizei width  = getLevelZeroWidth();
    GLsizei height = getLevelZeroHeight();
    GLsizei depth  = getLevelZeroDepth();

    if (width <= 0 || height <= 0 || depth <= 0)
    {
        return false;
    }

    if (level == static_cast<int>(getBaseLevel()))
    {
        return true;
    }

    ImageD3D *levelImage = mImageArray[level].get();

    if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
    {
        return false;
    }

    if (levelImage->getWidth() != std::max(1, width >> level))
    {
        return false;
    }

    if (levelImage->getHeight() != std::max(1, height >> level))
    {
        return false;
    }

    if (levelImage->getDepth() != std::max(1, depth >> level))
    {
        return false;
    }

    return true;
}

bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const
{
    return isLevelComplete(index.getLevelIndex());
}

angle::Result TextureD3D_3D::updateStorageLevel(const gl::Context *context, int level)
{
    ASSERT(level >= 0 && level < static_cast<int>(mImageArray.size()) &&
           mImageArray[level] != nullptr);
    ASSERT(isLevelComplete(level));

    if (mImageArray[level]->isDirty())
    {
        gl::ImageIndex index = gl::ImageIndex::Make3D(level);
        gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
        ANGLE_TRY(commitRegion(context, index, region));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_3D::redefineImage(const gl::Context *context,
                                           GLint level,
                                           GLenum internalformat,
                                           const gl::Extents &size,
                                           bool forceRelease)
{
    // If there currently is a corresponding storage texture image, it has these parameters
    const int storageWidth     = std::max(1, getLevelZeroWidth() >> level);
    const int storageHeight    = std::max(1, getLevelZeroHeight() >> level);
    const int storageDepth     = std::max(1, getLevelZeroDepth() >> level);
    const GLenum storageFormat = getBaseLevelInternalFormat();

    mImageArray[level]->redefine(gl::TextureType::_3D, internalformat, size, forceRelease);
    mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();

    if (mTexStorage)
    {
        const int storageLevels = mTexStorage->getLevelCount();

        if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
            size.height != storageHeight || size.depth != storageDepth ||
            internalformat != storageFormat)  // Discard mismatched storage
        {
            markAllImagesDirty();
            ANGLE_TRY(releaseTexStorage(context));
        }
    }

    return angle::Result::Continue;
}

gl::ImageIndexIterator TextureD3D_3D::imageIterator() const
{
    return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(),
                                          gl::ImageIndex::kEntireLevel,
                                          gl::ImageIndex::kEntireLevel);
}

gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const
{
    // The "layer" here does not apply to 3D images. We use one Image per mip.
    return gl::ImageIndex::Make3D(mip);
}

bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const
{
    return (mTexStorage && index.getType() == gl::TextureType::_3D && index.getLevelIndex() >= 0 &&
            index.getLevelIndex() < mTexStorage->getLevelCount());
}

void TextureD3D_3D::markAllImagesDirty()
{
    for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    {
        mImageArray[i]->markDirty();
    }
    mDirtyImages = true;
}

GLint TextureD3D_3D::getLevelZeroDepth() const
{
    ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelDepth())) > getBaseLevel());
    return getBaseLevelDepth() << getBaseLevel();
}

TextureD3D_2DArray::TextureD3D_2DArray(const gl::TextureState &state, RendererD3D *renderer)
    : TextureD3D(state, renderer)
{
    for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
    {
        mLayerCounts[level] = 0;
        mImageArray[level]  = nullptr;
    }
}

void TextureD3D_2DArray::onDestroy(const gl::Context *context)
{
    // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
    // for some of their data. If TextureStorage is deleted before the Images, then their data will
    // be wastefully copied back from the GPU before we delete the Images.
    deleteImages();
    return TextureD3D::onDestroy(context);
}

TextureD3D_2DArray::~TextureD3D_2DArray() {}

ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const
{
    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT((layer == 0 && mLayerCounts[level] == 0) || layer < mLayerCounts[level]);
    return (mImageArray[level] ? mImageArray[level][layer] : nullptr);
}

ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
{
    ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(index.hasLayer());
    ASSERT((index.getLayerIndex() == 0 && mLayerCounts[index.getLevelIndex()] == 0) ||
           index.getLayerIndex() < mLayerCounts[index.getLevelIndex()]);
    ASSERT(index.getType() == gl::TextureType::_2DArray);
    return (mImageArray[index.getLevelIndex()]
                ? mImageArray[index.getLevelIndex()][index.getLayerIndex()]
                : nullptr);
}

GLsizei TextureD3D_2DArray::getLayerCount(int level) const
{
    ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    return mLayerCounts[level];
}

GLsizei TextureD3D_2DArray::getWidth(GLint level) const
{
    return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0)
               ? mImageArray[level][0]->getWidth()
               : 0;
}

GLsizei TextureD3D_2DArray::getHeight(GLint level) const
{
    return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0)
               ? mImageArray[level][0]->getHeight()
               : 0;
}

GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const
{
    return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0)
               ? mImageArray[level][0]->getInternalFormat()
               : GL_NONE;
}

bool TextureD3D_2DArray::isDepth(GLint level) const
{
    return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}

bool TextureD3D_2DArray::isSRGB(GLint level) const
{
    return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).colorEncoding == GL_SRGB;
}

angle::Result TextureD3D_2DArray::setEGLImageTarget(const gl::Context *context,
                                                    gl::TextureType type,
                                                    egl::Image *image)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::setImage(const gl::Context *context,
                                           const gl::ImageIndex &index,
                                           GLenum internalFormat,
                                           const gl::Extents &size,
                                           GLenum format,
                                           GLenum type,
                                           const gl::PixelUnpackState &unpack,
                                           const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);

    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);

    ANGLE_TRY(
        redefineImage(context, index.getLevelIndex(), formatInfo.sizedInternalFormat, size, false));

    ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);

    GLuint inputDepthPitch = 0;
    ANGLE_CHECK_GL_MATH(contextD3D, formatInfo.computeDepthPitch(
                                        type, size.width, size.height, unpack.alignment,
                                        unpack.rowLength, unpack.imageHeight, &inputDepthPitch));

    for (int i = 0; i < size.depth; i++)
    {
        const ptrdiff_t layerOffset = (inputDepthPitch * i);
        gl::ImageIndex layerIndex   = gl::ImageIndex::Make2DArray(index.getLevelIndex(), i);
        ANGLE_TRY(setImageImpl(context, layerIndex, type, unpack, pixels, layerOffset));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::setSubImage(const gl::Context *context,
                                              const gl::ImageIndex &index,
                                              const gl::Box &area,
                                              GLenum format,
                                              GLenum type,
                                              const gl::PixelUnpackState &unpack,
                                              gl::Buffer *unpackBuffer,
                                              const uint8_t *pixels)
{
    ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);

    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
    const gl::InternalFormat &formatInfo =
        gl::GetInternalFormatInfo(getInternalFormat(index.getLevelIndex()), type);
    GLuint inputDepthPitch = 0;
    ANGLE_CHECK_GL_MATH(contextD3D, formatInfo.computeDepthPitch(
                                        type, area.width, area.height, unpack.alignment,
                                        unpack.rowLength, unpack.imageHeight, &inputDepthPitch));

    for (int i = 0; i < area.depth; i++)
    {
        int layer                   = area.z + i;
        const ptrdiff_t layerOffset = (inputDepthPitch * i);

        gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);

        gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), layer);
        ANGLE_TRY(TextureD3D::subImage(context, layerIndex, layerArea, format, type, unpack,
                                       unpackBuffer, pixels, layerOffset));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::setCompressedImage(const gl::Context *context,
                                                     const gl::ImageIndex &index,
                                                     GLenum internalFormat,
                                                     const gl::Extents &size,
                                                     const gl::PixelUnpackState &unpack,
                                                     size_t imageSize,
                                                     const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);

    ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);

    // compressed formats don't have separate sized internal formats-- we can just use the
    // compressed format directly
    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormat, size, false));

    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
    GLuint inputDepthPitch               = 0;
    ANGLE_CHECK_GL_MATH(
        contextD3D, formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0,
                                                 &inputDepthPitch));

    for (int i = 0; i < size.depth; i++)
    {
        const ptrdiff_t layerOffset = (inputDepthPitch * i);

        gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), i);
        ANGLE_TRY(setCompressedImageImpl(context, layerIndex, unpack, pixels, layerOffset));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::setCompressedSubImage(const gl::Context *context,
                                                        const gl::ImageIndex &index,
                                                        const gl::Box &area,
                                                        GLenum format,
                                                        const gl::PixelUnpackState &unpack,
                                                        size_t imageSize,
                                                        const uint8_t *pixels)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);

    ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);

    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
    GLuint inputDepthPitch               = 0;
    ANGLE_CHECK_GL_MATH(
        contextD3D, formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0,
                                                 &inputDepthPitch));

    for (int i = 0; i < area.depth; i++)
    {
        int layer                   = area.z + i;
        const ptrdiff_t layerOffset = (inputDepthPitch * i);

        gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);

        gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), layer);
        ANGLE_TRY(TextureD3D::subImageCompressed(context, layerIndex, layerArea, format, unpack,
                                                 pixels, layerOffset));
        ANGLE_TRY(commitRegion(context, layerIndex, layerArea));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::copyImage(const gl::Context *context,
                                            const gl::ImageIndex &index,
                                            const gl::Rectangle &sourceArea,
                                            GLenum internalFormat,
                                            gl::Framebuffer *source)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::copySubImage(const gl::Context *context,
                                               const gl::ImageIndex &index,
                                               const gl::Offset &destOffset,
                                               const gl::Rectangle &sourceArea,
                                               gl::Framebuffer *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);

    gl::Extents fbSize = source->getReadColorAttachment()->getSize();
    gl::Rectangle clippedSourceArea;
    if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
                       &clippedSourceArea))
    {
        return angle::Result::Continue;
    }
    const gl::Offset clippedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
                                       destOffset.y + clippedSourceArea.y - sourceArea.y,
                                       destOffset.z);

    if (!canCreateRenderTargetForImage(index))
    {
        gl::Offset destLayerOffset(clippedDestOffset.x, clippedDestOffset.y, 0);
        ANGLE_TRY(mImageArray[index.getLevelIndex()][clippedDestOffset.z]->copyFromFramebuffer(
            context, destLayerOffset, clippedSourceArea, source));
        mDirtyImages = true;
    }
    else
    {
        ANGLE_TRY(ensureRenderTarget(context));

        if (isValidLevel(index.getLevelIndex()))
        {
            ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
            ANGLE_TRY(
                mRenderer->copyImage2DArray(context, source, clippedSourceArea,
                                            gl::GetUnsizedFormat(getInternalFormat(getBaseLevel())),
                                            clippedDestOffset, mTexStorage, index.getLevelIndex()));
        }
    }
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::copyTexture(const gl::Context *context,
                                              const gl::ImageIndex &index,
                                              GLenum internalFormat,
                                              GLenum type,
                                              size_t sourceLevel,
                                              bool unpackFlipY,
                                              bool unpackPremultiplyAlpha,
                                              bool unpackUnmultiplyAlpha,
                                              const gl::Texture *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);

    gl::TextureType sourceType = source->getType();

    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
    gl::Extents size(
        static_cast<int>(source->getWidth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
        static_cast<int>(source->getHeight(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
        static_cast<int>(source->getDepth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)));

    ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
                            size, false));

    gl::Box sourceBox(0, 0, 0, size.width, size.height, size.depth);
    gl::Offset destOffset(0, 0, 0);

    gl::ImageIndex destIndex =
        gl::ImageIndex::Make2DArrayRange(index.getLevelIndex(), 0, size.depth);

    if (!isSRGB(index.getLevelIndex()) &&
        canCreateRenderTargetForImage(
            gl::ImageIndex::Make2DArrayRange(index.getLevelIndex(), 0, size.depth)))
    {
        ANGLE_TRY(ensureRenderTarget(context));
        ASSERT(isValidLevel(index.getLevelIndex()));
        ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
        ANGLE_TRY(mRenderer->copyTexture(
            context, source, static_cast<GLint>(sourceLevel), gl::TextureTarget::_2DArray,
            sourceBox, internalFormatInfo.format, internalFormatInfo.type, destOffset, mTexStorage,
            index.getTarget(), index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha,
            unpackUnmultiplyAlpha));
    }
    else
    {
        for (int i = 0; i < size.depth; i++)
        {
            gl::ImageIndex currentSourceDepthIndex =
                gl::ImageIndex::Make2DArray(static_cast<GLint>(sourceLevel), i);
            gl::ImageIndex currentDestDepthIndex =
                gl::ImageIndex::Make2DArray(static_cast<GLint>(index.getLevelIndex()), i);
            ImageD3D *sourceImage = nullptr;
            ImageD3D *destImage   = nullptr;
            TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);

            ANGLE_TRY(getImageAndSyncFromStorage(context, currentDestDepthIndex, &destImage));
            ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, currentSourceDepthIndex,
                                                            &sourceImage));
            gl::Box imageBox(sourceBox.x, sourceBox.y, 0, sourceBox.width, sourceBox.height, 1);
            ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, imageBox, destOffset,
                                           unpackFlipY, unpackPremultiplyAlpha,
                                           unpackUnmultiplyAlpha));
        }

        mDirtyImages = true;

        gl::Box destRegion(destOffset.x, destOffset.y, destOffset.z, sourceBox.width,
                           sourceBox.height, sourceBox.depth);
        ANGLE_TRY(commitRegion(context, destIndex, destRegion));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::copySubTexture(const gl::Context *context,
                                                 const gl::ImageIndex &index,
                                                 const gl::Offset &destOffset,
                                                 size_t sourceLevel,
                                                 const gl::Box &sourceBox,
                                                 bool unpackFlipY,
                                                 bool unpackPremultiplyAlpha,
                                                 bool unpackUnmultiplyAlpha,
                                                 const gl::Texture *source)
{
    ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);

    gl::ImageIndex destIndex = gl::ImageIndex::Make2DArrayRange(
        static_cast<GLint>(index.getLevelIndex()), destOffset.z, sourceBox.depth - destOffset.z);

    if (!isSRGB(destIndex.getLevelIndex()) && canCreateRenderTargetForImage(destIndex))
    {
        ANGLE_TRY(ensureRenderTarget(context));
        ASSERT(isValidLevel(destIndex.getLevelIndex()));
        ANGLE_TRY(updateStorageLevel(context, destIndex.getLevelIndex()));

        const gl::InternalFormat &internalFormatInfo =
            gl::GetSizedInternalFormatInfo(getInternalFormat(destIndex.getLevelIndex()));
        ANGLE_TRY(mRenderer->copyTexture(
            context, source, static_cast<GLint>(sourceLevel), gl::TextureTarget::_2DArray,
            sourceBox, internalFormatInfo.format, internalFormatInfo.type, destOffset, mTexStorage,
            index.getTarget(), index.getLevelIndex(), unpackFlipY, unpackPremultiplyAlpha,
            unpackUnmultiplyAlpha));
    }
    else
    {
        for (int i = 0; i < sourceBox.depth; i++)
        {
            gl::ImageIndex currentSourceIndex =
                gl::ImageIndex::Make2DArray(static_cast<GLint>(sourceLevel), i + sourceBox.z);
            gl::ImageIndex currentDestIndex = gl::ImageIndex::Make2DArray(
                static_cast<GLint>(index.getLevelIndex()), i + destOffset.z);

            gl::Box currentLayerBox(sourceBox.x, sourceBox.y, 0, sourceBox.width, sourceBox.height,
                                    1);

            TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
            ImageD3D *sourceImage = nullptr;
            ANGLE_TRY(
                sourceD3D->getImageAndSyncFromStorage(context, currentSourceIndex, &sourceImage));

            ImageD3D *destImage = nullptr;
            ANGLE_TRY(getImageAndSyncFromStorage(context, currentDestIndex, &destImage));

            ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, currentLayerBox,
                                           destOffset, unpackFlipY, unpackPremultiplyAlpha,
                                           unpackUnmultiplyAlpha));
        }

        mDirtyImages = true;

        gl::Box destRegion(destOffset.x, destOffset.y, destOffset.z, sourceBox.width,
                           sourceBox.height, sourceBox.depth);
        ANGLE_TRY(commitRegion(context, destIndex, destRegion));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::setStorage(const gl::Context *context,
                                             gl::TextureType type,
                                             size_t levels,
                                             GLenum internalFormat,
                                             const gl::Extents &size)
{
    ASSERT(type == gl::TextureType::_2DArray);

    deleteImages();

    for (size_t level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
    {
        gl::Extents levelLayerSize(std::max(1, size.width >> level),
                                   std::max(1, size.height >> level), 1);

        mLayerCounts[level] = (level < levels ? size.depth : 0);

        if (mLayerCounts[level] > 0)
        {
            // Create new images for this level
            mImageArray[level] = new ImageD3D *[mLayerCounts[level]];

            for (int layer = 0; layer < mLayerCounts[level]; layer++)
            {
                mImageArray[level][layer] = mRenderer->createImage();
                mImageArray[level][layer]->redefine(gl::TextureType::_2DArray, internalFormat,
                                                    levelLayerSize, true);
            }
        }
    }

    // TODO(geofflang): Verify storage creation had no errors
    bool renderTarget = IsRenderTargetUsage(mState.getUsage());
    TexStoragePointer storage(context);
    storage.reset(mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width,
                                                         size.height, size.depth,
                                                         static_cast<int>(levels)));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    ANGLE_TRY(updateStorage(context));

    mImmutable = true;

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::releaseTexImage(const gl::Context *context)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::initMipmapImages(const gl::Context *context)
{
    const GLuint baseLevel = mState.getEffectiveBaseLevel();
    const GLuint maxLevel  = mState.getMipmapMaxLevel();
    int baseWidth          = getLevelZeroWidth();
    int baseHeight         = getLevelZeroHeight();
    int baseDepth          = getLayerCount(getBaseLevel());
    GLenum baseFormat      = getBaseLevelInternalFormat();

    // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
    // levels.
    for (GLuint level = baseLevel + 1u; level <= maxLevel; level++)
    {
        ASSERT((baseWidth >> level) > 0 || (baseHeight >> level) > 0);
        gl::Extents levelLayerSize(std::max(baseWidth >> level, 1),
                                   std::max(baseHeight >> level, 1), baseDepth);
        ANGLE_TRY(redefineImage(context, level, baseFormat, levelLayerSize, false));
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::getRenderTarget(const gl::Context *context,
                                                  const gl::ImageIndex &index,
                                                  GLsizei samples,
                                                  RenderTargetD3D **outRT)
{
    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget(context));
    ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
    return mTexStorage->getRenderTarget(context, index, samples, outRT);
}

angle::Result TextureD3D_2DArray::initializeStorage(const gl::Context *context, bool renderTarget)
{
    // Only initialize the first time this texture is used as a render target or shader resource
    if (mTexStorage)
    {
        return angle::Result::Continue;
    }

    // do not attempt to create storage for nonexistant data
    if (!isLevelComplete(getBaseLevel()))
    {
        return angle::Result::Continue;
    }

    bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mState.getUsage()));

    TexStoragePointer storage(context);
    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    ASSERT(mTexStorage);

    // flush image data to the storage
    ANGLE_TRY(updateStorage(context));

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::createCompleteStorage(bool renderTarget,
                                                        TexStoragePointer *outStorage) const
{
    GLsizei width         = getLevelZeroWidth();
    GLsizei height        = getLevelZeroHeight();
    GLsizei depth         = getLayerCount(getBaseLevel());
    GLenum internalFormat = getBaseLevelInternalFormat();

    ASSERT(width > 0 && height > 0 && depth > 0);

    // use existing storage level count, when previously specified by TexStorage*D
    GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));

    // TODO(geofflang): Verify storage creation succeeds
    outStorage->reset(mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width,
                                                             height, depth, levels));

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::setCompleteTexStorage(const gl::Context *context,
                                                        TextureStorage *newCompleteTexStorage)
{
    ANGLE_TRY(releaseTexStorage(context));
    mTexStorage = newCompleteTexStorage;
    mTexStorageObserverBinding.bind(mTexStorage);
    mDirtyImages = true;

    // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only
    ASSERT(!mTexStorage->isManaged());

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DArray::updateStorage(const gl::Context *context)
{
    if (!mDirtyImages)
    {
        return angle::Result::Continue;
    }

    ASSERT(mTexStorage != nullptr);
    GLint storageLevels = mTexStorage->getLevelCount();
    for (int level = 0; level < storageLevels; level++)
    {
        if (isLevelComplete(level))
        {
            ANGLE_TRY(updateStorageLevel(context, level));
        }
    }

    mDirtyImages = false;
    return angle::Result::Continue;
}

bool TextureD3D_2DArray::isValidLevel(int level) const
{
    return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
}

bool TextureD3D_2DArray::isLevelComplete(int level) const
{
    ASSERT(level >= 0 && level < (int)ArraySize(mImageArray));

    if (isImmutable())
    {
        return true;
    }

    GLsizei width  = getLevelZeroWidth();
    GLsizei height = getLevelZeroHeight();

    if (width <= 0 || height <= 0)
    {
        return false;
    }

    // Layers check needs to happen after the above checks, otherwise out-of-range base level may be
    // queried.
    GLsizei layers = getLayerCount(getBaseLevel());

    if (layers <= 0)
    {
        return false;
    }

    if (level == static_cast<int>(getBaseLevel()))
    {
        return true;
    }

    if (getInternalFormat(level) != getInternalFormat(getBaseLevel()))
    {
        return false;
    }

    if (getWidth(level) != std::max(1, width >> level))
    {
        return false;
    }

    if (getHeight(level) != std::max(1, height >> level))
    {
        return false;
    }

    if (getLayerCount(level) != layers)
    {
        return false;
    }

    return true;
}

bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const
{
    return isLevelComplete(index.getLevelIndex());
}

angle::Result TextureD3D_2DArray::updateStorageLevel(const gl::Context *context, int level)
{
    ASSERT(level >= 0 && level < static_cast<int>(ArraySize(mLayerCounts)));
    ASSERT(isLevelComplete(level));

    for (int layer = 0; layer < mLayerCounts[level]; layer++)
    {
        ASSERT(mImageArray[level] != nullptr && mImageArray[level][layer] != nullptr);
        if (mImageArray[level][layer]->isDirty())
        {
            gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
            gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
            ANGLE_TRY(commitRegion(context, index, region));
        }
    }

    return angle::Result::Continue;
}

void TextureD3D_2DArray::deleteImages()
{
    for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
    {
        for (int layer = 0; layer < mLayerCounts[level]; ++layer)
        {
            delete mImageArray[level][layer];
        }
        delete[] mImageArray[level];
        mImageArray[level]  = nullptr;
        mLayerCounts[level] = 0;
    }
}

angle::Result TextureD3D_2DArray::redefineImage(const gl::Context *context,
                                                GLint level,
                                                GLenum internalformat,
                                                const gl::Extents &size,
                                                bool forceRelease)
{
    // If there currently is a corresponding storage texture image, it has these parameters
    const int storageWidth     = std::max(1, getLevelZeroWidth() >> level);
    const int storageHeight    = std::max(1, getLevelZeroHeight() >> level);
    const GLuint baseLevel     = getBaseLevel();
    const GLenum storageFormat = getBaseLevelInternalFormat();

    int storageDepth = 0;
    if (baseLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    {
        storageDepth = getLayerCount(baseLevel);
    }

    // Only reallocate the layers if the size doesn't match
    if (size.depth != mLayerCounts[level])
    {
        for (int layer = 0; layer < mLayerCounts[level]; layer++)
        {
            SafeDelete(mImageArray[level][layer]);
        }
        SafeDeleteArray(mImageArray[level]);
        mLayerCounts[level] = size.depth;

        if (size.depth > 0)
        {
            mImageArray[level] = new ImageD3D *[size.depth];
            for (int layer = 0; layer < mLayerCounts[level]; layer++)
            {
                mImageArray[level][layer] = mRenderer->createImage();
            }
        }
    }

    if (size.depth > 0)
    {
        for (int layer = 0; layer < mLayerCounts[level]; layer++)
        {
            mImageArray[level][layer]->redefine(gl::TextureType::_2DArray, internalformat,
                                                gl::Extents(size.width, size.height, 1),
                                                forceRelease);
            mDirtyImages = mDirtyImages || mImageArray[level][layer]->isDirty();
        }
    }

    if (mTexStorage)
    {
        const int storageLevels = mTexStorage->getLevelCount();

        if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
            size.height != storageHeight || size.depth != storageDepth ||
            internalformat != storageFormat)  // Discard mismatched storage
        {
            markAllImagesDirty();
            ANGLE_TRY(releaseTexStorage(context));
        }
    }

    return angle::Result::Continue;
}

gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const
{
    return gl::ImageIndexIterator::Make2DArray(0, mTexStorage->getLevelCount(), mLayerCounts);
}

gl::ImageIndex TextureD3D_2DArray::getImageIndex(GLint mip, GLint layer) const
{
    return gl::ImageIndex::Make2DArray(mip, layer);
}

bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const
{
    // Check for having a storage and the right type of index
    if (!mTexStorage || index.getType() != gl::TextureType::_2DArray)
    {
        return false;
    }

    // Check the mip index
    if (index.getLevelIndex() < 0 || index.getLevelIndex() >= mTexStorage->getLevelCount())
    {
        return false;
    }

    // Check the layer index
    return (!index.hasLayer() || (index.getLayerIndex() >= 0 &&
                                  index.getLayerIndex() < mLayerCounts[index.getLevelIndex()]));
}

void TextureD3D_2DArray::markAllImagesDirty()
{
    for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
    {
        for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++)
        {
            mImageArray[dirtyLevel][dirtyLayer]->markDirty();
        }
    }
    mDirtyImages = true;
}

TextureD3DImmutableBase::TextureD3DImmutableBase(const gl::TextureState &state,
                                                 RendererD3D *renderer)
    : TextureD3D(state, renderer)
{}

TextureD3DImmutableBase::~TextureD3DImmutableBase() {}

ImageD3D *TextureD3DImmutableBase::getImage(const gl::ImageIndex &index) const
{
    return nullptr;
}

angle::Result TextureD3DImmutableBase::setImage(const gl::Context *context,
                                                const gl::ImageIndex &index,
                                                GLenum internalFormat,
                                                const gl::Extents &size,
                                                GLenum format,
                                                GLenum type,
                                                const gl::PixelUnpackState &unpack,
                                                const uint8_t *pixels)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3DImmutableBase::setSubImage(const gl::Context *context,
                                                   const gl::ImageIndex &index,
                                                   const gl::Box &area,
                                                   GLenum format,
                                                   GLenum type,
                                                   const gl::PixelUnpackState &unpack,
                                                   gl::Buffer *unpackBuffer,
                                                   const uint8_t *pixels)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3DImmutableBase::setCompressedImage(const gl::Context *context,
                                                          const gl::ImageIndex &index,
                                                          GLenum internalFormat,
                                                          const gl::Extents &size,
                                                          const gl::PixelUnpackState &unpack,
                                                          size_t imageSize,
                                                          const uint8_t *pixels)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3DImmutableBase::setCompressedSubImage(const gl::Context *context,
                                                             const gl::ImageIndex &index,
                                                             const gl::Box &area,
                                                             GLenum format,
                                                             const gl::PixelUnpackState &unpack,
                                                             size_t imageSize,
                                                             const uint8_t *pixels)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3DImmutableBase::copyImage(const gl::Context *context,
                                                 const gl::ImageIndex &index,
                                                 const gl::Rectangle &sourceArea,
                                                 GLenum internalFormat,
                                                 gl::Framebuffer *source)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3DImmutableBase::copySubImage(const gl::Context *context,
                                                    const gl::ImageIndex &index,
                                                    const gl::Offset &destOffset,
                                                    const gl::Rectangle &sourceArea,
                                                    gl::Framebuffer *source)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3DImmutableBase::bindTexImage(const gl::Context *context,
                                                    egl::Surface *surface)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3DImmutableBase::releaseTexImage(const gl::Context *context)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

TextureD3D_External::TextureD3D_External(const gl::TextureState &state, RendererD3D *renderer)
    : TextureD3DImmutableBase(state, renderer)
{}

TextureD3D_External::~TextureD3D_External() {}

GLsizei TextureD3D_External::getLayerCount(int level) const
{
    return 1;
}

angle::Result TextureD3D_External::setImageExternal(const gl::Context *context,
                                                    gl::TextureType type,
                                                    egl::Stream *stream,
                                                    const egl::Stream::GLTextureDescription &desc)
{
    ASSERT(type == gl::TextureType::External);

    ANGLE_TRY(releaseTexStorage(context));

    // If the stream is null, the external image is unbound and we release the storage
    if (stream != nullptr)
    {
        mTexStorage = mRenderer->createTextureStorageExternal(stream, desc);
    }

    return angle::Result::Continue;
}

angle::Result TextureD3D_External::setEGLImageTarget(const gl::Context *context,
                                                     gl::TextureType type,
                                                     egl::Image *image)
{
    EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);

    // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
    RenderTargetD3D *renderTargetD3D = nullptr;
    ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D));

    ANGLE_TRY(releaseTexStorage(context));
    mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D);

    return angle::Result::Continue;
}

angle::Result TextureD3D_External::initMipmapImages(const gl::Context *context)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Stop;
}

angle::Result TextureD3D_External::getRenderTarget(const gl::Context *context,
                                                   const gl::ImageIndex &index,
                                                   GLsizei samples,
                                                   RenderTargetD3D **outRT)
{
    UNREACHABLE();
    return angle::Result::Stop;
}

bool TextureD3D_External::isImageComplete(const gl::ImageIndex &index) const
{
    return (index.getLevelIndex() == 0) ? (mTexStorage != nullptr) : false;
}

angle::Result TextureD3D_External::initializeStorage(const gl::Context *context, bool renderTarget)
{
    // Texture storage is created when an external image is bound
    ASSERT(mTexStorage);
    return angle::Result::Continue;
}

angle::Result TextureD3D_External::createCompleteStorage(bool renderTarget,
                                                         TexStoragePointer *outStorage) const
{
    UNREACHABLE();
    return angle::Result::Continue;
}

angle::Result TextureD3D_External::setCompleteTexStorage(const gl::Context *context,
                                                         TextureStorage *newCompleteTexStorage)
{
    UNREACHABLE();
    return angle::Result::Continue;
}

angle::Result TextureD3D_External::updateStorage(const gl::Context *context)
{
    // Texture storage does not need to be updated since it is already loaded with the latest
    // external image
    ASSERT(mTexStorage);
    return angle::Result::Continue;
}

gl::ImageIndexIterator TextureD3D_External::imageIterator() const
{
    return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
}

gl::ImageIndex TextureD3D_External::getImageIndex(GLint mip, GLint /*layer*/) const
{
    // "layer" does not apply to 2D Textures.
    return gl::ImageIndex::Make2D(mip);
}

bool TextureD3D_External::isValidIndex(const gl::ImageIndex &index) const
{
    return (mTexStorage && index.getType() == gl::TextureType::External &&
            index.getLevelIndex() == 0);
}

void TextureD3D_External::markAllImagesDirty()
{
    UNREACHABLE();
}

TextureD3D_2DMultisample::TextureD3D_2DMultisample(const gl::TextureState &state,
                                                   RendererD3D *renderer)
    : TextureD3DImmutableBase(state, renderer)
{}

TextureD3D_2DMultisample::~TextureD3D_2DMultisample() {}

angle::Result TextureD3D_2DMultisample::setStorageMultisample(const gl::Context *context,
                                                              gl::TextureType type,
                                                              GLsizei samples,
                                                              GLint internalformat,
                                                              const gl::Extents &size,
                                                              bool fixedSampleLocations)
{
    ASSERT(type == gl::TextureType::_2DMultisample && size.depth == 1);

    // We allocate storage immediately instead of doing it lazily like other TextureD3D classes do.
    // This requires less state in this class.
    TexStoragePointer storage(context);
    storage.reset(mRenderer->createTextureStorage2DMultisample(internalformat, size.width,
                                                               size.height, static_cast<int>(0),
                                                               samples, fixedSampleLocations));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    mImmutable = true;

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisample::setEGLImageTarget(const gl::Context *context,
                                                          gl::TextureType type,
                                                          egl::Image *image)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisample::getRenderTarget(const gl::Context *context,
                                                        const gl::ImageIndex &index,
                                                        GLsizei samples,
                                                        RenderTargetD3D **outRT)
{
    ASSERT(!index.hasLayer());

    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget(context));

    return mTexStorage->getRenderTarget(context, index, samples, outRT);
}

gl::ImageIndexIterator TextureD3D_2DMultisample::imageIterator() const
{
    return gl::ImageIndexIterator::Make2DMultisample();
}

gl::ImageIndex TextureD3D_2DMultisample::getImageIndex(GLint mip, GLint layer) const
{
    return gl::ImageIndex::Make2DMultisample();
}

bool TextureD3D_2DMultisample::isValidIndex(const gl::ImageIndex &index) const
{
    return (mTexStorage && index.getType() == gl::TextureType::_2DMultisample &&
            index.getLevelIndex() == 0);
}

GLsizei TextureD3D_2DMultisample::getLayerCount(int level) const
{
    return 1;
}

void TextureD3D_2DMultisample::markAllImagesDirty() {}

angle::Result TextureD3D_2DMultisample::initializeStorage(const gl::Context *context,
                                                          bool renderTarget)
{
    // initializeStorage should only be called in a situation where the texture already has storage
    // associated with it (storage is created in setStorageMultisample).
    ASSERT(mTexStorage);
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisample::createCompleteStorage(bool renderTarget,
                                                              TexStoragePointer *outStorage) const
{
    UNREACHABLE();
    outStorage->reset(mTexStorage);
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisample::setCompleteTexStorage(const gl::Context *context,
                                                              TextureStorage *newCompleteTexStorage)
{
    // These textures are immutable, so this should only be ever called once.
    ASSERT(!mTexStorage);
    mTexStorage = newCompleteTexStorage;
    mTexStorageObserverBinding.bind(mTexStorage);
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisample::updateStorage(const gl::Context *context)
{
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisample::initMipmapImages(const gl::Context *context)
{
    UNREACHABLE();
    return angle::Result::Continue;
}

bool TextureD3D_2DMultisample::isImageComplete(const gl::ImageIndex &index) const
{
    return true;
}

TextureD3D_2DMultisampleArray::TextureD3D_2DMultisampleArray(const gl::TextureState &state,
                                                             RendererD3D *renderer)
    : TextureD3DImmutableBase(state, renderer)
{}

TextureD3D_2DMultisampleArray::~TextureD3D_2DMultisampleArray() {}

angle::Result TextureD3D_2DMultisampleArray::setStorageMultisample(const gl::Context *context,
                                                                   gl::TextureType type,
                                                                   GLsizei samples,
                                                                   GLint internalformat,
                                                                   const gl::Extents &size,
                                                                   bool fixedSampleLocations)
{
    ASSERT(type == gl::TextureType::_2DMultisampleArray);

    mLayerCount = size.depth;

    TexStoragePointer storage(context);
    storage.reset(mRenderer->createTextureStorage2DMultisampleArray(
        internalformat, size.width, size.height, size.depth, static_cast<int>(0), samples,
        fixedSampleLocations));

    ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
    storage.release();

    mImmutable = true;

    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisampleArray::setEGLImageTarget(const gl::Context *context,
                                                               gl::TextureType type,
                                                               egl::Image *image)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisampleArray::getRenderTarget(const gl::Context *context,
                                                             const gl::ImageIndex &index,
                                                             GLsizei samples,
                                                             RenderTargetD3D **outRT)
{
    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget(context));

    return mTexStorage->getRenderTarget(context, index, samples, outRT);
}

gl::ImageIndexIterator TextureD3D_2DMultisampleArray::imageIterator() const
{
    return gl::ImageIndexIterator::Make2DMultisampleArray(&mLayerCount);
}

gl::ImageIndex TextureD3D_2DMultisampleArray::getImageIndex(GLint mip, GLint layer) const
{
    return gl::ImageIndex::Make2DMultisampleArray(layer);
}

bool TextureD3D_2DMultisampleArray::isValidIndex(const gl::ImageIndex &index) const
{
    return (mTexStorage && index.getType() == gl::TextureType::_2DMultisampleArray &&
            index.getLevelIndex() == 0);
}

GLsizei TextureD3D_2DMultisampleArray::getLayerCount(int level) const
{
    return mLayerCount;
}

void TextureD3D_2DMultisampleArray::markAllImagesDirty() {}

angle::Result TextureD3D_2DMultisampleArray::initializeStorage(const gl::Context *context,
                                                               bool renderTarget)
{
    // initializeStorage should only be called in a situation where the texture already has storage
    // associated with it (storage is created in setStorageMultisample).
    ASSERT(mTexStorage);
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisampleArray::createCompleteStorage(
    bool renderTarget,
    TexStoragePointer *outStorage) const
{
    UNREACHABLE();
    outStorage->reset(mTexStorage);
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisampleArray::setCompleteTexStorage(
    const gl::Context *context,
    TextureStorage *newCompleteTexStorage)
{
    // These textures are immutable, so this should only be ever called once.
    ASSERT(!mTexStorage);
    mTexStorage = newCompleteTexStorage;
    mTexStorageObserverBinding.bind(mTexStorage);
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisampleArray::updateStorage(const gl::Context *context)
{
    return angle::Result::Continue;
}

angle::Result TextureD3D_2DMultisampleArray::initMipmapImages(const gl::Context *context)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

bool TextureD3D_2DMultisampleArray::isImageComplete(const gl::ImageIndex &index) const
{
    return true;
}

}  // namespace rx
