• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // ImageIndex.cpp: Implementation for ImageIndex methods.
8 
9 #include "libANGLE/ImageIndex.h"
10 
11 #include "common/utilities.h"
12 #include "libANGLE/Constants.h"
13 #include "libANGLE/angletypes.h"
14 
15 #include <tuple>
16 
17 namespace gl
18 {
19 namespace
20 {
TextureTargetToLayer(TextureTarget target)21 GLint TextureTargetToLayer(TextureTarget target)
22 {
23     switch (target)
24     {
25         case TextureTarget::CubeMapPositiveX:
26             return 0;
27         case TextureTarget::CubeMapNegativeX:
28             return 1;
29         case TextureTarget::CubeMapPositiveY:
30             return 2;
31         case TextureTarget::CubeMapNegativeY:
32             return 3;
33         case TextureTarget::CubeMapPositiveZ:
34             return 4;
35         case TextureTarget::CubeMapNegativeZ:
36             return 5;
37         case TextureTarget::External:
38             return ImageIndex::kEntireLevel;
39         case TextureTarget::Rectangle:
40             return ImageIndex::kEntireLevel;
41         case TextureTarget::_2D:
42             return ImageIndex::kEntireLevel;
43         case TextureTarget::_2DArray:
44             return ImageIndex::kEntireLevel;
45         case TextureTarget::_2DMultisample:
46             return ImageIndex::kEntireLevel;
47         case TextureTarget::_2DMultisampleArray:
48             return ImageIndex::kEntireLevel;
49         case TextureTarget::_3D:
50             return ImageIndex::kEntireLevel;
51         default:
52             UNREACHABLE();
53             return 0;
54     }
55 }
56 
TextureTypeToTarget(TextureType type,GLint layerIndex)57 TextureTarget TextureTypeToTarget(TextureType type, GLint layerIndex)
58 {
59     if (type == TextureType::CubeMap)
60     {
61         // As GL_TEXTURE_CUBE_MAP cannot be a texture target in texImage*D APIs, so we don't allow
62         // an entire cube map to have a texture target.
63         ASSERT(layerIndex != ImageIndex::kEntireLevel);
64         return CubeFaceIndexToTextureTarget(layerIndex);
65     }
66     else
67     {
68         return NonCubeTextureTypeToTarget(type);
69     }
70 }
71 
IsArrayTarget(TextureTarget target)72 bool IsArrayTarget(TextureTarget target)
73 {
74     switch (target)
75     {
76         case TextureTarget::_2DArray:
77         case TextureTarget::_2DMultisampleArray:
78             return true;
79         default:
80             return false;
81     }
82 }
83 }  // anonymous namespace
84 
ImageIndex()85 ImageIndex::ImageIndex()
86     : mType(TextureType::InvalidEnum), mLevelIndex(0), mLayerIndex(0), mLayerCount(kEntireLevel)
87 {}
88 
89 ImageIndex::ImageIndex(const ImageIndex &other) = default;
90 
91 ImageIndex &ImageIndex::operator=(const ImageIndex &other) = default;
92 
hasLayer() const93 bool ImageIndex::hasLayer() const
94 {
95     return mLayerIndex != kEntireLevel;
96 }
97 
isLayered() const98 bool ImageIndex::isLayered() const
99 {
100     switch (mType)
101     {
102         case TextureType::_2DArray:
103         case TextureType::_2DMultisampleArray:
104         case TextureType::CubeMap:
105         case TextureType::_3D:
106             return mLayerIndex == kEntireLevel;
107         default:
108             return false;
109     }
110 }
111 
has3DLayer() const112 bool ImageIndex::has3DLayer() const
113 {
114     // It's quicker to check != CubeMap than calling usesTex3D, which checks multiple types. This
115     // ASSERT validates the check gives the same result.
116     ASSERT(!hasLayer() || ((mType != TextureType::CubeMap) == usesTex3D()));
117     return (hasLayer() && mType != TextureType::CubeMap);
118 }
119 
usesTex3D() const120 bool ImageIndex::usesTex3D() const
121 {
122     return mType == TextureType::_3D || mType == TextureType::_2DArray ||
123            mType == TextureType::_2DMultisampleArray;
124 }
125 
getTarget() const126 TextureTarget ImageIndex::getTarget() const
127 {
128     return TextureTypeToTarget(mType, mLayerIndex);
129 }
130 
getTargetOrFirstCubeFace() const131 gl::TextureTarget ImageIndex::getTargetOrFirstCubeFace() const
132 {
133     if (isEntireLevelCubeMap())
134     {
135         return gl::kCubeMapTextureTargetMin;
136     }
137     else
138     {
139         return getTarget();
140     }
141 }
142 
cubeMapFaceIndex() const143 GLint ImageIndex::cubeMapFaceIndex() const
144 {
145     ASSERT(mType == TextureType::CubeMap);
146     ASSERT(mLayerIndex == kEntireLevel || mLayerIndex < static_cast<GLint>(kCubeFaceCount));
147     return mLayerIndex;
148 }
149 
valid() const150 bool ImageIndex::valid() const
151 {
152     return mType != TextureType::InvalidEnum;
153 }
154 
isEntireLevelCubeMap() const155 bool ImageIndex::isEntireLevelCubeMap() const
156 {
157     return mType == TextureType::CubeMap && mLayerIndex == ImageIndex::kEntireLevel;
158 }
159 
Make2D(GLint levelIndex)160 ImageIndex ImageIndex::Make2D(GLint levelIndex)
161 {
162     return ImageIndex(TextureType::_2D, levelIndex, kEntireLevel, 1);
163 }
164 
MakeRectangle(GLint levelIndex)165 ImageIndex ImageIndex::MakeRectangle(GLint levelIndex)
166 {
167     return ImageIndex(TextureType::Rectangle, levelIndex, kEntireLevel, 1);
168 }
169 
MakeCubeMapFace(TextureTarget target,GLint levelIndex)170 ImageIndex ImageIndex::MakeCubeMapFace(TextureTarget target, GLint levelIndex)
171 {
172     ASSERT(IsCubeMapFaceTarget(target));
173     return ImageIndex(TextureType::CubeMap, levelIndex, TextureTargetToLayer(target), 1);
174 }
175 
Make2DArray(GLint levelIndex,GLint layerIndex)176 ImageIndex ImageIndex::Make2DArray(GLint levelIndex, GLint layerIndex)
177 {
178     return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, 1);
179 }
180 
Make2DArrayRange(GLint levelIndex,GLint layerIndex,GLint numLayers)181 ImageIndex ImageIndex::Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint numLayers)
182 {
183     return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, numLayers);
184 }
185 
Make3D(GLint levelIndex,GLint layerIndex)186 ImageIndex ImageIndex::Make3D(GLint levelIndex, GLint layerIndex)
187 {
188     return ImageIndex(TextureType::_3D, levelIndex, layerIndex, 1);
189 }
190 
MakeFromTarget(TextureTarget target,GLint levelIndex,GLint depth)191 ImageIndex ImageIndex::MakeFromTarget(TextureTarget target, GLint levelIndex, GLint depth)
192 {
193     return ImageIndex(TextureTargetToType(target), levelIndex, TextureTargetToLayer(target),
194                       IsArrayTarget(target) ? depth : 1);
195 }
196 
MakeFromType(TextureType type,GLint levelIndex,GLint layerIndex,GLint layerCount)197 ImageIndex ImageIndex::MakeFromType(TextureType type,
198                                     GLint levelIndex,
199                                     GLint layerIndex,
200                                     GLint layerCount)
201 {
202     GLint overrideLayerCount =
203         (type == TextureType::CubeMap && layerIndex == kEntireLevel ? kCubeFaceCount : layerCount);
204     return ImageIndex(type, levelIndex, layerIndex, overrideLayerCount);
205 }
206 
Make2DMultisample()207 ImageIndex ImageIndex::Make2DMultisample()
208 {
209     return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1);
210 }
211 
Make2DMultisampleArray(GLint layerIndex)212 ImageIndex ImageIndex::Make2DMultisampleArray(GLint layerIndex)
213 {
214     return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, 1);
215 }
216 
Make2DMultisampleArrayRange(GLint layerIndex,GLint numLayers)217 ImageIndex ImageIndex::Make2DMultisampleArrayRange(GLint layerIndex, GLint numLayers)
218 {
219     return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, numLayers);
220 }
221 
operator <(const ImageIndex & b) const222 bool ImageIndex::operator<(const ImageIndex &b) const
223 {
224     return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) <
225            std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
226 }
227 
operator ==(const ImageIndex & b) const228 bool ImageIndex::operator==(const ImageIndex &b) const
229 {
230     return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) ==
231            std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
232 }
233 
operator !=(const ImageIndex & b) const234 bool ImageIndex::operator!=(const ImageIndex &b) const
235 {
236     return !(*this == b);
237 }
238 
ImageIndex(TextureType type,GLint levelIndex,GLint layerIndex,GLint layerCount)239 ImageIndex::ImageIndex(TextureType type, GLint levelIndex, GLint layerIndex, GLint layerCount)
240     : mType(type), mLevelIndex(levelIndex), mLayerIndex(layerIndex), mLayerCount(layerCount)
241 {}
242 
getLayerIterator(GLint layerCount) const243 ImageIndexIterator ImageIndex::getLayerIterator(GLint layerCount) const
244 {
245     ASSERT(mType != TextureType::_2D && !hasLayer());
246     return ImageIndexIterator::MakeGeneric(mType, mLevelIndex, mLevelIndex + 1, 0, layerCount);
247 }
248 
249 ImageIndexIterator::ImageIndexIterator(const ImageIndexIterator &other) = default;
250 
Make2D(GLint minMip,GLint maxMip)251 ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
252 {
253     return ImageIndexIterator(TextureType::_2D, Range<GLint>(minMip, maxMip),
254                               Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
255                               nullptr);
256 }
257 
MakeRectangle(GLint minMip,GLint maxMip)258 ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
259 {
260     return ImageIndexIterator(TextureType::Rectangle, Range<GLint>(minMip, maxMip),
261                               Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
262                               nullptr);
263 }
264 
MakeCube(GLint minMip,GLint maxMip)265 ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
266 {
267     return ImageIndexIterator(TextureType::CubeMap, Range<GLint>(minMip, maxMip),
268                               Range<GLint>(0, 6), nullptr);
269 }
270 
Make3D(GLint minMip,GLint maxMip,GLint minLayer,GLint maxLayer)271 ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip,
272                                               GLint maxMip,
273                                               GLint minLayer,
274                                               GLint maxLayer)
275 {
276     return ImageIndexIterator(TextureType::_3D, Range<GLint>(minMip, maxMip),
277                               Range<GLint>(minLayer, maxLayer), nullptr);
278 }
279 
Make2DArray(GLint minMip,GLint maxMip,const GLsizei * layerCounts)280 ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip,
281                                                    GLint maxMip,
282                                                    const GLsizei *layerCounts)
283 {
284     return ImageIndexIterator(TextureType::_2DArray, Range<GLint>(minMip, maxMip),
285                               Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
286                               layerCounts);
287 }
288 
Make2DMultisample()289 ImageIndexIterator ImageIndexIterator::Make2DMultisample()
290 {
291     return ImageIndexIterator(TextureType::_2DMultisample, Range<GLint>(0, 1),
292                               Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
293                               nullptr);
294 }
295 
Make2DMultisampleArray(const GLsizei * layerCounts)296 ImageIndexIterator ImageIndexIterator::Make2DMultisampleArray(const GLsizei *layerCounts)
297 {
298     return ImageIndexIterator(TextureType::_2DMultisampleArray, Range<GLint>(0, 1),
299                               Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
300                               layerCounts);
301 }
302 
MakeGeneric(TextureType type,GLint minMip,GLint maxMip,GLint minLayer,GLint maxLayer)303 ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type,
304                                                    GLint minMip,
305                                                    GLint maxMip,
306                                                    GLint minLayer,
307                                                    GLint maxLayer)
308 {
309     if (type == TextureType::CubeMap)
310     {
311         return MakeCube(minMip, maxMip);
312     }
313 
314     return ImageIndexIterator(type, Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer),
315                               nullptr);
316 }
317 
ImageIndexIterator(TextureType type,const Range<GLint> & mipRange,const Range<GLint> & layerRange,const GLsizei * layerCounts)318 ImageIndexIterator::ImageIndexIterator(TextureType type,
319                                        const Range<GLint> &mipRange,
320                                        const Range<GLint> &layerRange,
321                                        const GLsizei *layerCounts)
322     : mMipRange(mipRange),
323       mLayerRange(layerRange),
324       mLayerCounts(layerCounts),
325       mCurrentIndex(type, mipRange.low(), layerRange.low(), 1)
326 {}
327 
maxLayer() const328 GLint ImageIndexIterator::maxLayer() const
329 {
330     if (mLayerCounts)
331     {
332         ASSERT(mCurrentIndex.hasLayer());
333         return (mCurrentIndex.getLevelIndex() < mMipRange.high())
334                    ? mLayerCounts[mCurrentIndex.getLevelIndex()]
335                    : 0;
336     }
337     return mLayerRange.high();
338 }
339 
next()340 ImageIndex ImageIndexIterator::next()
341 {
342     ASSERT(hasNext());
343 
344     // Make a copy of the current index to return
345     ImageIndex previousIndex = mCurrentIndex;
346 
347     // Iterate layers in the inner loop for now. We can add switchable
348     // layer or mip iteration if we need it.
349 
350     if (mCurrentIndex.hasLayer() && mCurrentIndex.getLayerIndex() < maxLayer() - 1)
351     {
352         mCurrentIndex.mLayerIndex++;
353     }
354     else if (mCurrentIndex.mLevelIndex < mMipRange.high() - 1)
355     {
356         mCurrentIndex.mLayerIndex = mLayerRange.low();
357         mCurrentIndex.mLevelIndex++;
358     }
359     else
360     {
361         mCurrentIndex = ImageIndex();
362     }
363 
364     return previousIndex;
365 }
366 
current() const367 ImageIndex ImageIndexIterator::current() const
368 {
369     return mCurrentIndex;
370 }
371 
hasNext() const372 bool ImageIndexIterator::hasNext() const
373 {
374     return mCurrentIndex.valid();
375 }
376 
377 }  // namespace gl
378