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
Make2DMultisample()206 ImageIndex ImageIndex::Make2DMultisample()
207 {
208 return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1);
209 }
210
Make2DMultisampleArray(GLint layerIndex)211 ImageIndex ImageIndex::Make2DMultisampleArray(GLint layerIndex)
212 {
213 return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, 1);
214 }
215
Make2DMultisampleArrayRange(GLint layerIndex,GLint numLayers)216 ImageIndex ImageIndex::Make2DMultisampleArrayRange(GLint layerIndex, GLint numLayers)
217 {
218 return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, numLayers);
219 }
220
operator <(const ImageIndex & b) const221 bool ImageIndex::operator<(const ImageIndex &b) const
222 {
223 return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) <
224 std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
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 !(*this == b);
236 }
237
ImageIndex(TextureType type,GLint levelIndex,GLint layerIndex,GLint layerCount)238 ImageIndex::ImageIndex(TextureType type, GLint levelIndex, GLint layerIndex, GLint layerCount)
239 : mType(type), mLevelIndex(levelIndex), mLayerIndex(layerIndex), mLayerCount(layerCount)
240 {}
241
getLayerIterator(GLint layerCount) const242 ImageIndexIterator ImageIndex::getLayerIterator(GLint layerCount) const
243 {
244 ASSERT(mType != TextureType::_2D && !hasLayer());
245 return ImageIndexIterator::MakeGeneric(mType, mLevelIndex, mLevelIndex + 1, 0, layerCount);
246 }
247
248 ImageIndexIterator::ImageIndexIterator(const ImageIndexIterator &other) = default;
249
Make2D(GLint minMip,GLint maxMip)250 ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
251 {
252 return ImageIndexIterator(TextureType::_2D, Range<GLint>(minMip, maxMip),
253 Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
254 nullptr);
255 }
256
MakeRectangle(GLint minMip,GLint maxMip)257 ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
258 {
259 return ImageIndexIterator(TextureType::Rectangle, Range<GLint>(minMip, maxMip),
260 Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
261 nullptr);
262 }
263
MakeCube(GLint minMip,GLint maxMip)264 ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
265 {
266 return ImageIndexIterator(TextureType::CubeMap, Range<GLint>(minMip, maxMip),
267 Range<GLint>(0, 6), nullptr);
268 }
269
Make3D(GLint minMip,GLint maxMip,GLint minLayer,GLint maxLayer)270 ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip,
271 GLint maxMip,
272 GLint minLayer,
273 GLint maxLayer)
274 {
275 return ImageIndexIterator(TextureType::_3D, Range<GLint>(minMip, maxMip),
276 Range<GLint>(minLayer, maxLayer), nullptr);
277 }
278
Make2DArray(GLint minMip,GLint maxMip,const GLsizei * layerCounts)279 ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip,
280 GLint maxMip,
281 const GLsizei *layerCounts)
282 {
283 return ImageIndexIterator(TextureType::_2DArray, Range<GLint>(minMip, maxMip),
284 Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
285 layerCounts);
286 }
287
Make2DMultisample()288 ImageIndexIterator ImageIndexIterator::Make2DMultisample()
289 {
290 return ImageIndexIterator(TextureType::_2DMultisample, Range<GLint>(0, 1),
291 Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
292 nullptr);
293 }
294
Make2DMultisampleArray(const GLsizei * layerCounts)295 ImageIndexIterator ImageIndexIterator::Make2DMultisampleArray(const GLsizei *layerCounts)
296 {
297 return ImageIndexIterator(TextureType::_2DMultisampleArray, Range<GLint>(0, 1),
298 Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
299 layerCounts);
300 }
301
MakeGeneric(TextureType type,GLint minMip,GLint maxMip,GLint minLayer,GLint maxLayer)302 ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type,
303 GLint minMip,
304 GLint maxMip,
305 GLint minLayer,
306 GLint maxLayer)
307 {
308 if (type == TextureType::CubeMap)
309 {
310 return MakeCube(minMip, maxMip);
311 }
312
313 return ImageIndexIterator(type, Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer),
314 nullptr);
315 }
316
ImageIndexIterator(TextureType type,const Range<GLint> & mipRange,const Range<GLint> & layerRange,const GLsizei * layerCounts)317 ImageIndexIterator::ImageIndexIterator(TextureType type,
318 const Range<GLint> &mipRange,
319 const Range<GLint> &layerRange,
320 const GLsizei *layerCounts)
321 : mMipRange(mipRange),
322 mLayerRange(layerRange),
323 mLayerCounts(layerCounts),
324 mCurrentIndex(type, mipRange.low(), layerRange.low(), 1)
325 {}
326
maxLayer() const327 GLint ImageIndexIterator::maxLayer() const
328 {
329 if (mLayerCounts)
330 {
331 ASSERT(mCurrentIndex.hasLayer());
332 return (mCurrentIndex.getLevelIndex() < mMipRange.high())
333 ? mLayerCounts[mCurrentIndex.getLevelIndex()]
334 : 0;
335 }
336 return mLayerRange.high();
337 }
338
next()339 ImageIndex ImageIndexIterator::next()
340 {
341 ASSERT(hasNext());
342
343 // Make a copy of the current index to return
344 ImageIndex previousIndex = mCurrentIndex;
345
346 // Iterate layers in the inner loop for now. We can add switchable
347 // layer or mip iteration if we need it.
348
349 if (mCurrentIndex.hasLayer() && mCurrentIndex.getLayerIndex() < maxLayer() - 1)
350 {
351 mCurrentIndex.mLayerIndex++;
352 }
353 else if (mCurrentIndex.mLevelIndex < mMipRange.high() - 1)
354 {
355 mCurrentIndex.mLayerIndex = mLayerRange.low();
356 mCurrentIndex.mLevelIndex++;
357 }
358 else
359 {
360 mCurrentIndex = ImageIndex();
361 }
362
363 return previousIndex;
364 }
365
current() const366 ImageIndex ImageIndexIterator::current() const
367 {
368 return mCurrentIndex;
369 }
370
hasNext() const371 bool ImageIndexIterator::hasNext() const
372 {
373 return mCurrentIndex.valid();
374 }
375
376 } // namespace gl
377