• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 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 "es3fFboColorbufferTests.hpp"
25 #include "es3fFboTestCase.hpp"
26 #include "es3fFboTestUtil.hpp"
27 #include "gluTextureUtil.hpp"
28 #include "gluContextInfo.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuRGBA.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "sglrContextUtil.hpp"
34 #include "deRandom.hpp"
35 #include "deString.h"
36 #include "glwEnums.hpp"
37 
38 namespace deqp
39 {
40 namespace gles3
41 {
42 namespace Functional
43 {
44 
45 using std::string;
46 using tcu::Vec2;
47 using tcu::Vec3;
48 using tcu::Vec4;
49 using tcu::IVec2;
50 using tcu::IVec3;
51 using tcu::IVec4;
52 using tcu::UVec4;
53 using tcu::TestLog;
54 using namespace FboTestUtil;
55 
56 const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12);
57 
58 template <int Size>
59 static tcu::Vector<float, Size> randomVector (de::Random& rnd, const tcu::Vector<float, Size>& minVal = tcu::Vector<float, Size>(0.0f), const tcu::Vector<float, Size>& maxVal = tcu::Vector<float, Size>(1.0f))
60 {
61 	tcu::Vector<float, Size> res;
62 	for (int ndx = 0; ndx < Size; ndx++)
63 		res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
64 	return res;
65 }
66 
generateRandomColor(de::Random & random)67 static tcu::Vec4 generateRandomColor (de::Random& random)
68 {
69 	tcu::Vec4 retVal;
70 
71 	for (int i = 0; i < 3; ++i)
72 		retVal[i] = random.getFloat();
73 	retVal[3] = 1.0f;
74 
75 	return retVal;
76 }
77 
78 class FboColorbufferCase : public FboTestCase
79 {
80 public:
FboColorbufferCase(Context & context,const char * name,const char * desc,const deUint32 format)81 	FboColorbufferCase (Context& context, const char* name, const char* desc, const deUint32 format)
82 		: FboTestCase			(context, name, desc)
83 		, m_format				(format)
84 	{
85 	}
86 
compare(const tcu::Surface & reference,const tcu::Surface & result)87 	bool compare (const tcu::Surface& reference, const tcu::Surface& result)
88 	{
89 		const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), MIN_THRESHOLD));
90 
91 		m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;
92 
93 		return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
94 	}
95 
96 protected:
97 	const deUint32	m_format;
98 };
99 
100 class FboColorClearCase : public FboColorbufferCase
101 {
102 public:
FboColorClearCase(Context & context,const char * name,const char * desc,deUint32 format,int width,int height)103 	FboColorClearCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height)
104 		: FboColorbufferCase	(context, name, desc, format)
105 		, m_width				(width)
106 		, m_height				(height)
107 	{
108 	}
109 
110 protected:
preCheck(void)111 	void preCheck (void)
112 	{
113 		checkFormatSupport(m_format);
114 	}
115 
render(tcu::Surface & dst)116 	void render (tcu::Surface& dst)
117 	{
118 		tcu::TextureFormat			fboFormat	= glu::mapGLInternalFormat(m_format);
119 		tcu::TextureChannelClass	fmtClass	= tcu::getTextureChannelClass(fboFormat.type);
120 		tcu::TextureFormatInfo		fmtInfo		= tcu::getTextureFormatInfo(fboFormat);
121 		de::Random					rnd			(17);
122 		const int					numClears	= 16;
123 		deUint32					fbo			= 0;
124 		deUint32					rbo			= 0;
125 
126 		glGenFramebuffers(1, &fbo);
127 		glGenRenderbuffers(1, &rbo);
128 
129 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
130 		glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_width, m_height);
131 		checkError();
132 
133 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
134 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
135 		checkError();
136 		checkFramebufferStatus(GL_FRAMEBUFFER);
137 
138 		glViewport(0, 0, m_width, m_height);
139 
140 		// Initialize to transparent black.
141 		switch (fmtClass)
142 		{
143 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
144 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
145 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
146 				glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr());
147 				break;
148 
149 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
150 				glClearBufferuiv(GL_COLOR, 0, UVec4(0).getPtr());
151 				break;
152 
153 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
154 				glClearBufferiv(GL_COLOR, 0, IVec4(0).getPtr());
155 				break;
156 
157 			default:
158 				DE_ASSERT(DE_FALSE);
159 		}
160 
161 		// Do random scissored clears.
162 		glEnable(GL_SCISSOR_TEST);
163 		for (int ndx = 0; ndx < numClears; ndx++)
164 		{
165 			int		x		= rnd.getInt(0, m_width		- 1);
166 			int		y		= rnd.getInt(0, m_height	- 1);
167 			int		w		= rnd.getInt(1, m_width		- x);
168 			int		h		= rnd.getInt(1, m_height	- y);
169 			Vec4	color	= randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
170 
171 			glScissor(x, y, w, h);
172 
173 			switch (fmtClass)
174 			{
175 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
176 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
177 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
178 					glClearBufferfv(GL_COLOR, 0, color.getPtr());
179 					break;
180 
181 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
182 					glClearBufferuiv(GL_COLOR, 0, color.cast<deUint32>().getPtr());
183 					break;
184 
185 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
186 					glClearBufferiv(GL_COLOR, 0, color.cast<int>().getPtr());
187 					break;
188 
189 				default:
190 					DE_ASSERT(DE_FALSE);
191 			}
192 		}
193 
194 		// Read results from renderbuffer.
195 		readPixels(dst, 0, 0, m_width, m_height, fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
196 		checkError();
197 	}
198 
199 private:
200 	const int			m_width;
201 	const int			m_height;
202 };
203 
204 class FboColorMultiTex2DCase : public FboColorbufferCase
205 {
206 public:
FboColorMultiTex2DCase(Context & context,const char * name,const char * description,deUint32 tex0Fmt,const IVec2 & tex0Size,deUint32 tex1Fmt,const IVec2 & tex1Size)207 	FboColorMultiTex2DCase (Context& context, const char* name, const char* description, deUint32 tex0Fmt, const IVec2& tex0Size, deUint32 tex1Fmt, const IVec2& tex1Size)
208 		: FboColorbufferCase	(context, name, description, tex0Fmt)
209 		, m_tex0Fmt				(tex0Fmt)
210 		, m_tex1Fmt				(tex1Fmt)
211 		, m_tex0Size			(tex0Size)
212 		, m_tex1Size			(tex1Size)
213 	{
214 	}
215 
216 protected:
preCheck(void)217 	void preCheck (void)
218 	{
219 		checkFormatSupport(m_tex0Fmt);
220 		checkFormatSupport(m_tex1Fmt);
221 	}
222 
render(tcu::Surface & dst)223 	void render (tcu::Surface& dst)
224 	{
225 		tcu::TextureFormat		texFmt0			= glu::mapGLInternalFormat(m_tex0Fmt);
226 		tcu::TextureFormat		texFmt1			= glu::mapGLInternalFormat(m_tex1Fmt);
227 		tcu::TextureFormatInfo	fmtInfo0		= tcu::getTextureFormatInfo(texFmt0);
228 		tcu::TextureFormatInfo	fmtInfo1		= tcu::getTextureFormatInfo(texFmt1);
229 
230 		Texture2DShader			texToFbo0Shader	(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt0), fmtInfo0.valueMax-fmtInfo0.valueMin, fmtInfo0.valueMin);
231 		Texture2DShader			texToFbo1Shader	(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt1), fmtInfo1.valueMax-fmtInfo1.valueMin, fmtInfo1.valueMin);
232 		Texture2DShader			multiTexShader	(DataTypes() << glu::getSampler2DType(texFmt0) << glu::getSampler2DType(texFmt1), glu::TYPE_FLOAT_VEC4);
233 
234 		deUint32				texToFbo0ShaderID = getCurrentContext()->createProgram(&texToFbo0Shader);
235 		deUint32				texToFbo1ShaderID = getCurrentContext()->createProgram(&texToFbo1Shader);
236 		deUint32				multiTexShaderID  = getCurrentContext()->createProgram(&multiTexShader);
237 
238 		// Setup shaders
239 		multiTexShader.setTexScaleBias(0, fmtInfo0.lookupScale * 0.5f, fmtInfo0.lookupBias * 0.5f);
240 		multiTexShader.setTexScaleBias(1, fmtInfo1.lookupScale * 0.5f, fmtInfo1.lookupBias * 0.5f);
241 		texToFbo0Shader.setUniforms(*getCurrentContext(), texToFbo0ShaderID);
242 		texToFbo1Shader.setUniforms(*getCurrentContext(), texToFbo1ShaderID);
243 		multiTexShader.setUniforms (*getCurrentContext(), multiTexShaderID);
244 
245 		// Framebuffers.
246 		deUint32				fbo0 = 0;
247 		deUint32				fbo1 = 0;
248 		deUint32				tex0 = 0;
249 		deUint32				tex1 = 0;
250 
251 		for (int ndx = 0; ndx < 2; ndx++)
252 		{
253 			glu::TransferFormat		transferFmt		= glu::getTransferFormat(ndx ? texFmt1 : texFmt0);
254 			deUint32				format			= ndx ? m_tex1Fmt : m_tex0Fmt;
255 			bool					isFilterable	= glu::isGLInternalColorFormatFilterable(format);
256 			const IVec2&			size			= ndx ? m_tex1Size : m_tex0Size;
257 			deUint32&				fbo				= ndx ? fbo1 : fbo0;
258 			deUint32&				tex				= ndx ? tex1 : tex0;
259 
260 			glGenFramebuffers(1, &fbo);
261 			glGenTextures(1, &tex);
262 
263 			glBindTexture(GL_TEXTURE_2D, tex);
264 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
265 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
266 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
267 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
268 			glTexImage2D(GL_TEXTURE_2D, 0, format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
269 
270 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
271 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
272 			checkError();
273 			checkFramebufferStatus(GL_FRAMEBUFFER);
274 		}
275 
276 		// Render textures to both framebuffers.
277 		for (int ndx = 0; ndx < 2; ndx++)
278 		{
279 			const deUint32		format		= GL_RGBA;
280 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
281 			const int			texW		= 128;
282 			const int			texH		= 128;
283 			deUint32			tmpTex		= 0;
284 			deUint32			fbo			= ndx ? fbo1 : fbo0;
285 			const IVec2&		viewport	= ndx ? m_tex1Size : m_tex0Size;
286 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
287 
288 			if (ndx == 0)
289 				tcu::fillWithComponentGradients(data.getAccess(), Vec4(0.0f), Vec4(1.0f));
290 			else
291 				tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
292 
293 			glGenTextures(1, &tmpTex);
294 			glBindTexture(GL_TEXTURE_2D, tmpTex);
295 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
296 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
297 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
298 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
299 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
300 
301 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
302 			glViewport(0, 0, viewport.x(), viewport.y());
303 			sglr::drawQuad(*getCurrentContext(), ndx ? texToFbo1ShaderID : texToFbo0ShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
304 		}
305 
306 		// Render to framebuffer.
307 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
308 		glViewport(0, 0, getWidth(), getHeight());
309 		glActiveTexture(GL_TEXTURE0);
310 		glBindTexture(GL_TEXTURE_2D, tex0);
311 		glActiveTexture(GL_TEXTURE1);
312 		glBindTexture(GL_TEXTURE_2D, tex1);
313 		sglr::drawQuad(*getCurrentContext(), multiTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
314 
315 		readPixels(dst, 0, 0, getWidth(), getHeight());
316 	}
317 
318 private:
319 	deUint32		m_tex0Fmt;
320 	deUint32		m_tex1Fmt;
321 	IVec2			m_tex0Size;
322 	IVec2			m_tex1Size;
323 };
324 
325 class FboColorTexCubeCase : public FboColorbufferCase
326 {
327 public:
FboColorTexCubeCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec2 & texSize)328 	FboColorTexCubeCase			(Context& context, const char* name, const char* description, deUint32 texFmt, const IVec2& texSize)
329 		: FboColorbufferCase	(context, name, description, texFmt)
330 		, m_texSize				(texSize)
331 	{
332 	}
333 
334 protected:
preCheck(void)335 	void preCheck (void)
336 	{
337 		checkFormatSupport(m_format);
338 	}
339 
render(tcu::Surface & dst)340 	void render (tcu::Surface& dst)
341 	{
342 		static const deUint32 cubeGLFaces[] =
343 		{
344 			GL_TEXTURE_CUBE_MAP_POSITIVE_X,
345 			GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
346 			GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
347 			GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
348 			GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
349 			GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
350 		};
351 
352 		static const tcu::CubeFace cubeTexFaces[] =
353 		{
354 			tcu::CUBEFACE_POSITIVE_X,
355 			tcu::CUBEFACE_POSITIVE_Y,
356 			tcu::CUBEFACE_POSITIVE_Z,
357 			tcu::CUBEFACE_NEGATIVE_X,
358 			tcu::CUBEFACE_NEGATIVE_Y,
359 			tcu::CUBEFACE_NEGATIVE_Z
360 		};
361 
362 		de::Random				rnd					(deStringHash(getName()) ^ 0x9eef603d);
363 		tcu::TextureFormat		texFmt				= glu::mapGLInternalFormat(m_format);
364 		tcu::TextureFormatInfo	fmtInfo				= tcu::getTextureFormatInfo(texFmt);
365 
366 		Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
367 		TextureCubeShader		cubeTexShader		(glu::getSamplerCubeType(texFmt), glu::TYPE_FLOAT_VEC4);
368 
369 		deUint32				texToFboShaderID	= getCurrentContext()->createProgram(&texToFboShader);
370 		deUint32				cubeTexShaderID		= getCurrentContext()->createProgram(&cubeTexShader);
371 
372 		// Setup shaders
373 		texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
374 		cubeTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
375 
376 		// Framebuffers.
377 		std::vector<deUint32>	fbos;
378 		deUint32				tex;
379 
380 		{
381 			glu::TransferFormat		transferFmt		= glu::getTransferFormat(texFmt);
382 			bool					isFilterable	= glu::isGLInternalColorFormatFilterable(m_format);
383 			const IVec2&			size			= m_texSize;
384 
385 
386 			glGenTextures(1, &tex);
387 
388 			glBindTexture(GL_TEXTURE_CUBE_MAP,		tex);
389 			glTexParameteri(GL_TEXTURE_CUBE_MAP,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
390 			glTexParameteri(GL_TEXTURE_CUBE_MAP,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
391 			glTexParameteri(GL_TEXTURE_CUBE_MAP,	GL_TEXTURE_MIN_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
392 			glTexParameteri(GL_TEXTURE_CUBE_MAP,	GL_TEXTURE_MAG_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
393 
394 			// Generate an image and FBO for each cube face
395 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
396 				glTexImage2D(cubeGLFaces[ndx], 0, m_format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
397 			checkError();
398 
399 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
400 			{
401 				deUint32			layerFbo;
402 
403 				glGenFramebuffers(1, &layerFbo);
404 				glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
405 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubeGLFaces[ndx], tex, 0);
406 				checkError();
407 				checkFramebufferStatus(GL_FRAMEBUFFER);
408 
409 				fbos.push_back(layerFbo);
410 			}
411 		}
412 
413 		// Render test images to random cube faces
414 		std::vector<int> order;
415 
416 		for (size_t n = 0; n < fbos.size(); n++)
417 			order.push_back((int)n);
418 		rnd.shuffle(order.begin(), order.end());
419 
420 		DE_ASSERT(order.size() >= 4);
421 		for (int ndx = 0; ndx < 4; ndx++)
422 		{
423 			const int			face		= order[ndx];
424 			const deUint32		format		= GL_RGBA;
425 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
426 			const int			texW		= 128;
427 			const int			texH		= 128;
428 			deUint32			tmpTex		= 0;
429 			const deUint32		fbo			= fbos[face];
430 			const IVec2&		viewport	= m_texSize;
431 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
432 
433 			tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
434 
435 			glGenTextures(1, &tmpTex);
436 			glBindTexture(GL_TEXTURE_2D, tmpTex);
437 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
438 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
439 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
440 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
441 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
442 
443 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
444 			glViewport(0, 0, viewport.x(), viewport.y());
445 			sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
446 			checkError();
447 
448 			// Render to framebuffer
449 			{
450 				const Vec3		p0	= Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
451 				const Vec3		p1	= p0 + Vec3(1.0f, 1.0f, 0.0f);
452 
453 				glBindFramebuffer(GL_FRAMEBUFFER, 0);
454 				glViewport(0, 0, getWidth(), getHeight());
455 
456 				glActiveTexture(GL_TEXTURE0);
457 				glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
458 
459 				cubeTexShader.setFace(cubeTexFaces[face]);
460 				cubeTexShader.setUniforms(*getCurrentContext(), cubeTexShaderID);
461 
462 				sglr::drawQuad(*getCurrentContext(), cubeTexShaderID, p0, p1);
463 				checkError();
464 			}
465 		}
466 
467 		readPixels(dst, 0, 0, getWidth(), getHeight());
468 	}
469 
470 private:
471 	IVec2			m_texSize;
472 };
473 
474 class FboColorTex2DArrayCase : public FboColorbufferCase
475 {
476 public:
FboColorTex2DArrayCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec3 & texSize)477 	FboColorTex2DArrayCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
478 		: FboColorbufferCase	(context, name, description, texFmt)
479 		, m_texSize				(texSize)
480 	{
481 	}
482 
483 protected:
preCheck(void)484 	void preCheck (void)
485 	{
486 		checkFormatSupport(m_format);
487 	}
488 
render(tcu::Surface & dst)489 	void render (tcu::Surface& dst)
490 	{
491 		de::Random				rnd					(deStringHash(getName()) ^ 0xed607a89);
492 		tcu::TextureFormat		texFmt				= glu::mapGLInternalFormat(m_format);
493 		tcu::TextureFormatInfo	fmtInfo				= tcu::getTextureFormatInfo(texFmt);
494 
495 		Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
496 		Texture2DArrayShader	arrayTexShader		(glu::getSampler2DArrayType(texFmt), glu::TYPE_FLOAT_VEC4);
497 
498 		deUint32				texToFboShaderID	= getCurrentContext()->createProgram(&texToFboShader);
499 		deUint32				arrayTexShaderID	= getCurrentContext()->createProgram(&arrayTexShader);
500 
501 		// Setup textures
502 		texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
503 		arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
504 
505 		// Framebuffers.
506 		std::vector<deUint32>	fbos;
507 		deUint32				tex;
508 
509 		{
510 			glu::TransferFormat		transferFmt		= glu::getTransferFormat(texFmt);
511 			bool					isFilterable	= glu::isGLInternalColorFormatFilterable(m_format);
512 			const IVec3&			size			= m_texSize;
513 
514 
515 			glGenTextures(1, &tex);
516 
517 			glBindTexture(GL_TEXTURE_2D_ARRAY,		tex);
518 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
519 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
520 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
521 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_MIN_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
522 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_MAG_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
523 			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
524 
525 			// Generate an FBO for each layer
526 			for (int ndx = 0; ndx < m_texSize.z(); ndx++)
527 			{
528 				deUint32			layerFbo;
529 
530 				glGenFramebuffers(1, &layerFbo);
531 				glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
532 				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
533 				checkError();
534 				checkFramebufferStatus(GL_FRAMEBUFFER);
535 
536 				fbos.push_back(layerFbo);
537 			}
538 		}
539 
540 		// Render test images to random texture layers
541 		std::vector<int>		order;
542 
543 		for (size_t n = 0; n < fbos.size(); n++)
544 			order.push_back((int)n);
545 		rnd.shuffle(order.begin(), order.end());
546 
547 		for (size_t ndx = 0; ndx < order.size(); ndx++)
548 		{
549 			const int			layer		= order[ndx];
550 			const deUint32		format		= GL_RGBA;
551 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
552 			const int			texW		= 128;
553 			const int			texH		= 128;
554 			deUint32			tmpTex		= 0;
555 			const deUint32		fbo			= fbos[layer];
556 			const IVec3&		viewport	= m_texSize;
557 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
558 
559 			tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
560 
561 			glGenTextures(1, &tmpTex);
562 			glBindTexture(GL_TEXTURE_2D, tmpTex);
563 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
564 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
565 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
566 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
567 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
568 
569 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
570 			glViewport(0, 0, viewport.x(), viewport.y());
571 			sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
572 			checkError();
573 
574 			// Render to framebuffer
575 			{
576 				const Vec3		p0	= Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
577 				const Vec3		p1	= p0 + Vec3(1.0f, 1.0f, 0.0f);
578 
579 				glBindFramebuffer(GL_FRAMEBUFFER, 0);
580 				glViewport(0, 0, getWidth(), getHeight());
581 
582 				glActiveTexture(GL_TEXTURE0);
583 				glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
584 
585 				arrayTexShader.setLayer(layer);
586 				arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID);
587 
588 				sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1);
589 				checkError();
590 			}
591 		}
592 
593 		readPixels(dst, 0, 0, getWidth(), getHeight());
594 	}
595 
596 private:
597 	IVec3			m_texSize;
598 };
599 
600 class FboColorTex3DCase : public FboColorbufferCase
601 {
602 public:
FboColorTex3DCase(Context & context,const char * name,const char * description,deUint32 texFmt,const IVec3 & texSize)603 	FboColorTex3DCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
604 		: FboColorbufferCase	(context, name, description, texFmt)
605 		, m_texSize				(texSize)
606 	{
607 	}
608 
609 protected:
preCheck(void)610 	void preCheck (void)
611 	{
612 		checkFormatSupport(m_format);
613 	}
614 
render(tcu::Surface & dst)615 	void render (tcu::Surface& dst)
616 	{
617 		de::Random				rnd				(deStringHash(getName()) ^ 0x74d947b2);
618 		tcu::TextureFormat		texFmt			= glu::mapGLInternalFormat(m_format);
619 		tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
620 
621 		Texture2DShader			texToFboShader	(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
622 		Texture3DShader			tdTexShader		(glu::getSampler3DType(texFmt), glu::TYPE_FLOAT_VEC4);
623 
624 		deUint32				texToFboShaderID= getCurrentContext()->createProgram(&texToFboShader);
625 		deUint32				tdTexShaderID	= getCurrentContext()->createProgram(&tdTexShader);
626 
627 		// Setup shaders
628 		texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
629 		tdTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
630 
631 		// Framebuffers.
632 		std::vector<deUint32>	fbos;
633 		deUint32				tex;
634 
635 		{
636 			glu::TransferFormat		transferFmt		= glu::getTransferFormat(texFmt);
637 			const IVec3&			size			= m_texSize;
638 
639 			glGenTextures(1, &tex);
640 
641 			glBindTexture(GL_TEXTURE_3D,		tex);
642 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
643 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
644 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
645 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
646 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
647 			glTexImage3D(GL_TEXTURE_3D, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
648 
649 			// Generate an FBO for each layer
650 			for (int ndx = 0; ndx < m_texSize.z(); ndx++)
651 			{
652 				deUint32			layerFbo;
653 
654 				glGenFramebuffers(1, &layerFbo);
655 				glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
656 				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
657 				checkError();
658 				checkFramebufferStatus(GL_FRAMEBUFFER);
659 
660 				fbos.push_back(layerFbo);
661 			}
662 		}
663 
664 		// Render test images to random texture layers
665 		std::vector<int> order;
666 
667 		for (size_t n = 0; n < fbos.size(); n++)
668 			order.push_back((int)n);
669 		rnd.shuffle(order.begin(), order.end());
670 
671 		for (size_t ndx = 0; ndx < order.size(); ndx++)
672 		{
673 			const int			layer		= order[ndx];
674 			const deUint32		format		= GL_RGBA;
675 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
676 			const int			texW		= 128;
677 			const int			texH		= 128;
678 			deUint32			tmpTex		= 0;
679 			const deUint32		fbo			= fbos[layer];
680 			const IVec3&		viewport	= m_texSize;
681 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
682 
683 			tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
684 
685 			glGenTextures(1, &tmpTex);
686 			glBindTexture(GL_TEXTURE_2D, tmpTex);
687 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
688 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
689 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
690 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
691 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
692 
693 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
694 			glViewport(0, 0, viewport.x(), viewport.y());
695 			sglr::drawQuad(*getCurrentContext() , texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
696 			checkError();
697 
698 			// Render to framebuffer
699 			{
700 				const Vec3		p0	= Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
701 				const Vec3		p1	= p0 + Vec3(1.0f, 1.0f, 0.0f);
702 
703 				glBindFramebuffer(GL_FRAMEBUFFER, 0);
704 				glViewport(0, 0, getWidth(), getHeight());
705 
706 				glActiveTexture(GL_TEXTURE0);
707 				glBindTexture(GL_TEXTURE_3D, tex);
708 
709 				tdTexShader.setDepth(float(layer) / float(m_texSize.z()-1));
710 				tdTexShader.setUniforms(*getCurrentContext(), tdTexShaderID);
711 
712 				sglr::drawQuad(*getCurrentContext(), tdTexShaderID, p0, p1);
713 				checkError();
714 			}
715 		}
716 
717 		readPixels(dst, 0, 0, getWidth(), getHeight());
718 	}
719 
720 private:
721 	IVec3			m_texSize;
722 };
723 
724 class FboBlendCase : public FboColorbufferCase
725 {
726 public:
FboBlendCase(Context & context,const char * name,const char * desc,deUint32 format,IVec2 size,deUint32 funcRGB,deUint32 funcAlpha,deUint32 srcRGB,deUint32 dstRGB,deUint32 srcAlpha,deUint32 dstAlpha)727 	FboBlendCase (Context& context, const char* name, const char* desc, deUint32 format, IVec2 size, deUint32 funcRGB, deUint32 funcAlpha, deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
728 		: FboColorbufferCase	(context, name, desc, format)
729 		, m_size				(size)
730 		, m_funcRGB				(funcRGB)
731 		, m_funcAlpha			(funcAlpha)
732 		, m_srcRGB				(srcRGB)
733 		, m_dstRGB				(dstRGB)
734 		, m_srcAlpha			(srcAlpha)
735 		, m_dstAlpha			(dstAlpha)
736 	{
737 	}
738 
739 protected:
preCheck(void)740 	void preCheck (void)
741 	{
742 		checkFormatSupport(m_format);
743 	}
744 
render(tcu::Surface & dst)745 	void render (tcu::Surface& dst)
746 	{
747 		// \note Assumes floating-point or fixed-point format.
748 		tcu::TextureFormat			fboFmt			= glu::mapGLInternalFormat(m_format);
749 		Texture2DShader				texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
750 		GradientShader				gradShader		(glu::TYPE_FLOAT_VEC4);
751 		deUint32					texShaderID		= getCurrentContext()->createProgram(&texShader);
752 		deUint32					gradShaderID	= getCurrentContext()->createProgram(&gradShader);
753 		deUint32					fbo				= 0;
754 		deUint32					rbo				= 0;
755 
756 		// Setup shaders
757 		texShader.setUniforms (*getCurrentContext(), texShaderID);
758 		gradShader.setGradient(*getCurrentContext(), gradShaderID, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
759 
760 		glGenFramebuffers(1, &fbo);
761 		glGenRenderbuffers(1, &rbo);
762 
763 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
764 		glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y());
765 		checkError();
766 
767 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
768 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
769 		checkError();
770 		checkFramebufferStatus(GL_FRAMEBUFFER);
771 
772 		glViewport(0, 0, m_size.x(), m_size.y());
773 
774 		// Fill framebuffer with grid pattern.
775 		{
776 			const deUint32		format		= GL_RGBA;
777 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
778 			const int			texW		= 128;
779 			const int			texH		= 128;
780 			deUint32			gridTex		= 0;
781 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
782 
783 			tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
784 
785 			glGenTextures(1, &gridTex);
786 			glBindTexture(GL_TEXTURE_2D, gridTex);
787 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
788 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
789 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
790 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
791 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
792 
793 			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
794 		}
795 
796 		// Setup blend.
797 		glEnable(GL_BLEND);
798 		glBlendEquationSeparate(m_funcRGB, m_funcAlpha);
799 		glBlendFuncSeparate(m_srcRGB, m_dstRGB, m_srcAlpha, m_dstAlpha);
800 
801 		// Render gradient with blend.
802 		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
803 
804 		readPixels(dst, 0, 0, m_size.x(), m_size.y(), fboFmt, Vec4(1.0f), Vec4(0.0f));
805 	}
806 
807 private:
808 	IVec2		m_size;
809 	deUint32	m_funcRGB;
810 	deUint32	m_funcAlpha;
811 	deUint32	m_srcRGB;
812 	deUint32	m_dstRGB;
813 	deUint32	m_srcAlpha;
814 	deUint32	m_dstAlpha;
815 };
816 
817 class FboRepeatedClearSampleTex2DCase : public FboColorbufferCase
818 {
819 public:
FboRepeatedClearSampleTex2DCase(Context & context,const char * name,const char * desc,deUint32 format)820 	FboRepeatedClearSampleTex2DCase (Context& context, const char* name, const char* desc, deUint32 format)
821 		: FboColorbufferCase(context, name, desc, format)
822 	{
823 	}
824 
825 protected:
preCheck(void)826 	void preCheck (void)
827 	{
828 		checkFormatSupport(m_format);
829 	}
830 
render(tcu::Surface & dst)831 	void render (tcu::Surface& dst)
832 	{
833 		const tcu::TextureFormat		fboFormat		= glu::mapGLInternalFormat(m_format);
834 		const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(fboFormat);
835 		const int						numRowsCols		= 4;
836 		const int						cellSize		= 16;
837 		const int						fboSizes[]		= { cellSize, cellSize*numRowsCols };
838 
839 		Texture2DShader					fboBlitShader	(DataTypes() << glu::getSampler2DType(fboFormat), getFragmentOutputType(fboFormat), Vec4(1.0f), Vec4(0.0f));
840 		const deUint32					fboBlitShaderID	= getCurrentContext()->createProgram(&fboBlitShader);
841 
842 		de::Random						rnd				(18169662);
843 		deUint32						fbos[]			= { 0, 0 };
844 		deUint32						textures[]		= { 0, 0 };
845 
846 		glGenFramebuffers(2, &fbos[0]);
847 		glGenTextures(2, &textures[0]);
848 
849 		for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
850 		{
851 			glBindTexture(GL_TEXTURE_2D, textures[fboNdx]);
852 			glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
853 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
854 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
855 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
856 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
857 			checkError();
858 
859 			glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
860 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
861 			checkError();
862 			checkFramebufferStatus(GL_FRAMEBUFFER);
863 		}
864 
865 		// larger fbo bound -- clear to transparent black
866 		clearColorBuffer(fboFormat, Vec4(0.0f));
867 
868 		fboBlitShader.setUniforms(*getCurrentContext(), fboBlitShaderID);
869 		glBindTexture(GL_TEXTURE_2D, textures[0]);
870 
871 		for (int cellY = 0; cellY < numRowsCols; cellY++)
872 		for (int cellX = 0; cellX < numRowsCols; cellX++)
873 		{
874 			const Vec4	color	= randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
875 
876 			glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
877 			clearColorBuffer(fboFormat, color);
878 
879 			glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
880 			glViewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize);
881 			sglr::drawQuad(*getCurrentContext(), fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
882 		}
883 
884 		readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
885 		checkError();
886 	}
887 };
888 
889 class FboRepeatedClearBlitTex2DCase : public FboColorbufferCase
890 {
891 public:
FboRepeatedClearBlitTex2DCase(Context & context,const char * name,const char * desc,deUint32 format)892 	FboRepeatedClearBlitTex2DCase (Context& context, const char* name, const char* desc, deUint32 format)
893 		: FboColorbufferCase(context, name, desc, format)
894 	{
895 	}
896 
897 protected:
preCheck(void)898 	void preCheck (void)
899 	{
900 		checkFormatSupport(m_format);
901 	}
902 
render(tcu::Surface & dst)903 	void render (tcu::Surface& dst)
904 	{
905 		const tcu::TextureFormat		fboFormat		= glu::mapGLInternalFormat(m_format);
906 		const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(fboFormat);
907 		const int						numRowsCols		= 4;
908 		const int						cellSize		= 16;
909 		const int						fboSizes[]		= { cellSize, cellSize*numRowsCols };
910 
911 		de::Random						rnd				(18169662);
912 		deUint32						fbos[]			= { 0, 0 };
913 		deUint32						textures[]		= { 0, 0 };
914 
915 		glGenFramebuffers(2, &fbos[0]);
916 		glGenTextures(2, &textures[0]);
917 
918 		for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
919 		{
920 			glBindTexture(GL_TEXTURE_2D, textures[fboNdx]);
921 			glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
922 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
923 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
924 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
925 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
926 			checkError();
927 
928 			glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
929 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0);
930 			checkError();
931 			checkFramebufferStatus(GL_FRAMEBUFFER);
932 		}
933 
934 		// larger fbo bound -- clear to transparent black
935 		clearColorBuffer(fboFormat, Vec4(0.0f));
936 
937 		for (int cellY = 0; cellY < numRowsCols; cellY++)
938 		for (int cellX = 0; cellX < numRowsCols; cellX++)
939 		{
940 			const Vec4	color	= randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
941 
942 			glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
943 			clearColorBuffer(fboFormat, color);
944 
945 			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
946 			glBlitFramebuffer(0, 0, cellSize, cellSize, cellX*cellSize, cellY*cellSize, (cellX+1)*cellSize, (cellY+1)*cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
947 		}
948 
949 		glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
950 		readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
951 		checkError();
952 	}
953 };
954 
955 class FboRepeatedClearBlitRboCase : public FboColorbufferCase
956 {
957 public:
FboRepeatedClearBlitRboCase(Context & context,const char * name,const char * desc,deUint32 format)958 	FboRepeatedClearBlitRboCase (Context& context, const char* name, const char* desc, deUint32 format)
959 		: FboColorbufferCase(context, name, desc, format)
960 	{
961 	}
962 
963 protected:
preCheck(void)964 	void preCheck (void)
965 	{
966 		checkFormatSupport(m_format);
967 	}
968 
render(tcu::Surface & dst)969 	void render (tcu::Surface& dst)
970 	{
971 		const tcu::TextureFormat		fboFormat		= glu::mapGLInternalFormat(m_format);
972 		const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(fboFormat);
973 		const int						numRowsCols		= 4;
974 		const int						cellSize		= 16;
975 		const int						fboSizes[]		= { cellSize, cellSize*numRowsCols };
976 
977 		de::Random						rnd				(18169662);
978 		deUint32						fbos[]			= { 0, 0 };
979 		deUint32						rbos[]			= { 0, 0 };
980 
981 		glGenFramebuffers(2, &fbos[0]);
982 		glGenRenderbuffers(2, &rbos[0]);
983 
984 		for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++)
985 		{
986 			glBindRenderbuffer(GL_RENDERBUFFER, rbos[fboNdx]);
987 			glRenderbufferStorage(GL_RENDERBUFFER, m_format, fboSizes[fboNdx], fboSizes[fboNdx]);
988 			checkError();
989 
990 			glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]);
991 			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbos[fboNdx]);
992 			checkError();
993 			checkFramebufferStatus(GL_FRAMEBUFFER);
994 		}
995 
996 		// larger fbo bound -- clear to transparent black
997 		clearColorBuffer(fboFormat, Vec4(0.0f));
998 
999 		for (int cellY = 0; cellY < numRowsCols; cellY++)
1000 		for (int cellX = 0; cellX < numRowsCols; cellX++)
1001 		{
1002 			const Vec4	color	= randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
1003 
1004 			glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]);
1005 			clearColorBuffer(fboFormat, color);
1006 
1007 			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
1008 			glBlitFramebuffer(0, 0, cellSize, cellSize, cellX*cellSize, cellY*cellSize, (cellX+1)*cellSize, (cellY+1)*cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1009 		}
1010 
1011 		glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]);
1012 		readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
1013 		checkError();
1014 	}
1015 };
1016 
FboColorTests(Context & context)1017 FboColorTests::FboColorTests (Context& context)
1018 	: TestCaseGroup(context, "color", "Colorbuffer tests")
1019 {
1020 }
1021 
~FboColorTests(void)1022 FboColorTests::~FboColorTests (void)
1023 {
1024 }
1025 
init(void)1026 void FboColorTests::init (void)
1027 {
1028 	static const deUint32 colorFormats[] =
1029 	{
1030 		// RGBA formats
1031 		GL_RGBA32I,
1032 		GL_RGBA32UI,
1033 		GL_RGBA16I,
1034 		GL_RGBA16UI,
1035 		GL_RGBA8,
1036 		GL_RGBA8I,
1037 		GL_RGBA8UI,
1038 		GL_SRGB8_ALPHA8,
1039 		GL_RGB10_A2,
1040 		GL_RGB10_A2UI,
1041 		GL_RGBA4,
1042 		GL_RGB5_A1,
1043 
1044 		// RGB formats
1045 		GL_RGB8,
1046 		GL_RGB565,
1047 
1048 		// RG formats
1049 		GL_RG32I,
1050 		GL_RG32UI,
1051 		GL_RG16I,
1052 		GL_RG16UI,
1053 		GL_RG8,
1054 		GL_RG8I,
1055 		GL_RG8UI,
1056 
1057 		// R formats
1058 		GL_R32I,
1059 		GL_R32UI,
1060 		GL_R16I,
1061 		GL_R16UI,
1062 		GL_R8,
1063 		GL_R8I,
1064 		GL_R8UI,
1065 
1066 		// GL_EXT_color_buffer_float
1067 		GL_RGBA32F,
1068 		GL_RGBA16F,
1069 		GL_R11F_G11F_B10F,
1070 		GL_RG32F,
1071 		GL_RG16F,
1072 		GL_R32F,
1073 		GL_R16F,
1074 
1075 		// GL_EXT_color_buffer_half_float
1076 		GL_RGB16F
1077 	};
1078 
1079 	// .clear
1080 	{
1081 		tcu::TestCaseGroup* clearGroup = new tcu::TestCaseGroup(m_testCtx, "clear", "Color clears");
1082 		addChild(clearGroup);
1083 
1084 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
1085 			clearGroup->addChild(new FboColorClearCase(m_context, getFormatName(colorFormats[ndx]), "", colorFormats[ndx], 129, 117));
1086 	}
1087 
1088 	// .tex2d
1089 	{
1090 		tcu::TestCaseGroup* tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "Texture 2D tests");
1091 		addChild(tex2DGroup);
1092 
1093 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1094 			tex2DGroup->addChild(new FboColorMultiTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1095 															colorFormats[fmtNdx], IVec2(129, 117),
1096 															colorFormats[fmtNdx], IVec2(99, 128)));
1097 	}
1098 
1099 	// .texcube
1100 	{
1101 		tcu::TestCaseGroup* texCubeGroup = new tcu::TestCaseGroup(m_testCtx, "texcube", "Texture cube map tests");
1102 		addChild(texCubeGroup);
1103 
1104 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1105 			texCubeGroup->addChild(new FboColorTexCubeCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1106 														   colorFormats[fmtNdx], IVec2(128, 128)));
1107 	}
1108 
1109 	// .tex2darray
1110 	{
1111 		tcu::TestCaseGroup* tex2DArrayGroup = new tcu::TestCaseGroup(m_testCtx, "tex2darray", "Texture 2D array tests");
1112 		addChild(tex2DArrayGroup);
1113 
1114 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1115 			tex2DArrayGroup->addChild(new FboColorTex2DArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1116 																 colorFormats[fmtNdx], IVec3(128, 128, 5)));
1117 	}
1118 
1119 	// .tex3d
1120 	{
1121 		tcu::TestCaseGroup* tex3DGroup = new tcu::TestCaseGroup(m_testCtx, "tex3d", "Texture 3D tests");
1122 		addChild(tex3DGroup);
1123 
1124 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1125 			tex3DGroup->addChild(new FboColorTex3DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
1126 													   colorFormats[fmtNdx], IVec3(128, 128, 5)));
1127 	}
1128 
1129 	// .blend
1130 	{
1131 		tcu::TestCaseGroup* blendGroup = new tcu::TestCaseGroup(m_testCtx, "blend", "Blending tests");
1132 		addChild(blendGroup);
1133 
1134 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1135 		{
1136 			deUint32					format		= colorFormats[fmtNdx];
1137 			tcu::TextureFormat			texFmt		= glu::mapGLInternalFormat(format);
1138 			tcu::TextureChannelClass	fmtClass	= tcu::getTextureChannelClass(texFmt.type);
1139 			string						fmtName		= getFormatName(format);
1140 
1141 			if (texFmt.type	== tcu::TextureFormat::FLOAT				||
1142 				fmtClass	== tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER	||
1143 				fmtClass	== tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1144 				continue; // Blending is not supported.
1145 
1146 			blendGroup->addChild(new FboBlendCase(m_context, (fmtName + "_src_over").c_str(), "", format, IVec2(127, 111), GL_FUNC_ADD, GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE));
1147 		}
1148 	}
1149 
1150 	// .repeated_clear
1151 	{
1152 		tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated clears and blits");
1153 		addChild(repeatedClearGroup);
1154 
1155 		// .sample.tex2d
1156 		{
1157 			tcu::TestCaseGroup* const sampleGroup = new tcu::TestCaseGroup(m_testCtx, "sample", "Read by sampling");
1158 			repeatedClearGroup->addChild(sampleGroup);
1159 
1160 			tcu::TestCaseGroup* const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture");
1161 			sampleGroup->addChild(tex2DGroup);
1162 
1163 			for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1164 				tex2DGroup->addChild(new FboRepeatedClearSampleTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]),
1165 																		 "", colorFormats[fmtNdx]));
1166 		}
1167 
1168 		// .blit
1169 		{
1170 			tcu::TestCaseGroup* const blitGroup = new tcu::TestCaseGroup(m_testCtx, "blit", "Blitted");
1171 			repeatedClearGroup->addChild(blitGroup);
1172 
1173 			// .tex2d
1174 			{
1175 				tcu::TestCaseGroup* const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture");
1176 				blitGroup->addChild(tex2DGroup);
1177 
1178 				for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1179 					tex2DGroup->addChild(new FboRepeatedClearBlitTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]),
1180 																		   "", colorFormats[fmtNdx]));
1181 			}
1182 
1183 			// .rbo
1184 			{
1185 				tcu::TestCaseGroup* const rboGroup = new tcu::TestCaseGroup(m_testCtx, "rbo", "Renderbuffer");
1186 				blitGroup->addChild(rboGroup);
1187 
1188 				for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
1189 					rboGroup->addChild(new FboRepeatedClearBlitRboCase(m_context, getFormatName(colorFormats[fmtNdx]),
1190 																	   "", colorFormats[fmtNdx]));
1191 			}
1192 		}
1193 	}
1194 }
1195 
1196 } // Functional
1197 } // gles3
1198 } // deqp
1199