diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/ImageIndex.cpp')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/ImageIndex.cpp | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/ImageIndex.cpp b/gfx/angle/checkout/src/libANGLE/ImageIndex.cpp new file mode 100644 index 0000000000..55e0393fa4 --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/ImageIndex.cpp @@ -0,0 +1,388 @@ +// +// 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/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::VideoImage: + 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) + { + 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()) + ? 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 |