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