1 #include "ImageIndex.h"
2 //
3 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6 //
7 
8 // ImageIndex.cpp: Implementation for ImageIndex methods.
9 
10 #include "libANGLE/ImageIndex.h"
11 #include "libANGLE/Constants.h"
12 #include "common/utilities.h"
13 
14 #include <tuple>
15 
16 namespace gl
17 {
18 
19 ImageIndex::ImageIndex(const ImageIndex &other) = default;
20 ImageIndex &ImageIndex::operator=(const ImageIndex &other) = default;
21 
is3D() const22 bool ImageIndex::is3D() const
23 {
24     return type == GL_TEXTURE_3D || type == GL_TEXTURE_2D_ARRAY;
25 }
26 
cubeMapFaceIndex() const27 GLint ImageIndex::cubeMapFaceIndex() const
28 {
29     ASSERT(type == GL_TEXTURE_CUBE_MAP);
30     ASSERT(target >= gl::FirstCubeMapTextureTarget && target <= gl::LastCubeMapTextureTarget);
31     return target - gl::FirstCubeMapTextureTarget;
32 }
33 
valid() const34 bool ImageIndex::valid() const
35 {
36     return type != GL_NONE;
37 }
38 
Make2D(GLint mipIndex)39 ImageIndex ImageIndex::Make2D(GLint mipIndex)
40 {
41     return ImageIndex(GL_TEXTURE_2D, GL_TEXTURE_2D, mipIndex, ENTIRE_LEVEL, 1);
42 }
43 
MakeRectangle(GLint mipIndex)44 ImageIndex ImageIndex::MakeRectangle(GLint mipIndex)
45 {
46     return ImageIndex(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_RECTANGLE_ANGLE, mipIndex,
47                       ENTIRE_LEVEL, 1);
48 }
49 
MakeCube(GLenum target,GLint mipIndex)50 ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex)
51 {
52     ASSERT(gl::IsCubeMapTextureTarget(target));
53     return ImageIndex(GL_TEXTURE_CUBE_MAP, target, mipIndex, ENTIRE_LEVEL, 1);
54 }
55 
Make2DArray(GLint mipIndex,GLint layerIndex)56 ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex)
57 {
58     return ImageIndex(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex, 1);
59 }
60 
Make2DArrayRange(GLint mipIndex,GLint layerIndex,GLint numLayers)61 ImageIndex ImageIndex::Make2DArrayRange(GLint mipIndex, GLint layerIndex, GLint numLayers)
62 {
63     return ImageIndex(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex, numLayers);
64 }
65 
Make3D(GLint mipIndex,GLint layerIndex)66 ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
67 {
68     return ImageIndex(GL_TEXTURE_3D, GL_TEXTURE_3D, mipIndex, layerIndex, 1);
69 }
70 
MakeGeneric(GLenum target,GLint mipIndex)71 ImageIndex ImageIndex::MakeGeneric(GLenum target, GLint mipIndex)
72 {
73     GLenum textureType = IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target;
74     return ImageIndex(textureType, target, mipIndex, ENTIRE_LEVEL, 1);
75 }
76 
Make2DMultisample()77 ImageIndex ImageIndex::Make2DMultisample()
78 {
79     return ImageIndex(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE, 0, ENTIRE_LEVEL, 1);
80 }
81 
MakeInvalid()82 ImageIndex ImageIndex::MakeInvalid()
83 {
84     return ImageIndex(GL_NONE, GL_NONE, -1, -1, -1);
85 }
86 
operator <(const ImageIndex & a,const ImageIndex & b)87 bool operator<(const ImageIndex &a, const ImageIndex &b)
88 {
89     return std::tie(a.type, a.target, a.mipIndex, a.layerIndex, a.numLayers) <
90            std::tie(b.type, b.target, b.mipIndex, b.layerIndex, b.numLayers);
91 }
92 
operator ==(const ImageIndex & a,const ImageIndex & b)93 bool operator==(const ImageIndex &a, const ImageIndex &b)
94 {
95     return std::tie(a.type, a.target, a.mipIndex, a.layerIndex, a.numLayers) ==
96            std::tie(b.type, b.target, b.mipIndex, b.layerIndex, b.numLayers);
97 }
98 
operator !=(const ImageIndex & a,const ImageIndex & b)99 bool operator!=(const ImageIndex &a, const ImageIndex &b)
100 {
101     return !(a == b);
102 }
103 
ImageIndex(GLenum typeIn,GLenum targetIn,GLint mipIndexIn,GLint layerIndexIn,GLint numLayersIn)104 ImageIndex::ImageIndex(GLenum typeIn,
105                        GLenum targetIn,
106                        GLint mipIndexIn,
107                        GLint layerIndexIn,
108                        GLint numLayersIn)
109     : type(typeIn),
110       target(targetIn),
111       mipIndex(mipIndexIn),
112       layerIndex(layerIndexIn),
113       numLayers(numLayersIn)
114 {}
115 
116 ImageIndexIterator::ImageIndexIterator(const ImageIndexIterator &other) = default;
117 
Make2D(GLint minMip,GLint maxMip)118 ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
119 {
120     return ImageIndexIterator(
121         GL_TEXTURE_2D, Range<GLenum>(GL_TEXTURE_2D, GL_TEXTURE_2D), Range<GLint>(minMip, maxMip),
122         Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), nullptr);
123 }
124 
MakeRectangle(GLint minMip,GLint maxMip)125 ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
126 {
127     return ImageIndexIterator(GL_TEXTURE_RECTANGLE_ANGLE,
128                               Range<GLenum>(GL_TEXTURE_RECTANGLE_ANGLE, GL_TEXTURE_RECTANGLE_ANGLE),
129                               Range<GLint>(minMip, maxMip),
130                               Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL),
131                               nullptr);
132 }
133 
MakeCube(GLint minMip,GLint maxMip)134 ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
135 {
136     return ImageIndexIterator(
137         GL_TEXTURE_CUBE_MAP,
138         Range<GLenum>(gl::FirstCubeMapTextureTarget, gl::LastCubeMapTextureTarget),
139         Range<GLint>(minMip, maxMip),
140         Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), nullptr);
141 }
142 
Make3D(GLint minMip,GLint maxMip,GLint minLayer,GLint maxLayer)143 ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip,
144                                               GLint minLayer, GLint maxLayer)
145 {
146     return ImageIndexIterator(GL_TEXTURE_3D, Range<GLenum>(GL_TEXTURE_3D, GL_TEXTURE_3D),
147                               Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer),
148                               nullptr);
149 }
150 
Make2DArray(GLint minMip,GLint maxMip,const GLsizei * layerCounts)151 ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip,
152                                                    const GLsizei *layerCounts)
153 {
154     return ImageIndexIterator(
155         GL_TEXTURE_2D_ARRAY, Range<GLenum>(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_2D_ARRAY),
156         Range<GLint>(minMip, maxMip), Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
157         layerCounts);
158 }
159 
Make2DMultisample()160 ImageIndexIterator ImageIndexIterator::Make2DMultisample()
161 {
162     return ImageIndexIterator(
163         GL_TEXTURE_2D_MULTISAMPLE,
164         Range<GLenum>(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_MULTISAMPLE), Range<GLint>(0, 0),
165         Range<GLint>(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), nullptr);
166 }
167 
ImageIndexIterator(GLenum type,const Range<GLenum> & targetRange,const Range<GLint> & mipRange,const Range<GLint> & layerRange,const GLsizei * layerCounts)168 ImageIndexIterator::ImageIndexIterator(GLenum type,
169                                        const Range<GLenum> &targetRange,
170                                        const Range<GLint> &mipRange,
171                                        const Range<GLint> &layerRange,
172                                        const GLsizei *layerCounts)
173     : mTargetRange(targetRange),
174       mMipRange(mipRange),
175       mLayerRange(layerRange),
176       mLayerCounts(layerCounts),
177       mCurrentIndex(type, targetRange.low(), mipRange.low(), layerRange.low(), 1)
178 {}
179 
maxLayer() const180 GLint ImageIndexIterator::maxLayer() const
181 {
182     if (mLayerCounts)
183     {
184         ASSERT(mCurrentIndex.hasLayer());
185         return (mCurrentIndex.mipIndex < mMipRange.high()) ? mLayerCounts[mCurrentIndex.mipIndex]
186                                                            : 0;
187     }
188     return mLayerRange.high();
189 }
190 
next()191 ImageIndex ImageIndexIterator::next()
192 {
193     ASSERT(hasNext());
194 
195     // Make a copy of the current index to return
196     ImageIndex previousIndex = mCurrentIndex;
197 
198     // Iterate layers in the inner loop for now. We can add switchable
199     // layer or mip iteration if we need it.
200 
201     if (mCurrentIndex.target < mTargetRange.high())
202     {
203         mCurrentIndex.target++;
204     }
205     else if (mCurrentIndex.hasLayer() && mCurrentIndex.layerIndex < maxLayer() - 1)
206     {
207         mCurrentIndex.target = mTargetRange.low();
208         mCurrentIndex.layerIndex++;
209     }
210     else if (mCurrentIndex.mipIndex < mMipRange.high() - 1)
211     {
212         mCurrentIndex.target     = mTargetRange.low();
213         mCurrentIndex.layerIndex = mLayerRange.low();
214         mCurrentIndex.mipIndex++;
215     }
216     else
217     {
218         mCurrentIndex = ImageIndex::MakeInvalid();
219     }
220 
221     return previousIndex;
222 }
223 
current() const224 ImageIndex ImageIndexIterator::current() const
225 {
226     return mCurrentIndex;
227 }
228 
hasNext() const229 bool ImageIndexIterator::hasNext() const
230 {
231     return mCurrentIndex.valid();
232 }
233 
234 }  // namespace gl
235