• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
BasicFboStencilCase(Context & context,const char * name,const char * desc,deUint32 format,IVec2 size,bool useDepth)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:
preCheck(void)61 	void preCheck (void)
62 	{
63 		checkFormatSupport(m_format);
64 	}
65 
render(tcu::Surface & dst)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:
DepthStencilAttachCase(Context & context,const char * name,const char * desc,deUint32 attachDepth,deUint32 attachStencil)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:
render(tcu::Surface & dst)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 
FboStencilTests(Context & context)237 FboStencilTests::FboStencilTests (Context& context)
238 	: TestCaseGroup(context, "stencil", "FBO Stencilbuffer tests")
239 {
240 }
241 
~FboStencilTests(void)242 FboStencilTests::~FboStencilTests (void)
243 {
244 }
245 
init(void)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