• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 FboColorTex2DCase : public FboColorbufferCase
115 {
116 	public:
FboColorTex2DCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec2 & texSize)117 		FboColorTex2DCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec2& texSize)
118 			: FboColorbufferCase	(context, name, description, texFmt)
119 			, m_texFmt				(texFmt)
120 			, m_texSize				(texSize)
121 	{
122 	}
123 
124 	protected:
preCheck(void)125 		void preCheck (void)
126 		{
127 			checkFormatSupport(m_texFmt);
128 		}
129 
render(tcu::Surface & dst)130 		void render (tcu::Surface& dst)
131 		{
132 			tcu::TextureFormat		texFmt		= glu::mapGLInternalFormat(m_texFmt);
133 			tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFmt);
134 
135 			Texture2DShader			texToFboShader	(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
136 			deUint32				texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader);
137 			deUint32				fbo;
138 			deUint32				tex;
139 
140 			// Setup shader
141 			texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
142 
143 			//  Generate fbo
144 			{
145 				glu::TransferFormat	transferFmt	= glu::getTransferFormat(texFmt);
146 				deUint32			format		= m_texFmt;
147 				const IVec2&		size		= m_texSize;
148 
149 				glGenFramebuffers(1, &fbo);
150 				glGenTextures(1, &tex);
151 
152 				glBindTexture(GL_TEXTURE_2D, tex);
153 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
154 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
155 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
156 				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
157 				glTexImage2D(GL_TEXTURE_2D, 0, format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
158 
159 				glBindFramebuffer(GL_FRAMEBUFFER, fbo);
160 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
161 				checkError();
162 				checkFramebufferStatus(GL_FRAMEBUFFER);
163 			}
164 
165 			// Render texture to fbo
166 			{
167 				const deUint32		format		= GL_RGBA;
168 				const deUint32		dataType	= GL_UNSIGNED_BYTE;
169 				const int			texW		= 128;
170 				const int			texH		= 128;
171 				deUint32			tmpTex		= 0;
172 				const IVec2&		viewport	= m_texSize;
173 				tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
174 
175 				tcu::fillWithComponentGradients(data.getAccess(), Vec4(0.0f), Vec4(1.0f));
176 
177 				glGenTextures(1, &tmpTex);
178 				glBindTexture(GL_TEXTURE_2D, tmpTex);
179 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
180 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
181 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
182 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
183 				glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
184 
185 				glBindFramebuffer(GL_FRAMEBUFFER, fbo);
186 				glViewport(0, 0, viewport.x(), viewport.y());
187 				sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
188 			}
189 
190 			readPixels(dst, 0, 0, getWidth(), getHeight(), texFmt, fmtInfo.lookupScale, fmtInfo.lookupBias);
191 			checkError();
192 		}
193 
194 	private:
195 		deUint32	m_texFmt;
196 		IVec2		m_texSize;
197 };
198 
199 class FboColorTexCubeArrayCase : public FboColorbufferCase
200 {
201 public:
FboColorTexCubeArrayCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec3 & texSize)202 	FboColorTexCubeArrayCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
203 		: FboColorbufferCase	(context, name, description, texFmt)
204 		, m_texSize				(texSize)
205 	{
206 		DE_ASSERT(texSize.z() % 6 == 0);
207 	}
208 
209 protected:
preCheck(void)210 	void preCheck (void)
211 	{
212 		auto ctxType = m_context.getRenderContext().getType();
213 		if (!glu::contextSupports(ctxType, glu::ApiType::core(4, 5)) &&
214 			!glu::contextSupports(ctxType, glu::ApiType::es(3, 2)) &&
215 			!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array"))
216 			TCU_THROW(NotSupportedError, "Test requires extension GL_EXT_texture_cube_map_array or a context version equal or higher than 3.2");
217 
218 		checkFormatSupport(m_format);
219 	}
220 
render(tcu::Surface & dst)221 	void render (tcu::Surface& dst)
222 	{
223 		TestLog&				log					= m_testCtx.getLog();
224 		de::Random				rnd					(deStringHash(getName()) ^ 0xed607a89 ^ m_testCtx.getCommandLine().getBaseSeed());
225 		tcu::TextureFormat		texFmt				= glu::mapGLInternalFormat(m_format);
226 		tcu::TextureFormatInfo	fmtInfo				= tcu::getTextureFormatInfo(texFmt);
227 
228 		Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
229 		TextureCubeArrayShader	arrayTexShader		(glu::getSamplerCubeArrayType(texFmt), glu::TYPE_FLOAT_VEC4, glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType()));
230 
231 		deUint32				texToFboShaderID	= getCurrentContext()->createProgram(&texToFboShader);
232 		deUint32				arrayTexShaderID	= getCurrentContext()->createProgram(&arrayTexShader);
233 
234 		// Setup textures
235 		texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
236 		arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
237 
238 		// Framebuffers.
239 		std::vector<deUint32>	fbos;
240 		deUint32				tex;
241 
242 		{
243 			glu::TransferFormat	transferFmt		= glu::getTransferFormat(texFmt);
244 			bool				isFilterable	= glu::isGLInternalColorFormatFilterable(m_format);
245 			const IVec3&		size			= m_texSize;
246 
247 			log << TestLog::Message
248 				<< "Creating a cube map array texture ("
249 				<< size.x() << "x" << size.y()
250 				<< ", depth: "
251 				<< size.z() << ")"
252 				<< TestLog::EndMessage;
253 
254 			glGenTextures(1, &tex);
255 
256 			glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
257 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
258 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
259 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
260 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_MIN_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
261 			glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY,	GL_TEXTURE_MAG_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
262 			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
263 
264 			log << TestLog::Message << "Creating a framebuffer object for each layer-face" << TestLog::EndMessage;
265 
266 			// Generate an FBO for each layer-face
267 			for (int ndx = 0; ndx < m_texSize.z(); ndx++)
268 			{
269 				deUint32 layerFbo;
270 
271 				glGenFramebuffers(1, &layerFbo);
272 				glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
273 				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
274 				checkError();
275 				checkFramebufferStatus(GL_FRAMEBUFFER);
276 
277 				fbos.push_back(layerFbo);
278 			}
279 		}
280 
281 		log << TestLog::Message << "Rendering test images to layer-faces in randomized order" << TestLog::EndMessage;
282 
283 		{
284 			std::vector<int> order(fbos.size());
285 
286 			for (size_t n = 0; n < order.size(); n++)
287 				order[n] = (int)n;
288 			rnd.shuffle(order.begin(), order.end());
289 
290 			for (size_t ndx = 0; ndx < order.size(); ndx++)
291 			{
292 				const int			layerFace	= order[ndx];
293 				const deUint32		format		= GL_RGBA;
294 				const deUint32		dataType	= GL_UNSIGNED_BYTE;
295 				const int			texW		= 128;
296 				const int			texH		= 128;
297 				deUint32			tmpTex		= 0;
298 				const deUint32		fbo			= fbos[layerFace];
299 				const IVec3&		viewport	= m_texSize;
300 				tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
301 
302 				tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
303 
304 				glGenTextures(1, &tmpTex);
305 				glBindTexture(GL_TEXTURE_2D, tmpTex);
306 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
307 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
308 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
309 				glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
310 				glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
311 
312 				glBindFramebuffer(GL_FRAMEBUFFER, fbo);
313 				glViewport(0, 0, viewport.x(), viewport.y());
314 				sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
315 				checkError();
316 
317 				// Render to framebuffer
318 				{
319 					const Vec3			p0		= Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
320 					const Vec3			p1		= p0 + Vec3(1.0f, 1.0f, 0.0f);
321 					const int			layer	= layerFace / 6;
322 					const tcu::CubeFace	face	= getCubeFaceFromNdx(layerFace % 6);
323 
324 					glBindFramebuffer(GL_FRAMEBUFFER, 0);
325 					glViewport(0, 0, getWidth(), getHeight());
326 
327 					glActiveTexture(GL_TEXTURE0);
328 					glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
329 
330 					arrayTexShader.setLayer(layer);
331 					arrayTexShader.setFace(face);
332 					arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID);
333 
334 					sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1);
335 					checkError();
336 				}
337 			}
338 		}
339 
340 		readPixels(dst, 0, 0, getWidth(), getHeight());
341 	}
342 
343 private:
344 	IVec3 m_texSize;
345 };
346 
FboColorTests(Context & context)347 FboColorTests::FboColorTests (Context& context)
348 	: TestCaseGroup(context, "color", "Colorbuffer tests")
349 {
350 }
351 
~FboColorTests(void)352 FboColorTests::~FboColorTests (void)
353 {
354 }
355 
init(void)356 void FboColorTests::init (void)
357 {
358 	static const deUint32 colorFormats[] =
359 	{
360 		// RGBA formats
361 		GL_RGBA32I,
362 		GL_RGBA32UI,
363 		GL_RGBA16I,
364 		GL_RGBA16UI,
365 		GL_RGBA8,
366 		GL_RGBA8I,
367 		GL_RGBA8UI,
368 		GL_SRGB8_ALPHA8,
369 		GL_RGB10_A2,
370 		GL_RGB10_A2UI,
371 		GL_RGBA4,
372 		GL_RGB5_A1,
373 
374 		// RGB formats
375 		GL_RGB8,
376 		GL_RGB565,
377 
378 		// RG formats
379 		GL_RG32I,
380 		GL_RG32UI,
381 		GL_RG16I,
382 		GL_RG16UI,
383 		GL_RG8,
384 		GL_RG8I,
385 		GL_RG8UI,
386 
387 		// R formats
388 		GL_R32I,
389 		GL_R32UI,
390 		GL_R16I,
391 		GL_R16UI,
392 		GL_R8,
393 		GL_R8I,
394 		GL_R8UI,
395 
396 		// GL_EXT_color_buffer_float
397 		GL_RGBA32F,
398 		GL_RGBA16F,
399 		GL_R11F_G11F_B10F,
400 		GL_RG32F,
401 		GL_RG16F,
402 		GL_R32F,
403 		GL_R16F,
404 
405 		// GL_EXT_color_buffer_half_float
406 		GL_RGB16F
407 	};
408 
409 	static const deUint32 unorm16ColorFormats[] =
410 	{
411 		GL_R16,
412 		GL_RG16,
413 		GL_RGBA16
414 	};
415 
416 	// .texcubearray
417 	{
418 		tcu::TestCaseGroup* texCubeArrayGroup = new tcu::TestCaseGroup(m_testCtx, "texcubearray", "Cube map array texture tests");
419 		addChild(texCubeArrayGroup);
420 
421 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
422 			texCubeArrayGroup->addChild(new FboColorTexCubeArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
423 																	 colorFormats[fmtNdx], IVec3(128, 128, 12)));
424 	}
425 
426 	// .tex2d
427 	{
428 		tcu::TestCaseGroup* tex2dGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "Render to texture");
429 		addChild(tex2dGroup);
430 
431 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(unorm16ColorFormats); ndx++)
432 			tex2dGroup->addChild(new FboColorTex2DCase(m_context, getFormatName(unorm16ColorFormats[ndx]), "", unorm16ColorFormats[ndx], IVec2(129, 117)));
433 	}
434 }
435 
436 } // Functional
437 } // gles31
438 } // deqp
439