1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief FBO colorbuffer tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fFboColorbufferTests.hpp"
25 #include "es31fFboTestCase.hpp"
26 #include "es31fFboTestUtil.hpp"
27 
28 #include "gluTextureUtil.hpp"
29 #include "gluContextInfo.hpp"
30 
31 #include "tcuCommandLine.hpp"
32 #include "tcuImageCompare.hpp"
33 #include "tcuRGBA.hpp"
34 #include "tcuTestLog.hpp"
35 #include "tcuTextureUtil.hpp"
36 
37 #include "sglrContextUtil.hpp"
38 
39 #include "deRandom.hpp"
40 #include "deString.h"
41 
42 #include "glwEnums.hpp"
43 
44 namespace deqp
45 {
46 namespace gles31
47 {
48 namespace Functional
49 {
50 
51 using std::string;
52 using tcu::Vec2;
53 using tcu::Vec3;
54 using tcu::Vec4;
55 using tcu::IVec2;
56 using tcu::IVec3;
57 using tcu::IVec4;
58 using tcu::UVec4;
59 using tcu::TestLog;
60 using namespace FboTestUtil;
61 
62 const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12);
63 
generateRandomColor(de::Random & random)64 static tcu::Vec4 generateRandomColor (de::Random& random)
65 {
66 	tcu::Vec4 retVal;
67 
68 	retVal[0] = random.getFloat();
69 	retVal[1] = random.getFloat();
70 	retVal[2] = random.getFloat();
71 	retVal[3] = 1.0f;
72 
73 	return retVal;
74 }
75 
getCubeFaceFromNdx(int ndx)76 static tcu::CubeFace getCubeFaceFromNdx (int ndx)
77 {
78 	switch (ndx)
79 	{
80 		case 0:	return tcu::CUBEFACE_POSITIVE_X;
81 		case 1:	return tcu::CUBEFACE_NEGATIVE_X;
82 		case 2:	return tcu::CUBEFACE_POSITIVE_Y;
83 		case 3:	return tcu::CUBEFACE_NEGATIVE_Y;
84 		case 4:	return tcu::CUBEFACE_POSITIVE_Z;
85 		case 5:	return tcu::CUBEFACE_NEGATIVE_Z;
86 		default:
87 			DE_ASSERT(false);
88 			return tcu::CUBEFACE_LAST;
89 	}
90 }
91 
92 class FboColorbufferCase : public FboTestCase
93 {
94 public:
FboColorbufferCase(Context & context,const char * name,const char * desc,const deUint32 format)95 	FboColorbufferCase (Context& context, const char* name, const char* desc, const deUint32 format)
96 		: FboTestCase	(context, name, desc)
97 		, m_format		(format)
98 	{
99 	}
100 
compare(const tcu::Surface & reference,const tcu::Surface & result)101 	bool compare (const tcu::Surface& reference, const tcu::Surface& result)
102 	{
103 		const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), MIN_THRESHOLD));
104 
105 		m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;
106 
107 		return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
108 	}
109 
110 protected:
111 	const deUint32	m_format;
112 };
113 
114 class FboColorTexCubeArrayCase : public FboColorbufferCase
115 {
116 public:
FboColorTexCubeArrayCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec3 & texSize)117 	FboColorTexCubeArrayCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
118 		: FboColorbufferCase	(context, name, description, texFmt)
119 		, m_texSize				(texSize)
120 	{
121 		DE_ASSERT(texSize.z() % 6 == 0);
122 	}
123 
124 protected:
preCheck(void)125 	void preCheck (void)
126 	{
127 		if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array"))
128 			throw tcu::NotSupportedError("GL_EXT_texture_cube_map_array not supported");
129 
130 		checkFormatSupport(m_format);
131 	}
132 
render(tcu::Surface & dst)133 	void render (tcu::Surface& dst)
134 	{
135 		TestLog&				log					= m_testCtx.getLog();
136 		de::Random				rnd					(deStringHash(getName()) ^ 0xed607a89 ^ m_testCtx.getCommandLine().getBaseSeed());
137 		tcu::TextureFormat		texFmt				= glu::mapGLInternalFormat(m_format);
138 		tcu::TextureFormatInfo	fmtInfo				= tcu::getTextureFormatInfo(texFmt);
139 
140 		Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
141 		TextureCubeArrayShader	arrayTexShader		(glu::getSamplerCubeArrayType(texFmt), glu::TYPE_FLOAT_VEC4);
142 
143 		deUint32				texToFboShaderID	= getCurrentContext()->createProgram(&texToFboShader);
144 		deUint32				arrayTexShaderID	= getCurrentContext()->createProgram(&arrayTexShader);
145 
146 		// Setup textures
147 		texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
148 		arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
149 
150 		// Framebuffers.
151 		std::vector<deUint32>	fbos;
152 		deUint32				tex;
153 
154 		{
155 			glu::TransferFormat	transferFmt		= glu::getTransferFormat(texFmt);
156 			bool				isFilterable	= glu::isGLInternalColorFormatFilterable(m_format);
157 			const IVec3&		size			= m_texSize;
158 
159 			log << TestLog::Message
160 				<< "Creating a cube map array texture ("
161 				<< size.x() << "x" << size.y()
162 				<< ", depth: "
163 				<< size.z() << ")"
164 				<< TestLog::EndMessage;
165 
166 			glGenTextures(1, &tex);
167 
168 			glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
169 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
170 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
171 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
172 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_MIN_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
173 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_MAG_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
174 			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
175 
176 			log << TestLog::Message << "Creating a framebuffer object for each layer-face" << TestLog::EndMessage;
177 
178 			// Generate an FBO for each layer-face
179 			for (int ndx = 0; ndx < m_texSize.z(); ndx++)
180 			{
181 				deUint32 layerFbo;
182 
183 				glGenFramebuffers(1, &layerFbo);
184 				glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
185 				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
186 				checkError();
187 				checkFramebufferStatus(GL_FRAMEBUFFER);
188 
189 				fbos.push_back(layerFbo);
190 			}
191 		}
192 
193 		log << TestLog::Message << "Rendering test images to layer-faces in randomized order" << TestLog::EndMessage;
194 
195 		{
196 			std::vector<int> order(fbos.size());
197 
198 			for (size_t n = 0; n < order.size(); n++)
199 				order[n] = (int)n;
200 			rnd.shuffle(order.begin(), order.end());
201 
202 			for (size_t ndx = 0; ndx < order.size(); ndx++)
203 			{
204 				const int			layerFace	= order[ndx];
205 				const deUint32		format		= GL_RGBA;
206 				const deUint32		dataType	= GL_UNSIGNED_BYTE;
207 				const int			texW		= 128;
208 				const int			texH		= 128;
209 				deUint32			tmpTex		= 0;
210 				const deUint32		fbo			= fbos[layerFace];
211 				const IVec3&		viewport	= m_texSize;
212 				tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
213 
214 				tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
215 
216 				glGenTextures(1, &tmpTex);
217 				glBindTexture(GL_TEXTURE_2D, tmpTex);
218 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
219 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
220 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
221 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
222 				glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
223 
224 				glBindFramebuffer(GL_FRAMEBUFFER, fbo);
225 				glViewport(0, 0, viewport.x(), viewport.y());
226 				sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
227 				checkError();
228 
229 				// Render to framebuffer
230 				{
231 					const Vec3			p0		= Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
232 					const Vec3			p1		= p0 + Vec3(1.0f, 1.0f, 0.0f);
233 					const int			layer	= layerFace / 6;
234 					const tcu::CubeFace	face	= getCubeFaceFromNdx(layerFace % 6);
235 
236 					glBindFramebuffer(GL_FRAMEBUFFER, 0);
237 					glViewport(0, 0, getWidth(), getHeight());
238 
239 					glActiveTexture(GL_TEXTURE0);
240 					glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
241 
242 					arrayTexShader.setLayer(layer);
243 					arrayTexShader.setFace(face);
244 					arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID);
245 
246 					sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1);
247 					checkError();
248 				}
249 			}
250 		}
251 
252 		readPixels(dst, 0, 0, getWidth(), getHeight());
253 	}
254 
255 private:
256 	IVec3 m_texSize;
257 };
258 
FboColorTests(Context & context)259 FboColorTests::FboColorTests (Context& context)
260 	: TestCaseGroup(context, "color", "Colorbuffer tests")
261 {
262 }
263 
~FboColorTests(void)264 FboColorTests::~FboColorTests (void)
265 {
266 }
267 
init(void)268 void FboColorTests::init (void)
269 {
270 	static const deUint32 colorFormats[] =
271 	{
272 		// RGBA formats
273 		GL_RGBA32I,
274 		GL_RGBA32UI,
275 		GL_RGBA16I,
276 		GL_RGBA16UI,
277 		GL_RGBA8,
278 		GL_RGBA8I,
279 		GL_RGBA8UI,
280 		GL_SRGB8_ALPHA8,
281 		GL_RGB10_A2,
282 		GL_RGB10_A2UI,
283 		GL_RGBA4,
284 		GL_RGB5_A1,
285 
286 		// RGB formats
287 		GL_RGB8,
288 		GL_RGB565,
289 
290 		// RG formats
291 		GL_RG32I,
292 		GL_RG32UI,
293 		GL_RG16I,
294 		GL_RG16UI,
295 		GL_RG8,
296 		GL_RG8I,
297 		GL_RG8UI,
298 
299 		// R formats
300 		GL_R32I,
301 		GL_R32UI,
302 		GL_R16I,
303 		GL_R16UI,
304 		GL_R8,
305 		GL_R8I,
306 		GL_R8UI,
307 
308 		// GL_EXT_color_buffer_float
309 		GL_RGBA32F,
310 		GL_RGBA16F,
311 		GL_R11F_G11F_B10F,
312 		GL_RG32F,
313 		GL_RG16F,
314 		GL_R32F,
315 		GL_R16F,
316 
317 		// GL_EXT_color_buffer_half_float
318 		GL_RGB16F
319 	};
320 
321 	// .texcubearray
322 	{
323 		tcu::TestCaseGroup* texCubeArrayGroup = new tcu::TestCaseGroup(m_testCtx, "texcubearray", "Cube map array texture tests");
324 		addChild(texCubeArrayGroup);
325 
326 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
327 			texCubeArrayGroup->addChild(new FboColorTexCubeArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
328 																	 colorFormats[fmtNdx], IVec3(128, 128, 12)));
329 	}
330 }
331 
332 } // Functional
333 } // gles31
334 } // deqp
335