Merge gerrit/vulkan-cts-1.0.1 into gerrit/vulkan-cts-1.0-dev
[platform/upstream/VK-GL-CTS.git] / framework / opengl / gluTexture.cpp
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
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
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
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
74 Texture1D::~Texture1D (void)
75 {
76         if (m_glTexture)
77                 m_context.getFunctions().deleteTextures(1, &m_glTexture);
78 }
79
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
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
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
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
155 Texture2D::~Texture2D (void)
156 {
157         if (m_glTexture)
158                 m_context.getFunctions().deleteTextures(1, &m_glTexture);
159 }
160
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
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
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
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
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
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
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
340 TextureCube::~TextureCube (void)
341 {
342         if (m_glTexture)
343                 m_context.getFunctions().deleteTextures(1, &m_glTexture);
344 }
345
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
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
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
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
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
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
463 Texture1DArray::~Texture1DArray (void)
464 {
465         if (m_glTexture)
466                 m_context.getFunctions().deleteTextures(1, &m_glTexture);
467 }
468
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
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
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
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
547 Texture2DArray::~Texture2DArray (void)
548 {
549         if (m_glTexture)
550                 m_context.getFunctions().deleteTextures(1, &m_glTexture);
551 }
552
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
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
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
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
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
667 Texture3D::~Texture3D (void)
668 {
669         if (m_glTexture)
670                 m_context.getFunctions().deleteTextures(1, &m_glTexture);
671 }
672
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
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
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
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
760 TextureCubeArray::~TextureCubeArray (void)
761 {
762         if (m_glTexture)
763                 m_context.getFunctions().deleteTextures(1, &m_glTexture);
764 }
765
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
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
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
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
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
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
897 const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture (void) const
898 {
899         return const_cast<TextureBuffer*>(this)->getFullRefTexture();
900 }
901
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