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