xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fFboColorbufferTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
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 FBO colorbuffer tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fFboColorbufferTests.hpp"
25 #include "es3fFboTestCase.hpp"
26 #include "es3fFboTestUtil.hpp"
27 #include "gluTextureUtil.hpp"
28 #include "gluContextInfo.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuRGBA.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "sglrContextUtil.hpp"
34 #include "deRandom.hpp"
35 #include "deString.h"
36 #include "glwEnums.hpp"
37 
38 namespace deqp
39 {
40 namespace gles3
41 {
42 namespace Functional
43 {
44 
45 using std::string;
46 using tcu::IVec2;
47 using tcu::IVec3;
48 using tcu::IVec4;
49 using tcu::TestLog;
50 using tcu::UVec4;
51 using tcu::Vec2;
52 using tcu::Vec3;
53 using tcu::Vec4;
54 using namespace FboTestUtil;
55 
56 const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12);
57 
58 template <int Size>
59 static tcu::Vector<float, Size> randomVector(de::Random &rnd,
60                                              const tcu::Vector<float, Size> &minVal = tcu::Vector<float, Size>(0.0f),
61                                              const tcu::Vector<float, Size> &maxVal = tcu::Vector<float, Size>(1.0f))
62 {
63     tcu::Vector<float, Size> res;
64     for (int ndx = 0; ndx < Size; ndx++)
65         res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
66     return res;
67 }
68 
generateRandomColor(de::Random & random)69 static tcu::Vec4 generateRandomColor(de::Random &random)
70 {
71     tcu::Vec4 retVal;
72 
73     for (int i = 0; i < 3; ++i)
74         retVal[i] = random.getFloat();
75     retVal[3] = 1.0f;
76 
77     return retVal;
78 }
79 
80 class FboColorbufferCase : public FboTestCase
81 {
82 public:
FboColorbufferCase(Context & context,const char * name,const char * desc,const uint32_t format)83     FboColorbufferCase(Context &context, const char *name, const char *desc, const uint32_t format)
84         : FboTestCase(context, name, desc)
85         , m_format(format)
86     {
87     }
88 
compare(const tcu::Surface & reference,const tcu::Surface & result)89     bool compare(const tcu::Surface &reference, const tcu::Surface &result)
90     {
91         const tcu::RGBA threshold(tcu::max(getFormatThreshold(m_format), MIN_THRESHOLD));
92 
93         m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;
94 
95         return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(),
96                                     result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
97     }
98 
99 protected:
100     const uint32_t m_format;
101 };
102 
103 class FboColorClearCase : public FboColorbufferCase
104 {
105 public:
FboColorClearCase(Context & context,const char * name,const char * desc,uint32_t format,int width,int height)106     FboColorClearCase(Context &context, const char *name, const char *desc, uint32_t format, int width, int height)
107         : FboColorbufferCase(context, name, desc, format)
108         , m_width(width)
109         , m_height(height)
110     {
111     }
112 
113 protected:
preCheck(void)114     void preCheck(void)
115     {
116         checkFormatSupport(m_format);
117     }
118 
render(tcu::Surface & dst)119     void render(tcu::Surface &dst)
120     {
121         tcu::TextureFormat fboFormat      = glu::mapGLInternalFormat(m_format);
122         tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(fboFormat.type);
123         tcu::TextureFormatInfo fmtInfo    = tcu::getTextureFormatInfo(fboFormat);
124         de::Random rnd(17);
125         const int numClears = 16;
126         uint32_t fbo        = 0;
127         uint32_t rbo        = 0;
128 
129         glGenFramebuffers(1, &fbo);
130         glGenRenderbuffers(1, &rbo);
131 
132         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
133         glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_width, m_height);
134         checkError();
135 
136         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
137         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
138         checkError();
139         checkFramebufferStatus(GL_FRAMEBUFFER);
140 
141         glViewport(0, 0, m_width, m_height);
142 
143         // Initialize to transparent black.
144         switch (fmtClass)
145         {
146         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
147         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
148         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
149             glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr());
150             break;
151 
152         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
153             glClearBufferuiv(GL_COLOR, 0, UVec4(0).getPtr());
154             break;
155 
156         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
157             glClearBufferiv(GL_COLOR, 0, IVec4(0).getPtr());
158             break;
159 
160         default:
161             DE_ASSERT(false);
162         }
163 
164         // Do random scissored clears.
165         glEnable(GL_SCISSOR_TEST);
166         for (int ndx = 0; ndx < numClears; ndx++)
167         {
168             int x      = rnd.getInt(0, m_width - 1);
169             int y      = rnd.getInt(0, m_height - 1);
170             int w      = rnd.getInt(1, m_width - x);
171             int h      = rnd.getInt(1, m_height - y);
172             Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
173 
174             glScissor(x, y, w, h);
175 
176             switch (fmtClass)
177             {
178             case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
179             case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
180             case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
181                 glClearBufferfv(GL_COLOR, 0, color.getPtr());
182                 break;
183 
184             case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
185                 glClearBufferuiv(GL_COLOR, 0, color.cast<uint32_t>().getPtr());
186                 break;
187 
188             case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
189                 glClearBufferiv(GL_COLOR, 0, color.cast<int>().getPtr());
190                 break;
191 
192             default:
193                 DE_ASSERT(false);
194             }
195         }
196 
197         // Read results from renderbuffer.
198         readPixels(dst, 0, 0, m_width, m_height, fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
199         checkError();
200     }
201 
202 private:
203     const int m_width;
204     const int m_height;
205 };
206 
207 class FboColorMultiTex2DCase : public FboColorbufferCase
208 {
209 public:
FboColorMultiTex2DCase(Context & context,const char * name,const char * description,uint32_t tex0Fmt,const IVec2 & tex0Size,uint32_t tex1Fmt,const IVec2 & tex1Size)210     FboColorMultiTex2DCase(Context &context, const char *name, const char *description, uint32_t tex0Fmt,
211                            const IVec2 &tex0Size, uint32_t tex1Fmt, const IVec2 &tex1Size)
212         : FboColorbufferCase(context, name, description, tex0Fmt)
213         , m_tex0Fmt(tex0Fmt)
214         , m_tex1Fmt(tex1Fmt)
215         , m_tex0Size(tex0Size)
216         , m_tex1Size(tex1Size)
217     {
218     }
219 
220 protected:
preCheck(void)221     void preCheck(void)
222     {
223         checkFormatSupport(m_tex0Fmt);
224         checkFormatSupport(m_tex1Fmt);
225     }
226 
render(tcu::Surface & dst)227     void render(tcu::Surface &dst)
228     {
229         tcu::TextureFormat texFmt0      = glu::mapGLInternalFormat(m_tex0Fmt);
230         tcu::TextureFormat texFmt1      = glu::mapGLInternalFormat(m_tex1Fmt);
231         tcu::TextureFormatInfo fmtInfo0 = tcu::getTextureFormatInfo(texFmt0);
232         tcu::TextureFormatInfo fmtInfo1 = tcu::getTextureFormatInfo(texFmt1);
233 
234         Texture2DShader texToFbo0Shader(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt0),
235                                         fmtInfo0.valueMax - fmtInfo0.valueMin, fmtInfo0.valueMin);
236         Texture2DShader texToFbo1Shader(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt1),
237                                         fmtInfo1.valueMax - fmtInfo1.valueMin, fmtInfo1.valueMin);
238         Texture2DShader multiTexShader(DataTypes() << glu::getSampler2DType(texFmt0) << glu::getSampler2DType(texFmt1),
239                                        glu::TYPE_FLOAT_VEC4);
240 
241         uint32_t texToFbo0ShaderID = getCurrentContext()->createProgram(&texToFbo0Shader);
242         uint32_t texToFbo1ShaderID = getCurrentContext()->createProgram(&texToFbo1Shader);
243         uint32_t multiTexShaderID  = getCurrentContext()->createProgram(&multiTexShader);
244 
245         // Setup shaders
246         multiTexShader.setTexScaleBias(0, fmtInfo0.lookupScale * 0.5f, fmtInfo0.lookupBias * 0.5f);
247         multiTexShader.setTexScaleBias(1, fmtInfo1.lookupScale * 0.5f, fmtInfo1.lookupBias * 0.5f);
248         texToFbo0Shader.setUniforms(*getCurrentContext(), texToFbo0ShaderID);
249         texToFbo1Shader.setUniforms(*getCurrentContext(), texToFbo1ShaderID);
250         multiTexShader.setUniforms(*getCurrentContext(), multiTexShaderID);
251 
252         // Framebuffers.
253         uint32_t fbo0 = 0;
254         uint32_t fbo1 = 0;
255         uint32_t tex0 = 0;
256         uint32_t tex1 = 0;
257 
258         for (int ndx = 0; ndx < 2; ndx++)
259         {
260             glu::TransferFormat transferFmt = glu::getTransferFormat(ndx ? texFmt1 : texFmt0);
261             uint32_t format                 = ndx ? m_tex1Fmt : m_tex0Fmt;
262             bool isFilterable               = glu::isGLInternalColorFormatFilterable(format);
263             const IVec2 &size               = ndx ? m_tex1Size : m_tex0Size;
264             uint32_t &fbo                   = ndx ? fbo1 : fbo0;
265             uint32_t &tex                   = ndx ? tex1 : tex0;
266 
267             glGenFramebuffers(1, &fbo);
268             glGenTextures(1, &tex);
269 
270             glBindTexture(GL_TEXTURE_2D, tex);
271             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
272             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
273             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
274             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
275             glTexImage2D(GL_TEXTURE_2D, 0, format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType,
276                          DE_NULL);
277 
278             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
279             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
280             checkError();
281             checkFramebufferStatus(GL_FRAMEBUFFER);
282         }
283 
284         // Render textures to both framebuffers.
285         for (int ndx = 0; ndx < 2; ndx++)
286         {
287             const uint32_t format   = GL_RGBA;
288             const uint32_t dataType = GL_UNSIGNED_BYTE;
289             const int texW          = 128;
290             const int texH          = 128;
291             uint32_t tmpTex         = 0;
292             uint32_t fbo            = ndx ? fbo1 : fbo0;
293             const IVec2 &viewport   = ndx ? m_tex1Size : m_tex0Size;
294             tcu::TextureLevel data(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
295 
296             if (ndx == 0)
297                 tcu::fillWithComponentGradients(data.getAccess(), Vec4(0.0f), Vec4(1.0f));
298             else
299                 tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
300 
301             glGenTextures(1, &tmpTex);
302             glBindTexture(GL_TEXTURE_2D, tmpTex);
303             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
304             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
305             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
306             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
307             glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
308 
309             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
310             glViewport(0, 0, viewport.x(), viewport.y());
311             sglr::drawQuad(*getCurrentContext(), ndx ? texToFbo1ShaderID : texToFbo0ShaderID, Vec3(-1.0f, -1.0f, 0.0f),
312                            Vec3(1.0f, 1.0f, 0.0f));
313         }
314 
315         // Render to framebuffer.
316         glBindFramebuffer(GL_FRAMEBUFFER, 0);
317         glViewport(0, 0, getWidth(), getHeight());
318         glActiveTexture(GL_TEXTURE0);
319         glBindTexture(GL_TEXTURE_2D, tex0);
320         glActiveTexture(GL_TEXTURE1);
321         glBindTexture(GL_TEXTURE_2D, tex1);
322         sglr::drawQuad(*getCurrentContext(), multiTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
323 
324         readPixels(dst, 0, 0, getWidth(), getHeight());
325     }
326 
327 private:
328     uint32_t m_tex0Fmt;
329     uint32_t m_tex1Fmt;
330     IVec2 m_tex0Size;
331     IVec2 m_tex1Size;
332 };
333 
334 class FboColorTexCubeCase : public FboColorbufferCase
335 {
336 public:
FboColorTexCubeCase(Context & context,const char * name,const char * description,uint32_t texFmt,const IVec2 & texSize)337     FboColorTexCubeCase(Context &context, const char *name, const char *description, uint32_t texFmt,
338                         const IVec2 &texSize)
339         : FboColorbufferCase(context, name, description, texFmt)
340         , m_texSize(texSize)
341     {
342     }
343 
344 protected:
preCheck(void)345     void preCheck(void)
346     {
347         checkFormatSupport(m_format);
348     }
349 
render(tcu::Surface & dst)350     void render(tcu::Surface &dst)
351     {
352         static const uint32_t cubeGLFaces[] = {GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
353                                                GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
354                                                GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z};
355 
356         static const tcu::CubeFace cubeTexFaces[] = {tcu::CUBEFACE_POSITIVE_X, tcu::CUBEFACE_POSITIVE_Y,
357                                                      tcu::CUBEFACE_POSITIVE_Z, tcu::CUBEFACE_NEGATIVE_X,
358                                                      tcu::CUBEFACE_NEGATIVE_Y, tcu::CUBEFACE_NEGATIVE_Z};
359 
360         de::Random rnd(deStringHash(getName()) ^ 0x9eef603d);
361         tcu::TextureFormat texFmt      = glu::mapGLInternalFormat(m_format);
362         tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
363 
364         Texture2DShader texToFboShader(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt),
365                                        fmtInfo.valueMax - fmtInfo.valueMin, fmtInfo.valueMin);
366         TextureCubeShader cubeTexShader(glu::getSamplerCubeType(texFmt), glu::TYPE_FLOAT_VEC4);
367 
368         uint32_t texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader);
369         uint32_t cubeTexShaderID  = getCurrentContext()->createProgram(&cubeTexShader);
370 
371         // Setup shaders
372         texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
373         cubeTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
374 
375         // Framebuffers.
376         std::vector<uint32_t> fbos;
377         uint32_t tex;
378 
379         {
380             glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
381             bool isFilterable               = glu::isGLInternalColorFormatFilterable(m_format);
382             const IVec2 &size               = m_texSize;
383 
384             glGenTextures(1, &tex);
385 
386             glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
387             glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
388             glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
389             glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
390             glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
391 
392             // Generate an image and FBO for each cube face
393             for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
394                 glTexImage2D(cubeGLFaces[ndx], 0, m_format, size.x(), size.y(), 0, transferFmt.format,
395                              transferFmt.dataType, DE_NULL);
396             checkError();
397 
398             for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
399             {
400                 uint32_t layerFbo;
401 
402                 glGenFramebuffers(1, &layerFbo);
403                 glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
404                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubeGLFaces[ndx], tex, 0);
405                 checkError();
406                 checkFramebufferStatus(GL_FRAMEBUFFER);
407 
408                 fbos.push_back(layerFbo);
409             }
410         }
411 
412         // Render test images to random cube faces
413         std::vector<int> order;
414 
415         for (size_t n = 0; n < fbos.size(); n++)
416             order.push_back((int)n);
417         rnd.shuffle(order.begin(), order.end());
418 
419         DE_ASSERT(order.size() >= 4);
420         for (int ndx = 0; ndx < 4; ndx++)
421         {
422             const int face          = order[ndx];
423             const uint32_t format   = GL_RGBA;
424             const uint32_t dataType = GL_UNSIGNED_BYTE;
425             const int texW          = 128;
426             const int texH          = 128;
427             uint32_t tmpTex         = 0;
428             const uint32_t fbo      = fbos[face];
429             const IVec2 &viewport   = m_texSize;
430             tcu::TextureLevel data(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
431 
432             tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
433 
434             glGenTextures(1, &tmpTex);
435             glBindTexture(GL_TEXTURE_2D, tmpTex);
436             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
437             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
438             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
439             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
440             glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
441 
442             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
443             glViewport(0, 0, viewport.x(), viewport.y());
444             sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
445             checkError();
446 
447             // Render to framebuffer
448             {
449                 const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
450                 const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
451 
452                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
453                 glViewport(0, 0, getWidth(), getHeight());
454 
455                 glActiveTexture(GL_TEXTURE0);
456                 glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
457 
458                 cubeTexShader.setFace(cubeTexFaces[face]);
459                 cubeTexShader.setUniforms(*getCurrentContext(), cubeTexShaderID);
460 
461                 sglr::drawQuad(*getCurrentContext(), cubeTexShaderID, p0, p1);
462                 checkError();
463             }
464         }
465 
466         readPixels(dst, 0, 0, getWidth(), getHeight());
467     }
468 
469 private:
470     IVec2 m_texSize;
471 };
472 
473 class FboColorTex2DArrayCase : public FboColorbufferCase
474 {
475 public:
FboColorTex2DArrayCase(Context & context,const char * name,const char * description,uint32_t texFmt,const IVec3 & texSize)476     FboColorTex2DArrayCase(Context &context, const char *name, const char *description, uint32_t texFmt,
477                            const IVec3 &texSize)
478         : FboColorbufferCase(context, name, description, texFmt)
479         , m_texSize(texSize)
480     {
481     }
482 
483 protected:
preCheck(void)484     void preCheck(void)
485     {
486         checkFormatSupport(m_format);
487     }
488 
render(tcu::Surface & dst)489     void render(tcu::Surface &dst)
490     {
491         de::Random rnd(deStringHash(getName()) ^ 0xed607a89);
492         tcu::TextureFormat texFmt      = glu::mapGLInternalFormat(m_format);
493         tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
494 
495         Texture2DShader texToFboShader(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt),
496                                        fmtInfo.valueMax - fmtInfo.valueMin, fmtInfo.valueMin);
497         Texture2DArrayShader arrayTexShader(glu::getSampler2DArrayType(texFmt), glu::TYPE_FLOAT_VEC4);
498 
499         uint32_t texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader);
500         uint32_t arrayTexShaderID = getCurrentContext()->createProgram(&arrayTexShader);
501 
502         // Setup textures
503         texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
504         arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
505 
506         // Framebuffers.
507         std::vector<uint32_t> fbos;
508         uint32_t tex;
509 
510         {
511             glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
512             bool isFilterable               = glu::isGLInternalColorFormatFilterable(m_format);
513             const IVec3 &size               = m_texSize;
514 
515             glGenTextures(1, &tex);
516 
517             glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
518             glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
519             glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
520             glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
521             glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
522             glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST);
523             glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format,
524                          transferFmt.dataType, DE_NULL);
525 
526             // Generate an FBO for each layer
527             for (int ndx = 0; ndx < m_texSize.z(); ndx++)
528             {
529                 uint32_t layerFbo;
530 
531                 glGenFramebuffers(1, &layerFbo);
532                 glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
533                 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
534                 checkError();
535                 checkFramebufferStatus(GL_FRAMEBUFFER);
536 
537                 fbos.push_back(layerFbo);
538             }
539         }
540 
541         // Render test images to random texture layers
542         std::vector<int> order;
543 
544         for (size_t n = 0; n < fbos.size(); n++)
545             order.push_back((int)n);
546         rnd.shuffle(order.begin(), order.end());
547 
548         for (size_t ndx = 0; ndx < order.size(); ndx++)
549         {
550             const int layer         = order[ndx];
551             const uint32_t format   = GL_RGBA;
552             const uint32_t dataType = GL_UNSIGNED_BYTE;
553             const int texW          = 128;
554             const int texH          = 128;
555             uint32_t tmpTex         = 0;
556             const uint32_t fbo      = fbos[layer];
557             const IVec3 &viewport   = m_texSize;
558             tcu::TextureLevel data(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
559 
560             tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
561 
562             glGenTextures(1, &tmpTex);
563             glBindTexture(GL_TEXTURE_2D, tmpTex);
564             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
565             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
566             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
567             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
568             glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
569 
570             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
571             glViewport(0, 0, viewport.x(), viewport.y());
572             sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
573             checkError();
574 
575             // Render to framebuffer
576             {
577                 const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
578                 const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
579 
580                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
581                 glViewport(0, 0, getWidth(), getHeight());
582 
583                 glActiveTexture(GL_TEXTURE0);
584                 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
585 
586                 arrayTexShader.setLayer(layer);
587                 arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID);
588 
589                 sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1);
590                 checkError();
591             }
592         }
593 
594         readPixels(dst, 0, 0, getWidth(), getHeight());
595     }
596 
597 private:
598     IVec3 m_texSize;
599 };
600 
601 class FboColorTex3DCase : public FboColorbufferCase
602 {
603 public:
FboColorTex3DCase(Context & context,const char * name,const char * description,uint32_t texFmt,const IVec3 & texSize)604     FboColorTex3DCase(Context &context, const char *name, const char *description, uint32_t texFmt,
605                       const IVec3 &texSize)
606         : FboColorbufferCase(context, name, description, texFmt)
607         , m_texSize(texSize)
608     {
609     }
610 
611 protected:
preCheck(void)612     void preCheck(void)
613     {
614         checkFormatSupport(m_format);
615     }
616 
render(tcu::Surface & dst)617     void render(tcu::Surface &dst)
618     {
619         de::Random rnd(deStringHash(getName()) ^ 0x74d947b2);
620         tcu::TextureFormat texFmt      = glu::mapGLInternalFormat(m_format);
621         tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
622 
623         Texture2DShader texToFboShader(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt),
624                                        fmtInfo.valueMax - fmtInfo.valueMin, fmtInfo.valueMin);
625         Texture3DShader tdTexShader(glu::getSampler3DType(texFmt), glu::TYPE_FLOAT_VEC4);
626 
627         uint32_t texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader);
628         uint32_t tdTexShaderID    = getCurrentContext()->createProgram(&tdTexShader);
629 
630         // Setup shaders
631         texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
632         tdTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
633 
634         // Framebuffers.
635         std::vector<uint32_t> fbos;
636         uint32_t tex;
637 
638         {
639             glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt);
640             const IVec3 &size               = m_texSize;
641 
642             glGenTextures(1, &tex);
643 
644             glBindTexture(GL_TEXTURE_3D, tex);
645             glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
646             glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
647             glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
648             glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
649             glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
650             glTexImage3D(GL_TEXTURE_3D, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format,
651                          transferFmt.dataType, DE_NULL);
652 
653             // Generate an FBO for each layer
654             for (int ndx = 0; ndx < m_texSize.z(); ndx++)
655             {
656                 uint32_t layerFbo;
657 
658                 glGenFramebuffers(1, &layerFbo);
659                 glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
660                 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
661                 checkError();
662                 checkFramebufferStatus(GL_FRAMEBUFFER);
663 
664                 fbos.push_back(layerFbo);
665             }
666         }
667 
668         // Render test images to random texture layers
669         std::vector<int> order;
670 
671         for (size_t n = 0; n < fbos.size(); n++)
672             order.push_back((int)n);
673         rnd.shuffle(order.begin(), order.end());
674 
675         for (size_t ndx = 0; ndx < order.size(); ndx++)
676         {
677             const int layer         = order[ndx];
678             const uint32_t format   = GL_RGBA;
679             const uint32_t dataType = GL_UNSIGNED_BYTE;
680             const int texW          = 128;
681             const int texH          = 128;
682             uint32_t tmpTex         = 0;
683             const uint32_t fbo      = fbos[layer];
684             const IVec3 &viewport   = m_texSize;
685             tcu::TextureLevel data(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
686 
687             tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
688 
689             glGenTextures(1, &tmpTex);
690             glBindTexture(GL_TEXTURE_2D, tmpTex);
691             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
692             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
693             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
694             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
695             glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
696 
697             glBindFramebuffer(GL_FRAMEBUFFER, fbo);
698             glViewport(0, 0, viewport.x(), viewport.y());
699             sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
700             checkError();
701 
702             // Render to framebuffer
703             {
704                 const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
705                 const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f);
706 
707                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
708                 glViewport(0, 0, getWidth(), getHeight());
709 
710                 glActiveTexture(GL_TEXTURE0);
711                 glBindTexture(GL_TEXTURE_3D, tex);
712 
713                 tdTexShader.setDepth(float(layer) / float(m_texSize.z() - 1));
714                 tdTexShader.setUniforms(*getCurrentContext(), tdTexShaderID);
715 
716                 sglr::drawQuad(*getCurrentContext(), tdTexShaderID, p0, p1);
717                 checkError();
718             }
719         }
720 
721         readPixels(dst, 0, 0, getWidth(), getHeight());
722     }
723 
724 private:
725     IVec3 m_texSize;
726 };
727 
728 class FboBlendCase : public FboColorbufferCase
729 {
730 public:
FboBlendCase(Context & context,const char * name,const char * desc,uint32_t format,IVec2 size,uint32_t funcRGB,uint32_t funcAlpha,uint32_t srcRGB,uint32_t dstRGB,uint32_t srcAlpha,uint32_t dstAlpha)731     FboBlendCase(Context &context, const char *name, const char *desc, uint32_t format, IVec2 size, uint32_t funcRGB,
732                  uint32_t funcAlpha, uint32_t srcRGB, uint32_t dstRGB, uint32_t srcAlpha, uint32_t dstAlpha)
733         : FboColorbufferCase(context, name, desc, format)
734         , m_size(size)
735         , m_funcRGB(funcRGB)
736         , m_funcAlpha(funcAlpha)
737         , m_srcRGB(srcRGB)
738         , m_dstRGB(dstRGB)
739         , m_srcAlpha(srcAlpha)
740         , m_dstAlpha(dstAlpha)
741     {
742     }
743 
744 protected:
preCheck(void)745     void preCheck(void)
746     {
747         checkFormatSupport(m_format);
748     }
749 
render(tcu::Surface & dst)750     void render(tcu::Surface &dst)
751     {
752         // \note Assumes floating-point or fixed-point format.
753         tcu::TextureFormat fboFmt = glu::mapGLInternalFormat(m_format);
754         Texture2DShader texShader(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
755         GradientShader gradShader(glu::TYPE_FLOAT_VEC4);
756         uint32_t texShaderID  = getCurrentContext()->createProgram(&texShader);
757         uint32_t gradShaderID = getCurrentContext()->createProgram(&gradShader);
758         uint32_t fbo          = 0;
759         uint32_t rbo          = 0;
760 
761         // Setup shaders
762         texShader.setUniforms(*getCurrentContext(), texShaderID);
763         gradShader.setGradient(*getCurrentContext(), gradShaderID, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
764 
765         glGenFramebuffers(1, &fbo);
766         glGenRenderbuffers(1, &rbo);
767 
768         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
769         glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y());
770         checkError();
771 
772         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
773         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
774         checkError();
775         checkFramebufferStatus(GL_FRAMEBUFFER);
776 
777         glViewport(0, 0, m_size.x(), m_size.y());
778 
779         // Fill framebuffer with grid pattern.
780         {
781             const uint32_t format   = GL_RGBA;
782             const uint32_t dataType = GL_UNSIGNED_BYTE;
783             const int texW          = 128;
784             const int texH          = 128;
785             uint32_t gridTex        = 0;
786             tcu::TextureLevel data(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
787 
788             tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
789 
790             glGenTextures(1, &gridTex);
791             glBindTexture(GL_TEXTURE_2D, gridTex);
792             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
793             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
794             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
795             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
796             glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
797 
798             sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
799         }
800 
801         // Setup blend.
802         glEnable(GL_BLEND);
803         glBlendEquationSeparate(m_funcRGB, m_funcAlpha);
804         glBlendFuncSeparate(m_srcRGB, m_dstRGB, m_srcAlpha, m_dstAlpha);
805 
806         // Render gradient with blend.
807         sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
808 
809         readPixels(dst, 0, 0, m_size.x(), m_size.y(), fboFmt, Vec4(1.0f), Vec4(0.0f));
810     }
811 
812 private:
813     IVec2 m_size;
814     uint32_t m_funcRGB;
815     uint32_t m_funcAlpha;
816     uint32_t m_srcRGB;
817     uint32_t m_dstRGB;
818     uint32_t m_srcAlpha;
819     uint32_t m_dstAlpha;
820 };
821 
822 class FboRepeatedClearSampleTex2DCase : public FboColorbufferCase
823 {
824 public:
FboRepeatedClearSampleTex2DCase(Context & context,const char * name,const char * desc,uint32_t format)825     FboRepeatedClearSampleTex2DCase(Context &context, const char *name, const char *desc, uint32_t format)
826         : FboColorbufferCase(context, name, desc, format)
827     {
828     }
829 
830 protected:
preCheck(void)831     void preCheck(void)
832     {
833         checkFormatSupport(m_format);
834     }
835 
render(tcu::Surface & dst)836     void render(tcu::Surface &dst)
837     {
838         const tcu::TextureFormat fboFormat   = glu::mapGLInternalFormat(m_format);
839         const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
840         const int numRowsCols                = 4;
841         const int cellSize                   = 16;
842         const int fboSizes[]                 = {cellSize, cellSize * numRowsCols};
843 
844         Texture2DShader fboBlitShader(DataTypes() << glu::getSampler2DType(fboFormat), getFragmentOutputType(fboFormat),
845                                       Vec4(1.0f), Vec4(0.0f));
846         const uint32_t fboBlitShaderID = getCurrentContext()->createProgram(&fboBlitShader);
847 
848         de::Random rnd(18169662);
849         uint32_t fbos[]     = {0, 0};
850         uint32_t textures[] = {0, 0};
851 
852         glGenFramebuffers(2, &fbos[0]);
853         glGenTextures(2, &textures[0]);
854 
855         for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
856         {
857             glBindTexture(GL_TEXTURE_2D, textures[fboNdx]);
858             glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
859             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
860             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
861             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
862             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
863             checkError();
864 
865             glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
866             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
867             checkError();
868             checkFramebufferStatus(GL_FRAMEBUFFER);
869         }
870 
871         // larger fbo bound -- clear to transparent black
872         clearColorBuffer(fboFormat, Vec4(0.0f));
873 
874         fboBlitShader.setUniforms(*getCurrentContext(), fboBlitShaderID);
875         glBindTexture(GL_TEXTURE_2D, textures[0]);
876 
877         for (int cellY = 0; cellY < numRowsCols; cellY++)
878             for (int cellX = 0; cellX < numRowsCols; cellX++)
879             {
880                 const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
881 
882                 glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
883                 clearColorBuffer(fboFormat, color);
884 
885                 glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
886                 glViewport(cellX * cellSize, cellY * cellSize, cellSize, cellSize);
887                 sglr::drawQuad(*getCurrentContext(), fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
888             }
889 
890         readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
891         checkError();
892     }
893 };
894 
895 class FboRepeatedClearBlitTex2DCase : public FboColorbufferCase
896 {
897 public:
FboRepeatedClearBlitTex2DCase(Context & context,const char * name,const char * desc,uint32_t format)898     FboRepeatedClearBlitTex2DCase(Context &context, const char *name, const char *desc, uint32_t format)
899         : FboColorbufferCase(context, name, desc, format)
900     {
901     }
902 
903 protected:
preCheck(void)904     void preCheck(void)
905     {
906         checkFormatSupport(m_format);
907     }
908 
render(tcu::Surface & dst)909     void render(tcu::Surface &dst)
910     {
911         const tcu::TextureFormat fboFormat   = glu::mapGLInternalFormat(m_format);
912         const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
913         const int numRowsCols                = 4;
914         const int cellSize                   = 16;
915         const int fboSizes[]                 = {cellSize, cellSize * numRowsCols};
916 
917         de::Random rnd(18169662);
918         uint32_t fbos[]     = {0, 0};
919         uint32_t textures[] = {0, 0};
920 
921         glGenFramebuffers(2, &fbos[0]);
922         glGenTextures(2, &textures[0]);
923 
924         for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
925         {
926             glBindTexture(GL_TEXTURE_2D, textures[fboNdx]);
927             glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
928             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
929             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
930             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
931             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
932             checkError();
933 
934             glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
935             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
936             checkError();
937             checkFramebufferStatus(GL_FRAMEBUFFER);
938         }
939 
940         // larger fbo bound -- clear to transparent black
941         clearColorBuffer(fboFormat, Vec4(0.0f));
942 
943         for (int cellY = 0; cellY < numRowsCols; cellY++)
944             for (int cellX = 0; cellX < numRowsCols; cellX++)
945             {
946                 const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
947 
948                 glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
949                 clearColorBuffer(fboFormat, color);
950 
951                 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
952                 glBlitFramebuffer(0, 0, cellSize, cellSize, cellX * cellSize, cellY * cellSize, (cellX + 1) * cellSize,
953                                   (cellY + 1) * cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
954             }
955 
956         glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
957         readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
958         checkError();
959     }
960 };
961 
962 class FboRepeatedClearBlitRboCase : public FboColorbufferCase
963 {
964 public:
FboRepeatedClearBlitRboCase(Context & context,const char * name,const char * desc,uint32_t format)965     FboRepeatedClearBlitRboCase(Context &context, const char *name, const char *desc, uint32_t format)
966         : FboColorbufferCase(context, name, desc, format)
967     {
968     }
969 
970 protected:
preCheck(void)971     void preCheck(void)
972     {
973         checkFormatSupport(m_format);
974     }
975 
render(tcu::Surface & dst)976     void render(tcu::Surface &dst)
977     {
978         const tcu::TextureFormat fboFormat   = glu::mapGLInternalFormat(m_format);
979         const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat);
980         const int numRowsCols                = 4;
981         const int cellSize                   = 16;
982         const int fboSizes[]                 = {cellSize, cellSize * numRowsCols};
983 
984         de::Random rnd(18169662);
985         uint32_t fbos[] = {0, 0};
986         uint32_t rbos[] = {0, 0};
987 
988         glGenFramebuffers(2, &fbos[0]);
989         glGenRenderbuffers(2, &rbos[0]);
990 
991         for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
992         {
993             glBindRenderbuffer(GL_RENDERBUFFER, rbos[fboNdx]);
994             glRenderbufferStorage(GL_RENDERBUFFER, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
995             checkError();
996 
997             glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
998             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbos[fboNdx]);
999             checkError();
1000             checkFramebufferStatus(GL_FRAMEBUFFER);
1001         }
1002 
1003         // larger fbo bound -- clear to transparent black
1004         clearColorBuffer(fboFormat, Vec4(0.0f));
1005 
1006         for (int cellY = 0; cellY < numRowsCols; cellY++)
1007             for (int cellX = 0; cellX < numRowsCols; cellX++)
1008             {
1009                 const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
1010 
1011                 glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
1012                 clearColorBuffer(fboFormat, color);
1013 
1014                 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
1015                 glBlitFramebuffer(0, 0, cellSize, cellSize, cellX * cellSize, cellY * cellSize, (cellX + 1) * cellSize,
1016                                   (cellY + 1) * cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1017             }
1018 
1019         glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
1020         readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
1021         checkError();
1022     }
1023 };
1024 
FboColorTests(Context & context)1025 FboColorTests::FboColorTests(Context &context) : TestCaseGroup(context, "color", "Colorbuffer tests")
1026 {
1027 }
1028 
~FboColorTests(void)1029 FboColorTests::~FboColorTests(void)
1030 {
1031 }
1032 
init(void)1033 void FboColorTests::init(void)
1034 {
1035     static const uint32_t colorFormats[] = {
1036         // RGBA formats
1037         GL_RGBA32I, GL_RGBA32UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA8, GL_RGBA8I, GL_RGBA8UI, GL_SRGB8_ALPHA8, GL_RGB10_A2,
1038         GL_RGB10_A2UI, GL_RGBA4, GL_RGB5_A1,
1039 
1040         // RGB formats
1041         GL_RGB8, GL_RGB565,
1042 
1043         // RG formats
1044         GL_RG32I, GL_RG32UI, GL_RG16I, GL_RG16UI, GL_RG8, GL_RG8I, GL_RG8UI,
1045 
1046         // R formats
1047         GL_R32I, GL_R32UI, GL_R16I, GL_R16UI, GL_R8, GL_R8I, GL_R8UI,
1048 
1049         // GL_EXT_color_buffer_float
1050         GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F, GL_RG32F, GL_RG16F, GL_R32F, GL_R16F,
1051 
1052         // GL_EXT_color_buffer_half_float
1053         GL_RGB16F};
1054 
1055     // .clear
1056     {
1057         tcu::TestCaseGroup *clearGroup = new tcu::TestCaseGroup(m_testCtx, "clear", "Color clears");
1058         addChild(clearGroup);
1059 
1060         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
1061             clearGroup->addChild(
1062                 new FboColorClearCase(m_context, getFormatName(colorFormats[ndx]), "", colorFormats[ndx], 129, 117));
1063     }
1064 
1065     // .tex2d
1066     {
1067         tcu::TestCaseGroup *tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "Texture 2D tests");
1068         addChild(tex2DGroup);
1069 
1070         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1071             tex2DGroup->addChild(new FboColorMultiTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1072                                                             colorFormats[fmtNdx], IVec2(129, 117), colorFormats[fmtNdx],
1073                                                             IVec2(99, 128)));
1074     }
1075 
1076     // .texcube
1077     {
1078         tcu::TestCaseGroup *texCubeGroup = new tcu::TestCaseGroup(m_testCtx, "texcube", "Texture cube map tests");
1079         addChild(texCubeGroup);
1080 
1081         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1082             texCubeGroup->addChild(new FboColorTexCubeCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1083                                                            colorFormats[fmtNdx], IVec2(128, 128)));
1084     }
1085 
1086     // .tex2darray
1087     {
1088         tcu::TestCaseGroup *tex2DArrayGroup = new tcu::TestCaseGroup(m_testCtx, "tex2darray", "Texture 2D array tests");
1089         addChild(tex2DArrayGroup);
1090 
1091         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1092             tex2DArrayGroup->addChild(new FboColorTex2DArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1093                                                                  colorFormats[fmtNdx], IVec3(128, 128, 5)));
1094     }
1095 
1096     // .tex3d
1097     {
1098         tcu::TestCaseGroup *tex3DGroup = new tcu::TestCaseGroup(m_testCtx, "tex3d", "Texture 3D tests");
1099         addChild(tex3DGroup);
1100 
1101         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1102             tex3DGroup->addChild(new FboColorTex3DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1103                                                        colorFormats[fmtNdx], IVec3(128, 128, 5)));
1104     }
1105 
1106     // .blend
1107     {
1108         tcu::TestCaseGroup *blendGroup = new tcu::TestCaseGroup(m_testCtx, "blend", "Blending tests");
1109         addChild(blendGroup);
1110 
1111         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1112         {
1113             uint32_t format                   = colorFormats[fmtNdx];
1114             tcu::TextureFormat texFmt         = glu::mapGLInternalFormat(format);
1115             tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(texFmt.type);
1116             string fmtName                    = getFormatName(format);
1117 
1118             if (texFmt.type == tcu::TextureFormat::FLOAT || fmtClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ||
1119                 fmtClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1120                 continue; // Blending is not supported.
1121 
1122             blendGroup->addChild(new FboBlendCase(m_context, (fmtName + "_src_over").c_str(), "", format,
1123                                                   IVec2(127, 111), GL_FUNC_ADD, GL_FUNC_ADD, GL_SRC_ALPHA,
1124                                                   GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE));
1125         }
1126     }
1127 
1128     // .repeated_clear
1129     {
1130         tcu::TestCaseGroup *const repeatedClearGroup =
1131             new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated clears and blits");
1132         addChild(repeatedClearGroup);
1133 
1134         // .sample.tex2d
1135         {
1136             tcu::TestCaseGroup *const sampleGroup = new tcu::TestCaseGroup(m_testCtx, "sample", "Read by sampling");
1137             repeatedClearGroup->addChild(sampleGroup);
1138 
1139             tcu::TestCaseGroup *const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture");
1140             sampleGroup->addChild(tex2DGroup);
1141 
1142             for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1143                 tex2DGroup->addChild(new FboRepeatedClearSampleTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]),
1144                                                                          "", colorFormats[fmtNdx]));
1145         }
1146 
1147         // .blit
1148         {
1149             tcu::TestCaseGroup *const blitGroup = new tcu::TestCaseGroup(m_testCtx, "blit", "Blitted");
1150             repeatedClearGroup->addChild(blitGroup);
1151 
1152             // .tex2d
1153             {
1154                 tcu::TestCaseGroup *const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture");
1155                 blitGroup->addChild(tex2DGroup);
1156 
1157                 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1158                     tex2DGroup->addChild(new FboRepeatedClearBlitTex2DCase(
1159                         m_context, getFormatName(colorFormats[fmtNdx]), "", colorFormats[fmtNdx]));
1160             }
1161 
1162             // .rbo
1163             {
1164                 tcu::TestCaseGroup *const rboGroup = new tcu::TestCaseGroup(m_testCtx, "rbo", "Renderbuffer");
1165                 blitGroup->addChild(rboGroup);
1166 
1167                 for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1168                     rboGroup->addChild(new FboRepeatedClearBlitRboCase(m_context, getFormatName(colorFormats[fmtNdx]),
1169                                                                        "", colorFormats[fmtNdx]));
1170             }
1171         }
1172     }
1173 }
1174 
1175 } // namespace Functional
1176 } // namespace gles3
1177 } // namespace deqp
1178