1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Framebuffer Object Tests.
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 *//*--------------------------------------------------------------------*/
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"
43 #include "glwFunctions.hpp"
44 #include "glwEnums.hpp"
53 using namespace glw; // GL types
64 class FlatColorShader : public sglr::ShaderProgram
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"
76 " gl_Position = a_position;\n"
78 << sglr::pdec::FragmentSource(
79 "uniform mediump vec4 u_color;\n"
82 " gl_FragColor = u_color;\n"
87 void setColor (sglr::Context& gl, deUint32 program, const tcu::Vec4& color)
89 gl.useProgram(program);
90 gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, color.getPtr());
93 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
95 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
96 packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
99 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
101 const tcu::Vec4 color(m_uniforms[0].value.f4);
105 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
106 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
107 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
111 class SingleTex2DShader : public sglr::ShaderProgram
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"
127 " gl_Position = a_position;\n"
128 " v_coord = a_coord;\n"
130 << sglr::pdec::FragmentSource(
131 "uniform sampler2D u_sampler0;\n"
132 "varying mediump vec2 v_coord;\n"
135 " gl_FragColor = texture2D(u_sampler0, v_coord);\n"
140 void setUnit (sglr::Context& gl, deUint32 program, int unitNdx)
142 gl.useProgram(program);
143 gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unitNdx);
146 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
148 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
150 rr::VertexPacket& packet = *packets[packetNdx];
152 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
153 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
157 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
159 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
160 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
162 const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
163 const float lod = 0.0f;
165 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, this->m_uniforms[0].sampler.tex2D->sample(v_coord.x(), v_coord.y(), lod));
171 class MixTexturesShader : public sglr::ShaderProgram
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"
188 " gl_Position = a_position;\n"
189 " v_coord = a_coord;\n"
191 << sglr::pdec::FragmentSource(
192 "uniform sampler2D u_sampler0;\n"
193 "uniform sampler2D u_sampler1;\n"
194 "varying mediump vec2 v_coord;\n"
197 " gl_FragColor = texture2D(u_sampler0, v_coord)*0.5 + texture2D(u_sampler1, v_coord)*0.5;\n"
202 void setUnits (sglr::Context& gl, deUint32 program, int unit0, int unit1)
204 gl.useProgram(program);
205 gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), unit0);
206 gl.uniform1i(gl.getUniformLocation(program, "u_sampler1"), unit1);
209 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
211 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
213 rr::VertexPacket& packet = *packets[packetNdx];
215 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
216 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
220 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
222 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
223 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
225 const tcu::Vec4 v_coord = rr::readVarying<float>(packets[packetNdx], context, 0, fragNdx);
226 const float lod = 0.0f;
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);
234 // Framebuffer config.
240 : colorbufferType (GL_NONE)
241 , colorbufferFormat (GL_NONE)
242 , depthbufferType (GL_NONE)
243 , depthbufferFormat (GL_NONE)
244 , stencilbufferType (GL_NONE)
245 , stencilbufferFormat (GL_NONE)
249 std::string getName (void) const;
251 GLenum colorbufferType; //!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER
252 GLenum colorbufferFormat; //!< Internal format for color buffer texture or renderbuffer
254 GLenum depthbufferType; //!< GL_RENDERBUFFER
255 GLenum depthbufferFormat;
257 GLenum stencilbufferType; //!< GL_RENDERBUFFER
258 GLenum stencilbufferFormat;
261 static const char* getFormatName (GLenum format);
264 const char* FboConfig::getFormatName (GLenum format)
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;
284 std::string FboConfig::getName (void) const
286 std::string name = "";
288 if (colorbufferType != GL_NONE)
290 switch (colorbufferType)
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;
297 name += getFormatName(colorbufferFormat);
300 if (depthbufferType != GL_NONE)
302 DE_ASSERT(depthbufferType == GL_RENDERBUFFER);
303 if (name.length() > 0)
305 name += getFormatName(depthbufferFormat);
308 if (stencilbufferType != GL_NONE)
310 DE_ASSERT(stencilbufferType == GL_RENDERBUFFER);
311 if (name.length() > 0)
313 name += getFormatName(stencilbufferFormat);
319 class FboIncompleteException : public tcu::TestError
322 FboIncompleteException (const FboConfig& config, GLenum reason, const char* file, int line);
323 virtual ~FboIncompleteException (void) throw() {}
325 const FboConfig& getConfig (void) const { return m_config; }
326 GLenum getReason (void) const { return m_reason; }
333 static const char* getFboIncompleteReasonName (GLenum reason)
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";
346 FboIncompleteException::FboIncompleteException (const FboConfig& config, GLenum reason, const char* file, int line)
347 : TestError("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
356 Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorbuffer = 0, deUint32 depthbuffer = 0, deUint32 stencilbuffer = 0);
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; }
365 void checkCompleteness (void);
368 void createRbo (deUint32& name, GLenum format, int width, int height);
369 void destroyBuffer (deUint32 name, GLenum type);
372 sglr::Context& m_context;
373 deUint32 m_framebuffer;
374 deUint32 m_colorbuffer;
375 deUint32 m_depthbuffer;
376 deUint32 m_stencilbuffer;
379 static bool isExtensionSupported (sglr::Context& context, const char* name)
381 std::istringstream extensions(context.getString(GL_EXTENSIONS));
382 std::string extension;
384 while (std::getline(extensions, extension, ' '))
386 if (extension == name)
393 static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat)
401 if (!isExtensionSupported(context, "GL_EXT_color_buffer_half_float"))
402 throw tcu::NotSupportedError("GL_EXT_color_buffer_half_float is not supported");
409 Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorbuffer, deUint32 depthbuffer, deUint32 stencilbuffer)
411 , m_context (context)
412 , m_framebuffer (fbo)
413 , m_colorbuffer (colorbuffer)
414 , m_depthbuffer (depthbuffer)
415 , m_stencilbuffer (stencilbuffer)
417 // Verify that color format is supported
418 checkColorFormatSupport(context, config.colorbufferFormat);
420 if (m_framebuffer == 0)
421 context.genFramebuffers(1, &m_framebuffer);
422 context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
424 switch (m_config.colorbufferType)
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);
433 if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height))
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);
440 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorbuffer, 0);
443 case GL_TEXTURE_CUBE_MAP:
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);
453 DE_ASSERT(m_config.colorbufferType == GL_NONE);
457 if (m_config.depthbufferType == GL_RENDERBUFFER)
459 createRbo(m_depthbuffer, m_config.depthbufferFormat, width, height);
460 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer);
463 DE_ASSERT(m_config.depthbufferType == GL_NONE);
465 if (m_config.stencilbufferType == GL_RENDERBUFFER)
467 createRbo(m_stencilbuffer, m_config.stencilbufferFormat, width, height);
468 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilbuffer);
471 DE_ASSERT(m_config.stencilbufferType == GL_NONE);
473 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
476 Framebuffer::~Framebuffer (void)
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);
484 void Framebuffer::checkCompleteness (void)
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__);
493 void Framebuffer::createRbo (deUint32& name, GLenum format, int width, int height)
496 m_context.genRenderbuffers(1, &name);
497 m_context.bindRenderbuffer(GL_RENDERBUFFER, name);
498 m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
501 void Framebuffer::destroyBuffer (deUint32 name, GLenum type)
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);
508 DE_ASSERT(type == GL_NONE);
511 static void createMetaballsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
513 tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType);
514 tcu::TextureLevel level (texFormat, width, height);
516 tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height);
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);
523 static void createQuadsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height)
525 tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType);
526 tcu::TextureLevel level (texFormat, width, height);
528 tcu::fillWithRGBAQuads(level.getAccess());
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);
535 class FboRenderCase : public TestCase
538 FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config);
539 virtual ~FboRenderCase (void) {}
541 virtual IterateResult iterate (void);
542 virtual void render (sglr::Context& fboContext, Surface& dst) = DE_NULL;
544 const FboConfig& getConfig (void) const { return m_config; }
546 static bool isConfigSupported (const FboConfig& config) { DE_UNREF(config); return true; }
552 FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config)
553 : TestCase(context, name, description)
558 TestCase::IterateResult FboRenderCase::iterate (void)
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;
566 // Position & size for context
568 deRandom_init(&rnd, deStringHash(getName()));
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;
577 tcu::Surface gles2Frame (width, height);
578 tcu::Surface refFrame (width, height);
582 // Render using GLES2
585 sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
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);
590 render(context, gles2Frame); // Call actual render func
591 gles2Error = context.getError();
593 catch (const FboIncompleteException& e)
595 if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED)
597 // Mark test case as unsupported
599 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
603 throw; // Propagate error
606 // Render reference image
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());
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);
614 render(context, refFrame);
615 refError = context.getError();
618 // Compare error codes
619 bool errorCodesOk = (gles2Error == refError);
623 log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles2Error) << ", expected " << glu::getErrorStr(refError) << tcu::TestLog::EndMessage;
624 failReason = "Got unexpected error";
628 const float threshold = 0.03f;
629 bool imagesOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, gles2Frame, threshold, tcu::COMPARE_LOG_RESULT);
631 if (!imagesOk && !failReason)
632 failReason = "Image comparison failed";
635 bool isOk = errorCodesOk && imagesOk;
636 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
637 isOk ? "Pass" : failReason);
645 class ColorClearsTest : public FboRenderCase
648 ColorClearsTest (Context& context, const FboConfig& config);
649 ~ColorClearsTest (void) {}
651 void render (sglr::Context& context, Surface& dst);
654 ColorClearsTest::ColorClearsTest (Context& context, const FboConfig& config)
655 : FboRenderCase(context, config.getName().c_str(), "Color buffer clears", config)
659 void ColorClearsTest::render (sglr::Context& context, Surface& dst)
665 deRandom_init(&rnd, 0);
667 // Create framebuffer
668 Framebuffer fbo(context, getConfig(), width, height);
669 fbo.checkCompleteness();
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);
677 // Enable scissor test.
678 context.enable(GL_SCISSOR_TEST);
680 // Do 10 random color clears
681 for (int i = 0; i < 15; i++)
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();
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);
695 context.disable(GL_SCISSOR_TEST);
697 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
700 context.bindFramebuffer(GL_FRAMEBUFFER, 0);
703 SingleTex2DShader shader;
704 deUint32 shaderID = context.createProgram(&shader);
706 shader.setUnit(context, shaderID, 0);
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));
713 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
718 context.readPixels(dst, 0, 0, width, height);
722 class IntersectingQuadsTest : public FboRenderCase
725 IntersectingQuadsTest (Context& context, const FboConfig& config, bool npot = false);
726 virtual ~IntersectingQuadsTest (void) {}
728 virtual void render (sglr::Context& context, Surface& dst);
730 static bool isConfigSupported (const FboConfig& config);
737 class IntersectingQuadsNpotTest : public IntersectingQuadsTest
740 IntersectingQuadsNpotTest (Context& context, const FboConfig& config)
741 : IntersectingQuadsTest(context, config, true)
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)
753 bool IntersectingQuadsTest::isConfigSupported (const FboConfig& config)
755 // \note Disabled for stencil configurations since doesn't exercise stencil buffer
756 return config.depthbufferType != GL_NONE &&
757 config.stencilbufferType == GL_NONE;
760 void IntersectingQuadsTest::render (sglr::Context& ctx, Surface& dst)
762 SingleTex2DShader texShader;
763 deUint32 texShaderID = ctx.createProgram(&texShader);
765 deUint32 metaballsTex = 1;
766 deUint32 quadsTex = 2;
768 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
769 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
771 int width = m_fboWidth;
772 int height = m_fboHeight;
773 Framebuffer fbo(ctx, getConfig(), width, height);
774 fbo.checkCompleteness();
777 texShader.setUnit(ctx, texShaderID, 0);
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);
785 ctx.enable(GL_DEPTH_TEST);
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));
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));
793 ctx.disable(GL_DEPTH_TEST);
795 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
798 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
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));
806 ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
811 ctx.readPixels(dst, 0, 0, width, height);
815 class MixTest : public FboRenderCase
818 MixTest (Context& context, const FboConfig& config, bool npot = false);
819 virtual ~MixTest (void) {}
821 void render (sglr::Context& context, Surface& dst);
823 static bool isConfigSupported (const FboConfig& config);
832 class MixNpotTest : public MixTest
835 MixNpotTest (Context& context, const FboConfig& config)
836 : MixTest(context, config, true)
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)
850 bool MixTest::isConfigSupported (const FboConfig& config)
852 // \note Disabled for stencil configurations since doesn't exercise stencil buffer
853 return config.colorbufferType == GL_TEXTURE_2D &&
854 config.stencilbufferType == GL_NONE;
857 void MixTest::render (sglr::Context& context, Surface& dst)
859 SingleTex2DShader singleTexShader;
860 MixTexturesShader mixShader;
862 deUint32 singleTexShaderID = context.createProgram(&singleTexShader);
863 deUint32 mixShaderID = context.createProgram(&mixShader);
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);
871 singleTexShader.setUnit(context, singleTexShaderID, 0);
872 mixShader.setUnits(context, mixShaderID, 0, 1);
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));
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);
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));
907 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
910 class BlendTest : public FboRenderCase
913 BlendTest (Context& context, const FboConfig& config, bool npot = false);
914 virtual ~BlendTest (void) {}
916 void render (sglr::Context& context, Surface& dst);
918 static bool isConfigSupported (const FboConfig& config);
925 class BlendNpotTest : public BlendTest
928 BlendNpotTest (Context& context, const FboConfig& config)
929 : BlendTest(context, config, true)
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)
941 bool BlendTest::isConfigSupported (const FboConfig& config)
943 // \note Disabled for stencil configurations since doesn't exercise stencil buffer
944 return config.stencilbufferType == GL_NONE;
947 void BlendTest::render (sglr::Context& context, Surface& dst)
949 SingleTex2DShader shader;
950 deUint32 shaderID = context.createProgram(&shader);
951 int width = m_fboWidth;
952 int height = m_fboHeight;
953 deUint32 metaballsTex = 1;
955 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64);
957 Framebuffer fbo(context, getConfig(), width, height);
958 fbo.checkCompleteness();
960 shader.setUnit(context, shaderID, 0);
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);
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);
974 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
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());
983 context.readPixels(dst, 0, 0, width, height);
986 class StencilClearsTest : public FboRenderCase
989 StencilClearsTest (Context& context, const FboConfig& config);
990 virtual ~StencilClearsTest (void) {};
992 void render (sglr::Context& context, Surface& dst);
994 static bool isConfigSupported (const FboConfig& config);
997 StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config)
998 : FboRenderCase(context, config.getName().c_str(), "Stencil clears", config)
1002 void StencilClearsTest::render (sglr::Context& context, Surface& dst)
1004 SingleTex2DShader shader;
1005 deUint32 shaderID = context.createProgram(&shader);
1008 deUint32 quadsTex = 1;
1009 deUint32 metaballsTex = 2;
1011 createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1012 createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height);
1014 Framebuffer fbo(context, getConfig(), width, height);
1015 fbo.checkCompleteness();
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);
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);
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);
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));
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));
1048 context.disable(GL_STENCIL_TEST);
1050 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
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());
1061 context.readPixels(dst, 0, 0, width, height);
1064 bool StencilClearsTest::isConfigSupported (const FboConfig& config)
1066 return config.stencilbufferType != GL_NONE;
1069 class StencilTest : public FboRenderCase
1072 StencilTest (Context& context, const FboConfig& config, bool npot = false);
1073 virtual ~StencilTest (void) {};
1075 void render (sglr::Context& context, Surface& dst);
1077 static bool isConfigSupported (const FboConfig& config);
1084 class StencilNpotTest : public StencilTest
1087 StencilNpotTest (Context& context, const FboConfig& config)
1088 : StencilTest(context, config, true)
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)
1100 bool StencilTest::isConfigSupported (const FboConfig& config)
1102 return config.stencilbufferType != GL_NONE;
1105 void StencilTest::render (sglr::Context& ctx, Surface& dst)
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;
1115 deUint32 quadsTex = 1;
1116 deUint32 metaballsTex = 2;
1117 bool depth = getConfig().depthbufferType != GL_NONE;
1119 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
1120 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
1122 Framebuffer fbo(ctx, getConfig(), width, height);
1123 fbo.checkCompleteness();
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);
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);
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));
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));
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));
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));
1157 ctx.disable(GL_STENCIL_TEST);
1159 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
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());
1169 ctx.readPixels(dst, 0, 0, width, height);
1172 class SharedColorbufferTest : public FboRenderCase
1175 SharedColorbufferTest (Context& context, const FboConfig& config);
1176 virtual ~SharedColorbufferTest (void) {};
1178 void render (sglr::Context& context, Surface& dst);
1181 SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config)
1182 : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer", config)
1186 void SharedColorbufferTest::render (sglr::Context& context, Surface& dst)
1188 SingleTex2DShader shader;
1189 deUint32 shaderID = context.createProgram(&shader);
1192 // bool depth = getConfig().depthbufferFormat != GL_NONE;
1193 bool stencil = getConfig().stencilbufferFormat != GL_NONE;
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);
1201 context.viewport(0, 0, width, height);
1203 shader.setUnit(context, shaderID, 0);
1206 Framebuffer fboA(context, getConfig(), width, height);
1207 fboA.checkCompleteness();
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);
1215 // Attach color buffer from fbo A
1216 context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer());
1217 switch (getConfig().colorbufferType)
1220 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorbuffer(), 0);
1223 case GL_RENDERBUFFER:
1224 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorbuffer());
1231 // Clear depth and stencil in fbo B
1232 context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
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);
1242 // Stencil to 1 in fbo A
1243 context.clearStencil(1);
1244 context.clear(GL_STENCIL_BUFFER_BIT);
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);
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));
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);
1266 FlatColorShader flatShader;
1267 deUint32 flatShaderID = context.createProgram(&flatShader);
1269 flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
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);
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);
1286 if (fboA.getConfig().colorbufferType == GL_TEXTURE_2D)
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());
1295 context.readPixels(dst, 0, 0, width, height);
1298 class SharedColorbufferClearsTest : public FboRenderCase
1301 SharedColorbufferClearsTest (Context& context, const FboConfig& config);
1302 virtual ~SharedColorbufferClearsTest (void) {}
1304 static bool isConfigSupported (const FboConfig& config);
1305 void render (sglr::Context& context, Surface& dst);
1308 SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config)
1309 : FboRenderCase(context, config.getName().c_str(), "Shared colorbuffer clears", config)
1313 bool SharedColorbufferClearsTest::isConfigSupported (const FboConfig& config)
1315 return config.colorbufferType != GL_NONE &&
1316 config.depthbufferType == GL_NONE &&
1317 config.stencilbufferType == GL_NONE;
1320 void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst)
1324 deUint32 colorbuffer = 1;
1326 checkColorFormatSupport(context, getConfig().colorbufferFormat);
1328 // Single colorbuffer
1329 if (getConfig().colorbufferType == GL_TEXTURE_2D)
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);
1337 DE_ASSERT(getConfig().colorbufferType == GL_RENDERBUFFER);
1338 context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer);
1339 context.renderbufferStorage(GL_RENDERBUFFER, getConfig().colorbufferFormat, width, height);
1342 // Multiple framebuffers sharing the colorbuffer
1343 for (int fbo = 1; fbo <= 3; fbo++)
1345 context.bindFramebuffer(GL_FRAMEBUFFER, fbo);
1347 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1348 context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
1350 context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
1353 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
1355 // Check completeness
1357 GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER);
1358 if (status != GL_FRAMEBUFFER_COMPLETE)
1359 throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
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);
1367 context.enable(GL_SCISSOR_TEST);
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);
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);
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);
1387 context.disable(GL_SCISSOR_TEST);
1389 if (getConfig().colorbufferType == GL_TEXTURE_2D)
1391 SingleTex2DShader shader;
1392 deUint32 shaderID = context.createProgram(&shader);
1394 shader.setUnit(context, shaderID, 0);
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());
1402 context.readPixels(dst, 0, 0, width, height);
1405 class SharedDepthbufferTest : public FboRenderCase
1408 SharedDepthbufferTest (Context& context, const FboConfig& config);
1409 virtual ~SharedDepthbufferTest (void) {};
1411 static bool isConfigSupported (const FboConfig& config);
1412 void render (sglr::Context& context, Surface& dst);
1415 SharedDepthbufferTest::SharedDepthbufferTest (Context& context, const FboConfig& config)
1416 : FboRenderCase(context, config.getName().c_str(), "Shared depthbuffer", config)
1420 bool SharedDepthbufferTest::isConfigSupported (const FboConfig& config)
1422 return config.depthbufferType == GL_RENDERBUFFER;
1425 void SharedDepthbufferTest::render (sglr::Context& context, Surface& dst)
1427 SingleTex2DShader texShader;
1428 FlatColorShader colorShader;
1429 deUint32 texShaderID = context.createProgram(&texShader);
1430 deUint32 colorShaderID = context.createProgram(&colorShader);
1433 bool stencil = getConfig().stencilbufferType != GL_NONE;
1436 texShader.setUnit(context, texShaderID, 0);
1437 colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
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);
1445 context.viewport(0, 0, width, height);
1448 Framebuffer fboA(context, getConfig(), width, height);
1449 fboA.checkCompleteness();
1452 FboConfig cfg = getConfig();
1453 cfg.depthbufferType = GL_NONE;
1454 cfg.depthbufferFormat = GL_NONE;
1455 Framebuffer fboB(context, cfg, width, height);
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());
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);
1467 // Enable depth test.
1468 context.enable(GL_DEPTH_TEST);
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));
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));
1482 context.disable(GL_DEPTH_TEST);
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);
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);
1500 if (getConfig().colorbufferType == GL_TEXTURE_2D)
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));
1510 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1514 // Read results from fbo B
1515 context.readPixels(dst, 0, 0, width, height);
1519 class TexSubImageAfterRenderTest : public FboRenderCase
1522 TexSubImageAfterRenderTest (Context& context, const FboConfig& config);
1523 virtual ~TexSubImageAfterRenderTest (void) {}
1525 static bool isConfigSupported (const FboConfig& config);
1526 void render (sglr::Context& context, Surface& dst);
1529 TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config)
1530 : FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config)
1534 bool TexSubImageAfterRenderTest::isConfigSupported (const FboConfig& config)
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;
1542 void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst)
1544 SingleTex2DShader shader;
1545 deUint32 shaderID = context.createProgram(&shader);
1546 bool isRGBA = getConfig().colorbufferFormat == GL_RGBA;
1548 tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1549 tcu::fillWithRGBAQuads(fourQuads.getAccess());
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);
1554 shader.setUnit(context, shaderID, 0);
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());
1561 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
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);
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));
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());
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());
1585 class TexSubImageBetweenRenderTest : public FboRenderCase
1588 TexSubImageBetweenRenderTest (Context& context, const FboConfig& config);
1589 virtual ~TexSubImageBetweenRenderTest (void) {}
1591 static bool isConfigSupported (const FboConfig& config);
1592 void render (sglr::Context& context, Surface& dst);
1595 TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config)
1596 : FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config)
1600 bool TexSubImageBetweenRenderTest::isConfigSupported (const FboConfig& config)
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;
1608 void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst)
1610 SingleTex2DShader shader;
1611 deUint32 shaderID = context.createProgram(&shader);
1612 bool isRGBA = getConfig().colorbufferFormat == GL_RGBA;
1614 tcu::TextureLevel fourQuads(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), 64, 64);
1615 tcu::fillWithRGBAQuads(fourQuads.getAccess());
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);
1620 tcu::TextureLevel metaballs2(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), 64, 64);
1621 tcu::fillWithMetaballs(metaballs2.getAccess(), 5, 4);
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());
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());
1633 context.bindFramebuffer(GL_FRAMEBUFFER, 1);
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);
1641 shader.setUnit(context, shaderID, 0);
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));
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());
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);
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));
1665 context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight());
1668 class ResizeTest : public FboRenderCase
1671 ResizeTest (Context& context, const FboConfig& config);
1672 virtual ~ResizeTest (void) {}
1674 void render (sglr::Context& context, Surface& dst);
1677 ResizeTest::ResizeTest (Context& context, const FboConfig& config)
1678 : FboRenderCase(context, config.getName().c_str(), "Resize framebuffer", config)
1682 void ResizeTest::render (sglr::Context& context, Surface& dst)
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;
1693 createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1694 createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32);
1696 Framebuffer fbo(context, getConfig(), 128, 128);
1697 fbo.checkCompleteness();
1700 texShader.setUnit(context, texShaderID, 0);
1701 colorShader.setColor(context, colorShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f));
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));
1711 if (fbo.getConfig().colorbufferType == GL_TEXTURE_2D)
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));
1720 context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
1727 switch (fbo.getConfig().colorbufferType)
1730 context.bindTexture(GL_TEXTURE_2D, fbo.getColorbuffer());
1731 context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
1734 case GL_RENDERBUFFER:
1735 context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorbuffer());
1736 context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorbufferFormat, newWidth, newHeight);
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);
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);
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);
1762 context.enable(GL_DEPTH_TEST);
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));
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));
1770 context.disable(GL_DEPTH_TEST);
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);
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);
1786 if (getConfig().colorbufferType == GL_TEXTURE_2D)
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());
1795 context.readPixels(dst, 0, 0, newWidth, newHeight);
1798 template <GLenum Buffers>
1799 class RecreateBuffersTest : public FboRenderCase
1802 RecreateBuffersTest (Context& context, const FboConfig& config, bool rebind);
1803 virtual ~RecreateBuffersTest (void) {}
1805 static bool isConfigSupported (const FboConfig& config);
1806 void render (sglr::Context& context, Surface& dst);
1812 template <GLenum Buffers>
1813 class RecreateBuffersNoRebindTest : public RecreateBuffersTest<Buffers>
1816 RecreateBuffersNoRebindTest (Context& context, const FboConfig& config)
1817 : RecreateBuffersTest<Buffers>(context, config, false)
1822 template <GLenum Buffers>
1823 class RecreateBuffersRebindTest : public RecreateBuffersTest<Buffers>
1826 RecreateBuffersRebindTest (Context& context, const FboConfig& config)
1827 : RecreateBuffersTest<Buffers>(context, config, true)
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)
1839 template <GLenum Buffers>
1840 bool RecreateBuffersTest<Buffers>::isConfigSupported (const FboConfig& config)
1842 if ((Buffers & GL_COLOR_BUFFER_BIT) && config.colorbufferType == GL_NONE)
1844 if ((Buffers & GL_DEPTH_BUFFER_BIT) && config.depthbufferType == GL_NONE)
1846 if ((Buffers & GL_STENCIL_BUFFER_BIT) && config.stencilbufferType == GL_NONE)
1851 template <GLenum Buffers>
1852 void RecreateBuffersTest<Buffers>::render (sglr::Context& ctx, Surface& dst)
1854 SingleTex2DShader texShader;
1855 deUint32 texShaderID = ctx.createProgram(&texShader);
1858 deUint32 metaballsTex = 1;
1859 deUint32 quadsTex = 2;
1860 bool stencil = getConfig().stencilbufferType != GL_NONE;
1862 createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1863 createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64);
1865 Framebuffer fbo(ctx, getConfig(), width, height);
1866 fbo.checkCompleteness();
1869 texShader.setUnit(ctx, texShaderID, 0);
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);
1877 ctx.enable(GL_DEPTH_TEST);
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));
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);
1893 ctx.bindFramebuffer(GL_FRAMEBUFFER, 0);
1895 if (Buffers & GL_COLOR_BUFFER_BIT)
1897 deUint32 colorbuf = fbo.getColorbuffer();
1898 switch (fbo.getConfig().colorbufferType)
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);
1907 ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuf, 0);
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);
1916 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuf);
1924 if (Buffers & GL_DEPTH_BUFFER_BIT)
1926 deUint32 depthbuf = fbo.getDepthbuffer();
1927 DE_ASSERT(fbo.getConfig().depthbufferType == GL_RENDERBUFFER);
1929 ctx.deleteRenderbuffers(1, &depthbuf);
1930 ctx.bindRenderbuffer(GL_RENDERBUFFER, depthbuf);
1931 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthbufferFormat, width, height);
1934 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuf);
1937 if (Buffers & GL_STENCIL_BUFFER_BIT)
1939 deUint32 stencilbuf = fbo.getStencilbuffer();
1940 DE_ASSERT(fbo.getConfig().stencilbufferType == GL_RENDERBUFFER);
1942 ctx.deleteRenderbuffers(1, &stencilbuf);
1943 ctx.bindRenderbuffer(GL_RENDERBUFFER, stencilbuf);
1944 ctx.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().stencilbufferFormat, width, height);
1947 ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilbuf);
1951 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer());
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
1959 // \note Stencil test enabled only if we have stencil buffer
1960 ctx.enable(GL_STENCIL_TEST);
1961 ctx.stencilFunc(GL_EQUAL, 0, 0xffu);
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));
1966 ctx.disable(GL_STENCIL_TEST);
1968 ctx.disable(GL_DEPTH_TEST);
1971 ctx.readPixels(dst, 0, 0, width, height);
1974 class RepeatedClearCase : public FboRenderCase
1977 static FboConfig makeConfig (deUint32 format)
1980 cfg.colorbufferType = GL_TEXTURE_2D;
1981 cfg.colorbufferFormat = format;
1982 cfg.depthbufferType = GL_NONE;
1983 cfg.stencilbufferType = GL_NONE;
1988 RepeatedClearCase (Context& context, deUint32 format)
1989 : FboRenderCase(context, makeConfig(format).getName().c_str(), "Repeated clears", makeConfig(format))
1994 void render (sglr::Context& ctx, Surface& dst)
1996 const int numRowsCols = 4;
1997 const int cellSize = 16;
1998 const int fboSizes[] = { cellSize, cellSize*numRowsCols };
2000 SingleTex2DShader fboBlitShader;
2001 const deUint32 fboBlitShaderID = ctx.createProgram(&fboBlitShader);
2003 de::Random rnd (18169662);
2004 deUint32 fbos[] = { 0, 0 };
2005 deUint32 textures[] = { 0, 0 };
2007 ctx.genFramebuffers(2, &fbos[0]);
2008 ctx.genTextures(2, &textures[0]);
2010 for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
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);
2020 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
2021 ctx.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
2024 const GLenum status = ctx.checkFramebufferStatus(GL_FRAMEBUFFER);
2025 if (status != GL_FRAMEBUFFER_COMPLETE)
2026 throw FboIncompleteException(getConfig(), status, __FILE__, __LINE__);
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);
2034 fboBlitShader.setUnit(ctx, fboBlitShaderID, 0);
2035 ctx.bindTexture(GL_TEXTURE_2D, textures[0]);
2037 for (int cellY = 0; cellY < numRowsCols; cellY++)
2038 for (int cellX = 0; cellX < numRowsCols; cellX++)
2040 const float r = rnd.getFloat();
2041 const float g = rnd.getFloat();
2042 const float b = rnd.getFloat();
2043 const float a = rnd.getFloat();
2045 ctx.bindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
2046 ctx.clearColor(r, g, b, a);
2047 ctx.clear(GL_COLOR_BUFFER_BIT);
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));
2054 ctx.readPixels(dst, 0, 0, fboSizes[1], fboSizes[1]);
2060 FboRenderTestGroup::FboRenderTestGroup (Context& context)
2061 : TestCaseGroup(context, "render", "Rendering Tests")
2065 FboRenderTestGroup::~FboRenderTestGroup (void)
2072 struct TypeFormatPair
2078 template <typename CaseType>
2079 void addChildVariants (deqp::gles2::TestCaseGroup* group)
2081 TypeFormatPair colorbufferConfigs[] =
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 }
2094 TypeFormatPair depthbufferConfigs[] =
2096 { GL_NONE, GL_NONE },
2097 { GL_RENDERBUFFER, GL_DEPTH_COMPONENT16 }
2099 TypeFormatPair stencilbufferConfigs[] =
2101 { GL_NONE, GL_NONE },
2102 { GL_RENDERBUFFER, GL_STENCIL_INDEX8 }
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++)
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;
2117 if (CaseType::isConfigSupported(config))
2118 group->addChild(new CaseType(group->getContext(), config));
2122 template <typename CaseType>
2123 void createChildGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
2125 deqp::gles2::TestCaseGroup* tmpGroup = new deqp::gles2::TestCaseGroup(parent->getContext(), name, description);
2126 parent->addChild(tmpGroup);
2127 addChildVariants<CaseType>(tmpGroup);
2130 template <GLbitfield Buffers>
2131 void createRecreateBuffersGroup (deqp::gles2::TestCaseGroup* parent, const char* name, const char* description)
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);
2141 void FboRenderTestGroup::init (void)
2143 createChildGroup<FboCases::ColorClearsTest> (this, "color_clear", "Color buffer clears");
2144 createChildGroup<FboCases::StencilClearsTest> (this, "stencil_clear", "Stencil buffer clears");
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);
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);
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);
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");
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");
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);
2178 tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated FBO clears");
2179 addChild(repeatedClearGroup);
2181 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGB));
2182 repeatedClearGroup->addChild(new FboCases::RepeatedClearCase(m_context, GL_RGBA));