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