Branch :
#include "ImageIndex.h"
//
// 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 "libANGLE/Constants.h"
#include "common/utilities.h"
#include <tuple>
namespace gl
{
ImageIndex::ImageIndex(const ImageIndex &other) = default;
ImageIndex &ImageIndex::operator=(const ImageIndex &other) = default;
bool ImageIndex::is3D() const
{
return type == TextureType::_3D || type == TextureType::_2DArray;
}
GLint ImageIndex::cubeMapFaceIndex() const
{
ASSERT(type == TextureType::CubeMap);
ASSERT(TextureTargetToType(target) == TextureType::CubeMap);
return static_cast<GLint>(CubeMapTextureTargetToFaceIndex(target));
}
bool ImageIndex::valid() const
{
return type != TextureType::InvalidEnum;
}
ImageIndex ImageIndex::Make2D(GLint mipIndex)
{
return ImageIndex(TextureType::_2D, TextureTarget::_2D, mipIndex, ENTIRE_LEVEL, 1);
}
ImageIndex ImageIndex::MakeRectangle(GLint mipIndex)
{
return ImageIndex(TextureType::Rectangle, TextureTarget::Rectangle, mipIndex, ENTIRE_LEVEL, 1);
}
ImageIndex ImageIndex::MakeCube(TextureTarget target, GLint mipIndex)
{
ASSERT(TextureTargetToType(target) == TextureType::CubeMap);
return ImageIndex(TextureType::CubeMap, target, mipIndex, ENTIRE_LEVEL, 1);
}
ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex)
{
return ImageIndex(TextureType::_2DArray, TextureTarget::_2DArray, mipIndex, layerIndex, 1);
}
ImageIndex ImageIndex::Make2DArrayRange(GLint mipIndex, GLint layerIndex, GLint numLayers)
{
return ImageIndex(TextureType::_2DArray, TextureTarget::_2DArray, mipIndex, layerIndex,
numLayers);
}
ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
{
return ImageIndex(TextureType::_3D, TextureTarget::_3D, mipIndex, layerIndex, 1);
}
ImageIndex ImageIndex::MakeGeneric(TextureTarget target, GLint mipIndex)
{
return ImageIndex(TextureTargetToType(target), target, mipIndex, ENTIRE_LEVEL, 1);
}
ImageIndex ImageIndex::Make2DMultisample()
{
return ImageIndex(TextureType::_2DMultisample, TextureTarget::_2DMultisample, 0, ENTIRE_LEVEL,
1);
}
ImageIndex ImageIndex::MakeInvalid()
{
return ImageIndex(TextureType::InvalidEnum, TextureTarget::InvalidEnum, -1, -1, -1);
}
bool operator<(const ImageIndex &a, const ImageIndex &b)
{
return std::tie(a.type, a.target, a.mipIndex, a.layerIndex, a.numLayers) <
std::tie(b.type, b.target, b.mipIndex, b.layerIndex, b.numLayers);
}
bool operator==(const ImageIndex &a, const ImageIndex &b)
{
return std::tie(a.type, a.target, a.mipIndex, a.layerIndex, a.numLayers) ==
std::tie(b.type, b.target, b.mipIndex, b.layerIndex, b.numLayers);
}
bool operator!=(const ImageIndex &a, const ImageIndex &b)
{
return !(a == b);
}
ImageIndex::ImageIndex(TextureType typeIn,
TextureTarget targetIn,
GLint mipIndexIn,
GLint layerIndexIn,
GLint numLayersIn)
: type(typeIn),
target(targetIn),
mipIndex(mipIndexIn),
layerIndex(layerIndexIn),
numLayers(numLayersIn)
{}
ImageIndexIterator::ImageIndexIterator(const ImageIndexIterator &other) = default;
ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
{
return ImageIndexIterator(
TextureType::_2D, TextureTarget::_2D, TextureTarget::_2D, Range<GLint>(minMip, maxMip),
Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), nullptr);
}
ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
{
return ImageIndexIterator(TextureType::Rectangle, TextureTarget::Rectangle,
TextureTarget::Rectangle, Range<GLint>(minMip, maxMip),
Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
nullptr);
}
ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
{
return ImageIndexIterator(TextureType::CubeMap, kCubeMapTextureTargetMin,
kCubeMapTextureTargetMax, Range<GLint>(minMip, maxMip),
Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
nullptr);
}
ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip,
GLint minLayer, GLint maxLayer)
{
return ImageIndexIterator(TextureType::_3D, TextureTarget::_3D, TextureTarget::_3D,
Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer),
nullptr);
}
ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
const GLsizei *layerCounts)
{
return ImageIndexIterator(TextureType::_2DArray, TextureTarget::_2DArray,
TextureTarget::_2DArray, Range<GLint>(minMip, maxMip),
Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
layerCounts);
}
ImageIndexIterator ImageIndexIterator::Make2DMultisample()
{
return ImageIndexIterator(TextureType::_2DMultisample, TextureTarget::_2DMultisample,
TextureTarget::_2DMultisample, Range<GLint>(0, 0),
Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
nullptr);
}
ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type, GLint minMip, GLint maxMip)
{
if (type == TextureType::CubeMap)
{
return MakeCube(minMip, maxMip);
}
TextureTarget target = NonCubeTextureTypeToTarget(type);
return ImageIndexIterator(type, target, target, Range<GLint>(minMip, maxMip),
Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
nullptr);
}
ImageIndexIterator::ImageIndexIterator(TextureType type,
angle::EnumIterator<TextureTarget> targetLow,
angle::EnumIterator<TextureTarget> targetHigh,
const Range<GLint> &mipRange,
const Range<GLint> &layerRange,
const GLsizei *layerCounts)
: mTargetLow(targetLow),
mTargetHigh(targetHigh),
mMipRange(mipRange),
mLayerRange(layerRange),
mLayerCounts(layerCounts),
mCurrentIndex(type, *targetLow, mipRange.low(), layerRange.low(), 1)
{}
GLint ImageIndexIterator::maxLayer() const
{
if (mLayerCounts)
{
ASSERT(mCurrentIndex.hasLayer());
return (mCurrentIndex.mipIndex < mMipRange.high()) ? mLayerCounts[mCurrentIndex.mipIndex]
: 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.
angle::EnumIterator<TextureTarget> currentTarget = mCurrentIndex.target;
if (currentTarget != mTargetHigh)
{
++currentTarget;
mCurrentIndex.target = *currentTarget;
}
else if (mCurrentIndex.hasLayer() && mCurrentIndex.layerIndex < maxLayer() - 1)
{
mCurrentIndex.target = *mTargetLow;
mCurrentIndex.layerIndex++;
}
else if (mCurrentIndex.mipIndex < mMipRange.high() - 1)
{
mCurrentIndex.target = *mTargetLow;
mCurrentIndex.layerIndex = mLayerRange.low();
mCurrentIndex.mipIndex++;
}
else
{
mCurrentIndex = ImageIndex::MakeInvalid();
}
return previousIndex;
}
ImageIndex ImageIndexIterator::current() const
{
return mCurrentIndex;
}
bool ImageIndexIterator::hasNext() const
{
return mCurrentIndex.valid();
}
} // namespace gl