Edit

kc3-lang/angle/src/libANGLE/ImageIndex.cpp

Branch :

  • Show log

    Commit

  • Author : Jiawei Shao
    Date : 2018-05-28 11:17:47
    Hash : a8802477
    Message : ES31: Implement FramebufferTextureEXT on OpenGL back-ends This patch intends to implement FramebufferTextureEXT on OpenGL back-ends. 1. Support layered framebuffer attachments. 2. Add new framebuffer completeness rules on layered framebuffer attachments. 3. Support FRAMEBUFFER_ATTACHMENT_LAYERED_EXT as a valid <pname> parameter of GetFramebufferAttachmentParameteriv. Note that for an entire level of a cube map: 1. It has no TextureTarget because TEXTURE_CUBE is not a valid target for TexImage*D. 2. It corresponds to 6 ImageDescs (that represents its faces) in class Texture, so when the cube map is cube complete, we return the ImageDesc of its first face, meanwhile we do not allow querying ImageDesc if it is not cube complete. BUG=angleproject:1941 TEST=angle_end2end_tests dEQP-GLES31.functional.geometry_shading.query.framebuffer_attachment_layers dEQP-GLES31.functional.geometry_shading.query.framebuffer_incomplete_layer_targets dEQP-GLES31.functional.geometry_shading.layered.* dEQP-GLES31.functional.geometry_shading.instanced.invocation_per_layer_* dEQP-GLES31.functional.geometry_shading.instanced.multiple_layers_per_invocation_* Change-Id: I44393b513ec8f1a682fd1c47d3eaa6f3b3fae877 Reviewed-on: https://chromium-review.googlesource.com/1075811 Commit-Queue: Jiawei Shao <jiawei.shao@intel.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org>

  • src/libANGLE/ImageIndex.cpp
  • //
    // 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:
                return ImageIndex::kEntireLevel;
            case TextureTarget::Rectangle:
                return ImageIndex::kEntireLevel;
            case TextureTarget::_2D:
                return ImageIndex::kEntireLevel;
            case TextureTarget::_2DArray:
                return ImageIndex::kEntireLevel;
            case TextureTarget::_2DMultisample:
                return ImageIndex::kEntireLevel;
            case TextureTarget::_3D:
                return ImageIndex::kEntireLevel;
            default:
                UNREACHABLE();
                return 0;
        }
    }
    
    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);
        }
    }
    }  // anonymous namespace
    
    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::CubeMap:
            case TextureType::_3D:
                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;
    }
    
    TextureTarget ImageIndex::getTarget() const
    {
        return TextureTypeToTarget(mType, mLayerIndex);
    }
    
    GLint ImageIndex::cubeMapFaceIndex() const
    {
        ASSERT(mType == TextureType::CubeMap);
        ASSERT(mLayerIndex == kEntireLevel || mLayerIndex < static_cast<GLint>(CUBE_FACE_COUNT));
        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)
    {
        return ImageIndex(TextureTargetToType(target), levelIndex, TextureTargetToLayer(target), 1);
    }
    
    ImageIndex ImageIndex::MakeFromType(TextureType type,
                                        GLint levelIndex,
                                        GLint layerIndex,
                                        GLint layerCount)
    {
        GLint overrideLayerCount =
            (type == TextureType::CubeMap && layerIndex == kEntireLevel ? CUBE_FACE_COUNT : layerCount);
        return ImageIndex(type, levelIndex, layerIndex, overrideLayerCount);
    }
    
    ImageIndex ImageIndex::Make2DMultisample()
    {
        return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1);
    }
    
    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, 0),
                                  Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
                                  nullptr);
    }
    
    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