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 36using std::vector; 37 38namespace glu 39{ 40 41static 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 52Texture1D::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 63Texture1D::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 74Texture1D::~Texture1D (void) 75{ 76 if (m_glTexture) 77 m_context.getFunctions().deleteTextures(1, &m_glTexture); 78} 79 80void 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 105Texture2D::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, isES2Context(context.getType())) 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 117Texture2D::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, isES2Context(context.getType())) 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 129Texture2D::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(), isES2Context(context.getType())) 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 155Texture2D::~Texture2D (void) 156{ 157 if (m_glTexture) 158 m_context.getFunctions().deleteTextures(1, &m_glTexture); 159} 160 161void 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 187void 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 214Texture2D* 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 275Texture2D* 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// ImmutableTexture2D 287 288ImmutableTexture2D::ImmutableTexture2D (const RenderContext& context, deUint32 sizedFormat, int width, int height) 289 : Texture2D(context, sizedFormat, width, height) 290{ 291} 292 293void ImmutableTexture2D::upload (void) 294{ 295 const glw::Functions& gl = m_context.getFunctions(); 296 297 DE_ASSERT(!m_isCompressed); 298 299 TCU_CHECK(m_glTexture); 300 gl.bindTexture(GL_TEXTURE_2D, m_glTexture); 301 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 302 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 303 304 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 305 306 gl.texStorage2D(GL_TEXTURE_2D, m_refTexture.getNumLevels(), m_format, m_refTexture.getWidth(), m_refTexture.getHeight()); 307 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 308 { 309 if (m_refTexture.isLevelEmpty(levelNdx)) 310 continue; // Don't upload. 311 312 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 313 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 314 gl.texSubImage2D(GL_TEXTURE_2D, levelNdx, 0, 0, access.getWidth(), access.getHeight(), transferFormat.format, transferFormat.dataType, access.getDataPtr()); 315 } 316 317 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 318} 319 320// TextureCube 321 322TextureCube::TextureCube (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 323 : m_context (context) 324 , m_isCompressed (true) 325 , m_format (getGLFormat(levels[0].getFormat())) 326 , m_refTexture (getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), isES2Context(context.getType())) 327 , m_glTexture (0) 328{ 329 const glw::Functions& gl = m_context.getFunctions(); 330 331 TCU_CHECK_INTERNAL(levels[0].getWidth() == levels[0].getHeight()); 332 333 if (!contextInfo.isCompressedTextureFormatSupported(m_format)) 334 throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__); 335 336 gl.genTextures(1, &m_glTexture); 337 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 338 339 try 340 { 341 loadCompressed(numLevels, levels, decompressionParams); 342 } 343 catch (const std::exception&) 344 { 345 gl.deleteTextures(1, &m_glTexture); 346 throw; 347 } 348} 349 350TextureCube::TextureCube (const RenderContext& context, deUint32 format, deUint32 dataType, int size) 351 : m_context (context) 352 , m_isCompressed (false) 353 , m_format (format) 354 , m_refTexture (mapGLTransferFormat(format, dataType), size, isES2Context(context.getType())) 355 , m_glTexture (0) 356{ 357 const glw::Functions& gl = m_context.getFunctions(); 358 gl.genTextures(1, &m_glTexture); 359 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 360} 361 362TextureCube::TextureCube (const RenderContext& context, deUint32 internalFormat, int size) 363 : m_context (context) 364 , m_isCompressed (false) 365 , m_format (internalFormat) 366 , m_refTexture (mapGLInternalFormat(internalFormat), size, isES2Context(context.getType())) 367 , m_glTexture (0) 368{ 369 const glw::Functions& gl = m_context.getFunctions(); 370 gl.genTextures(1, &m_glTexture); 371 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 372} 373 374TextureCube::~TextureCube (void) 375{ 376 if (m_glTexture) 377 m_context.getFunctions().deleteTextures(1, &m_glTexture); 378} 379 380void TextureCube::upload (void) 381{ 382 const glw::Functions& gl = m_context.getFunctions(); 383 384 DE_ASSERT(!m_isCompressed); 385 386 TCU_CHECK(m_glTexture); 387 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture); 388 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 389 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 390 391 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 392 393 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 394 { 395 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 396 { 397 if (m_refTexture.isLevelEmpty((tcu::CubeFace)face, levelNdx)) 398 continue; // Don't upload. 399 400 tcu::ConstPixelBufferAccess access = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face); 401 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 402 gl.texImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 403 } 404 } 405 406 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 407} 408 409void TextureCube::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 410{ 411 const glw::Functions& gl = m_context.getFunctions(); 412 deUint32 compressedFormat = getGLFormat(levels[0].getFormat()); 413 414 TCU_CHECK(m_glTexture); 415 gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture); 416 417 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 418 { 419 for (int face = 0; face < tcu::CUBEFACE_LAST; face++) 420 { 421 const tcu::CompressedTexture& level = levels[levelNdx*tcu::CUBEFACE_LAST + face]; 422 423 // Decompress to reference texture. 424 m_refTexture.allocLevel((tcu::CubeFace)face, levelNdx); 425 tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face); 426 TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && 427 level.getHeight() == refLevelAccess.getHeight()); 428 level.decompress(refLevelAccess, decompressionParams); 429 430 // Upload to GL texture in compressed form. 431 gl.compressedTexImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, compressedFormat, 432 level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData()); 433 } 434 } 435 436 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 437} 438 439TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const char* const* filenames) 440{ 441 DE_ASSERT(numLevels > 0); 442 443 std::string ext = de::FilePath(filenames[0]).getFileExtension(); 444 445 // \todo [2011-11-21 pyry] Support PNG images. 446 if (ext == "pkm") 447 { 448 // Compressed texture. 449 int numImages = numLevels*tcu::CUBEFACE_LAST; 450 vector<tcu::CompressedTexture> levels (numImages); 451 452 for (int ndx = 0; ndx < numImages; ndx++) 453 tcu::ImageIO::loadPKM(levels[ndx], archive, filenames[ndx]); 454 455 return new TextureCube(context, contextInfo, numLevels, &levels[0]); 456 } 457 else 458 TCU_FAIL("Unsupported file format"); 459} 460 461TextureCube* TextureCube::create (const RenderContext& context, const ContextInfo& contextInfo, const tcu::Archive& archive, int numLevels, const std::vector<std::string>& filenames) 462{ 463 DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6); 464 TCU_CHECK(numLevels*tcu::CUBEFACE_LAST == (int)filenames.size()); 465 466 std::vector<const char*> charPtrs(filenames.size()); 467 for (int ndx = 0; ndx < (int)filenames.size(); ndx++) 468 charPtrs[ndx] = filenames[ndx].c_str(); 469 470 return TextureCube::create(context, contextInfo, archive, numLevels, &charPtrs[0]); 471} 472 473// Texture1DArray 474 475Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int numLevels) 476 : m_context (context) 477 , m_format (format) 478 , m_refTexture (mapGLTransferFormat(format, dataType), width, numLevels) 479 , m_glTexture (0) 480{ 481 const glw::Functions& gl = m_context.getFunctions(); 482 gl.genTextures(1, &m_glTexture); 483 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 484} 485 486Texture1DArray::Texture1DArray (const RenderContext& context, deUint32 sizedFormat, int width, int numLevels) 487 : m_context (context) 488 , m_format (sizedFormat) 489 , m_refTexture (mapGLInternalFormat(sizedFormat), width, numLevels) 490 , m_glTexture (0) 491{ 492 const glw::Functions& gl = m_context.getFunctions(); 493 gl.genTextures(1, &m_glTexture); 494 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 495} 496 497Texture1DArray::~Texture1DArray (void) 498{ 499 if (m_glTexture) 500 m_context.getFunctions().deleteTextures(1, &m_glTexture); 501} 502 503void Texture1DArray::upload (void) 504{ 505 const glw::Functions& gl = m_context.getFunctions(); 506 507 TCU_CHECK(m_glTexture); 508 gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_glTexture); 509 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 510 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 511 512 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 513 514 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 515 { 516 if (m_refTexture.isLevelEmpty(levelNdx)) 517 continue; // Don't upload. 518 519 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 520 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 521 gl.texImage2D(GL_TEXTURE_1D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 522 } 523 524 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 525} 526 527// Texture2DArray 528 529Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int numLevels) 530 : m_context (context) 531 , m_isCompressed (false) 532 , m_format (format) 533 , m_refTexture (mapGLTransferFormat(format, dataType), width, height, numLevels) 534 , m_glTexture (0) 535{ 536 // \todo [2013-04-08 pyry] Check support here. 537 const glw::Functions& gl = m_context.getFunctions(); 538 gl.genTextures(1, &m_glTexture); 539 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 540} 541 542Texture2DArray::Texture2DArray (const RenderContext& context, deUint32 sizedFormat, int width, int height, int numLevels) 543 : m_context (context) 544 , m_isCompressed (false) 545 , m_format (sizedFormat) 546 , m_refTexture (mapGLInternalFormat(sizedFormat), width, height, numLevels) 547 , m_glTexture (0) 548{ 549 // \todo [2013-04-08 pyry] Check support here. 550 const glw::Functions& gl = m_context.getFunctions(); 551 gl.genTextures(1, &m_glTexture); 552 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 553} 554 555Texture2DArray::Texture2DArray (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 556 : m_context (context) 557 , m_isCompressed (true) 558 , m_format (getGLFormat(levels[0].getFormat())) 559 , m_refTexture (getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(), levels[0].getDepth()) 560 , m_glTexture (0) 561{ 562 const glw::Functions& gl = context.getFunctions(); 563 564 if (!contextInfo.isCompressedTextureFormatSupported(m_format)) 565 throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__); 566 567 gl.genTextures(1, &m_glTexture); 568 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 569 570 try 571 { 572 loadCompressed(numLevels, levels, decompressionParams); 573 } 574 catch (const std::exception&) 575 { 576 gl.deleteTextures(1, &m_glTexture); 577 throw; 578 } 579} 580 581Texture2DArray::~Texture2DArray (void) 582{ 583 if (m_glTexture) 584 m_context.getFunctions().deleteTextures(1, &m_glTexture); 585} 586 587void Texture2DArray::upload (void) 588{ 589 const glw::Functions& gl = m_context.getFunctions(); 590 591 if (!gl.texImage3D) 592 throw tcu::NotSupportedError("glTexImage3D() is not supported"); 593 594 TCU_CHECK(m_glTexture); 595 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture); 596 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 597 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 598 599 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 600 601 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 602 { 603 if (m_refTexture.isLevelEmpty(levelNdx)) 604 continue; // Don't upload. 605 606 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 607 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 608 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight()); 609 gl.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 610 } 611 612 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 613} 614 615void Texture2DArray::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 616{ 617 const glw::Functions& gl = m_context.getFunctions(); 618 deUint32 compressedFormat = getGLFormat(levels[0].getFormat()); 619 620 TCU_CHECK(m_glTexture); 621 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture); 622 623 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 624 { 625 const tcu::CompressedTexture& level = levels[levelNdx]; 626 627 // Decompress to reference texture. 628 m_refTexture.allocLevel(levelNdx); 629 tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx); 630 TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && 631 level.getHeight() == refLevelAccess.getHeight() && 632 level.getDepth() == refLevelAccess.getDepth()); 633 level.decompress(refLevelAccess, decompressionParams); 634 635 // Upload to GL texture in compressed form. 636 gl.compressedTexImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, compressedFormat, 637 level.getWidth(), level.getHeight(), m_refTexture.getLevel(levelNdx).getDepth(), 0 /* border */, level.getDataSize(), level.getData()); 638 } 639 640 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 641} 642 643// Texture3D 644 645Texture3D::Texture3D (const RenderContext& context, deUint32 format, deUint32 dataType, int width, int height, int depth) 646 : m_context (context) 647 , m_isCompressed (false) 648 , m_format (format) 649 , m_refTexture (mapGLTransferFormat(format, dataType), width, height, depth) 650 , m_glTexture (0) 651{ 652 // \todo [2013-04-08 pyry] Check support here. 653 const glw::Functions& gl = m_context.getFunctions(); 654 gl.genTextures(1, &m_glTexture); 655 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 656} 657 658Texture3D::Texture3D (const RenderContext& context, deUint32 sizedFormat, int width, int height, int depth) 659 : m_context (context) 660 , m_isCompressed (false) 661 , m_format (sizedFormat) 662 , m_refTexture (mapGLInternalFormat(sizedFormat), width, height, depth) 663 , m_glTexture (0) 664{ 665 // \todo [2013-04-08 pyry] Check support here. 666 const glw::Functions& gl = m_context.getFunctions(); 667 gl.genTextures(1, &m_glTexture); 668 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 669} 670 671Texture3D::Texture3D (const RenderContext& context, 672 const ContextInfo& contextInfo, 673 int numLevels, 674 const tcu::CompressedTexture* levels, 675 const tcu::TexDecompressionParams& decompressionParams) 676 : m_context (context) 677 , m_isCompressed (true) 678 , m_format (getGLFormat(levels[0].getFormat())) 679 , m_refTexture (getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(), levels[0].getDepth()) 680 , m_glTexture (0) 681{ 682 const glw::Functions& gl = context.getFunctions(); 683 684 if (!contextInfo.isCompressedTextureFormatSupported(m_format)) 685 throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__); 686 687 gl.genTextures(1, &m_glTexture); 688 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 689 690 try 691 { 692 loadCompressed(numLevels, levels, decompressionParams); 693 } 694 catch (const std::exception&) 695 { 696 gl.deleteTextures(1, &m_glTexture); 697 throw; 698 } 699} 700 701Texture3D::~Texture3D (void) 702{ 703 if (m_glTexture) 704 m_context.getFunctions().deleteTextures(1, &m_glTexture); 705} 706 707void Texture3D::upload (void) 708{ 709 const glw::Functions& gl = m_context.getFunctions(); 710 711 DE_ASSERT(!m_isCompressed); 712 713 if (!gl.texImage3D) 714 throw tcu::NotSupportedError("glTexImage3D() is not supported"); 715 716 TCU_CHECK(m_glTexture); 717 gl.bindTexture(GL_TEXTURE_3D, m_glTexture); 718 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 719 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 720 721 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 722 723 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 724 { 725 if (m_refTexture.isLevelEmpty(levelNdx)) 726 continue; // Don't upload. 727 728 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 729 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 730 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight()); 731 gl.texImage3D(GL_TEXTURE_3D, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 732 } 733 734 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 735} 736 737void Texture3D::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams) 738{ 739 const glw::Functions& gl = m_context.getFunctions(); 740 deUint32 compressedFormat = getGLFormat(levels[0].getFormat()); 741 742 if (!gl.compressedTexImage3D) 743 throw tcu::NotSupportedError("glCompressedTexImage3D() is not supported"); 744 745 TCU_CHECK(m_glTexture); 746 gl.bindTexture(GL_TEXTURE_3D, m_glTexture); 747 748 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++) 749 { 750 const tcu::CompressedTexture& level = levels[levelNdx]; 751 752 // Decompress to reference texture. 753 m_refTexture.allocLevel(levelNdx); 754 tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx); 755 TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && 756 level.getHeight() == refLevelAccess.getHeight() && 757 level.getDepth() == refLevelAccess.getDepth()); 758 level.decompress(refLevelAccess, decompressionParams); 759 760 // Upload to GL texture in compressed form. 761 gl.compressedTexImage3D(GL_TEXTURE_3D, levelNdx, compressedFormat, 762 level.getWidth(), level.getHeight(), level.getDepth(), 0 /* border */, level.getDataSize(), level.getData()); 763 } 764 765 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 766} 767 768// TextureCubeArray 769 770TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 format, deUint32 dataType, int size, int numLayers) 771 : m_context (context) 772 , m_format (format) 773 , m_refTexture (mapGLTransferFormat(format, dataType), size, numLayers) 774 , m_glTexture (0) 775{ 776 // \todo [2013-04-08 pyry] Check support here. 777 const glw::Functions& gl = m_context.getFunctions(); 778 gl.genTextures(1, &m_glTexture); 779 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 780} 781 782TextureCubeArray::TextureCubeArray (const RenderContext& context, deUint32 sizedFormat, int size, int numLayers) 783 : m_context (context) 784 , m_format (sizedFormat) 785 , m_refTexture (mapGLInternalFormat(sizedFormat), size, numLayers) 786 , m_glTexture (0) 787{ 788 // \todo [2013-04-08 pyry] Check support here. 789 const glw::Functions& gl = m_context.getFunctions(); 790 gl.genTextures(1, &m_glTexture); 791 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 792} 793 794TextureCubeArray::~TextureCubeArray (void) 795{ 796 if (m_glTexture) 797 m_context.getFunctions().deleteTextures(1, &m_glTexture); 798} 799 800void TextureCubeArray::upload (void) 801{ 802 const glw::Functions& gl = m_context.getFunctions(); 803 804 if (!gl.texImage3D) 805 throw tcu::NotSupportedError("glTexImage3D() is not supported"); 806 807 TCU_CHECK(m_glTexture); 808 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_glTexture); 809 gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat())); 810 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 811 812 TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat()); 813 814 for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++) 815 { 816 if (m_refTexture.isLevelEmpty(levelNdx)) 817 continue; // Don't upload. 818 819 tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx); 820 DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize()*access.getWidth()); 821 DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize()*access.getWidth()*access.getHeight()); 822 gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr()); 823 } 824 825 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed"); 826} 827 828// TextureBuffer 829 830TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize) 831 : m_context (context) 832 , m_format (0) 833 , m_offset (0) 834 , m_size (0) 835 , m_glTexture (0) 836 , m_glBuffer (0) 837{ 838 init(internalFormat, bufferSize, 0, 0, DE_NULL); 839} 840 841TextureBuffer::TextureBuffer (const RenderContext& context, deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data) 842 : m_context (context) 843 , m_format (0) 844 , m_offset (0) 845 , m_size (0) 846 , m_glTexture (0) 847 , m_glBuffer (0) 848{ 849 init(internalFormat, bufferSize, offset, size, data); 850} 851 852void TextureBuffer::init (deUint32 internalFormat, size_t bufferSize, size_t offset, size_t size, const void* data) 853{ 854 const glw::Functions& gl = m_context.getFunctions(); 855 de::UniquePtr<ContextInfo> info (ContextInfo::create(m_context)); 856 857 if (offset != 0 || size != 0) 858 { 859 if (!(contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) && info->isExtensionSupported("GL_ARB_texture_buffer_range")) 860 && !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) 861 && info->isExtensionSupported("GL_EXT_texture_buffer"))) 862 { 863 throw tcu::NotSupportedError("Ranged texture buffers not supported", "", __FILE__, __LINE__); 864 } 865 } 866 else 867 { 868 if (!contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) 869 && !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) 870 && info->isExtensionSupported("GL_EXT_texture_buffer"))) 871 { 872 throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__); 873 } 874 } 875 876 m_refBuffer.setStorage(bufferSize); 877 if (data) 878 deMemcpy(m_refBuffer.getPtr(), data, (int)bufferSize); 879 880 m_format = internalFormat; 881 m_offset = offset; 882 m_size = size; 883 884 DE_ASSERT(size != 0 || offset == 0); 885 886 { 887 gl.genTextures(1, &m_glTexture); 888 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed"); 889 890 gl.genBuffers(1, &m_glBuffer); 891 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed"); 892 893 gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer); 894 gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), data, GL_STATIC_DRAW); 895 gl.bindBuffer(GL_TEXTURE_BUFFER, 0); 896 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffer"); 897 898 gl.bindTexture(GL_TEXTURE_BUFFER, m_glTexture); 899 900 if (offset != 0 || size != 0) 901 gl.texBufferRange(GL_TEXTURE_BUFFER, m_format, m_glBuffer, (glw::GLintptr)m_offset, (glw::GLsizeiptr)m_size); 902 else 903 gl.texBuffer(GL_TEXTURE_BUFFER, m_format, m_glBuffer); 904 905 gl.bindTexture(GL_TEXTURE_BUFFER, 0); 906 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffer to texture"); 907 } 908} 909 910TextureBuffer::~TextureBuffer (void) 911{ 912 if (m_glTexture) 913 m_context.getFunctions().deleteTextures(1, &m_glTexture); 914 915 if (m_glBuffer) 916 m_context.getFunctions().deleteBuffers(1, &m_glBuffer); 917} 918 919 920const tcu::PixelBufferAccess TextureBuffer::getFullRefTexture (void) 921{ 922 const tcu::TextureFormat format = mapGLInternalFormat(m_format); 923 const size_t bufferLengthBytes = (m_size != 0) ? (m_size) : (m_refBuffer.size()); 924 const int bufferLengthPixels = (int)bufferLengthBytes / format.getPixelSize(); 925 926 return tcu::PixelBufferAccess(format, 927 tcu::IVec3(bufferLengthPixels, 1, 1), 928 (deUint8*)m_refBuffer.getPtr() + m_offset); 929} 930 931const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture (void) const 932{ 933 return const_cast<TextureBuffer*>(this)->getFullRefTexture(); 934} 935 936void TextureBuffer::upload (void) 937{ 938 const glw::Functions& gl = m_context.getFunctions(); 939 940 gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer); 941 gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), m_refBuffer.getPtr(), GL_STATIC_DRAW); 942 gl.bindBuffer(GL_TEXTURE_BUFFER, 0); 943 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer"); 944} 945 946} // glu 947