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 depthbuffer tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es3fFboDepthbufferTests.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
32namespace deqp
33{
34namespace gles3
35{
36namespace Functional
37{
38
39using std::string;
40using tcu::Vec2;
41using tcu::Vec3;
42using tcu::Vec4;
43using tcu::IVec2;
44using tcu::IVec3;
45using tcu::IVec4;
46using tcu::UVec4;
47using namespace FboTestUtil;
48
49class BasicFboDepthCase : public FboTestCase
50{
51public:
52	BasicFboDepthCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height)
53		: FboTestCase	(context, name, desc)
54		, m_format		(format)
55		, m_width		(width)
56		, m_height		(height)
57	{
58	}
59
60protected:
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		deUint32		fbo				= 0;
70		deUint32		colorRbo		= 0;
71		deUint32		depthRbo		= 0;
72		GradientShader	gradShader		(glu::TYPE_FLOAT_VEC4);
73		Texture2DShader	texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
74		deUint32		gradShaderID	= getCurrentContext()->createProgram(&gradShader);
75		deUint32		texShaderID		= getCurrentContext()->createProgram(&texShader);
76		float			clearDepth		= 1.0f;
77
78		// Setup shaders
79		gradShader.setGradient(*getCurrentContext(), gradShaderID, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
80		texShader.setUniforms (*getCurrentContext(), texShaderID);
81
82		// Setup FBO
83
84		glGenFramebuffers(1, &fbo);
85		glGenRenderbuffers(1, &colorRbo);
86		glGenRenderbuffers(1, &depthRbo);
87
88		glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
89		glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_width, m_height);
90
91		glBindRenderbuffer(GL_RENDERBUFFER, depthRbo);
92		glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_width, m_height);
93
94		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
95		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
96		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRbo);
97		checkError();
98		checkFramebufferStatus(GL_FRAMEBUFFER);
99
100		glViewport(0, 0, m_width, m_height);
101
102		// Clear depth to 1
103		glClearBufferfv(GL_DEPTH, 0, &clearDepth);
104
105		// Render gradient with depth = [-1..1]
106		glEnable(GL_DEPTH_TEST);
107		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
108
109		// Render grid pattern with depth = 0
110		{
111			const deUint32		format		= GL_RGBA;
112			const deUint32		dataType	= GL_UNSIGNED_BYTE;
113			const int			texW		= 128;
114			const int			texH		= 128;
115			deUint32			gridTex		= 0;
116			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
117
118			tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
119
120			glGenTextures(1, &gridTex);
121			glBindTexture(GL_TEXTURE_2D, gridTex);
122			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
123			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
124			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
125			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
126			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
127
128			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
129		}
130
131		// Read results.
132		readPixels(dst, 0, 0, m_width, m_height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
133	}
134
135private:
136	deUint32		m_format;
137	int				m_width;
138	int				m_height;
139};
140
141class DepthWriteClampCase : public FboTestCase
142{
143public:
144	DepthWriteClampCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height)
145		: FboTestCase	(context, name, desc)
146		, m_format		(format)
147		, m_width		(width)
148		, m_height		(height)
149	{
150	}
151
152protected:
153	void preCheck (void)
154	{
155		checkFormatSupport(m_format);
156	}
157
158	void render (tcu::Surface& dst)
159	{
160		const deUint32			colorFormat			= GL_RGBA8;
161		deUint32				fbo					= 0;
162		deUint32				colorRbo			= 0;
163		deUint32				depthTexture		= 0;
164		glu::TransferFormat		transferFmt			= glu::getTransferFormat(glu::mapGLInternalFormat(m_format));
165
166		DepthGradientShader		depthGradShader		(glu::TYPE_FLOAT_VEC4);
167		const deUint32			depthGradShaderID	= getCurrentContext()->createProgram(&depthGradShader);
168		const float				clearDepth			= 1.0f;
169		const tcu::Vec4			red					(1.0, 0.0, 0.0, 1.0);
170		const tcu::Vec4			green				(0.0, 1.0, 0.0, 1.0);
171
172		// Setup FBO
173
174		glGenFramebuffers(1, &fbo);
175		glGenRenderbuffers(1, &colorRbo);
176		glGenTextures(1, &depthTexture);
177
178		glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
179		glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_width, m_height);
180
181		glBindTexture(GL_TEXTURE_2D, depthTexture);
182		glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_width, m_height, 0, transferFmt.format, transferFmt.dataType, DE_NULL);
183		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
184		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
185
186		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
187		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
188		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
189		checkError();
190		checkFramebufferStatus(GL_FRAMEBUFFER);
191
192		glViewport(0, 0, m_width, m_height);
193
194		// Clear depth to 1
195		glClearBufferfv(GL_DEPTH, 0, &clearDepth);
196
197		// Test that invalid values are not written to the depth buffer
198
199		// Render green quad, depth gradient = [-1..2]
200		glEnable(GL_DEPTH_TEST);
201		glDepthFunc(GL_ALWAYS);
202
203		depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, -1.0f, 2.0f, green);
204		sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
205		glDepthMask(GL_FALSE);
206
207		// Test if any fragment has greater depth than 1; there should be none
208		glDepthFunc(GL_LESS); // (1 < depth) ?
209		depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, 1.0f, 1.0f, red);
210		sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
211
212		// Test if any fragment has smaller depth than 0; there should be none
213		glDepthFunc(GL_GREATER); // (0 > depth) ?
214		depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, 0.0f, 0.0f, red);
215		sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
216
217		// Read results.
218		readPixels(dst, 0, 0, m_width, m_height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
219	}
220
221private:
222	const deUint32		m_format;
223	const int			m_width;
224	const int			m_height;
225};
226
227class DepthTestClampCase : public FboTestCase
228{
229public:
230	DepthTestClampCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height)
231		: FboTestCase	(context, name, desc)
232		, m_format		(format)
233		, m_width		(width)
234		, m_height		(height)
235	{
236	}
237
238protected:
239	void preCheck (void)
240	{
241		checkFormatSupport(m_format);
242	}
243
244	void render (tcu::Surface& dst)
245	{
246		const deUint32			colorFormat			= GL_RGBA8;
247		deUint32				fbo					= 0;
248		deUint32				colorRbo			= 0;
249		deUint32				depthTexture		= 0;
250		glu::TransferFormat		transferFmt			= glu::getTransferFormat(glu::mapGLInternalFormat(m_format));
251
252		DepthGradientShader		depthGradShader		(glu::TYPE_FLOAT_VEC4);
253		const deUint32			depthGradShaderID	= getCurrentContext()->createProgram(&depthGradShader);
254		const float				clearDepth			= 1.0f;
255		const tcu::Vec4			yellow				(1.0, 1.0, 0.0, 1.0);
256		const tcu::Vec4			green				(0.0, 1.0, 0.0, 1.0);
257
258		// Setup FBO
259
260		glGenFramebuffers(1, &fbo);
261		glGenRenderbuffers(1, &colorRbo);
262		glGenTextures(1, &depthTexture);
263
264		glBindRenderbuffer(GL_RENDERBUFFER, colorRbo);
265		glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, m_width, m_height);
266
267		glBindTexture(GL_TEXTURE_2D, depthTexture);
268		glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_width, m_height, 0, transferFmt.format, transferFmt.dataType, DE_NULL);
269		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
270		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
271
272		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
273		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo);
274		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
275		checkError();
276		checkFramebufferStatus(GL_FRAMEBUFFER);
277
278		glViewport(0, 0, m_width, m_height);
279
280		// Clear depth to 1
281		glClearBufferfv(GL_DEPTH, 0, &clearDepth);
282
283		// Test values used in depth test are clamped
284
285		// Render green quad, depth gradient = [-1..2]
286		glEnable(GL_DEPTH_TEST);
287		glDepthFunc(GL_ALWAYS);
288
289		depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, -1.0f, 2.0f, green);
290		sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
291
292		// Render yellow quad, depth gradient = [-0.5..3]. Gradients have equal values only outside [0, 1] range due to clamping
293		glDepthFunc(GL_EQUAL);
294		depthGradShader.setUniforms(*getCurrentContext(), depthGradShaderID, -0.5f, 3.0f, yellow);
295		sglr::drawQuad(*getCurrentContext(), depthGradShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f));
296
297		// Read results.
298		readPixels(dst, 0, 0, m_width, m_height, glu::mapGLInternalFormat(colorFormat), Vec4(1.0f), Vec4(0.0f));
299	}
300
301private:
302	const deUint32		m_format;
303	const int			m_width;
304	const int			m_height;
305};
306
307FboDepthTests::FboDepthTests (Context& context)
308	: TestCaseGroup(context, "depth", "Depth tests")
309{
310}
311
312FboDepthTests::~FboDepthTests (void)
313{
314}
315
316void FboDepthTests::init (void)
317{
318	static const deUint32 depthFormats[] =
319	{
320		GL_DEPTH_COMPONENT32F,
321		GL_DEPTH_COMPONENT24,
322		GL_DEPTH_COMPONENT16,
323		GL_DEPTH32F_STENCIL8,
324		GL_DEPTH24_STENCIL8
325	};
326
327	// .basic
328	{
329		tcu::TestCaseGroup* basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Basic depth tests");
330		addChild(basicGroup);
331
332		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthFormats); fmtNdx++)
333			basicGroup->addChild(new BasicFboDepthCase(m_context, getFormatName(depthFormats[fmtNdx]), "", depthFormats[fmtNdx], 119, 127));
334	}
335
336	// .depth_write_clamp
337	{
338		tcu::TestCaseGroup* depthClampGroup = new tcu::TestCaseGroup(m_testCtx, "depth_write_clamp", "Depth write clamping tests");
339		addChild(depthClampGroup);
340
341		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthFormats); fmtNdx++)
342			depthClampGroup->addChild(new DepthWriteClampCase(m_context, getFormatName(depthFormats[fmtNdx]), "", depthFormats[fmtNdx], 119, 127));
343	}
344
345	// .depth_test_clamp
346	{
347		tcu::TestCaseGroup* depthClampGroup = new tcu::TestCaseGroup(m_testCtx, "depth_test_clamp", "Depth test value clamping tests");
348		addChild(depthClampGroup);
349
350		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthFormats); fmtNdx++)
351			depthClampGroup->addChild(new DepthTestClampCase(m_context, getFormatName(depthFormats[fmtNdx]), "", depthFormats[fmtNdx], 119, 127));
352	}
353}
354
355} // Functional
356} // gles3
357} // deqp
358