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