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 Read pixels tests
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "es2fReadPixelsTests.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "tcuTexture.hpp"
27e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
28e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp"
29e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
30e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ci#include "deRandom.hpp"
33e5c31af7Sopenharmony_ci#include "deMath.h"
34e5c31af7Sopenharmony_ci#include "deString.h"
35e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ci#include "gluDefs.hpp"
38e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
39e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp"
40e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp"
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ci#include "glw.h"
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_ci#include <cstring>
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_cinamespace deqp
47e5c31af7Sopenharmony_ci{
48e5c31af7Sopenharmony_cinamespace gles2
49e5c31af7Sopenharmony_ci{
50e5c31af7Sopenharmony_cinamespace Functional
51e5c31af7Sopenharmony_ci{
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_ciclass ReadPixelsTest : public TestCase
54e5c31af7Sopenharmony_ci{
55e5c31af7Sopenharmony_cipublic:
56e5c31af7Sopenharmony_ci					ReadPixelsTest	(Context& context, const char* name, const char* description, bool chooseFormat, int alignment);
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ci	IterateResult	iterate			(void);
59e5c31af7Sopenharmony_ci	void			render			(tcu::Texture2D& reference);
60e5c31af7Sopenharmony_ci
61e5c31af7Sopenharmony_ciprivate:
62e5c31af7Sopenharmony_ci	bool			m_chooseFormat;
63e5c31af7Sopenharmony_ci	int				m_alignment;
64e5c31af7Sopenharmony_ci	int				m_seed;
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_ci	void			getFormatInfo	(tcu::TextureFormat& format, GLint& glFormat, GLint& glType, int& pixelSize);
67e5c31af7Sopenharmony_ci};
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_ciReadPixelsTest::ReadPixelsTest	(Context& context, const char* name, const char* description, bool chooseFormat, int alignment)
70e5c31af7Sopenharmony_ci	: TestCase			(context, name, description)
71e5c31af7Sopenharmony_ci	, m_chooseFormat	(chooseFormat)
72e5c31af7Sopenharmony_ci	, m_alignment		(alignment)
73e5c31af7Sopenharmony_ci	, m_seed			(deStringHash(name))
74e5c31af7Sopenharmony_ci{
75e5c31af7Sopenharmony_ci}
76e5c31af7Sopenharmony_ci
77e5c31af7Sopenharmony_civoid ReadPixelsTest::render (tcu::Texture2D& reference)
78e5c31af7Sopenharmony_ci{
79e5c31af7Sopenharmony_ci	// Create program
80e5c31af7Sopenharmony_ci	const char* vertexSource =
81e5c31af7Sopenharmony_ci	"attribute mediump vec2 a_coord;\n"
82e5c31af7Sopenharmony_ci	"void main (void)\n"
83e5c31af7Sopenharmony_ci	"{\n"
84e5c31af7Sopenharmony_ci	"\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
85e5c31af7Sopenharmony_ci	"}\n";
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_ci	const char* fragmentSource =
88e5c31af7Sopenharmony_ci	"void main (void)\n"
89e5c31af7Sopenharmony_ci	"{\n"
90e5c31af7Sopenharmony_ci	"\tgl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
91e5c31af7Sopenharmony_ci	"}\n";
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_ci	glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexSource, fragmentSource));
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_ci	m_testCtx.getLog() << program;
96e5c31af7Sopenharmony_ci	TCU_CHECK(program.isOk());
97e5c31af7Sopenharmony_ci	GLU_CHECK_CALL(glUseProgram(program.getProgram()));
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci	// Render
100e5c31af7Sopenharmony_ci	{
101e5c31af7Sopenharmony_ci		const float coords[] =
102e5c31af7Sopenharmony_ci		{
103e5c31af7Sopenharmony_ci			-0.5f, -0.5f,
104e5c31af7Sopenharmony_ci			 0.5f, -0.5f,
105e5c31af7Sopenharmony_ci			 0.5f,  0.5f,
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci			 0.5f,  0.5f,
108e5c31af7Sopenharmony_ci			-0.5f,  0.5f,
109e5c31af7Sopenharmony_ci			-0.5f, -0.5f
110e5c31af7Sopenharmony_ci		};
111e5c31af7Sopenharmony_ci		GLuint coordLoc;
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci		coordLoc = glGetAttribLocation(program.getProgram(), "a_coord");
114e5c31af7Sopenharmony_ci		GLU_CHECK_MSG("glGetAttribLocation()");
115e5c31af7Sopenharmony_ci
116e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glEnableVertexAttribArray(coordLoc));
117e5c31af7Sopenharmony_ci
118e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glVertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, coords));
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, 6));
121e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glDisableVertexAttribArray(coordLoc));
122e5c31af7Sopenharmony_ci	}
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci	// Render reference
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_ci	const int coordX1 = (int)((-0.5f * (float)reference.getWidth()	/ 2.0f) + (float)reference.getWidth() / 2.0f);
127e5c31af7Sopenharmony_ci	const int coordY1 = (int)((-0.5f * (float)reference.getHeight()	/ 2.0f) + (float)reference.getHeight() / 2.0f);
128e5c31af7Sopenharmony_ci	const int coordX2 = (int)(( 0.5f * (float)reference.getWidth()	/ 2.0f) + (float)reference.getWidth() / 2.0f);
129e5c31af7Sopenharmony_ci	const int coordY2 = (int)(( 0.5f * (float)reference.getHeight()	/ 2.0f) + (float)reference.getHeight() / 2.0f);
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci	for (int x = 0; x < reference.getWidth(); x++)
132e5c31af7Sopenharmony_ci	{
133e5c31af7Sopenharmony_ci		if (x < coordX1 || x > coordX2)
134e5c31af7Sopenharmony_ci			continue;
135e5c31af7Sopenharmony_ci
136e5c31af7Sopenharmony_ci		for (int y = 0; y < reference.getHeight(); y++)
137e5c31af7Sopenharmony_ci		{
138e5c31af7Sopenharmony_ci			if (y >= coordY1 && y <= coordY2)
139e5c31af7Sopenharmony_ci				reference.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), x, y);
140e5c31af7Sopenharmony_ci		}
141e5c31af7Sopenharmony_ci	}
142e5c31af7Sopenharmony_ci}
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_civoid ReadPixelsTest::getFormatInfo (tcu::TextureFormat& format, GLint& glFormat, GLint& glType, int& pixelSize)
145e5c31af7Sopenharmony_ci{
146e5c31af7Sopenharmony_ci	if (m_chooseFormat)
147e5c31af7Sopenharmony_ci	{
148e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glFormat));
149e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glType));
150e5c31af7Sopenharmony_ci
151e5c31af7Sopenharmony_ci		if (glFormat != GL_RGBA && glFormat != GL_BGRA && glFormat != GL_RGB)
152e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, ("Unsupported IMPLEMENTATION_COLOR_READ_FORMAT: " + de::toString(glu::getTextureFormatStr(glFormat))).c_str());
153e5c31af7Sopenharmony_ci		if (glu::getTypeName(glType) == DE_NULL)
154e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, ("Unsupported GL_IMPLEMENTATION_COLOR_READ_TYPE: " + de::toString(tcu::Format::Hex<4>(glType))).c_str());
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci		format = glu::mapGLTransferFormat(glFormat, glType);
157e5c31af7Sopenharmony_ci		pixelSize = format.getPixelSize();
158e5c31af7Sopenharmony_ci	}
159e5c31af7Sopenharmony_ci	else
160e5c31af7Sopenharmony_ci	{
161e5c31af7Sopenharmony_ci		format		= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
162e5c31af7Sopenharmony_ci		pixelSize	= 1 * 4;
163e5c31af7Sopenharmony_ci		glFormat	= GL_RGBA;
164e5c31af7Sopenharmony_ci		glType		= GL_UNSIGNED_BYTE;
165e5c31af7Sopenharmony_ci	}
166e5c31af7Sopenharmony_ci}
167e5c31af7Sopenharmony_ci
168e5c31af7Sopenharmony_ciTestCase::IterateResult ReadPixelsTest::iterate (void)
169e5c31af7Sopenharmony_ci{
170e5c31af7Sopenharmony_ci	// Create reference
171e5c31af7Sopenharmony_ci	const int					width	= 13;
172e5c31af7Sopenharmony_ci	const int					height	= 13;
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_ci	de::Random					rnd(m_seed);
175e5c31af7Sopenharmony_ci
176e5c31af7Sopenharmony_ci	tcu::TextureFormat			format(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
177e5c31af7Sopenharmony_ci	int							pixelSize;
178e5c31af7Sopenharmony_ci	GLint						glFormat;
179e5c31af7Sopenharmony_ci	GLint						glType;
180e5c31af7Sopenharmony_ci
181e5c31af7Sopenharmony_ci	getFormatInfo(format, glFormat, glType, pixelSize);
182e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Format: " << glu::getTextureFormatStr(glFormat) << ", Type: " << glu::getTypeStr(glType) << tcu::TestLog::EndMessage;
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ci	tcu::Texture2D reference(format, width, height, glu::isES2Context(m_context.getRenderContext().getType()));
185e5c31af7Sopenharmony_ci	reference.allocLevel(0);
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_ci	GLU_CHECK_CALL(glViewport(0, 0, width, height));
188e5c31af7Sopenharmony_ci
189e5c31af7Sopenharmony_ci	// Clear color
190e5c31af7Sopenharmony_ci	{
191e5c31af7Sopenharmony_ci		const float red		= rnd.getFloat();
192e5c31af7Sopenharmony_ci		const float green	= rnd.getFloat();
193e5c31af7Sopenharmony_ci		const float blue	= rnd.getFloat();
194e5c31af7Sopenharmony_ci		const float alpha	= 1.0f;
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Clear color: (" << red << ", " << green << ", " << blue << ", " << alpha << ")" << tcu::TestLog::EndMessage;
197e5c31af7Sopenharmony_ci
198e5c31af7Sopenharmony_ci		// Clear target
199e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glClearColor(red, green, blue, alpha));
200e5c31af7Sopenharmony_ci		GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_ci		tcu::clear(reference.getLevel(0), tcu::Vec4(red, green, blue, alpha));
203e5c31af7Sopenharmony_ci	}
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci	render(reference);
206e5c31af7Sopenharmony_ci
207e5c31af7Sopenharmony_ci	std::vector<deUint8> pixelData;
208e5c31af7Sopenharmony_ci	const int rowPitch = m_alignment * deCeilFloatToInt32(float(pixelSize * width) / (float)m_alignment);
209e5c31af7Sopenharmony_ci
210e5c31af7Sopenharmony_ci	pixelData.resize(rowPitch * height, 0);
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci	GLU_CHECK_CALL(glPixelStorei(GL_PACK_ALIGNMENT, m_alignment));
213e5c31af7Sopenharmony_ci	GLU_CHECK_CALL(glReadPixels(0, 0, width, height, glFormat, glType, &(pixelData[0])));
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_ci	if (m_context.getRenderTarget().getNumSamples() > 1)
216e5c31af7Sopenharmony_ci	{
217e5c31af7Sopenharmony_ci		const tcu::IVec4	formatBitDepths	= tcu::getTextureFormatBitDepth(format);
218e5c31af7Sopenharmony_ci		const deUint8		redThreshold	= (deUint8)deCeilFloatToInt32(256.0f * (2.0f / (float)(1 << deMin32(m_context.getRenderTarget().getPixelFormat().redBits,	formatBitDepths.x()))));
219e5c31af7Sopenharmony_ci		const deUint8		greenThreshold	= (deUint8)deCeilFloatToInt32(256.0f * (2.0f / (float)(1 << deMin32(m_context.getRenderTarget().getPixelFormat().greenBits,	formatBitDepths.y()))));
220e5c31af7Sopenharmony_ci		const deUint8		blueThreshold	= (deUint8)deCeilFloatToInt32(256.0f * (2.0f / (float)(1 << deMin32(m_context.getRenderTarget().getPixelFormat().blueBits,	formatBitDepths.z()))));
221e5c31af7Sopenharmony_ci		const deUint8		alphaThreshold	= (deUint8)deCeilFloatToInt32(256.0f * (2.0f / (float)(1 << deMin32(m_context.getRenderTarget().getPixelFormat().alphaBits,	formatBitDepths.w()))));
222e5c31af7Sopenharmony_ci
223e5c31af7Sopenharmony_ci		// bilinearCompare only accepts RGBA, UINT8
224e5c31af7Sopenharmony_ci		tcu::Texture2D		referenceRGBA8	(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height, glu::isES2Context(m_context.getRenderContext().getType()));
225e5c31af7Sopenharmony_ci		tcu::Texture2D		resultRGBA8		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width, height, glu::isES2Context(m_context.getRenderContext().getType()));
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_ci		referenceRGBA8.allocLevel(0);
228e5c31af7Sopenharmony_ci		resultRGBA8.allocLevel(0);
229e5c31af7Sopenharmony_ci
230e5c31af7Sopenharmony_ci		tcu::copy(referenceRGBA8.getLevel(0), reference.getLevel(0));
231e5c31af7Sopenharmony_ci		tcu::copy(resultRGBA8.getLevel(0), tcu::PixelBufferAccess(format, width, height, 1, rowPitch, 0, &(pixelData[0])));
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci		if (tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Result", referenceRGBA8.getLevel(0), resultRGBA8.getLevel(0), tcu::RGBA(redThreshold, greenThreshold, blueThreshold, alphaThreshold), tcu::COMPARE_LOG_RESULT))
234e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
235e5c31af7Sopenharmony_ci		else
236e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
237e5c31af7Sopenharmony_ci	}
238e5c31af7Sopenharmony_ci	else
239e5c31af7Sopenharmony_ci	{
240e5c31af7Sopenharmony_ci		const tcu::IVec4	formatBitDepths	= tcu::getTextureFormatBitDepth(format);
241e5c31af7Sopenharmony_ci		const float			redThreshold	= 2.0f / (float)(1 << deMin32(m_context.getRenderTarget().getPixelFormat().redBits,		formatBitDepths.x()));
242e5c31af7Sopenharmony_ci		const float			greenThreshold	= 2.0f / (float)(1 << deMin32(m_context.getRenderTarget().getPixelFormat().greenBits,	formatBitDepths.y()));
243e5c31af7Sopenharmony_ci		const float			blueThreshold	= 2.0f / (float)(1 << deMin32(m_context.getRenderTarget().getPixelFormat().blueBits,	formatBitDepths.z()));
244e5c31af7Sopenharmony_ci		const float			alphaThreshold	= 2.0f / (float)(1 << deMin32(m_context.getRenderTarget().getPixelFormat().alphaBits,	formatBitDepths.w()));
245e5c31af7Sopenharmony_ci
246e5c31af7Sopenharmony_ci		// Compare
247e5c31af7Sopenharmony_ci		if (tcu::floatThresholdCompare(m_testCtx.getLog(), "Result", "Result", reference.getLevel(0), tcu::PixelBufferAccess(format, width, height, 1, rowPitch, 0, &(pixelData[0])), tcu::Vec4(redThreshold, greenThreshold, blueThreshold, alphaThreshold), tcu::COMPARE_LOG_RESULT))
248e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
249e5c31af7Sopenharmony_ci		else
250e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
251e5c31af7Sopenharmony_ci	}
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci	return STOP;
254e5c31af7Sopenharmony_ci}
255e5c31af7Sopenharmony_ci
256e5c31af7Sopenharmony_ciReadPixelsTests::ReadPixelsTests (Context& context)
257e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "read_pixels", "ReadPixel tests")
258e5c31af7Sopenharmony_ci{
259e5c31af7Sopenharmony_ci}
260e5c31af7Sopenharmony_ci
261e5c31af7Sopenharmony_civoid ReadPixelsTests::init (void)
262e5c31af7Sopenharmony_ci{
263e5c31af7Sopenharmony_ci	addChild(new ReadPixelsTest(m_context, "rgba_ubyte_align_1", "", false, 1));
264e5c31af7Sopenharmony_ci	addChild(new ReadPixelsTest(m_context, "rgba_ubyte_align_2", "", false, 2));
265e5c31af7Sopenharmony_ci	addChild(new ReadPixelsTest(m_context, "rgba_ubyte_align_4", "", false, 4));
266e5c31af7Sopenharmony_ci	addChild(new ReadPixelsTest(m_context, "rgba_ubyte_align_8", "", false, 8));
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci	addChild(new ReadPixelsTest(m_context, "choose_align_1", "", true, 1));
269e5c31af7Sopenharmony_ci	addChild(new ReadPixelsTest(m_context, "choose_align_2", "", true, 2));
270e5c31af7Sopenharmony_ci	addChild(new ReadPixelsTest(m_context, "choose_align_4", "", true, 4));
271e5c31af7Sopenharmony_ci	addChild(new ReadPixelsTest(m_context, "choose_align_8", "", true, 8));
272e5c31af7Sopenharmony_ci}
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_ci} // Functional
275e5c31af7Sopenharmony_ci} // gles2
276e5c31af7Sopenharmony_ci} // deqp
277