//
// 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.
//

// ImageIndex.cpp: Implementation for ImageIndex methods.

#include "libANGLE/ImageIndex.h"
#include "common/unsafe_buffers.h"

#include "common/utilities.h"
#include "libANGLE/Constants.h"
#include "libANGLE/angletypes.h"

#include <tuple>

namespace gl
{
namespace
{
GLint TextureTargetToLayer(TextureTarget target)
{
    switch (target)
    {
        case TextureTarget::CubeMapPositiveX:
            return 0;
        case TextureTarget::CubeMapNegativeX:
            return 1;
        case TextureTarget::CubeMapPositiveY:
            return 2;
        case TextureTarget::CubeMapNegativeY:
            return 3;
        case TextureTarget::CubeMapPositiveZ:
            return 4;
        case TextureTarget::CubeMapNegativeZ:
            return 5;
        case TextureTarget::External:
        case TextureTarget::Rectangle:
        case TextureTarget::_2D:
        case TextureTarget::_2DArray:
        case TextureTarget::_2DMultisample:
        case TextureTarget::_2DMultisampleArray:
        case TextureTarget::_3D:
        case TextureTarget::Buffer:
        case TextureTarget::CubeMapArray:
            return ImageIndex::kEntireLevel;
        default:
            UNREACHABLE();
            return 0;
    }
}

bool IsArrayTarget(TextureTarget target)
{
    switch (target)
    {
        case TextureTarget::_2DArray:
        case TextureTarget::_2DMultisampleArray:
        case TextureTarget::CubeMapArray:
            return true;
        default:
            return false;
    }
}
}  // anonymous namespace

TextureTarget TextureTypeToTarget(TextureType type, GLint layerIndex)
{
    if (type == TextureType::CubeMap)
    {
        // As GL_TEXTURE_CUBE_MAP cannot be a texture target in texImage*D APIs, so we don't allow
        // an entire cube map to have a texture target.
        ASSERT(layerIndex != ImageIndex::kEntireLevel);
        return CubeFaceIndexToTextureTarget(layerIndex);
    }
    else
    {
        return NonCubeTextureTypeToTarget(type);
    }
}

ImageIndex::ImageIndex()
    : mType(TextureType::InvalidEnum), mLevelIndex(0), mLayerIndex(0), mLayerCount(kEntireLevel)
{}

ImageIndex::ImageIndex(const ImageIndex &other) = default;

ImageIndex &ImageIndex::operator=(const ImageIndex &other) = default;

bool ImageIndex::hasLayer() const
{
    return mLayerIndex != kEntireLevel;
}

bool ImageIndex::isLayered() const
{
    switch (mType)
    {
        case TextureType::_2DArray:
        case TextureType::_2DMultisampleArray:
        case TextureType::CubeMap:
        case TextureType::_3D:
        case TextureType::CubeMapArray:
            return mLayerIndex == kEntireLevel;
        default:
            return false;
    }
}

bool ImageIndex::has3DLayer() const
{
    // It's quicker to check != CubeMap than calling usesTex3D, which checks multiple types. This
    // ASSERT validates the check gives the same result.
    ASSERT(!hasLayer() || ((mType != TextureType::CubeMap) == usesTex3D()));
    return (hasLayer() && mType != TextureType::CubeMap);
}

bool ImageIndex::usesTex3D() const
{
    return mType == TextureType::_3D || mType == TextureType::_2DArray ||
           mType == TextureType::_2DMultisampleArray || mType == TextureType::CubeMapArray;
}

TextureTarget ImageIndex::getTarget() const
{
    return TextureTypeToTarget(mType, mLayerIndex);
}

gl::TextureTarget ImageIndex::getTargetOrFirstCubeFace() const
{
    if (isEntireLevelCubeMap())
    {
        return gl::kCubeMapTextureTargetMin;
    }
    else
    {
        return getTarget();
    }
}

GLint ImageIndex::cubeMapFaceIndex() const
{
    ASSERT(mType == TextureType::CubeMap);
    ASSERT(mLayerIndex == kEntireLevel || mLayerIndex < static_cast<GLint>(kCubeFaceCount));
    return mLayerIndex;
}

bool ImageIndex::valid() const
{
    return mType != TextureType::InvalidEnum;
}

bool ImageIndex::isEntireLevelCubeMap() const
{
    return mType == TextureType::CubeMap && mLayerIndex == ImageIndex::kEntireLevel;
}

ImageIndex ImageIndex::Make2D(GLint levelIndex)
{
    return ImageIndex(TextureType::_2D, levelIndex, kEntireLevel, 1);
}

ImageIndex ImageIndex::MakeRectangle(GLint levelIndex)
{
    return ImageIndex(TextureType::Rectangle, levelIndex, kEntireLevel, 1);
}

ImageIndex ImageIndex::MakeCubeMapFace(TextureTarget target, GLint levelIndex)
{
    ASSERT(IsCubeMapFaceTarget(target));
    return ImageIndex(TextureType::CubeMap, levelIndex, TextureTargetToLayer(target), 1);
}

ImageIndex ImageIndex::Make2DArray(GLint levelIndex, GLint layerIndex)
{
    return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, 1);
}

ImageIndex ImageIndex::Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint numLayers)
{
    return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, numLayers);
}

ImageIndex ImageIndex::Make3D(GLint levelIndex, GLint layerIndex)
{
    return ImageIndex(TextureType::_3D, levelIndex, layerIndex, 1);
}

ImageIndex ImageIndex::MakeFromTarget(TextureTarget target, GLint levelIndex, GLint depth)
{
    return ImageIndex(TextureTargetToType(target), levelIndex, TextureTargetToLayer(target),
                      IsArrayTarget(target) ? depth : 1);
}

ImageIndex ImageIndex::MakeFromType(TextureType type,
                                    GLint levelIndex,
                                    GLint layerIndex,
                                    GLint layerCount)
{
    GLint overrideLayerCount =
        (type == TextureType::CubeMap && layerIndex == kEntireLevel ? kCubeFaceCount : layerCount);
    return ImageIndex(type, levelIndex, layerIndex, overrideLayerCount);
}

ImageIndex ImageIndex::MakeBuffer()
{
    return ImageIndex(TextureType::Buffer, 0, kEntireLevel, 1);
}

ImageIndex ImageIndex::Make2DMultisample()
{
    return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1);
}

ImageIndex ImageIndex::Make2DMultisampleArray(GLint layerIndex)
{
    return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, 1);
}

ImageIndex ImageIndex::Make2DMultisampleArrayRange(GLint layerIndex, GLint numLayers)
{
    return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, numLayers);
}

bool ImageIndex::operator<(const ImageIndex &b) const
{
    return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) <
           std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
}

bool ImageIndex::operator==(const ImageIndex &b) const
{
    return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) ==
           std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
}

bool ImageIndex::operator!=(const ImageIndex &b) const
{
    return !(*this == b);
}

ImageIndex::ImageIndex(TextureType type, GLint levelIndex, GLint layerIndex, GLint layerCount)
    : mType(type), mLevelIndex(levelIndex), mLayerIndex(layerIndex), mLayerCount(layerCount)
{}

ImageIndexIterator ImageIndex::getLayerIterator(GLint layerCount) const
{
    ASSERT(mType != TextureType::_2D && !hasLayer());
    return ImageIndexIterator::MakeGeneric(mType, mLevelIndex, mLevelIndex + 1, 0, layerCount);
}

ImageIndexIterator::ImageIndexIterator(const ImageIndexIterator &other) = default;

ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
{
    return ImageIndexIterator(TextureType::_2D, Range<GLint>(minMip, maxMip),
                              Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
                              nullptr);
}

ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
{
    return ImageIndexIterator(TextureType::Rectangle, Range<GLint>(minMip, maxMip),
                              Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
                              nullptr);
}

ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
{
    return ImageIndexIterator(TextureType::CubeMap, Range<GLint>(minMip, maxMip),
                              Range<GLint>(0, 6), nullptr);
}

ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip,
                                              GLint maxMip,
                                              GLint minLayer,
                                              GLint maxLayer)
{
    return ImageIndexIterator(TextureType::_3D, Range<GLint>(minMip, maxMip),
                              Range<GLint>(minLayer, maxLayer), nullptr);
}

ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip,
                                                   GLint maxMip,
                                                   const GLsizei *layerCounts)
{
    return ImageIndexIterator(TextureType::_2DArray, Range<GLint>(minMip, maxMip),
                              Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
                              layerCounts);
}

ImageIndexIterator ImageIndexIterator::Make2DMultisample()
{
    return ImageIndexIterator(TextureType::_2DMultisample, Range<GLint>(0, 1),
                              Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
                              nullptr);
}

ImageIndexIterator ImageIndexIterator::MakeBuffer()
{
    return ImageIndexIterator(TextureType::Buffer, Range<GLint>(0, 1),
                              Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
                              nullptr);
}

ImageIndexIterator ImageIndexIterator::Make2DMultisampleArray(const GLsizei *layerCounts)
{
    return ImageIndexIterator(TextureType::_2DMultisampleArray, Range<GLint>(0, 1),
                              Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
                              layerCounts);
}

ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type,
                                                   GLint minMip,
                                                   GLint maxMip,
                                                   GLint minLayer,
                                                   GLint maxLayer)
{
    if (type == TextureType::CubeMap && minLayer == ImageIndex::kEntireLevel &&
        maxLayer == ImageIndex::kEntireLevel)
    {
        return MakeCube(minMip, maxMip);
    }

    return ImageIndexIterator(type, Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer),
                              nullptr);
}

ImageIndexIterator::ImageIndexIterator(TextureType type,
                                       const Range<GLint> &mipRange,
                                       const Range<GLint> &layerRange,
                                       const GLsizei *layerCounts)
    : mMipRange(mipRange),
      mLayerRange(layerRange),
      mLayerCounts(layerCounts),
      mCurrentIndex(type, mipRange.low(), layerRange.low(), 1)
{}

GLint ImageIndexIterator::maxLayer() const
{
    if (mLayerCounts)
    {
        ASSERT(mCurrentIndex.hasLayer());
        return (mCurrentIndex.getLevelIndex() < mMipRange.high())
                   ? ANGLE_UNSAFE_TODO(mLayerCounts[mCurrentIndex.getLevelIndex()])
                   : 0;
    }
    return mLayerRange.high();
}

ImageIndex ImageIndexIterator::next()
{
    ASSERT(hasNext());

    // Make a copy of the current index to return
    ImageIndex previousIndex = mCurrentIndex;

    // Iterate layers in the inner loop for now. We can add switchable
    // layer or mip iteration if we need it.

    if (mCurrentIndex.hasLayer() && mCurrentIndex.getLayerIndex() < maxLayer() - 1)
    {
        mCurrentIndex.mLayerIndex++;
    }
    else if (mCurrentIndex.mLevelIndex < mMipRange.high() - 1)
    {
        mCurrentIndex.mLayerIndex = mLayerRange.low();
        mCurrentIndex.mLevelIndex++;
    }
    else
    {
        mCurrentIndex = ImageIndex();
    }

    return previousIndex;
}

ImageIndex ImageIndexIterator::current() const
{
    return mCurrentIndex;
}

bool ImageIndexIterator::hasNext() const
{
    return mCurrentIndex.valid();
}

}  // namespace gl
