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