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