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