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,deUint32 format,deUint32 dataType,int width)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
Texture1D(const RenderContext & context,deUint32 sizedFormat,int width)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
~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, transferFormat.dataType, access.getDataPtr());
98 }
99
100 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
101 }
102
103 // Texture2D
104
Texture2D(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int height)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, 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
Texture2D(const RenderContext & context,deUint32 sizedFormat,int width,int height)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, 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
Texture2D(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)129 Texture2D::Texture2D (const RenderContext& context, const ContextInfo& contextInfo, int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
130 : m_context (context)
131 , m_isCompressed (true)
132 , m_format (getGLFormat(levels[0].getFormat()))
133 , m_refTexture (getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(), 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
~Texture2D(void)155 Texture2D::~Texture2D (void)
156 {
157 if (m_glTexture)
158 m_context.getFunctions().deleteTextures(1, &m_glTexture);
159 }
160
upload(void)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
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)187 void Texture2D::loadCompressed (int numLevels, const tcu::CompressedTexture* levels, const tcu::TexDecompressionParams& decompressionParams)
188 {
189 const glw::Functions& gl = m_context.getFunctions();
190 deUint32 compressedFormat = getGLFormat(levels[0].getFormat());
191
192 TCU_CHECK(m_glTexture);
193 gl.bindTexture(GL_TEXTURE_2D, m_glTexture);
194
195 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
196 {
197 const tcu::CompressedTexture& level = levels[levelNdx];
198
199 // Decompress to reference texture.
200 m_refTexture.allocLevel(levelNdx);
201 tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
202 TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() &&
203 level.getHeight() == refLevelAccess.getHeight());
204 level.decompress(refLevelAccess, decompressionParams);
205
206 // Upload to GL texture in compressed form.
207 gl.compressedTexImage2D(GL_TEXTURE_2D, levelNdx, compressedFormat,
208 level.getWidth(), level.getHeight(), 0 /* border */, level.getDataSize(), level.getData());
209 }
210
211 GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
212 }
213
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const char * const * levelFileNames)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
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const std::vector<std::string> & filenames)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 // ImmutableTexture2D
287
ImmutableTexture2D(const RenderContext & context,deUint32 sizedFormat,int width,int height)288 ImmutableTexture2D::ImmutableTexture2D (const RenderContext& context, deUint32 sizedFormat, int width, int height)
289 : Texture2D(context, sizedFormat, width, height)
290 {
291 }
292
upload(void)293 void 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
TextureCube(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)322 TextureCube::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
TextureCube(const RenderContext & context,deUint32 format,deUint32 dataType,int size)350 TextureCube::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
TextureCube(const RenderContext & context,deUint32 internalFormat,int size)362 TextureCube::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
~TextureCube(void)374 TextureCube::~TextureCube (void)
375 {
376 if (m_glTexture)
377 m_context.getFunctions().deleteTextures(1, &m_glTexture);
378 }
379
upload(void)380 void 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
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)409 void 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
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const char * const * filenames)439 TextureCube* 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
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const std::vector<std::string> & filenames)461 TextureCube* 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
Texture1DArray(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int numLevels)475 Texture1DArray::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
Texture1DArray(const RenderContext & context,deUint32 sizedFormat,int width,int numLevels)486 Texture1DArray::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
~Texture1DArray(void)497 Texture1DArray::~Texture1DArray (void)
498 {
499 if (m_glTexture)
500 m_context.getFunctions().deleteTextures(1, &m_glTexture);
501 }
502
upload(void)503 void 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
Texture2DArray(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int height,int numLevels)529 Texture2DArray::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
Texture2DArray(const RenderContext & context,deUint32 sizedFormat,int width,int height,int numLevels)542 Texture2DArray::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
Texture2DArray(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)555 Texture2DArray::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
~Texture2DArray(void)581 Texture2DArray::~Texture2DArray (void)
582 {
583 if (m_glTexture)
584 m_context.getFunctions().deleteTextures(1, &m_glTexture);
585 }
586
upload(void)587 void 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
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)615 void 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
Texture3D(const RenderContext & context,deUint32 format,deUint32 dataType,int width,int height,int depth)645 Texture3D::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
Texture3D(const RenderContext & context,deUint32 sizedFormat,int width,int height,int depth)658 Texture3D::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
Texture3D(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)671 Texture3D::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
~Texture3D(void)701 Texture3D::~Texture3D (void)
702 {
703 if (m_glTexture)
704 m_context.getFunctions().deleteTextures(1, &m_glTexture);
705 }
706
upload(void)707 void 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
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)737 void 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
TextureCubeArray(const RenderContext & context,deUint32 format,deUint32 dataType,int size,int numLayers)770 TextureCubeArray::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
TextureCubeArray(const RenderContext & context,deUint32 sizedFormat,int size,int numLayers)782 TextureCubeArray::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
~TextureCubeArray(void)794 TextureCubeArray::~TextureCubeArray (void)
795 {
796 if (m_glTexture)
797 m_context.getFunctions().deleteTextures(1, &m_glTexture);
798 }
799
upload(void)800 void 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
TextureBuffer(const RenderContext & context,deUint32 internalFormat,size_t bufferSize)830 TextureBuffer::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
TextureBuffer(const RenderContext & context,deUint32 internalFormat,size_t bufferSize,size_t offset,size_t size,const void * data)841 TextureBuffer::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
init(deUint32 internalFormat,size_t bufferSize,size_t offset,size_t size,const void * data)852 void 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
~TextureBuffer(void)910 TextureBuffer::~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
getFullRefTexture(void)920 const 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
getFullRefTexture(void) const931 const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture (void) const
932 {
933 return const_cast<TextureBuffer*>(this)->getFullRefTexture();
934 }
935
upload(void)936 void 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