Merge "Fix color change verification in dithering tests" into nougat-cts-dev am:...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fFboRenderTest.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 Framebuffer Object Tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es3fFboRenderTest.hpp"
25 #include "sglrContextUtil.hpp"
26 #include "sglrGLContext.hpp"
27 #include "sglrReferenceContext.hpp"
28 #include "es3fFboTestUtil.hpp"
29 #include "tcuSurface.hpp"
30 #include "tcuImageCompare.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "tcuVectorUtil.hpp"
33 #include "tcuRenderTarget.hpp"
34 #include "gluPixelTransfer.hpp"
35 #include "gluTextureUtil.hpp"
36 #include "gluStrUtil.hpp"
37 #include "deRandom.h"
38 #include "deString.h"
39 #include "glwDefs.hpp"
40 #include "glwEnums.hpp"
41
42 #include <sstream>
43
44 using std::vector;
45 using std::string;
46 using tcu::TestLog;
47 using tcu::Vec2;
48 using tcu::Vec3;
49 using tcu::Vec4;
50 using tcu::IVec2;
51 using tcu::IVec3;
52 using tcu::IVec4;
53 using tcu::RGBA;
54 using tcu::Surface;
55
56 namespace deqp
57 {
58 namespace gles3
59 {
60 namespace Functional
61 {
62
63 using glw::GLenum;
64 using namespace FboTestUtil;
65
66 class FboConfig
67 {
68 public:
69         FboConfig (deUint32 buffers_, deUint32 colorType_, deUint32 colorFormat_, deUint32 depthStencilType_, deUint32 depthStencilFormat_, int width_ = 0, int height_ = 0, int samples_ = 0)
70                 : buffers                               (buffers_)
71                 , colorType                             (colorType_)
72                 , colorFormat                   (colorFormat_)
73                 , depthStencilType              (depthStencilType_)
74                 , depthStencilFormat    (depthStencilFormat_)
75                 , width                                 (width_)
76                 , height                                (height_)
77                 , samples                               (samples_)
78         {
79         }
80
81         FboConfig (void)
82                 : buffers                               (0)
83                 , colorType                             (GL_NONE)
84                 , colorFormat                   (GL_NONE)
85                 , depthStencilType              (GL_NONE)
86                 , depthStencilFormat    (GL_NONE)
87                 , width                                 (0)
88                 , height                                (0)
89                 , samples                               (0)
90         {
91         }
92
93         std::string                             getName                 (void) const;
94
95         deUint32                                buffers;                //!< Buffer bit mask (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|...)
96
97         GLenum                                  colorType;              //!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER
98         GLenum                                  colorFormat;    //!< Internal format for color buffer texture or renderbuffer
99
100         GLenum                                  depthStencilType;
101         GLenum                                  depthStencilFormat;
102
103         int                                             width;
104         int                                             height;
105         int                                             samples;
106 };
107
108 static const char* getTypeName (GLenum type)
109 {
110         switch (type)
111         {
112                 case GL_TEXTURE_2D:             return "tex2d";
113                 case GL_RENDERBUFFER:   return "rbo";
114                 default:
115                         TCU_FAIL("Unknown type");
116         }
117 }
118
119 std::string FboConfig::getName (void) const
120 {
121         std::ostringstream name;
122
123         DE_ASSERT(buffers & GL_COLOR_BUFFER_BIT);
124         name << getTypeName(colorType) << "_" << getFormatName(colorFormat);
125
126         if (buffers & GL_DEPTH_BUFFER_BIT)
127                 name << "_depth";
128         if (buffers & GL_STENCIL_BUFFER_BIT)
129                 name << "_stencil";
130
131         if (buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))
132                 name << "_" << getTypeName(depthStencilType) << "_" << getFormatName(depthStencilFormat);
133
134         return name.str();
135 }
136
137 class Framebuffer
138 {
139 public:
140                                                 Framebuffer                             (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorBuffer = 0, deUint32 depthStencilBuffer = 0);
141                                                 ~Framebuffer                    (void);
142
143         const FboConfig&        getConfig                               (void) const { return m_config;                         }
144         deUint32                        getFramebuffer                  (void) const { return m_framebuffer;            }
145         deUint32                        getColorBuffer                  (void) const { return m_colorBuffer;            }
146         deUint32                        getDepthStencilBuffer   (void) const { return m_depthStencilBuffer;     }
147
148         void                            checkCompleteness               (void);
149
150 private:
151         deUint32                        createTex2D                             (deUint32 name, GLenum format, int width, int height);
152         deUint32                        createRbo                               (deUint32 name, GLenum format, int width, int height);
153         void                            destroyBuffer                   (deUint32 name, GLenum type);
154
155         FboConfig                       m_config;
156         sglr::Context&          m_context;
157         deUint32                        m_framebuffer;
158         deUint32                        m_colorBuffer;
159         deUint32                        m_depthStencilBuffer;
160 };
161
162 static std::vector<std::string> getEnablingExtensions (deUint32 format)
163 {
164         std::vector<std::string> out;
165
166         switch (format)
167         {
168                 case GL_RGB16F:
169                         out.push_back("GL_EXT_color_buffer_half_float");
170                         break;
171
172                 case GL_RGBA16F:
173                 case GL_RG16F:
174                 case GL_R16F:
175                         out.push_back("GL_EXT_color_buffer_half_float");
176
177                 case GL_RGBA32F:
178                 case GL_RGB32F:
179                 case GL_R11F_G11F_B10F:
180                 case GL_RG32F:
181                 case GL_R32F:
182                         out.push_back("GL_EXT_color_buffer_float");
183
184                 default:
185                         break;
186         }
187
188         return out;
189 }
190
191 static bool isExtensionSupported (sglr::Context& context, const char* name)
192 {
193         std::istringstream extensions(context.getString(GL_EXTENSIONS));
194         std::string extension;
195
196         while (std::getline(extensions, extension, ' '))
197         {
198                 if (extension == name)
199                         return true;
200         }
201
202         return false;
203 }
204
205 static bool isAnyExtensionSupported (sglr::Context& context, const std::vector<std::string>& requiredExts)
206 {
207         if (requiredExts.empty())
208                 return true;
209
210         for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++)
211         {
212                 const std::string& extension = *iter;
213
214                 if (isExtensionSupported(context, extension.c_str()))
215                         return true;
216         }
217
218         return false;
219 }
220
221 template<typename T>
222 static std::string join (const std::vector<T>& list, const std::string& sep)
223 {
224         std::ostringstream      out;
225
226         for (typename std::vector<T>::const_iterator iter = list.begin(); iter != list.end(); iter++)
227         {
228                 if (iter != list.begin())
229                         out << sep;
230                 out << *iter;
231         }
232
233         return out.str();
234 }
235
236 static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat)
237 {
238         const std::vector<std::string> requiredExts = getEnablingExtensions(sizedFormat);
239
240         if (!isAnyExtensionSupported(context, requiredExts))
241         {
242                 std::string     errMsg  = "Format not supported, requires "
243                                                         + ((requiredExts.size() == 1) ? requiredExts[0] : " one of the following: " + join(requiredExts, ", "));
244
245                 throw tcu::NotSupportedError(errMsg);
246         }
247 }
248
249 Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorBufferName, deUint32 depthStencilBufferName)
250         : m_config                              (config)
251         , m_context                             (context)
252         , m_framebuffer                 (fbo)
253         , m_colorBuffer                 (0)
254         , m_depthStencilBuffer  (0)
255 {
256         // Verify that color format is supported
257         checkColorFormatSupport(context, config.colorFormat);
258
259         if (m_framebuffer == 0)
260                 context.genFramebuffers(1, &m_framebuffer);
261         context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
262
263         if (m_config.buffers & (GL_COLOR_BUFFER_BIT))
264         {
265                 switch (m_config.colorType)
266                 {
267                         case GL_TEXTURE_2D:
268                                 m_colorBuffer = createTex2D(colorBufferName, m_config.colorFormat, width, height);
269                                 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0);
270                                 break;
271
272                         case GL_RENDERBUFFER:
273                                 m_colorBuffer = createRbo(colorBufferName, m_config.colorFormat, width, height);
274                                 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);
275                                 break;
276
277                         default:
278                                 TCU_FAIL("Unsupported type");
279                 }
280         }
281
282         if (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))
283         {
284                 switch (m_config.depthStencilType)
285                 {
286                         case GL_TEXTURE_2D:             m_depthStencilBuffer = createTex2D(depthStencilBufferName, m_config.depthStencilFormat, width, height);         break;
287                         case GL_RENDERBUFFER:   m_depthStencilBuffer = createRbo(depthStencilBufferName, m_config.depthStencilFormat, width, height);           break;
288                         default:
289                                 TCU_FAIL("Unsupported type");
290                 }
291         }
292
293         for (int ndx = 0; ndx < 2; ndx++)
294         {
295                 deUint32        bit             = ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
296                 deUint32        point   = ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
297
298                 if ((m_config.buffers & bit) == 0)
299                         continue; /* Not used. */
300
301                 switch (m_config.depthStencilType)
302                 {
303                         case GL_TEXTURE_2D:             context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, m_depthStencilBuffer, 0);    break;
304                         case GL_RENDERBUFFER:   context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, m_depthStencilBuffer);  break;
305                         default:
306                                 DE_ASSERT(false);
307                 }
308         }
309
310         GLenum err = m_context.getError();
311         if (err != GL_NO_ERROR)
312                 throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), "", __FILE__, __LINE__);
313
314         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
315 }
316
317 Framebuffer::~Framebuffer (void)
318 {
319         m_context.deleteFramebuffers(1, &m_framebuffer);
320         destroyBuffer(m_colorBuffer, m_config.colorType);
321         destroyBuffer(m_depthStencilBuffer, m_config.depthStencilType);
322 }
323
324 void Framebuffer::checkCompleteness (void)
325 {
326         m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
327         GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER);
328         m_context.bindFramebuffer(GL_FRAMEBUFFER, 0);
329         if (status != GL_FRAMEBUFFER_COMPLETE)
330                 throw FboIncompleteException(status, __FILE__, __LINE__);
331 }
332
333 deUint32 Framebuffer::createTex2D (deUint32 name, GLenum format, int width, int height)
334 {
335         if (name == 0)
336                 m_context.genTextures(1, &name);
337
338         m_context.bindTexture(GL_TEXTURE_2D, name);
339         m_context.texImage2D(GL_TEXTURE_2D, 0, format, width, height);
340
341         if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height))
342         {
343                 // Set wrap mode to clamp for NPOT FBOs
344                 m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
345                 m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
346         }
347
348         m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
349         m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
350
351         return name;
352 }
353
354 deUint32 Framebuffer::createRbo (deUint32 name, GLenum format, int width, int height)
355 {
356         if (name == 0)
357                 m_context.genRenderbuffers(1, &name);
358
359         m_context.bindRenderbuffer(GL_RENDERBUFFER, name);
360         m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
361
362         return name;
363 }
364
365 void Framebuffer::destroyBuffer (deUint32 name, GLenum type)
366 {
367         if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP)
368                 m_context.deleteTextures(1, &name);
369         else if (type == GL_RENDERBUFFER)
370                 m_context.deleteRenderbuffers(1, &name);
371         else
372                 DE_ASSERT(type == GL_NONE);
373 }
374
375 static void createMetaballsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
376 {
377         tcu::TextureFormat      texFormat       = glu::mapGLTransferFormat(format, dataType);
378         tcu::TextureLevel       level           (texFormat, width, height);
379
380         tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height);
381
382         context.bindTexture(GL_TEXTURE_2D, name);
383         context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
384         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
385 }
386
387 static void createQuadsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
388 {
389         tcu::TextureFormat      texFormat       = glu::mapGLTransferFormat(format, dataType);
390         tcu::TextureLevel       level           (texFormat, width, height);
391
392         tcu::fillWithRGBAQuads(level.getAccess());
393
394         context.bindTexture(GL_TEXTURE_2D, name);
395         context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
396         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
397 }
398
399 class FboRenderCase : public TestCase
400 {
401 public:
402                                                                 FboRenderCase                   (Context& context, const char* name, const char* description, const FboConfig& config);
403         virtual                                         ~FboRenderCase                  (void) {}
404
405         virtual IterateResult           iterate                                 (void);
406         virtual void                            render                                  (sglr::Context& fboContext, Surface& dst) = DE_NULL;
407
408         bool                                            compare                                 (const tcu::Surface& reference, const tcu::Surface& result);
409
410 protected:
411         const FboConfig                         m_config;
412 };
413
414 FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config)
415         : TestCase      (context, name, description)
416         , m_config      (config)
417 {
418 }
419
420 TestCase::IterateResult FboRenderCase::iterate (void)
421 {
422         tcu::Vec4                                       clearColor                              = tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f);
423         glu::RenderContext&                     renderCtx                               = m_context.getRenderContext();
424         const tcu::RenderTarget&        renderTarget                    = renderCtx.getRenderTarget();
425         tcu::TestLog&                           log                                             = m_testCtx.getLog();
426         const char*                                     failReason                              = DE_NULL;
427
428         // Position & size for context
429         deRandom rnd;
430         deRandom_init(&rnd, deStringHash(getName()));
431
432         int             width   = deMin32(renderTarget.getWidth(), 128);
433         int             height  = deMin32(renderTarget.getHeight(), 128);
434         int             xMax    = renderTarget.getWidth()-width+1;
435         int             yMax    = renderTarget.getHeight()-height+1;
436         int             x               = deRandom_getUint32(&rnd) % xMax;
437         int             y               = deRandom_getUint32(&rnd) % yMax;
438
439         tcu::Surface    gles3Frame      (width, height);
440         tcu::Surface    refFrame        (width, height);
441         GLenum                  gles3Error;
442         GLenum                  refError;
443
444         // Render using GLES3
445         try
446         {
447                 sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
448
449                 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
450                 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
451
452                 render(context, gles3Frame); // Call actual render func
453                 gles3Error = context.getError();
454         }
455         catch (const FboIncompleteException& e)
456         {
457                 if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
458                 {
459                         // Mark test case as unsupported
460                         log << e;
461                         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
462                         return STOP;
463                 }
464                 else
465                         throw; // Propagate error
466         }
467
468         // Render reference image
469         {
470                 sglr::ReferenceContextBuffers   buffers (tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height);
471                 sglr::ReferenceContext                  context (sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
472
473                 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
474                 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
475
476                 render(context, refFrame);
477                 refError = context.getError();
478         }
479
480         // Compare error codes
481         bool errorCodesOk = (gles3Error == refError);
482
483         if (!errorCodesOk)
484         {
485                 log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles3Error) << ", expected " << glu::getErrorStr(refError) << tcu::TestLog::EndMessage;
486                 failReason = "Got unexpected error";
487         }
488
489         // Compare images
490         bool imagesOk = compare(refFrame, gles3Frame);
491
492         if (!imagesOk && !failReason)
493                 failReason = "Image comparison failed";
494
495         // Store test result
496         bool isOk = errorCodesOk && imagesOk;
497         m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
498                                                         isOk ? "Pass"                           : failReason);
499
500         return STOP;
501 }
502
503 bool FboRenderCase::compare (const tcu::Surface& reference, const tcu::Surface& result)
504 {
505         const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_config.colorFormat), tcu::RGBA(12, 12, 12, 12)));
506
507         return tcu::bilinearCompare(m_testCtx.getLog(), "ComparisonResult", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
508 }
509
510 namespace FboCases
511 {
512
513 class StencilClearsTest : public FboRenderCase
514 {
515 public:
516                                                 StencilClearsTest               (Context& context, const FboConfig& config);
517         virtual                         ~StencilClearsTest              (void) {};
518
519         void                            render                                  (sglr::Context& context, Surface& dst);
520 };
521
522 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
523         : FboRenderCase (context, config.getName().c_str(), "Stencil clears", config)
524 {
525 }
526
527 void StencilClearsTest::render (sglr::Context& context, Surface& dst)
528 {
529         tcu::TextureFormat              colorFormat                     = glu::mapGLInternalFormat(m_config.colorFormat);
530         glu::DataType                   fboSamplerType          = glu::getSampler2DType(colorFormat);
531         glu::DataType                   fboOutputType           = getFragmentOutputType(colorFormat);
532         tcu::TextureFormatInfo  fboRangeInfo            = tcu::getTextureFormatInfo(colorFormat);
533         Vec4                                    fboOutScale                     = fboRangeInfo.valueMax - fboRangeInfo.valueMin;
534         Vec4                                    fboOutBias                      = fboRangeInfo.valueMin;
535
536         Texture2DShader                 texToFboShader          (DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
537         Texture2DShader                 texFromFboShader        (DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
538
539         deUint32                                texToFboShaderID        = context.createProgram(&texToFboShader);
540         deUint32                                texFromFboShaderID      = context.createProgram(&texFromFboShader);
541
542         deUint32                                metaballsTex            = 1;
543         deUint32                                quadsTex                        = 2;
544         int                                             width                           = 128;
545         int                                             height                          = 128;
546
547         texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
548         texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
549
550         createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
551         createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
552
553         Framebuffer fbo(context, m_config, width, height);
554         fbo.checkCompleteness();
555
556         // Bind framebuffer and clear
557         context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
558         context.viewport(0, 0, width, height);
559         context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
560         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
561
562         // Do stencil clears
563         context.enable(GL_SCISSOR_TEST);
564         context.scissor(10, 16, 32, 120);
565         context.clearStencil(1);
566         context.clear(GL_STENCIL_BUFFER_BIT);
567         context.scissor(16, 32, 100, 64);
568         context.clearStencil(2);
569         context.clear(GL_STENCIL_BUFFER_BIT);
570         context.disable(GL_SCISSOR_TEST);
571
572         // Draw 2 textures with stecil tests
573         context.enable(GL_STENCIL_TEST);
574
575         context.bindTexture(GL_TEXTURE_2D, quadsTex);
576         context.stencilFunc(GL_EQUAL, 1, 0xffu);
577
578         texToFboShader.setUniforms(context, texToFboShaderID);
579         sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
580
581         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
582         context.stencilFunc(GL_EQUAL, 2, 0xffu);
583
584         texToFboShader.setUniforms(context, texToFboShaderID);
585         sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
586
587         context.disable(GL_STENCIL_TEST);
588
589         if (fbo.getConfig().colorType == GL_TEXTURE_2D)
590         {
591                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
592                 context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
593                 context.viewport(0, 0, context.getWidth(), context.getHeight());
594
595                 texFromFboShader.setUniforms(context, texFromFboShaderID);
596                 sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
597
598                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
599         }
600         else
601                 readPixels(context, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
602 }
603
604 class SharedColorbufferTest : public FboRenderCase
605 {
606 public:
607                                                 SharedColorbufferTest                   (Context& context, const FboConfig& config);
608         virtual                         ~SharedColorbufferTest                  (void) {};
609
610         void                            render                                                  (sglr::Context& context, Surface& dst);
611 };
612
613 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
614         : FboRenderCase (context, config.getName().c_str(), "Shared colorbuffer", config)
615 {
616 }
617
618 void SharedColorbufferTest::render (sglr::Context& context, Surface& dst)
619 {
620         Texture2DShader                 texShader               (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
621         FlatColorShader                 flatShader              (glu::TYPE_FLOAT_VEC4);
622         deUint32                                texShaderID             = context.createProgram(&texShader);
623         deUint32                                flatShaderID    = context.createProgram(&flatShader);
624
625         int                                             width                   = 128;
626         int                                             height                  = 128;
627         deUint32                                quadsTex                = 1;
628         deUint32                                metaballsTex    = 2;
629         bool                                    stencil                 = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
630
631         context.disable(GL_DITHER);
632
633         // Textures
634         createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
635         createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
636
637         context.viewport(0, 0, width, height);
638
639         // Fbo A
640         Framebuffer fboA(context, m_config, width, height);
641         fboA.checkCompleteness();
642
643         // Fbo B - don't create colorbuffer
644         FboConfig cfg = m_config;
645         cfg.buffers             &= ~GL_COLOR_BUFFER_BIT;
646         cfg.colorType    = GL_NONE;
647         cfg.colorFormat  = GL_NONE;
648         Framebuffer fboB(context, cfg, width, height);
649
650         // Attach color buffer from fbo A
651         context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
652         switch (m_config.colorType)
653         {
654                 case GL_TEXTURE_2D:
655                         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorBuffer(), 0);
656                         break;
657
658                 case GL_RENDERBUFFER:
659                         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorBuffer());
660                         break;
661
662                 default:
663                         DE_ASSERT(DE_FALSE);
664         }
665
666         // Clear depth and stencil in fbo B
667         context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
668
669         // Render quads to fbo 1, with depth 0.0
670         context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
671         context.bindTexture(GL_TEXTURE_2D, quadsTex);
672         context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
673         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
674
675         if (stencil)
676         {
677                 // Stencil to 1 in fbo A
678                 context.clearStencil(1);
679                 context.clear(GL_STENCIL_BUFFER_BIT);
680         }
681
682         texShader.setUniforms(context, texShaderID);
683
684         context.enable(GL_DEPTH_TEST);
685         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
686         context.disable(GL_DEPTH_TEST);
687
688         // Blend metaballs to fbo 2
689         context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
690         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
691         context.enable(GL_BLEND);
692         context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
693         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
694
695         // Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
696         context.bindTexture(GL_TEXTURE_2D, quadsTex);
697         context.enable(GL_DEPTH_TEST);
698         sglr::drawQuad(context, texShaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
699         context.disable(GL_DEPTH_TEST);
700
701         if (stencil)
702         {
703                 flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
704
705                 // Clear subset of stencil buffer to 1
706                 context.enable(GL_SCISSOR_TEST);
707                 context.scissor(10, 10, 12, 25);
708                 context.clearStencil(1);
709                 context.clear(GL_STENCIL_BUFFER_BIT);
710                 context.disable(GL_SCISSOR_TEST);
711
712                 // Render quad with stencil mask == 1
713                 context.enable(GL_STENCIL_TEST);
714                 context.stencilFunc(GL_EQUAL, 1, 0xffu);
715                 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
716                 context.disable(GL_STENCIL_TEST);
717         }
718
719         // Get results
720         if (fboA.getConfig().colorType == GL_TEXTURE_2D)
721         {
722                 texShader.setUniforms(context, texShaderID);
723
724                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
725                 context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer());
726                 context.viewport(0, 0, context.getWidth(), context.getHeight());
727                 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
728                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
729         }
730         else
731                 readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(fboA.getConfig().colorFormat), Vec4(1.0f), Vec4(0.0f));
732 }
733
734 class SharedColorbufferClearsTest : public FboRenderCase
735 {
736 public:
737                                         SharedColorbufferClearsTest             (Context& context, const FboConfig& config);
738         virtual                 ~SharedColorbufferClearsTest    (void) {}
739
740         void                    render                                                  (sglr::Context& context, Surface& dst);
741 };
742
743 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
744         : FboRenderCase (context, config.getName().c_str(), "Shared colorbuffer clears", config)
745 {
746 }
747
748 void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
749 {
750         tcu::TextureFormat              colorFormat             = glu::mapGLInternalFormat(m_config.colorFormat);
751         glu::DataType                   fboSamplerType  = glu::getSampler2DType(colorFormat);
752         int                                             width                   = 128;
753         int                                             height                  = 128;
754         deUint32                                colorbuffer             = 1;
755
756         // Check for format support.
757         checkColorFormatSupport(context, m_config.colorFormat);
758
759         // Single colorbuffer
760         if (m_config.colorType == GL_TEXTURE_2D)
761         {
762                 context.bindTexture(GL_TEXTURE_2D, colorbuffer);
763                 context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorFormat, width, height);
764                 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
765                 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
766         }
767         else
768         {
769                 DE_ASSERT(m_config.colorType == GL_RENDERBUFFER);
770                 context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
771                 context.renderbufferStorage(GL_RENDERBUFFER, m_config.colorFormat, width, height);
772         }
773
774         // Multiple framebuffers sharing the colorbuffer
775         for (int fbo = 1; fbo <= 3; fbo++)
776         {
777                 context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
778
779                 if (m_config.colorType == GL_TEXTURE_2D)
780                         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
781                 else
782                         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
783         }
784
785         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
786
787         // Check completeness
788         {
789                 GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
790                 if (status != GL_FRAMEBUFFER_COMPLETE)
791                         throw FboIncompleteException(status, __FILE__, __LINE__);
792         }
793
794         // Render to them
795         context.viewport(0, 0, width, height);
796         context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
797         context.clear(GL_COLOR_BUFFER_BIT);
798
799         context.enable(GL_SCISSOR_TEST);
800
801         context.bindFramebuffer(GL_FRAMEBUFFER, 2);
802         context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
803         context.scissor(10, 10, 64, 64);
804         context.clear(GL_COLOR_BUFFER_BIT);
805         context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
806         context.scissor(60, 60, 40, 20);
807         context.clear(GL_COLOR_BUFFER_BIT);
808
809         context.bindFramebuffer(GL_FRAMEBUFFER, 3);
810         context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
811         context.scissor(20, 20, 100, 10);
812         context.clear(GL_COLOR_BUFFER_BIT);
813
814         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
815         context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
816         context.scissor(20, 20, 5, 100);
817         context.clear(GL_COLOR_BUFFER_BIT);
818
819         context.disable(GL_SCISSOR_TEST);
820
821         if (m_config.colorType == GL_TEXTURE_2D)
822         {
823                 Texture2DShader shader(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
824                 deUint32 shaderID = context.createProgram(&shader);
825
826                 shader.setUniforms(context, shaderID);
827
828                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
829                 context.viewport(0, 0, context.getWidth(), context.getHeight());
830                 sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
831                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
832         }
833         else
834                 readPixels(context, dst, 0, 0, width, height, colorFormat, Vec4(1.0f), Vec4(0.0f));
835 }
836
837 class SharedDepthStencilTest : public FboRenderCase
838 {
839 public:
840                                         SharedDepthStencilTest          (Context& context, const FboConfig& config);
841         virtual                 ~SharedDepthStencilTest         (void) {};
842
843         static bool             isConfigSupported                       (const FboConfig& config);
844         void                    render                                          (sglr::Context& context, Surface& dst);
845 };
846
847 SharedDepthStencilTest::SharedDepthStencilTest (Context& context, const FboConfig& config)
848         : FboRenderCase (context, config.getName().c_str(), "Shared depth/stencilbuffer", config)
849 {
850 }
851
852 bool SharedDepthStencilTest::isConfigSupported (const FboConfig& config)
853 {
854         return (config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0;
855 }
856
857 void SharedDepthStencilTest::render (sglr::Context& context, Surface& dst)
858 {
859         Texture2DShader texShader               (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
860         FlatColorShader flatShader              (glu::TYPE_FLOAT_VEC4);
861         deUint32                texShaderID             = context.createProgram(&texShader);
862         deUint32                flatShaderID    = context.createProgram(&flatShader);
863         int                             width                   = 128;
864         int                             height                  = 128;
865 //      bool                    depth                   = (m_config.buffers & GL_DEPTH_BUFFER_BIT) != 0;
866         bool                    stencil                 = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
867
868         // Textures
869         deUint32 metaballsTex   = 5;
870         deUint32 quadsTex               = 6;
871         createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
872         createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
873
874         context.viewport(0, 0, width, height);
875
876         // Fbo A
877         Framebuffer fboA(context, m_config, width, height);
878         fboA.checkCompleteness();
879
880         // Fbo B
881         FboConfig cfg = m_config;
882         cfg.buffers                             &= ~(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
883         cfg.depthStencilType     = GL_NONE;
884         cfg.depthStencilFormat   = GL_NONE;
885         Framebuffer fboB(context, cfg, width, height);
886
887         // Bind depth/stencil buffers from fbo A to fbo B
888         context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
889         for (int ndx = 0; ndx < 2; ndx++)
890         {
891                 deUint32        bit             = ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT;
892                 deUint32        point   = ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
893
894                 if ((m_config.buffers & bit) == 0)
895                         continue;
896
897                 switch (m_config.depthStencilType)
898                 {
899                         case GL_TEXTURE_2D:             context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, fboA.getDepthStencilBuffer(), 0);    break;
900                         case GL_RENDERBUFFER:   context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, fboA.getDepthStencilBuffer());  break;
901                         default:
902                                 TCU_FAIL("Not implemented");
903                 }
904         }
905
906         // Setup uniforms
907         texShader.setUniforms(context, texShaderID);
908
909         // Clear color to red and stencil to 1 in fbo B.
910         context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
911         context.clearStencil(1);
912         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
913
914         context.enable(GL_DEPTH_TEST);
915
916         // Render quad to fbo A
917         context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
918         context.bindTexture(GL_TEXTURE_2D, quadsTex);
919         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
920
921         if (stencil)
922         {
923                 // Clear subset of stencil buffer to 0 in fbo A
924                 context.enable(GL_SCISSOR_TEST);
925                 context.scissor(10, 10, 12, 25);
926                 context.clearStencil(0);
927                 context.clear(GL_STENCIL_BUFFER_BIT);
928                 context.disable(GL_SCISSOR_TEST);
929         }
930
931         // Render metaballs to fbo B
932         context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
933         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
934         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
935
936         context.disable(GL_DEPTH_TEST);
937
938         if (stencil)
939         {
940                 // Render quad with stencil mask == 0
941                 context.enable(GL_STENCIL_TEST);
942                 context.stencilFunc(GL_EQUAL, 0, 0xffu);
943                 context.useProgram(flatShaderID);
944                 flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
945                 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
946                 context.disable(GL_STENCIL_TEST);
947         }
948
949         if (m_config.colorType == GL_TEXTURE_2D)
950         {
951                 // Render both to screen
952                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
953                 context.viewport(0, 0, context.getWidth(), context.getHeight());
954                 context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer());
955                 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
956                 context.bindTexture(GL_TEXTURE_2D, fboB.getColorBuffer());
957                 sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
958
959                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
960         }
961         else
962         {
963                 // Read results from fbo B
964                 readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(m_config.colorFormat), Vec4(1.0f), Vec4(0.0f));
965         }
966 }
967
968 #if 0
969 class TexSubImageAfterRenderTest : public FboRenderCase
970 {
971 public:
972                                         TexSubImageAfterRenderTest              (Context& context, const FboConfig& config);
973         virtual                 ~TexSubImageAfterRenderTest             (void) {}
974
975         void                    render                                                  (sglr::Context& context, Surface& dst);
976 };
977
978 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
979         : FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
980 {
981 }
982
983 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
984 {
985         using sglr::TexturedQuadOp;
986
987         bool isRGBA = true;
988
989         Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
990         tcu::SurfaceUtil::fillWithFourQuads(fourQuads);
991
992         Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
993         tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);
994
995         deUint32 fourQuadsTex = 1;
996         context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
997         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
998         context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads);
999
1000         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1001
1002         deUint32 fboTex = 2;
1003         context.bindTexture(GL_TEXTURE_2D, fboTex);
1004         context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1005         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1006         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1007
1008         // Render to fbo
1009         context.viewport(0, 0, 128, 128);
1010         context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1011         context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1012
1013         // Update texture using TexSubImage2D
1014         context.bindTexture(GL_TEXTURE_2D, fboTex);
1015         context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);
1016
1017         // Draw to screen
1018         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1019         context.viewport(0, 0, context.getWidth(), context.getHeight());
1020         context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1021         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1022 }
1023
1024 class TexSubImageBetweenRenderTest : public FboRenderCase
1025 {
1026 public:
1027                                         TexSubImageBetweenRenderTest            (Context& context, const FboConfig& config);
1028         virtual                 ~TexSubImageBetweenRenderTest           (void) {}
1029
1030         void                    render                                                          (sglr::Context& context, Surface& dst);
1031 };
1032
1033 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
1034         : FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
1035 {
1036 }
1037
1038 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
1039 {
1040         using sglr::TexturedQuadOp;
1041         using sglr::BlendTextureOp;
1042
1043         bool isRGBA = true;
1044
1045         Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64);
1046         tcu::SurfaceUtil::fillWithFourQuads(fourQuads);
1047
1048         Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64);
1049         tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3);
1050
1051         Surface metaballs2(Surface::PIXELFORMAT_RGBA, 64, 64);
1052         tcu::SurfaceUtil::fillWithMetaballs(metaballs2, 5, 4);
1053
1054         deUint32 metaballsTex = 3;
1055         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1056         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1057         context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, metaballs2);
1058
1059         deUint32 fourQuadsTex = 1;
1060         context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1061         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1062         context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads);
1063
1064         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1065
1066         deUint32 fboTex = 2;
1067         context.bindTexture(GL_TEXTURE_2D, fboTex);
1068         context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1069         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1070         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1071
1072         // Render to fbo
1073         context.viewport(0, 0, 128, 128);
1074         context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1075         context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1076
1077         // Update texture using TexSubImage2D
1078         context.bindTexture(GL_TEXTURE_2D, fboTex);
1079         context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs);
1080
1081         // Render again to fbo
1082         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1083         context.draw(BlendTextureOp(0));
1084
1085         // Draw to screen
1086         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1087         context.viewport(0, 0, context.getWidth(), context.getHeight());
1088         context.bindTexture(GL_TEXTURE_2D, fboTex);
1089         context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0));
1090
1091         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1092 }
1093 #endif
1094
1095 class ResizeTest : public FboRenderCase
1096 {
1097 public:
1098                                         ResizeTest                              (Context& context, const FboConfig& config);
1099         virtual                 ~ResizeTest                             (void) {}
1100
1101         void                    render                                  (sglr::Context& context, Surface& dst);
1102 };
1103
1104 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
1105         : FboRenderCase (context, config.getName().c_str(), "Resize framebuffer", config)
1106 {
1107 }
1108
1109 void ResizeTest::render (sglr::Context& context, Surface& dst)
1110 {
1111         tcu::TextureFormat              colorFormat                     = glu::mapGLInternalFormat(m_config.colorFormat);
1112         glu::DataType                   fboSamplerType          = glu::getSampler2DType(colorFormat);
1113         glu::DataType                   fboOutputType           = getFragmentOutputType(colorFormat);
1114         tcu::TextureFormatInfo  fboRangeInfo            = tcu::getTextureFormatInfo(colorFormat);
1115         Vec4                                    fboOutScale                     = fboRangeInfo.valueMax - fboRangeInfo.valueMin;
1116         Vec4                                    fboOutBias                      = fboRangeInfo.valueMin;
1117
1118         Texture2DShader                 texToFboShader          (DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
1119         Texture2DShader                 texFromFboShader        (DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
1120         FlatColorShader                 flatShader                      (fboOutputType);
1121         deUint32                                texToFboShaderID        = context.createProgram(&texToFboShader);
1122         deUint32                                texFromFboShaderID      = context.createProgram(&texFromFboShader);
1123         deUint32                                flatShaderID            = context.createProgram(&flatShader);
1124
1125         deUint32                                quadsTex                        = 1;
1126         deUint32                                metaballsTex            = 2;
1127         bool                                    depth                           = (m_config.buffers & GL_DEPTH_BUFFER_BIT)              != 0;
1128         bool                                    stencil                         = (m_config.buffers & GL_STENCIL_BUFFER_BIT)    != 0;
1129         int                                             initialWidth            = 128;
1130         int                                             initialHeight           = 128;
1131         int                                             newWidth                        = 64;
1132         int                                             newHeight                       = 32;
1133
1134         texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
1135         texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1136
1137         createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1138         createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
1139
1140         Framebuffer fbo(context, m_config, initialWidth, initialHeight);
1141         fbo.checkCompleteness();
1142
1143         // Setup shaders
1144         texToFboShader.setUniforms      (context, texToFboShaderID);
1145         texFromFboShader.setUniforms(context, texFromFboShaderID);
1146         flatShader.setColor                     (context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f) * fboOutScale + fboOutBias);
1147
1148         // Render quads
1149         context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1150         context.viewport(0, 0, initialWidth, initialHeight);
1151         clearColorBuffer(context, colorFormat, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1152         context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1153         context.bindTexture(GL_TEXTURE_2D, quadsTex);
1154         sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1155
1156         if (fbo.getConfig().colorType == GL_TEXTURE_2D)
1157         {
1158                 // Render fbo to screen
1159                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1160                 context.viewport(0, 0, context.getWidth(), context.getHeight());
1161                 context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1162                 sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1163
1164                 // Restore binding
1165                 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1166         }
1167
1168         // Resize buffers
1169         switch (fbo.getConfig().colorType)
1170         {
1171                 case GL_TEXTURE_2D:
1172                         context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1173                         context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorFormat, newWidth, newHeight);
1174                         break;
1175
1176                 case GL_RENDERBUFFER:
1177                         context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorBuffer());
1178                         context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorFormat, newWidth, newHeight);
1179                         break;
1180
1181                 default:
1182                         DE_ASSERT(DE_FALSE);
1183         }
1184
1185         if (depth || stencil)
1186         {
1187                 switch (fbo.getConfig().depthStencilType)
1188                 {
1189                         case GL_TEXTURE_2D:
1190                                 context.bindTexture(GL_TEXTURE_2D, fbo.getDepthStencilBuffer());
1191                                 context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().depthStencilFormat, newWidth, newHeight);
1192                                 break;
1193
1194                         case GL_RENDERBUFFER:
1195                                 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthStencilBuffer());
1196                                 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthStencilFormat, newWidth, newHeight);
1197                                 break;
1198
1199                         default:
1200                                 DE_ASSERT(false);
1201                 }
1202         }
1203
1204         // Render to resized fbo
1205         context.viewport(0, 0, newWidth, newHeight);
1206         clearColorBuffer(context, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1207         context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1208
1209         context.enable(GL_DEPTH_TEST);
1210
1211         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1212         sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1213
1214         context.bindTexture(GL_TEXTURE_2D, quadsTex);
1215         sglr::drawQuad(context, texToFboShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));
1216
1217         context.disable(GL_DEPTH_TEST);
1218
1219         if (stencil)
1220         {
1221                 context.enable(GL_SCISSOR_TEST);
1222                 context.clearStencil(1);
1223                 context.scissor(10, 10, 5, 15);
1224                 context.clear(GL_STENCIL_BUFFER_BIT);
1225                 context.disable(GL_SCISSOR_TEST);
1226
1227                 context.enable(GL_STENCIL_TEST);
1228                 context.stencilFunc(GL_EQUAL, 1, 0xffu);
1229                 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1230                 context.disable(GL_STENCIL_TEST);
1231         }
1232
1233         if (m_config.colorType == GL_TEXTURE_2D)
1234         {
1235                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1236                 context.viewport(0, 0, context.getWidth(), context.getHeight());
1237                 context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1238                 sglr::drawQuad(context, texFromFboShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
1239                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1240         }
1241         else
1242                 readPixels(context, dst, 0, 0, newWidth, newHeight, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1243 }
1244
1245 class RecreateBuffersTest : public FboRenderCase
1246 {
1247 public:
1248                                         RecreateBuffersTest                     (Context& context, const FboConfig& config, deUint32 buffers, bool rebind);
1249         virtual                 ~RecreateBuffersTest            (void) {}
1250
1251         void                    render                                          (sglr::Context& context, Surface& dst);
1252
1253 private:
1254         deUint32                m_buffers;
1255         bool                    m_rebind;
1256 };
1257
1258 RecreateBuffersTest::RecreateBuffersTest (Context& context, const FboConfig& config, deUint32 buffers, bool rebind)
1259         : FboRenderCase         (context, (string(config.getName()) + (rebind ? "" : "_no_rebind")).c_str(), "Recreate buffers", config)
1260         , m_buffers                     (buffers)
1261         , m_rebind                      (rebind)
1262 {
1263 }
1264
1265 void RecreateBuffersTest::render (sglr::Context& ctx, Surface& dst)
1266 {
1267         tcu::TextureFormat              colorFormat                     = glu::mapGLInternalFormat(m_config.colorFormat);
1268         glu::DataType                   fboSamplerType          = glu::getSampler2DType(colorFormat);
1269         glu::DataType                   fboOutputType           = getFragmentOutputType(colorFormat);
1270         tcu::TextureFormatInfo  fboRangeInfo            = tcu::getTextureFormatInfo(colorFormat);
1271         Vec4                                    fboOutScale                     = fboRangeInfo.valueMax - fboRangeInfo.valueMin;
1272         Vec4                                    fboOutBias                      = fboRangeInfo.valueMin;
1273
1274         Texture2DShader                 texToFboShader          (DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType);
1275         Texture2DShader                 texFromFboShader        (DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4);
1276         FlatColorShader                 flatShader                      (fboOutputType);
1277         deUint32                                texToFboShaderID        = ctx.createProgram(&texToFboShader);
1278         deUint32                                texFromFboShaderID      = ctx.createProgram(&texFromFboShader);
1279         deUint32                                flatShaderID            = ctx.createProgram(&flatShader);
1280
1281         int                                             width                           = 128;
1282         int                                             height                          = 128;
1283         deUint32                                metaballsTex            = 1;
1284         deUint32                                quadsTex                        = 2;
1285         bool                                    stencil                         = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0;
1286
1287         createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1288         createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1289
1290         Framebuffer fbo(ctx, m_config, width, height);
1291         fbo.checkCompleteness();
1292
1293         // Setup shaders
1294         texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
1295         texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1296         texToFboShader.setUniforms      (ctx, texToFboShaderID);
1297         texFromFboShader.setUniforms(ctx, texFromFboShaderID);
1298         flatShader.setColor                     (ctx, flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f) * fboOutScale + fboOutBias);
1299
1300         // Draw scene
1301         ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1302         ctx.viewport(0, 0, width, height);
1303         clearColorBuffer(ctx, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1304         ctx.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1305
1306         ctx.enable(GL_DEPTH_TEST);
1307
1308         ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
1309         sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1310
1311         ctx.disable(GL_DEPTH_TEST);
1312
1313         if (stencil)
1314         {
1315                 ctx.enable(GL_SCISSOR_TEST);
1316                 ctx.scissor(width/4, height/4, width/2, height/2);
1317                 ctx.clearStencil(1);
1318                 ctx.clear(GL_STENCIL_BUFFER_BIT);
1319                 ctx.disable(GL_SCISSOR_TEST);
1320         }
1321
1322         // Recreate buffers
1323         if (!m_rebind)
1324                 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1325
1326         DE_ASSERT((m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == 0 ||
1327                           (m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)));
1328
1329         // Recreate.
1330         for (int ndx = 0; ndx < 2; ndx++)
1331         {
1332                 deUint32        bit             = ndx == 0 ? GL_COLOR_BUFFER_BIT
1333                                                                            : (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1334                 deUint32        type    = ndx == 0 ? fbo.getConfig().colorType
1335                                                                            : fbo.getConfig().depthStencilType;
1336                 deUint32        format  = ndx == 0 ? fbo.getConfig().colorFormat
1337                                                                            : fbo.getConfig().depthStencilFormat;
1338                 deUint32        buf             = ndx == 0 ? fbo.getColorBuffer()
1339                                                                            : fbo.getDepthStencilBuffer();
1340
1341                 if ((m_buffers & bit) == 0)
1342                         continue;
1343
1344                 switch (type)
1345                 {
1346                         case GL_TEXTURE_2D:
1347                                 ctx.deleteTextures(1, &buf);
1348                                 ctx.bindTexture(GL_TEXTURE_2D, buf);
1349                                 ctx.texImage2D(GL_TEXTURE_2D, 0, format, width, height);
1350                                 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1351                                 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1352                                 break;
1353
1354                         case GL_RENDERBUFFER:
1355                                 ctx.deleteRenderbuffers(1, &buf);
1356                                 ctx.bindRenderbuffer(GL_RENDERBUFFER, buf);
1357                                 ctx.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
1358                                 break;
1359
1360                         default:
1361                                 DE_ASSERT(false);
1362                 }
1363         }
1364
1365         // Rebind.
1366         if (m_rebind)
1367         {
1368                 for (int ndx = 0; ndx < 3; ndx++)
1369                 {
1370                         deUint32        bit             = ndx == 0 ? GL_COLOR_BUFFER_BIT        :
1371                                                                   ndx == 1 ? GL_DEPTH_BUFFER_BIT        :
1372                                                                   ndx == 2 ? GL_STENCIL_BUFFER_BIT      : 0;
1373                         deUint32        point   = ndx == 0 ? GL_COLOR_ATTACHMENT0       :
1374                                                                   ndx == 1 ? GL_DEPTH_ATTACHMENT        :
1375                                                                   ndx == 2 ? GL_STENCIL_ATTACHMENT      : 0;
1376                         deUint32        type    = ndx == 0 ? fbo.getConfig().colorType
1377                                                                                    : fbo.getConfig().depthStencilType;
1378                         deUint32        buf             = ndx == 0 ? fbo.getColorBuffer()
1379                                                                                    : fbo.getDepthStencilBuffer();
1380
1381                         if ((m_buffers & bit) == 0)
1382                                 continue;
1383
1384                         switch (type)
1385                         {
1386                                 case GL_TEXTURE_2D:
1387                                         ctx.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, buf, 0);
1388                                         break;
1389
1390                                 case GL_RENDERBUFFER:
1391                                         ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, buf);
1392                                         break;
1393
1394                                 default:
1395                                         DE_ASSERT(false);
1396                         }
1397                 }
1398         }
1399
1400         if (!m_rebind)
1401                 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1402
1403         ctx.clearStencil(0);
1404         ctx.clear(m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); // \note Clear only buffers that were re-created
1405         if (m_buffers & GL_COLOR_BUFFER_BIT)
1406         {
1407                 // Clearing of integer buffers is undefined so do clearing by rendering flat color.
1408                 sglr::drawQuad(ctx, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1409         }
1410
1411         ctx.enable(GL_DEPTH_TEST);
1412
1413         if (stencil)
1414         {
1415                 // \note Stencil test enabled only if we have stencil buffer
1416                 ctx.enable(GL_STENCIL_TEST);
1417                 ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
1418         }
1419         ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
1420         sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
1421         if (stencil)
1422                 ctx.disable(GL_STENCIL_TEST);
1423
1424         ctx.disable(GL_DEPTH_TEST);
1425
1426         if (fbo.getConfig().colorType == GL_TEXTURE_2D)
1427         {
1428                 // Unbind fbo
1429                 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1430
1431                 // Draw to screen
1432                 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer());
1433                 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
1434                 sglr::drawQuad(ctx, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1435
1436                 // Read from screen
1437                 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
1438         }
1439         else
1440         {
1441                 // Read from fbo
1442                 readPixels(ctx, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias);
1443         }
1444 }
1445
1446 } // FboCases
1447
1448 FboRenderTestGroup::FboRenderTestGroup (Context& context)
1449         : TestCaseGroup(context, "render", "Rendering Tests")
1450 {
1451 }
1452
1453 FboRenderTestGroup::~FboRenderTestGroup (void)
1454 {
1455 }
1456
1457 void FboRenderTestGroup::init (void)
1458 {
1459         static const deUint32 objectTypes[] =
1460         {
1461                 GL_TEXTURE_2D,
1462                 GL_RENDERBUFFER
1463         };
1464
1465         enum FormatType
1466         {
1467                 FORMATTYPE_FLOAT = 0,
1468                 FORMATTYPE_FIXED,
1469                 FORMATTYPE_INT,
1470                 FORMATTYPE_UINT,
1471
1472                 FORMATTYPE_LAST
1473         };
1474
1475         // Required by specification.
1476         static const struct
1477         {
1478                 deUint32        format;
1479                 FormatType      type;
1480         } colorFormats[] =
1481         {
1482                 { GL_RGBA32F,                   FORMATTYPE_FLOAT        },
1483                 { GL_RGBA32I,                   FORMATTYPE_INT          },
1484                 { GL_RGBA32UI,                  FORMATTYPE_UINT         },
1485                 { GL_RGBA16F,                   FORMATTYPE_FLOAT        },
1486                 { GL_RGBA16I,                   FORMATTYPE_INT          },
1487                 { GL_RGBA16UI,                  FORMATTYPE_UINT         },
1488                 { GL_RGB16F,                    FORMATTYPE_FLOAT        },
1489                 { GL_RGBA8,                             FORMATTYPE_FIXED        },
1490                 { GL_RGBA8I,                    FORMATTYPE_INT          },
1491                 { GL_RGBA8UI,                   FORMATTYPE_UINT         },
1492                 { GL_SRGB8_ALPHA8,              FORMATTYPE_FIXED        },
1493                 { GL_RGB10_A2,                  FORMATTYPE_FIXED        },
1494                 { GL_RGB10_A2UI,                FORMATTYPE_UINT         },
1495                 { GL_RGBA4,                             FORMATTYPE_FIXED        },
1496                 { GL_RGB5_A1,                   FORMATTYPE_FIXED        },
1497                 { GL_RGB8,                              FORMATTYPE_FIXED        },
1498                 { GL_RGB565,                    FORMATTYPE_FIXED        },
1499                 { GL_R11F_G11F_B10F,    FORMATTYPE_FLOAT        },
1500                 { GL_RG32F,                             FORMATTYPE_FLOAT        },
1501                 { GL_RG32I,                             FORMATTYPE_INT          },
1502                 { GL_RG32UI,                    FORMATTYPE_UINT         },
1503                 { GL_RG16F,                             FORMATTYPE_FLOAT        },
1504                 { GL_RG16I,                             FORMATTYPE_INT          },
1505                 { GL_RG16UI,                    FORMATTYPE_UINT         },
1506                 { GL_RG8,                               FORMATTYPE_FLOAT        },
1507                 { GL_RG8I,                              FORMATTYPE_INT          },
1508                 { GL_RG8UI,                             FORMATTYPE_UINT         },
1509                 { GL_R32F,                              FORMATTYPE_FLOAT        },
1510                 { GL_R32I,                              FORMATTYPE_INT          },
1511                 { GL_R32UI,                             FORMATTYPE_UINT         },
1512                 { GL_R16F,                              FORMATTYPE_FLOAT        },
1513                 { GL_R16I,                              FORMATTYPE_INT          },
1514                 { GL_R16UI,                             FORMATTYPE_UINT         },
1515                 { GL_R8,                                FORMATTYPE_FLOAT        },
1516                 { GL_R8I,                               FORMATTYPE_INT          },
1517                 { GL_R8UI,                              FORMATTYPE_UINT         }
1518         };
1519
1520         static const struct
1521         {
1522                 deUint32        format;
1523                 bool            depth;
1524                 bool            stencil;
1525         } depthStencilFormats[] =
1526         {
1527                 { GL_DEPTH_COMPONENT32F,        true,   false   },
1528                 { GL_DEPTH_COMPONENT24,         true,   false   },
1529                 { GL_DEPTH_COMPONENT16,         true,   false   },
1530                 { GL_DEPTH32F_STENCIL8,         true,   true    },
1531                 { GL_DEPTH24_STENCIL8,          true,   true    },
1532                 { GL_STENCIL_INDEX8,            false,  true    }
1533         };
1534
1535         using namespace FboCases;
1536
1537         // .stencil_clear
1538         tcu::TestCaseGroup* stencilClearGroup = new tcu::TestCaseGroup(m_testCtx, "stencil_clear", "Stencil buffer clears");
1539         addChild(stencilClearGroup);
1540         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
1541         {
1542                 deUint32        colorType       = GL_TEXTURE_2D;
1543                 deUint32        stencilType     = GL_RENDERBUFFER;
1544                 deUint32        colorFmt        = GL_RGBA8;
1545
1546                 if (!depthStencilFormats[fmtNdx].stencil)
1547                         continue;
1548
1549                 FboConfig config(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, colorType, colorFmt, stencilType, depthStencilFormats[fmtNdx].format);
1550                 stencilClearGroup->addChild(new StencilClearsTest(m_context, config));
1551         }
1552
1553         // .shared_colorbuffer_clear
1554         tcu::TestCaseGroup* sharedColorbufferClearGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer_clear", "Shader colorbuffer clears");
1555         addChild(sharedColorbufferClearGroup);
1556         for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1557         {
1558                 // Clearing of integer buffers is undefined.
1559                 if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT || colorFormats[colorFmtNdx].type == FORMATTYPE_UINT)
1560                         continue;
1561
1562                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1563                 {
1564                         FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE);
1565                         sharedColorbufferClearGroup->addChild(new SharedColorbufferClearsTest(m_context, config));
1566                 }
1567         }
1568
1569         // .shared_colorbuffer
1570         tcu::TestCaseGroup* sharedColorbufferGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer", "Shared colorbuffer tests");
1571         addChild(sharedColorbufferGroup);
1572         for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1573         {
1574                 deUint32        depthStencilType        = GL_RENDERBUFFER;
1575                 deUint32        depthStencilFormat      = GL_DEPTH24_STENCIL8;
1576
1577                 // Blending with integer buffers and fp32 targets is not supported.
1578                 if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT    ||
1579                         colorFormats[colorFmtNdx].type == FORMATTYPE_UINT       ||
1580                         colorFormats[colorFmtNdx].format == GL_RGBA32F          ||
1581                         colorFormats[colorFmtNdx].format == GL_RGB32F           ||
1582                         colorFormats[colorFmtNdx].format == GL_RG32F            ||
1583                         colorFormats[colorFmtNdx].format == GL_R32F)
1584                         continue;
1585
1586                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1587                 {
1588                         FboConfig colorOnlyConfig                       (GL_COLOR_BUFFER_BIT,                                                                                   objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE);
1589                         FboConfig colorDepthConfig                      (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT,                                               objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat);
1590                         FboConfig colorDepthStencilConfig       (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat);
1591
1592                         sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorOnlyConfig));
1593                         sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthConfig));
1594                         sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthStencilConfig));
1595                 }
1596         }
1597
1598         // .shared_depth_stencil
1599         tcu::TestCaseGroup* sharedDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "shared_depth_stencil", "Shared depth and stencil buffers");
1600         addChild(sharedDepthStencilGroup);
1601         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
1602         {
1603                 deUint32        colorType               = GL_TEXTURE_2D;
1604                 deUint32        colorFmt                = GL_RGBA8;
1605                 bool            depth                   = depthStencilFormats[fmtNdx].depth;
1606                 bool            stencil                 = depthStencilFormats[fmtNdx].stencil;
1607
1608                 if (!depth)
1609                         continue; // Not verified.
1610
1611                 // Depth and stencil: both rbo and textures
1612                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1613                 {
1614                         FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
1615                         sharedDepthStencilGroup->addChild(new SharedDepthStencilTest(m_context, config));
1616                 }
1617         }
1618
1619         // .resize
1620         tcu::TestCaseGroup* resizeGroup = new tcu::TestCaseGroup(m_testCtx, "resize", "FBO resize tests");
1621         addChild(resizeGroup);
1622         for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1623         {
1624                 deUint32 colorFormat = colorFormats[colorFmtNdx].format;
1625
1626                 // Color-only.
1627                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1628                 {
1629                         FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormat, GL_NONE, GL_NONE);
1630                         resizeGroup->addChild(new ResizeTest(m_context, config));
1631                 }
1632
1633                 // For selected color formats tests depth & stencil variants.
1634                 if (colorFormat == GL_RGBA8 || colorFormat == GL_RGBA16F)
1635                 {
1636                         for (int depthStencilFmtNdx = 0; depthStencilFmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); depthStencilFmtNdx++)
1637                         {
1638                                 deUint32        colorType               = GL_TEXTURE_2D;
1639                                 bool            depth                   = depthStencilFormats[depthStencilFmtNdx].depth;
1640                                 bool            stencil                 = depthStencilFormats[depthStencilFmtNdx].stencil;
1641
1642                                 // Depth and stencil: both rbo and textures
1643                                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1644                                 {
1645                                         if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
1646                                                 continue; // Not supported.
1647
1648                                         FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0),
1649                                                                          colorType, colorFormat,
1650                                                                          objectTypes[typeNdx], depthStencilFormats[depthStencilFmtNdx].format);
1651                                         resizeGroup->addChild(new ResizeTest(m_context, config));
1652                                 }
1653                         }
1654                 }
1655         }
1656
1657         // .recreate_color
1658         tcu::TestCaseGroup* recreateColorGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_color", "Recreate colorbuffer tests");
1659         addChild(recreateColorGroup);
1660         for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++)
1661         {
1662                 deUint32        colorFormat                     = colorFormats[colorFmtNdx].format;
1663                 deUint32        depthStencilFormat      = GL_DEPTH24_STENCIL8;
1664                 deUint32        depthStencilType        = GL_RENDERBUFFER;
1665
1666                 // Color-only.
1667                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1668                 {
1669                         FboConfig config(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormat, depthStencilType, depthStencilFormat);
1670                         recreateColorGroup->addChild(new RecreateBuffersTest(m_context, config, GL_COLOR_BUFFER_BIT, true /* rebind */));
1671                 }
1672         }
1673
1674         // .recreate_depth_stencil
1675         tcu::TestCaseGroup* recreateDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_depth_stencil", "Recreate depth and stencil buffers");
1676         addChild(recreateDepthStencilGroup);
1677         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++)
1678         {
1679                 deUint32        colorType               = GL_TEXTURE_2D;
1680                 deUint32        colorFmt                = GL_RGBA8;
1681                 bool            depth                   = depthStencilFormats[fmtNdx].depth;
1682                 bool            stencil                 = depthStencilFormats[fmtNdx].stencil;
1683
1684                 // Depth and stencil: both rbo and textures
1685                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++)
1686                 {
1687                         if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER)
1688                                 continue;
1689
1690                         FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format);
1691                         recreateDepthStencilGroup->addChild(new RecreateBuffersTest(m_context, config, (depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), true /* rebind */));
1692                 }
1693         }
1694 }
1695
1696 } // Functional
1697 } // gles3
1698 } // deqp