xref: /aosp_15_r20/external/deqp/framework/opengl/gluTexture.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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,uint32_t format,uint32_t dataType,int width)52 Texture1D::Texture1D(const RenderContext &context, uint32_t format, uint32_t 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,uint32_t sizedFormat,int width)63 Texture1D::Texture1D(const RenderContext &context, uint32_t 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,
98                       transferFormat.dataType, access.getDataPtr());
99     }
100 
101     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
102 }
103 
104 // Texture2D
105 
Texture2D(const RenderContext & context,uint32_t format,uint32_t dataType,int width,int height)106 Texture2D::Texture2D(const RenderContext &context, uint32_t format, uint32_t dataType, int width, int height)
107     : m_context(context)
108     , m_isCompressed(false)
109     , m_format(format)
110     , m_refTexture(mapGLTransferFormat(format, dataType), width, height, isES2Context(context.getType()))
111     , m_glTexture(0)
112 {
113     const glw::Functions &gl = context.getFunctions();
114     gl.genTextures(1, &m_glTexture);
115     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
116 }
117 
Texture2D(const RenderContext & context,uint32_t sizedFormat,int width,int height)118 Texture2D::Texture2D(const RenderContext &context, uint32_t sizedFormat, int width, int height)
119     : m_context(context)
120     , m_isCompressed(false)
121     , m_format(sizedFormat)
122     , m_refTexture(mapGLInternalFormat(sizedFormat), width, height, isES2Context(context.getType()))
123     , m_glTexture(0)
124 {
125     const glw::Functions &gl = context.getFunctions();
126     gl.genTextures(1, &m_glTexture);
127     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
128 }
129 
Texture2D(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)130 Texture2D::Texture2D(const RenderContext &context, const ContextInfo &contextInfo, int numLevels,
131                      const tcu::CompressedTexture *levels, const tcu::TexDecompressionParams &decompressionParams)
132     : m_context(context)
133     , m_isCompressed(true)
134     , m_format(getGLFormat(levels[0].getFormat()))
135     , m_refTexture(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(),
136                    isES2Context(context.getType()))
137     , m_glTexture(0)
138 {
139     const glw::Functions &gl = context.getFunctions();
140 
141     if (!contextInfo.isCompressedTextureFormatSupported(m_format))
142         TCU_THROW(NotSupportedError, "Compressed texture format not supported");
143 
144     gl.genTextures(1, &m_glTexture);
145     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
146 
147     try
148     {
149         loadCompressed(numLevels, levels, decompressionParams);
150     }
151     catch (const std::exception &)
152     {
153         gl.deleteTextures(1, &m_glTexture);
154         throw;
155     }
156 }
157 
~Texture2D(void)158 Texture2D::~Texture2D(void)
159 {
160     if (m_glTexture)
161         m_context.getFunctions().deleteTextures(1, &m_glTexture);
162 }
163 
upload(void)164 void Texture2D::upload(void)
165 {
166     const glw::Functions &gl = m_context.getFunctions();
167 
168     DE_ASSERT(!m_isCompressed);
169 
170     TCU_CHECK(m_glTexture);
171     gl.bindTexture(GL_TEXTURE_2D, m_glTexture);
172     gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
173     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
174 
175     TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
176 
177     for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
178     {
179         if (m_refTexture.isLevelEmpty(levelNdx))
180             continue; // Don't upload.
181 
182         tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
183         DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
184         gl.texImage2D(GL_TEXTURE_2D, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */,
185                       transferFormat.format, transferFormat.dataType, access.getDataPtr());
186     }
187 
188     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
189 }
190 
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)191 void Texture2D::loadCompressed(int numLevels, const tcu::CompressedTexture *levels,
192                                const tcu::TexDecompressionParams &decompressionParams)
193 {
194     const glw::Functions &gl  = m_context.getFunctions();
195     uint32_t compressedFormat = getGLFormat(levels[0].getFormat());
196 
197     TCU_CHECK(m_glTexture);
198     gl.bindTexture(GL_TEXTURE_2D, m_glTexture);
199 
200     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
201     {
202         const tcu::CompressedTexture &level = levels[levelNdx];
203 
204         // Decompress to reference texture.
205         m_refTexture.allocLevel(levelNdx);
206         tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
207         TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && level.getHeight() == refLevelAccess.getHeight());
208         level.decompress(refLevelAccess, decompressionParams);
209 
210         // Upload to GL texture in compressed form.
211         gl.compressedTexImage2D(GL_TEXTURE_2D, levelNdx, compressedFormat, level.getWidth(), level.getHeight(),
212                                 0 /* border */, level.getDataSize(), level.getData());
213     }
214 
215     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
216 }
217 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const char * const * levelFileNames)218 Texture2D *Texture2D::create(const RenderContext &context, const ContextInfo &contextInfo, const tcu::Archive &archive,
219                              int numLevels, const char *const *levelFileNames)
220 {
221     DE_ASSERT(numLevels > 0);
222 
223     std::string ext = de::FilePath(levelFileNames[0]).getFileExtension();
224 
225     if (ext == "png")
226     {
227         // Uncompressed texture.
228 
229         tcu::TextureLevel level;
230 
231         // Load level 0.
232         tcu::ImageIO::loadPNG(level, archive, levelFileNames[0]);
233 
234         TCU_CHECK_INTERNAL(
235             level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
236             level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
237 
238         bool isRGBA = level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
239         Texture2D *texture =
240             new Texture2D(context, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, level.getWidth(), level.getHeight());
241 
242         try
243         {
244             // Fill level 0.
245             texture->getRefTexture().allocLevel(0);
246             tcu::copy(texture->getRefTexture().getLevel(0), level.getAccess());
247 
248             // Fill remaining levels.
249             for (int levelNdx = 1; levelNdx < numLevels; levelNdx++)
250             {
251                 tcu::ImageIO::loadPNG(level, archive, levelFileNames[levelNdx]);
252 
253                 texture->getRefTexture().allocLevel(levelNdx);
254                 tcu::copy(texture->getRefTexture().getLevel(levelNdx), level.getAccess());
255             }
256 
257             // Upload data.
258             texture->upload();
259         }
260         catch (const std::exception &)
261         {
262             delete texture;
263             throw;
264         }
265 
266         return texture;
267     }
268     else if (ext == "pkm")
269     {
270         // Compressed texture.
271         vector<tcu::CompressedTexture> levels(numLevels);
272 
273         for (int ndx = 0; ndx < numLevels; ndx++)
274             tcu::ImageIO::loadPKM(levels[ndx], archive, levelFileNames[ndx]);
275 
276         return new Texture2D(context, contextInfo, numLevels, &levels[0]);
277     }
278     else
279         TCU_FAIL("Unsupported file format");
280 }
281 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const std::vector<std::string> & filenames)282 Texture2D *Texture2D::create(const RenderContext &context, const ContextInfo &contextInfo, const tcu::Archive &archive,
283                              int numLevels, const std::vector<std::string> &filenames)
284 {
285     TCU_CHECK(numLevels == (int)filenames.size());
286 
287     std::vector<const char *> charPtrs(filenames.size());
288     for (int ndx = 0; ndx < (int)filenames.size(); ndx++)
289         charPtrs[ndx] = filenames[ndx].c_str();
290 
291     return Texture2D::create(context, contextInfo, archive, numLevels, &charPtrs[0]);
292 }
293 
294 // ImmutableTexture2D
295 
ImmutableTexture2D(const RenderContext & context,uint32_t sizedFormat,int width,int height)296 ImmutableTexture2D::ImmutableTexture2D(const RenderContext &context, uint32_t sizedFormat, int width, int height)
297     : Texture2D(context, sizedFormat, width, height)
298 {
299 }
300 
upload(void)301 void ImmutableTexture2D::upload(void)
302 {
303     const glw::Functions &gl = m_context.getFunctions();
304 
305     DE_ASSERT(!m_isCompressed);
306 
307     TCU_CHECK(m_glTexture);
308     gl.bindTexture(GL_TEXTURE_2D, m_glTexture);
309     gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
310     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
311 
312     TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
313 
314     gl.texStorage2D(GL_TEXTURE_2D, m_refTexture.getNumLevels(), m_format, m_refTexture.getWidth(),
315                     m_refTexture.getHeight());
316     for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
317     {
318         if (m_refTexture.isLevelEmpty(levelNdx))
319             continue; // Don't upload.
320 
321         tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
322         DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
323         gl.texSubImage2D(GL_TEXTURE_2D, levelNdx, 0, 0, access.getWidth(), access.getHeight(), transferFormat.format,
324                          transferFormat.dataType, access.getDataPtr());
325     }
326 
327     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
328 }
329 
330 // TextureCube
331 
TextureCube(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)332 TextureCube::TextureCube(const RenderContext &context, const ContextInfo &contextInfo, int numLevels,
333                          const tcu::CompressedTexture *levels, const tcu::TexDecompressionParams &decompressionParams)
334     : m_context(context)
335     , m_isCompressed(true)
336     , m_format(getGLFormat(levels[0].getFormat()))
337     , m_refTexture(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), isES2Context(context.getType()))
338     , m_glTexture(0)
339 {
340     const glw::Functions &gl = m_context.getFunctions();
341 
342     TCU_CHECK_INTERNAL(levels[0].getWidth() == levels[0].getHeight());
343 
344     if (!contextInfo.isCompressedTextureFormatSupported(m_format))
345         throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);
346 
347     gl.genTextures(1, &m_glTexture);
348     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
349 
350     try
351     {
352         loadCompressed(numLevels, levels, decompressionParams);
353     }
354     catch (const std::exception &)
355     {
356         gl.deleteTextures(1, &m_glTexture);
357         throw;
358     }
359 }
360 
TextureCube(const RenderContext & context,uint32_t format,uint32_t dataType,int size)361 TextureCube::TextureCube(const RenderContext &context, uint32_t format, uint32_t dataType, int size)
362     : m_context(context)
363     , m_isCompressed(false)
364     , m_format(format)
365     , m_refTexture(mapGLTransferFormat(format, dataType), size, isES2Context(context.getType()))
366     , m_glTexture(0)
367 {
368     const glw::Functions &gl = m_context.getFunctions();
369     gl.genTextures(1, &m_glTexture);
370     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
371 }
372 
TextureCube(const RenderContext & context,uint32_t internalFormat,int size)373 TextureCube::TextureCube(const RenderContext &context, uint32_t internalFormat, int size)
374     : m_context(context)
375     , m_isCompressed(false)
376     , m_format(internalFormat)
377     , m_refTexture(mapGLInternalFormat(internalFormat), size, isES2Context(context.getType()))
378     , m_glTexture(0)
379 {
380     const glw::Functions &gl = m_context.getFunctions();
381     gl.genTextures(1, &m_glTexture);
382     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
383 }
384 
~TextureCube(void)385 TextureCube::~TextureCube(void)
386 {
387     if (m_glTexture)
388         m_context.getFunctions().deleteTextures(1, &m_glTexture);
389 }
390 
upload(void)391 void TextureCube::upload(void)
392 {
393     const glw::Functions &gl = m_context.getFunctions();
394 
395     DE_ASSERT(!m_isCompressed);
396 
397     TCU_CHECK(m_glTexture);
398     gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);
399     gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
400     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
401 
402     TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
403 
404     for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
405     {
406         for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
407         {
408             if (m_refTexture.isLevelEmpty((tcu::CubeFace)face, levelNdx))
409                 continue; // Don't upload.
410 
411             tcu::ConstPixelBufferAccess access = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
412             DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
413             gl.texImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, m_format, access.getWidth(), access.getHeight(),
414                           0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
415         }
416     }
417 
418     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
419 }
420 
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)421 void TextureCube::loadCompressed(int numLevels, const tcu::CompressedTexture *levels,
422                                  const tcu::TexDecompressionParams &decompressionParams)
423 {
424     const glw::Functions &gl  = m_context.getFunctions();
425     uint32_t compressedFormat = getGLFormat(levels[0].getFormat());
426 
427     TCU_CHECK(m_glTexture);
428     gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_glTexture);
429 
430     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
431     {
432         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
433         {
434             const tcu::CompressedTexture &level = levels[levelNdx * tcu::CUBEFACE_LAST + face];
435 
436             // Decompress to reference texture.
437             m_refTexture.allocLevel((tcu::CubeFace)face, levelNdx);
438             tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevelFace(levelNdx, (tcu::CubeFace)face);
439             TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && level.getHeight() == refLevelAccess.getHeight());
440             level.decompress(refLevelAccess, decompressionParams);
441 
442             // Upload to GL texture in compressed form.
443             gl.compressedTexImage2D(getGLCubeFace((tcu::CubeFace)face), levelNdx, compressedFormat, level.getWidth(),
444                                     level.getHeight(), 0 /* border */, level.getDataSize(), level.getData());
445         }
446     }
447 
448     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
449 }
450 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const char * const * filenames)451 TextureCube *TextureCube::create(const RenderContext &context, const ContextInfo &contextInfo,
452                                  const tcu::Archive &archive, int numLevels, const char *const *filenames)
453 {
454     DE_ASSERT(numLevels > 0);
455 
456     std::string ext = de::FilePath(filenames[0]).getFileExtension();
457 
458     // \todo [2011-11-21 pyry] Support PNG images.
459     if (ext == "pkm")
460     {
461         // Compressed texture.
462         int numImages = numLevels * tcu::CUBEFACE_LAST;
463         vector<tcu::CompressedTexture> levels(numImages);
464 
465         for (int ndx = 0; ndx < numImages; ndx++)
466             tcu::ImageIO::loadPKM(levels[ndx], archive, filenames[ndx]);
467 
468         return new TextureCube(context, contextInfo, numLevels, &levels[0]);
469     }
470     else
471         TCU_FAIL("Unsupported file format");
472 }
473 
create(const RenderContext & context,const ContextInfo & contextInfo,const tcu::Archive & archive,int numLevels,const std::vector<std::string> & filenames)474 TextureCube *TextureCube::create(const RenderContext &context, const ContextInfo &contextInfo,
475                                  const tcu::Archive &archive, int numLevels, const std::vector<std::string> &filenames)
476 {
477     DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6);
478     TCU_CHECK(numLevels * tcu::CUBEFACE_LAST == (int)filenames.size());
479 
480     std::vector<const char *> charPtrs(filenames.size());
481     for (int ndx = 0; ndx < (int)filenames.size(); ndx++)
482         charPtrs[ndx] = filenames[ndx].c_str();
483 
484     return TextureCube::create(context, contextInfo, archive, numLevels, &charPtrs[0]);
485 }
486 
487 // Texture1DArray
488 
Texture1DArray(const RenderContext & context,uint32_t format,uint32_t dataType,int width,int numLevels)489 Texture1DArray::Texture1DArray(const RenderContext &context, uint32_t format, uint32_t dataType, int width,
490                                int numLevels)
491     : m_context(context)
492     , m_format(format)
493     , m_refTexture(mapGLTransferFormat(format, dataType), width, numLevels)
494     , m_glTexture(0)
495 {
496     const glw::Functions &gl = m_context.getFunctions();
497     gl.genTextures(1, &m_glTexture);
498     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
499 }
500 
Texture1DArray(const RenderContext & context,uint32_t sizedFormat,int width,int numLevels)501 Texture1DArray::Texture1DArray(const RenderContext &context, uint32_t sizedFormat, int width, int numLevels)
502     : m_context(context)
503     , m_format(sizedFormat)
504     , m_refTexture(mapGLInternalFormat(sizedFormat), width, numLevels)
505     , m_glTexture(0)
506 {
507     const glw::Functions &gl = m_context.getFunctions();
508     gl.genTextures(1, &m_glTexture);
509     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
510 }
511 
~Texture1DArray(void)512 Texture1DArray::~Texture1DArray(void)
513 {
514     if (m_glTexture)
515         m_context.getFunctions().deleteTextures(1, &m_glTexture);
516 }
517 
upload(void)518 void Texture1DArray::upload(void)
519 {
520     const glw::Functions &gl = m_context.getFunctions();
521 
522     TCU_CHECK(m_glTexture);
523     gl.bindTexture(GL_TEXTURE_1D_ARRAY, m_glTexture);
524     gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
525     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
526 
527     TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
528 
529     for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
530     {
531         if (m_refTexture.isLevelEmpty(levelNdx))
532             continue; // Don't upload.
533 
534         tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
535         DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
536         gl.texImage2D(GL_TEXTURE_1D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), 0 /* border */,
537                       transferFormat.format, transferFormat.dataType, access.getDataPtr());
538     }
539 
540     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
541 }
542 
543 // Texture2DArray
544 
Texture2DArray(const RenderContext & context,uint32_t format,uint32_t dataType,int width,int height,int numLevels)545 Texture2DArray::Texture2DArray(const RenderContext &context, uint32_t format, uint32_t dataType, int width, int height,
546                                int numLevels)
547     : m_context(context)
548     , m_isCompressed(false)
549     , m_format(format)
550     , m_refTexture(mapGLTransferFormat(format, dataType), width, height, numLevels)
551     , m_glTexture(0)
552 {
553     // \todo [2013-04-08 pyry] Check support here.
554     const glw::Functions &gl = m_context.getFunctions();
555     gl.genTextures(1, &m_glTexture);
556     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
557 }
558 
Texture2DArray(const RenderContext & context,uint32_t sizedFormat,int width,int height,int numLevels)559 Texture2DArray::Texture2DArray(const RenderContext &context, uint32_t sizedFormat, int width, int height, int numLevels)
560     : m_context(context)
561     , m_isCompressed(false)
562     , m_format(sizedFormat)
563     , m_refTexture(mapGLInternalFormat(sizedFormat), width, height, numLevels)
564     , m_glTexture(0)
565 {
566     // \todo [2013-04-08 pyry] Check support here.
567     const glw::Functions &gl = m_context.getFunctions();
568     gl.genTextures(1, &m_glTexture);
569     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
570 }
571 
Texture2DArray(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)572 Texture2DArray::Texture2DArray(const RenderContext &context, const ContextInfo &contextInfo, int numLevels,
573                                const tcu::CompressedTexture *levels,
574                                const tcu::TexDecompressionParams &decompressionParams)
575     : m_context(context)
576     , m_isCompressed(true)
577     , m_format(getGLFormat(levels[0].getFormat()))
578     , m_refTexture(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(),
579                    levels[0].getDepth())
580     , m_glTexture(0)
581 {
582     const glw::Functions &gl = context.getFunctions();
583 
584     if (!contextInfo.isCompressedTextureFormatSupported(m_format))
585         throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);
586 
587     gl.genTextures(1, &m_glTexture);
588     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
589 
590     try
591     {
592         loadCompressed(numLevels, levels, decompressionParams);
593     }
594     catch (const std::exception &)
595     {
596         gl.deleteTextures(1, &m_glTexture);
597         throw;
598     }
599 }
600 
~Texture2DArray(void)601 Texture2DArray::~Texture2DArray(void)
602 {
603     if (m_glTexture)
604         m_context.getFunctions().deleteTextures(1, &m_glTexture);
605 }
606 
upload(void)607 void Texture2DArray::upload(void)
608 {
609     const glw::Functions &gl = m_context.getFunctions();
610 
611     if (!gl.texImage3D)
612         throw tcu::NotSupportedError("glTexImage3D() is not supported");
613 
614     TCU_CHECK(m_glTexture);
615     gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture);
616     gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
617     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
618 
619     TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
620 
621     for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
622     {
623         if (m_refTexture.isLevelEmpty(levelNdx))
624             continue; // Don't upload.
625 
626         tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
627         DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
628         DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * access.getWidth() * access.getHeight());
629         gl.texImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(),
630                       0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
631     }
632 
633     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
634 }
635 
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)636 void Texture2DArray::loadCompressed(int numLevels, const tcu::CompressedTexture *levels,
637                                     const tcu::TexDecompressionParams &decompressionParams)
638 {
639     const glw::Functions &gl  = m_context.getFunctions();
640     uint32_t compressedFormat = getGLFormat(levels[0].getFormat());
641 
642     TCU_CHECK(m_glTexture);
643     gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_glTexture);
644 
645     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
646     {
647         const tcu::CompressedTexture &level = levels[levelNdx];
648 
649         // Decompress to reference texture.
650         m_refTexture.allocLevel(levelNdx);
651         tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
652         TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && level.getHeight() == refLevelAccess.getHeight() &&
653                   level.getDepth() == refLevelAccess.getDepth());
654         level.decompress(refLevelAccess, decompressionParams);
655 
656         // Upload to GL texture in compressed form.
657         gl.compressedTexImage3D(GL_TEXTURE_2D_ARRAY, levelNdx, compressedFormat, level.getWidth(), level.getHeight(),
658                                 m_refTexture.getLevel(levelNdx).getDepth(), 0 /* border */, level.getDataSize(),
659                                 level.getData());
660     }
661 
662     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
663 }
664 
665 // Texture3D
666 
Texture3D(const RenderContext & context,uint32_t format,uint32_t dataType,int width,int height,int depth)667 Texture3D::Texture3D(const RenderContext &context, uint32_t format, uint32_t dataType, int width, int height, int depth)
668     : m_context(context)
669     , m_isCompressed(false)
670     , m_format(format)
671     , m_refTexture(mapGLTransferFormat(format, dataType), width, height, depth)
672     , m_glTexture(0)
673 {
674     // \todo [2013-04-08 pyry] Check support here.
675     const glw::Functions &gl = m_context.getFunctions();
676     gl.genTextures(1, &m_glTexture);
677     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
678 }
679 
Texture3D(const RenderContext & context,uint32_t sizedFormat,int width,int height,int depth)680 Texture3D::Texture3D(const RenderContext &context, uint32_t sizedFormat, int width, int height, int depth)
681     : m_context(context)
682     , m_isCompressed(false)
683     , m_format(sizedFormat)
684     , m_refTexture(mapGLInternalFormat(sizedFormat), width, height, depth)
685     , m_glTexture(0)
686 {
687     // \todo [2013-04-08 pyry] Check support here.
688     const glw::Functions &gl = m_context.getFunctions();
689     gl.genTextures(1, &m_glTexture);
690     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
691 }
692 
Texture3D(const RenderContext & context,const ContextInfo & contextInfo,int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)693 Texture3D::Texture3D(const RenderContext &context, const ContextInfo &contextInfo, int numLevels,
694                      const tcu::CompressedTexture *levels, const tcu::TexDecompressionParams &decompressionParams)
695     : m_context(context)
696     , m_isCompressed(true)
697     , m_format(getGLFormat(levels[0].getFormat()))
698     , m_refTexture(getUncompressedFormat(levels[0].getFormat()), levels[0].getWidth(), levels[0].getHeight(),
699                    levels[0].getDepth())
700     , m_glTexture(0)
701 {
702     const glw::Functions &gl = context.getFunctions();
703 
704     if (!contextInfo.isCompressedTextureFormatSupported(m_format))
705         throw tcu::NotSupportedError("Compressed texture format not supported", "", __FILE__, __LINE__);
706 
707     gl.genTextures(1, &m_glTexture);
708     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
709 
710     try
711     {
712         loadCompressed(numLevels, levels, decompressionParams);
713     }
714     catch (const std::exception &)
715     {
716         gl.deleteTextures(1, &m_glTexture);
717         throw;
718     }
719 }
720 
~Texture3D(void)721 Texture3D::~Texture3D(void)
722 {
723     if (m_glTexture)
724         m_context.getFunctions().deleteTextures(1, &m_glTexture);
725 }
726 
upload(void)727 void Texture3D::upload(void)
728 {
729     const glw::Functions &gl = m_context.getFunctions();
730 
731     DE_ASSERT(!m_isCompressed);
732 
733     if (!gl.texImage3D)
734         throw tcu::NotSupportedError("glTexImage3D() is not supported");
735 
736     TCU_CHECK(m_glTexture);
737     gl.bindTexture(GL_TEXTURE_3D, m_glTexture);
738     gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
739     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
740 
741     TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
742 
743     for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
744     {
745         if (m_refTexture.isLevelEmpty(levelNdx))
746             continue; // Don't upload.
747 
748         tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
749         DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
750         DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * access.getWidth() * access.getHeight());
751         gl.texImage3D(GL_TEXTURE_3D, levelNdx, m_format, access.getWidth(), access.getHeight(), access.getDepth(),
752                       0 /* border */, transferFormat.format, transferFormat.dataType, access.getDataPtr());
753     }
754 
755     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
756 }
757 
loadCompressed(int numLevels,const tcu::CompressedTexture * levels,const tcu::TexDecompressionParams & decompressionParams)758 void Texture3D::loadCompressed(int numLevels, const tcu::CompressedTexture *levels,
759                                const tcu::TexDecompressionParams &decompressionParams)
760 {
761     const glw::Functions &gl  = m_context.getFunctions();
762     uint32_t compressedFormat = getGLFormat(levels[0].getFormat());
763 
764     if (!gl.compressedTexImage3D)
765         throw tcu::NotSupportedError("glCompressedTexImage3D() is not supported");
766 
767     TCU_CHECK(m_glTexture);
768     gl.bindTexture(GL_TEXTURE_3D, m_glTexture);
769 
770     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
771     {
772         const tcu::CompressedTexture &level = levels[levelNdx];
773 
774         // Decompress to reference texture.
775         m_refTexture.allocLevel(levelNdx);
776         tcu::PixelBufferAccess refLevelAccess = m_refTexture.getLevel(levelNdx);
777         TCU_CHECK(level.getWidth() == refLevelAccess.getWidth() && level.getHeight() == refLevelAccess.getHeight() &&
778                   level.getDepth() == refLevelAccess.getDepth());
779         level.decompress(refLevelAccess, decompressionParams);
780 
781         // Upload to GL texture in compressed form.
782         gl.compressedTexImage3D(GL_TEXTURE_3D, levelNdx, compressedFormat, level.getWidth(), level.getHeight(),
783                                 level.getDepth(), 0 /* border */, level.getDataSize(), level.getData());
784     }
785 
786     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
787 }
788 
789 // TextureCubeArray
790 
TextureCubeArray(const RenderContext & context,uint32_t format,uint32_t dataType,int size,int numLayers)791 TextureCubeArray::TextureCubeArray(const RenderContext &context, uint32_t format, uint32_t dataType, int size,
792                                    int numLayers)
793     : m_context(context)
794     , m_format(format)
795     , m_refTexture(mapGLTransferFormat(format, dataType), size, numLayers)
796     , m_glTexture(0)
797 {
798     // \todo [2013-04-08 pyry] Check support here.
799     const glw::Functions &gl = m_context.getFunctions();
800     gl.genTextures(1, &m_glTexture);
801     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
802 }
803 
TextureCubeArray(const RenderContext & context,uint32_t sizedFormat,int size,int numLayers)804 TextureCubeArray::TextureCubeArray(const RenderContext &context, uint32_t sizedFormat, int size, int numLayers)
805     : m_context(context)
806     , m_format(sizedFormat)
807     , m_refTexture(mapGLInternalFormat(sizedFormat), size, numLayers)
808     , m_glTexture(0)
809 {
810     // \todo [2013-04-08 pyry] Check support here.
811     const glw::Functions &gl = m_context.getFunctions();
812     gl.genTextures(1, &m_glTexture);
813     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
814 }
815 
~TextureCubeArray(void)816 TextureCubeArray::~TextureCubeArray(void)
817 {
818     if (m_glTexture)
819         m_context.getFunctions().deleteTextures(1, &m_glTexture);
820 }
821 
upload(void)822 void TextureCubeArray::upload(void)
823 {
824     const glw::Functions &gl = m_context.getFunctions();
825 
826     if (!gl.texImage3D)
827         throw tcu::NotSupportedError("glTexImage3D() is not supported");
828 
829     TCU_CHECK(m_glTexture);
830     gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_glTexture);
831     gl.pixelStorei(GL_UNPACK_ALIGNMENT, computePixelStore(m_refTexture.getFormat()));
832     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
833 
834     TransferFormat transferFormat = getTransferFormat(m_refTexture.getFormat());
835 
836     for (int levelNdx = 0; levelNdx < m_refTexture.getNumLevels(); levelNdx++)
837     {
838         if (m_refTexture.isLevelEmpty(levelNdx))
839             continue; // Don't upload.
840 
841         tcu::ConstPixelBufferAccess access = m_refTexture.getLevel(levelNdx);
842         DE_ASSERT(access.getRowPitch() == access.getFormat().getPixelSize() * access.getWidth());
843         DE_ASSERT(access.getSlicePitch() == access.getFormat().getPixelSize() * access.getWidth() * access.getHeight());
844         gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, levelNdx, m_format, access.getWidth(), access.getHeight(),
845                       access.getDepth(), 0 /* border */, transferFormat.format, transferFormat.dataType,
846                       access.getDataPtr());
847     }
848 
849     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture upload failed");
850 }
851 
852 // TextureBuffer
853 
TextureBuffer(const RenderContext & context,uint32_t internalFormat,size_t bufferSize)854 TextureBuffer::TextureBuffer(const RenderContext &context, uint32_t internalFormat, size_t bufferSize)
855     : m_context(context)
856     , m_format(0)
857     , m_offset(0)
858     , m_size(0)
859     , m_glTexture(0)
860     , m_glBuffer(0)
861 {
862     init(internalFormat, bufferSize, 0, 0, DE_NULL);
863 }
864 
TextureBuffer(const RenderContext & context,uint32_t internalFormat,size_t bufferSize,size_t offset,size_t size,const void * data)865 TextureBuffer::TextureBuffer(const RenderContext &context, uint32_t internalFormat, size_t bufferSize, size_t offset,
866                              size_t size, const void *data)
867     : m_context(context)
868     , m_format(0)
869     , m_offset(0)
870     , m_size(0)
871     , m_glTexture(0)
872     , m_glBuffer(0)
873 {
874     init(internalFormat, bufferSize, offset, size, data);
875 }
876 
init(uint32_t internalFormat,size_t bufferSize,size_t offset,size_t size,const void * data)877 void TextureBuffer::init(uint32_t internalFormat, size_t bufferSize, size_t offset, size_t size, const void *data)
878 {
879     const glw::Functions &gl = m_context.getFunctions();
880     de::UniquePtr<ContextInfo> info(ContextInfo::create(m_context));
881 
882     if (offset != 0 || size != 0)
883     {
884         if (!(contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) &&
885               info->isExtensionSupported("GL_ARB_texture_buffer_range")) &&
886             !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) &&
887               info->isExtensionSupported("GL_EXT_texture_buffer")))
888         {
889             throw tcu::NotSupportedError("Ranged texture buffers not supported", "", __FILE__, __LINE__);
890         }
891     }
892     else
893     {
894         if (!contextSupports(m_context.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)) &&
895             !(contextSupports(m_context.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) &&
896               info->isExtensionSupported("GL_EXT_texture_buffer")))
897         {
898             throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
899         }
900     }
901 
902     m_refBuffer.setStorage(bufferSize);
903     if (data)
904         deMemcpy(m_refBuffer.getPtr(), data, (int)bufferSize);
905 
906     m_format = internalFormat;
907     m_offset = offset;
908     m_size   = size;
909 
910     DE_ASSERT(size != 0 || offset == 0);
911 
912     {
913         gl.genTextures(1, &m_glTexture);
914         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
915 
916         gl.genBuffers(1, &m_glBuffer);
917         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
918 
919         gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
920         gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), data, GL_STATIC_DRAW);
921         gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
922         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffer");
923 
924         gl.bindTexture(GL_TEXTURE_BUFFER, m_glTexture);
925 
926         if (offset != 0 || size != 0)
927             gl.texBufferRange(GL_TEXTURE_BUFFER, m_format, m_glBuffer, (glw::GLintptr)m_offset,
928                               (glw::GLsizeiptr)m_size);
929         else
930             gl.texBuffer(GL_TEXTURE_BUFFER, m_format, m_glBuffer);
931 
932         gl.bindTexture(GL_TEXTURE_BUFFER, 0);
933         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffer to texture");
934     }
935 }
936 
~TextureBuffer(void)937 TextureBuffer::~TextureBuffer(void)
938 {
939     if (m_glTexture)
940         m_context.getFunctions().deleteTextures(1, &m_glTexture);
941 
942     if (m_glBuffer)
943         m_context.getFunctions().deleteBuffers(1, &m_glBuffer);
944 }
945 
getFullRefTexture(void)946 const tcu::PixelBufferAccess TextureBuffer::getFullRefTexture(void)
947 {
948     const tcu::TextureFormat format = mapGLInternalFormat(m_format);
949     const size_t bufferLengthBytes  = (m_size != 0) ? (m_size) : (m_refBuffer.size());
950     const int bufferLengthPixels    = (int)bufferLengthBytes / format.getPixelSize();
951 
952     return tcu::PixelBufferAccess(format, tcu::IVec3(bufferLengthPixels, 1, 1),
953                                   (uint8_t *)m_refBuffer.getPtr() + m_offset);
954 }
955 
getFullRefTexture(void) const956 const tcu::ConstPixelBufferAccess TextureBuffer::getFullRefTexture(void) const
957 {
958     return const_cast<TextureBuffer *>(this)->getFullRefTexture();
959 }
960 
upload(void)961 void TextureBuffer::upload(void)
962 {
963     const glw::Functions &gl = m_context.getFunctions();
964 
965     gl.bindBuffer(GL_TEXTURE_BUFFER, m_glBuffer);
966     gl.bufferData(GL_TEXTURE_BUFFER, (glw::GLsizei)m_refBuffer.size(), m_refBuffer.getPtr(), GL_STATIC_DRAW);
967     gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
968     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to upload buffer");
969 }
970 
971 } // namespace glu
972