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::CompressedTexture::DecompressionParams& decompressionParams) 130 : m_context (context) 131 , m_isCompressed (true) 132 , m_format (getGLFormat(levels[0].getFormat())) 133 , m_refTexture (levels[0].getUncompressedFormat(), 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 throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__); 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::CompressedTexture::DecompressionParams& 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::CompressedTexture::DecompressionParams& decompressionParams) 289 : m_context (context) 290 , m_isCompressed (true) 291 , m_format (getGLFormat(levels[0].getFormat())) 292 , m_refTexture (levels[0].getUncompressedFormat(), 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 static deUint32 cubeFaceToGLFace (tcu::CubeFace face) 347 { 348 switch (face) 349 { 350 case tcu::CUBEFACE_NEGATIVE_X: return GL_TEXTURE_CUBE_MAP_NEGATIVE_X; 351 case tcu::CUBEFACE_POSITIVE_X: return GL_TEXTURE_CUBE_MAP_POSITIVE_X; 352 case tcu::CUBEFACE_NEGATIVE_Y: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; 353 case tcu::CUBEFACE_POSITIVE_Y: return GL_TEXTURE_CUBE_MAP_POSITIVE_Y; 354 case tcu::CUBEFACE_NEGATIVE_Z: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; 355 case tcu::CUBEFACE_POSITIVE_Z: return GL_TEXTURE_CUBE_MAP_POSITIVE_Z; 356 default: 357 DE_ASSERT(DE_FALSE); 358 return GL_NONE; 359 } 360 } 361 362 void TextureCube::upload (void) 363 { 364 const glw::Functions& gl = m_context.getFunctions(); 365 366 DE_ASSERT(!m_isCompressed); 367 368 TCU_CHECK(m_glTexture); 369 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture); 370 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 371 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 372 373 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 374 375 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 376 { 377 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 378 { 379 if (m_refTexture.isLevelEmpty((tcu::CubeFace)face, levelNdx)) 380 continue; // Don't upload. 381 382 tcu::ConstPixelBufferAccess access = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face); 383 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 384 gl.texImage2D(cubeFaceToGLFace((tcu::CubeFace)face), levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 385 } 386 } 387 388 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 389 } 390 391 void TextureCube::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::CompressedTexture::DecompressionParams& decompressionParams) 392 { 393 const glw::Functions& gl = m_context.getFunctions(); 394 deUint32 compressedFormat = getGLFormat(levels[0].getFormat()); 395 396 TCU_CHECK(m_glTexture); 397 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture); 398 399 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 400 { 401 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 402 { 403 const tcu::CompressedTexture& level = levels[levelNdx*tcu::CUBEFACE_LAST + face]; 404 405 // Decompress to reference texture. 406 m_refTexture.allocLevel((tcu::CubeFace)face, levelNdx); 407 tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face); 408 TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && 409 level.getHeight() == refLevelAccess.getHeight()); 410 level.decompress(refLevelAccess, decompressionParams); 411 412 // Upload to GL texture in compressed form. 413 gl.compressedTexImage2D(cubeFaceToGLFace((tcu::CubeFace)face), levelNdx, compressedFormat, 414 level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData()); 415 } 416 } 417 418 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 419 } 420 421 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* filenames) 422 { 423 DE_ASSERT(numLevels > 0); 424 425 std::string ext = de::FilePath(filenames[0]).getFileExtension(); 426 427 // \todo [2011-11-21 pyry] Support PNG images. 428 if (ext == "pkm") 429 { 430 // Compressed texture. 431 int numImages = numLevels*tcu::CUBEFACE_LAST; 432 vector<tcu::CompressedTexture> levels (numImages); 433 434 for (int ndx = 0; ndx < numImages; ndx++) 435 tcu::ImageIO::loadPKM(levels[ndx], archive, filenames[ndx]); 436 437 return new TextureCube(context, contextInfo, numLevels, &levels[0]); 438 } 439 else 440 TCU_FAIL("Unsupported file format"); 441 } 442 443 TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames) 444 { 445 DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6); 446 TCU_CHECK(numLevels*tcu::CUBEFACE_LAST == (int)filenames.size()); 447 448 std::vector<const char*> charPtrs(filenames.size()); 449 for (int ndx = 0; ndx < (int)filenames.size(); ndx++) 450 charPtrs[ndx] = filenames[ndx].c_str(); 451 452 return TextureCube::create(context, contextInfo, archive, numLevels, &charPtrs[0]); 453 } 454 455 // Texture1DArray 456 457 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int numLevels) 458 : m_context (context) 459 , m_format (format) 460 , m_refTexture (mapGLTransferFormat(format, dataType), width, numLevels) 461 , m_glTexture (0) 462 { 463 const glw::Functions& gl = m_context.getFunctions(); 464 gl.genTextures(1, &m_glTexture); 465 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 466 } 467 468 Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 sizedFormat, int width, int numLevels) 469 : m_context (context) 470 , m_format (sizedFormat) 471 , m_refTexture (mapGLInternalFormat(sizedFormat), width, numLevels) 472 , m_glTexture (0) 473 { 474 const glw::Functions& gl = m_context.getFunctions(); 475 gl.genTextures(1, &m_glTexture); 476 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 477 } 478 479 Texture1DArray::~Texture1DArray (void) 480 { 481 if (m_glTexture) 482 m_context.getFunctions().deleteTextures(1, &m_glTexture); 483 } 484 485 void Texture1DArray::upload (void) 486 { 487 const glw::Functions& gl = m_context.getFunctions(); 488 489 TCU_CHECK(m_glTexture); 490 gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_glTexture); 491 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 492 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 493 494 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 495 496 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 497 { 498 if (m_refTexture.isLevelEmpty(levelNdx)) 499 continue; // Don't upload. 500 501 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 502 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 503 gl.texImage2D(GL_TEXTURE_1D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 504 } 505 506 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 507 } 508 509 // Texture2DArray 510 511 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int numLevels) 512 : m_context (context) 513 , m_format (format) 514 , m_refTexture (mapGLTransferFormat(format, dataType), width, height, numLevels) 515 , m_glTexture (0) 516 { 517 // \todo [2013-04-08 pyry] Check support here. 518 const glw::Functions& gl = m_context.getFunctions(); 519 gl.genTextures(1, &m_glTexture); 520 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 521 } 522 523 Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 sizedFormat, int width, int height, int numLevels) 524 : m_context (context) 525 , m_format (sizedFormat) 526 , m_refTexture (mapGLInternalFormat(sizedFormat), width, height, numLevels) 527 , m_glTexture (0) 528 { 529 // \todo [2013-04-08 pyry] Check support here. 530 const glw::Functions& gl = m_context.getFunctions(); 531 gl.genTextures(1, &m_glTexture); 532 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 533 } 534 535 Texture2DArray::~Texture2DArray (void) 536 { 537 if (m_glTexture) 538 m_context.getFunctions().deleteTextures(1, &m_glTexture); 539 } 540 541 void Texture2DArray::upload (void) 542 { 543 const glw::Functions& gl = m_context.getFunctions(); 544 545 if (!gl.texImage3D) 546 throw tcu::NotSupportedError("glTexImage3D() is not supported"); 547 548 TCU_CHECK(m_glTexture); 549 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture); 550 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 551 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 552 553 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 554 555 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 556 { 557 if (m_refTexture.isLevelEmpty(levelNdx)) 558 continue; // Don't upload. 559 560 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 561 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 562 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight()); 563 gl.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 564 } 565 566 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 567 } 568 569 // Texture3D 570 571 Texture3D::Texture3D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int depth) 572 : m_context (context) 573 , m_format (format) 574 , m_refTexture (mapGLTransferFormat(format, dataType), width, height, depth) 575 , m_glTexture (0) 576 { 577 // \todo [2013-04-08 pyry] Check support here. 578 const glw::Functions& gl = m_context.getFunctions(); 579 gl.genTextures(1, &m_glTexture); 580 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 581 } 582 583 Texture3D::Texture3D (const RenderContext& context, deUint32 sizedFormat, int width, int height, int depth) 584 : m_context (context) 585 , m_format (sizedFormat) 586 , m_refTexture (mapGLInternalFormat(sizedFormat), width, height, depth) 587 , m_glTexture (0) 588 { 589 // \todo [2013-04-08 pyry] Check support here. 590 const glw::Functions& gl = m_context.getFunctions(); 591 gl.genTextures(1, &m_glTexture); 592 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 593 } 594 595 Texture3D::~Texture3D (void) 596 { 597 if (m_glTexture) 598 m_context.getFunctions().deleteTextures(1, &m_glTexture); 599 } 600 601 void Texture3D::upload (void) 602 { 603 const glw::Functions& gl = m_context.getFunctions(); 604 605 if (!gl.texImage3D) 606 throw tcu::NotSupportedError("glTexImage3D() is not supported"); 607 608 TCU_CHECK(m_glTexture); 609 gl.bindTexture(GL_TEXTURE_3D, m_glTexture); 610 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 611 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 612 613 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 614 615 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 616 { 617 if (m_refTexture.isLevelEmpty(levelNdx)) 618 continue; // Don't upload. 619 620 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 621 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 622 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight()); 623 gl.texImage3D(GL_TEXTURE_3D, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 624 } 625 626 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 627 } 628 629 // TextureCubeArray 630 631 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 format, deUint32 dataType, int size, int numLayers) 632 : m_context (context) 633 , m_format (format) 634 , m_refTexture (mapGLTransferFormat(format, dataType), size, numLayers) 635 , m_glTexture (0) 636 { 637 // \todo [2013-04-08 pyry] Check support here. 638 const glw::Functions& gl = m_context.getFunctions(); 639 gl.genTextures(1, &m_glTexture); 640 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 641 } 642 643 TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 sizedFormat, int size, int numLayers) 644 : m_context (context) 645 , m_format (sizedFormat) 646 , m_refTexture (mapGLInternalFormat(sizedFormat), size, numLayers) 647 , m_glTexture (0) 648 { 649 // \todo [2013-04-08 pyry] Check support here. 650 const glw::Functions& gl = m_context.getFunctions(); 651 gl.genTextures(1, &m_glTexture); 652 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 653 } 654 655 TextureCubeArray::~TextureCubeArray (void) 656 { 657 if (m_glTexture) 658 m_context.getFunctions().deleteTextures(1, &m_glTexture); 659 } 660 661 void TextureCubeArray::upload (void) 662 { 663 const glw::Functions& gl = m_context.getFunctions(); 664 665 if (!gl.texImage3D) 666 throw tcu::NotSupportedError("glTexImage3D() is not supported"); 667 668 TCU_CHECK(m_glTexture); 669 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_glTexture); 670 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 671 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 672 673 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 674 675 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 676 { 677 if (m_refTexture.isLevelEmpty(levelNdx)) 678 continue; // Don't upload. 679 680 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 681 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 682 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight()); 683 gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 684 } 685 686 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 687 } 688 689 // TextureBuffer 690 691 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize) 692 : m_context (context) 693 , m_format (0) 694 , m_offset (0) 695 , m_size (0) 696 , m_glTexture (0) 697 , m_glBuffer (0) 698 { 699 init(internalFormat, bufferSize, 0, 0, DE_NULL); 700 } 701 702 TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data) 703 : m_context (context) 704 , m_format (0) 705 , m_offset (0) 706 , m_size (0) 707 , m_glTexture (0) 708 , m_glBuffer (0) 709 { 710 init(internalFormat, bufferSize, offset, size, data); 711 } 712 713 void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data) 714 { 715 const glw::Functions& gl = m_context.getFunctions(); 716 de::UniquePtr<ContextInfo> info (ContextInfo::create(m_context)); 717 718 if (offset != 0 || size != 0) 719 { 720 if (!(contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) && info->isExtensionSupported("GL_ARB_texture_buffer_range")) 721 && !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) 722 && info->isExtensionSupported("GL_EXT_texture_buffer"))) 723 { 724 throw tcu::NotSupportedError("Ranged texture buffers not supported", "", __FILE__, __LINE__); 725 } 726 } 727 else 728 { 729 if (!contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) 730 && !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) 731 && info->isExtensionSupported("GL_EXT_texture_buffer"))) 732 { 733 throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__); 734 } 735 } 736 737 m_refBuffer.resize(bufferSize, 0); 738 739 if (data) 740 deMemcpy(&m_refBuffer[0], data, (int)bufferSize); 741 742 m_format = internalFormat; 743 m_offset = offset; 744 m_size = size; 745 746 DE_ASSERT(size != 0 || offset == 0); 747 748 { 749 const tcu::TextureFormat format = mapGLInternalFormat(internalFormat); 750 deInt32 maxTextureSize = 0; 751 752 gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize); 753 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE) failed"); 754 755 m_refTexture = tcu::PixelBufferAccess(format, de::min<int>((int)maxTextureSize, (int)((m_size != 0 ? m_size : bufferSize) / format.getPixelSize())), 1, 1, &(m_refBuffer[m_offset])); 756 } 757 758 { 759 gl.genTextures(1, &m_glTexture); 760 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 761 762 gl.genBuffers(1, &m_glBuffer); 763 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 764 765 gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer); 766 gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), &(m_refBuffer[0]), GL_STATIC_DRAW); 767 gl.bindBuffer(GL_TEXTURE_BUFFER, 0); 768 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffer"); 769 770 gl.bindTexture(GL_TEXTURE_BUFFER, m_glTexture); 771 772 if (offset != 0 || size != 0) 773 gl.texBufferRange(GL_TEXTURE_BUFFER, m_format, m_glBuffer, (glw::GLintptr)m_offset, (glw::GLsizeiptr)m_size); 774 else 775 gl.texBuffer(GL_TEXTURE_BUFFER, m_format, m_glBuffer); 776 777 gl.bindTexture(GL_TEXTURE_BUFFER, 0); 778 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffer to texture"); 779 } 780 } 781 782 TextureBuffer::~TextureBuffer (void) 783 { 784 if (m_glTexture) 785 m_context.getFunctions().deleteTextures(1, &m_glTexture); 786 787 if (m_glBuffer) 788 m_context.getFunctions().deleteBuffers(1, &m_glBuffer); 789 } 790 791 void TextureBuffer::upload (void) 792 { 793 const glw::Functions& gl = m_context.getFunctions(); 794 795 gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer); 796 gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), &(m_refBuffer[0]), GL_STATIC_DRAW); 797 gl.bindBuffer(GL_TEXTURE_BUFFER, 0); 798 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer"); 799 } 800 801 void TextureBuffer::bufferData (const deUint8* data, size_t size) 802 { 803 const glw::Functions& gl = m_context.getFunctions(); 804 805 m_refBuffer = vector<deUint8>(data, data+size); 806 807 { 808 const tcu::TextureFormat format = mapGLInternalFormat(m_format); 809 deInt32 maxTextureSize = 0; 810 811 gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize); 812 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE) failed"); 813 814 m_refTexture = tcu::PixelBufferAccess(format, de::min<int>((int)maxTextureSize, (int)((m_size != 0 ? m_size : m_refBuffer.size()) / format.getPixelSize())), 1, 1, &(m_refBuffer[m_offset])); 815 } 816 } 817 818 } // glu 819