| // |
| // 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.h: A helper struct for indexing into an Image array |
| |
| #ifndef LIBANGLE_IMAGE_INDEX_H_ |
| #define LIBANGLE_IMAGE_INDEX_H_ |
| |
| #include "common/PackedEnums.h" |
| #include "common/mathutil.h" |
| #include "libANGLE/angletypes.h" |
| |
| #include "angle_gl.h" |
| |
| namespace egl |
| { |
| struct ImageSourceAttributes; |
| } |
| |
| namespace gl |
| { |
| |
| class ImageIndexIterator; |
| |
| class ImageIndex |
| { |
| public: |
| ImageIndex(); |
| ImageIndex(const ImageIndex &other); |
| ImageIndex &operator=(const ImageIndex &other); |
| |
| TextureType getType() const { return mType; } |
| GLint getLevelIndex() const { return mLevelIndex; } |
| GLint getLayerIndex() const { return mLayerIndex; } |
| GLint getLayerCount() const { return mLayerCount; } |
| |
| bool hasLayer() const; |
| bool has3DLayer() const; |
| bool usesTex3D() const; |
| GLint cubeMapFaceIndex() const; |
| bool valid() const; |
| // Note that you cannot use this function when the ImageIndex represents an entire level of cube |
| // map. |
| TextureTarget getTarget() const; |
| TextureTarget getTargetOrFirstCubeFace() const; |
| |
| bool isLayered() const; |
| bool isEntireLevelCubeMap() const; |
| |
| static ImageIndex MakeBuffer(); |
| static ImageIndex Make2D(GLint levelIndex); |
| static ImageIndex MakeRectangle(GLint levelIndex); |
| static ImageIndex MakeCubeMapFace(TextureTarget target, GLint levelIndex); |
| static ImageIndex Make2DArray(GLint levelIndex, GLint layerIndex = kEntireLevel); |
| static ImageIndex Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint layerCount); |
| static ImageIndex Make3D(GLint levelIndex, GLint layerIndex = kEntireLevel); |
| static ImageIndex MakeFromTarget(TextureTarget target, GLint levelIndex, GLint depth = 0); |
| static ImageIndex MakeFromType(TextureType type, |
| GLint levelIndex, |
| GLint layerIndex = kEntireLevel, |
| GLint layerCount = 1); |
| static ImageIndex Make2DMultisample(); |
| static ImageIndex Make2DMultisampleArray(GLint layerIndex = kEntireLevel); |
| static ImageIndex Make2DMultisampleArrayRange(GLint layerIndex, GLint layerCount); |
| |
| static constexpr GLint kEntireLevel = static_cast<GLint>(-1); |
| |
| bool operator<(const ImageIndex &b) const; |
| bool operator==(const ImageIndex &b) const; |
| bool operator!=(const ImageIndex &b) const; |
| |
| // Only valid for 3D/Cube textures with layers. |
| ImageIndexIterator getLayerIterator(GLint layerCount) const; |
| |
| private: |
| friend class ImageIndexIterator; |
| |
| ImageIndex(TextureType type, GLint leveIndex, GLint layerIndex, GLint layerCount); |
| |
| TextureType mType; |
| GLint mLevelIndex; |
| GLint mLayerIndex; |
| GLint mLayerCount; |
| }; |
| |
| // To be used like this: |
| // |
| // ImageIndexIterator it = ...; |
| // while (it.hasNext()) |
| // { |
| // ImageIndex current = it.next(); |
| // } |
| class ImageIndexIterator |
| { |
| public: |
| ImageIndexIterator(const ImageIndexIterator &other); |
| |
| static ImageIndexIterator MakeBuffer(); |
| static ImageIndexIterator Make2D(GLint minMip, GLint maxMip); |
| static ImageIndexIterator MakeRectangle(GLint minMip, GLint maxMip); |
| static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip); |
| static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer); |
| static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts); |
| static ImageIndexIterator Make2DMultisample(); |
| static ImageIndexIterator Make2DMultisampleArray(const GLsizei *layerCounts); |
| static ImageIndexIterator MakeGeneric(TextureType type, |
| GLint minMip, |
| GLint maxMip, |
| GLint minLayer, |
| GLint maxLayer); |
| |
| ImageIndex next(); |
| ImageIndex current() const; |
| bool hasNext() const; |
| |
| private: |
| ImageIndexIterator(TextureType type, |
| const Range<GLint> &mipRange, |
| const Range<GLint> &layerRange, |
| const GLsizei *layerCounts); |
| |
| GLint maxLayer() const; |
| |
| const Range<GLint> mMipRange; |
| const Range<GLint> mLayerRange; |
| const GLsizei *const mLayerCounts; |
| |
| ImageIndex mCurrentIndex; |
| }; |
| |
| TextureTarget TextureTypeToTarget(TextureType type, GLint layerIndex); |
| |
| // A |Texture| can have a number of levels and layers. An EGL image may be created out of the |
| // texture, viewing a specific level and layer specified by EGL_GL_TEXTURE_LEVEL_KHR and |
| // EGL_GL_TEXTURE_ZOFFSET_KHR. The EGL image can then be imported into another texture whose own |
| // state does not include these offsets (e.g. the texture is accessed at level 0). It may similarly |
| // be imported into a renderbuffer that doesn't even have a level and layer state. It's easy to |
| // confuse which gl::ImageIndex translates to the (backend's) backing image's level/layer. |
| // |
| // For example, consider the source texture as defined as having 4 levels, with base level 2. The |
| // EGL image is created with EGL_GL_TEXTURE_LEVEL_KHR = 3, and imported into the target texture |
| // Then: |
| // |
| // * The backing image (such as VkImage) can be created with 2 levels, corresponding to the source |
| // texture's levels 2 and 3. |
| // * The target texture's base level (always 0) maps to the backing image's level 1, which is 3 (the |
| // EGL image level) minus 2 (base level). |
| // |
| // To avoid all confusions, some types specific to image siblings are created: |
| // |
| // * OwnLevel, OwnLayer and OwnImageIndex: these contain levels and layers from the |
| // point of view of the current texture, be it the source or target texture. They correspond to |
| // the front-end's state, and are passed to the backend. |
| // * SourceLevel, SourceLayer and SourceImageIndex: these contain levels and layers corresponding to |
| // the source texture. For the source texture itself, these are equal to the Own* variants. For |
| // the target texture, they are offset by mEGLImageSourceAttributes. This property holds for the |
| // source texture too, since these offsets are zero. |
| // |
| // Before the backend accesses the backing image, it must use the |toSource*()| helpers in |
| // TextureState/RenderbufferState to convert |Own*| types to |Source*| types, where the EGL image |
| // level and layer offsets are applied, and finally |get()| the translated level/layer/image index |
| // to interface with the backing image. The backend |TextureBackend| object should strive to |
| // internally pass around either Own* or Source* types, never gl::LevelIndex, uint32_t |
| // layer or gl::ImageIndex directly to ensure translation is always done and done only once. |
| // Ideally, the backend would _never_ use the gl::LevelIndex, uint32_t layer and gl::ImageIndex |
| // directly and would always use either the |Own*| or |Source*| type so there cannot be mistakes. |
| // |
| // For backends that don't need this translation, such as the GL backend where the translation is |
| // done by the driver, use |getUntranslated()| to get the untranslated front-end values for the |
| // current texture out of |Own*| types. |
| template <typename T> |
| class OwnIndex |
| { |
| public: |
| explicit OwnIndex(T index) : mIndex(index) {} |
| |
| T getUntranslated() const { return mIndex; } |
| |
| protected: |
| T mIndex; |
| }; |
| |
| template <typename T> |
| class SourceIndex |
| { |
| public: |
| T get() const { return mIndex; } |
| |
| protected: |
| friend struct egl::ImageSourceAttributes; |
| SourceIndex(T index) : mIndex(index) {} |
| T mIndex; |
| }; |
| |
| // Note: The front-end generally uses uint32_t for levels instead of LevelIndex. The templated type |
| // uses LevelIndex so it's different from OwnLayer, but a uint32_t-taking constructor is added for |
| // convenience. |
| class OwnLevel : public OwnIndex<LevelIndex> |
| { |
| public: |
| explicit OwnLevel(uint32_t level) : OwnIndex(LevelIndex(level)) {} |
| }; |
| using OwnLayer = OwnIndex<uint32_t>; |
| class OwnImageIndex : public OwnIndex<ImageIndex> |
| { |
| public: |
| explicit OwnImageIndex(const ImageIndex &index) : OwnIndex(index) {} |
| |
| // Convenience helpers that forward to ImageIndex and possibly wrap the results. |
| TextureType getType() const { return mIndex.getType(); } |
| OwnLevel getLevelIndex() const { return OwnLevel(mIndex.getLevelIndex()); } |
| bool hasLayer() const { return mIndex.hasLayer(); } |
| OwnLayer getLayerIndex() const |
| { |
| return OwnLayer(mIndex.hasLayer() ? mIndex.getLayerIndex() : 0); |
| } |
| OwnLayer cubeMapFaceIndex() const { return OwnLayer(mIndex.cubeMapFaceIndex()); } |
| uint32_t getLayerCount() const { return mIndex.getLayerCount(); } |
| bool usesTex3D() const { return mIndex.usesTex3D(); } |
| TextureTarget getTarget() const { return mIndex.getTarget(); } |
| TextureTarget getTargetOrFirstCubeFace() const { return mIndex.getTargetOrFirstCubeFace(); } |
| }; |
| |
| class SourceImageIndex; |
| class SourceLevel : public SourceIndex<LevelIndex> |
| { |
| public: |
| // Convenience helpers |
| SourceLevel operator+(uint32_t offset) const { return SourceLevel(mIndex + offset); } |
| |
| // Helper while code is being transitioned to using SourceLevel consistently. Remove once done. |
| // TODO(http://anglebug.com/525079760) |
| static SourceLevel VerifiedSourceLevel(LevelIndex level) { return SourceLevel(level); } |
| |
| protected: |
| friend struct egl::ImageSourceAttributes; |
| friend class SourceImageIndex; |
| SourceLevel(LevelIndex level) : SourceIndex(level) {} |
| }; |
| class SourceLayer : public SourceIndex<uint32_t> |
| { |
| public: |
| // Convenience helpers |
| SourceLayer operator+(uint32_t offset) const { return SourceLayer(mIndex + offset); } |
| |
| // Helper while code is being transitioned to using SourceLayer consistently. Remove once done. |
| // TODO(http://anglebug.com/525079760) |
| static SourceLayer VerifiedSourceLayer(uint32_t layer) { return SourceLayer(layer); } |
| |
| protected: |
| friend struct egl::ImageSourceAttributes; |
| friend class SourceImageIndex; |
| SourceLayer(uint32_t layer) : SourceIndex(layer) {} |
| }; |
| class SourceImageIndex : public SourceIndex<ImageIndex> |
| { |
| public: |
| // Helper while code is being transitioned to using SourceLevel consistently. Remove once done. |
| // TODO(http://anglebug.com/525079760) |
| static SourceImageIndex VerifiedSourceIndex(ImageIndex index) |
| { |
| return SourceImageIndex(index); |
| } |
| |
| // Convenience helpers that forward to ImageIndex and possibly wrap the results. |
| TextureType getType() const { return mIndex.getType(); } |
| SourceLevel getLevelIndex() const { return SourceLevel(LevelIndex(mIndex.getLevelIndex())); } |
| bool hasLayer() const { return mIndex.hasLayer(); } |
| SourceLayer getLayerIndex() const |
| { |
| return SourceLayer(mIndex.hasLayer() ? mIndex.getLayerIndex() : 0); |
| } |
| SourceLayer cubeMapFaceIndex() const { return SourceLayer(mIndex.cubeMapFaceIndex()); } |
| uint32_t getLayerCount() const { return mIndex.getLayerCount(); } |
| bool usesTex3D() const { return mIndex.usesTex3D(); } |
| TextureTarget getTarget() const { return mIndex.getTarget(); } |
| TextureTarget getTargetOrFirstCubeFace() const { return mIndex.getTargetOrFirstCubeFace(); } |
| |
| protected: |
| friend struct egl::ImageSourceAttributes; |
| SourceImageIndex(const ImageIndex &index) : SourceIndex(index) {} |
| }; |
| |
| } // namespace gl |
| |
| #endif // LIBANGLE_IMAGE_INDEX_H_ |