• 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::VideoImage:
44             return ImageIndex::kEntireLevel;
45         case TextureTarget::_2DArray:
46             return ImageIndex::kEntireLevel;
47         case TextureTarget::_2DMultisample:
48             return ImageIndex::kEntireLevel;
49         case TextureTarget::_2DMultisampleArray:
50             return ImageIndex::kEntireLevel;
51         case TextureTarget::_3D:
52             return ImageIndex::kEntireLevel;
53         case TextureTarget::CubeMapArray:
54             return ImageIndex::kEntireLevel;
55         default:
56             UNREACHABLE();
57             return 0;
58     }
59 }
60 
IsArrayTarget(TextureTarget target)61 bool IsArrayTarget(TextureTarget target)
62 {
63     switch (target)
64     {
65         case TextureTarget::_2DArray:
66         case TextureTarget::_2DMultisampleArray:
67             return true;
68         default:
69             return false;
70     }
71 }
72 }  // anonymous namespace
73 
TextureTypeToTarget(TextureType type,GLint layerIndex)74 TextureTarget TextureTypeToTarget(TextureType type, GLint layerIndex)
75 {
76     if (type == TextureType::CubeMap)
77     {
78         // As GL_TEXTURE_CUBE_MAP cannot be a texture target in texImage*D APIs, so we don't allow
79         // an entire cube map to have a texture target.
80         ASSERT(layerIndex != ImageIndex::kEntireLevel);
81         return CubeFaceIndexToTextureTarget(layerIndex);
82     }
83     else
84     {
85         return NonCubeTextureTypeToTarget(type);
86     }
87 }
88 
ImageIndex()89 ImageIndex::ImageIndex()
90     : mType(TextureType::InvalidEnum), mLevelIndex(0), mLayerIndex(0), mLayerCount(kEntireLevel)
91 {}
92 
93 ImageIndex::ImageIndex(const ImageIndex &other) = default;
94 
95 ImageIndex &ImageIndex::operator=(const ImageIndex &other) = default;
96 
hasLayer() const97 bool ImageIndex::hasLayer() const
98 {
99     return mLayerIndex != kEntireLevel;
100 }
101 
isLayered() const102 bool ImageIndex::isLayered() const
103 {
104     switch (mType)
105     {
106         case TextureType::_2DArray:
107         case TextureType::_2DMultisampleArray:
108         case TextureType::CubeMap:
109         case TextureType::_3D:
110         case TextureType::CubeMapArray:
111             return mLayerIndex == kEntireLevel;
112         default:
113             return false;
114     }
115 }
116 
has3DLayer() const117 bool ImageIndex::has3DLayer() const
118 {
119     // It's quicker to check != CubeMap than calling usesTex3D, which checks multiple types. This
120     // ASSERT validates the check gives the same result.
121     ASSERT(!hasLayer() || ((mType != TextureType::CubeMap) == usesTex3D()));
122     return (hasLayer() && mType != TextureType::CubeMap);
123 }
124 
usesTex3D() const125 bool ImageIndex::usesTex3D() const
126 {
127     return mType == TextureType::_3D || mType == TextureType::_2DArray ||
128            mType == TextureType::_2DMultisampleArray || mType == TextureType::CubeMapArray;
129 }
130 
getTarget() const131 TextureTarget ImageIndex::getTarget() const
132 {
133     return TextureTypeToTarget(mType, mLayerIndex);
134 }
135 
getTargetOrFirstCubeFace() const136 gl::TextureTarget ImageIndex::getTargetOrFirstCubeFace() const
137 {
138     if (isEntireLevelCubeMap())
139     {
140         return gl::kCubeMapTextureTargetMin;
141     }
142     else
143     {
144         return getTarget();
145     }
146 }
147 
cubeMapFaceIndex() const148 GLint ImageIndex::cubeMapFaceIndex() const
149 {
150     ASSERT(mType == TextureType::CubeMap);
151     ASSERT(mLayerIndex == kEntireLevel || mLayerIndex < static_cast<GLint>(kCubeFaceCount));
152     return mLayerIndex;
153 }
154 
valid() const155 bool ImageIndex::valid() const
156 {
157     return mType != TextureType::InvalidEnum;
158 }
159 
isEntireLevelCubeMap() const160 bool ImageIndex::isEntireLevelCubeMap() const
161 {
162     return mType == TextureType::CubeMap && mLayerIndex == ImageIndex::kEntireLevel;
163 }
164 
Make2D(GLint levelIndex)165 ImageIndex ImageIndex::Make2D(GLint levelIndex)
166 {
167     return ImageIndex(TextureType::_2D, levelIndex, kEntireLevel, 1);
168 }
169 
MakeRectangle(GLint levelIndex)170 ImageIndex ImageIndex::MakeRectangle(GLint levelIndex)
171 {
172     return ImageIndex(TextureType::Rectangle, levelIndex, kEntireLevel, 1);
173 }
174 
MakeCubeMapFace(TextureTarget target,GLint levelIndex)175 ImageIndex ImageIndex::MakeCubeMapFace(TextureTarget target, GLint levelIndex)
176 {
177     ASSERT(IsCubeMapFaceTarget(target));
178     return ImageIndex(TextureType::CubeMap, levelIndex, TextureTargetToLayer(target), 1);
179 }
180 
Make2DArray(GLint levelIndex,GLint layerIndex)181 ImageIndex ImageIndex::Make2DArray(GLint levelIndex, GLint layerIndex)
182 {
183     return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, 1);
184 }
185 
Make2DArrayRange(GLint levelIndex,GLint layerIndex,GLint numLayers)186 ImageIndex ImageIndex::Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint numLayers)
187 {
188     return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, numLayers);
189 }
190 
Make3D(GLint levelIndex,GLint layerIndex)191 ImageIndex ImageIndex::Make3D(GLint levelIndex, GLint layerIndex)
192 {
193     return ImageIndex(TextureType::_3D, levelIndex, layerIndex, 1);
194 }
195 
MakeFromTarget(TextureTarget target,GLint levelIndex,GLint depth)196 ImageIndex ImageIndex::MakeFromTarget(TextureTarget target, GLint levelIndex, GLint depth)
197 {
198     return ImageIndex(TextureTargetToType(target), levelIndex, TextureTargetToLayer(target),
199                       IsArrayTarget(target) ? depth : 1);
200 }
201 
MakeFromType(TextureType type,GLint levelIndex,GLint layerIndex,GLint layerCount)202 ImageIndex ImageIndex::MakeFromType(TextureType type,
203                                     GLint levelIndex,
204                                     GLint layerIndex,
205                                     GLint layerCount)
206 {
207     GLint overrideLayerCount =
208         (type == TextureType::CubeMap && layerIndex == kEntireLevel ? kCubeFaceCount : layerCount);
209     return ImageIndex(type, levelIndex, layerIndex, overrideLayerCount);
210 }
211 
Make2DMultisample()212 ImageIndex ImageIndex::Make2DMultisample()
213 {
214     return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1);
215 }
216 
Make2DMultisampleArray(GLint layerIndex)217 ImageIndex ImageIndex::Make2DMultisampleArray(GLint layerIndex)
218 {
219     return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, 1);
220 }
221 
Make2DMultisampleArrayRange(GLint layerIndex,GLint numLayers)222 ImageIndex ImageIndex::Make2DMultisampleArrayRange(GLint layerIndex, GLint numLayers)
223 {
224     return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, numLayers);
225 }
226 
operator <(const ImageIndex & b) const227 bool ImageIndex::operator<(const ImageIndex &b) const
228 {
229     return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) <
230            std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
231 }
232 
operator ==(const ImageIndex & b) const233 bool ImageIndex::operator==(const ImageIndex &b) const
234 {
235     return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) ==
236            std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
237 }
238 
operator !=(const ImageIndex & b) const239 bool ImageIndex::operator!=(const ImageIndex &b) const
240 {
241     return !(*this == b);
242 }
243 
ImageIndex(TextureType type,GLint levelIndex,GLint layerIndex,GLint layerCount)244 ImageIndex::ImageIndex(TextureType type, GLint levelIndex, GLint layerIndex, GLint layerCount)
245     : mType(type), mLevelIndex(levelIndex), mLayerIndex(layerIndex), mLayerCount(layerCount)
246 {}
247 
getLayerIterator(GLint layerCount) const248 ImageIndexIterator ImageIndex::getLayerIterator(GLint layerCount) const
249 {
250     ASSERT(mType != TextureType::_2D && !hasLayer());
251     return ImageIndexIterator::MakeGeneric(mType, mLevelIndex, mLevelIndex + 1, 0, layerCount);
252 }
253 
254 ImageIndexIterator::ImageIndexIterator(const ImageIndexIterator &other) = default;
255 
Make2D(GLint minMip,GLint maxMip)256 ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
257 {
258     return ImageIndexIterator(TextureType::_2D, Range<GLint>(minMip, maxMip),
259                               Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
260                               nullptr);
261 }
262 
MakeRectangle(GLint minMip,GLint maxMip)263 ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
264 {
265     return ImageIndexIterator(TextureType::Rectangle, Range<GLint>(minMip, maxMip),
266                               Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
267                               nullptr);
268 }
269 
MakeCube(GLint minMip,GLint maxMip)270 ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
271 {
272     return ImageIndexIterator(TextureType::CubeMap, Range<GLint>(minMip, maxMip),
273                               Range<GLint>(0, 6), nullptr);
274 }
275 
Make3D(GLint minMip,GLint maxMip,GLint minLayer,GLint maxLayer)276 ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip,
277                                               GLint maxMip,
278                                               GLint minLayer,
279                                               GLint maxLayer)
280 {
281     return ImageIndexIterator(TextureType::_3D, Range<GLint>(minMip, maxMip),
282                               Range<GLint>(minLayer, maxLayer), nullptr);
283 }
284 
Make2DArray(GLint minMip,GLint maxMip,const GLsizei * layerCounts)285 ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip,
286                                                    GLint maxMip,
287                                                    const GLsizei *layerCounts)
288 {
289     return ImageIndexIterator(TextureType::_2DArray, Range<GLint>(minMip, maxMip),
290                               Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
291                               layerCounts);
292 }
293 
Make2DMultisample()294 ImageIndexIterator ImageIndexIterator::Make2DMultisample()
295 {
296     return ImageIndexIterator(TextureType::_2DMultisample, Range<GLint>(0, 1),
297                               Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
298                               nullptr);
299 }
300 
Make2DMultisampleArray(const GLsizei * layerCounts)301 ImageIndexIterator ImageIndexIterator::Make2DMultisampleArray(const GLsizei *layerCounts)
302 {
303     return ImageIndexIterator(TextureType::_2DMultisampleArray, Range<GLint>(0, 1),
304                               Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
305                               layerCounts);
306 }
307 
MakeGeneric(TextureType type,GLint minMip,GLint maxMip,GLint minLayer,GLint maxLayer)308 ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type,
309                                                    GLint minMip,
310                                                    GLint maxMip,
311                                                    GLint minLayer,
312                                                    GLint maxLayer)
313 {
314     if (type == TextureType::CubeMap)
315     {
316         return MakeCube(minMip, maxMip);
317     }
318 
319     return ImageIndexIterator(type, Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer),
320                               nullptr);
321 }
322 
ImageIndexIterator(TextureType type,const Range<GLint> & mipRange,const Range<GLint> & layerRange,const GLsizei * layerCounts)323 ImageIndexIterator::ImageIndexIterator(TextureType type,
324                                        const Range<GLint> &mipRange,
325                                        const Range<GLint> &layerRange,
326                                        const GLsizei *layerCounts)
327     : mMipRange(mipRange),
328       mLayerRange(layerRange),
329       mLayerCounts(layerCounts),
330       mCurrentIndex(type, mipRange.low(), layerRange.low(), 1)
331 {}
332 
maxLayer() const333 GLint ImageIndexIterator::maxLayer() const
334 {
335     if (mLayerCounts)
336     {
337         ASSERT(mCurrentIndex.hasLayer());
338         return (mCurrentIndex.getLevelIndex() < mMipRange.high())
339                    ? mLayerCounts[mCurrentIndex.getLevelIndex()]
340                    : 0;
341     }
342     return mLayerRange.high();
343 }
344 
next()345 ImageIndex ImageIndexIterator::next()
346 {
347     ASSERT(hasNext());
348 
349     // Make a copy of the current index to return
350     ImageIndex previousIndex = mCurrentIndex;
351 
352     // Iterate layers in the inner loop for now. We can add switchable
353     // layer or mip iteration if we need it.
354 
355     if (mCurrentIndex.hasLayer() && mCurrentIndex.getLayerIndex() < maxLayer() - 1)
356     {
357         mCurrentIndex.mLayerIndex++;
358     }
359     else if (mCurrentIndex.mLevelIndex < mMipRange.high() - 1)
360     {
361         mCurrentIndex.mLayerIndex = mLayerRange.low();
362         mCurrentIndex.mLevelIndex++;
363     }
364     else
365     {
366         mCurrentIndex = ImageIndex();
367     }
368 
369     return previousIndex;
370 }
371 
current() const372 ImageIndex ImageIndexIterator::current() const
373 {
374     return mCurrentIndex;
375 }
376 
hasNext() const377 bool ImageIndexIterator::hasNext() const
378 {
379     return mCurrentIndex.valid();
380 }
381 
382 }  // namespace gl
383