Merge branch 'jekstrand_renderpass_transfer_bit_fix' into 'master'
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / functional / es2fFboRenderTest.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.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  * Notes:
24  *   + Like in API tests, tcu::sgl2s::Context class is used.
25  *   + ReferenceContext is used to generate reference images.
26  *   + API calls can be logged \todo [pyry] Implement.
27  *//*--------------------------------------------------------------------*/
28
29 #include "es2fFboRenderTest.hpp"
30 #include "sglrContextUtil.hpp"
31 #include "sglrGLContext.hpp"
32 #include "sglrReferenceContext.hpp"
33 #include "tcuSurface.hpp"
34 #include "tcuTextureUtil.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "gluPixelTransfer.hpp"
38 #include "gluTextureUtil.hpp"
39 #include "gluStrUtil.hpp"
40 #include "deRandom.hpp"
41 #include "deString.h"
42
43 #include "glwFunctions.hpp"
44 #include "glwEnums.hpp"
45
46 using std::vector;
47 using std::string;
48 using tcu::Vec2;
49 using tcu::Vec3;
50 using tcu::Vec4;
51 using tcu::RGBA;
52 using tcu::Surface;
53 using namespace glw; // GL types
54
55 namespace deqp
56 {
57 namespace gles2
58 {
59 namespace Functional
60 {
61
62 // Shaders.
63
64 class FlatColorShader : public sglr::ShaderProgram
65 {
66 public:
67         FlatColorShader (void)
68                 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
69                                                                 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
70                                                                 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
71                                                                 << sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
72                                                                 << sglr::pdec::VertexSource(
73                                                                                 "attribute highp vec4 a_position;\n"
74                                                                                 "void main (void)\n"
75                                                                                 "{\n"
76                                                                                 "       gl_Position = a_position;\n"
77                                                                                 "}\n")
78                                                                 << sglr::pdec::FragmentSource(
79                                                                                 "uniform mediump vec4 u_color;\n"
80                                                                                 "void main (void)\n"
81                                                                                 "{\n"
82                                                                                 "       gl_FragColor = u_color;\n"
83                                                                                 "}\n"))
84         {
85         }
86
87         void setColor (sglr::Context& gl, deUint32 program, const tcu::Vec4& color)
88         {
89                 gl.useProgram(program);
90                 gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, color.getPtr());
91         }
92
93         void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
94         {
95                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
96                         packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
97         }
98
99         void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
100         {
101                 const tcu::Vec4 color(m_uniforms[0].value.f4);
102
103                 DE_UNREF(packets);
104
105                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
106                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
107                         rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
108         }
109 };
110
111 class SingleTex2DShader : public sglr::ShaderProgram
112 {
113 public:
114         SingleTex2DShader (void)
115                 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
116                                                                 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
117                                                                 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
118                                                                 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
119                                                                 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
120                                                                 << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
121                                                                 << sglr::pdec::VertexSource(
122                                                                                 "attribute highp vec4 a_position;\n"
123                                                                                 "attribute mediump vec2 a_coord;\n"
124                                                                                 "varying mediump vec2 v_coord;\n"
125                                                                                 "void main (void)\n"
126                                                                                 "{\n"
127                                                                                 "       gl_Position = a_position;\n"
128                                                                                 "       v_coord = a_coord;\n"
129                                                                                 "}\n")
130                                                                 << sglr::pdec::FragmentSource(
131                                                                                 "uniform sampler2D u_sampler0;\n"
132                                                                                 "varying mediump vec2 v_coord;\n"
133                                                                                 "void main (void)\n"
134                                                                                 "{\n"
135                                                                                 "       gl_FragColor = texture2D(u_sampler0, v_coord);\n"
136                                                                                 "}\n"))
137         {
138         }
139
140         void setUnit (sglr::Context& gl, deUint32 program, int unitNdx)
141         {
142                 gl.useProgram(program);
143                 gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unitNdx);
144         }
145
146         void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
147         {
148                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
149                 {
150                         rr::VertexPacket& packet = *packets[packetNdx];
151
152                         packet.position         = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
153                         packet.outputs[0]       = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
154                 }
155         }
156
157         void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
158         {
159                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
160                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
161                 {
162                         const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
163                         const float             lod             = 0.0f;
164
165                         rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod));
166                 }
167         }
168
169 };
170
171 class MixTexturesShader : public sglr::ShaderProgram
172 {
173 public:
174         MixTexturesShader (void)
175                 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
176                                                                 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
177                                                                 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
178                                                                 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
179                                                                 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
180                                                                 << sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
181                                                                 << sglr::pdec::Uniform("u_sampler1", glu::TYPE_SAMPLER_2D)
182                                                                 << sglr::pdec::VertexSource(
183                                                                                 "attribute highp vec4 a_position;\n"
184                                                                                 "attribute mediump vec2 a_coord;\n"
185                                                                                 "varying mediump vec2 v_coord;\n"
186                                                                                 "void main (void)\n"
187                                                                                 "{\n"
188                                                                                 "       gl_Position = a_position;\n"
189                                                                                 "       v_coord = a_coord;\n"
190                                                                                 "}\n")
191                                                                 << sglr::pdec::FragmentSource(
192                                                                                 "uniform sampler2D u_sampler0;\n"
193                                                                                 "uniform sampler2D u_sampler1;\n"
194                                                                                 "varying mediump vec2 v_coord;\n"
195                                                                                 "void main (void)\n"
196                                                                                 "{\n"
197                                                                                 "       gl_FragColor = texture2D(u_sampler0, v_coord)*0.5 + texture2D(u_sampler1, v_coord)*0.5;\n"
198                                                                                 "}\n"))
199         {
200         }
201
202         void setUnits (sglr::Context& gl, deUint32 program, int unit0, int unit1)
203         {
204                 gl.useProgram(program);
205                 gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unit0);
206                 gl.uniform1i(gl.getUniformLocation(program, "u_sampler1"), unit1);
207         }
208
209         void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
210         {
211                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
212                 {
213                         rr::VertexPacket& packet = *packets[packetNdx];
214
215                         packet.position         = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
216                         packet.outputs[0]       = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
217                 }
218         }
219
220         void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
221         {
222                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
223                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
224                 {
225                         const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
226                         const float             lod             = 0.0f;
227
228                         rr::writeFragmentOutput(context, packetNdx, fragNdx, 0,   this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f
229                                                                                 + this->m_uniforms[1].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod) * 0.5f);
230                 }
231         }
232 };
233
234 // Framebuffer config.
235
236 class FboConfig
237 {
238 public:
239         FboConfig (void)
240                 : colorbufferType               (GL_NONE)
241                 , colorbufferFormat             (GL_NONE)
242                 , depthbufferType               (GL_NONE)
243                 , depthbufferFormat             (GL_NONE)
244                 , stencilbufferType             (GL_NONE)
245                 , stencilbufferFormat   (GL_NONE)
246         {
247         }
248
249         std::string                             getName                 (void) const;
250
251         GLenum                                  colorbufferType;                //!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER
252         GLenum                                  colorbufferFormat;              //!< Internal format for color buffer texture or renderbuffer
253
254         GLenum                                  depthbufferType;                //!< GL_RENDERBUFFER
255         GLenum                                  depthbufferFormat;
256
257         GLenum                                  stencilbufferType;              //!< GL_RENDERBUFFER
258         GLenum                                  stencilbufferFormat;
259
260 private:
261         static const char*              getFormatName   (GLenum format);
262 };
263
264 const char* FboConfig::getFormatName (GLenum format)
265 {
266         switch (format)
267         {
268                 case GL_RGB:                            return "rgb";
269                 case GL_RGBA:                           return "rgba";
270                 case GL_ALPHA:                          return "alpha";
271                 case GL_LUMINANCE:                      return "luminance";
272                 case GL_LUMINANCE_ALPHA:        return "luminance_alpha";
273                 case GL_RGB565:                         return "rgb565";
274                 case GL_RGB5_A1:                        return "rgb5_a1";
275                 case GL_RGBA4:                          return "rgba4";
276                 case GL_RGBA16F:                        return "rgba16f";
277                 case GL_RGB16F:                         return "rgb16f";
278                 case GL_DEPTH_COMPONENT16:      return "depth_component16";
279                 case GL_STENCIL_INDEX8:         return "stencil_index8";
280                 default:                                        DE_ASSERT(false); return DE_NULL;
281         }
282 }
283
284 std::string FboConfig::getName (void) const
285 {
286         std::string name = "";
287
288         if (colorbufferType != GL_NONE)
289         {
290                 switch (colorbufferType)
291                 {
292                         case GL_TEXTURE_2D:                     name += "tex2d_";       break;
293                         case GL_TEXTURE_CUBE_MAP:       name += "texcube_";     break;
294                         case GL_RENDERBUFFER:           name += "rbo_";         break;
295                         default:                                        DE_ASSERT(false);       break;
296                 }
297                 name += getFormatName(colorbufferFormat);
298         }
299
300         if (depthbufferType != GL_NONE)
301         {
302                 DE_ASSERT(depthbufferType == GL_RENDERBUFFER);
303                 if (name.length() > 0)
304                         name += "_";
305                 name += getFormatName(depthbufferFormat);
306         }
307
308         if (stencilbufferType != GL_NONE)
309         {
310                 DE_ASSERT(stencilbufferType == GL_RENDERBUFFER);
311                 if (name.length() > 0)
312                         name += "_";
313                 name += getFormatName(stencilbufferFormat);
314         }
315
316         return name;
317 }
318
319 class FboIncompleteException : public tcu::TestError
320 {
321 public:
322                                                 FboIncompleteException          (const FboConfig& config, GLenum reason, const char* file, int line);
323         virtual                         ~FboIncompleteException         (void) throw() {}
324
325         const FboConfig&        getConfig                                       (void) const { return m_config; }
326         GLenum                          getReason                                       (void) const { return m_reason; }
327
328 private:
329         FboConfig                       m_config;
330         GLenum                          m_reason;
331 };
332
333 static const char* getFboIncompleteReasonName (GLenum reason)
334 {
335         switch (reason)
336         {
337                 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:                      return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
338                 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:      return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
339                 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:                      return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
340                 case GL_FRAMEBUFFER_UNSUPPORTED:                                        return "GL_FRAMEBUFFER_UNSUPPORTED";
341                 case GL_FRAMEBUFFER_COMPLETE:                                           return "GL_FRAMEBUFFER_COMPLETE";
342                 default:                                                                                        return "UNKNOWN";
343         }
344 }
345
346 FboIncompleteException::FboIncompleteException (const FboConfig& config, GLenum reason, const char* file, int line)
347         : TestError("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
348         , m_config(config)
349         , m_reason(reason)
350 {
351 }
352
353 class Framebuffer
354 {
355 public:
356                                                 Framebuffer                     (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorbuffer = 0, deUint32 depthbuffer = 0, deUint32 stencilbuffer = 0);
357                                                 ~Framebuffer            (void);
358
359         const FboConfig&        getConfig                       (void) const { return m_config; }
360         deUint32                        getFramebuffer          (void) const { return m_framebuffer; }
361         deUint32                        getColorbuffer          (void) const { return m_colorbuffer; }
362         deUint32                        getDepthbuffer          (void) const { return m_depthbuffer; }
363         deUint32                        getStencilbuffer        (void) const { return m_stencilbuffer; }
364
365         void                            checkCompleteness       (void);
366
367 private:
368         void                            createRbo                       (deUint32& name, GLenum format, int width, int height);
369         void                            destroyBuffer           (deUint32 name, GLenum type);
370
371         FboConfig                       m_config;
372         sglr::Context&          m_context;
373         deUint32                        m_framebuffer;
374         deUint32                        m_colorbuffer;
375         deUint32                        m_depthbuffer;
376         deUint32                        m_stencilbuffer;
377 };
378
379 static bool isExtensionSupported (sglr::Context& context, const char* name)
380 {
381         std::istringstream extensions(context.getString(GL_EXTENSIONS));
382         std::string extension;
383
384         while (std::getline(extensions, extension, ' '))
385         {
386                 if (extension == name)
387                         return true;
388         }
389
390         return false;
391 }
392
393 static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat)
394 {
395         switch (sizedFormat)
396         {
397                 case GL_RGBA16F:
398                 case GL_RGB16F:
399                 case GL_RG16F:
400                 case GL_R16F:
401                         if (!isExtensionSupported(context, "GL_EXT_color_buffer_half_float"))
402                                 throw tcu::NotSupportedError("GL_EXT_color_buffer_half_float is not supported");
403
404                 default:
405                         break;
406         }
407 }
408
409 Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorbuffer, deUint32 depthbuffer, deUint32 stencilbuffer)
410         : m_config                      (config)
411         , m_context                     (context)
412         , m_framebuffer         (fbo)
413         , m_colorbuffer         (colorbuffer)
414         , m_depthbuffer         (depthbuffer)
415         , m_stencilbuffer       (stencilbuffer)
416 {
417         // Verify that color format is supported
418         checkColorFormatSupport(context, config.colorbufferFormat);
419
420         if (m_framebuffer == 0)
421                 context.genFramebuffers(1, &m_framebuffer);
422         context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
423
424         switch (m_config.colorbufferType)
425         {
426                 case GL_TEXTURE_2D:
427                         if (m_colorbuffer == 0)
428                                 context.genTextures(1, &m_colorbuffer);
429                         context.bindTexture(GL_TEXTURE_2D, m_colorbuffer);
430                         context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorbufferFormat, width, height);
431                         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
432
433                         if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height))
434                         {
435                                 // Set wrap mode to clamp for NPOT FBOs
436                                 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
437                                 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
438                         }
439
440                         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorbuffer, 0);
441                         break;
442
443                 case GL_TEXTURE_CUBE_MAP:
444                         DE_FATAL("TODO");
445                         break;
446
447                 case GL_RENDERBUFFER:
448                         createRbo(m_colorbuffer, m_config.colorbufferFormat, width, height);
449                         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorbuffer);
450                         break;
451
452                 default:
453                         DE_ASSERT(m_config.colorbufferType == GL_NONE);
454                         break;
455         }
456
457         if (m_config.depthbufferType == GL_RENDERBUFFER)
458         {
459                 createRbo(m_depthbuffer, m_config.depthbufferFormat, width, height);
460                 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer);
461         }
462         else
463                 DE_ASSERT(m_config.depthbufferType == GL_NONE);
464
465         if (m_config.stencilbufferType == GL_RENDERBUFFER)
466         {
467                 createRbo(m_stencilbuffer, m_config.stencilbufferFormat, width, height);
468                 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilbuffer);
469         }
470         else
471                 DE_ASSERT(m_config.stencilbufferType == GL_NONE);
472
473         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
474 }
475
476 Framebuffer::~Framebuffer (void)
477 {
478         m_context.deleteFramebuffers(1, &m_framebuffer);
479         destroyBuffer(m_colorbuffer, m_config.colorbufferType);
480         destroyBuffer(m_depthbuffer, m_config.depthbufferType);
481         destroyBuffer(m_stencilbuffer, m_config.stencilbufferType);
482 }
483
484 void Framebuffer::checkCompleteness (void)
485 {
486         m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
487         GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER);
488         m_context.bindFramebuffer(GL_FRAMEBUFFER, 0);
489         if (status != GL_FRAMEBUFFER_COMPLETE)
490                 throw FboIncompleteException(m_config, status, __FILE__, __LINE__);
491 }
492
493 void Framebuffer::createRbo (deUint32& name, GLenum format, int width, int height)
494 {
495         if (name == 0)
496                 m_context.genRenderbuffers(1, &name);
497         m_context.bindRenderbuffer(GL_RENDERBUFFER, name);
498         m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
499 }
500
501 void Framebuffer::destroyBuffer (deUint32 name, GLenum type)
502 {
503         if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP)
504                 m_context.deleteTextures(1, &name);
505         else if (type == GL_RENDERBUFFER)
506                 m_context.deleteRenderbuffers(1, &name);
507         else
508                 DE_ASSERT(type == GL_NONE);
509 }
510
511 static void createMetaballsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
512 {
513         tcu::TextureFormat      texFormat       = glu::mapGLTransferFormat(format, dataType);
514         tcu::TextureLevel       level           (texFormat, width, height);
515
516         tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height);
517
518         context.bindTexture(GL_TEXTURE_2D, name);
519         context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
520         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
521 }
522
523 static void createQuadsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
524 {
525         tcu::TextureFormat      texFormat       = glu::mapGLTransferFormat(format, dataType);
526         tcu::TextureLevel       level           (texFormat, width, height);
527
528         tcu::fillWithRGBAQuads(level.getAccess());
529
530         context.bindTexture(GL_TEXTURE_2D, name);
531         context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr());
532         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
533 }
534
535 class FboRenderCase : public TestCase
536 {
537 public:
538                                                                 FboRenderCase                   (Context& context, const char* name, const char* description, const FboConfig& config);
539         virtual                                         ~FboRenderCase                  (void) {}
540
541         virtual IterateResult           iterate                                 (void);
542         virtual void                            render                                  (sglr::Context& fboContext, Surface& dst) = DE_NULL;
543
544         const FboConfig&                        getConfig                               (void) const { return m_config; }
545
546         static bool                                     isConfigSupported               (const FboConfig& config) { DE_UNREF(config); return true; }
547
548 private:
549         FboConfig                                       m_config;
550 };
551
552 FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config)
553         : TestCase(context, name, description)
554         , m_config(config)
555 {
556 }
557
558 TestCase::IterateResult FboRenderCase::iterate (void)
559 {
560         Vec4                                            clearColor                              (0.125f, 0.25f, 0.5f, 1.0f);
561         glu::RenderContext&                     renderCtx                               = m_context.getRenderContext();
562         const tcu::RenderTarget&        renderTarget                    = m_context.getRenderTarget();
563         tcu::TestLog&                           log                                             = m_testCtx.getLog();
564         const char*                                     failReason                              = DE_NULL;
565
566         // Position & size for context
567         deRandom rnd;
568         deRandom_init(&rnd, deStringHash(getName()));
569
570         int             width   = deMin32(renderTarget.getWidth(), 128);
571         int             height  = deMin32(renderTarget.getHeight(), 128);
572         int             xMax    = renderTarget.getWidth()-width+1;
573         int             yMax    = renderTarget.getHeight()-height+1;
574         int             x               = deRandom_getUint32(&rnd) % xMax;
575         int             y               = deRandom_getUint32(&rnd) % yMax;
576
577         tcu::Surface    gles2Frame      (width, height);
578         tcu::Surface    refFrame        (width, height);
579         GLenum                  gles2Error;
580         GLenum                  refError;
581
582         // Render using GLES2
583         try
584         {
585                 sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
586
587                 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
588                 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
589
590                 render(context, gles2Frame); // Call actual render func
591                 gles2Error = context.getError();
592         }
593         catch (const FboIncompleteException& e)
594         {
595                 if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
596                 {
597                         // Mark test case as unsupported
598                         log << e;
599                         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
600                         return STOP;
601                 }
602                 else
603                         throw; // Propagate error
604         }
605
606         // Render reference image
607         {
608                 sglr::ReferenceContextBuffers   buffers (tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height);
609                 sglr::ReferenceContext                  context (sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer());
610
611                 context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
612                 context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
613
614                 render(context, refFrame);
615                 refError = context.getError();
616         }
617
618         // Compare error codes
619         bool errorCodesOk = (gles2Error == refError);
620
621         if (!errorCodesOk)
622         {
623                 log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles2Error) << ", expected " << glu::getErrorStr(refError) << tcu::TestLog::EndMessage;
624                 failReason = "Got unexpected error";
625         }
626
627         // Compare images
628         const float             threshold       = 0.03f;
629         bool                    imagesOk        = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles2Frame, threshold, tcu::COMPARE_LOG_RESULT);
630
631         if (!imagesOk && !failReason)
632                 failReason = "Image comparison failed";
633
634         // Store test result
635         bool isOk = errorCodesOk && imagesOk;
636         m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS      : QP_TEST_RESULT_FAIL,
637                                                         isOk ? "Pass"                           : failReason);
638
639         return STOP;
640 }
641
642 namespace FboCases
643 {
644
645 class ColorClearsTest : public FboRenderCase
646 {
647 public:
648                                                 ColorClearsTest                         (Context& context, const FboConfig& config);
649                                                 ~ColorClearsTest                        (void) {}
650
651         void                            render                                          (sglr::Context& context, Surface& dst);
652 };
653
654 ColorClearsTest::ColorClearsTest (Context& context, const FboConfig& config)
655         : FboRenderCase(context, config.getName().c_str(), "Color buffer clears", config)
656 {
657 }
658
659 void ColorClearsTest::render (sglr::Context& context, Surface& dst)
660 {
661         int                     width   = 128;
662         int                     height  = 128;
663         deRandom        rnd;
664
665         deRandom_init(&rnd, 0);
666
667         // Create framebuffer
668         Framebuffer fbo(context, getConfig(), width, height);
669         fbo.checkCompleteness();
670
671         // Clear fbo
672         context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
673         context.viewport(0, 0, width, height);
674         context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
675         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
676
677         // Enable scissor test.
678         context.enable(GL_SCISSOR_TEST);
679
680         // Do 10 random color clears
681         for (int i = 0; i < 15; i++)
682         {
683                 int             cX              = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % width;
684                 int             cY              = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % height;
685                 int             cWidth  = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (width-cX);
686                 int             cHeight = (int)(deRandom_getUint32(&rnd) & 0x7fffffff) % (height-cY);
687                 Vec4    color   = RGBA(deRandom_getUint32(&rnd)).toVec();
688
689                 context.scissor(cX, cY, cWidth, cHeight);
690                 context.clearColor(color.x(), color.y(), color.z(), color.w());
691                 context.clear(GL_COLOR_BUFFER_BIT);
692         }
693
694         // Disable scissor.
695         context.disable(GL_SCISSOR_TEST);
696
697         if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
698         {
699                 // Unbind fbo
700                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
701
702                 // Draw to screen
703                 SingleTex2DShader       shader;
704                 deUint32                        shaderID = context.createProgram(&shader);
705
706                 shader.setUnit(context, shaderID, 0);
707
708                 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
709                 context.viewport(0, 0, context.getWidth(), context.getHeight());
710                 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
711
712                 // Read from screen
713                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
714         }
715         else
716         {
717                 // Read from fbo
718                 context.readPixels(dst, 0, 0, width, height);
719         }
720 }
721
722 class IntersectingQuadsTest : public FboRenderCase
723 {
724 public:
725                                         IntersectingQuadsTest                   (Context& context, const FboConfig& config, bool npot = false);
726         virtual                 ~IntersectingQuadsTest                  (void) {}
727
728         virtual void    render                                                  (sglr::Context& context, Surface& dst);
729
730         static bool             isConfigSupported                               (const FboConfig& config);
731
732 private:
733         int                             m_fboWidth;
734         int                             m_fboHeight;
735 };
736
737 class IntersectingQuadsNpotTest : public IntersectingQuadsTest
738 {
739 public:
740         IntersectingQuadsNpotTest (Context& context, const FboConfig& config)
741                 : IntersectingQuadsTest(context, config, true)
742         {
743         }
744 };
745
746 IntersectingQuadsTest::IntersectingQuadsTest (Context& context, const FboConfig& config, bool npot)
747         : FboRenderCase (context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Intersecting textured quads", config)
748         , m_fboWidth    (npot ? 127 : 128)
749         , m_fboHeight   (npot ?  95 : 128)
750 {
751 }
752
753 bool IntersectingQuadsTest::isConfigSupported (const FboConfig& config)
754 {
755         // \note Disabled for stencil configurations since doesn't exercise stencil buffer
756         return config.depthbufferType   != GL_NONE &&
757                    config.stencilbufferType     == GL_NONE;
758 }
759
760 void IntersectingQuadsTest::render (sglr::Context& ctx, Surface& dst)
761 {
762         SingleTex2DShader       texShader;
763         deUint32                        texShaderID = ctx.createProgram(&texShader);
764
765         deUint32 metaballsTex   = 1;
766         deUint32 quadsTex               = 2;
767
768         createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
769         createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
770
771         int width       = m_fboWidth;
772         int height      = m_fboHeight;
773         Framebuffer fbo(ctx, getConfig(), width, height);
774         fbo.checkCompleteness();
775
776         // Setup shaders
777         texShader.setUnit(ctx, texShaderID, 0);
778
779         // Draw scene
780         ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
781         ctx.viewport(0, 0, width, height);
782         ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
783         ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
784
785         ctx.enable(GL_DEPTH_TEST);
786
787         ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
788         sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
789
790         ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
791         sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
792
793         ctx.disable(GL_DEPTH_TEST);
794
795         if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
796         {
797                 // Unbind fbo
798                 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
799
800                 // Draw to screen
801                 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
802                 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
803                 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
804
805                 // Read from screen
806                 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
807         }
808         else
809         {
810                 // Read from fbo
811                 ctx.readPixels(dst, 0, 0, width, height);
812         }
813 }
814
815 class MixTest : public FboRenderCase
816 {
817 public:
818                                                 MixTest                         (Context& context, const FboConfig& config, bool npot = false);
819         virtual                         ~MixTest                        (void) {}
820
821         void                            render                          (sglr::Context& context, Surface& dst);
822
823         static bool                     isConfigSupported       (const FboConfig& config);
824
825 private:
826         int                                     m_fboAWidth;
827         int                                     m_fboAHeight;
828         int                                     m_fboBWidth;
829         int                                     m_fboBHeight;
830 };
831
832 class MixNpotTest : public MixTest
833 {
834 public:
835         MixNpotTest (Context& context, const FboConfig& config)
836                 : MixTest(context, config, true)
837         {
838         }
839 };
840
841 MixTest::MixTest (Context& context, const FboConfig& config, bool npot)
842         : FboRenderCase (context, (string(npot ? "mix_npot_" : "mix_") + config.getName()).c_str(), "Use two fbos as sources in draw operation", config)
843         , m_fboAWidth   (npot ? 127 : 128)
844         , m_fboAHeight  (npot ?  95 : 128)
845         , m_fboBWidth   (npot ?  55 :  64)
846         , m_fboBHeight  (npot ?  63 :  64)
847 {
848 }
849
850 bool MixTest::isConfigSupported (const FboConfig& config)
851 {
852         // \note Disabled for stencil configurations since doesn't exercise stencil buffer
853         return config.colorbufferType   == GL_TEXTURE_2D &&
854                    config.stencilbufferType     == GL_NONE;
855 }
856
857 void MixTest::render (sglr::Context& context, Surface& dst)
858 {
859         SingleTex2DShader       singleTexShader;
860         MixTexturesShader       mixShader;
861
862         deUint32                        singleTexShaderID       = context.createProgram(&singleTexShader);
863         deUint32                        mixShaderID                     = context.createProgram(&mixShader);
864
865         // Texture with metaballs
866         deUint32 metaballsTex = 1;
867         context.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
868         createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
869
870         // Setup shaders
871         singleTexShader.setUnit(context, singleTexShaderID, 0);
872         mixShader.setUnits(context, mixShaderID, 0, 1);
873
874         // Fbo, quad with metaballs texture
875         Framebuffer fboA(context, getConfig(), m_fboAWidth, m_fboAHeight);
876         fboA.checkCompleteness();
877         context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
878         context.viewport(0, 0, m_fboAWidth, m_fboAHeight);
879         context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
880         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
881         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
882         sglr::drawQuad(context, singleTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
883
884         // Fbo, color clears
885         Framebuffer fboB(context, getConfig(), m_fboBWidth, m_fboBHeight);
886         fboB.checkCompleteness();
887         context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
888         context.viewport(0, 0, m_fboBWidth, m_fboBHeight);
889         context.enable(GL_SCISSOR_TEST);
890         context.scissor(0, 0, 32, 64);
891         context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
892         context.clear(GL_COLOR_BUFFER_BIT);
893         context.scissor(32, 0, 32, 64);
894         context.clearColor(0.0f, 1.0f, 0.0f, 1.0f);
895         context.clear(GL_COLOR_BUFFER_BIT);
896         context.disable(GL_SCISSOR_TEST);
897
898         // Final mix op
899         context.activeTexture(GL_TEXTURE0);
900         context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
901         context.activeTexture(GL_TEXTURE1);
902         context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
903         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
904         context.viewport(0, 0, context.getWidth(), context.getHeight());
905         sglr::drawQuad(context, mixShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
906
907         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
908 }
909
910 class BlendTest : public FboRenderCase
911 {
912 public:
913                                                 BlendTest                       (Context& context, const FboConfig& config, bool npot = false);
914         virtual                         ~BlendTest                      (void) {}
915
916         void                            render                          (sglr::Context& context, Surface& dst);
917
918         static bool                     isConfigSupported       (const FboConfig& config);
919
920 private:
921         int                                     m_fboWidth;
922         int                                     m_fboHeight;
923 };
924
925 class BlendNpotTest : public BlendTest
926 {
927 public:
928         BlendNpotTest (Context& context, const FboConfig& config)
929                 : BlendTest(context, config, true)
930         {
931         }
932 };
933
934 BlendTest::BlendTest (Context& context, const FboConfig& config, bool npot)
935         : FboRenderCase (context, (string(npot ? "blend_npot_" : "blend_") + config.getName()).c_str(), "Blend to fbo", config)
936         , m_fboWidth    (npot ? 111 : 128)
937         , m_fboHeight   (npot ? 122 : 128)
938 {
939 }
940
941 bool BlendTest::isConfigSupported (const FboConfig& config)
942 {
943         // \note Disabled for stencil configurations since doesn't exercise stencil buffer
944         return config.stencilbufferType == GL_NONE;
945 }
946
947 void BlendTest::render (sglr::Context& context, Surface& dst)
948 {
949         SingleTex2DShader       shader;
950         deUint32                        shaderID                = context.createProgram(&shader);
951         int                                     width                   = m_fboWidth;
952         int                                     height                  = m_fboHeight;
953         deUint32                        metaballsTex    = 1;
954
955         createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
956
957         Framebuffer fbo(context, getConfig(), width, height);
958         fbo.checkCompleteness();
959
960         shader.setUnit(context, shaderID, 0);
961
962         context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
963         context.viewport(0, 0, width, height);
964         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
965         context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
966         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
967
968         context.enable(GL_BLEND);
969         context.blendEquation(GL_FUNC_ADD);
970         context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
971         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
972         context.disable(GL_BLEND);
973
974         if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
975         {
976                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
977                 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
978                 context.viewport(0, 0, context.getWidth(), context.getHeight());
979                 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
980                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
981         }
982         else
983                 context.readPixels(dst, 0, 0, width, height);
984 }
985
986 class StencilClearsTest : public FboRenderCase
987 {
988 public:
989                                                 StencilClearsTest               (Context& context, const FboConfig& config);
990         virtual                         ~StencilClearsTest              (void) {};
991
992         void                            render                                  (sglr::Context& context, Surface& dst);
993
994         static bool                     isConfigSupported               (const FboConfig& config);
995 };
996
997 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
998         : FboRenderCase(context, config.getName().c_str(), "Stencil clears", config)
999 {
1000 }
1001
1002 void StencilClearsTest::render (sglr::Context& context, Surface& dst)
1003 {
1004         SingleTex2DShader       shader;
1005         deUint32                        shaderID                = context.createProgram(&shader);
1006         int                                     width                   = 128;
1007         int                                     height                  = 128;
1008         deUint32                        quadsTex                = 1;
1009         deUint32                        metaballsTex    = 2;
1010
1011         createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1012         createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1013
1014         Framebuffer fbo(context, getConfig(), width, height);
1015         fbo.checkCompleteness();
1016
1017         // Bind framebuffer and clear
1018         context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1019         context.viewport(0, 0, width, height);
1020         context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1021         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1022
1023         // Do stencil clears
1024         context.enable(GL_SCISSOR_TEST);
1025         context.scissor(10, 16, 32, 120);
1026         context.clearStencil(1);
1027         context.clear(GL_STENCIL_BUFFER_BIT);
1028         context.scissor(16, 32, 100, 64);
1029         context.clearStencil(2);
1030         context.clear(GL_STENCIL_BUFFER_BIT);
1031         context.disable(GL_SCISSOR_TEST);
1032
1033         // Draw 2 textures with stecil tests
1034         context.activeTexture(GL_TEXTURE0);
1035         context.bindTexture(GL_TEXTURE_2D, quadsTex);
1036         context.activeTexture(GL_TEXTURE1);
1037         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1038
1039         context.enable(GL_STENCIL_TEST);
1040         context.stencilFunc(GL_EQUAL, 1, 0xffffffffu);
1041         shader.setUnit(context, shaderID, 0);
1042         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1043
1044         context.stencilFunc(GL_EQUAL, 2, 0xffffffffu);
1045         shader.setUnit(context, shaderID, 1);
1046         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1047
1048         context.disable(GL_STENCIL_TEST);
1049
1050         if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1051         {
1052                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1053                 context.activeTexture(GL_TEXTURE0);
1054                 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1055                 context.viewport(0, 0, context.getWidth(), context.getHeight());
1056                 shader.setUnit(context, shaderID, 0);
1057                 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1058                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1059         }
1060         else
1061                 context.readPixels(dst, 0, 0, width, height);
1062 }
1063
1064 bool StencilClearsTest::isConfigSupported (const FboConfig& config)
1065 {
1066         return config.stencilbufferType != GL_NONE;
1067 }
1068
1069 class StencilTest : public FboRenderCase
1070 {
1071 public:
1072                                                 StencilTest                             (Context& context, const FboConfig& config, bool npot = false);
1073         virtual                         ~StencilTest                    (void) {};
1074
1075         void                            render                                  (sglr::Context& context, Surface& dst);
1076
1077         static bool                     isConfigSupported               (const FboConfig& config);
1078
1079 private:
1080         int                                     m_fboWidth;
1081         int                                     m_fboHeight;
1082 };
1083
1084 class StencilNpotTest : public StencilTest
1085 {
1086 public:
1087         StencilNpotTest (Context& context, const FboConfig& config)
1088                 : StencilTest(context, config, true)
1089         {
1090         }
1091 };
1092
1093 StencilTest::StencilTest (Context& context, const FboConfig& config, bool npot)
1094         : FboRenderCase (context, (string(npot ? "npot_" : "") + config.getName()).c_str(), "Stencil ops", config)
1095         , m_fboWidth    (npot ?  99 : 128)
1096         , m_fboHeight   (npot ? 110 : 128)
1097 {
1098 }
1099
1100 bool StencilTest::isConfigSupported (const FboConfig& config)
1101 {
1102         return config.stencilbufferType != GL_NONE;
1103 }
1104
1105 void StencilTest::render (sglr::Context& ctx, Surface& dst)
1106 {
1107         FlatColorShader         colorShader;
1108         SingleTex2DShader       texShader;
1109         deUint32                        colorShaderID   = ctx.createProgram(&colorShader);
1110         deUint32                        texShaderID             = ctx.createProgram(&texShader);
1111         int                                     width                   = m_fboWidth;
1112         int                                     height                  = m_fboHeight;
1113         int                                     texWidth                = 64;
1114         int                                     texHeight               = 64;
1115         deUint32                        quadsTex                = 1;
1116         deUint32                        metaballsTex    = 2;
1117         bool                            depth                   = getConfig().depthbufferType != GL_NONE;
1118
1119         createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
1120         createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
1121
1122         Framebuffer fbo(ctx, getConfig(), width, height);
1123         fbo.checkCompleteness();
1124
1125         // Bind framebuffer and clear
1126         ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1127         ctx.viewport(0, 0, width, height);
1128         ctx.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1129         ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1130
1131         // Render intersecting quads - increment stencil on depth pass
1132         ctx.enable(GL_DEPTH_TEST);
1133         ctx.enable(GL_STENCIL_TEST);
1134         ctx.stencilFunc(GL_ALWAYS, 0, 0xffu);
1135         ctx.stencilOp(GL_KEEP, GL_KEEP, GL_INCR);
1136
1137         colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
1138         sglr::drawQuad(ctx, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1139
1140         ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
1141         texShader.setUnit(ctx, texShaderID, 0);
1142         sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));
1143
1144         // Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
1145         ctx.disable(GL_DEPTH_TEST);
1146         ctx.stencilFunc(GL_EQUAL, depth ? 2 : 1, 0xffu);
1147         ctx.stencilOp(GL_DECR, GL_KEEP, GL_KEEP);
1148         colorShader.setColor(ctx, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1149         sglr::drawQuad(ctx, colorShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));
1150
1151         // Draw metaballs with stencil test where stencil > 1 or 2 depending on depth buffer
1152         ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
1153         ctx.stencilFunc(GL_GREATER, depth ? 1 : 2, 0xffu);
1154         ctx.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1155         sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1156
1157         ctx.disable(GL_STENCIL_TEST);
1158
1159         if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1160         {
1161                 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1162                 ctx.activeTexture(GL_TEXTURE0);
1163                 ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1164                 ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
1165                 sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1166                 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
1167         }
1168         else
1169                 ctx.readPixels(dst, 0, 0, width, height);
1170 }
1171
1172 class SharedColorbufferTest : public FboRenderCase
1173 {
1174 public:
1175                                                 SharedColorbufferTest                   (Context& context, const FboConfig& config);
1176         virtual                         ~SharedColorbufferTest                  (void) {};
1177
1178         void                            render                                                  (sglr::Context& context, Surface& dst);
1179 };
1180
1181 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
1182         : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config)
1183 {
1184 }
1185
1186 void SharedColorbufferTest::render (sglr::Context& context, Surface& dst)
1187 {
1188         SingleTex2DShader       shader;
1189         deUint32                        shaderID                = context.createProgram(&shader);
1190         int                                     width                   = 128;
1191         int                                     height                  = 128;
1192 //      bool                            depth                   = getConfig().depthbufferFormat         != GL_NONE;
1193         bool                            stencil                 = getConfig().stencilbufferFormat       != GL_NONE;
1194
1195         // Textures
1196         deUint32        quadsTex                = 1;
1197         deUint32        metaballsTex    = 2;
1198         createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1199         createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
1200
1201         context.viewport(0, 0, width, height);
1202
1203         shader.setUnit(context, shaderID, 0);
1204
1205         // Fbo A
1206         Framebuffer fboA(context, getConfig(), width, height);
1207         fboA.checkCompleteness();
1208
1209         // Fbo B - don't create colorbuffer
1210         FboConfig cfg = getConfig();
1211         cfg.colorbufferType             = GL_NONE;
1212         cfg.colorbufferFormat   = GL_NONE;
1213         Framebuffer fboB(context, cfg, width, height);
1214
1215         // Attach color buffer from fbo A
1216         context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1217         switch (getConfig().colorbufferType)
1218         {
1219                 case GL_TEXTURE_2D:
1220                         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorbuffer(), 0);
1221                         break;
1222
1223                 case GL_RENDERBUFFER:
1224                         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorbuffer());
1225                         break;
1226
1227                 default:
1228                         DE_ASSERT(false);
1229         }
1230
1231         // Clear depth and stencil in fbo B
1232         context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1233
1234         // Render quads to fbo 1, with depth 0.0
1235         context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
1236         context.bindTexture(GL_TEXTURE_2D, quadsTex);
1237         context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1238         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1239
1240         if (stencil)
1241         {
1242                 // Stencil to 1 in fbo A
1243                 context.clearStencil(1);
1244                 context.clear(GL_STENCIL_BUFFER_BIT);
1245         }
1246
1247         context.enable(GL_DEPTH_TEST);
1248         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1249         context.disable(GL_DEPTH_TEST);
1250
1251         // Blend metaballs to fbo 2
1252         context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1253         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1254         context.enable(GL_BLEND);
1255         context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
1256         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1257
1258         // Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits
1259         context.bindTexture(GL_TEXTURE_2D, quadsTex);
1260         context.enable(GL_DEPTH_TEST);
1261         sglr::drawQuad(context, shaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
1262         context.disable(GL_DEPTH_TEST);
1263
1264         if (stencil)
1265         {
1266                 FlatColorShader flatShader;
1267                 deUint32                flatShaderID = context.createProgram(&flatShader);
1268
1269                 flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1270
1271                 // Clear subset of stencil buffer to 1
1272                 context.enable(GL_SCISSOR_TEST);
1273                 context.scissor(10, 10, 12, 25);
1274                 context.clearStencil(1);
1275                 context.clear(GL_STENCIL_BUFFER_BIT);
1276                 context.disable(GL_SCISSOR_TEST);
1277
1278                 // Render quad with stencil mask == 1
1279                 context.enable(GL_STENCIL_TEST);
1280                 context.stencilFunc(GL_EQUAL, 1, 0xffu);
1281                 sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1282                 context.disable(GL_STENCIL_TEST);
1283         }
1284
1285         // Get results
1286         if (fboA.getConfig().colorbufferType == GL_TEXTURE_2D)
1287         {
1288                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1289                 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
1290                 context.viewport(0, 0, context.getWidth(), context.getHeight());
1291                 sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1292                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1293         }
1294         else
1295                 context.readPixels(dst, 0, 0, width, height);
1296 }
1297
1298 class SharedColorbufferClearsTest : public FboRenderCase
1299 {
1300 public:
1301                                         SharedColorbufferClearsTest             (Context& context, const FboConfig& config);
1302         virtual                 ~SharedColorbufferClearsTest    (void) {}
1303
1304         static bool             isConfigSupported                               (const FboConfig& config);
1305         void                    render                                                  (sglr::Context& context, Surface& dst);
1306 };
1307
1308 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
1309         : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config)
1310 {
1311 }
1312
1313 bool SharedColorbufferClearsTest::isConfigSupported (const FboConfig& config)
1314 {
1315         return config.colorbufferType   != GL_NONE &&
1316                    config.depthbufferType       == GL_NONE &&
1317                    config.stencilbufferType     == GL_NONE;
1318 }
1319
1320 void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
1321 {
1322         int                     width                   = 128;
1323         int                     height                  = 128;
1324         deUint32        colorbuffer             = 1;
1325
1326         checkColorFormatSupport(context, getConfig().colorbufferFormat);
1327
1328         // Single colorbuffer
1329         if (getConfig().colorbufferType == GL_TEXTURE_2D)
1330         {
1331                 context.bindTexture(GL_TEXTURE_2D, colorbuffer);
1332                 context.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, width, height);
1333                 context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1334         }
1335         else
1336         {
1337                 DE_ASSERT(getConfig().colorbufferType == GL_RENDERBUFFER);
1338                 context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
1339                 context.renderbufferStorage(GL_RENDERBUFFER, getConfig().colorbufferFormat, width, height);
1340         }
1341
1342         // Multiple framebuffers sharing the colorbuffer
1343         for (int fbo = 1; fbo <= 3; fbo++)
1344         {
1345                 context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
1346
1347                 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1348                         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1349                 else
1350                         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
1351         }
1352
1353         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1354
1355         // Check completeness
1356         {
1357                 GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
1358                 if (status != GL_FRAMEBUFFER_COMPLETE)
1359                         throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
1360         }
1361
1362         // Render to them
1363         context.viewport(0, 0, width, height);
1364         context.clearColor(0.0f, 0.0f, 1.0f, 1.0f);
1365         context.clear(GL_COLOR_BUFFER_BIT);
1366
1367         context.enable(GL_SCISSOR_TEST);
1368
1369         context.bindFramebuffer(GL_FRAMEBUFFER, 2);
1370         context.clearColor(0.6f, 0.0f, 0.0f, 1.0f);
1371         context.scissor(10, 10, 64, 64);
1372         context.clear(GL_COLOR_BUFFER_BIT);
1373         context.clearColor(0.0f, 0.6f, 0.0f, 1.0f);
1374         context.scissor(60, 60, 40, 20);
1375         context.clear(GL_COLOR_BUFFER_BIT);
1376
1377         context.bindFramebuffer(GL_FRAMEBUFFER, 3);
1378         context.clearColor(0.0f, 0.0f, 0.6f, 1.0f);
1379         context.scissor(20, 20, 100, 10);
1380         context.clear(GL_COLOR_BUFFER_BIT);
1381
1382         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1383         context.clearColor(0.6f, 0.0f, 0.6f, 1.0f);
1384         context.scissor(20, 20, 5, 100);
1385         context.clear(GL_COLOR_BUFFER_BIT);
1386
1387         context.disable(GL_SCISSOR_TEST);
1388
1389         if (getConfig().colorbufferType == GL_TEXTURE_2D)
1390         {
1391                 SingleTex2DShader       shader;
1392                 deUint32                        shaderID = context.createProgram(&shader);
1393
1394                 shader.setUnit(context, shaderID, 0);
1395
1396                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1397                 context.viewport(0, 0, context.getWidth(), context.getHeight());
1398                 sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f));
1399                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1400         }
1401         else
1402                 context.readPixels(dst, 0, 0, width, height);
1403 }
1404
1405 class SharedDepthbufferTest : public FboRenderCase
1406 {
1407 public:
1408                                         SharedDepthbufferTest           (Context& context, const FboConfig& config);
1409         virtual                 ~SharedDepthbufferTest          (void) {};
1410
1411         static bool             isConfigSupported                       (const FboConfig& config);
1412         void                    render                                          (sglr::Context& context, Surface& dst);
1413 };
1414
1415 SharedDepthbufferTest::SharedDepthbufferTest (Context& context, const FboConfig& config)
1416         : FboRenderCase(context, config.getName().c_str(), "Shared depthbuffer", config)
1417 {
1418 }
1419
1420 bool SharedDepthbufferTest::isConfigSupported (const FboConfig& config)
1421 {
1422         return config.depthbufferType == GL_RENDERBUFFER;
1423 }
1424
1425 void SharedDepthbufferTest::render (sglr::Context& context, Surface& dst)
1426 {
1427         SingleTex2DShader       texShader;
1428         FlatColorShader         colorShader;
1429         deUint32                        texShaderID             = context.createProgram(&texShader);
1430         deUint32                        colorShaderID   = context.createProgram(&colorShader);
1431         int                                     width                   = 128;
1432         int                                     height                  = 128;
1433         bool                            stencil                 = getConfig().stencilbufferType != GL_NONE;
1434
1435         // Setup shaders
1436         texShader.setUnit(context, texShaderID, 0);
1437         colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1438
1439         // Textures
1440         deUint32 metaballsTex   = 5;
1441         deUint32 quadsTex               = 6;
1442         createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1443         createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1444
1445         context.viewport(0, 0, width, height);
1446
1447         // Fbo A
1448         Framebuffer fboA(context, getConfig(), width, height);
1449         fboA.checkCompleteness();
1450
1451         // Fbo B
1452         FboConfig cfg = getConfig();
1453         cfg.depthbufferType             = GL_NONE;
1454         cfg.depthbufferFormat   = GL_NONE;
1455         Framebuffer fboB(context, cfg, width, height);
1456
1457         // Bind depth buffer from fbo A to fbo B
1458         DE_ASSERT(fboA.getConfig().depthbufferType == GL_RENDERBUFFER);
1459         context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1460         context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboA.getDepthbuffer());
1461
1462         // Clear fbo B color to red and stencil to 1
1463         context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
1464         context.clearStencil(1);
1465         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1466
1467         // Enable depth test.
1468         context.enable(GL_DEPTH_TEST);
1469
1470         // Render quad to fbo A
1471         context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer());
1472         context.bindTexture(GL_TEXTURE_2D, quadsTex);
1473         context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1474         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1475         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1476
1477         // Render metaballs to fbo B
1478         context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1479         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1480         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
1481
1482         context.disable(GL_DEPTH_TEST);
1483
1484         if (stencil)
1485         {
1486                 // Clear subset of stencil buffer to 0
1487                 context.enable(GL_SCISSOR_TEST);
1488                 context.scissor(10, 10, 12, 25);
1489                 context.clearStencil(0);
1490                 context.clear(GL_STENCIL_BUFFER_BIT);
1491                 context.disable(GL_SCISSOR_TEST);
1492
1493                 // Render quad with stencil mask == 0
1494                 context.enable(GL_STENCIL_TEST);
1495                 context.stencilFunc(GL_EQUAL, 0, 0xffu);
1496                 sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1497                 context.disable(GL_STENCIL_TEST);
1498         }
1499
1500         if (getConfig().colorbufferType == GL_TEXTURE_2D)
1501         {
1502                 // Render both to screen
1503                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1504                 context.viewport(0, 0, context.getWidth(), context.getHeight());
1505                 context.bindTexture(GL_TEXTURE_2D, fboA.getColorbuffer());
1506                 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f));
1507                 context.bindTexture(GL_TEXTURE_2D, fboB.getColorbuffer());
1508                 sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1509
1510                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1511         }
1512         else
1513         {
1514                 // Read results from fbo B
1515                 context.readPixels(dst, 0, 0, width, height);
1516         }
1517 }
1518
1519 class TexSubImageAfterRenderTest : public FboRenderCase
1520 {
1521 public:
1522                                         TexSubImageAfterRenderTest              (Context& context, const FboConfig& config);
1523         virtual                 ~TexSubImageAfterRenderTest             (void) {}
1524
1525         static bool             isConfigSupported                               (const FboConfig& config);
1526         void                    render                                                  (sglr::Context& context, Surface& dst);
1527 };
1528
1529 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
1530         : FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
1531 {
1532 }
1533
1534 bool TexSubImageAfterRenderTest::isConfigSupported (const FboConfig& config)
1535 {
1536         return config.colorbufferType == GL_TEXTURE_2D &&
1537                    (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
1538                    config.depthbufferType == GL_NONE &&
1539                    config.stencilbufferType == GL_NONE;
1540 }
1541
1542 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
1543 {
1544         SingleTex2DShader       shader;
1545         deUint32                        shaderID        = context.createProgram(&shader);
1546         bool                            isRGBA          = getConfig().colorbufferFormat == GL_RGBA;
1547
1548         tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1549         tcu::fillWithRGBAQuads(fourQuads.getAccess());
1550
1551         tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1552         tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
1553
1554         shader.setUnit(context, shaderID, 0);
1555
1556         deUint32 fourQuadsTex = 1;
1557         context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1558         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1559         context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());
1560
1561         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1562
1563         deUint32 fboTex = 2;
1564         context.bindTexture(GL_TEXTURE_2D, fboTex);
1565         context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1566         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1567         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1568
1569         // Render to fbo
1570         context.viewport(0, 0, 128, 128);
1571         context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1572         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1573
1574         // Update texture using TexSubImage2D
1575         context.bindTexture(GL_TEXTURE_2D, fboTex);
1576         context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());
1577
1578         // Draw to screen
1579         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1580         context.viewport(0, 0, context.getWidth(), context.getHeight());
1581         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1582         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1583 }
1584
1585 class TexSubImageBetweenRenderTest : public FboRenderCase
1586 {
1587 public:
1588                                         TexSubImageBetweenRenderTest            (Context& context, const FboConfig& config);
1589         virtual                 ~TexSubImageBetweenRenderTest           (void) {}
1590
1591         static bool             isConfigSupported                                       (const FboConfig& config);
1592         void                    render                                                          (sglr::Context& context, Surface& dst);
1593 };
1594
1595 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
1596         : FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
1597 {
1598 }
1599
1600 bool TexSubImageBetweenRenderTest::isConfigSupported (const FboConfig& config)
1601 {
1602         return config.colorbufferType == GL_TEXTURE_2D &&
1603                    (config.colorbufferFormat == GL_RGB || config.colorbufferFormat == GL_RGBA) &&
1604                    config.depthbufferType == GL_NONE &&
1605                    config.stencilbufferType == GL_NONE;
1606 }
1607
1608 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
1609 {
1610         SingleTex2DShader       shader;
1611         deUint32                        shaderID        = context.createProgram(&shader);
1612         bool                            isRGBA          = getConfig().colorbufferFormat == GL_RGBA;
1613
1614         tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1615         tcu::fillWithRGBAQuads(fourQuads.getAccess());
1616
1617         tcu::TextureLevel metaballs(tcu::TextureFormat(isRGBA ? tcu::TextureFormat::RGBA : tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1618         tcu::fillWithMetaballs(metaballs.getAccess(), 5, 3);
1619
1620         tcu::TextureLevel metaballs2(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 64, 64);
1621         tcu::fillWithMetaballs(metaballs2.getAccess(), 5, 4);
1622
1623         deUint32 metaballsTex = 3;
1624         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1625         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1626         context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, metaballs2.getAccess().getDataPtr());
1627
1628         deUint32 fourQuadsTex = 1;
1629         context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1630         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1631         context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, fourQuads.getAccess().getDataPtr());
1632
1633         context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1634
1635         deUint32 fboTex = 2;
1636         context.bindTexture(GL_TEXTURE_2D, fboTex);
1637         context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128);
1638         context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1639         context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
1640
1641         shader.setUnit(context, shaderID, 0);
1642
1643         // Render to fbo
1644         context.viewport(0, 0, 128, 128);
1645         context.bindTexture(GL_TEXTURE_2D, fourQuadsTex);
1646         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1647
1648         // Update texture using TexSubImage2D
1649         context.bindTexture(GL_TEXTURE_2D, fboTex);
1650         context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, 64, 64, isRGBA ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, metaballs.getAccess().getDataPtr());
1651
1652         // Render again to fbo
1653         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1654         context.enable(GL_BLEND);
1655         context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
1656         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1657         context.disable(GL_BLEND);
1658
1659         // Draw to screen
1660         context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1661         context.viewport(0, 0, context.getWidth(), context.getHeight());
1662         context.bindTexture(GL_TEXTURE_2D, fboTex);
1663         sglr::drawQuad(context, shaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1664
1665         context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1666 }
1667
1668 class ResizeTest : public FboRenderCase
1669 {
1670 public:
1671                                         ResizeTest                              (Context& context, const FboConfig& config);
1672         virtual                 ~ResizeTest                             (void) {}
1673
1674         void                    render                                  (sglr::Context& context, Surface& dst);
1675 };
1676
1677 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
1678         : FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config)
1679 {
1680 }
1681
1682 void ResizeTest::render (sglr::Context& context, Surface& dst)
1683 {
1684         SingleTex2DShader       texShader;
1685         FlatColorShader         colorShader;
1686         deUint32                        texShaderID             = context.createProgram(&texShader);
1687         deUint32                        colorShaderID   = context.createProgram(&colorShader);
1688         deUint32                        quadsTex                = 1;
1689         deUint32                        metaballsTex    = 2;
1690         bool                            depth                   = getConfig().depthbufferType    != GL_NONE;
1691         bool                            stencil                 = getConfig().stencilbufferType  != GL_NONE;
1692
1693         createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1694         createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
1695
1696         Framebuffer fbo(context, getConfig(), 128, 128);
1697         fbo.checkCompleteness();
1698
1699         // Setup shaders
1700         texShader.setUnit(context, texShaderID, 0);
1701         colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1702
1703         // Render quads
1704         context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1705         context.viewport(0, 0, 128, 128);
1706         context.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1707         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1708         context.bindTexture(GL_TEXTURE_2D, quadsTex);
1709         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1710
1711         if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
1712         {
1713                 // Render fbo to screen
1714                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1715                 context.viewport(0, 0, context.getWidth(), context.getHeight());
1716                 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1717                 sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1718
1719                 // Restore binding
1720                 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1721         }
1722
1723         int newWidth    = 64;
1724         int newHeight   = 32;
1725
1726         // Resize buffers
1727         switch (fbo.getConfig().colorbufferType)
1728         {
1729                 case GL_TEXTURE_2D:
1730                         context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1731                         context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
1732                         break;
1733
1734                 case GL_RENDERBUFFER:
1735                         context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorbuffer());
1736                         context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
1737                         break;
1738
1739                 default:
1740                         DE_ASSERT(false);
1741         }
1742
1743         if (depth)
1744         {
1745                 DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
1746                 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthbuffer());
1747                 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, newWidth, newHeight);
1748         }
1749
1750         if (stencil)
1751         {
1752                 DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
1753                 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getStencilbuffer());
1754                 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, newWidth, newHeight);
1755         }
1756
1757         // Render to resized fbo
1758         context.viewport(0, 0, newWidth, newHeight);
1759         context.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
1760         context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1761
1762         context.enable(GL_DEPTH_TEST);
1763
1764         context.bindTexture(GL_TEXTURE_2D, metaballsTex);
1765         sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1766
1767         context.bindTexture(GL_TEXTURE_2D, quadsTex);
1768         sglr::drawQuad(context, texShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f));
1769
1770         context.disable(GL_DEPTH_TEST);
1771
1772         if (stencil)
1773         {
1774                 context.enable(GL_SCISSOR_TEST);
1775                 context.scissor(10, 10, 5, 15);
1776                 context.clearStencil(1);
1777                 context.clear(GL_STENCIL_BUFFER_BIT);
1778                 context.disable(GL_SCISSOR_TEST);
1779
1780                 context.enable(GL_STENCIL_TEST);
1781                 context.stencilFunc(GL_EQUAL, 1, 0xffu);
1782                 sglr::drawQuad(context, colorShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
1783                 context.disable(GL_STENCIL_TEST);
1784         }
1785
1786         if (getConfig().colorbufferType == GL_TEXTURE_2D)
1787         {
1788                 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
1789                 context.viewport(0, 0, context.getWidth(), context.getHeight());
1790                 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1791                 sglr::drawQuad(context, texShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f));
1792                 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1793         }
1794         else
1795                 context.readPixels(dst, 0, 0, newWidth, newHeight);
1796 }
1797
1798 template <GLenum Buffers>
1799 class RecreateBuffersTest : public FboRenderCase
1800 {
1801 public:
1802                                         RecreateBuffersTest                     (Context& context, const FboConfig& config, bool rebind);
1803         virtual                 ~RecreateBuffersTest            (void) {}
1804
1805         static bool             isConfigSupported                       (const FboConfig& config);
1806         void                    render                                          (sglr::Context& context, Surface& dst);
1807
1808 private:
1809         bool                    m_rebind;
1810 };
1811
1812 template <GLenum Buffers>
1813 class RecreateBuffersNoRebindTest : public RecreateBuffersTest<Buffers>
1814 {
1815 public:
1816         RecreateBuffersNoRebindTest (Context& context, const FboConfig& config)
1817                 : RecreateBuffersTest<Buffers>(context, config, false)
1818         {
1819         }
1820 };
1821
1822 template <GLenum Buffers>
1823 class RecreateBuffersRebindTest : public RecreateBuffersTest<Buffers>
1824 {
1825 public:
1826         RecreateBuffersRebindTest (Context& context, const FboConfig& config)
1827                 : RecreateBuffersTest<Buffers>(context, config, true)
1828         {
1829         }
1830 };
1831
1832 template <GLenum Buffers>
1833 RecreateBuffersTest<Buffers>::RecreateBuffersTest (Context& context, const FboConfig& config, bool rebind)
1834         : FboRenderCase         (context, (string(rebind ? "rebind_" : "no_rebind_") + config.getName()).c_str(), "Recreate buffers", config)
1835         , m_rebind                      (rebind)
1836 {
1837 }
1838
1839 template <GLenum Buffers>
1840 bool RecreateBuffersTest<Buffers>::isConfigSupported (const FboConfig& config)
1841 {
1842         if ((Buffers & GL_COLOR_BUFFER_BIT) && config.colorbufferType == GL_NONE)
1843                 return false;
1844         if ((Buffers & GL_DEPTH_BUFFER_BIT) && config.depthbufferType == GL_NONE)
1845                 return false;
1846         if ((Buffers & GL_STENCIL_BUFFER_BIT) && config.stencilbufferType == GL_NONE)
1847                 return false;
1848         return true;
1849 }
1850
1851 template <GLenum Buffers>
1852 void RecreateBuffersTest<Buffers>::render (sglr::Context& ctx, Surface& dst)
1853 {
1854         SingleTex2DShader       texShader;
1855         deUint32                        texShaderID             = ctx.createProgram(&texShader);
1856         int                                     width                   = 128;
1857         int                                     height                  = 128;
1858         deUint32                        metaballsTex    = 1;
1859         deUint32                        quadsTex                = 2;
1860         bool                            stencil                 = getConfig().stencilbufferType != GL_NONE;
1861
1862         createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1863         createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1864
1865         Framebuffer fbo(ctx, getConfig(), width, height);
1866         fbo.checkCompleteness();
1867
1868         // Setup shader
1869         texShader.setUnit(ctx, texShaderID, 0);
1870
1871         // Draw scene
1872         ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1873         ctx.viewport(0, 0, width, height);
1874         ctx.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
1875         ctx.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
1876
1877         ctx.enable(GL_DEPTH_TEST);
1878
1879         ctx.bindTexture(GL_TEXTURE_2D, quadsTex);
1880         sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
1881
1882         if (stencil)
1883         {
1884                 ctx.enable(GL_SCISSOR_TEST);
1885                 ctx.scissor(width/4, height/4, width/2, height/2);
1886                 ctx.clearStencil(1);
1887                 ctx.clear(GL_STENCIL_BUFFER_BIT);
1888                 ctx.disable(GL_SCISSOR_TEST);
1889         }
1890
1891         // Recreate buffers
1892         if (!m_rebind)
1893                 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1894
1895         if (Buffers & GL_COLOR_BUFFER_BIT)
1896         {
1897                 deUint32 colorbuf = fbo.getColorbuffer();
1898                 switch (fbo.getConfig().colorbufferType)
1899                 {
1900                         case GL_TEXTURE_2D:
1901                                 ctx.deleteTextures(1, &colorbuf);
1902                                 ctx.bindTexture(GL_TEXTURE_2D, colorbuf);
1903                                 ctx.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, width, height);
1904                                 ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1905
1906                                 if (m_rebind)
1907                                         ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuf, 0);
1908                                 break;
1909
1910                         case GL_RENDERBUFFER:
1911                                 ctx.deleteRenderbuffers(1, &colorbuf);
1912                                 ctx.bindRenderbuffer(GL_RENDERBUFFER, colorbuf);
1913                                 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, width, height);
1914
1915                                 if (m_rebind)
1916                                         ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf);
1917                                 break;
1918
1919                         default:
1920                                 DE_ASSERT(false);
1921                 }
1922         }
1923
1924         if (Buffers & GL_DEPTH_BUFFER_BIT)
1925         {
1926                 deUint32 depthbuf = fbo.getDepthbuffer();
1927                 DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
1928
1929                 ctx.deleteRenderbuffers(1, &depthbuf);
1930                 ctx.bindRenderbuffer(GL_RENDERBUFFER, depthbuf);
1931                 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, width, height);
1932
1933                 if (m_rebind)
1934                         ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuf);
1935         }
1936
1937         if (Buffers & GL_STENCIL_BUFFER_BIT)
1938         {
1939                 deUint32 stencilbuf = fbo.getStencilbuffer();
1940                 DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
1941
1942                 ctx.deleteRenderbuffers(1, &stencilbuf);
1943                 ctx.bindRenderbuffer(GL_RENDERBUFFER, stencilbuf);
1944                 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, width, height);
1945
1946                 if (m_rebind)
1947                         ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilbuf);
1948         }
1949
1950         if (!m_rebind)
1951                 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1952
1953         ctx.clearColor(0.0f, 0.0f, 1.0f, 0.0f);
1954         ctx.clearStencil(0);
1955         ctx.clear(Buffers); // \note Clear only buffers that were re-created
1956
1957         if (stencil)
1958         {
1959                 // \note Stencil test enabled only if we have stencil buffer
1960                 ctx.enable(GL_STENCIL_TEST);
1961                 ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
1962         }
1963         ctx.bindTexture(GL_TEXTURE_2D, metaballsTex);
1964         sglr::drawQuad(ctx, texShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f));
1965         if (stencil)
1966                 ctx.disable(GL_STENCIL_TEST);
1967
1968         ctx.disable(GL_DEPTH_TEST);
1969
1970         // Read from fbo
1971         ctx.readPixels(dst, 0, 0, width, height);
1972 }
1973
1974 class RepeatedClearCase : public FboRenderCase
1975 {
1976 private:
1977         static FboConfig makeConfig (deUint32 format)
1978         {
1979                 FboConfig cfg;
1980                 cfg.colorbufferType             = GL_TEXTURE_2D;
1981                 cfg.colorbufferFormat   = format;
1982                 cfg.depthbufferType             = GL_NONE;
1983                 cfg.stencilbufferType   = GL_NONE;
1984                 return cfg;
1985         }
1986
1987 public:
1988         RepeatedClearCase (Context& context, deUint32 format)
1989                 : FboRenderCase(context, makeConfig(format).getName().c_str(), "Repeated clears", makeConfig(format))
1990         {
1991         }
1992
1993 protected:
1994         void render (sglr::Context& ctx, Surface& dst)
1995         {
1996                 const int                                               numRowsCols             = 4;
1997                 const int                                               cellSize                = 16;
1998                 const int                                               fboSizes[]              = { cellSize, cellSize*numRowsCols };
1999
2000                 SingleTex2DShader                               fboBlitShader;
2001                 const deUint32                                  fboBlitShaderID = ctx.createProgram(&fboBlitShader);
2002
2003                 de::Random                                              rnd                             (18169662);
2004                 deUint32                                                fbos[]                  = { 0, 0 };
2005                 deUint32                                                textures[]              = { 0, 0 };
2006
2007                 ctx.genFramebuffers(2, &fbos[0]);
2008                 ctx.genTextures(2, &textures[0]);
2009
2010                 for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
2011                 {
2012                         ctx.bindTexture(GL_TEXTURE_2D, textures[fboNdx]);
2013                         ctx.texImage2D(GL_TEXTURE_2D, 0, getConfig().colorbufferFormat, fboSizes[fboNdx], fboSizes[fboNdx], 0,
2014                                                    getConfig().colorbufferFormat, GL_UNSIGNED_BYTE, DE_NULL);
2015                         ctx.texParameteri(GL_TEXTURE_2D,        GL_TEXTURE_WRAP_S,              GL_CLAMP_TO_EDGE);
2016                         ctx.texParameteri(GL_TEXTURE_2D,        GL_TEXTURE_WRAP_T,              GL_CLAMP_TO_EDGE);
2017                         ctx.texParameteri(GL_TEXTURE_2D,        GL_TEXTURE_MIN_FILTER,  GL_NEAREST);
2018                         ctx.texParameteri(GL_TEXTURE_2D,        GL_TEXTURE_MAG_FILTER,  GL_NEAREST);
2019
2020                         ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
2021                         ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
2022
2023                         {
2024                                 const GLenum status = ctx.checkFramebufferStatus(GL_FRAMEBUFFER);
2025                                 if (status != GL_FRAMEBUFFER_COMPLETE)
2026                                         throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
2027                         }
2028                 }
2029
2030                 // larger fbo bound -- clear to transparent black
2031                 ctx.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2032                 ctx.clear(GL_COLOR_BUFFER_BIT);
2033
2034                 fboBlitShader.setUnit(ctx, fboBlitShaderID, 0);
2035                 ctx.bindTexture(GL_TEXTURE_2D, textures[0]);
2036
2037                 for (int cellY = 0; cellY < numRowsCols; cellY++)
2038                 for (int cellX = 0; cellX < numRowsCols; cellX++)
2039                 {
2040                         const float     r       = rnd.getFloat();
2041                         const float     g       = rnd.getFloat();
2042                         const float     b       = rnd.getFloat();
2043                         const float     a       = rnd.getFloat();
2044
2045                         ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
2046                         ctx.clearColor(r, g, b, a);
2047                         ctx.clear(GL_COLOR_BUFFER_BIT);
2048
2049                         ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
2050                         ctx.viewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize);
2051                         sglr::drawQuad(ctx, fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
2052                 }
2053
2054                 ctx.readPixels(dst, 0, 0, fboSizes[1], fboSizes[1]);
2055         }
2056 };
2057
2058 } // FboCases
2059
2060 FboRenderTestGroup::FboRenderTestGroup (Context& context)
2061         : TestCaseGroup(context, "render", "Rendering Tests")
2062 {
2063 }
2064
2065 FboRenderTestGroup::~FboRenderTestGroup (void)
2066 {
2067 }
2068
2069 namespace
2070 {
2071
2072 struct TypeFormatPair
2073 {
2074         GLenum          type;
2075         GLenum          format;
2076 };
2077
2078 template <typename CaseType>
2079 void addChildVariants (deqp::gles2::TestCaseGroup* group)
2080 {
2081         TypeFormatPair colorbufferConfigs[] =
2082         {
2083 //              { GL_TEXTURE_2D,        GL_ALPHA },
2084 //              { GL_TEXTURE_2D,        GL_LUMINANCE },
2085 //              { GL_TEXTURE_2D,        GL_LUMINANCE_ALPHA },
2086                 { GL_TEXTURE_2D,        GL_RGB },
2087                 { GL_TEXTURE_2D,        GL_RGBA },
2088                 { GL_RENDERBUFFER,      GL_RGB565 },
2089                 { GL_RENDERBUFFER,      GL_RGB5_A1 },
2090                 { GL_RENDERBUFFER,      GL_RGBA4 },
2091 //              { GL_RENDERBUFFER,      GL_RGBA16F },
2092 //              { GL_RENDERBUFFER,      GL_RGB16F }
2093         };
2094         TypeFormatPair depthbufferConfigs[] =
2095         {
2096                 { GL_NONE,                      GL_NONE },
2097                 { GL_RENDERBUFFER,      GL_DEPTH_COMPONENT16 }
2098         };
2099         TypeFormatPair stencilbufferConfigs[] =
2100         {
2101                 { GL_NONE,                      GL_NONE },
2102                 { GL_RENDERBUFFER,      GL_STENCIL_INDEX8 }
2103         };
2104
2105         for (int colorbufferNdx = 0; colorbufferNdx < DE_LENGTH_OF_ARRAY(colorbufferConfigs); colorbufferNdx++)
2106         for (int depthbufferNdx = 0; depthbufferNdx < DE_LENGTH_OF_ARRAY(depthbufferConfigs); depthbufferNdx++)
2107         for (int stencilbufferNdx = 0; stencilbufferNdx < DE_LENGTH_OF_ARRAY(stencilbufferConfigs); stencilbufferNdx++)
2108         {
2109                 FboConfig config;
2110                 config.colorbufferType          = colorbufferConfigs[colorbufferNdx].type;
2111                 config.colorbufferFormat        = colorbufferConfigs[colorbufferNdx].format;
2112                 config.depthbufferType          = depthbufferConfigs[depthbufferNdx].type;
2113                 config.depthbufferFormat        = depthbufferConfigs[depthbufferNdx].format;
2114                 config.stencilbufferType        = stencilbufferConfigs[stencilbufferNdx].type;
2115                 config.stencilbufferFormat      = stencilbufferConfigs[stencilbufferNdx].format;
2116
2117                 if (CaseType::isConfigSupported(config))
2118                         group->addChild(new CaseType(group->getContext(), config));
2119         }
2120 }
2121
2122 template <typename CaseType>
2123 void createChildGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
2124 {
2125         deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
2126         parent->addChild(tmpGroup);
2127         addChildVariants<CaseType>(tmpGroup);
2128 }
2129
2130 template <GLbitfield Buffers>
2131 void createRecreateBuffersGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
2132 {
2133         deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
2134         parent->addChild(tmpGroup);
2135         addChildVariants<FboCases::RecreateBuffersRebindTest<Buffers> >         (tmpGroup);
2136         addChildVariants<FboCases::RecreateBuffersNoRebindTest<Buffers> >       (tmpGroup);
2137 }
2138
2139 } // anonymous
2140
2141 void FboRenderTestGroup::init (void)
2142 {
2143         createChildGroup<FboCases::ColorClearsTest>                                     (this, "color_clear",           "Color buffer clears");
2144         createChildGroup<FboCases::StencilClearsTest>                           (this, "stencil_clear",         "Stencil buffer clears");
2145
2146         deqp::gles2::TestCaseGroup* colorGroup = new deqp::gles2::TestCaseGroup(m_context, "color", "Color buffer tests");
2147         addChild(colorGroup);
2148         addChildVariants<FboCases::MixTest>                     (colorGroup);
2149         addChildVariants<FboCases::MixNpotTest>         (colorGroup);
2150         addChildVariants<FboCases::BlendTest>           (colorGroup);
2151         addChildVariants<FboCases::BlendNpotTest>       (colorGroup);
2152
2153         deqp::gles2::TestCaseGroup* depthGroup = new deqp::gles2::TestCaseGroup(m_context, "depth", "Depth bufer tests");
2154         addChild(depthGroup);
2155         addChildVariants<FboCases::IntersectingQuadsTest>               (depthGroup);
2156         addChildVariants<FboCases::IntersectingQuadsNpotTest>   (depthGroup);
2157
2158         deqp::gles2::TestCaseGroup* stencilGroup = new deqp::gles2::TestCaseGroup(m_context, "stencil", "Stencil buffer tests");
2159         addChild(stencilGroup);
2160         addChildVariants<FboCases::StencilTest>         (stencilGroup);
2161         addChildVariants<FboCases::StencilNpotTest>     (stencilGroup);
2162
2163         createChildGroup<FboCases::SharedColorbufferClearsTest>         (this, "shared_colorbuffer_clear",      "Shared colorbuffer clears");
2164         createChildGroup<FboCases::SharedColorbufferTest>                       (this, "shared_colorbuffer",            "Shared colorbuffer tests");
2165         createChildGroup<FboCases::SharedDepthbufferTest>                       (this, "shared_depthbuffer",            "Shared depthbuffer tests");
2166         createChildGroup<FboCases::ResizeTest>                                          (this, "resize",                                        "FBO resize tests");
2167
2168         createRecreateBuffersGroup<GL_COLOR_BUFFER_BIT>                         (this, "recreate_colorbuffer",          "Recreate colorbuffer tests");
2169         createRecreateBuffersGroup<GL_DEPTH_BUFFER_BIT>                         (this, "recreate_depthbuffer",          "Recreate depthbuffer tests");
2170         createRecreateBuffersGroup<GL_STENCIL_BUFFER_BIT>                       (this, "recreate_stencilbuffer",        "Recreate stencilbuffer tests");
2171
2172         deqp::gles2::TestCaseGroup* texSubImageGroup = new deqp::gles2::TestCaseGroup(m_context, "texsubimage", "TexSubImage interop with FBO colorbuffer texture");
2173         addChild(texSubImageGroup);
2174         addChildVariants<FboCases::TexSubImageAfterRenderTest>          (texSubImageGroup);
2175         addChildVariants<FboCases::TexSubImageBetweenRenderTest>        (texSubImageGroup);
2176
2177         {
2178                 tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated FBO clears");
2179                 addChild(repeatedClearGroup);
2180
2181                 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGB));
2182                 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGBA));
2183         }
2184 }
2185
2186 } // Functional
2187 } // gles2
2188 } // deqp