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