//
// 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/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/EGLImageD3D.h"
#include "libANGLE/renderer/d3d/ImageD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/TextureStorage.h"

namespace rx
{

namespace
{

gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pixels,
                           ptrdiff_t layerOffset, const uint8_t **pointerOut)
{
    if (unpack.pixelBuffer.id() != 0)
    {
        // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported
        gl::Buffer *pixelBuffer = unpack.pixelBuffer.get();
        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>(pixelBuffer);
        ASSERT(bufferD3D);
        const uint8_t *bufferData = nullptr;
        ANGLE_TRY(bufferD3D->getData(&bufferData));
        *pointerOut = bufferData + offset;
    }
    else
    {
        *pointerOut = pixels;
    }

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

    return gl::NoError();
}

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

}

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

TextureD3D::~TextureD3D()
{
}

gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage)
{
    // ensure the underlying texture is created
    ANGLE_TRY(initializeStorage(false));

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

    ASSERT(outStorage);

    *outStorage = mTexStorage;
    return gl::NoError();
}

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

gl::Error TextureD3D::setStorageMultisample(ContextImpl *contextImpl,
                                            GLenum target,
                                            GLsizei samples,
                                            GLint internalFormat,
                                            const gl::Extents &size,
                                            GLboolean fixedSampleLocations)
{
    UNIMPLEMENTED();
    return gl::InternalError() << "setStorageMultisample is unimplemented.";
}

bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
{
    if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload)
    {
        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);
}

gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index,
                                   GLenum type,
                                   const gl::PixelUnpackState &unpack,
                                   const uint8_t *pixels,
                                   ptrdiff_t layerOffset)
{
    ImageD3D *image = getImage(index);
    ASSERT(image);

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

    // 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(unpack, pixels, layerOffset, &pixelData));

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

        mDirtyImages = true;
    }

    return gl::NoError();
}

gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
                               const gl::PixelUnpackState &unpack, 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(unpack, pixels, layerOffset, &pixelData));

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

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

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

    return gl::NoError();
}

gl::Error TextureD3D::setCompressedImageImpl(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 gl::NoError();
    }

    // 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(unpack, pixels, layerOffset, &pixelData));

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

        mDirtyImages = true;
    }

    return gl::NoError();
}

gl::Error TextureD3D::subImageCompressed(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;
    ANGLE_TRY(GetUnpackPointer(unpack, pixels, layerOffset, &pixelData));

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

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

        mDirtyImages = true;
    }

    return gl::NoError();
}

bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat)
{
    return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
}

gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
                                       GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget)
{
    if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 ||
        unpack.skipImages != 0)
    {
        // TODO(jmadill): additional unpack parameters
        UNIMPLEMENTED();
        return gl::Error(GL_INVALID_OPERATION,
                         "Unimplemented pixel store parameters in fastUnpackPixels");
    }

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

    // 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(unpack, static_cast<unsigned int>(offset),
                                                 destRenderTarget, sizedInternalFormat, type,
                                                 destArea));

    return gl::NoError();
}

GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
{
    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
    {
        // 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));
}

gl::Error TextureD3D::setImageExternal(GLenum target,
                                       egl::Stream *stream,
                                       const egl::Stream::GLTextureDescription &desc)
{
    // Only external images can accept external textures
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D::generateMipmap(ContextImpl *contextImpl)
{
    const GLuint baseLevel = mState.getEffectiveBaseLevel();
    const GLuint maxLevel = mState.getMipmapMaxLevel();
    ASSERT(maxLevel > baseLevel);  // Should be checked before calling this.

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

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

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

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

    return gl::NoError();
}

gl::Error TextureD3D::generateMipmapUsingImages(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->getWorkarounds().setDataFasterThanImageUpload && 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(srcIndex, mTexStorage));
            }
        }
        else
        {
            ANGLE_TRY(updateStorage());
        }
    }

    // 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->getWorkarounds().zeroMaxLodWorkaround));

    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(sourceIndex, destIndex));
            }
            else
            {
                // CPU-side mipmapping
                ANGLE_TRY(mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex)));
            }
        }
    }

    if (mTexStorage)
    {
        updateStorage();
    }

    return gl::NoError();
}

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

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

    if (!gl::IsCubeMapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0)
    {
        return true;
    }

    if (baseImage->getTarget() == GL_TEXTURE_3D && baseImage->getDepth() <= 0)
    {
        return true;
    }

    if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(getBaseLevel()) <= 0)
    {
        return true;
    }

    return false;
}

gl::Error TextureD3D::ensureRenderTarget()
{
    ANGLE_TRY(initializeStorage(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)
    {
        UNREACHABLE();
        return gl::InternalError() << "Cannot render to incomplete texture.";
    }

    if (!isBaseImageZeroSize())
    {
        ASSERT(mTexStorage);
        if (!mTexStorage->isRenderTarget())
        {
            TextureStorage *newRenderTargetStorage = nullptr;
            ANGLE_TRY(createCompleteStorage(true, &newRenderTargetStorage));

            std::unique_ptr<TextureStorage> newStorageRef(newRenderTargetStorage);
            ANGLE_TRY(mTexStorage->copyToStorage(newRenderTargetStorage));
            ANGLE_TRY(setCompleteTexStorage(newRenderTargetStorage));
            newStorageRef.release();
        }
    }

    return gl::NoError();
}

bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const
{
    ImageD3D *image = getImage(index);
    bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0)));
    return (image->isRenderableFormat() && levelsComplete);
}

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

    return gl::NoError();
}

gl::Error TextureD3D::getAttachmentRenderTarget(GLenum /*binding*/,
                                                const gl::ImageIndex &imageIndex,
                                                FramebufferAttachmentRenderTarget **rtOut)
{
    RenderTargetD3D *rtD3D = nullptr;
    gl::Error error        = getRenderTarget(imageIndex, &rtD3D);
    *rtOut = static_cast<FramebufferAttachmentRenderTarget *>(rtD3D);
    return error;
}

void TextureD3D::setBaseLevel(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();
        SafeDelete(mTexStorage);
    }
}

void TextureD3D::syncState(const gl::Texture::DirtyBits &dirtyBits)
{
    // TODO(geofflang): Use dirty bits
}

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

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

TextureD3D_2DMultisample::~TextureD3D_2DMultisample()
{
}

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

gl::Error TextureD3D_2DMultisample::setImage(ContextImpl *contextImpl,
                                             GLenum target,
                                             size_t level,
                                             GLenum internalFormat,
                                             const gl::Extents &size,
                                             GLenum format,
                                             GLenum type,
                                             const gl::PixelUnpackState &unpack,
                                             const uint8_t *pixels)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::setSubImage(ContextImpl *contextImpl,
                                                GLenum target,
                                                size_t level,
                                                const gl::Box &area,
                                                GLenum format,
                                                GLenum type,
                                                const gl::PixelUnpackState &unpack,
                                                const uint8_t *pixels)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::setCompressedImage(ContextImpl *contextImpl,
                                                       GLenum target,
                                                       size_t level,
                                                       GLenum internalFormat,
                                                       const gl::Extents &size,
                                                       const gl::PixelUnpackState &unpack,
                                                       size_t imageSize,
                                                       const uint8_t *pixels)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::setCompressedSubImage(ContextImpl *contextImpl,
                                                          GLenum target,
                                                          size_t level,
                                                          const gl::Box &area,
                                                          GLenum format,
                                                          const gl::PixelUnpackState &unpack,
                                                          size_t imageSize,
                                                          const uint8_t *pixels)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::copyImage(ContextImpl *contextImpl,
                                              GLenum target,
                                              size_t level,
                                              const gl::Rectangle &sourceArea,
                                              GLenum internalFormat,
                                              const gl::Framebuffer *source)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::copySubImage(ContextImpl *contextImpl,
                                                 GLenum target,
                                                 size_t level,
                                                 const gl::Offset &destOffset,
                                                 const gl::Rectangle &sourceArea,
                                                 const gl::Framebuffer *source)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::setStorage(ContextImpl *contextImpl,
                                               GLenum target,
                                               size_t levels,
                                               GLenum internalFormat,
                                               const gl::Extents &size)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::setImageExternal(GLenum target,
                                                     egl::Stream *stream,
                                                     const egl::Stream::GLTextureDescription &desc)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

void TextureD3D_2DMultisample::bindTexImage(egl::Surface *surface)
{
    UNIMPLEMENTED();
}

void TextureD3D_2DMultisample::releaseTexImage()
{
    UNIMPLEMENTED();
}

gl::Error TextureD3D_2DMultisample::setEGLImageTarget(GLenum target, egl::Image *image)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::getRenderTarget(const gl::ImageIndex &index,
                                                    RenderTargetD3D **outRT)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

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

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

bool TextureD3D_2DMultisample::isValidIndex(const gl::ImageIndex &index) const
{
    UNIMPLEMENTED();
    return false;
}

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

void TextureD3D_2DMultisample::markAllImagesDirty()
{
    UNIMPLEMENTED();
}

gl::Error TextureD3D_2DMultisample::initializeStorage(bool renderTarget)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::createCompleteStorage(bool renderTarget,
                                                          TextureStorage **outTexStorage) const
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

gl::Error TextureD3D_2DMultisample::updateStorage()
{
    UNIMPLEMENTED();
    return gl::InternalError();
}

void TextureD3D_2DMultisample::initMipmapImages()
{
    UNIMPLEMENTED();
}

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

TextureD3D_2D::~TextureD3D_2D()
{
    // 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 (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
    {
        SafeDelete(mImageArray[i]);
    }

    SafeDelete(mTexStorage);
}

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

ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
{
    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(!index.hasLayer());
    ASSERT(index.type == GL_TEXTURE_2D);
    return mImageArray[index.mipIndex];
}

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

gl::Error TextureD3D_2D::setImage(ContextImpl *contextImpl,
                                  GLenum target,
                                  size_t imageLevel,
                                  GLenum internalFormat,
                                  const gl::Extents &size,
                                  GLenum format,
                                  GLenum type,
                                  const gl::PixelUnpackState &unpack,
                                  const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_2D && size.depth == 1);

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

    bool fastUnpacked = false;
    GLint level       = static_cast<GLint>(imageLevel);

    redefineImage(level, internalFormatInfo.sizedInternalFormat, size, false);

    gl::ImageIndex index = gl::ImageIndex::Make2D(level);

    // Attempt a fast gpu copy of the pixel data to the surface
    if (isFastUnpackable(unpack, internalFormatInfo.sizedInternalFormat) && isLevelComplete(level))
    {
        // Will try to create RT storage if it does not exist
        RenderTargetD3D *destRenderTarget = nullptr;
        ANGLE_TRY(getRenderTarget(index, &destRenderTarget));

        gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1);

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

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

        fastUnpacked = true;
    }

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

    return gl::NoError();
}

gl::Error TextureD3D_2D::setSubImage(ContextImpl *contextImpl,
                                     GLenum target,
                                     size_t imageLevel,
                                     const gl::Box &area,
                                     GLenum format,
                                     GLenum type,
                                     const gl::PixelUnpackState &unpack,
                                     const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);

    GLint level          = static_cast<GLint>(imageLevel);
    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
    if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
    {
        RenderTargetD3D *renderTarget = nullptr;
        ANGLE_TRY(getRenderTarget(index, &renderTarget));
        ASSERT(!mImageArray[level]->isDirty());

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

gl::Error TextureD3D_2D::setCompressedImage(ContextImpl *contextImpl,
                                            GLenum target,
                                            size_t imageLevel,
                                            GLenum internalFormat,
                                            const gl::Extents &size,
                                            const gl::PixelUnpackState &unpack,
                                            size_t imageSize,
                                            const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_2D && size.depth == 1);
    GLint level = static_cast<GLint>(imageLevel);

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

    return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0);
}

gl::Error TextureD3D_2D::setCompressedSubImage(ContextImpl *contextImpl,
                                               GLenum target,
                                               size_t level,
                                               const gl::Box &area,
                                               GLenum format,
                                               const gl::PixelUnpackState &unpack,
                                               size_t imageSize,
                                               const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);

    gl::ImageIndex index = gl::ImageIndex::Make2D(static_cast<GLint>(level));
    ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));

    return commitRegion(index, area);
}

gl::Error TextureD3D_2D::copyImage(ContextImpl *contextImpl,
                                   GLenum target,
                                   size_t imageLevel,
                                   const gl::Rectangle &sourceArea,
                                   GLenum internalFormat,
                                   const gl::Framebuffer *source)
{
    ASSERT(target == GL_TEXTURE_2D);

    GLint level                = static_cast<GLint>(imageLevel);
    const gl::InternalFormat &internalFormatInfo =
        gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
    redefineImage(level, internalFormatInfo.sizedInternalFormat,
                  gl::Extents(sourceArea.width, sourceArea.height, 1), false);

    gl::ImageIndex index = gl::ImageIndex::Make2D(level);
    gl::Offset destOffset(0, 0, 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->getWorkarounds().zeroMaxLodWorkaround)
    {
        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
        mDirtyImages = true;
    }
    else
    {
        ANGLE_TRY(ensureRenderTarget());
        mImageArray[level]->markClean();

        if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level))
        {
            ANGLE_TRY(mRenderer->copyImage2D(source, sourceArea, internalFormat, destOffset,
                                             mTexStorage, level));
        }
    }

    return gl::NoError();
}

gl::Error TextureD3D_2D::copySubImage(ContextImpl *contextImpl,
                                      GLenum target,
                                      size_t imageLevel,
                                      const gl::Offset &destOffset,
                                      const gl::Rectangle &sourceArea,
                                      const gl::Framebuffer *source)
{
    ASSERT(target == GL_TEXTURE_2D && destOffset.z == 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)

    GLint level          = static_cast<GLint>(imageLevel);
    gl::ImageIndex index = gl::ImageIndex::Make2D(level);

    // 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->getWorkarounds().zeroMaxLodWorkaround)
    {
        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
        mDirtyImages = true;
    }
    else
    {
        ANGLE_TRY(ensureRenderTarget());

        if (isValidLevel(level))
        {
            ANGLE_TRY(updateStorageLevel(level));
            ANGLE_TRY(mRenderer->copyImage2D(source, sourceArea,
                                             gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
                                             destOffset, mTexStorage, level));
        }
    }

    return gl::NoError();
}

gl::Error TextureD3D_2D::copyTexture(ContextImpl *contextImpl,
                                     GLenum target,
                                     size_t level,
                                     GLenum internalFormat,
                                     GLenum type,
                                     size_t sourceLevel,
                                     bool unpackFlipY,
                                     bool unpackPremultiplyAlpha,
                                     bool unpackUnmultiplyAlpha,
                                     const gl::Texture *source)
{
    ASSERT(target == GL_TEXTURE_2D);

    GLenum sourceTarget = source->getTarget();

    GLint destLevel = static_cast<GLint>(level);

    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);
    redefineImage(destLevel, internalFormatInfo.sizedInternalFormat, size, false);

    ASSERT(canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)));

    ANGLE_TRY(ensureRenderTarget());
    ASSERT(isValidLevel(destLevel));
    ANGLE_TRY(updateStorageLevel(destLevel));

    gl::Rectangle sourceRect(0, 0, size.width, size.height);
    gl::Offset destOffset(0, 0, 0);
    ANGLE_TRY(mRenderer->copyTexture(source, static_cast<GLint>(sourceLevel), sourceRect,
                                     internalFormatInfo.format, destOffset, mTexStorage, target,
                                     destLevel, unpackFlipY, unpackPremultiplyAlpha,
                                     unpackUnmultiplyAlpha));

    return gl::NoError();
}

gl::Error TextureD3D_2D::copySubTexture(ContextImpl *contextImpl,
                                        GLenum target,
                                        size_t level,
                                        const gl::Offset &destOffset,
                                        size_t sourceLevel,
                                        const gl::Rectangle &sourceArea,
                                        bool unpackFlipY,
                                        bool unpackPremultiplyAlpha,
                                        bool unpackUnmultiplyAlpha,
                                        const gl::Texture *source)
{
    ASSERT(target == GL_TEXTURE_2D);

    GLint destLevel = static_cast<GLint>(level);

    ASSERT(canCreateRenderTargetForImage(gl::ImageIndex::Make2D(destLevel)));

    ANGLE_TRY(ensureRenderTarget());
    ASSERT(isValidLevel(destLevel));
    ANGLE_TRY(updateStorageLevel(destLevel));

    ANGLE_TRY(mRenderer->copyTexture(source, static_cast<GLint>(sourceLevel), sourceArea,
                                     gl::GetUnsizedFormat(getBaseLevelInternalFormat()), destOffset,
                                     mTexStorage, target, destLevel, unpackFlipY,
                                     unpackPremultiplyAlpha, unpackUnmultiplyAlpha));

    return gl::NoError();
}

gl::Error TextureD3D_2D::copyCompressedTexture(ContextImpl *contextImpl, const gl::Texture *source)
{
    GLenum sourceTarget = source->getTarget();
    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);
    redefineImage(destLevel, sizedInternalFormat, size, false);

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

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

    return gl::NoError();
}

gl::Error TextureD3D_2D::setStorage(ContextImpl *contextImpl,
                                    GLenum target,
                                    size_t levels,
                                    GLenum internalFormat,
                                    const gl::Extents &size)
{
    ASSERT(GL_TEXTURE_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);
        redefineImage(level, internalFormat, levelSize, true);
    }

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

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

    gl::Error error = setCompleteTexStorage(storage);
    if (error.isError())
    {
        SafeDelete(storage);
        return error;
    }

    ANGLE_TRY(updateStorage());

    mImmutable = true;

    return gl::NoError();
}

void TextureD3D_2D::bindTexImage(egl::Surface *surface)
{
    GLenum internalformat = surface->getConfig()->renderTargetFormat;

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

    if (mTexStorage)
    {
        SafeDelete(mTexStorage);
    }

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

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

    mDirtyImages = true;
}

void TextureD3D_2D::releaseTexImage()
{
    if (mTexStorage)
    {
        SafeDelete(mTexStorage);
    }

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

gl::Error TextureD3D_2D::setEGLImageTarget(GLenum target, 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);
    redefineImage(0, format.info->sizedInternalFormat, size, true);

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

    SafeDelete(mTexStorage);
    mImageArray[0]->markClean();

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

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

    return gl::NoError();
}

void TextureD3D_2D::initMipmapImages()
{
    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);

        redefineImage(level, getBaseLevelInternalFormat(), levelSize, false);
    }
}

gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
    ASSERT(!index.hasLayer());

    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget());
    ANGLE_TRY(updateStorageLevel(index.mipIndex));

    return mTexStorage->getRenderTarget(index, 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 <= (int)ArraySize(mImageArray) && mImageArray[level] != nullptr);
    ImageD3D *image = mImageArray[level];

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

// Constructs a native texture resource from the texture images
gl::Error TextureD3D_2D::initializeStorage(bool renderTarget)
{
    // Only initialize the first time this texture is used as a render target or shader resource
    if (mTexStorage)
    {
        return gl::NoError();
    }

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

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

    TextureStorage *storage = nullptr;
    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));

    gl::Error error = setCompleteTexStorage(storage);
    if (error.isError())
    {
        SafeDelete(storage);
        return error;
    }

    ASSERT(mTexStorage);

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

    return gl::NoError();
}

gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) 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->getWorkarounds().zeroMaxLodWorkaround)
    {
        // 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
    *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly);

    return gl::NoError();
}

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

    SafeDelete(mTexStorage);
    mTexStorage = newCompleteTexStorage;

    mDirtyImages = true;

    return gl::NoError();
}

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

    return gl::NoError();
}

gl::Error TextureD3D_2D::updateStorageLevel(int level)
{
    ASSERT(level <= (int)ArraySize(mImageArray) && 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(index, region));
    }

    return gl::NoError();
}

void TextureD3D_2D::redefineImage(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_TEXTURE_2D, internalformat, size, forceRelease);

    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)
        {
            // TODO(jmadill): Don't discard error.
            mImageArray[0]->copyFromTexStorage(gl::ImageIndex::Make2D(0), mTexStorage);
        }

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

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

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.type == GL_TEXTURE_2D &&
            index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
}

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

gl::Error TextureD3D_2D::setStorageMultisample(ContextImpl *contextImpl,
                                               GLenum target,
                                               GLsizei samples,
                                               GLint internalFormat,
                                               const gl::Extents &size,
                                               GLboolean fixedSampleLocations)
{
    UNIMPLEMENTED();
    return gl::InternalError() << "setStorageMultisample is unimplemented.";
}

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

TextureD3D_Cube::~TextureD3D_Cube()
{
    // 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 (int i = 0; i < 6; i++)
    {
        for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
        {
            SafeDelete(mImageArray[i][j]);
        }
    }

    SafeDelete(mTexStorage);
}

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

ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
{
    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(index.layerIndex >= 0 && index.layerIndex < 6);
    return mImageArray[index.layerIndex][index.mipIndex];
}

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

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

gl::Error TextureD3D_Cube::setEGLImageTarget(GLenum target, egl::Image *image)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_Cube::setImage(ContextImpl *contextImpl,
                                    GLenum target,
                                    size_t level,
                                    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);
    gl::ImageIndex index       = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));

    redefineImage(index.layerIndex, static_cast<GLint>(level),
                  internalFormatInfo.sizedInternalFormat, size);

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

gl::Error TextureD3D_Cube::setSubImage(ContextImpl *contextImpl,
                                       GLenum target,
                                       size_t level,
                                       const gl::Box &area,
                                       GLenum format,
                                       GLenum type,
                                       const gl::PixelUnpackState &unpack,
                                       const uint8_t *pixels)
{
    ASSERT(area.depth == 1 && area.z == 0);

    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
    return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
}

gl::Error TextureD3D_Cube::setCompressedImage(ContextImpl *contextImpl,
                                              GLenum target,
                                              size_t level,
                                              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
    size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target);

    redefineImage(static_cast<int>(faceIndex), static_cast<GLint>(level), internalFormat, size);

    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
    return setCompressedImageImpl(index, unpack, pixels, 0);
}

gl::Error TextureD3D_Cube::setCompressedSubImage(ContextImpl *contextImpl,
                                                 GLenum target,
                                                 size_t level,
                                                 const gl::Box &area,
                                                 GLenum format,
                                                 const gl::PixelUnpackState &unpack,
                                                 size_t imageSize,
                                                 const uint8_t *pixels)
{
    ASSERT(area.depth == 1 && area.z == 0);

    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));

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

gl::Error TextureD3D_Cube::copyImage(ContextImpl *contextImpl,
                                     GLenum target,
                                     size_t imageLevel,
                                     const gl::Rectangle &sourceArea,
                                     GLenum internalFormat,
                                     const gl::Framebuffer *source)
{
    int faceIndex              = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));
    const gl::InternalFormat &internalFormatInfo =
        gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);

    GLint level = static_cast<GLint>(imageLevel);

    gl::Extents size(sourceArea.width, sourceArea.height, 1);
    redefineImage(static_cast<int>(faceIndex), level, internalFormatInfo.sizedInternalFormat, size);

    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
    gl::Offset destOffset(0, 0, 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->getWorkarounds().zeroMaxLodWorkaround)
    {
        ANGLE_TRY(
            mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source));
        mDirtyImages = true;
    }
    else
    {
        ANGLE_TRY(ensureRenderTarget());
        mImageArray[faceIndex][level]->markClean();

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

        if (size.width > 0 && isValidFaceLevel(faceIndex, level))
        {
            ANGLE_TRY(mRenderer->copyImageCube(source, sourceArea, internalFormat, destOffset,
                                               mTexStorage, target, level));
        }
    }

    return gl::NoError();
}

gl::Error TextureD3D_Cube::copySubImage(ContextImpl *contextImpl,
                                        GLenum target,
                                        size_t imageLevel,
                                        const gl::Offset &destOffset,
                                        const gl::Rectangle &sourceArea,
                                        const gl::Framebuffer *source)
{
    int faceIndex = static_cast<int>(gl::CubeMapTextureTargetToLayerIndex(target));

    GLint level          = static_cast<GLint>(imageLevel);
    gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);

    // 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->getWorkarounds().zeroMaxLodWorkaround)
    {
        gl::Error error =
            mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source);
        if (error.isError())
        {
            return error;
        }

        mDirtyImages = true;
    }
    else
    {
        ANGLE_TRY(ensureRenderTarget());
        if (isValidFaceLevel(faceIndex, level))
        {
            ANGLE_TRY(updateStorageFaceLevel(faceIndex, level));
            ANGLE_TRY(mRenderer->copyImageCube(source, sourceArea,
                                               gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
                                               destOffset, mTexStorage, target, level));
        }
    }

    return gl::NoError();
}

gl::Error TextureD3D_Cube::setStorage(ContextImpl *contextImpl,
                                      GLenum target,
                                      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 (int faceIndex = 0; faceIndex < 6; faceIndex++)
        {
            mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalFormat, gl::Extents(mipSize, mipSize, 1), true);
        }
    }

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

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

    TextureStorage *storage = mRenderer->createTextureStorageCube(
        internalFormat, renderTarget, size.width, static_cast<int>(levels), false);

    gl::Error error = setCompleteTexStorage(storage);
    if (error.isError())
    {
        SafeDelete(storage);
        return error;
    }

    ANGLE_TRY(updateStorage());

    mImmutable = true;

    return gl::NoError();
}

// 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 (int faceIndex = 1; faceIndex < 6; faceIndex++)
    {
        const ImageD3D &faceBaseImage = *mImageArray[faceIndex][getBaseLevel()];

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

    return true;
}

void TextureD3D_Cube::bindTexImage(egl::Surface *surface)
{
    UNREACHABLE();
}

void TextureD3D_Cube::releaseTexImage()
{
    UNREACHABLE();
}

void TextureD3D_Cube::initMipmapImages()
{
    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 < 6; faceIndex++)
    {
        for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
        {
            int faceLevelSize =
                (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1));
            redefineImage(faceIndex, level, mImageArray[faceIndex][baseLevel]->getInternalFormat(),
                          gl::Extents(faceLevelSize, faceLevelSize, 1));
        }
    }
}

gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
    ASSERT(gl::IsCubeMapTextureTarget(index.type));

    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget());
    ANGLE_TRY(updateStorageFaceLevel(index.layerIndex, index.mipIndex));

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

gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget)
{
    // Only initialize the first time this texture is used as a render target or shader resource
    if (mTexStorage)
    {
        return gl::NoError();
    }

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

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

    TextureStorage *storage = nullptr;
    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));

    gl::Error error = setCompleteTexStorage(storage);
    if (error.isError())
    {
        SafeDelete(storage);
        return error;
    }

    ASSERT(mTexStorage);

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

    return gl::NoError();
}

gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) 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->getWorkarounds().zeroMaxLodWorkaround)
    {
        // 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 < 6 && 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
    *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly);

    return gl::NoError();
}

gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
{
    if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
    {
        for (int faceIndex = 0; faceIndex < 6; faceIndex++)
        {
            for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
            {
                ANGLE_TRY(mImageArray[faceIndex][level]->setManagedSurfaceCube(
                    newCompleteTexStorage, faceIndex, level));
            }
        }
    }

    SafeDelete(mTexStorage);
    mTexStorage = newCompleteTexStorage;

    mDirtyImages = true;
    return gl::NoError();
}

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

    return gl::NoError();
}

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 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) &&
           mImageArray[faceIndex][level] != nullptr);

    if (isImmutable())
    {
        return true;
    }

    int levelZeroSize = getLevelZeroWidth();

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

    // "isCubeComplete" checks for base level completeness and we must call that
    // to determine if any face at level 0 is complete. We omit that check here
    // to avoid re-checking cube-completeness for every face at level 0.
    if (level == 0)
    {
        return true;
    }

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

    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.layerIndex, index.mipIndex);
}

gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
{
    ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) &&
           mImageArray[faceIndex][level] != nullptr);
    ImageD3D *image = mImageArray[faceIndex][level];

    if (image->isDirty())
    {
        GLenum faceTarget = gl::LayerIndexToCubeMapTextureTarget(faceIndex);
        gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level);
        gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
        ANGLE_TRY(commitRegion(index, region));
    }

    return gl::NoError();
}

void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size)
{
    // 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_TEXTURE_CUBE_MAP, internalformat, size, false);

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

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

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::MakeCube(gl::LayerIndexToCubeMapTextureTarget(layer), mip);
}

bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const
{
    return (mTexStorage && gl::IsCubeMapTextureTarget(index.type) &&
            index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
}

void TextureD3D_Cube::markAllImagesDirty()
{
    for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
    {
        for (int dirtyFace = 0; dirtyFace < 6; 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] = renderer->createImage();
    }
}

TextureD3D_3D::~TextureD3D_3D()
{
    // 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 (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
    {
        delete mImageArray[i];
    }

    SafeDelete(mTexStorage);
}

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

ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
{
    ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT(!index.hasLayer());
    ASSERT(index.type == GL_TEXTURE_3D);
    return mImageArray[index.mipIndex];
}

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

gl::Error TextureD3D_3D::setEGLImageTarget(GLenum target, egl::Image *image)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_3D::setImage(ContextImpl *contextImpl,
                                  GLenum target,
                                  size_t imageLevel,
                                  GLenum internalFormat,
                                  const gl::Extents &size,
                                  GLenum format,
                                  GLenum type,
                                  const gl::PixelUnpackState &unpack,
                                  const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_3D);
    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);

    GLint level = static_cast<GLint>(imageLevel);
    redefineImage(level, internalFormatInfo.sizedInternalFormat, size);

    bool fastUnpacked = false;

    gl::ImageIndex index = gl::ImageIndex::Make3D(level);

    // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
    if (isFastUnpackable(unpack, internalFormatInfo.sizedInternalFormat) && !size.empty() &&
        isLevelComplete(level))
    {
        // Will try to create RT storage if it does not exist
        RenderTargetD3D *destRenderTarget = nullptr;
        ANGLE_TRY(getRenderTarget(index, &destRenderTarget));

        gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));

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

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

        fastUnpacked = true;
    }

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

    return gl::NoError();
}

gl::Error TextureD3D_3D::setSubImage(ContextImpl *contextImpl,
                                     GLenum target,
                                     size_t imageLevel,
                                     const gl::Box &area,
                                     GLenum format,
                                     GLenum type,
                                     const gl::PixelUnpackState &unpack,
                                     const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_3D);

    GLint level          = static_cast<GLint>(imageLevel);
    gl::ImageIndex index = gl::ImageIndex::Make3D(level);

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

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

gl::Error TextureD3D_3D::setCompressedImage(ContextImpl *contextImpl,
                                            GLenum target,
                                            size_t imageLevel,
                                            GLenum internalFormat,
                                            const gl::Extents &size,
                                            const gl::PixelUnpackState &unpack,
                                            size_t imageSize,
                                            const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_3D);

    GLint level = static_cast<GLint>(imageLevel);
    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
    redefineImage(level, internalFormat, size);

    gl::ImageIndex index = gl::ImageIndex::Make3D(level);
    return setCompressedImageImpl(index, unpack, pixels, 0);
}

gl::Error TextureD3D_3D::setCompressedSubImage(ContextImpl *contextImpl,
                                               GLenum target,
                                               size_t level,
                                               const gl::Box &area,
                                               GLenum format,
                                               const gl::PixelUnpackState &unpack,
                                               size_t imageSize,
                                               const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_3D);

    gl::ImageIndex index = gl::ImageIndex::Make3D(static_cast<GLint>(level));
    ANGLE_TRY(TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0));
    return commitRegion(index, area);
}

gl::Error TextureD3D_3D::copyImage(ContextImpl *contextImpl,
                                   GLenum target,
                                   size_t level,
                                   const gl::Rectangle &sourceArea,
                                   GLenum internalFormat,
                                   const gl::Framebuffer *source)
{
    UNIMPLEMENTED();
    return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented.");
}

gl::Error TextureD3D_3D::copySubImage(ContextImpl *contextImpl,
                                      GLenum target,
                                      size_t imageLevel,
                                      const gl::Offset &destOffset,
                                      const gl::Rectangle &sourceArea,
                                      const gl::Framebuffer *source)
{
    ASSERT(target == GL_TEXTURE_3D);

    GLint level          = static_cast<GLint>(imageLevel);

    // Currently, 3D single-layer blits are broken because we don't know how to make an SRV
    // for a single layer of a 3D texture.
    // TODO(jmadill): Investigate 3D blits in D3D11.
    // gl::ImageIndex index = gl::ImageIndex::Make3D(level);

    // if (!canCreateRenderTargetForImage(index))
    {
        ANGLE_TRY(mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source));
        mDirtyImages = true;
    }
    // else
    //{
    //    ANGLE_TRY(ensureRenderTarget());
    //    if (isValidLevel(level))
    //    {
    //        ANGLE_TRY(updateStorageLevel(level));
    //        ANGLE_TRY(mRenderer->copyImage3D(
    //            source, sourceArea,
    //            gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
    //            destOffset, mTexStorage, level));
    //    }
    //}

    return gl::NoError();
}

gl::Error TextureD3D_3D::setStorage(ContextImpl *contextImpl,
                                    GLenum target,
                                    size_t levels,
                                    GLenum internalFormat,
                                    const gl::Extents &size)
{
    ASSERT(target == GL_TEXTURE_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_TEXTURE_3D, internalFormat, levelSize, true);
    }

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

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

    gl::Error error = setCompleteTexStorage(storage);
    if (error.isError())
    {
        SafeDelete(storage);
        return error;
    }

    ANGLE_TRY(updateStorage());

    mImmutable = true;

    return gl::NoError();
}

void TextureD3D_3D::bindTexImage(egl::Surface *surface)
{
    UNREACHABLE();
}

void TextureD3D_3D::releaseTexImage()
{
    UNREACHABLE();
}

void TextureD3D_3D::initMipmapImages()
{
    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));
        redefineImage(level, getBaseLevelInternalFormat(), levelSize);
    }
}

gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget());

    if (index.hasLayer())
    {
        ANGLE_TRY(updateStorage());
    }
    else
    {
        ANGLE_TRY(updateStorageLevel(index.mipIndex));
    }

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

gl::Error TextureD3D_3D::initializeStorage(bool renderTarget)
{
    // Only initialize the first time this texture is used as a render target or shader resource
    if (mTexStorage)
    {
        return gl::NoError();
    }

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

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

    TextureStorage *storage = nullptr;
    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));

    gl::Error error = setCompleteTexStorage(storage);
    if (error.isError())
    {
        SafeDelete(storage);
        return error;
    }

    ASSERT(mTexStorage);

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

    return gl::NoError();
}

gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **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 = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels);

    return gl::NoError();
}

gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
{
    SafeDelete(mTexStorage);
    mTexStorage = newCompleteTexStorage;
    mDirtyImages = true;

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

    return gl::NoError();
}

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

    return gl::NoError();
}

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 < (int)ArraySize(mImageArray) && 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];

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

gl::Error TextureD3D_3D::updateStorageLevel(int level)
{
    ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && 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(index, region));
    }

    return gl::NoError();
}

void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
{
    // 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_TEXTURE_3D, internalformat, size, false);

    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();
            SafeDelete(mTexStorage);
        }
    }
}

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

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.type == GL_TEXTURE_3D &&
            index.mipIndex >= 0 && index.mipIndex < 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;
    }
}

TextureD3D_2DArray::~TextureD3D_2DArray()
{
    // 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();
    SafeDelete(mTexStorage);
}

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.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
    ASSERT((index.layerIndex == 0 && mLayerCounts[index.mipIndex] == 0) ||
           index.layerIndex < mLayerCounts[index.mipIndex]);
    ASSERT(index.type == GL_TEXTURE_2D_ARRAY);
    return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : 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;
}

gl::Error TextureD3D_2DArray::setEGLImageTarget(GLenum target, egl::Image *image)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_2DArray::setImage(ContextImpl *contextImpl,
                                       GLenum target,
                                       size_t imageLevel,
                                       GLenum internalFormat,
                                       const gl::Extents &size,
                                       GLenum format,
                                       GLenum type,
                                       const gl::PixelUnpackState &unpack,
                                       const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_2D_ARRAY);

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

    GLint level = static_cast<GLint>(imageLevel);
    redefineImage(level, formatInfo.sizedInternalFormat, size);

    GLsizei inputDepthPitch              = 0;
    ANGLE_TRY_RESULT(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 index = gl::ImageIndex::Make2DArray(level, i);
        ANGLE_TRY(setImageImpl(index, type, unpack, pixels, layerOffset));
    }

    return gl::NoError();
}

gl::Error TextureD3D_2DArray::setSubImage(ContextImpl *contextImpl,
                                          GLenum target,
                                          size_t imageLevel,
                                          const gl::Box &area,
                                          GLenum format,
                                          GLenum type,
                                          const gl::PixelUnpackState &unpack,
                                          const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_2D_ARRAY);
    GLint level                          = static_cast<GLint>(imageLevel);
    const gl::InternalFormat &formatInfo =
        gl::GetInternalFormatInfo(getInternalFormat(level), type);
    GLsizei inputDepthPitch              = 0;
    ANGLE_TRY_RESULT(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 index = gl::ImageIndex::Make2DArray(level, layer);
        ANGLE_TRY(
            TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset));
    }

    return gl::NoError();
}

gl::Error TextureD3D_2DArray::setCompressedImage(ContextImpl *contextImpl,
                                                 GLenum target,
                                                 size_t imageLevel,
                                                 GLenum internalFormat,
                                                 const gl::Extents &size,
                                                 const gl::PixelUnpackState &unpack,
                                                 size_t imageSize,
                                                 const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_2D_ARRAY);

    GLint level = static_cast<GLint>(imageLevel);
    // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
    redefineImage(level, internalFormat, size);

    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
    GLsizei inputDepthPitch              = 0;
    ANGLE_TRY_RESULT(
        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 index = gl::ImageIndex::Make2DArray(level, i);
        ANGLE_TRY(setCompressedImageImpl(index, unpack, pixels, layerOffset));
    }

    return gl::NoError();
}

gl::Error TextureD3D_2DArray::setCompressedSubImage(ContextImpl *contextImpl,
                                                    GLenum target,
                                                    size_t level,
                                                    const gl::Box &area,
                                                    GLenum format,
                                                    const gl::PixelUnpackState &unpack,
                                                    size_t imageSize,
                                                    const uint8_t *pixels)
{
    ASSERT(target == GL_TEXTURE_2D_ARRAY);

    const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
    GLsizei inputDepthPitch              = 0;
    ANGLE_TRY_RESULT(
        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 index = gl::ImageIndex::Make2DArray(static_cast<GLint>(level), layer);
        ANGLE_TRY(
            TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset));
        ANGLE_TRY(commitRegion(index, layerArea));
    }

    return gl::NoError();
}

gl::Error TextureD3D_2DArray::copyImage(ContextImpl *contextImpl,
                                        GLenum target,
                                        size_t level,
                                        const gl::Rectangle &sourceArea,
                                        GLenum internalFormat,
                                        const gl::Framebuffer *source)
{
    UNIMPLEMENTED();
    return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented.");
}

gl::Error TextureD3D_2DArray::copySubImage(ContextImpl *contextImpl,
                                           GLenum target,
                                           size_t imageLevel,
                                           const gl::Offset &destOffset,
                                           const gl::Rectangle &sourceArea,
                                           const gl::Framebuffer *source)
{
    ASSERT(target == GL_TEXTURE_2D_ARRAY);

    GLint level          = static_cast<GLint>(imageLevel);
    gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);

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

        if (isValidLevel(level))
        {
            ANGLE_TRY(updateStorageLevel(level));
            ANGLE_TRY(mRenderer->copyImage2DArray(
                source, sourceArea, gl::GetUnsizedFormat(getInternalFormat(getBaseLevel())),
                destOffset, mTexStorage, level));
        }
    }
    return gl::NoError();
}

gl::Error TextureD3D_2DArray::setStorage(ContextImpl *contextImpl,
                                         GLenum target,
                                         size_t levels,
                                         GLenum internalFormat,
                                         const gl::Extents &size)
{
    ASSERT(target == GL_TEXTURE_2D_ARRAY);

    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_TEXTURE_2D_ARRAY, internalFormat, levelLayerSize, true);
            }
        }
    }

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

    gl::Error error = setCompleteTexStorage(storage);
    if (error.isError())
    {
        SafeDelete(storage);
        return error;
    }

    ANGLE_TRY(updateStorage());

    mImmutable = true;

    return gl::NoError();
}

void TextureD3D_2DArray::bindTexImage(egl::Surface *surface)
{
    UNREACHABLE();
}

void TextureD3D_2DArray::releaseTexImage()
{
    UNREACHABLE();
}

void TextureD3D_2DArray::initMipmapImages()
{
    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);
        redefineImage(level, baseFormat, levelLayerSize);
    }
}

gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
    // ensure the underlying texture is created
    ANGLE_TRY(ensureRenderTarget());
    ANGLE_TRY(updateStorageLevel(index.mipIndex));
    return mTexStorage->getRenderTarget(index, outRT);
}

gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget)
{
    // Only initialize the first time this texture is used as a render target or shader resource
    if (mTexStorage)
    {
        return gl::NoError();
    }

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

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

    TextureStorage *storage = nullptr;
    ANGLE_TRY(createCompleteStorage(createRenderTarget, &storage));

    gl::Error error = setCompleteTexStorage(storage);
    if (error.isError())
    {
        SafeDelete(storage);
        return error;
    }

    ASSERT(mTexStorage);

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

    return gl::NoError();
}

gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **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 = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels);

    return gl::NoError();
}

gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
{
    SafeDelete(mTexStorage);
    mTexStorage = newCompleteTexStorage;
    mDirtyImages = true;

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

    return gl::NoError();
}

gl::Error TextureD3D_2DArray::updateStorage()
{
    ASSERT(mTexStorage != nullptr);
    GLint storageLevels = mTexStorage->getLevelCount();
    for (int level = 0; level < storageLevels; level++)
    {
        if (isLevelComplete(level))
        {
            ANGLE_TRY(updateStorageLevel(level));
        }
    }

    return gl::NoError();
}

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

gl::Error TextureD3D_2DArray::updateStorageLevel(int level)
{
    ASSERT(level >= 0 && level < (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(index, region));
        }
    }

    return gl::NoError();
}

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

void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
{
    // 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();
    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_TEXTURE_2D_ARRAY, internalformat,
                                                gl::Extents(size.width, size.height, 1), false);
        }
    }

    if (mTexStorage)
    {
        const GLenum storageFormat = getBaseLevelInternalFormat();
        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();
            SafeDelete(mTexStorage);
        }
    }
}

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.type != GL_TEXTURE_2D_ARRAY)
    {
        return false;
    }

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

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

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

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

TextureD3D_External::~TextureD3D_External()
{
    SafeDelete(mTexStorage);
}

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

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

gl::Error TextureD3D_External::setImage(ContextImpl *contextImpl,
                                        GLenum target,
                                        size_t imageLevel,
                                        GLenum internalFormat,
                                        const gl::Extents &size,
                                        GLenum format,
                                        GLenum type,
                                        const gl::PixelUnpackState &unpack,
                                        const uint8_t *pixels)
{
    // Image setting is not supported for external images
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_External::setSubImage(ContextImpl *contextImpl,
                                           GLenum target,
                                           size_t imageLevel,
                                           const gl::Box &area,
                                           GLenum format,
                                           GLenum type,
                                           const gl::PixelUnpackState &unpack,
                                           const uint8_t *pixels)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_External::setCompressedImage(ContextImpl *contextImpl,
                                                  GLenum target,
                                                  size_t imageLevel,
                                                  GLenum internalFormat,
                                                  const gl::Extents &size,
                                                  const gl::PixelUnpackState &unpack,
                                                  size_t imageSize,
                                                  const uint8_t *pixels)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_External::setCompressedSubImage(ContextImpl *contextImpl,
                                                     GLenum target,
                                                     size_t level,
                                                     const gl::Box &area,
                                                     GLenum format,
                                                     const gl::PixelUnpackState &unpack,
                                                     size_t imageSize,
                                                     const uint8_t *pixels)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_External::copyImage(ContextImpl *contextImpl,
                                         GLenum target,
                                         size_t imageLevel,
                                         const gl::Rectangle &sourceArea,
                                         GLenum internalFormat,
                                         const gl::Framebuffer *source)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_External::copySubImage(ContextImpl *contextImpl,
                                            GLenum target,
                                            size_t imageLevel,
                                            const gl::Offset &destOffset,
                                            const gl::Rectangle &sourceArea,
                                            const gl::Framebuffer *source)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_External::setStorage(ContextImpl *contextImpl,
                                          GLenum target,
                                          size_t levels,
                                          GLenum internalFormat,
                                          const gl::Extents &size)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

gl::Error TextureD3D_External::setImageExternal(GLenum target,
                                                egl::Stream *stream,
                                                const egl::Stream::GLTextureDescription &desc)
{
    ASSERT(target == GL_TEXTURE_EXTERNAL_OES);

    SafeDelete(mTexStorage);

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

    return gl::NoError();
}

void TextureD3D_External::bindTexImage(egl::Surface *surface)
{
    UNREACHABLE();
}

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

gl::Error TextureD3D_External::setEGLImageTarget(GLenum target, 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(&renderTargetD3D));

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

    return gl::NoError();
}

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

gl::Error TextureD3D_External::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
    UNREACHABLE();
    return gl::Error(GL_INVALID_OPERATION);
}

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

gl::Error TextureD3D_External::initializeStorage(bool renderTarget)
{
    // Texture storage is created when an external image is bound
    ASSERT(mTexStorage);
    return gl::NoError();
}

gl::Error TextureD3D_External::createCompleteStorage(bool renderTarget,
                                                     TextureStorage **outTexStorage) const
{
    UNREACHABLE();
    return gl::NoError();
}

gl::Error TextureD3D_External::setCompleteTexStorage(TextureStorage *newCompleteTexStorage)
{
    UNREACHABLE();
    return gl::NoError();
}

gl::Error TextureD3D_External::updateStorage()
{
    // Texture storage does not need to be updated since it is already loaded with the latest
    // external image
    ASSERT(mTexStorage);
    return gl::NoError();
}

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.type == GL_TEXTURE_EXTERNAL_OES && index.mipIndex == 0);
}

void TextureD3D_External::markAllImagesDirty()
{
    UNREACHABLE();
}
}  // namespace rx
