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