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