1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.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 Polygon offset tests.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "es3fPolygonOffsetTests.hpp"
25e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
26e5c31af7Sopenharmony_ci#include "deRandom.hpp"
27e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp"
28e5c31af7Sopenharmony_ci#include "gluRenderContext.hpp"
29e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
30e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
31e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp"
32e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
33e5c31af7Sopenharmony_ci#include "glwDefs.hpp"
34e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
35e5c31af7Sopenharmony_ci#include "tcuTestContext.hpp"
36e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
37e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
38e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
39e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp"
40e5c31af7Sopenharmony_ci#include "rrRenderer.hpp"
41e5c31af7Sopenharmony_ci#include "rrFragmentOperations.hpp"
42e5c31af7Sopenharmony_ci
43e5c31af7Sopenharmony_ci#include "sglrReferenceContext.hpp"
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_ci#include <string>
46e5c31af7Sopenharmony_ci#include <limits>
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ciusing namespace glw; // GLint and other GL types
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_cinamespace deqp
51e5c31af7Sopenharmony_ci{
52e5c31af7Sopenharmony_cinamespace gles3
53e5c31af7Sopenharmony_ci{
54e5c31af7Sopenharmony_cinamespace Functional
55e5c31af7Sopenharmony_ci{
56e5c31af7Sopenharmony_cinamespace
57e5c31af7Sopenharmony_ci{
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_ciconst char* s_shaderSourceVertex	= "#version 300 es\n"
60e5c31af7Sopenharmony_ci									  "in highp vec4 a_position;\n"
61e5c31af7Sopenharmony_ci									  "in highp vec4 a_color;\n"
62e5c31af7Sopenharmony_ci									  "out highp vec4 v_color;\n"
63e5c31af7Sopenharmony_ci									  "void main (void)\n"
64e5c31af7Sopenharmony_ci									  "{\n"
65e5c31af7Sopenharmony_ci									  "	gl_Position = a_position;\n"
66e5c31af7Sopenharmony_ci									  "	v_color = a_color;\n"
67e5c31af7Sopenharmony_ci									  "}\n";
68e5c31af7Sopenharmony_ciconst char* s_shaderSourceFragment	= "#version 300 es\n"
69e5c31af7Sopenharmony_ci									  "in highp vec4 v_color;\n"
70e5c31af7Sopenharmony_ci									  "layout(location = 0) out mediump vec4 fragColor;"
71e5c31af7Sopenharmony_ci									  "void main (void)\n"
72e5c31af7Sopenharmony_ci									  "{\n"
73e5c31af7Sopenharmony_ci									  "	fragColor = v_color;\n"
74e5c31af7Sopenharmony_ci									  "}\n";
75e5c31af7Sopenharmony_ci
76e5c31af7Sopenharmony_cistatic const tcu::Vec4	MASK_COLOR_OK	= tcu::Vec4(0.0f, 0.1f, 0.0f, 1.0f);
77e5c31af7Sopenharmony_cistatic const tcu::Vec4	MASK_COLOR_DEV	= tcu::Vec4(0.8f, 0.5f, 0.0f, 1.0f);
78e5c31af7Sopenharmony_cistatic const tcu::Vec4	MASK_COLOR_FAIL	= tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f);
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_ciinline bool compareThreshold (const tcu::IVec4& a, const tcu::IVec4& b, const tcu::IVec4& threshold)
81e5c31af7Sopenharmony_ci{
82e5c31af7Sopenharmony_ci	return tcu::boolAll(tcu::lessThanEqual(tcu::abs(a - b), threshold));
83e5c31af7Sopenharmony_ci}
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
86e5c31af7Sopenharmony_ci* \brief Pixelwise comparison of two images.
87e5c31af7Sopenharmony_ci* \note copied & modified from glsRasterizationTests
88e5c31af7Sopenharmony_ci*
89e5c31af7Sopenharmony_ci* Kernel radius defines maximum allowed distance. If radius is 0, only
90e5c31af7Sopenharmony_ci* perfect match is allowed. Radius of 1 gives a 3x3 kernel.
91e5c31af7Sopenharmony_ci*
92e5c31af7Sopenharmony_ci* Return values: -1 = Perfect match
93e5c31af7Sopenharmony_ci* 0 = Deviation within kernel
94e5c31af7Sopenharmony_ci* >0 = Number of faulty pixels
95e5c31af7Sopenharmony_ci*//*--------------------------------------------------------------------*/
96e5c31af7Sopenharmony_ciint compareImages (tcu::TestLog& log, glu::RenderContext& renderCtx, const tcu::ConstPixelBufferAccess& test, const tcu::ConstPixelBufferAccess& ref, const tcu::PixelBufferAccess& diffMask, int radius)
97e5c31af7Sopenharmony_ci{
98e5c31af7Sopenharmony_ci	const int			height			= test.getHeight();
99e5c31af7Sopenharmony_ci	const int			width			= test.getWidth();
100e5c31af7Sopenharmony_ci	const int			colorThreshold	= 128;
101e5c31af7Sopenharmony_ci	const tcu::RGBA		formatThreshold	= renderCtx.getRenderTarget().getPixelFormat().getColorThreshold();
102e5c31af7Sopenharmony_ci	const tcu::IVec4	threshold		= tcu::IVec4(colorThreshold, colorThreshold, colorThreshold, formatThreshold.getAlpha() > 0 ? colorThreshold : 0)
103e5c31af7Sopenharmony_ci										+ tcu::IVec4(formatThreshold.getRed(), formatThreshold.getGreen(), formatThreshold.getBlue(), formatThreshold.getAlpha());
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_ci	int			faultyPixels	= 0;
106e5c31af7Sopenharmony_ci	int			compareFailed	= -1;
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_ci	tcu::clear(diffMask, MASK_COLOR_OK);
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci	for (int y = 0; y < height; y++)
111e5c31af7Sopenharmony_ci	{
112e5c31af7Sopenharmony_ci		for (int x = 0; x < width; x++)
113e5c31af7Sopenharmony_ci		{
114e5c31af7Sopenharmony_ci			const tcu::IVec4 cRef = ref.getPixelInt(x, y);
115e5c31af7Sopenharmony_ci
116e5c31af7Sopenharmony_ci			// Pixelwise match, no deviation or fault
117e5c31af7Sopenharmony_ci			{
118e5c31af7Sopenharmony_ci				const tcu::IVec4 cTest = test.getPixelInt(x, y);
119e5c31af7Sopenharmony_ci				if (compareThreshold(cRef, cTest, threshold))
120e5c31af7Sopenharmony_ci					continue;
121e5c31af7Sopenharmony_ci			}
122e5c31af7Sopenharmony_ci
123e5c31af7Sopenharmony_ci			// If not, search within kernel radius
124e5c31af7Sopenharmony_ci			{
125e5c31af7Sopenharmony_ci				const int kYmin = deMax32(y - radius, 0);
126e5c31af7Sopenharmony_ci				const int kYmax = deMin32(y + radius, height-1);
127e5c31af7Sopenharmony_ci				const int kXmin = deMax32(x - radius, 0);
128e5c31af7Sopenharmony_ci				const int kXmax = deMin32(x + radius, width-1);
129e5c31af7Sopenharmony_ci				bool found = false;
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci				for (int kY = kYmin; kY <= kYmax; kY++)
132e5c31af7Sopenharmony_ci				for (int kX = kXmin; kX <= kXmax; kX++)
133e5c31af7Sopenharmony_ci				{
134e5c31af7Sopenharmony_ci					const tcu::IVec4 cTest = test.getPixelInt(kX, kY);
135e5c31af7Sopenharmony_ci					if (compareThreshold(cRef, cTest, threshold))
136e5c31af7Sopenharmony_ci						found = true;
137e5c31af7Sopenharmony_ci				}
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_ci				if (found)	// The pixel is deviating if the color is found inside the kernel
140e5c31af7Sopenharmony_ci				{
141e5c31af7Sopenharmony_ci					diffMask.setPixel(MASK_COLOR_DEV, x, y);
142e5c31af7Sopenharmony_ci					if (compareFailed == -1)
143e5c31af7Sopenharmony_ci						compareFailed = 0;
144e5c31af7Sopenharmony_ci					continue;
145e5c31af7Sopenharmony_ci				}
146e5c31af7Sopenharmony_ci			}
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ci			diffMask.setPixel(MASK_COLOR_FAIL, x, y);
149e5c31af7Sopenharmony_ci			faultyPixels++;										// The pixel is faulty if the color is not found
150e5c31af7Sopenharmony_ci			compareFailed = 1;
151e5c31af7Sopenharmony_ci		}
152e5c31af7Sopenharmony_ci	}
153e5c31af7Sopenharmony_ci
154e5c31af7Sopenharmony_ci	log << tcu::TestLog::Message << faultyPixels << " faulty pixel(s) found." << tcu::TestLog::EndMessage;
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci	return (compareFailed == 1 ? faultyPixels : compareFailed);
157e5c31af7Sopenharmony_ci}
158e5c31af7Sopenharmony_ci
159e5c31af7Sopenharmony_civoid verifyImages (tcu::TestLog& log, tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const tcu::ConstPixelBufferAccess& testImage, const tcu::ConstPixelBufferAccess& referenceImage)
160e5c31af7Sopenharmony_ci{
161e5c31af7Sopenharmony_ci	using tcu::TestLog;
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci	const int			kernelRadius		= 1;
164e5c31af7Sopenharmony_ci	const int			faultyPixelLimit	= 20;
165e5c31af7Sopenharmony_ci	int					faultyPixels;
166e5c31af7Sopenharmony_ci	tcu::Surface		diffMask			(testImage.getWidth(), testImage.getHeight());
167e5c31af7Sopenharmony_ci
168e5c31af7Sopenharmony_ci	faultyPixels = compareImages(log, renderCtx, referenceImage, testImage, diffMask.getAccess(), kernelRadius);
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_ci	if (faultyPixels > faultyPixelLimit)
171e5c31af7Sopenharmony_ci	{
172e5c31af7Sopenharmony_ci		log << TestLog::ImageSet("Images", "Image comparison");
173e5c31af7Sopenharmony_ci		log << TestLog::Image("Test image", "Test image", testImage);
174e5c31af7Sopenharmony_ci		log << TestLog::Image("Reference image", "Reference image", referenceImage);
175e5c31af7Sopenharmony_ci		log << TestLog::Image("Difference mask", "Difference mask", diffMask.getAccess());
176e5c31af7Sopenharmony_ci		log << TestLog::EndImageSet;
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage;
179e5c31af7Sopenharmony_ci		testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels");
180e5c31af7Sopenharmony_ci	}
181e5c31af7Sopenharmony_ci}
182e5c31af7Sopenharmony_ci
183e5c31af7Sopenharmony_civoid verifyError (tcu::TestContext& testCtx, const glw::Functions& gl, GLenum expected)
184e5c31af7Sopenharmony_ci{
185e5c31af7Sopenharmony_ci	deUint32 got = gl.getError();
186e5c31af7Sopenharmony_ci	if (got != expected)
187e5c31af7Sopenharmony_ci	{
188e5c31af7Sopenharmony_ci		testCtx.getLog() << tcu::TestLog::Message << "// ERROR: expected " << glu::getErrorStr(expected) << "; got " << glu::getErrorStr(got) << tcu::TestLog::EndMessage;
189e5c31af7Sopenharmony_ci		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
190e5c31af7Sopenharmony_ci			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid error");
191e5c31af7Sopenharmony_ci	}
192e5c31af7Sopenharmony_ci}
193e5c31af7Sopenharmony_ci
194e5c31af7Sopenharmony_civoid checkCanvasSize (int width, int height, int minWidth, int minHeight)
195e5c31af7Sopenharmony_ci{
196e5c31af7Sopenharmony_ci	if (width < minWidth || height < minHeight)
197e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError(std::string("Render context size must be at least ") + de::toString(minWidth) + "x" + de::toString(minWidth));
198e5c31af7Sopenharmony_ci}
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ciclass PositionColorShader : public sglr::ShaderProgram
201e5c31af7Sopenharmony_ci{
202e5c31af7Sopenharmony_cipublic:
203e5c31af7Sopenharmony_ci	enum
204e5c31af7Sopenharmony_ci	{
205e5c31af7Sopenharmony_ci		VARYINGLOC_COLOR = 0
206e5c31af7Sopenharmony_ci	};
207e5c31af7Sopenharmony_ci
208e5c31af7Sopenharmony_ci			PositionColorShader (void);
209e5c31af7Sopenharmony_ci	void	shadeVertices		(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
210e5c31af7Sopenharmony_ci	void	shadeFragments		(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
211e5c31af7Sopenharmony_ci};
212e5c31af7Sopenharmony_ci
213e5c31af7Sopenharmony_ciPositionColorShader::PositionColorShader (void)
214e5c31af7Sopenharmony_ci	: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
215e5c31af7Sopenharmony_ci							<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
216e5c31af7Sopenharmony_ci							<< sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
217e5c31af7Sopenharmony_ci							<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
218e5c31af7Sopenharmony_ci							<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
219e5c31af7Sopenharmony_ci							<< sglr::pdec::VertexSource(s_shaderSourceVertex)
220e5c31af7Sopenharmony_ci							<< sglr::pdec::FragmentSource(s_shaderSourceFragment))
221e5c31af7Sopenharmony_ci{
222e5c31af7Sopenharmony_ci}
223e5c31af7Sopenharmony_ci
224e5c31af7Sopenharmony_civoid PositionColorShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
225e5c31af7Sopenharmony_ci{
226e5c31af7Sopenharmony_ci	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
227e5c31af7Sopenharmony_ci	{
228e5c31af7Sopenharmony_ci		const int positionAttrLoc = 0;
229e5c31af7Sopenharmony_ci		const int colorAttrLoc = 1;
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_ci		rr::VertexPacket& packet = *packets[packetNdx];
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci		// Transform to position
234e5c31af7Sopenharmony_ci		packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx);
235e5c31af7Sopenharmony_ci
236e5c31af7Sopenharmony_ci		// Pass color to FS
237e5c31af7Sopenharmony_ci		packet.outputs[VARYINGLOC_COLOR] = rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx);
238e5c31af7Sopenharmony_ci	}
239e5c31af7Sopenharmony_ci}
240e5c31af7Sopenharmony_ci
241e5c31af7Sopenharmony_civoid PositionColorShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
242e5c31af7Sopenharmony_ci{
243e5c31af7Sopenharmony_ci	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
244e5c31af7Sopenharmony_ci	{
245e5c31af7Sopenharmony_ci		rr::FragmentPacket& packet = packets[packetNdx];
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_ci		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
248e5c31af7Sopenharmony_ci			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packet, context, VARYINGLOC_COLOR, fragNdx));
249e5c31af7Sopenharmony_ci	}
250e5c31af7Sopenharmony_ci}
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci// PolygonOffsetTestCase
253e5c31af7Sopenharmony_ci
254e5c31af7Sopenharmony_ciclass PolygonOffsetTestCase : public TestCase
255e5c31af7Sopenharmony_ci{
256e5c31af7Sopenharmony_cipublic:
257e5c31af7Sopenharmony_ci					PolygonOffsetTestCase	(Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName, int canvasSize);
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_ci	virtual void	testPolygonOffset		(void) = DE_NULL;
260e5c31af7Sopenharmony_ci	IterateResult	iterate					(void);
261e5c31af7Sopenharmony_ci
262e5c31af7Sopenharmony_ciprotected:
263e5c31af7Sopenharmony_ci	const GLenum	m_internalFormat;
264e5c31af7Sopenharmony_ci	const char*		m_internalFormatName;
265e5c31af7Sopenharmony_ci	const int		m_targetSize;
266e5c31af7Sopenharmony_ci};
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ciPolygonOffsetTestCase::PolygonOffsetTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName, int canvasSize)
269e5c31af7Sopenharmony_ci	: TestCase				(context, name, description)
270e5c31af7Sopenharmony_ci	, m_internalFormat		(internalFormat)
271e5c31af7Sopenharmony_ci	, m_internalFormatName	(internalFormatName)
272e5c31af7Sopenharmony_ci	, m_targetSize			(canvasSize)
273e5c31af7Sopenharmony_ci{
274e5c31af7Sopenharmony_ci}
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ciPolygonOffsetTestCase::IterateResult PolygonOffsetTestCase::iterate (void)
277e5c31af7Sopenharmony_ci{
278e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
279e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Testing PolygonOffset with " << m_internalFormatName << " depth buffer." << tcu::TestLog::EndMessage;
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ci	if (m_internalFormat == 0)
282e5c31af7Sopenharmony_ci	{
283e5c31af7Sopenharmony_ci		// default framebuffer
284e5c31af7Sopenharmony_ci		const int width		= m_context.getRenderTarget().getWidth();
285e5c31af7Sopenharmony_ci		const int height	= m_context.getRenderTarget().getHeight();
286e5c31af7Sopenharmony_ci
287e5c31af7Sopenharmony_ci		checkCanvasSize(width, height, m_targetSize, m_targetSize);
288e5c31af7Sopenharmony_ci
289e5c31af7Sopenharmony_ci		if (m_context.getRenderTarget().getDepthBits() == 0)
290e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("polygon offset tests require depth buffer");
291e5c31af7Sopenharmony_ci
292e5c31af7Sopenharmony_ci		testPolygonOffset();
293e5c31af7Sopenharmony_ci	}
294e5c31af7Sopenharmony_ci	else
295e5c31af7Sopenharmony_ci	{
296e5c31af7Sopenharmony_ci		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci		// framebuffer object
299e5c31af7Sopenharmony_ci		GLuint	colorRboId	= 0;
300e5c31af7Sopenharmony_ci		GLuint	depthRboId	= 0;
301e5c31af7Sopenharmony_ci		GLuint	fboId		= 0;
302e5c31af7Sopenharmony_ci		bool	fboComplete;
303e5c31af7Sopenharmony_ci
304e5c31af7Sopenharmony_ci		gl.genRenderbuffers(1, &colorRboId);
305e5c31af7Sopenharmony_ci		gl.bindRenderbuffer(GL_RENDERBUFFER, colorRboId);
306e5c31af7Sopenharmony_ci		gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, m_targetSize, m_targetSize);
307e5c31af7Sopenharmony_ci		verifyError(m_testCtx, gl, GL_NO_ERROR);
308e5c31af7Sopenharmony_ci
309e5c31af7Sopenharmony_ci		gl.genRenderbuffers(1, &depthRboId);
310e5c31af7Sopenharmony_ci		gl.bindRenderbuffer(GL_RENDERBUFFER, depthRboId);
311e5c31af7Sopenharmony_ci		gl.renderbufferStorage(GL_RENDERBUFFER, m_internalFormat, m_targetSize, m_targetSize);
312e5c31af7Sopenharmony_ci		verifyError(m_testCtx, gl, GL_NO_ERROR);
313e5c31af7Sopenharmony_ci
314e5c31af7Sopenharmony_ci		gl.genFramebuffers(1, &fboId);
315e5c31af7Sopenharmony_ci		gl.bindFramebuffer(GL_FRAMEBUFFER, fboId);
316e5c31af7Sopenharmony_ci		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRboId);
317e5c31af7Sopenharmony_ci		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,	GL_RENDERBUFFER, depthRboId);
318e5c31af7Sopenharmony_ci		verifyError(m_testCtx, gl, GL_NO_ERROR);
319e5c31af7Sopenharmony_ci
320e5c31af7Sopenharmony_ci		fboComplete = gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_ci		if (fboComplete)
323e5c31af7Sopenharmony_ci			testPolygonOffset();
324e5c31af7Sopenharmony_ci
325e5c31af7Sopenharmony_ci		gl.deleteFramebuffers(1, &fboId);
326e5c31af7Sopenharmony_ci		gl.deleteRenderbuffers(1, &depthRboId);
327e5c31af7Sopenharmony_ci		gl.deleteRenderbuffers(1, &colorRboId);
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci		if (!fboComplete)
330e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("could not create fbo for testing.");
331e5c31af7Sopenharmony_ci	}
332e5c31af7Sopenharmony_ci
333e5c31af7Sopenharmony_ci	return STOP;
334e5c31af7Sopenharmony_ci}
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci// UsageTestCase
337e5c31af7Sopenharmony_ci
338e5c31af7Sopenharmony_ciclass UsageTestCase : public PolygonOffsetTestCase
339e5c31af7Sopenharmony_ci{
340e5c31af7Sopenharmony_cipublic:
341e5c31af7Sopenharmony_ci			UsageTestCase		(Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName);
342e5c31af7Sopenharmony_ci
343e5c31af7Sopenharmony_ci	void	testPolygonOffset	(void);
344e5c31af7Sopenharmony_ci};
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ciUsageTestCase::UsageTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName)
347e5c31af7Sopenharmony_ci	: PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200)
348e5c31af7Sopenharmony_ci{
349e5c31af7Sopenharmony_ci}
350e5c31af7Sopenharmony_ci
351e5c31af7Sopenharmony_civoid UsageTestCase::testPolygonOffset (void)
352e5c31af7Sopenharmony_ci{
353e5c31af7Sopenharmony_ci	using tcu::TestLog;
354e5c31af7Sopenharmony_ci
355e5c31af7Sopenharmony_ci	const tcu::Vec4 triangle[] =
356e5c31af7Sopenharmony_ci	{
357e5c31af7Sopenharmony_ci		tcu::Vec4(-1,  1,  0,  1),
358e5c31af7Sopenharmony_ci		tcu::Vec4( 1,  1,  0,  1),
359e5c31af7Sopenharmony_ci		tcu::Vec4( 1, -1,  0,  1),
360e5c31af7Sopenharmony_ci	};
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci	tcu::TestLog&		log				= m_testCtx.getLog();
363e5c31af7Sopenharmony_ci	tcu::Surface		testImage		(m_targetSize, m_targetSize);
364e5c31af7Sopenharmony_ci	tcu::Surface		referenceImage	(m_targetSize, m_targetSize);
365e5c31af7Sopenharmony_ci	int					subpixelBits	= 0;
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_ci	// render test image
368e5c31af7Sopenharmony_ci	{
369e5c31af7Sopenharmony_ci		const glw::Functions&		gl			= m_context.getRenderContext().getFunctions();
370e5c31af7Sopenharmony_ci		const glu::ShaderProgram	program		(m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment));
371e5c31af7Sopenharmony_ci		const GLint					positionLoc = gl.getAttribLocation(program.getProgram(), "a_position");
372e5c31af7Sopenharmony_ci		const GLint					colorLoc	= gl.getAttribLocation(program.getProgram(), "a_color");
373e5c31af7Sopenharmony_ci
374e5c31af7Sopenharmony_ci		if (!program.isOk())
375e5c31af7Sopenharmony_ci		{
376e5c31af7Sopenharmony_ci			log << program;
377e5c31af7Sopenharmony_ci			TCU_FAIL("Shader compile failed.");
378e5c31af7Sopenharmony_ci		}
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_ci		gl.clearColor				(0, 0, 0, 1);
381e5c31af7Sopenharmony_ci		gl.clearDepthf				(1.0f);
382e5c31af7Sopenharmony_ci		gl.clear					(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
383e5c31af7Sopenharmony_ci		gl.viewport					(0, 0, m_targetSize, m_targetSize);
384e5c31af7Sopenharmony_ci		gl.useProgram				(program.getProgram());
385e5c31af7Sopenharmony_ci		gl.enable					(GL_DEPTH_TEST);
386e5c31af7Sopenharmony_ci		gl.depthFunc				(GL_LEQUAL);	// make test pass if polygon offset doesn't do anything. It has its own test case. This test is only for to detect always-on cases.
387e5c31af7Sopenharmony_ci
388e5c31af7Sopenharmony_ci		log << TestLog::Message << "DepthFunc = GL_LEQUAL" << TestLog::EndMessage;
389e5c31af7Sopenharmony_ci
390e5c31af7Sopenharmony_ci		gl.enableVertexAttribArray	(positionLoc);
391e5c31af7Sopenharmony_ci		gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangle);
392e5c31af7Sopenharmony_ci
393e5c31af7Sopenharmony_ci		//draw back (offset disabled)
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_ci		log << TestLog::Message << "Draw bottom-right. Color = White.\tState: PolygonOffset(0, -2), POLYGON_OFFSET_FILL disabled." << TestLog::EndMessage;
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci		gl.polygonOffset			(0, -2);
398e5c31af7Sopenharmony_ci		gl.disable					(GL_POLYGON_OFFSET_FILL);
399e5c31af7Sopenharmony_ci		gl.vertexAttrib4f			(colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
400e5c31af7Sopenharmony_ci		gl.drawArrays				(GL_TRIANGLES, 0, 3);
401e5c31af7Sopenharmony_ci
402e5c31af7Sopenharmony_ci		//draw front
403e5c31af7Sopenharmony_ci
404e5c31af7Sopenharmony_ci		log << TestLog::Message << "Draw bottom-right. Color = Red.\tState: PolygonOffset(0, -1), POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage;
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_ci		gl.polygonOffset			(0, -1);
407e5c31af7Sopenharmony_ci		gl.enable					(GL_POLYGON_OFFSET_FILL);
408e5c31af7Sopenharmony_ci		gl.vertexAttrib4f			(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
409e5c31af7Sopenharmony_ci		gl.drawArrays				(GL_TRIANGLES, 0, 3);
410e5c31af7Sopenharmony_ci
411e5c31af7Sopenharmony_ci		gl.disableVertexAttribArray	(positionLoc);
412e5c31af7Sopenharmony_ci		gl.useProgram				(0);
413e5c31af7Sopenharmony_ci		gl.finish					();
414e5c31af7Sopenharmony_ci
415e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess());
416e5c31af7Sopenharmony_ci
417e5c31af7Sopenharmony_ci		gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
418e5c31af7Sopenharmony_ci	}
419e5c31af7Sopenharmony_ci
420e5c31af7Sopenharmony_ci	// render reference image
421e5c31af7Sopenharmony_ci	{
422e5c31af7Sopenharmony_ci		rr::Renderer		referenceRenderer;
423e5c31af7Sopenharmony_ci		rr::VertexAttrib	attribs[2];
424e5c31af7Sopenharmony_ci		rr::RenderState		state((rr::ViewportState)(rr::WindowRectangle(0, 0, m_targetSize, m_targetSize)), subpixelBits);
425e5c31af7Sopenharmony_ci
426e5c31af7Sopenharmony_ci		PositionColorShader program;
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ci		attribs[0].type				= rr::VERTEXATTRIBTYPE_FLOAT;
429e5c31af7Sopenharmony_ci		attribs[0].size				= 4;
430e5c31af7Sopenharmony_ci		attribs[0].stride			= 0;
431e5c31af7Sopenharmony_ci		attribs[0].instanceDivisor	= 0;
432e5c31af7Sopenharmony_ci		attribs[0].pointer			= triangle;
433e5c31af7Sopenharmony_ci
434e5c31af7Sopenharmony_ci		attribs[1].type				= rr::VERTEXATTRIBTYPE_DONT_CARE;
435e5c31af7Sopenharmony_ci		attribs[1].generic			= tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
436e5c31af7Sopenharmony_ci
437e5c31af7Sopenharmony_ci		tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
438e5c31af7Sopenharmony_ci
439e5c31af7Sopenharmony_ci		log << TestLog::Message << "Expecting: Bottom-right = Red." << TestLog::EndMessage;
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci		referenceRenderer.draw(
442e5c31af7Sopenharmony_ci			rr::DrawCommand(
443e5c31af7Sopenharmony_ci				state,
444e5c31af7Sopenharmony_ci				rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(referenceImage.getAccess())),
445e5c31af7Sopenharmony_ci				rr::Program(program.getVertexShader(), program.getFragmentShader()),
446e5c31af7Sopenharmony_ci				2,
447e5c31af7Sopenharmony_ci				attribs,
448e5c31af7Sopenharmony_ci				rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, 3, 0)));
449e5c31af7Sopenharmony_ci	}
450e5c31af7Sopenharmony_ci
451e5c31af7Sopenharmony_ci	// compare
452e5c31af7Sopenharmony_ci	verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess());
453e5c31af7Sopenharmony_ci}
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci// UsageDisplacementTestCase
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ciclass UsageDisplacementTestCase : public PolygonOffsetTestCase
458e5c31af7Sopenharmony_ci{
459e5c31af7Sopenharmony_cipublic:
460e5c31af7Sopenharmony_ci				UsageDisplacementTestCase	(Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName);
461e5c31af7Sopenharmony_ci
462e5c31af7Sopenharmony_ciprivate:
463e5c31af7Sopenharmony_ci	tcu::Vec4	genRandomVec4				(de::Random& rnd) const;
464e5c31af7Sopenharmony_ci	void		testPolygonOffset			(void);
465e5c31af7Sopenharmony_ci};
466e5c31af7Sopenharmony_ci
467e5c31af7Sopenharmony_ciUsageDisplacementTestCase::UsageDisplacementTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName)
468e5c31af7Sopenharmony_ci	: PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200)
469e5c31af7Sopenharmony_ci{
470e5c31af7Sopenharmony_ci}
471e5c31af7Sopenharmony_ci
472e5c31af7Sopenharmony_citcu::Vec4 UsageDisplacementTestCase::genRandomVec4 (de::Random& rnd) const
473e5c31af7Sopenharmony_ci{
474e5c31af7Sopenharmony_ci	// generater triangle endpoint with following properties
475e5c31af7Sopenharmony_ci	//	1) it will not be clipped
476e5c31af7Sopenharmony_ci	//	2) it is not near either far or near plane to prevent possible problems related to depth clamping
477e5c31af7Sopenharmony_ci	// => w >= 1.0 and z in (-0.9, 0.9) range
478e5c31af7Sopenharmony_ci	tcu::Vec4 retVal;
479e5c31af7Sopenharmony_ci
480e5c31af7Sopenharmony_ci	retVal.x() = rnd.getFloat(-1, 1);
481e5c31af7Sopenharmony_ci	retVal.y() = rnd.getFloat(-1, 1);
482e5c31af7Sopenharmony_ci	retVal.z() = 0.5f;
483e5c31af7Sopenharmony_ci	retVal.w() = 1.0f + rnd.getFloat();
484e5c31af7Sopenharmony_ci
485e5c31af7Sopenharmony_ci	return retVal;
486e5c31af7Sopenharmony_ci}
487e5c31af7Sopenharmony_ci
488e5c31af7Sopenharmony_civoid UsageDisplacementTestCase::testPolygonOffset (void)
489e5c31af7Sopenharmony_ci{
490e5c31af7Sopenharmony_ci	using tcu::TestLog;
491e5c31af7Sopenharmony_ci
492e5c31af7Sopenharmony_ci	de::Random			rnd				(0xdec0de);
493e5c31af7Sopenharmony_ci	tcu::TestLog&		log				= m_testCtx.getLog();
494e5c31af7Sopenharmony_ci	tcu::Surface		testImage		(m_targetSize, m_targetSize);
495e5c31af7Sopenharmony_ci	tcu::Surface		referenceImage	(m_targetSize, m_targetSize);
496e5c31af7Sopenharmony_ci
497e5c31af7Sopenharmony_ci	// render test image
498e5c31af7Sopenharmony_ci	{
499e5c31af7Sopenharmony_ci		const glw::Functions&		gl				= m_context.getRenderContext().getFunctions();
500e5c31af7Sopenharmony_ci		const glu::ShaderProgram	program			(m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment));
501e5c31af7Sopenharmony_ci		const GLint					positionLoc		= gl.getAttribLocation(program.getProgram(), "a_position");
502e5c31af7Sopenharmony_ci		const GLint					colorLoc		= gl.getAttribLocation(program.getProgram(), "a_color");
503e5c31af7Sopenharmony_ci		const int					numIterations	= 40;
504e5c31af7Sopenharmony_ci
505e5c31af7Sopenharmony_ci		if (!program.isOk())
506e5c31af7Sopenharmony_ci		{
507e5c31af7Sopenharmony_ci			log << program;
508e5c31af7Sopenharmony_ci			TCU_FAIL("Shader compile failed.");
509e5c31af7Sopenharmony_ci		}
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci		gl.clearColor				(0, 0, 0, 1);
512e5c31af7Sopenharmony_ci		gl.clearDepthf				(1.0f);
513e5c31af7Sopenharmony_ci		gl.clear					(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
514e5c31af7Sopenharmony_ci		gl.viewport					(0, 0, m_targetSize, m_targetSize);
515e5c31af7Sopenharmony_ci		gl.useProgram				(program.getProgram());
516e5c31af7Sopenharmony_ci		gl.enable					(GL_DEPTH_TEST);
517e5c31af7Sopenharmony_ci		gl.enable					(GL_POLYGON_OFFSET_FILL);
518e5c31af7Sopenharmony_ci		gl.enableVertexAttribArray	(positionLoc);
519e5c31af7Sopenharmony_ci		gl.vertexAttrib4f			(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
520e5c31af7Sopenharmony_ci
521e5c31af7Sopenharmony_ci		log << TestLog::Message << "Framebuffer cleared, clear color = Black." << TestLog::EndMessage;
522e5c31af7Sopenharmony_ci		log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage;
523e5c31af7Sopenharmony_ci
524e5c31af7Sopenharmony_ci		// draw colorless (mask = 0,0,0) triangle at random* location, set offset and render green triangle with depthfunc = equal
525e5c31af7Sopenharmony_ci		// *) w >= 1.0 and z in (-1, 1) range
526e5c31af7Sopenharmony_ci		for (int iterationNdx = 0; iterationNdx < numIterations; ++iterationNdx)
527e5c31af7Sopenharmony_ci		{
528e5c31af7Sopenharmony_ci			const bool		offsetDirection = rnd.getBool();
529e5c31af7Sopenharmony_ci			const float		offset = offsetDirection ? -1.0f : 1.0f;
530e5c31af7Sopenharmony_ci			tcu::Vec4		triangle[3];
531e5c31af7Sopenharmony_ci
532e5c31af7Sopenharmony_ci			for (int vertexNdx = 0; vertexNdx < DE_LENGTH_OF_ARRAY(triangle); ++vertexNdx)
533e5c31af7Sopenharmony_ci				triangle[vertexNdx] = genRandomVec4(rnd);
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_ci			gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangle);
536e5c31af7Sopenharmony_ci
537e5c31af7Sopenharmony_ci			log << TestLog::Message << "Setup triangle with random coordinates:" << TestLog::EndMessage;
538e5c31af7Sopenharmony_ci			for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(triangle); ++ndx)
539e5c31af7Sopenharmony_ci				log << TestLog::Message
540e5c31af7Sopenharmony_ci						<< "\tx=" << triangle[ndx].x()
541e5c31af7Sopenharmony_ci						<< "\ty=" << triangle[ndx].y()
542e5c31af7Sopenharmony_ci						<< "\tz=" << triangle[ndx].z()
543e5c31af7Sopenharmony_ci						<< "\tw=" << triangle[ndx].w()
544e5c31af7Sopenharmony_ci						<< TestLog::EndMessage;
545e5c31af7Sopenharmony_ci
546e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw colorless triangle.\tState: DepthFunc = GL_ALWAYS, PolygonOffset(0, 0)." << TestLog::EndMessage;
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_ALWAYS);
549e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, 0);
550e5c31af7Sopenharmony_ci			gl.colorMask				(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
551e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
552e5c31af7Sopenharmony_ci
553e5c31af7Sopenharmony_ci			// all fragments should have different Z => DepthFunc == GL_EQUAL fails with every fragment
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw green triangle.\tState: DepthFunc = GL_EQUAL, PolygonOffset(0, " << offset << ")." << TestLog::EndMessage;
556e5c31af7Sopenharmony_ci
557e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_EQUAL);
558e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, offset);
559e5c31af7Sopenharmony_ci			gl.colorMask				(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
560e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
561e5c31af7Sopenharmony_ci
562e5c31af7Sopenharmony_ci			log << TestLog::Message << TestLog::EndMessage; // empty line for clarity
563e5c31af7Sopenharmony_ci		}
564e5c31af7Sopenharmony_ci
565e5c31af7Sopenharmony_ci		gl.disableVertexAttribArray	(positionLoc);
566e5c31af7Sopenharmony_ci		gl.useProgram				(0);
567e5c31af7Sopenharmony_ci		gl.finish					();
568e5c31af7Sopenharmony_ci
569e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess());
570e5c31af7Sopenharmony_ci	}
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_ci	// render reference image
573e5c31af7Sopenharmony_ci	log << TestLog::Message << "Expecting black framebuffer." << TestLog::EndMessage;
574e5c31af7Sopenharmony_ci	tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
575e5c31af7Sopenharmony_ci
576e5c31af7Sopenharmony_ci	// compare
577e5c31af7Sopenharmony_ci	verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess());
578e5c31af7Sopenharmony_ci}
579e5c31af7Sopenharmony_ci
580e5c31af7Sopenharmony_ci// UsagePositiveNegativeTestCase
581e5c31af7Sopenharmony_ci
582e5c31af7Sopenharmony_ciclass UsagePositiveNegativeTestCase : public PolygonOffsetTestCase
583e5c31af7Sopenharmony_ci{
584e5c31af7Sopenharmony_cipublic:
585e5c31af7Sopenharmony_ci			UsagePositiveNegativeTestCase	(Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName);
586e5c31af7Sopenharmony_ci
587e5c31af7Sopenharmony_ci	void	testPolygonOffset				(void);
588e5c31af7Sopenharmony_ci};
589e5c31af7Sopenharmony_ci
590e5c31af7Sopenharmony_ciUsagePositiveNegativeTestCase::UsagePositiveNegativeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName)
591e5c31af7Sopenharmony_ci	: PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200)
592e5c31af7Sopenharmony_ci{
593e5c31af7Sopenharmony_ci}
594e5c31af7Sopenharmony_ci
595e5c31af7Sopenharmony_civoid UsagePositiveNegativeTestCase::testPolygonOffset (void)
596e5c31af7Sopenharmony_ci{
597e5c31af7Sopenharmony_ci	using tcu::TestLog;
598e5c31af7Sopenharmony_ci
599e5c31af7Sopenharmony_ci	const tcu::Vec4 triangleBottomRight[] =
600e5c31af7Sopenharmony_ci	{
601e5c31af7Sopenharmony_ci		tcu::Vec4(-1,  1,  0,  1),
602e5c31af7Sopenharmony_ci		tcu::Vec4( 1,  1,  0,  1),
603e5c31af7Sopenharmony_ci		tcu::Vec4( 1, -1,  0,  1),
604e5c31af7Sopenharmony_ci	};
605e5c31af7Sopenharmony_ci	const tcu::Vec4 triangleTopLeft[] =
606e5c31af7Sopenharmony_ci	{
607e5c31af7Sopenharmony_ci		tcu::Vec4(-1, -1,  0,  1),
608e5c31af7Sopenharmony_ci		tcu::Vec4(-1,  1,  0,  1),
609e5c31af7Sopenharmony_ci		tcu::Vec4( 1, -1,  0,  1),
610e5c31af7Sopenharmony_ci	};
611e5c31af7Sopenharmony_ci
612e5c31af7Sopenharmony_ci	tcu::TestLog&		log				= m_testCtx.getLog();
613e5c31af7Sopenharmony_ci	tcu::Surface		testImage		(m_targetSize, m_targetSize);
614e5c31af7Sopenharmony_ci	tcu::Surface		referenceImage	(m_targetSize, m_targetSize);
615e5c31af7Sopenharmony_ci	int					subpixelBits	= 0;
616e5c31af7Sopenharmony_ci	// render test image
617e5c31af7Sopenharmony_ci	{
618e5c31af7Sopenharmony_ci		const glw::Functions&		gl				= m_context.getRenderContext().getFunctions();
619e5c31af7Sopenharmony_ci		const glu::ShaderProgram	program			(m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment));
620e5c31af7Sopenharmony_ci		const GLint					positionLoc		= gl.getAttribLocation(program.getProgram(), "a_position");
621e5c31af7Sopenharmony_ci		const GLint					colorLoc		= gl.getAttribLocation(program.getProgram(), "a_color");
622e5c31af7Sopenharmony_ci
623e5c31af7Sopenharmony_ci		if (!program.isOk())
624e5c31af7Sopenharmony_ci		{
625e5c31af7Sopenharmony_ci			log << program;
626e5c31af7Sopenharmony_ci			TCU_FAIL("Shader compile failed.");
627e5c31af7Sopenharmony_ci		}
628e5c31af7Sopenharmony_ci
629e5c31af7Sopenharmony_ci		gl.clearColor				(0, 0, 0, 1);
630e5c31af7Sopenharmony_ci		gl.clearDepthf				(1.0f);
631e5c31af7Sopenharmony_ci		gl.clear					(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
632e5c31af7Sopenharmony_ci		gl.viewport					(0, 0, m_targetSize, m_targetSize);
633e5c31af7Sopenharmony_ci		gl.depthFunc				(GL_LESS);
634e5c31af7Sopenharmony_ci		gl.useProgram				(program.getProgram());
635e5c31af7Sopenharmony_ci		gl.enable					(GL_DEPTH_TEST);
636e5c31af7Sopenharmony_ci		gl.enable					(GL_POLYGON_OFFSET_FILL);
637e5c31af7Sopenharmony_ci		gl.enableVertexAttribArray	(positionLoc);
638e5c31af7Sopenharmony_ci
639e5c31af7Sopenharmony_ci		log << TestLog::Message << "DepthFunc = GL_LESS." << TestLog::EndMessage;
640e5c31af7Sopenharmony_ci		log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage;
641e5c31af7Sopenharmony_ci
642e5c31af7Sopenharmony_ci		//draw top left (negative offset test)
643e5c31af7Sopenharmony_ci		{
644e5c31af7Sopenharmony_ci			gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleTopLeft);
645e5c31af7Sopenharmony_ci
646e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw top-left. Color = White.\tState: PolygonOffset(0, 0)." << TestLog::EndMessage;
647e5c31af7Sopenharmony_ci
648e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, 0);
649e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
650e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
651e5c31af7Sopenharmony_ci
652e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw top-left. Color = Green.\tState: PolygonOffset(0, -1)." << TestLog::EndMessage;
653e5c31af7Sopenharmony_ci
654e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, -1);
655e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
656e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
657e5c31af7Sopenharmony_ci		}
658e5c31af7Sopenharmony_ci
659e5c31af7Sopenharmony_ci		//draw bottom right (positive offset test)
660e5c31af7Sopenharmony_ci		{
661e5c31af7Sopenharmony_ci			gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleBottomRight);
662e5c31af7Sopenharmony_ci
663e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw bottom-right. Color = White.\tState: PolygonOffset(0, 1)." << TestLog::EndMessage;
664e5c31af7Sopenharmony_ci
665e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, 1);
666e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
667e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
668e5c31af7Sopenharmony_ci
669e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw bottom-right. Color = Yellow.\tState: PolygonOffset(0, 0)." << TestLog::EndMessage;
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, 0);
672e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 1.0f, 0.0f, 1.0f);
673e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
674e5c31af7Sopenharmony_ci		}
675e5c31af7Sopenharmony_ci
676e5c31af7Sopenharmony_ci		gl.disableVertexAttribArray	(positionLoc);
677e5c31af7Sopenharmony_ci		gl.useProgram				(0);
678e5c31af7Sopenharmony_ci		gl.finish					();
679e5c31af7Sopenharmony_ci
680e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess());
681e5c31af7Sopenharmony_ci
682e5c31af7Sopenharmony_ci		gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
683e5c31af7Sopenharmony_ci	}
684e5c31af7Sopenharmony_ci
685e5c31af7Sopenharmony_ci	// render reference image
686e5c31af7Sopenharmony_ci	{
687e5c31af7Sopenharmony_ci		rr::Renderer		referenceRenderer;
688e5c31af7Sopenharmony_ci		rr::VertexAttrib	attribs[2];
689e5c31af7Sopenharmony_ci		rr::RenderState		state((rr::ViewportState)(rr::WindowRectangle(0, 0, m_targetSize, m_targetSize)), subpixelBits);
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ci		PositionColorShader program;
692e5c31af7Sopenharmony_ci
693e5c31af7Sopenharmony_ci		attribs[0].type				= rr::VERTEXATTRIBTYPE_FLOAT;
694e5c31af7Sopenharmony_ci		attribs[0].size				= 4;
695e5c31af7Sopenharmony_ci		attribs[0].stride			= 0;
696e5c31af7Sopenharmony_ci		attribs[0].instanceDivisor	= 0;
697e5c31af7Sopenharmony_ci		attribs[0].pointer			= triangleTopLeft;
698e5c31af7Sopenharmony_ci
699e5c31af7Sopenharmony_ci		attribs[1].type				= rr::VERTEXATTRIBTYPE_DONT_CARE;
700e5c31af7Sopenharmony_ci		attribs[1].generic			= tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
701e5c31af7Sopenharmony_ci
702e5c31af7Sopenharmony_ci		tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
703e5c31af7Sopenharmony_ci
704e5c31af7Sopenharmony_ci		log << TestLog::Message << "Expecting: Top-left = Green, Bottom-right = Yellow." << TestLog::EndMessage;
705e5c31af7Sopenharmony_ci
706e5c31af7Sopenharmony_ci		referenceRenderer.draw(
707e5c31af7Sopenharmony_ci			rr::DrawCommand(
708e5c31af7Sopenharmony_ci				state,
709e5c31af7Sopenharmony_ci				rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(referenceImage.getAccess())),
710e5c31af7Sopenharmony_ci				rr::Program(program.getVertexShader(), program.getFragmentShader()),
711e5c31af7Sopenharmony_ci				2,
712e5c31af7Sopenharmony_ci				attribs,
713e5c31af7Sopenharmony_ci				rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, 3, 0)));
714e5c31af7Sopenharmony_ci
715e5c31af7Sopenharmony_ci		attribs[0].pointer = triangleBottomRight;
716e5c31af7Sopenharmony_ci		attribs[1].generic = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
717e5c31af7Sopenharmony_ci
718e5c31af7Sopenharmony_ci		referenceRenderer.draw(
719e5c31af7Sopenharmony_ci			rr::DrawCommand(
720e5c31af7Sopenharmony_ci				state,
721e5c31af7Sopenharmony_ci				rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(referenceImage.getAccess())),
722e5c31af7Sopenharmony_ci				rr::Program(program.getVertexShader(), program.getFragmentShader()),
723e5c31af7Sopenharmony_ci				2,
724e5c31af7Sopenharmony_ci				attribs,
725e5c31af7Sopenharmony_ci				rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, 3, 0)));
726e5c31af7Sopenharmony_ci	}
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci	// compare
729e5c31af7Sopenharmony_ci	verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess());
730e5c31af7Sopenharmony_ci}
731e5c31af7Sopenharmony_ci
732e5c31af7Sopenharmony_ci// ResultClampingTestCase
733e5c31af7Sopenharmony_ci
734e5c31af7Sopenharmony_ciclass ResultClampingTestCase : public PolygonOffsetTestCase
735e5c31af7Sopenharmony_ci{
736e5c31af7Sopenharmony_cipublic:
737e5c31af7Sopenharmony_ci			ResultClampingTestCase	(Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName);
738e5c31af7Sopenharmony_ci
739e5c31af7Sopenharmony_ci	void	testPolygonOffset		(void);
740e5c31af7Sopenharmony_ci};
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ciResultClampingTestCase::ResultClampingTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName)
743e5c31af7Sopenharmony_ci	: PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200)
744e5c31af7Sopenharmony_ci{
745e5c31af7Sopenharmony_ci}
746e5c31af7Sopenharmony_ci
747e5c31af7Sopenharmony_civoid ResultClampingTestCase::testPolygonOffset (void)
748e5c31af7Sopenharmony_ci{
749e5c31af7Sopenharmony_ci	using tcu::TestLog;
750e5c31af7Sopenharmony_ci
751e5c31af7Sopenharmony_ci	const tcu::Vec4 triangleBottomRight[] =
752e5c31af7Sopenharmony_ci	{
753e5c31af7Sopenharmony_ci		tcu::Vec4(-1,  1,  1,  1),
754e5c31af7Sopenharmony_ci		tcu::Vec4( 1,  1,  1,  1),
755e5c31af7Sopenharmony_ci		tcu::Vec4( 1, -1,  1,  1),
756e5c31af7Sopenharmony_ci	};
757e5c31af7Sopenharmony_ci	const tcu::Vec4 triangleTopLeft[] =
758e5c31af7Sopenharmony_ci	{
759e5c31af7Sopenharmony_ci		tcu::Vec4(-1, -1, -1,  1),
760e5c31af7Sopenharmony_ci		tcu::Vec4(-1,  1, -1,  1),
761e5c31af7Sopenharmony_ci		tcu::Vec4( 1, -1, -1,  1),
762e5c31af7Sopenharmony_ci	};
763e5c31af7Sopenharmony_ci
764e5c31af7Sopenharmony_ci	tcu::TestLog&		log				= m_testCtx.getLog();
765e5c31af7Sopenharmony_ci	tcu::Surface		testImage		(m_targetSize, m_targetSize);
766e5c31af7Sopenharmony_ci	tcu::Surface		referenceImage	(m_targetSize, m_targetSize);
767e5c31af7Sopenharmony_ci
768e5c31af7Sopenharmony_ci	// render test image
769e5c31af7Sopenharmony_ci	{
770e5c31af7Sopenharmony_ci		const glw::Functions&		gl			= m_context.getRenderContext().getFunctions();
771e5c31af7Sopenharmony_ci		const glu::ShaderProgram	program		(m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment));
772e5c31af7Sopenharmony_ci		const GLint					positionLoc = gl.getAttribLocation(program.getProgram(), "a_position");
773e5c31af7Sopenharmony_ci		const GLint					colorLoc	= gl.getAttribLocation(program.getProgram(), "a_color");
774e5c31af7Sopenharmony_ci
775e5c31af7Sopenharmony_ci		if (!program.isOk())
776e5c31af7Sopenharmony_ci		{
777e5c31af7Sopenharmony_ci			log << program;
778e5c31af7Sopenharmony_ci			TCU_FAIL("Shader compile failed.");
779e5c31af7Sopenharmony_ci		}
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci		gl.clearColor				(0, 0, 0, 1);
782e5c31af7Sopenharmony_ci		gl.clearDepthf				(1.0f);
783e5c31af7Sopenharmony_ci		gl.clear					(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
784e5c31af7Sopenharmony_ci		gl.viewport					(0, 0, m_targetSize, m_targetSize);
785e5c31af7Sopenharmony_ci		gl.useProgram				(program.getProgram());
786e5c31af7Sopenharmony_ci		gl.enable					(GL_DEPTH_TEST);
787e5c31af7Sopenharmony_ci		gl.enable					(GL_POLYGON_OFFSET_FILL);
788e5c31af7Sopenharmony_ci		gl.enableVertexAttribArray	(positionLoc);
789e5c31af7Sopenharmony_ci
790e5c31af7Sopenharmony_ci		log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage;
791e5c31af7Sopenharmony_ci
792e5c31af7Sopenharmony_ci		//draw bottom right (far)
793e5c31af7Sopenharmony_ci		{
794e5c31af7Sopenharmony_ci			gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleBottomRight);
795e5c31af7Sopenharmony_ci
796e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw bottom-right. Color = White.\tState: DepthFunc = ALWAYS, PolygonOffset(0, 8), Polygon Z = 1.0. (Result depth should clamp to 1.0)." << TestLog::EndMessage;
797e5c31af7Sopenharmony_ci
798e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_ALWAYS);
799e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, 8);
800e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
801e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
802e5c31af7Sopenharmony_ci
803e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw bottom-right. Color = Red.\tState: DepthFunc = GREATER, PolygonOffset(0, 9), Polygon Z = 1.0. (Result depth should clamp to 1.0 too)" << TestLog::EndMessage;
804e5c31af7Sopenharmony_ci
805e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_GREATER);
806e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, 9);
807e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
808e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
809e5c31af7Sopenharmony_ci		}
810e5c31af7Sopenharmony_ci
811e5c31af7Sopenharmony_ci		//draw top left (near)
812e5c31af7Sopenharmony_ci		{
813e5c31af7Sopenharmony_ci			gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleTopLeft);
814e5c31af7Sopenharmony_ci
815e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw top-left. Color = White.\tState: DepthFunc = ALWAYS, PolygonOffset(0, -8), Polygon Z = -1.0. (Result depth should clamp to -1.0)" << TestLog::EndMessage;
816e5c31af7Sopenharmony_ci
817e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_ALWAYS);
818e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, -8);
819e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
820e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
821e5c31af7Sopenharmony_ci
822e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw top-left. Color = Yellow.\tState: DepthFunc = LESS, PolygonOffset(0, -9), Polygon Z = -1.0. (Result depth should clamp to -1.0 too)." << TestLog::EndMessage;
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_LESS);
825e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, -9);
826e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 1.0f, 0.0f, 1.0f);
827e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
828e5c31af7Sopenharmony_ci		}
829e5c31af7Sopenharmony_ci
830e5c31af7Sopenharmony_ci		gl.disableVertexAttribArray	(positionLoc);
831e5c31af7Sopenharmony_ci		gl.useProgram				(0);
832e5c31af7Sopenharmony_ci		gl.finish					();
833e5c31af7Sopenharmony_ci
834e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess());
835e5c31af7Sopenharmony_ci	}
836e5c31af7Sopenharmony_ci
837e5c31af7Sopenharmony_ci	// render reference image
838e5c31af7Sopenharmony_ci	log << TestLog::Message << "Expecting: Top-left = White, Bottom-right = White." << TestLog::EndMessage;
839e5c31af7Sopenharmony_ci	tcu::clear(referenceImage.getAccess(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
840e5c31af7Sopenharmony_ci
841e5c31af7Sopenharmony_ci	// compare
842e5c31af7Sopenharmony_ci	verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess());
843e5c31af7Sopenharmony_ci}
844e5c31af7Sopenharmony_ci
845e5c31af7Sopenharmony_ci// UsageSlopeTestCase
846e5c31af7Sopenharmony_ci
847e5c31af7Sopenharmony_ciclass UsageSlopeTestCase  : public PolygonOffsetTestCase
848e5c31af7Sopenharmony_ci{
849e5c31af7Sopenharmony_cipublic:
850e5c31af7Sopenharmony_ci			UsageSlopeTestCase	(Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName);
851e5c31af7Sopenharmony_ci
852e5c31af7Sopenharmony_ci	void	testPolygonOffset	(void);
853e5c31af7Sopenharmony_ci};
854e5c31af7Sopenharmony_ci
855e5c31af7Sopenharmony_ciUsageSlopeTestCase::UsageSlopeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName)
856e5c31af7Sopenharmony_ci	: PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200)
857e5c31af7Sopenharmony_ci{
858e5c31af7Sopenharmony_ci}
859e5c31af7Sopenharmony_ci
860e5c31af7Sopenharmony_civoid UsageSlopeTestCase::testPolygonOffset (void)
861e5c31af7Sopenharmony_ci{
862e5c31af7Sopenharmony_ci	using tcu::TestLog;
863e5c31af7Sopenharmony_ci
864e5c31af7Sopenharmony_ci	const tcu::Vec4 triangleBottomRight[] =
865e5c31af7Sopenharmony_ci	{
866e5c31af7Sopenharmony_ci		tcu::Vec4(-1,  1,  0.0f,  1),
867e5c31af7Sopenharmony_ci		tcu::Vec4( 1,  1,  0.9f,  1),
868e5c31af7Sopenharmony_ci		tcu::Vec4( 1, -1,  0.9f,  1),
869e5c31af7Sopenharmony_ci	};
870e5c31af7Sopenharmony_ci	const tcu::Vec4 triangleTopLeft[] =
871e5c31af7Sopenharmony_ci	{
872e5c31af7Sopenharmony_ci		tcu::Vec4(-1, -1,  -0.9f,  1),
873e5c31af7Sopenharmony_ci		tcu::Vec4(-1,  1,   0.9f,  1),
874e5c31af7Sopenharmony_ci		tcu::Vec4( 1, -1,   0.0f,  1),
875e5c31af7Sopenharmony_ci	};
876e5c31af7Sopenharmony_ci
877e5c31af7Sopenharmony_ci	tcu::TestLog&		log				= m_testCtx.getLog();
878e5c31af7Sopenharmony_ci	tcu::Surface		testImage		(m_targetSize, m_targetSize);
879e5c31af7Sopenharmony_ci	tcu::Surface		referenceImage	(m_targetSize, m_targetSize);
880e5c31af7Sopenharmony_ci
881e5c31af7Sopenharmony_ci	// render test image
882e5c31af7Sopenharmony_ci	{
883e5c31af7Sopenharmony_ci		const glw::Functions&		gl			= m_context.getRenderContext().getFunctions();
884e5c31af7Sopenharmony_ci		const glu::ShaderProgram	program		(m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment));
885e5c31af7Sopenharmony_ci		const GLint					positionLoc = gl.getAttribLocation(program.getProgram(), "a_position");
886e5c31af7Sopenharmony_ci		const GLint					colorLoc	= gl.getAttribLocation(program.getProgram(), "a_color");
887e5c31af7Sopenharmony_ci
888e5c31af7Sopenharmony_ci		if (!program.isOk())
889e5c31af7Sopenharmony_ci		{
890e5c31af7Sopenharmony_ci			log << program;
891e5c31af7Sopenharmony_ci			TCU_FAIL("Shader compile failed.");
892e5c31af7Sopenharmony_ci		}
893e5c31af7Sopenharmony_ci
894e5c31af7Sopenharmony_ci		gl.clearColor				(0, 0, 0, 1);
895e5c31af7Sopenharmony_ci		gl.clearDepthf				(1.0f);
896e5c31af7Sopenharmony_ci		gl.clear					(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
897e5c31af7Sopenharmony_ci		gl.viewport					(0, 0, m_targetSize, m_targetSize);
898e5c31af7Sopenharmony_ci		gl.useProgram				(program.getProgram());
899e5c31af7Sopenharmony_ci		gl.enable					(GL_DEPTH_TEST);
900e5c31af7Sopenharmony_ci		gl.enable					(GL_POLYGON_OFFSET_FILL);
901e5c31af7Sopenharmony_ci		gl.enableVertexAttribArray	(positionLoc);
902e5c31af7Sopenharmony_ci
903e5c31af7Sopenharmony_ci		log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage;
904e5c31af7Sopenharmony_ci
905e5c31af7Sopenharmony_ci		//draw top left (negative offset test)
906e5c31af7Sopenharmony_ci		{
907e5c31af7Sopenharmony_ci			gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleTopLeft);
908e5c31af7Sopenharmony_ci
909e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw top-left. Color = White.\tState: DepthFunc = ALWAYS, PolygonOffset(0, 0)." << TestLog::EndMessage;
910e5c31af7Sopenharmony_ci
911e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_ALWAYS);
912e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, 0);
913e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
914e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
915e5c31af7Sopenharmony_ci
916e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw top-left. Color = Green.\tState: DepthFunc = LESS, PolygonOffset(-1, 0)." << TestLog::EndMessage;
917e5c31af7Sopenharmony_ci
918e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_LESS);
919e5c31af7Sopenharmony_ci			gl.polygonOffset			(-1, 0);
920e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
921e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
922e5c31af7Sopenharmony_ci		}
923e5c31af7Sopenharmony_ci
924e5c31af7Sopenharmony_ci		//draw bottom right (positive offset test)
925e5c31af7Sopenharmony_ci		{
926e5c31af7Sopenharmony_ci			gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleBottomRight);
927e5c31af7Sopenharmony_ci
928e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw bottom-right. Color = White.\tState: DepthFunc = ALWAYS, PolygonOffset(0, 0)." << TestLog::EndMessage;
929e5c31af7Sopenharmony_ci
930e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_ALWAYS);
931e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, 0);
932e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 1.0f, 1.0f, 1.0f);
933e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
934e5c31af7Sopenharmony_ci
935e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw bottom-right. Color = Green.\tState: DepthFunc = GREATER, PolygonOffset(1, 0)." << TestLog::EndMessage;
936e5c31af7Sopenharmony_ci
937e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_GREATER);
938e5c31af7Sopenharmony_ci			gl.polygonOffset			(1, 0);
939e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
940e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
941e5c31af7Sopenharmony_ci		}
942e5c31af7Sopenharmony_ci
943e5c31af7Sopenharmony_ci		gl.disableVertexAttribArray	(positionLoc);
944e5c31af7Sopenharmony_ci		gl.useProgram				(0);
945e5c31af7Sopenharmony_ci		gl.finish					();
946e5c31af7Sopenharmony_ci
947e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess());
948e5c31af7Sopenharmony_ci	}
949e5c31af7Sopenharmony_ci
950e5c31af7Sopenharmony_ci	// render reference image
951e5c31af7Sopenharmony_ci	log << TestLog::Message << "Expecting: Top-left = Green, Bottom-right = Green." << TestLog::EndMessage;
952e5c31af7Sopenharmony_ci	tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
953e5c31af7Sopenharmony_ci
954e5c31af7Sopenharmony_ci	// compare
955e5c31af7Sopenharmony_ci	verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess());
956e5c31af7Sopenharmony_ci}
957e5c31af7Sopenharmony_ci
958e5c31af7Sopenharmony_ci// ZeroSlopeTestCase
959e5c31af7Sopenharmony_ci
960e5c31af7Sopenharmony_ciclass ZeroSlopeTestCase : public PolygonOffsetTestCase
961e5c31af7Sopenharmony_ci{
962e5c31af7Sopenharmony_cipublic:
963e5c31af7Sopenharmony_ci			ZeroSlopeTestCase	(Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName);
964e5c31af7Sopenharmony_ci
965e5c31af7Sopenharmony_ci	void	testPolygonOffset	(void);
966e5c31af7Sopenharmony_ci};
967e5c31af7Sopenharmony_ci
968e5c31af7Sopenharmony_ciZeroSlopeTestCase::ZeroSlopeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName)
969e5c31af7Sopenharmony_ci	: PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200)
970e5c31af7Sopenharmony_ci{
971e5c31af7Sopenharmony_ci}
972e5c31af7Sopenharmony_ci
973e5c31af7Sopenharmony_civoid ZeroSlopeTestCase::testPolygonOffset (void)
974e5c31af7Sopenharmony_ci{
975e5c31af7Sopenharmony_ci	using tcu::TestLog;
976e5c31af7Sopenharmony_ci
977e5c31af7Sopenharmony_ci	const tcu::Vec4 triangle[] =
978e5c31af7Sopenharmony_ci	{
979e5c31af7Sopenharmony_ci		tcu::Vec4(-0.4f,  0.4f, 0.0f, 1.0f),
980e5c31af7Sopenharmony_ci		tcu::Vec4(-0.8f, -0.5f, 0.0f, 1.0f),
981e5c31af7Sopenharmony_ci		tcu::Vec4( 0.7f,  0.2f, 0.0f, 1.0f),
982e5c31af7Sopenharmony_ci	};
983e5c31af7Sopenharmony_ci
984e5c31af7Sopenharmony_ci	tcu::TestLog&		log				= m_testCtx.getLog();
985e5c31af7Sopenharmony_ci	tcu::Surface		testImage		(m_targetSize, m_targetSize);
986e5c31af7Sopenharmony_ci	tcu::Surface		referenceImage	(m_targetSize, m_targetSize);
987e5c31af7Sopenharmony_ci
988e5c31af7Sopenharmony_ci	// log the triangle
989e5c31af7Sopenharmony_ci	log << TestLog::Message << "Setup triangle with coordinates:" << TestLog::EndMessage;
990e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(triangle); ++ndx)
991e5c31af7Sopenharmony_ci		log << TestLog::Message
992e5c31af7Sopenharmony_ci				<< "\tx=" << triangle[ndx].x()
993e5c31af7Sopenharmony_ci				<< "\ty=" << triangle[ndx].y()
994e5c31af7Sopenharmony_ci				<< "\tz=" << triangle[ndx].z()
995e5c31af7Sopenharmony_ci				<< "\tw=" << triangle[ndx].w()
996e5c31af7Sopenharmony_ci				<< TestLog::EndMessage;
997e5c31af7Sopenharmony_ci
998e5c31af7Sopenharmony_ci	// render test image
999e5c31af7Sopenharmony_ci	{
1000e5c31af7Sopenharmony_ci		const glw::Functions&		gl			= m_context.getRenderContext().getFunctions();
1001e5c31af7Sopenharmony_ci		const glu::ShaderProgram	program		(m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment));
1002e5c31af7Sopenharmony_ci		const GLint					positionLoc = gl.getAttribLocation(program.getProgram(), "a_position");
1003e5c31af7Sopenharmony_ci		const GLint					colorLoc	= gl.getAttribLocation(program.getProgram(), "a_color");
1004e5c31af7Sopenharmony_ci
1005e5c31af7Sopenharmony_ci		if (!program.isOk())
1006e5c31af7Sopenharmony_ci		{
1007e5c31af7Sopenharmony_ci			log << program;
1008e5c31af7Sopenharmony_ci			TCU_FAIL("Shader compile failed.");
1009e5c31af7Sopenharmony_ci		}
1010e5c31af7Sopenharmony_ci
1011e5c31af7Sopenharmony_ci		gl.clearColor				(0, 0, 0, 1);
1012e5c31af7Sopenharmony_ci		gl.clearDepthf				(1.0f);
1013e5c31af7Sopenharmony_ci		gl.clear					(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1014e5c31af7Sopenharmony_ci		gl.viewport					(0, 0, m_targetSize, m_targetSize);
1015e5c31af7Sopenharmony_ci		gl.useProgram				(program.getProgram());
1016e5c31af7Sopenharmony_ci		gl.enable					(GL_DEPTH_TEST);
1017e5c31af7Sopenharmony_ci		gl.enable					(GL_POLYGON_OFFSET_FILL);
1018e5c31af7Sopenharmony_ci		gl.enableVertexAttribArray	(positionLoc);
1019e5c31af7Sopenharmony_ci
1020e5c31af7Sopenharmony_ci		log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage;
1021e5c31af7Sopenharmony_ci
1022e5c31af7Sopenharmony_ci		{
1023e5c31af7Sopenharmony_ci			gl.vertexAttribPointer		(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangle);
1024e5c31af7Sopenharmony_ci
1025e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw triangle. Color = Red.\tState: DepthFunc = ALWAYS, PolygonOffset(0, 0)." << TestLog::EndMessage;
1026e5c31af7Sopenharmony_ci
1027e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_ALWAYS);
1028e5c31af7Sopenharmony_ci			gl.polygonOffset			(0, 0);
1029e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
1030e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
1031e5c31af7Sopenharmony_ci
1032e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw triangle. Color = Black.\tState: DepthFunc = EQUAL, PolygonOffset(4, 0)." << TestLog::EndMessage;
1033e5c31af7Sopenharmony_ci
1034e5c31af7Sopenharmony_ci			gl.depthFunc				(GL_EQUAL);
1035e5c31af7Sopenharmony_ci			gl.polygonOffset			(4, 0);	// triangle slope == 0
1036e5c31af7Sopenharmony_ci			gl.vertexAttrib4f			(colorLoc, 0.0f, 0.0f, 0.0f, 1.0f);
1037e5c31af7Sopenharmony_ci			gl.drawArrays				(GL_TRIANGLES, 0, 3);
1038e5c31af7Sopenharmony_ci		}
1039e5c31af7Sopenharmony_ci
1040e5c31af7Sopenharmony_ci		gl.disableVertexAttribArray	(positionLoc);
1041e5c31af7Sopenharmony_ci		gl.useProgram				(0);
1042e5c31af7Sopenharmony_ci		gl.finish					();
1043e5c31af7Sopenharmony_ci
1044e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess());
1045e5c31af7Sopenharmony_ci	}
1046e5c31af7Sopenharmony_ci
1047e5c31af7Sopenharmony_ci	// render reference image
1048e5c31af7Sopenharmony_ci	log << TestLog::Message << "Expecting black triangle." << TestLog::EndMessage;
1049e5c31af7Sopenharmony_ci	tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1050e5c31af7Sopenharmony_ci
1051e5c31af7Sopenharmony_ci	// compare
1052e5c31af7Sopenharmony_ci	verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess());
1053e5c31af7Sopenharmony_ci}
1054e5c31af7Sopenharmony_ci
1055e5c31af7Sopenharmony_ci// OneSlopeTestCase
1056e5c31af7Sopenharmony_ci
1057e5c31af7Sopenharmony_ciclass OneSlopeTestCase : public PolygonOffsetTestCase
1058e5c31af7Sopenharmony_ci{
1059e5c31af7Sopenharmony_cipublic:
1060e5c31af7Sopenharmony_ci			OneSlopeTestCase	(Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName);
1061e5c31af7Sopenharmony_ci
1062e5c31af7Sopenharmony_ci	void	testPolygonOffset	(void);
1063e5c31af7Sopenharmony_ci};
1064e5c31af7Sopenharmony_ci
1065e5c31af7Sopenharmony_ciOneSlopeTestCase::OneSlopeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName)
1066e5c31af7Sopenharmony_ci	: PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200)
1067e5c31af7Sopenharmony_ci{
1068e5c31af7Sopenharmony_ci}
1069e5c31af7Sopenharmony_ci
1070e5c31af7Sopenharmony_civoid OneSlopeTestCase::testPolygonOffset (void)
1071e5c31af7Sopenharmony_ci{
1072e5c31af7Sopenharmony_ci	using tcu::TestLog;
1073e5c31af7Sopenharmony_ci
1074e5c31af7Sopenharmony_ci	/*
1075e5c31af7Sopenharmony_ci		* setup vertices subject to following properties
1076e5c31af7Sopenharmony_ci		*   dz_w / dx_w == 1
1077e5c31af7Sopenharmony_ci		*   dz_w / dy_w == 0
1078e5c31af7Sopenharmony_ci		* or
1079e5c31af7Sopenharmony_ci		*   dz_w / dx_w == 0
1080e5c31af7Sopenharmony_ci		*   dz_w / dy_w == 1
1081e5c31af7Sopenharmony_ci		* ==> m == 1
1082e5c31af7Sopenharmony_ci		*/
1083e5c31af7Sopenharmony_ci	const float cornerDepth = float(m_targetSize);
1084e5c31af7Sopenharmony_ci	const tcu::Vec4 triangles[2][3] =
1085e5c31af7Sopenharmony_ci	{
1086e5c31af7Sopenharmony_ci		{
1087e5c31af7Sopenharmony_ci			tcu::Vec4(-1, -1, -cornerDepth, 1),
1088e5c31af7Sopenharmony_ci			tcu::Vec4(-1,  1, -cornerDepth, 1),
1089e5c31af7Sopenharmony_ci			tcu::Vec4( 1, -1,  cornerDepth, 1),
1090e5c31af7Sopenharmony_ci		},
1091e5c31af7Sopenharmony_ci		{
1092e5c31af7Sopenharmony_ci			tcu::Vec4(-1,  1,  cornerDepth, 1),
1093e5c31af7Sopenharmony_ci			tcu::Vec4( 1,  1,  cornerDepth, 1),
1094e5c31af7Sopenharmony_ci			tcu::Vec4( 1, -1, -cornerDepth, 1),
1095e5c31af7Sopenharmony_ci		},
1096e5c31af7Sopenharmony_ci	};
1097e5c31af7Sopenharmony_ci
1098e5c31af7Sopenharmony_ci	tcu::TestLog&		log				= m_testCtx.getLog();
1099e5c31af7Sopenharmony_ci	tcu::Surface		testImage		(m_targetSize, m_targetSize);
1100e5c31af7Sopenharmony_ci	tcu::Surface		referenceImage	(m_targetSize, m_targetSize);
1101e5c31af7Sopenharmony_ci
1102e5c31af7Sopenharmony_ci	// log triangle info
1103e5c31af7Sopenharmony_ci	log << TestLog::Message << "Setup triangle0 coordinates: (slope in window coordinates = 1.0)" << TestLog::EndMessage;
1104e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(triangles[0]); ++ndx)
1105e5c31af7Sopenharmony_ci		log << TestLog::Message
1106e5c31af7Sopenharmony_ci				<< "\tx=" << triangles[0][ndx].x()
1107e5c31af7Sopenharmony_ci				<< "\ty=" << triangles[0][ndx].y()
1108e5c31af7Sopenharmony_ci				<< "\tz=" << triangles[0][ndx].z()
1109e5c31af7Sopenharmony_ci				<< "\tw=" << triangles[0][ndx].w()
1110e5c31af7Sopenharmony_ci				<< TestLog::EndMessage;
1111e5c31af7Sopenharmony_ci	log << TestLog::Message << "Setup triangle1 coordinates: (slope in window coordinates = 1.0)" << TestLog::EndMessage;
1112e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(triangles[1]); ++ndx)
1113e5c31af7Sopenharmony_ci		log << TestLog::Message
1114e5c31af7Sopenharmony_ci				<< "\tx=" << triangles[1][ndx].x()
1115e5c31af7Sopenharmony_ci				<< "\ty=" << triangles[1][ndx].y()
1116e5c31af7Sopenharmony_ci				<< "\tz=" << triangles[1][ndx].z()
1117e5c31af7Sopenharmony_ci				<< "\tw=" << triangles[1][ndx].w()
1118e5c31af7Sopenharmony_ci				<< TestLog::EndMessage;
1119e5c31af7Sopenharmony_ci
1120e5c31af7Sopenharmony_ci	// render test image
1121e5c31af7Sopenharmony_ci	{
1122e5c31af7Sopenharmony_ci		const glw::Functions&		gl			= m_context.getRenderContext().getFunctions();
1123e5c31af7Sopenharmony_ci		const glu::ShaderProgram	program		(m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment));
1124e5c31af7Sopenharmony_ci		const GLint					positionLoc = gl.getAttribLocation(program.getProgram(), "a_position");
1125e5c31af7Sopenharmony_ci		const GLint					colorLoc	= gl.getAttribLocation(program.getProgram(), "a_color");
1126e5c31af7Sopenharmony_ci
1127e5c31af7Sopenharmony_ci		if (!program.isOk())
1128e5c31af7Sopenharmony_ci		{
1129e5c31af7Sopenharmony_ci			log << program;
1130e5c31af7Sopenharmony_ci			TCU_FAIL("Shader compile failed.");
1131e5c31af7Sopenharmony_ci		}
1132e5c31af7Sopenharmony_ci
1133e5c31af7Sopenharmony_ci		gl.clearColor				(0, 0, 0, 1);
1134e5c31af7Sopenharmony_ci		gl.clear					(GL_COLOR_BUFFER_BIT);
1135e5c31af7Sopenharmony_ci		gl.viewport					(0, 0, m_targetSize, m_targetSize);
1136e5c31af7Sopenharmony_ci		gl.useProgram				(program.getProgram());
1137e5c31af7Sopenharmony_ci		gl.enable					(GL_DEPTH_TEST);
1138e5c31af7Sopenharmony_ci		gl.enable					(GL_POLYGON_OFFSET_FILL);
1139e5c31af7Sopenharmony_ci		gl.enableVertexAttribArray	(positionLoc);
1140e5c31af7Sopenharmony_ci
1141e5c31af7Sopenharmony_ci		log << TestLog::Message << "Framebuffer cleared, clear color = Black." << TestLog::EndMessage;
1142e5c31af7Sopenharmony_ci		log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage;
1143e5c31af7Sopenharmony_ci
1144e5c31af7Sopenharmony_ci		// top left (positive offset)
1145e5c31af7Sopenharmony_ci		{
1146e5c31af7Sopenharmony_ci			log << TestLog::Message << "Clear depth to 1.0." << TestLog::EndMessage;
1147e5c31af7Sopenharmony_ci
1148e5c31af7Sopenharmony_ci			gl.clearDepthf			(1.0f); // far
1149e5c31af7Sopenharmony_ci			gl.clear				(GL_DEPTH_BUFFER_BIT);
1150e5c31af7Sopenharmony_ci
1151e5c31af7Sopenharmony_ci			gl.vertexAttribPointer	(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangles[0]);
1152e5c31af7Sopenharmony_ci
1153e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw triangle0. Color = Red.\tState: DepthFunc = NOTEQUAL, PolygonOffset(10, 0). (Result depth should clamp to 1.0)." << TestLog::EndMessage;
1154e5c31af7Sopenharmony_ci
1155e5c31af7Sopenharmony_ci			gl.polygonOffset		(10, 0);		// clamps any depth on the triangle to 1
1156e5c31af7Sopenharmony_ci			gl.depthFunc			(GL_NOTEQUAL);
1157e5c31af7Sopenharmony_ci			gl.vertexAttrib4f		(colorLoc, 1.0f, 0.0f, 0.0f, 1.0f);
1158e5c31af7Sopenharmony_ci			gl.drawArrays			(GL_TRIANGLES, 0, 3);
1159e5c31af7Sopenharmony_ci		}
1160e5c31af7Sopenharmony_ci		// bottom right (negative offset)
1161e5c31af7Sopenharmony_ci		{
1162e5c31af7Sopenharmony_ci			log << TestLog::Message << "Clear depth to 0.0." << TestLog::EndMessage;
1163e5c31af7Sopenharmony_ci
1164e5c31af7Sopenharmony_ci			gl.clearDepthf			(0.0f); // far
1165e5c31af7Sopenharmony_ci			gl.clear				(GL_DEPTH_BUFFER_BIT);
1166e5c31af7Sopenharmony_ci
1167e5c31af7Sopenharmony_ci			gl.vertexAttribPointer	(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangles[1]);
1168e5c31af7Sopenharmony_ci
1169e5c31af7Sopenharmony_ci			log << TestLog::Message << "Draw triangle1. Color = Green.\tState: DepthFunc = NOTEQUAL, PolygonOffset(-10, 0). (Result depth should clamp to 0.0)." << TestLog::EndMessage;
1170e5c31af7Sopenharmony_ci
1171e5c31af7Sopenharmony_ci			gl.polygonOffset		(-10, 0); // clamps depth to 0
1172e5c31af7Sopenharmony_ci			gl.depthFunc			(GL_NOTEQUAL);
1173e5c31af7Sopenharmony_ci			gl.vertexAttrib4f		(colorLoc, 0.0f, 1.0f, 0.0f, 1.0f);
1174e5c31af7Sopenharmony_ci			gl.drawArrays			(GL_TRIANGLES, 0, 3);
1175e5c31af7Sopenharmony_ci		}
1176e5c31af7Sopenharmony_ci
1177e5c31af7Sopenharmony_ci		gl.disableVertexAttribArray	(positionLoc);
1178e5c31af7Sopenharmony_ci		gl.useProgram				(0);
1179e5c31af7Sopenharmony_ci		gl.finish					();
1180e5c31af7Sopenharmony_ci
1181e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess());
1182e5c31af7Sopenharmony_ci	}
1183e5c31af7Sopenharmony_ci
1184e5c31af7Sopenharmony_ci	// render reference image
1185e5c31af7Sopenharmony_ci	log << TestLog::Message << "Expecting black framebuffer." << TestLog::EndMessage;
1186e5c31af7Sopenharmony_ci	tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
1187e5c31af7Sopenharmony_ci
1188e5c31af7Sopenharmony_ci	// compare
1189e5c31af7Sopenharmony_ci	verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess());
1190e5c31af7Sopenharmony_ci}
1191e5c31af7Sopenharmony_ci
1192e5c31af7Sopenharmony_ci} // anonymous
1193e5c31af7Sopenharmony_ci
1194e5c31af7Sopenharmony_ciPolygonOffsetTests::PolygonOffsetTests (Context& context)
1195e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "polygon_offset", "Polygon offset tests")
1196e5c31af7Sopenharmony_ci{
1197e5c31af7Sopenharmony_ci}
1198e5c31af7Sopenharmony_ci
1199e5c31af7Sopenharmony_ciPolygonOffsetTests::~PolygonOffsetTests (void)
1200e5c31af7Sopenharmony_ci{
1201e5c31af7Sopenharmony_ci}
1202e5c31af7Sopenharmony_ci
1203e5c31af7Sopenharmony_civoid PolygonOffsetTests::init (void)
1204e5c31af7Sopenharmony_ci{
1205e5c31af7Sopenharmony_ci	const struct DepthBufferFormat
1206e5c31af7Sopenharmony_ci	{
1207e5c31af7Sopenharmony_ci		enum BufferType
1208e5c31af7Sopenharmony_ci		{
1209e5c31af7Sopenharmony_ci			TYPE_FIXED_POINT,
1210e5c31af7Sopenharmony_ci			TYPE_FLOATING_POINT,
1211e5c31af7Sopenharmony_ci			TYPE_UNKNOWN
1212e5c31af7Sopenharmony_ci		};
1213e5c31af7Sopenharmony_ci
1214e5c31af7Sopenharmony_ci		GLenum		internalFormat;
1215e5c31af7Sopenharmony_ci		int			bits;
1216e5c31af7Sopenharmony_ci		BufferType	floatingPoint;
1217e5c31af7Sopenharmony_ci		const char* name;
1218e5c31af7Sopenharmony_ci	} depthFormats[]=
1219e5c31af7Sopenharmony_ci	{
1220e5c31af7Sopenharmony_ci		{ 0,						0,		DepthBufferFormat::TYPE_UNKNOWN,		"default" },
1221e5c31af7Sopenharmony_ci		{ GL_DEPTH_COMPONENT16,		16,		DepthBufferFormat::TYPE_FIXED_POINT,	"fixed16" },
1222e5c31af7Sopenharmony_ci		{ GL_DEPTH_COMPONENT24,		24,		DepthBufferFormat::TYPE_FIXED_POINT,	"fixed24" },
1223e5c31af7Sopenharmony_ci		{ GL_DEPTH_COMPONENT32F,	32,		DepthBufferFormat::TYPE_FLOATING_POINT,	"float32" },
1224e5c31af7Sopenharmony_ci	};
1225e5c31af7Sopenharmony_ci
1226e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthFormats); ++ndx)
1227e5c31af7Sopenharmony_ci	{
1228e5c31af7Sopenharmony_ci		const DepthBufferFormat& format = depthFormats[ndx];
1229e5c31af7Sopenharmony_ci
1230e5c31af7Sopenharmony_ci		// enable works?
1231e5c31af7Sopenharmony_ci		addChild(new UsageTestCase(m_context, (std::string(format.name) + "_enable").c_str(), "test enable GL_POLYGON_OFFSET_FILL", format.internalFormat, format.name));
1232e5c31af7Sopenharmony_ci
1233e5c31af7Sopenharmony_ci		// Really moves the polygons ?
1234e5c31af7Sopenharmony_ci		addChild(new UsageDisplacementTestCase(m_context, (std::string(format.name) + "_displacement_with_units").c_str(), "test polygon offset", format.internalFormat, format.name));
1235e5c31af7Sopenharmony_ci
1236e5c31af7Sopenharmony_ci		// Really moves the polygons to right direction ?
1237e5c31af7Sopenharmony_ci		addChild(new UsagePositiveNegativeTestCase(m_context, (std::string(format.name) + "_render_with_units").c_str(), "test polygon offset", format.internalFormat, format.name));
1238e5c31af7Sopenharmony_ci
1239e5c31af7Sopenharmony_ci		// Is total result clamped to [0,1] like promised?
1240e5c31af7Sopenharmony_ci		addChild(new ResultClampingTestCase(m_context, (std::string(format.name) + "_result_depth_clamp").c_str(), "test polygon offset clamping", format.internalFormat, format.name));
1241e5c31af7Sopenharmony_ci
1242e5c31af7Sopenharmony_ci		// Slope really moves the polygon?
1243e5c31af7Sopenharmony_ci		addChild(new UsageSlopeTestCase(m_context, (std::string(format.name) + "_render_with_factor").c_str(), "test polygon offset factor", format.internalFormat, format.name));
1244e5c31af7Sopenharmony_ci
1245e5c31af7Sopenharmony_ci		// Factor with zero slope
1246e5c31af7Sopenharmony_ci		addChild(new ZeroSlopeTestCase(m_context, (std::string(format.name) + "_factor_0_slope").c_str(), "test polygon offset factor", format.internalFormat, format.name));
1247e5c31af7Sopenharmony_ci
1248e5c31af7Sopenharmony_ci		// Factor with 1.0 slope
1249e5c31af7Sopenharmony_ci		addChild(new OneSlopeTestCase(m_context, (std::string(format.name) + "_factor_1_slope").c_str(), "test polygon offset factor", format.internalFormat, format.name));
1250e5c31af7Sopenharmony_ci	}
1251e5c31af7Sopenharmony_ci}
1252e5c31af7Sopenharmony_ci
1253e5c31af7Sopenharmony_ci} // Functional
1254e5c31af7Sopenharmony_ci} // gles3
1255e5c31af7Sopenharmony_ci} // deqp
1256