Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.0 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief FBO stencilbuffer tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fFboStencilbufferTests.hpp"
     25 #include "es3fFboTestCase.hpp"
     26 #include "es3fFboTestUtil.hpp"
     27 #include "gluTextureUtil.hpp"
     28 #include "tcuTextureUtil.hpp"
     29 #include "sglrContextUtil.hpp"
     30 #include "glwEnums.hpp"
     31 
     32 namespace deqp
     33 {
     34 namespace gles3
     35 {
     36 namespace Functional
     37 {
     38 
     39 using std::string;
     40 using tcu::Vec2;
     41 using tcu::Vec3;
     42 using tcu::Vec4;
     43 using tcu::IVec2;
     44 using tcu::IVec3;
     45 using tcu::IVec4;
     46 using tcu::UVec4;
     47 using namespace FboTestUtil;
     48 
     49 class BasicFboStencilCase : public FboTestCase
     50 {
     51 public:
     52 	BasicFboStencilCase (Context& context, const char* name, const char* desc, deUint32 format, IVec2 size, bool useDepth)
     53 		: FboTestCase	(context, name, desc)
     54 		, m_format		(format)
     55 		, m_size		(size)
     56 		, m_useDepth	(useDepth)
     57 	{
     58 	}
     59 
     60 protected:
     61 	void preCheck (void)
     62 	{
     63 		checkFormatSupport(m_format);
     64 	}
     65 
     66 	void render (tcu::Surface& dst)
     67 	{
     68 		const deUint32			colorFormat		= GL_RGBA8;
     69 
     70 		GradientShader			gradShader		(glu::TYPE_FLOAT_VEC4);
     71 		FlatColorShader			flatShader		(glu::TYPE_FLOAT_VEC4);
     72 		deUint32				flatShaderID	= getCurrentContext()->createProgram(&flatShader);
     73 		deUint32				gradShaderID	= getCurrentContext()->createProgram(&gradShader);
     74 
     75 		deUint32				fbo				= 0;
     76 		deUint32				colorRbo		= 0;
     77 		deUint32				depthStencilRbo	= 0;
     78 
     79 		// Colorbuffer.
     80 		glGenRenderbuffers(1, &colorRbo);
     81 		glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
     82 		glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_size.x(), m_size.y());
     83 
     84 		// Stencil (and depth) buffer.
     85 		glGenRenderbuffers(1, &depthStencilRbo);
     86 		glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
     87 		glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y());
     88 
     89 		// Framebuffer.
     90 		glGenFramebuffers(1, &fbo);
     91 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
     92 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
     93 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
     94 		if (m_useDepth)
     95 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRbo);
     96 		checkError();
     97 		checkFramebufferStatus(GL_FRAMEBUFFER);
     98 
     99 		glViewport(0, 0, m_size.x(), m_size.y());
    100 
    101 		// Clear framebuffer.
    102 		glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr());
    103 		glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
    104 
    105 		// Render intersecting quads - increment stencil on depth pass
    106 		glEnable(GL_DEPTH_TEST);
    107 		glEnable(GL_STENCIL_TEST);
    108 		glStencilFunc(GL_ALWAYS, 0, 0xffu);
    109 		glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
    110 
    111 		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
    112 		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f,  0.0f), Vec3(+1.0f, +1.0f,  0.0f));
    113 
    114 		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
    115 		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));
    116 
    117 		glDisable(GL_DEPTH_TEST);
    118 
    119 		// Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
    120 		glStencilFunc(GL_EQUAL, m_useDepth ? 2 : 1, 0xffu);
    121 		glStencilOp(GL_DECR, GL_KEEP, GL_KEEP);
    122 
    123 		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0));
    124 		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));
    125 
    126 		// Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer
    127 		glStencilFunc(GL_GREATER, m_useDepth ? 1 : 2, 0xffu);
    128 
    129 		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
    130 		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
    131 
    132 		readPixels(dst, 0, 0, m_size.x(), m_size.y(), glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
    133 	}
    134 
    135 private:
    136 	deUint32	m_format;
    137 	IVec2		m_size;
    138 	bool		m_useDepth;
    139 };
    140 
    141 class DepthStencilAttachCase : public FboTestCase
    142 {
    143 public:
    144 	DepthStencilAttachCase (Context& context, const char* name, const char* desc, deUint32 attachDepth, deUint32 attachStencil)
    145 		: FboTestCase		(context, name, desc)
    146 		, m_attachDepth		(attachDepth)
    147 		, m_attachStencil	(attachStencil)
    148 	{
    149 		DE_ASSERT(m_attachDepth == GL_DEPTH_ATTACHMENT || m_attachDepth == GL_DEPTH_STENCIL_ATTACHMENT || m_attachDepth == GL_NONE);
    150 		DE_ASSERT(m_attachStencil == GL_STENCIL_ATTACHMENT || m_attachStencil == GL_NONE);
    151 		DE_ASSERT(m_attachDepth != GL_DEPTH_STENCIL || m_attachStencil == GL_NONE);
    152 	}
    153 
    154 protected:
    155 	void render (tcu::Surface& dst)
    156 	{
    157 		const deUint32			colorFormat			= GL_RGBA8;
    158 		const deUint32			depthStencilFormat	= GL_DEPTH24_STENCIL8;
    159 		const int				width				= 128;
    160 		const int				height				= 128;
    161 		const bool				hasDepth			= (m_attachDepth == GL_DEPTH_STENCIL || m_attachDepth == GL_DEPTH_ATTACHMENT);
    162 //		const bool				hasStencil			= (m_attachDepth == GL_DEPTH_STENCIL || m_attachStencil == GL_DEPTH_STENCIL_ATTACHMENT);
    163 
    164 		GradientShader			gradShader			(glu::TYPE_FLOAT_VEC4);
    165 		FlatColorShader			flatShader			(glu::TYPE_FLOAT_VEC4);
    166 		deUint32				flatShaderID		= getCurrentContext()->createProgram(&flatShader);
    167 		deUint32				gradShaderID		= getCurrentContext()->createProgram(&gradShader);
    168 
    169 		deUint32				fbo					= 0;
    170 		deUint32				colorRbo			= 0;
    171 		deUint32				depthStencilRbo		= 0;
    172 
    173 		// Colorbuffer.
    174 		glGenRenderbuffers(1, &colorRbo);
    175 		glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
    176 		glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, width, height);
    177 
    178 		// Depth-stencil buffer.
    179 		glGenRenderbuffers(1, &depthStencilRbo);
    180 		glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRbo);
    181 		glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, width, height);
    182 
    183 		// Framebuffer.
    184 		glGenFramebuffers(1, &fbo);
    185 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    186 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
    187 
    188 		if (m_attachDepth != GL_NONE)
    189 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_attachDepth, GL_RENDERBUFFER, depthStencilRbo);
    190 		if (m_attachStencil != GL_NONE)
    191 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_attachStencil, GL_RENDERBUFFER, depthStencilRbo);
    192 
    193 		checkError();
    194 		checkFramebufferStatus(GL_FRAMEBUFFER);
    195 
    196 		glViewport(0, 0, width, height);
    197 
    198 		// Clear framebuffer.
    199 		glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr());
    200 		glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0f, 0);
    201 
    202 		// Render intersecting quads - increment stencil on depth pass
    203 		glEnable(GL_DEPTH_TEST);
    204 		glEnable(GL_STENCIL_TEST);
    205 		glStencilFunc(GL_ALWAYS, 0, 0xffu);
    206 		glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
    207 
    208 		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(1.0f, 0.0f, 0.0f, 1.0f));
    209 		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f,  0.0f), Vec3(+1.0f, +1.0f,  0.0f));
    210 
    211 		gradShader.setGradient(*getCurrentContext(), gradShaderID, Vec4(0.0f), Vec4(1.0f));
    212 		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(+1.0f, +1.0f, +1.0f));
    213 
    214 		glDisable(GL_DEPTH_TEST);
    215 
    216 		// Draw quad with stencil test (stencil == 1 or 2 depending on depth) - decrement on stencil failure
    217 		glStencilFunc(GL_EQUAL, hasDepth ? 2 : 1, 0xffu);
    218 		glStencilOp(GL_DECR, GL_KEEP, GL_KEEP);
    219 
    220 		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0));
    221 		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(+0.5f, +0.5f, 0.0f));
    222 
    223 		// Draw quad with stencil test where stencil > 1 or 2 depending on depth buffer
    224 		glStencilFunc(GL_GREATER, hasDepth ? 1 : 2, 0xffu);
    225 
    226 		flatShader.setColor(*getCurrentContext(), flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f));
    227 		sglr::drawQuad(*getCurrentContext(), flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f));
    228 
    229 		readPixels(dst, 0, 0, width, height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
    230 	}
    231 
    232 private:
    233 	deUint32		m_attachDepth;
    234 	deUint32		m_attachStencil;
    235 };
    236 
    237 FboStencilTests::FboStencilTests (Context& context)
    238 	: TestCaseGroup(context, "stencil", "FBO Stencilbuffer tests")
    239 {
    240 }
    241 
    242 FboStencilTests::~FboStencilTests (void)
    243 {
    244 }
    245 
    246 void FboStencilTests::init (void)
    247 {
    248 	static const deUint32 stencilFormats[] =
    249 	{
    250 		GL_DEPTH32F_STENCIL8,
    251 		GL_DEPTH24_STENCIL8,
    252 		GL_STENCIL_INDEX8
    253 	};
    254 
    255 	// .basic
    256 	{
    257 		tcu::TestCaseGroup* basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic stencil tests");
    258 		addChild(basicGroup);
    259 
    260 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(stencilFormats); fmtNdx++)
    261 		{
    262 			deUint32			format		= stencilFormats[fmtNdx];
    263 			tcu::TextureFormat	texFmt		= glu::mapGLInternalFormat(format);
    264 
    265 			basicGroup->addChild(new BasicFboStencilCase(m_context, getFormatName(format), "", format, IVec2(111, 132), false));
    266 
    267 			if (texFmt.order == tcu::TextureFormat::DS)
    268 				basicGroup->addChild(new BasicFboStencilCase(m_context, (string(getFormatName(format)) + "_depth").c_str(), "", format, IVec2(111, 132), true));
    269 		}
    270 	}
    271 
    272 	// .attach
    273 	{
    274 		tcu::TestCaseGroup* attachGroup = new tcu::TestCaseGroup(m_testCtx, "attach", "Attaching depth stencil");
    275 		addChild(attachGroup);
    276 
    277 		attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_only",				"Only depth part of depth-stencil RBO attached",			GL_DEPTH_ATTACHMENT,			GL_NONE));
    278 		attachGroup->addChild(new DepthStencilAttachCase(m_context, "stencil_only",				"Only stencil part of depth-stencil RBO attached",			GL_NONE,						GL_STENCIL_ATTACHMENT));
    279 		attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_stencil_separate",	"Depth and stencil attached separately",					GL_DEPTH_ATTACHMENT,			GL_STENCIL_ATTACHMENT));
    280 		attachGroup->addChild(new DepthStencilAttachCase(m_context, "depth_stencil_attachment",	"Depth and stencil attached with DEPTH_STENCIL_ATTACHMENT",	GL_DEPTH_STENCIL_ATTACHMENT,	GL_NONE));
    281 	}
    282 }
    283 
    284 } // Functional
    285 } // gles3
    286 } // deqp
    287