• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) 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 GLES Scissor tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "glsScissorTests.hpp"
25 #include "glsTextureTestUtil.hpp"
26 
27 #include "deMath.h"
28 #include "deRandom.hpp"
29 #include "deUniquePtr.hpp"
30 
31 #include "tcuTestCase.hpp"
32 #include "tcuImageCompare.hpp"
33 #include "tcuVector.hpp"
34 #include "tcuVectorUtil.hpp"
35 #include "tcuTexture.hpp"
36 #include "tcuStringTemplate.hpp"
37 
38 #include "gluStrUtil.hpp"
39 #include "gluDrawUtil.hpp"
40 #include "gluPixelTransfer.hpp"
41 #include "gluObjectWrapper.hpp"
42 
43 #include "glwEnums.hpp"
44 #include "glwFunctions.hpp"
45 
46 #include <map>
47 
48 namespace deqp
49 {
50 namespace gls
51 {
52 namespace Functional
53 {
54 namespace
55 {
56 
57 using namespace ScissorTestInternal;
58 using namespace glw; // GL types
59 
60 using tcu::ConstPixelBufferAccess;
61 using tcu::PixelBufferAccess;
62 using tcu::TestLog;
63 
64 using std::vector;
65 using std::string;
66 using std::map;
67 using tcu::Vec3;
68 using tcu::Vec4;
69 using tcu::IVec4;
70 using tcu::UVec4;
71 
drawQuad(const glw::Functions & gl,deUint32 program,const Vec3 & p0,const Vec3 & p1)72 void drawQuad (const glw::Functions& gl, deUint32 program, const Vec3& p0, const Vec3& p1)
73 {
74 	// Vertex data.
75 	const float hz = (p0.z() + p1.z()) * 0.5f;
76 	const float position[] =
77 	{
78 		p0.x(), p0.y(), p0.z(),	1.0f,
79 		p0.x(), p1.y(), hz,		1.0f,
80 		p1.x(), p0.y(), hz,		1.0f,
81 		p1.x(), p1.y(), p1.z(),	1.0f
82 	};
83 
84 	const deUint16	indices[]	= { 0, 1, 2, 2, 1, 3 };
85 
86 	const deInt32	posLoc		= gl.getAttribLocation(program, "a_position");
87 
88 	gl.useProgram(program);
89 	gl.enableVertexAttribArray(posLoc);
90 	gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &position[0]);
91 
92 	gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0]);
93 
94 	gl.disableVertexAttribArray(posLoc);
95 
96 }
97 
drawPrimitives(const glw::Functions & gl,deUint32 program,const deUint32 type,const vector<float> & vertices,const vector<deUint16> & indices)98 void drawPrimitives (const glw::Functions& gl, deUint32 program, const deUint32 type, const vector<float>& vertices, const vector<deUint16>& indices)
99 {
100 	const deInt32 posLoc = gl.getAttribLocation(program, "a_position");
101 
102 	TCU_CHECK(posLoc >= 0);
103 
104 	gl.useProgram(program);
105 	gl.enableVertexAttribArray(posLoc);
106 	gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, &vertices[0]);
107 
108 	gl.drawElements(type, GLsizei(indices.size()), GL_UNSIGNED_SHORT, &indices[0]);
109 
110 	gl.disableVertexAttribArray(posLoc);
111 }
112 
113 template<typename T>
clearEdges(const tcu::PixelBufferAccess & access,const T & color,const IVec4 & scissorArea)114 void clearEdges (const tcu::PixelBufferAccess& access, const T& color, const IVec4& scissorArea)
115 {
116 	for (int y = 0; y < access.getHeight(); y++)
117 	for (int x = 0; x < access.getWidth(); x++)
118 	{
119 		if (y < scissorArea.y() ||
120 			y >= scissorArea.y() + scissorArea.w() ||
121 			x < scissorArea.x() ||
122 			x >= scissorArea.x()+ scissorArea.z())
123 			access.setPixel(color, x, y);
124 	}
125 }
126 
genShaders(glu::GLSLVersion version,bool isPoint)127 glu::ProgramSources genShaders(glu::GLSLVersion version, bool isPoint)
128 {
129 	string vtxSource;
130 
131 	if (isPoint)
132 	{
133 		 vtxSource = "${VERSION}\n"
134 					 "${IN} highp vec4 a_position;\n"
135 					 "void main(){\n"
136 					 "	gl_Position = a_position;\n"
137 					 "	gl_PointSize = 1.0;\n"
138 					 "}\n";
139 	}
140 	else
141 	{
142 		 vtxSource = "${VERSION}\n"
143 					 "${IN} highp vec4 a_position;\n"
144 					 "void main(){\n"
145 					 "	gl_Position = a_position;\n"
146 					 "}\n";
147 	}
148 
149 	const string frgSource = "${VERSION}\n"
150 							 "${OUT_DECL}"
151 							 "uniform highp vec4 u_color;\n"
152 							 "void main(){\n"
153 							 "	${OUTPUT} = u_color;\n"
154 							 "}\n";
155 
156 	map<string, string>	params;
157 
158 	switch(version)
159 	{
160 		case glu::GLSL_VERSION_100_ES:
161 			params["VERSION"] = "#version 100";
162 			params["IN"] = "attribute";
163 			params["OUT_DECL"] = "";
164 			params["OUTPUT"] = "gl_FragColor";
165 			break;
166 
167 		case glu::GLSL_VERSION_300_ES:
168 		case glu::GLSL_VERSION_310_ES: // Assumed to support 3.0
169 			params["VERSION"] = "#version 300 es";
170 			params["IN"] = "in";
171 			params["OUT_DECL"] = "out mediump vec4 f_color;\n";
172 			params["OUTPUT"] = "f_color";
173 			break;
174 
175 		default:
176 			DE_FATAL("Unsupported version");
177 	}
178 
179 	return glu::makeVtxFragSources(tcu::StringTemplate(vtxSource).specialize(params), tcu::StringTemplate(frgSource).specialize(params));
180 }
181 
182 // Wrapper class, provides iterator & reporting logic
183 class ScissorCase : public tcu::TestCase
184 {
185 public:
186 							ScissorCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char *name, const char* desc, const Vec4& scissorArea);
~ScissorCase(void)187 	virtual					~ScissorCase	(void) {}
188 
189 	virtual IterateResult	iterate			(void);
190 
191 protected:
192 	virtual void			render			(GLuint program, const IVec4& viewport) const = 0;
193 
194 	// Initialize gl_PointSize to 1.0f when drawing points, or the point size is undefined according to spec.
195 	virtual bool			isPoint			(void) const = 0;
196 
197 	glu::RenderContext&		m_renderCtx;
198 	const Vec4				m_scissorArea;
199 };
200 
ScissorCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,const Vec4 & scissorArea)201 ScissorCase::ScissorCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char *name, const char* desc, const Vec4& scissorArea)
202 	: TestCase		(testCtx, name, desc)
203 	, m_renderCtx	(renderCtx)
204 	, m_scissorArea	(scissorArea)
205 {
206 }
207 
iterate(void)208 ScissorCase::IterateResult ScissorCase::iterate (void)
209 {
210 	using TextureTestUtil::RandomViewport;
211 
212 	const glw::Functions&		gl				= m_renderCtx.getFunctions();
213 	TestLog&					log				= m_testCtx.getLog();
214 	const tcu::PixelFormat		renderFormat	= m_renderCtx.getRenderTarget().getPixelFormat();
215 	const tcu::Vec4				threshold		= 0.02f * UVec4(1u << de::max(0, 8 - renderFormat.redBits),
216 																1u << de::max(0, 8 - renderFormat.greenBits),
217 																1u << de::max(0, 8 - renderFormat.blueBits),
218 																1u << de::max(0, 8 - renderFormat.alphaBits)).asFloat();
219 	const glu::ShaderProgram	shader			(m_renderCtx, genShaders(glu::getContextTypeGLSLVersion(m_renderCtx.getType()), isPoint()));
220 
221 	const RandomViewport		viewport		(m_renderCtx.getRenderTarget(), 256, 256, deStringHash(getName()));
222 	const IVec4					relScissorArea	(int(m_scissorArea.x() * (float)viewport.width),
223 												 int(m_scissorArea.y() * (float)viewport.height),
224 												 int(m_scissorArea.z() * (float)viewport.width),
225 												 int(m_scissorArea.w() * (float)viewport.height));
226 	const IVec4					absScissorArea	(relScissorArea.x() + viewport.x,
227 												 relScissorArea.y() + viewport.y,
228 												 relScissorArea.z(),
229 												 relScissorArea.w());
230 
231 	tcu::Surface				refImage		(viewport.width, viewport.height);
232 	tcu::Surface				resImage		(viewport.width, viewport.height);
233 
234 	if (!shader.isOk())
235 	{
236 		log << shader;
237 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader compile/link failed");
238 		return STOP;
239 	}
240 
241 	log << TestLog::Message << "Viewport area is " << IVec4(viewport.x, viewport.y, viewport.width, viewport.height) << TestLog::EndMessage;
242 	log << TestLog::Message << "Scissor area is " << absScissorArea << TestLog::EndMessage;
243 
244 	// Render reference (no scissors)
245 	{
246 		log << TestLog::Message << "Rendering reference (scissors disabled)" << TestLog::EndMessage;
247 
248 		gl.useProgram(shader.getProgram());
249 		gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
250 
251 		gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
252 		gl.clearDepthf(1.0f);
253 		gl.clearStencil(0);
254 		gl.disable(GL_DEPTH_TEST);
255 		gl.disable(GL_STENCIL_TEST);
256 		gl.disable(GL_SCISSOR_TEST);
257 		gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
258 
259 		render(shader.getProgram(), IVec4(viewport.x, viewport.y, viewport.width, viewport.height));
260 
261 		glu::readPixels(m_renderCtx, viewport.x, viewport.y, refImage.getAccess());
262 		GLU_CHECK_ERROR(gl.getError());
263 	}
264 
265 	// Render result (scissors)
266 	{
267 		log << TestLog::Message << "Rendering result (scissors enabled)" << TestLog::EndMessage;
268 
269 		gl.useProgram(shader.getProgram());
270 		gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
271 
272 		gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
273 		gl.clearDepthf(1.0f);
274 		gl.clearStencil(0);
275 		gl.disable(GL_DEPTH_TEST);
276 		gl.disable(GL_STENCIL_TEST);
277 		gl.disable(GL_SCISSOR_TEST);
278 		gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
279 
280 		gl.scissor(absScissorArea.x(), absScissorArea.y(), absScissorArea.z(), absScissorArea.w());
281 		gl.enable(GL_SCISSOR_TEST);
282 
283 		render(shader.getProgram(), IVec4(viewport.x, viewport.y, viewport.width, viewport.height));
284 
285 		glu::readPixels(m_renderCtx, viewport.x, viewport.y, resImage.getAccess());
286 		GLU_CHECK_ERROR(gl.getError());
287 	}
288 
289 	// Manual 'scissors' for reference image
290 	log << TestLog::Message << "Clearing area outside scissor area from reference" << TestLog::EndMessage;
291 	clearEdges(refImage.getAccess(), IVec4(32, 64, 128, 255), relScissorArea);
292 
293 	if (tcu::floatThresholdCompare(log, "ComparisonResult", "Image comparison result", refImage.getAccess(), resImage.getAccess(), threshold, tcu::COMPARE_LOG_RESULT))
294 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
295 	else
296 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
297 
298 	return STOP;
299 }
300 
301 // Tests scissoring with multiple primitive types
302 class ScissorPrimitiveCase : public ScissorCase
303 {
304 public:
305 								ScissorPrimitiveCase	(tcu::TestContext&		testCtx,
306 														 glu::RenderContext&	renderCtx,
307 														 const char*			name,
308 														 const char*			desc,
309 														 const Vec4&			scissorArea,
310 														 const Vec4&			renderArea,
311 														 PrimitiveType			type,
312 														 int					primitiveCount);
~ScissorPrimitiveCase(void)313 	virtual						~ScissorPrimitiveCase	(void){}
314 
315 protected:
316 	virtual void				render					(GLuint program, const IVec4& viewport) const;
317 	virtual bool				isPoint					(void) const;
318 
319 private:
320 	const Vec4					m_renderArea;
321 	const PrimitiveType			m_primitiveType;
322 	const int					m_primitiveCount;
323 };
324 
ScissorPrimitiveCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,const Vec4 & scissorArea,const Vec4 & renderArea,PrimitiveType type,int primitiveCount)325 ScissorPrimitiveCase::ScissorPrimitiveCase	(tcu::TestContext&		testCtx,
326 											 glu::RenderContext&	renderCtx,
327 											 const char*			name,
328 											 const char*			desc,
329 											 const Vec4&			scissorArea,
330 											 const Vec4&			renderArea,
331 											 PrimitiveType			type,
332 											 int					primitiveCount)
333 	: ScissorCase		(testCtx, renderCtx, name, desc, scissorArea)
334 	, m_renderArea		(renderArea)
335 	, m_primitiveType	(type)
336 	, m_primitiveCount	(primitiveCount)
337 {
338 }
339 
isPoint(void) const340 bool ScissorPrimitiveCase::isPoint (void) const
341 {
342 	return (m_primitiveType == POINT);
343 }
344 
render(GLuint program,const IVec4 &) const345 void ScissorPrimitiveCase::render (GLuint program, const IVec4&) const
346 {
347 	const glw::Functions&		gl				= m_renderCtx.getFunctions();
348 	const Vec4					white			(1.0f, 1.0f, 1.0f, 1.0);
349 	const Vec4					primitiveArea	(m_renderArea.x()*2.0f-1.0f,
350 												 m_renderArea.x()*2.0f-1.0f,
351 												 m_renderArea.z()*2.0f,
352 												 m_renderArea.w()*2.0f);
353 
354 	static const float quadPositions[] =
355 	{
356 		 0.0f,  1.0f,
357 		 0.0f,  0.0f,
358 		 1.0f,  1.0f,
359 		 1.0f,  0.0f
360 	};
361 	static const float triPositions[] =
362 	{
363 		 0.0f,  0.0f,
364 		 1.0f,  0.0f,
365 		 0.5f,  1.0f,
366 	};
367 	static const float linePositions[] =
368 	{
369 		 0.0f,  0.0f,
370 		 1.0f,  1.0f
371 	};
372 	static const float pointPosition[] =
373 	{
374 		 0.5f,  0.5f
375 	};
376 
377 	const float*		positionSet[]	= { pointPosition, linePositions, triPositions, quadPositions };
378 	const int			vertexCountSet[]= { 1, 2, 3, 4 };
379 	const int			indexCountSet[]	= { 1, 2, 3, 6 };
380 
381 	const deUint16		baseIndices[]	= { 0, 1, 2, 2, 1, 3 };
382 	const float*		basePositions	= positionSet[m_primitiveType];
383 	const int			vertexCount		= vertexCountSet[m_primitiveType];
384 	const int			indexCount		= indexCountSet[m_primitiveType];
385 
386 	const float			scale			= 1.44f/deFloatSqrt(float(m_primitiveCount)*2.0f); // Magic value to roughly fill the render area with primitives at a readable density
387 	vector<float>		positions		(4*vertexCount*m_primitiveCount);
388 	vector<deUint16>	indices			(indexCount*m_primitiveCount);
389 	de::Random			rng				(1234);
390 
391 	for (int primNdx = 0; primNdx < m_primitiveCount; primNdx++)
392 	{
393 		const float dx = m_primitiveCount>1 ? rng.getFloat() : 0.0f;
394 		const float dy = m_primitiveCount>1 ? rng.getFloat() : 0.0f;
395 
396 		for (int vertNdx = 0; vertNdx < vertexCount; vertNdx++)
397 		{
398 			const int ndx = primNdx*4*vertexCount + vertNdx*4;
399 			positions[ndx+0] = (basePositions[vertNdx*2 + 0]*scale + dx)*primitiveArea.z() + primitiveArea.x();
400 			positions[ndx+1] = (basePositions[vertNdx*2 + 1]*scale + dy)*primitiveArea.w() + primitiveArea.y();
401 			positions[ndx+2] = 0.2f;
402 			positions[ndx+3] = 1.0f;
403 		}
404 
405 		for (int ndx = 0; ndx < indexCount; ndx++)
406 			indices[primNdx*indexCount + ndx] = (deUint16)(baseIndices[ndx] + primNdx*vertexCount);
407 	}
408 
409 	gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, white.m_data);
410 
411 	switch (m_primitiveType)
412 	{
413 		case TRIANGLE:	drawPrimitives(gl, program, GL_TRIANGLES,	positions, indices);	break;
414 		case LINE:		drawPrimitives(gl, program, GL_LINES,		positions, indices);	break;
415 		case POINT:		drawPrimitives(gl, program, GL_POINTS,		positions, indices);	break;
416 		default:		DE_ASSERT(false);													break;
417 	}
418 }
419 
420 // Test effect of scissor on default framebuffer clears
421 class ScissorClearCase : public ScissorCase
422 {
423 public:
424 					ScissorClearCase	(tcu::TestContext&		testCtx,
425 										 glu::RenderContext&	renderCtx,
426 										 const char*			name,
427 										 const char*			desc,
428 										 const Vec4&			scissorArea,
429 										 deUint32				clearMode);
~ScissorClearCase(void)430 	virtual			~ScissorClearCase	(void) {}
431 
432 	virtual void	init				(void);
433 
434 protected:
435 	virtual void	render				(GLuint program, const IVec4& viewport) const;
436 	virtual bool	isPoint				(void) const;
437 
438 private:
439 	const deUint32	m_clearMode; //!< Combination of the flags accepted by glClear
440 };
441 
ScissorClearCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,const Vec4 & scissorArea,deUint32 clearMode)442 ScissorClearCase::ScissorClearCase	(tcu::TestContext&		testCtx,
443 									 glu::RenderContext&	renderCtx,
444 									 const char*			name,
445 									 const char*			desc,
446 									 const Vec4&			scissorArea,
447 									 deUint32				clearMode)
448 	: ScissorCase	(testCtx, renderCtx, name, desc, scissorArea)
449 	, m_clearMode	(clearMode)
450 {
451 }
452 
init(void)453 void ScissorClearCase::init (void)
454 {
455 	if ((m_clearMode & GL_DEPTH_BUFFER_BIT) && m_renderCtx.getRenderTarget().getDepthBits() == 0)
456 		throw tcu::NotSupportedError("Cannot clear depth; no depth buffer present", "", __FILE__, __LINE__);
457 	else if ((m_clearMode & GL_STENCIL_BUFFER_BIT) && m_renderCtx.getRenderTarget().getStencilBits() == 0)
458 		throw tcu::NotSupportedError("Cannot clear stencil; no stencil buffer present", "", __FILE__, __LINE__);
459 }
460 
isPoint(void) const461 bool ScissorClearCase::isPoint (void) const
462 {
463 	return false;
464 }
465 
render(GLuint program,const IVec4 &) const466 void ScissorClearCase::render (GLuint program, const IVec4&) const
467 {
468 	const glw::Functions&	gl		= m_renderCtx.getFunctions();
469 	const Vec4				white	(1.0f, 1.0f, 1.0f, 1.0);
470 
471 	gl.clearColor(0.6f, 0.1f, 0.1f, 1.0);
472 	gl.clearDepthf(0.0f);
473 
474 	if (m_clearMode & GL_DEPTH_BUFFER_BIT)
475 	{
476 		gl.enable(GL_DEPTH_TEST);
477 		gl.depthFunc(GL_GREATER);
478 	}
479 
480 	if (m_clearMode & GL_STENCIL_BUFFER_BIT)
481 	{
482 		gl.clearStencil(123);
483 		gl.enable(GL_STENCIL_TEST);
484 		gl.stencilFunc(GL_EQUAL, 123, ~0u);
485 	}
486 
487 	if (m_clearMode & GL_COLOR_BUFFER_BIT)
488 		gl.clearColor(0.1f, 0.6f, 0.1f, 1.0);
489 
490 	gl.clear(m_clearMode);
491 	gl.disable(GL_SCISSOR_TEST);
492 
493 	gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, white.getPtr());
494 
495 	if (!(m_clearMode & GL_COLOR_BUFFER_BIT))
496 		drawQuad(gl, program, Vec3(-1.0f, -1.0f, 0.5f), Vec3(1.0f, 1.0f, 0.5f));
497 
498 	gl.disable(GL_DEPTH_TEST);
499 	gl.disable(GL_STENCIL_TEST);
500 }
501 
502 class FramebufferBlitCase : public ScissorCase
503 {
504 public:
505 					FramebufferBlitCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, const Vec4& scissorArea);
~FramebufferBlitCase(void)506 	virtual			~FramebufferBlitCase	(void) {}
507 
508 	virtual void	init					(void);
509 	virtual void	deinit					(void);
510 
511 protected:
512 	typedef de::MovePtr<glu::Framebuffer> FramebufferP;
513 
514 	enum {SIZE = 64};
515 
516 	virtual void	render					(GLuint program, const IVec4& viewport) const;
517 	virtual bool	isPoint					(void) const;
518 
519 	FramebufferP	m_fbo;
520 };
521 
FramebufferBlitCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,const Vec4 & scissorArea)522 FramebufferBlitCase::FramebufferBlitCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, const Vec4& scissorArea)
523 	: ScissorCase(testCtx, renderCtx, name, desc, scissorArea)
524 {
525 }
526 
init(void)527 void FramebufferBlitCase::init (void)
528 {
529 	if (m_renderCtx.getRenderTarget().getNumSamples())
530 		throw tcu::NotSupportedError("Cannot blit to multisampled framebuffer", "", __FILE__, __LINE__);
531 
532 	const glw::Functions&	gl			= m_renderCtx.getFunctions();
533 	const glu::Renderbuffer	colorbuf	(gl);
534 	const tcu::Vec4			clearColor	(1.0f, 0.5, 0.125f, 1.0f);
535 
536 	m_fbo = FramebufferP(new glu::Framebuffer(gl));
537 
538 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, **m_fbo);
539 
540 	gl.bindRenderbuffer(GL_RENDERBUFFER, *colorbuf);
541 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SIZE, SIZE);
542 	gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorbuf);
543 
544 	gl.clearBufferfv(GL_COLOR, 0, clearColor.getPtr());
545 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_renderCtx.getDefaultFramebuffer());
546 }
547 
deinit(void)548 void FramebufferBlitCase::deinit (void)
549 {
550 	m_fbo.clear();
551 }
552 
isPoint(void) const553 bool FramebufferBlitCase::isPoint (void) const
554 {
555 	return false;
556 }
557 
render(GLuint program,const IVec4 & viewport) const558 void FramebufferBlitCase::render(GLuint program, const IVec4& viewport) const
559 {
560 	const glw::Functions&	gl					= m_renderCtx.getFunctions();
561 
562 	const int				width				= viewport.z();
563 	const int				height				= viewport.w();
564 	const deInt32			defaultFramebuffer	= m_renderCtx.getDefaultFramebuffer();
565 
566 	DE_UNREF(program);
567 
568 	// blit to default framebuffer
569 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, **m_fbo);
570 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebuffer);
571 
572 	gl.blitFramebuffer(0, 0, SIZE, SIZE, viewport.x(), viewport.y(), viewport.x() + width, viewport.y() + height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
573 
574 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, defaultFramebuffer);
575 }
576 
577 struct BufferFmtDesc
578 {
579 	tcu::TextureFormat	texFmt;
580 	GLenum				colorFmt;
581 };
582 
583 struct Color
584 {
585 	enum Type {FLOAT, INT, UINT};
586 
587 	Type type;
588 
589 	union
590 	{
591 		float		f[4];
592 		deInt32		i[4];
593 		deUint32	u[4];
594 	};
595 
Colordeqp::gls::Functional::__anon4c95315a0111::Color596 	Color(const float f_[4])    : type(FLOAT) { f[0] = f_[0]; f[1] = f_[1]; f[2] = f_[2]; f[3] = f_[3]; }
Colordeqp::gls::Functional::__anon4c95315a0111::Color597 	Color(const deInt32 i_[4])  : type(INT)   { i[0] = i_[0]; i[1] = i_[1]; i[2] = i_[2]; i[3] = i_[3]; }
Colordeqp::gls::Functional::__anon4c95315a0111::Color598 	Color(const deUint32 u_[4]) : type(UINT)  { u[0] = u_[0]; u[1] = u_[1]; u[2] = u_[2]; u[3] = u_[3]; }
599 };
600 
601 class FramebufferClearCase : public tcu::TestCase
602 {
603 public:
604 							FramebufferClearCase	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, ClearType clearType);
~FramebufferClearCase(void)605 	virtual					~FramebufferClearCase	(void) {}
606 
607 	virtual IterateResult	iterate					(void);
608 
609 private:
610 	static void				clearBuffers			(const glw::Functions& gl, Color color, float depth, int stencil);
611 	static Color			getBaseColor			(const BufferFmtDesc& bufferFmt);
612 	static Color			getMainColor			(const BufferFmtDesc& bufferFmt);
613 	static BufferFmtDesc	getBufferFormat			(ClearType type);
614 
615 	virtual void			render					(GLuint program) const;
616 	virtual bool			isPoint					(void) const;
617 
618 	glu::RenderContext&		m_renderCtx;
619 	const ClearType			m_clearType;
620 };
621 
FramebufferClearCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,ClearType clearType)622 FramebufferClearCase::FramebufferClearCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, ClearType clearType)
623 	: tcu::TestCase	(testCtx, name, desc)
624 	, m_renderCtx	(renderCtx)
625 	, m_clearType	(clearType)
626 {
627 }
628 
clearBuffers(const glw::Functions & gl,Color color,float depth,int stencil)629 void FramebufferClearCase::clearBuffers (const glw::Functions& gl, Color color, float depth, int stencil)
630 {
631 	switch(color.type)
632 	{
633 		case Color::FLOAT:	gl.clearBufferfv (GL_COLOR, 0, color.f); break;
634 		case Color::INT:	gl.clearBufferiv (GL_COLOR, 0, color.i); break;
635 		case Color::UINT:	gl.clearBufferuiv(GL_COLOR, 0, color.u); break;
636 		default:
637 			DE_ASSERT(false);
638 	}
639 
640 	gl.clearBufferfv(GL_DEPTH, 0, &depth);
641 	gl.clearBufferiv(GL_STENCIL, 0, &stencil);
642 }
643 
iterate(void)644 FramebufferClearCase::IterateResult FramebufferClearCase::iterate (void)
645 {
646 	TestLog&					log				= m_testCtx.getLog();
647 	const glw::Functions&		gl				= m_renderCtx.getFunctions();
648 	const glu::ShaderProgram	shader			(m_renderCtx, genShaders(glu::getContextTypeGLSLVersion(m_renderCtx.getType()), isPoint()));
649 
650 	const glu::Framebuffer		fbo				(gl);
651 	const glu::Renderbuffer		colorbuf		(gl);
652 	const glu::Renderbuffer		depthbuf		(gl);
653 
654 	const BufferFmtDesc			bufferFmt		= getBufferFormat(m_clearType);
655 	const Color					baseColor		= getBaseColor(bufferFmt);
656 
657 	const int					width			= 64;
658 	const int					height			= 64;
659 
660 	const IVec4					scissorArea		(8, 8, 48, 48);
661 
662 	vector<deUint8>				refData			(width*height*bufferFmt.texFmt.getPixelSize());
663 	vector<deUint8>				resData			(width*height*bufferFmt.texFmt.getPixelSize());
664 
665 	tcu::PixelBufferAccess		refAccess		(bufferFmt.texFmt, width, height, 1, &refData[0]);
666 	tcu::PixelBufferAccess		resAccess		(bufferFmt.texFmt, width, height, 1, &resData[0]);
667 
668 	if (!shader.isOk())
669 	{
670 		log << shader;
671 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Shader compile/link failed");
672 		return STOP;
673 	}
674 
675 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *fbo);
676 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *fbo);
677 
678 	// Color
679 	gl.bindRenderbuffer(GL_RENDERBUFFER, *colorbuf);
680 	gl.renderbufferStorage(GL_RENDERBUFFER, bufferFmt.colorFmt, width, height);
681 	gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *colorbuf);
682 
683 	// Depth/stencil
684 	gl.bindRenderbuffer(GL_RENDERBUFFER, *depthbuf);
685 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
686 	gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *depthbuf);
687 
688 	log << TestLog::Message << "Scissor area is " << scissorArea << TestLog::EndMessage;
689 
690 	// Render reference
691 	{
692 		log << TestLog::Message << "Rendering reference (scissors disabled)" << TestLog::EndMessage;
693 
694 		gl.useProgram(shader.getProgram());
695 		gl.viewport(0, 0, width, height);
696 
697 		gl.disable(GL_DEPTH_TEST);
698 		gl.disable(GL_STENCIL_TEST);
699 		gl.disable(GL_SCISSOR_TEST);
700 
701 		clearBuffers(gl, baseColor, 1.0f, 0);
702 
703 		render(shader.getProgram());
704 
705 		glu::readPixels(m_renderCtx, 0, 0, refAccess);
706 		GLU_CHECK_ERROR(gl.getError());
707 	}
708 
709 	// Render result
710 	{
711 		log << TestLog::Message << "Rendering result (scissors enabled)" << TestLog::EndMessage;
712 
713 		gl.useProgram(shader.getProgram());
714 		gl.viewport(0, 0, width, height);
715 
716 		gl.disable(GL_DEPTH_TEST);
717 		gl.disable(GL_STENCIL_TEST);
718 		gl.disable(GL_SCISSOR_TEST);
719 
720 		clearBuffers(gl, baseColor, 1.0f, 0);
721 
722 		gl.enable(GL_SCISSOR_TEST);
723 		gl.scissor(scissorArea.x(), scissorArea.y(), scissorArea.z(), scissorArea.w());
724 
725 		render(shader.getProgram());
726 
727 		glu::readPixels(m_renderCtx, 0, 0, resAccess);
728 		GLU_CHECK_ERROR(gl.getError());
729 	}
730 
731 	{
732 		bool resultOk = false;
733 
734 		switch (baseColor.type)
735 		{
736 			case Color::FLOAT:
737 				clearEdges(refAccess, Vec4(baseColor.f[0], baseColor.f[1], baseColor.f[2], baseColor.f[3]), scissorArea);
738 				resultOk = tcu::floatThresholdCompare(log, "ComparisonResult", "Image comparison result", refAccess, resAccess, Vec4(0.02f, 0.02f, 0.02f, 0.02f), tcu::COMPARE_LOG_RESULT);
739 				break;
740 
741 			case Color::INT:
742 				clearEdges(refAccess, IVec4(baseColor.i[0], baseColor.i[1], baseColor.i[2], baseColor.i[3]), scissorArea);
743 				resultOk = tcu::intThresholdCompare(log, "ComparisonResult", "Image comparison result", refAccess, resAccess, UVec4(2, 2, 2, 2), tcu::COMPARE_LOG_RESULT);
744 				break;
745 
746 			case Color::UINT:
747 				clearEdges(refAccess, UVec4(baseColor.u[0], baseColor.u[1], baseColor.u[2], baseColor.u[3]), scissorArea);
748 				resultOk = tcu::intThresholdCompare(log, "ComparisonResult", "Image comparison result", refAccess, resAccess, UVec4(2, 2, 2, 2), tcu::COMPARE_LOG_RESULT);
749 				break;
750 		}
751 
752 		if (resultOk)
753 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
754 		else
755 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
756 	}
757 
758 	return STOP;
759 }
760 
getBaseColor(const BufferFmtDesc & bufferFmt)761 Color FramebufferClearCase::getBaseColor (const BufferFmtDesc& bufferFmt)
762 {
763 	const float		f[4] = {0.125f, 0.25f, 0.5f, 1.0f};
764 	const deInt32	i[4] = {0, 0, 0, 0};
765 	const deUint32	u[4] = {0, 0, 0, 0};
766 
767 	switch(bufferFmt.colorFmt)
768 	{
769 		case GL_RGBA8:		return Color(f);
770 		case GL_RGBA8I:		return Color(i);
771 		case GL_RGBA8UI:	return Color(u);
772 		default:
773 			DE_ASSERT(false);
774 	}
775 
776 	return Color(f);
777 }
778 
getMainColor(const BufferFmtDesc & bufferFmt)779 Color FramebufferClearCase::getMainColor (const BufferFmtDesc& bufferFmt)
780 {
781 	const float		f[4] = {1.0f, 1.0f, 0.5f, 1.0f};
782 	const deInt32	i[4] = {127, -127, 0, 127};
783 	const deUint32	u[4] = {255, 255, 0, 255};
784 
785 	switch(bufferFmt.colorFmt)
786 	{
787 		case GL_RGBA8:		return Color(f);
788 		case GL_RGBA8I:		return Color(i);
789 		case GL_RGBA8UI:	return Color(u);
790 		default:
791 			DE_ASSERT(false);
792 	}
793 
794 	return Color(f);
795 }
796 
getBufferFormat(ClearType type)797 BufferFmtDesc FramebufferClearCase::getBufferFormat (ClearType type)
798 {
799 	BufferFmtDesc retval;
800 
801 	switch (type)
802 	{
803 		case CLEAR_COLOR_FLOAT:
804 			retval.colorFmt	= GL_RGBA16F;
805 			retval.texFmt	= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::HALF_FLOAT);
806 			DE_FATAL("Floating point clear not implemented");// \todo [2014-1-23 otto] pixel read format & type, nothing guaranteed, need extension...
807 			break;
808 
809 		case CLEAR_COLOR_INT:
810 			retval.colorFmt	= GL_RGBA8I;
811 			retval.texFmt	= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
812 			break;
813 
814 		case CLEAR_COLOR_UINT:
815 			retval.colorFmt	= GL_RGBA8UI;
816 			retval.texFmt	= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
817 			break;
818 
819 		default:
820 			retval.colorFmt = GL_RGBA8;
821 			retval.texFmt	= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
822 			break;
823 	}
824 
825 	return retval;
826 }
827 
render(GLuint program) const828 void FramebufferClearCase::render (GLuint program) const
829 {
830 	const glw::Functions&	gl					= m_renderCtx.getFunctions();
831 
832 	const BufferFmtDesc		bufferFmt			= getBufferFormat(m_clearType);
833 	const Color				clearColor			= getMainColor(bufferFmt);
834 
835 	const int				clearStencil		= 123;
836 	const float				clearDepth			= 0.5f;
837 
838 	switch (m_clearType)
839 	{
840 		case CLEAR_COLOR_FIXED:		gl.clearBufferfv (GL_COLOR, 0, clearColor.f);						break;
841 		case CLEAR_COLOR_FLOAT:		gl.clearBufferfv (GL_COLOR, 0, clearColor.f);						break;
842 		case CLEAR_COLOR_INT:		gl.clearBufferiv (GL_COLOR, 0, clearColor.i);						break;
843 		case CLEAR_COLOR_UINT:		gl.clearBufferuiv(GL_COLOR, 0, clearColor.u);						break;
844 		case CLEAR_DEPTH:			gl.clearBufferfv (GL_DEPTH, 0, &clearDepth);						break;
845 		case CLEAR_STENCIL:			gl.clearBufferiv (GL_STENCIL, 0, &clearStencil);					break;
846 		case CLEAR_DEPTH_STENCIL:	gl.clearBufferfi (GL_DEPTH_STENCIL, 0, clearDepth, clearStencil);	break;
847 
848 		default:
849 			DE_ASSERT(false);
850 	}
851 
852 	const bool useDepth		= (m_clearType == CLEAR_DEPTH   || m_clearType == CLEAR_DEPTH_STENCIL);
853 	const bool useStencil	= (m_clearType == CLEAR_STENCIL || m_clearType == CLEAR_DEPTH_STENCIL);
854 
855 	// Render something to expose changes to depth/stencil buffer
856 	if (useDepth || useStencil)
857 	{
858 		if (useDepth)
859 			gl.enable(GL_DEPTH_TEST);
860 
861 		if (useStencil)
862 			gl.enable(GL_STENCIL_TEST);
863 
864 		gl.stencilFunc(GL_EQUAL, clearStencil, ~0u);
865 		gl.depthFunc(GL_GREATER);
866 		gl.disable(GL_SCISSOR_TEST);
867 
868 		gl.uniform4fv(gl.getUniformLocation(program, "u_color"), 1, clearColor.f);
869 		drawQuad(gl, program, tcu::Vec3(-1.0f, -1.0f, 0.6f), tcu::Vec3(1.0f, 1.0f, 0.6f));
870 	}
871 }
872 
isPoint(void) const873 bool FramebufferClearCase::isPoint (void) const
874 {
875 	return false;
876 }
877 
878 } // Anonymous
879 
880 namespace ScissorTestInternal
881 {
882 
createPrimitiveTest(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,const Vec4 & scissorArea,const Vec4 & renderArea,PrimitiveType type,int primitiveCount)883 tcu::TestNode* createPrimitiveTest (tcu::TestContext&	testCtx,
884 									glu::RenderContext&	renderCtx,
885 									const char*			name,
886 									const char*			desc,
887 									const Vec4&			scissorArea,
888 									const Vec4&			renderArea,
889 									PrimitiveType		type,
890 									int					primitiveCount)
891 {
892 	return new ScissorPrimitiveCase(testCtx, renderCtx, name, desc, scissorArea, renderArea, type, primitiveCount);
893 }
894 
createClearTest(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,const Vec4 & scissorArea,deUint32 clearMode)895 tcu::TestNode* createClearTest (tcu::TestContext&	testCtx,
896 								glu::RenderContext&	renderCtx,
897 								const char*			name,
898 								const char*			desc,
899 								const Vec4&			scissorArea,
900 								deUint32			clearMode)
901 {
902 	return new ScissorClearCase(testCtx, renderCtx, name, desc, scissorArea, clearMode);
903 }
904 
createFramebufferClearTest(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,ClearType clearType)905 tcu::TestNode* createFramebufferClearTest (tcu::TestContext&	testCtx,
906 										   glu::RenderContext&	renderCtx,
907 										   const char*			name,
908 										   const char*			desc,
909 										   ClearType			clearType)
910 {
911 	return new FramebufferClearCase(testCtx, renderCtx, name, desc, clearType);
912 }
913 
createFramebufferBlitTest(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * desc,const Vec4 & scissorArea)914 tcu::TestNode* createFramebufferBlitTest (tcu::TestContext&		testCtx,
915 										  glu::RenderContext&	renderCtx,
916 										  const char*			name,
917 										  const char*			desc,
918 										  const Vec4&			scissorArea)
919 {
920 	return new FramebufferBlitCase(testCtx, renderCtx, name, desc, scissorArea);
921 }
922 
923 } // ScissorTestInternal
924 } // Functional
925 } // gls
926 } // deqp
927