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