glsFragmentOpUtil.cpp revision 3c827367444ee418f129b2c238299f49d3264554
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 Fragment operation test utilities.
22 *//*--------------------------------------------------------------------*/
23
24#include "glsFragmentOpUtil.hpp"
25#include "gluRenderContext.hpp"
26#include "gluShaderProgram.hpp"
27#include "gluDrawUtil.hpp"
28#include "glwFunctions.hpp"
29#include "glwEnums.hpp"
30
31namespace deqp
32{
33namespace gls
34{
35namespace FragmentOpUtil
36{
37
38template<typename T>
39inline T triQuadInterpolate (const T values[4], float xFactor, float yFactor)
40{
41	if (xFactor + yFactor < 1.0f)
42		return values[0] + (values[2]-values[0])*xFactor		+ (values[1]-values[0])*yFactor;
43	else
44		return values[3] + (values[1]-values[3])*(1.0f-xFactor)	+ (values[2]-values[3])*(1.0f-yFactor);
45}
46
47// GLSL ES 1.0 shaders
48static const char* s_glsl1VertSrc =
49	"attribute highp vec4 a_position;\n"
50	"attribute mediump vec4 a_color;\n"
51	"varying mediump vec4 v_color;\n"
52	"void main()\n"
53	"{\n"
54	"	gl_Position = a_position;\n"
55	"	v_color = a_color;\n"
56	"}\n";
57static const char* s_glsl1FragSrc =
58	"varying mediump vec4 v_color;\n"
59	"void main()\n"
60	"{\n"
61	"	gl_FragColor = v_color;\n"
62	"}\n";
63
64// GLSL ES 3.0 shaders
65static const char* s_glsl3VertSrc =
66	"#version 300 es\n"
67	"in highp vec4 a_position;\n"
68	"in mediump vec4 a_color;\n"
69	"out mediump vec4 v_color;\n"
70	"void main()\n"
71	"{\n"
72	"	gl_Position = a_position;\n"
73	"	v_color = a_color;\n"
74	"}\n";
75static const char* s_glsl3FragSrc =
76	"#version 300 es\n"
77	"in mediump vec4 v_color;\n"
78	"layout(location = 0) out mediump vec4 o_color;\n"
79	"void main()\n"
80	"{\n"
81	"	o_color = v_color;\n"
82	"}\n";
83
84// GLSL 3.3 shaders
85static const char* s_glsl33VertSrc =
86	"#version 330 core\n"
87	"in vec4 a_position;\n"
88	"in vec4 a_color;\n"
89	"in vec4 a_color1;\n"
90	"out vec4 v_color;\n"
91	"out vec4 v_color1;\n"
92	"void main()\n"
93	"{\n"
94	"	gl_Position	= a_position;\n"
95	"	v_color		= a_color;\n"
96	"	v_color1	= a_color1;\n"
97	"}\n";
98static const char* s_glsl33FragSrc =
99	"#version 330 core\n"
100	"in vec4 v_color;\n"
101	"in vec4 v_color1;\n"
102	"layout(location = 0, index = 0) out vec4 o_color;\n"
103	"layout(location = 0, index = 1) out vec4 o_color1;\n"
104	"void main()\n"
105	"{\n"
106	"	o_color  = v_color;\n"
107	"	o_color1 = v_color1;\n"
108	"}\n";
109
110static const char* getVertSrc (glu::GLSLVersion glslVersion)
111{
112	if (glslVersion == glu::GLSL_VERSION_100_ES)
113		return s_glsl1VertSrc;
114	else if (glslVersion == glu::GLSL_VERSION_300_ES)
115		return s_glsl3VertSrc;
116	else if (glslVersion == glu::GLSL_VERSION_330)
117		return s_glsl33VertSrc;
118
119	DE_ASSERT(DE_FALSE);
120	return 0;
121}
122
123static const char* getFragSrc (glu::GLSLVersion glslVersion)
124{
125	if (glslVersion == glu::GLSL_VERSION_100_ES)
126		return s_glsl1FragSrc;
127	else if (glslVersion == glu::GLSL_VERSION_300_ES)
128		return s_glsl3FragSrc;
129	else if (glslVersion == glu::GLSL_VERSION_330)
130		return s_glsl33FragSrc;
131
132	DE_ASSERT(DE_FALSE);
133	return 0;
134}
135
136QuadRenderer::QuadRenderer (const glu::RenderContext& context, glu::GLSLVersion glslVersion)
137	: m_context			(context)
138	, m_program			(DE_NULL)
139	, m_positionLoc		(0)
140	, m_colorLoc		(-1)
141	, m_color1Loc		(-1)
142	, m_blendFuncExt	(!glu::glslVersionIsES(glslVersion) && (glslVersion >= glu::GLSL_VERSION_330))
143{
144	DE_ASSERT(glslVersion == glu::GLSL_VERSION_100_ES ||
145			  glslVersion == glu::GLSL_VERSION_300_ES ||
146			  glslVersion == glu::GLSL_VERSION_330);
147
148	const glw::Functions&	gl		= context.getFunctions();
149	const char*				vertSrc	= getVertSrc(glslVersion);
150	const char*				fragSrc	= getFragSrc(glslVersion);
151
152	m_program = new glu::ShaderProgram(m_context, glu::makeVtxFragSources(vertSrc, fragSrc));
153	if (!m_program->isOk())
154	{
155		delete m_program;
156		throw tcu::TestError("Failed to compile program", DE_NULL, __FILE__, __LINE__);
157	}
158
159	m_positionLoc	= gl.getAttribLocation(m_program->getProgram(), "a_position");
160	m_colorLoc		= gl.getAttribLocation(m_program->getProgram(), "a_color");
161
162	if (m_blendFuncExt)
163		m_color1Loc = gl.getAttribLocation(m_program->getProgram(), "a_color1");
164
165	if (m_positionLoc < 0 || m_colorLoc < 0 || (m_blendFuncExt && m_color1Loc < 0))
166	{
167		delete m_program;
168		throw tcu::TestError("Invalid attribute locations", DE_NULL, __FILE__, __LINE__);
169	}
170}
171
172QuadRenderer::~QuadRenderer (void)
173{
174	delete m_program;
175}
176
177void QuadRenderer::render (const Quad& quad) const
178{
179	const float position[] =
180	{
181		quad.posA.x(), quad.posA.y(), quad.depth[0], 1.0f,
182		quad.posA.x(), quad.posB.y(), quad.depth[1], 1.0f,
183		quad.posB.x(), quad.posA.y(), quad.depth[2], 1.0f,
184		quad.posB.x(), quad.posB.y(), quad.depth[3], 1.0f
185	};
186	const deUint8 indices[] = { 0, 2, 1, 1, 2, 3 };
187
188	DE_STATIC_ASSERT(sizeof(tcu::Vec4) == sizeof(float)*4);
189	DE_STATIC_ASSERT(sizeof(quad.color) == sizeof(float)*4*4);
190	DE_STATIC_ASSERT(sizeof(quad.color1) == sizeof(float)*4*4);
191
192	std::vector<glu::VertexArrayBinding> vertexArrays;
193
194	vertexArrays.push_back(glu::va::Float(m_positionLoc,	4, 4, 0, &position[0]));
195	vertexArrays.push_back(glu::va::Float(m_colorLoc,		4, 4, 0, (const float*)&quad.color[0]));
196
197	if (m_blendFuncExt)
198		vertexArrays.push_back(glu::va::Float(m_color1Loc,	4, 4, 0, (const float*)&quad.color1[0]));
199
200	m_context.getFunctions().useProgram(m_program->getProgram());
201	glu::draw(m_context, m_program->getProgram(),
202			  (int)vertexArrays.size(), &vertexArrays[0],
203			  glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
204}
205
206ReferenceQuadRenderer::ReferenceQuadRenderer (void)
207	: m_fragmentBufferSize(0)
208{
209	for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_fragmentDepths); i++)
210		m_fragmentDepths[i] = 0.0f;
211}
212
213void ReferenceQuadRenderer::flushFragmentBuffer (const rr::MultisamplePixelBufferAccess&	colorBuffer,
214												 const rr::MultisamplePixelBufferAccess&	depthBuffer,
215												 const rr::MultisamplePixelBufferAccess&	stencilBuffer,
216												 rr::FaceType								faceType,
217												 const rr::FragmentOperationState&			state)
218{
219	m_fragmentProcessor.render(colorBuffer, depthBuffer, stencilBuffer, &m_fragmentBuffer[0], m_fragmentBufferSize, faceType, state);
220	m_fragmentBufferSize = 0;
221}
222
223void ReferenceQuadRenderer::render (const tcu::PixelBufferAccess&			colorBuffer,
224									const tcu::PixelBufferAccess&			depthBuffer,
225									const tcu::PixelBufferAccess&			stencilBuffer,
226									const IntegerQuad&						quad,
227									const rr::FragmentOperationState&		state)
228{
229	bool			flipX			= quad.posA.x() > quad.posB.x();
230	bool			flipY			= quad.posA.y() > quad.posB.y();
231	rr::FaceType	faceType		= flipX == flipY ? rr::FACETYPE_FRONT : rr::FACETYPE_BACK;
232	int				xFirst			= flipX ? quad.posB.x() : quad.posA.x();
233	int				xLast			= flipX ? quad.posA.x() : quad.posB.x();
234	int				yFirst			= flipY ? quad.posB.y() : quad.posA.y();
235	int				yLast			= flipY ? quad.posA.y() : quad.posB.y();
236	float			width			= (float)(xLast - xFirst + 1);
237	float			height			= (float)(yLast - yFirst + 1);
238
239	for (int y = yFirst; y <= yLast; y++)
240	{
241		// Interpolation factor for y.
242		float yRatio = (0.5f + (float)(y - yFirst)) / height;
243		if (flipY)
244			yRatio = 1.0f - yRatio;
245
246		for (int x = xFirst; x <= xLast; x++)
247		{
248			// Interpolation factor for x.
249			float xRatio = (0.5f + (float)(x - xFirst)) / width;
250			if (flipX)
251				xRatio = 1.0f - xRatio;
252
253			tcu::Vec4	color	= triQuadInterpolate(quad.color, xRatio, yRatio);
254			tcu::Vec4	color1	= triQuadInterpolate(quad.color1, xRatio, yRatio);
255			float		depth	= triQuadInterpolate(quad.depth, xRatio, yRatio);
256
257			// Interpolated color and depth.
258
259			DE_STATIC_ASSERT(MAX_FRAGMENT_BUFFER_SIZE == DE_LENGTH_OF_ARRAY(m_fragmentBuffer));
260
261			if (m_fragmentBufferSize >= MAX_FRAGMENT_BUFFER_SIZE)
262				flushFragmentBuffer(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer),
263									rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer),
264									rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer), faceType, state);
265
266			m_fragmentDepths[m_fragmentBufferSize] = depth;
267			m_fragmentBuffer[m_fragmentBufferSize] = rr::Fragment(tcu::IVec2(x, y), rr::GenericVec4(color), rr::GenericVec4(color1), 1u /* coverage mask */, &m_fragmentDepths[m_fragmentBufferSize]);
268			m_fragmentBufferSize++;
269		}
270	}
271
272	flushFragmentBuffer(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer),
273						rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer),
274						rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer), faceType, state);
275}
276
277tcu::PixelBufferAccess getMultisampleAccess(const tcu::PixelBufferAccess& original)
278{
279	return tcu::PixelBufferAccess(original.getFormat(),
280								  1,
281								  original.getWidth(),
282								  original.getHeight(),
283								  original.getFormat().getPixelSize(),
284								  original.getRowPitch(),
285								  original.getDataPtr());
286}
287
288tcu::ConstPixelBufferAccess getMultisampleAccess(const tcu::ConstPixelBufferAccess& original)
289{
290	return tcu::ConstPixelBufferAccess(original.getFormat(),
291									   1,
292									   original.getWidth(),
293									   original.getHeight(),
294									   original.getFormat().getPixelSize(),
295									   original.getRowPitch(),
296									   original.getDataPtr());
297}
298
299} // FragmentOpUtil
300} // gls
301} // deqp
302