ImageIndex.cpp (11938B)
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 { 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 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 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 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 91 bool ImageIndex::hasLayer() const 92 { 93 return mLayerIndex != kEntireLevel; 94 } 95 96 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 111 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 119 bool ImageIndex::usesTex3D() const 120 { 121 return mType == TextureType::_3D || mType == TextureType::_2DArray || 122 mType == TextureType::_2DMultisampleArray || mType == TextureType::CubeMapArray; 123 } 124 125 TextureTarget ImageIndex::getTarget() const 126 { 127 return TextureTypeToTarget(mType, mLayerIndex); 128 } 129 130 gl::TextureTarget ImageIndex::getTargetOrFirstCubeFace() const 131 { 132 if (isEntireLevelCubeMap()) 133 { 134 return gl::kCubeMapTextureTargetMin; 135 } 136 else 137 { 138 return getTarget(); 139 } 140 } 141 142 GLint ImageIndex::cubeMapFaceIndex() const 143 { 144 ASSERT(mType == TextureType::CubeMap); 145 ASSERT(mLayerIndex == kEntireLevel || mLayerIndex < static_cast<GLint>(kCubeFaceCount)); 146 return mLayerIndex; 147 } 148 149 bool ImageIndex::valid() const 150 { 151 return mType != TextureType::InvalidEnum; 152 } 153 154 bool ImageIndex::isEntireLevelCubeMap() const 155 { 156 return mType == TextureType::CubeMap && mLayerIndex == ImageIndex::kEntireLevel; 157 } 158 159 ImageIndex ImageIndex::Make2D(GLint levelIndex) 160 { 161 return ImageIndex(TextureType::_2D, levelIndex, kEntireLevel, 1); 162 } 163 164 ImageIndex ImageIndex::MakeRectangle(GLint levelIndex) 165 { 166 return ImageIndex(TextureType::Rectangle, levelIndex, kEntireLevel, 1); 167 } 168 169 ImageIndex ImageIndex::MakeCubeMapFace(TextureTarget target, GLint levelIndex) 170 { 171 ASSERT(IsCubeMapFaceTarget(target)); 172 return ImageIndex(TextureType::CubeMap, levelIndex, TextureTargetToLayer(target), 1); 173 } 174 175 ImageIndex ImageIndex::Make2DArray(GLint levelIndex, GLint layerIndex) 176 { 177 return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, 1); 178 } 179 180 ImageIndex ImageIndex::Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint numLayers) 181 { 182 return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, numLayers); 183 } 184 185 ImageIndex ImageIndex::Make3D(GLint levelIndex, GLint layerIndex) 186 { 187 return ImageIndex(TextureType::_3D, levelIndex, layerIndex, 1); 188 } 189 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 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 206 ImageIndex ImageIndex::MakeBuffer() 207 { 208 return ImageIndex(TextureType::Buffer, 0, kEntireLevel, 1); 209 } 210 211 ImageIndex ImageIndex::Make2DMultisample() 212 { 213 return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1); 214 } 215 216 ImageIndex ImageIndex::Make2DMultisampleArray(GLint layerIndex) 217 { 218 return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, 1); 219 } 220 221 ImageIndex ImageIndex::Make2DMultisampleArrayRange(GLint layerIndex, GLint numLayers) 222 { 223 return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, numLayers); 224 } 225 226 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 232 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 238 bool ImageIndex::operator!=(const ImageIndex &b) const 239 { 240 return !(*this == b); 241 } 242 243 ImageIndex::ImageIndex(TextureType type, GLint levelIndex, GLint layerIndex, GLint layerCount) 244 : mType(type), mLevelIndex(levelIndex), mLayerIndex(layerIndex), mLayerCount(layerCount) 245 {} 246 247 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 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 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 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 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 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 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 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 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 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 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 339 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 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 378 ImageIndex ImageIndexIterator::current() const 379 { 380 return mCurrentIndex; 381 } 382 383 bool ImageIndexIterator::hasNext() const 384 { 385 return mCurrentIndex.valid(); 386 } 387 388 } // namespace gl