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