1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.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 gl_FragData[] tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fShaderFragDataTests.hpp"
25 
26 #include "glsShaderLibrary.hpp"
27 
28 #include "gluRenderContext.hpp"
29 #include "gluShaderProgram.hpp"
30 #include "gluDrawUtil.hpp"
31 #include "gluPixelTransfer.hpp"
32 #include "gluObjectWrapper.hpp"
33 
34 #include "tcuRenderTarget.hpp"
35 #include "tcuStringTemplate.hpp"
36 #include "tcuTestLog.hpp"
37 #include "tcuSurface.hpp"
38 
39 #include "glwFunctions.hpp"
40 #include "glwEnums.hpp"
41 
42 namespace deqp
43 {
44 namespace gles2
45 {
46 namespace Functional
47 {
48 
49 using std::string;
50 using tcu::TestLog;
51 
52 namespace
53 {
54 
55 enum IndexExprType
56 {
57 	INDEX_EXPR_STATIC	= 0,
58 	INDEX_EXPR_UNIFORM,
59 	INDEX_EXPR_DYNAMIC,
60 
61 	INDEX_EXPR_TYPE_LAST
62 };
63 
compareSingleColor(tcu::TestLog & log,const tcu::Surface & surface,tcu::RGBA expectedColor,tcu::RGBA threshold)64 static bool compareSingleColor (tcu::TestLog& log, const tcu::Surface& surface, tcu::RGBA expectedColor, tcu::RGBA threshold)
65 {
66 	const int	maxPrints			= 10;
67 	int			numFailedPixels		= 0;
68 
69 	log << TestLog::Message << "Expecting " << expectedColor << " with threshold " << threshold << TestLog::EndMessage;
70 
71 	for (int y = 0; y < surface.getHeight(); y++)
72 	{
73 		for (int x = 0; x < surface.getWidth(); x++)
74 		{
75 			const tcu::RGBA		resultColor		= surface.getPixel(x, y);
76 			const bool			isOk			= compareThreshold(resultColor, expectedColor, threshold);
77 
78 			if (!isOk)
79 			{
80 				if (numFailedPixels < maxPrints)
81 					log << TestLog::Message << "ERROR: Got " << resultColor << " at (" << x << ", " << y << ")!" << TestLog::EndMessage;
82 				else if (numFailedPixels == maxPrints)
83 					log << TestLog::Message << "..." << TestLog::EndMessage;
84 
85 				numFailedPixels += 1;
86 			}
87 		}
88 	}
89 
90 	if (numFailedPixels > 0)
91 	{
92 		log << TestLog::Message << "Found " << numFailedPixels << " invalid pixels, comparison FAILED!" << TestLog::EndMessage;
93 		log << TestLog::Image("ResultImage", "Result Image", surface);
94 		return false;
95 	}
96 	else
97 	{
98 		log << TestLog::Message << "Image comparison passed." << TestLog::EndMessage;
99 		return true;
100 	}
101 }
102 
103 class FragDataIndexingCase : public TestCase
104 {
105 public:
FragDataIndexingCase(Context & context,const char * name,const char * description,IndexExprType indexExprType)106 	FragDataIndexingCase (Context& context, const char* name, const char* description, IndexExprType indexExprType)
107 		: TestCase			(context, name, description)
108 		, m_indexExprType	(indexExprType)
109 	{
110 	}
111 
genSources(const IndexExprType indexExprType)112 	static glu::ProgramSources genSources (const IndexExprType indexExprType)
113 	{
114 		const char* const	fragIndexExpr	= indexExprType == INDEX_EXPR_STATIC	? "0"				:
115 											  indexExprType == INDEX_EXPR_UNIFORM	? "u_index"			:
116 											  indexExprType == INDEX_EXPR_DYNAMIC	? "int(v_index)"	: DE_NULL;
117 		glu::ProgramSources	sources;
118 
119 		DE_ASSERT(fragIndexExpr);
120 
121 		sources << glu::VertexSource(
122 			"attribute highp vec4 a_position;\n"
123 			"attribute highp float a_index;\n"
124 			"attribute highp vec4 a_color;\n"
125 			"varying mediump float v_index;\n"
126 			"varying mediump vec4 v_color;\n"
127 			"void main (void)\n"
128 			"{\n"
129 			"	gl_Position = a_position;\n"
130 			"	v_color = a_color;\n"
131 			"	v_index = a_index;\n"
132 			"}\n");
133 
134 		sources << glu::FragmentSource(string(
135 			"varying mediump vec4 v_color;\n"
136 			"varying mediump float v_index;\n"
137 			"uniform mediump int u_index;\n"
138 			"void main (void)\n"
139 			"{\n"
140 			"	gl_FragData[") + fragIndexExpr + "] = v_color;\n"
141 			"}\n");
142 
143 		return sources;
144 	}
145 
iterate(void)146 	IterateResult iterate (void)
147 	{
148 		const glu::RenderContext&		renderCtx		= m_context.getRenderContext();
149 		const glw::Functions&			gl				= renderCtx.getFunctions();
150 		const glu::ShaderProgram		program			(renderCtx, genSources(m_indexExprType));
151 		const int						viewportW		= de::min(renderCtx.getRenderTarget().getWidth(), 128);
152 		const int						viewportH		= de::min(renderCtx.getRenderTarget().getHeight(), 128);
153 
154 		const float positions[] =
155 		{
156 			-1.0f, -1.0f,
157 			+1.0f, -1.0f,
158 			-1.0f, +1.0f,
159 			+1.0f, +1.0f
160 		};
161 		const float colors[] =
162 		{
163 			0.0f, 1.0f, 0.0f, 1.0f,
164 			0.0f, 1.0f, 0.0f, 1.0f,
165 			0.0f, 1.0f, 0.0f, 1.0f,
166 			0.0f, 1.0f, 0.0f, 1.0f
167 		};
168 		const float		indexValues[]	= { 0.0f, 0.0f, 0.0f, 0.0f };
169 		const deUint8	indices[]		= { 0, 1, 2, 2, 1, 3 };
170 
171 		const glu::VertexArrayBinding vertexArrays[] =
172 		{
173 			glu::va::Float("a_position",	2, 4, 0, &positions[0]),
174 			glu::va::Float("a_color",		4, 4, 0, &colors[0]),
175 			glu::va::Float("a_index",		1, 4, 0, &indexValues[0])
176 		};
177 
178 		m_testCtx.getLog() << program;
179 
180 		if (!program.isOk())
181 		{
182 			if (m_indexExprType == INDEX_EXPR_STATIC)
183 				TCU_FAIL("Compile failed");
184 			else
185 				throw tcu::NotSupportedError("Dynamic indexing of gl_FragData[] not supported");
186 		}
187 
188 		gl.clearColor	(1.0f, 0.0f, 0.0f, 1.0f);
189 		gl.clear		(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
190 
191 		gl.viewport		(0, 0, viewportW, viewportH);
192 		gl.useProgram	(program.getProgram());
193 		gl.uniform1i	(gl.getUniformLocation(program.getProgram(), "u_index"), 0);
194 
195 		glu::draw(renderCtx, program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
196 				  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
197 		GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
198 
199 		{
200 			tcu::Surface		result		(viewportW, viewportH);
201 			const tcu::RGBA		threshold	= renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
202 			bool				isOk;
203 
204 			glu::readPixels(renderCtx, 0, 0, result.getAccess());
205 			GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels failed");
206 
207 			isOk = compareSingleColor(m_testCtx.getLog(), result, tcu::RGBA::green(), threshold);
208 
209 			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
210 									isOk ? "Pass"				: "Image comparison failed");
211 		}
212 
213 		return STOP;
214 	}
215 
216 private:
217 	const IndexExprType m_indexExprType;
218 };
219 
220 } // anonymous
221 
ShaderFragDataTests(Context & context)222 ShaderFragDataTests::ShaderFragDataTests (Context& context)
223 	: TestCaseGroup(context, "fragdata", "gl_FragData[] Tests")
224 {
225 }
226 
~ShaderFragDataTests(void)227 ShaderFragDataTests::~ShaderFragDataTests (void)
228 {
229 }
230 
init(void)231 void ShaderFragDataTests::init (void)
232 {
233 	addChild(new FragDataIndexingCase(m_context, "valid_static_index",	"Valid gl_FragData[] assignment using static index",	INDEX_EXPR_STATIC));
234 	addChild(new FragDataIndexingCase(m_context, "valid_uniform_index",	"Valid gl_FragData[] assignment using uniform index",	INDEX_EXPR_UNIFORM));
235 	addChild(new FragDataIndexingCase(m_context, "valid_dynamic_index",	"Valid gl_FragData[] assignment using dynamic index",	INDEX_EXPR_DYNAMIC));
236 
237 	// Negative cases.
238 	{
239 		gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
240 		std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/fragdata.test");
241 
242 		for (std::vector<tcu::TestNode*>::iterator i = negativeCases.begin(); i != negativeCases.end(); i++)
243 			addChild(*i);
244 	}
245 }
246 
247 } // Functional
248 } // gles2
249 } // deqp
250