1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES Utilities 3 * ------------------------------------------------ 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Texture classes. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "gluTexture.hpp" 25 #include "gluTextureUtil.hpp" 26 #include "deFilePath.hpp" 27 #include "tcuImageIO.hpp" 28 #include "tcuSurface.hpp" 29 #include "tcuTextureUtil.hpp" 30 31 #include "glwFunctions.hpp" 32 #include "glwEnums.hpp" 33 34 #include "deUniquePtr.hpp" 35 36 using std::vector; 37 38 namespace glu 39 { 40 41 static inline int computePixelStore (const tcu::TextureFormat& format) 42 { 43 int pixelSize = format.getPixelSize(); 44 if (deIsPowerOfTwo32(pixelSize)) 45 return de::min(pixelSize, 8); 46 else 47 return 1; 48 } 49 50 // Texture1D 51 52 Texture1D::Texture1D (const RenderContext& context, deUint32 format, deUint32 dataType, int width) 53 : m_context (context) 54 , m_format (format) 55 , m_refTexture (mapGLTransferFormat(format, dataType), width) 56 , m_glTexture (0) 57 { 58 const glw::Functions& gl = context.getFunctions(); 59 gl.genTextures(1, &m_glTexture); 60 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 61 } 62 63 Texture1D::Texture1D (const RenderContext& context, deUint32 sizedFormat, int width) 64 : m_context (context) 65 , m_format (sizedFormat) 66 , m_refTexture (mapGLInternalFormat(sizedFormat), width) 67 , m_glTexture (0) 68 { 69 const glw::Functions& gl = context.getFunctions(); 70 gl.genTextures(1, &m_glTexture); 71 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 72 } 73 74 Texture1D::~Texture1D (void) 75 { 76 if (m_glTexture) 77 m_context.getFunctions().deleteTextures(1, &m_glTexture); 78 } 79 80 void Texture1D::upload (void) 81 { 82 const glw::Functions& gl = m_context.getFunctions(); 83 84 TCU_CHECK(m_glTexture); 85 gl.bindTexture(GL_TEXTURE_1D, m_glTexture); 86 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 87 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 88 89 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 90 91 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 92 { 93 if (m_refTexture.isLevelEmpty(levelNdx)) 94 continue; // Don't upload. 95 96 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 97 gl.texImage1D(GL_TEXTURE_1D, levelNdx, m_format, access.getWidth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 98 } 99 100 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 101 } 102 103 // Texture2D 104 105 Texture2D::Texture2D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height) 106 : m_context (context) 107 , m_isCompressed (false) 108 , m_format (format) 109 , m_refTexture (mapGLTransferFormat(format, dataType), width, height) 110 , m_glTexture (0) 111 { 112 const glw::Functions& gl = context.getFunctions(); 113 gl.genTextures(1, &m_glTexture); 114 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 115 } 116 117 Texture2D::Texture2D (const RenderContext& context, deUint32 sizedFormat, int width, int height) 118 : m_context (context) 119 , m_isCompressed (false) 120 , m_format (sizedFormat) 121 , m_refTexture (mapGLInternalFormat(sizedFormat), width, height) 122 , m_glTexture (0) 123 { 124 const glw::Functions& gl = context.getFunctions(); 125 gl.genTextures(1, &m_glTexture); 126 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 127 } 128 129 Texture2D::Texture2D (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 130 : m_context (context) 131 , m_isCompressed (true) 132 , m_format (getGLFormat(levels[0].getFormat())) 133 , m_refTexture (getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight()) 134 , m_glTexture (0) 135 { 136 const glw::Functions& gl = context.getFunctions(); 137 138 if (!contextInfo.isCompressedTextureFormatSupported(m_format)) 139 TCU_THROW(NotSupportedError, "Compressed texture format not supported"); 140 141 gl.genTextures(1, &m_glTexture); 142 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 143 144 try 145 { 146 loadCompressed(numLevels, levels, decompressionParams); 147 } 148 catch (const std::exception&) 149 { 150 gl.deleteTextures(1, &m_glTexture); 151 throw; 152 } 153 } 154 155 Texture2D::~Texture2D (void) 156 { 157 if (m_glTexture) 158 m_context.getFunctions().deleteTextures(1, &m_glTexture); 159 } 160 161 void Texture2D::upload (void) 162 { 163 const glw::Functions& gl = m_context.getFunctions(); 164 165 DE_ASSERT(!m_isCompressed); 166 167 TCU_CHECK(m_glTexture); 168 gl.bindTexture(GL_TEXTURE_2D, m_glTexture); 169 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 170 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 171 172 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 173 174 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 175 { 176 if (m_refTexture.isLevelEmpty(levelNdx)) 177 continue; // Don't upload. 178 179 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 180 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 181 gl.texImage2D(GL_TEXTURE_2D, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 182 } 183 184 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 185 } 186 187 void Texture2D::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 188 { 189 const glw::Functions& gl = m_context.getFunctions(); 190 deUint32 compressedFormat = getGLFormat(levels[0].getFormat()); 191 192 TCU_CHECK(m_glTexture); 193 gl.bindTexture(GL_TEXTURE_2D, m_glTexture); 194 195 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 196 { 197 const tcu::CompressedTexture& level = levels[levelNdx]; 198 199 // Decompress to reference texture. 200 m_refTexture.allocLevel(levelNdx); 201 tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx); 202 TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && 203 level.getHeight() == refLevelAccess.getHeight()); 204 level.decompress(refLevelAccess, decompressionParams); 205 206 // Upload to GL texture in compressed form. 207 gl.compressedTexImage2D(GL_TEXTURE_2D, levelNdx, compressedFormat, 208 level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData()); 209 } 210 211 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 212 } 213 214 Texture2D* Texture2D::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* levelFileNames) 215 { 216 DE_ASSERT(numLevels > 0); 217 218 std::string ext = de::FilePath(levelFileNames[0]).getFileExtension(); 219 220 if (ext == "png") 221 { 222 // Uncompressed texture. 223 224 tcu::TextureLevel level; 225 226 // Load level 0. 227 tcu::ImageIO::loadPNG(level, archive, levelFileNames[0]); 228 229 TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) || 230 level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8)); 231 232 bool isRGBA = level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8); 233 Texture2D* texture = new Texture2D(context, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, level.getWidth(), level.getHeight()); 234 235 try 236 { 237 // Fill level 0. 238 texture->getRefTexture().allocLevel(0); 239 tcu::copy(texture->getRefTexture().getLevel(0), level.getAccess()); 240 241 // Fill remaining levels. 242 for (int levelNdx = 1; levelNdx < numLevels; levelNdx++) 243 { 244 tcu::ImageIO::loadPNG(level, archive, levelFileNames[levelNdx]); 245 246 texture->getRefTexture().allocLevel(levelNdx); 247 tcu::copy(texture->getRefTexture().getLevel(levelNdx), level.getAccess()); 248 } 249 250 // Upload data. 251 texture->upload(); 252 } 253 catch (const std::exception&) 254 { 255 delete texture; 256 throw; 257 } 258 259 return texture; 260 } 261 else if (ext == "pkm") 262 { 263 // Compressed texture. 264 vector<tcu::CompressedTexture> levels(numLevels); 265 266 for (int ndx = 0; ndx < numLevels; ndx++) 267 tcu::ImageIO::loadPKM(levels[ndx], archive, levelFileNames[ndx]); 268 269 return new Texture2D(context, contextInfo, numLevels, &levels[0]); 270 } 271 else 272 TCU_FAIL("Unsupported file format"); 273 } 274 275 Texture2D* Texture2D::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames) 276 { 277 TCU_CHECK(numLevels == (int)filenames.size()); 278 279 std::vector<const char*> charPtrs(filenames.size()); 280 for (int ndx = 0; ndx < (int)filenames.size(); ndx++) 281 charPtrs[ndx] = filenames[ndx].c_str(); 282 283 return Texture2D::create(context, contextInfo, archive, numLevels, &charPtrs[0]); 284 } 285 286 // TextureCube 287 288 TextureCube::TextureCube (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 289 : m_context (context) 290 , m_isCompressed (true) 291 , m_format (getGLFormat(levels[0].getFormat())) 292 , m_refTexture (getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth()) 293 , m_glTexture (0) 294 { 295 const glw::Functions& gl = m_context.getFunctions(); 296 297 TCU_CHECK_INTERNAL(levels[0].getWidth() == levels[0].getHeight()); 298 299 if (!contextInfo.isCompressedTextureFormatSupported(m_format)) 300 throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__); 301 302 gl.genTextures(1, &m_glTexture); 303 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 304 305 try 306 { 307 loadCompressed(numLevels, levels, decompressionParams); 308 } 309 catch (const std::exception&) 310 { 311 gl.deleteTextures(1, &m_glTexture); 312 throw; 313 } 314 } 315 316 TextureCube::TextureCube (const RenderContext& context, deUint32 format, deUint32 dataType, int size) 317 : m_context (context) 318 , m_isCompressed (false) 319 , m_format (format) 320 , m_refTexture (mapGLTransferFormat(format, dataType), size) 321 , m_glTexture (0) 322 { 323 const glw::Functions& gl = m_context.getFunctions(); 324 gl.genTextures(1, &m_glTexture); 325 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 326 } 327 328 TextureCube::TextureCube (const RenderContext& context, deUint32 internalFormat, int size) 329 : m_context (context) 330 , m_isCompressed (false) 331 , m_format (internalFormat) 332 , m_refTexture (mapGLInternalFormat(internalFormat), size) 333 , m_glTexture (0) 334 { 335 const glw::Functions& gl = m_context.getFunctions(); 336 gl.genTextures(1, &m_glTexture); 337 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 338 } 339 340 TextureCube::~TextureCube (void) 341 { 342 if (m_glTexture) 343 m_context.getFunctions().deleteTextures(1, &m_glTexture); 344 } 345 346 void TextureCube::upload (void) 347 { 348 const glw::Functions& gl = m_context.getFunctions(); 349 350 DE_ASSERT(!m_isCompressed); 351 352 TCU_CHECK(m_glTexture); 353 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture); 354 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 355 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 356 357 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 358 359 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 360 { 361 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 362 { 363 if (m_refTexture.isLevelEmpty((tcu::CubeFace)face, levelNdx)) 364 continue; // Don't upload. 365 366 tcu::ConstPixelBufferAccess access = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face); 367 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 368 gl.texImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 369 } 370 } 371 372 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 373 } 374 375 void TextureCube::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 376 { 377 const glw::Functions& gl = m_context.getFunctions(); 378 deUint32 compressedFormat = getGLFormat(levels[0].getFormat()); 379 380 TCU_CHECK(m_glTexture); 381 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture); 382 383 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 384 { 385 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 386 { 387 const tcu::CompressedTexture& level = levels[levelNdx*tcu::CUBEFACE_LAST + face]; 388 389 // Decompress to reference texture. 390 m_refTexture.allocLevel((tcu::CubeFace)face, levelNdx); 391 tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face); 392 TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && 393 level.getHeight() == refLevelAccess.getHeight()); 394 level.decompress(refLevelAccess, decompressionParams); 395 396 // Upload to GL texture in compressed form. 397 gl.compressedTexImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, compressedFormat, 398 level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData()); 399 } 400 } 401 402 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 403 } 404 405 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* filenames) 406 { 407 DE_ASSERT(numLevels > 0); 408 409 std::string ext = de::FilePath(filenames[0]).getFileExtension(); 410 411 // \todo [2011-11-21 pyry] Support PNG images. 412 if (ext == "pkm") 413 { 414 // Compressed texture. 415 int numImages = numLevels*tcu::CUBEFACE_LAST; 416 vector<tcu::CompressedTexture> levels (numImages); 417 418 for (int ndx = 0; ndx < numImages; ndx++) 419 tcu::ImageIO::loadPKM(levels[ndx], archive, filenames[ndx]); 420 421 return new TextureCube(context, contextInfo, numLevels, &levels[0]); 422 } 423 else 424 TCU_FAIL("Unsupported file format"); 425 } 426 427 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames) 428 { 429 DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6); 430 TCU_CHECK(numLevels*tcu::CUBEFACE_LAST == (int)filenames.size()); 431 432 std::vector<const char*> charPtrs(filenames.size()); 433 for (int ndx = 0; ndx < (int)filenames.size(); ndx++) 434 charPtrs[ndx] = filenames[ndx].c_str(); 435 436 return TextureCube::create(context, contextInfo, archive, numLevels, &charPtrs[0]); 437 } 438 439 // Texture1DArray 440 441 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int numLevels) 442 : m_context (context) 443 , m_format (format) 444 , m_refTexture (mapGLTransferFormat(format, dataType), width, numLevels) 445 , m_glTexture (0) 446 { 447 const glw::Functions& gl = m_context.getFunctions(); 448 gl.genTextures(1, &m_glTexture); 449 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 450 } 451 452 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 sizedFormat, int width, int numLevels) 453 : m_context (context) 454 , m_format (sizedFormat) 455 , m_refTexture (mapGLInternalFormat(sizedFormat), width, numLevels) 456 , m_glTexture (0) 457 { 458 const glw::Functions& gl = m_context.getFunctions(); 459 gl.genTextures(1, &m_glTexture); 460 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 461 } 462 463 Texture1DArray::~Texture1DArray (void) 464 { 465 if (m_glTexture) 466 m_context.getFunctions().deleteTextures(1, &m_glTexture); 467 } 468 469 void Texture1DArray::upload (void) 470 { 471 const glw::Functions& gl = m_context.getFunctions(); 472 473 TCU_CHECK(m_glTexture); 474 gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_glTexture); 475 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 476 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 477 478 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 479 480 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 481 { 482 if (m_refTexture.isLevelEmpty(levelNdx)) 483 continue; // Don't upload. 484 485 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 486 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 487 gl.texImage2D(GL_TEXTURE_1D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 488 } 489 490 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 491 } 492 493 // Texture2DArray 494 495 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int numLevels) 496 : m_context (context) 497 , m_isCompressed (false) 498 , m_format (format) 499 , m_refTexture (mapGLTransferFormat(format, dataType), width, height, numLevels) 500 , m_glTexture (0) 501 { 502 // \todo [2013-04-08 pyry] Check support here. 503 const glw::Functions& gl = m_context.getFunctions(); 504 gl.genTextures(1, &m_glTexture); 505 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 506 } 507 508 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 sizedFormat, int width, int height, int numLevels) 509 : m_context (context) 510 , m_isCompressed (false) 511 , m_format (sizedFormat) 512 , m_refTexture (mapGLInternalFormat(sizedFormat), width, height, numLevels) 513 , m_glTexture (0) 514 { 515 // \todo [2013-04-08 pyry] Check support here. 516 const glw::Functions& gl = m_context.getFunctions(); 517 gl.genTextures(1, &m_glTexture); 518 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 519 } 520 521 Texture2DArray::Texture2DArray (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 522 : m_context (context) 523 , m_isCompressed (true) 524 , m_format (getGLFormat(levels[0].getFormat())) 525 , m_refTexture (getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(), levels[0].getDepth()) 526 , m_glTexture (0) 527 { 528 const glw::Functions& gl = context.getFunctions(); 529 530 if (!contextInfo.isCompressedTextureFormatSupported(m_format)) 531 throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__); 532 533 gl.genTextures(1, &m_glTexture); 534 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 535 536 try 537 { 538 loadCompressed(numLevels, levels, decompressionParams); 539 } 540 catch (const std::exception&) 541 { 542 gl.deleteTextures(1, &m_glTexture); 543 throw; 544 } 545 } 546 547 Texture2DArray::~Texture2DArray (void) 548 { 549 if (m_glTexture) 550 m_context.getFunctions().deleteTextures(1, &m_glTexture); 551 } 552 553 void Texture2DArray::upload (void) 554 { 555 const glw::Functions& gl = m_context.getFunctions(); 556 557 if (!gl.texImage3D) 558 throw tcu::NotSupportedError("glTexImage3D() is not supported"); 559 560 TCU_CHECK(m_glTexture); 561 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture); 562 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 563 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 564 565 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 566 567 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 568 { 569 if (m_refTexture.isLevelEmpty(levelNdx)) 570 continue; // Don't upload. 571 572 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 573 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 574 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight()); 575 gl.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 576 } 577 578 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 579 } 580 581 void Texture2DArray::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 582 { 583 const glw::Functions& gl = m_context.getFunctions(); 584 deUint32 compressedFormat = getGLFormat(levels[0].getFormat()); 585 586 TCU_CHECK(m_glTexture); 587 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture); 588 589 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 590 { 591 const tcu::CompressedTexture& level = levels[levelNdx]; 592 593 // Decompress to reference texture. 594 m_refTexture.allocLevel(levelNdx); 595 tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx); 596 TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && 597 level.getHeight() == refLevelAccess.getHeight() && 598 level.getDepth() == refLevelAccess.getDepth()); 599 level.decompress(refLevelAccess, decompressionParams); 600 601 // Upload to GL texture in compressed form. 602 gl.compressedTexImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, compressedFormat, 603 level.getWidth(), level.getHeight(), m_refTexture.getLevel(levelNdx).getDepth(), 0 /* border */, level.getDataSize(), level.getData()); 604 } 605 606 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 607 } 608 609 // Texture3D 610 611 Texture3D::Texture3D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int depth) 612 : m_context (context) 613 , m_isCompressed (false) 614 , m_format (format) 615 , m_refTexture (mapGLTransferFormat(format, dataType), width, height, depth) 616 , m_glTexture (0) 617 { 618 // \todo [2013-04-08 pyry] Check support here. 619 const glw::Functions& gl = m_context.getFunctions(); 620 gl.genTextures(1, &m_glTexture); 621 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 622 } 623 624 Texture3D::Texture3D (const RenderContext& context, deUint32 sizedFormat, int width, int height, int depth) 625 : m_context (context) 626 , m_isCompressed (false) 627 , m_format (sizedFormat) 628 , m_refTexture (mapGLInternalFormat(sizedFormat), width, height, depth) 629 , m_glTexture (0) 630 { 631 // \todo [2013-04-08 pyry] Check support here. 632 const glw::Functions& gl = m_context.getFunctions(); 633 gl.genTextures(1, &m_glTexture); 634 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 635 } 636 637 Texture3D::Texture3D (const RenderContext& context, 638 const ContextInfo& contextInfo, 639 int numLevels, 640 const tcu::CompressedTexture* levels, 641 const tcu::TexDecompressionParams& decompressionParams) 642 : m_context (context) 643 , m_isCompressed (true) 644 , m_format (getGLFormat(levels[0].getFormat())) 645 , m_refTexture (getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(), levels[0].getDepth()) 646 , m_glTexture (0) 647 { 648 const glw::Functions& gl = context.getFunctions(); 649 650 if (!contextInfo.isCompressedTextureFormatSupported(m_format)) 651 throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__); 652 653 gl.genTextures(1, &m_glTexture); 654 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 655 656 try 657 { 658 loadCompressed(numLevels, levels, decompressionParams); 659 } 660 catch (const std::exception&) 661 { 662 gl.deleteTextures(1, &m_glTexture); 663 throw; 664 } 665 } 666 667 Texture3D::~Texture3D (void) 668 { 669 if (m_glTexture) 670 m_context.getFunctions().deleteTextures(1, &m_glTexture); 671 } 672 673 void Texture3D::upload (void) 674 { 675 const glw::Functions& gl = m_context.getFunctions(); 676 677 DE_ASSERT(!m_isCompressed); 678 679 if (!gl.texImage3D) 680 throw tcu::NotSupportedError("glTexImage3D() is not supported"); 681 682 TCU_CHECK(m_glTexture); 683 gl.bindTexture(GL_TEXTURE_3D, m_glTexture); 684 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 685 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 686 687 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 688 689 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 690 { 691 if (m_refTexture.isLevelEmpty(levelNdx)) 692 continue; // Don't upload. 693 694 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 695 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 696 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight()); 697 gl.texImage3D(GL_TEXTURE_3D, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 698 } 699 700 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 701 } 702 703 void Texture3D::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 704 { 705 const glw::Functions& gl = m_context.getFunctions(); 706 deUint32 compressedFormat = getGLFormat(levels[0].getFormat()); 707 708 if (!gl.compressedTexImage3D) 709 throw tcu::NotSupportedError("glCompressedTexImage3D() is not supported"); 710 711 TCU_CHECK(m_glTexture); 712 gl.bindTexture(GL_TEXTURE_3D, m_glTexture); 713 714 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 715 { 716 const tcu::CompressedTexture& level = levels[levelNdx]; 717 718 // Decompress to reference texture. 719 m_refTexture.allocLevel(levelNdx); 720 tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx); 721 TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && 722 level.getHeight() == refLevelAccess.getHeight() && 723 level.getDepth() == refLevelAccess.getDepth()); 724 level.decompress(refLevelAccess, decompressionParams); 725 726 // Upload to GL texture in compressed form. 727 gl.compressedTexImage3D(GL_TEXTURE_3D, levelNdx, compressedFormat, 728 level.getWidth(), level.getHeight(), level.getDepth(), 0 /* border */, level.getDataSize(), level.getData()); 729 } 730 731 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 732 } 733 734 // TextureCubeArray 735 736 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 format, deUint32 dataType, int size, int numLayers) 737 : m_context (context) 738 , m_format (format) 739 , m_refTexture (mapGLTransferFormat(format, dataType), size, numLayers) 740 , m_glTexture (0) 741 { 742 // \todo [2013-04-08 pyry] Check support here. 743 const glw::Functions& gl = m_context.getFunctions(); 744 gl.genTextures(1, &m_glTexture); 745 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 746 } 747 748 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 sizedFormat, int size, int numLayers) 749 : m_context (context) 750 , m_format (sizedFormat) 751 , m_refTexture (mapGLInternalFormat(sizedFormat), size, numLayers) 752 , m_glTexture (0) 753 { 754 // \todo [2013-04-08 pyry] Check support here. 755 const glw::Functions& gl = m_context.getFunctions(); 756 gl.genTextures(1, &m_glTexture); 757 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 758 } 759 760 TextureCubeArray::~TextureCubeArray (void) 761 { 762 if (m_glTexture) 763 m_context.getFunctions().deleteTextures(1, &m_glTexture); 764 } 765 766 void TextureCubeArray::upload (void) 767 { 768 const glw::Functions& gl = m_context.getFunctions(); 769 770 if (!gl.texImage3D) 771 throw tcu::NotSupportedError("glTexImage3D() is not supported"); 772 773 TCU_CHECK(m_glTexture); 774 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_glTexture); 775 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 776 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 777 778 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 779 780 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 781 { 782 if (m_refTexture.isLevelEmpty(levelNdx)) 783 continue; // Don't upload. 784 785 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 786 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 787 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight()); 788 gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 789 } 790 791 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 792 } 793 794 // TextureBuffer 795 796 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize) 797 : m_context (context) 798 , m_format (0) 799 , m_offset (0) 800 , m_size (0) 801 , m_glTexture (0) 802 , m_glBuffer (0) 803 { 804 init(internalFormat, bufferSize, 0, 0, DE_NULL); 805 } 806 807 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data) 808 : m_context (context) 809 , m_format (0) 810 , m_offset (0) 811 , m_size (0) 812 , m_glTexture (0) 813 , m_glBuffer (0) 814 { 815 init(internalFormat, bufferSize, offset, size, data); 816 } 817 818 void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data) 819 { 820 const glw::Functions& gl = m_context.getFunctions(); 821 de::UniquePtr<ContextInfo> info (ContextInfo::create(m_context)); 822 823 if (offset != 0 || size != 0) 824 { 825 if (!(contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) && info->isExtensionSupported("GL_ARB_texture_buffer_range")) 826 && !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) 827 && info->isExtensionSupported("GL_EXT_texture_buffer"))) 828 { 829 throw tcu::NotSupportedError("Ranged texture buffers not supported", "", __FILE__, __LINE__); 830 } 831 } 832 else 833 { 834 if (!contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) 835 && !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) 836 && info->isExtensionSupported("GL_EXT_texture_buffer"))) 837 { 838 throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__); 839 } 840 } 841 842 m_refBuffer.setStorage(bufferSize); 843 if (data) 844 deMemcpy(m_refBuffer.getPtr(), data, (int)bufferSize); 845 846 m_format = internalFormat; 847 m_offset = offset; 848 m_size = size; 849 850 DE_ASSERT(size != 0 || offset == 0); 851 852 { 853 gl.genTextures(1, &m_glTexture); 854 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 855 856 gl.genBuffers(1, &m_glBuffer); 857 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 858 859 gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer); 860 gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), data, GL_STATIC_DRAW); 861 gl.bindBuffer(GL_TEXTURE_BUFFER, 0); 862 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffer"); 863 864 gl.bindTexture(GL_TEXTURE_BUFFER, m_glTexture); 865 866 if (offset != 0 || size != 0) 867 gl.texBufferRange(GL_TEXTURE_BUFFER, m_format, m_glBuffer, (glw::GLintptr)m_offset, (glw::GLsizeiptr)m_size); 868 else 869 gl.texBuffer(GL_TEXTURE_BUFFER, m_format, m_glBuffer); 870 871 gl.bindTexture(GL_TEXTURE_BUFFER, 0); 872 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffer to texture"); 873 } 874 } 875 876 TextureBuffer::~TextureBuffer (void) 877 { 878 if (m_glTexture) 879 m_context.getFunctions().deleteTextures(1, &m_glTexture); 880 881 if (m_glBuffer) 882 m_context.getFunctions().deleteBuffers(1, &m_glBuffer); 883 } 884 885 886 const tcu::PixelBufferAccess TextureBuffer::getFullRefTexture (void) 887 { 888 const tcu::TextureFormat format = mapGLInternalFormat(m_format); 889 const size_t bufferLengthBytes = (m_size != 0) ? (m_size) : (m_refBuffer.size()); 890 const int bufferLengthPixels = (int)bufferLengthBytes / format.getPixelSize(); 891 892 return tcu::PixelBufferAccess(format, 893 tcu::IVec3(bufferLengthPixels, 1, 1), 894 (deUint8*)m_refBuffer.getPtr() + m_offset); 895 } 896 897 const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture (void) const 898 { 899 return const_cast<TextureBuffer*>(this)->getFullRefTexture(); 900 } 901 902 void TextureBuffer::upload (void) 903 { 904 const glw::Functions& gl = m_context.getFunctions(); 905 906 gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer); 907 gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), m_refBuffer.getPtr(), GL_STATIC_DRAW); 908 gl.bindBuffer(GL_TEXTURE_BUFFER, 0); 909 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer"); 910 } 911 912 } // glu 913