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 Pixel Buffer Object tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fPixelBufferObjectTests.hpp"
25 
26 #include "tcuTexture.hpp"
27 #include "tcuTextureUtil.hpp"
28 #include "tcuImageCompare.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuRenderTarget.hpp"
31 
32 #include "gluTextureUtil.hpp"
33 #include "gluPixelTransfer.hpp"
34 #include "gluShaderProgram.hpp"
35 
36 #include "deRandom.hpp"
37 #include "deString.h"
38 
39 #include <string>
40 #include <sstream>
41 
42 #include "glw.h"
43 
44 using std::string;
45 using std::stringstream;
46 
47 namespace deqp
48 {
49 namespace gles3
50 {
51 namespace Functional
52 {
53 
54 namespace
55 {
56 
57 class ReadPixelsTest : public TestCase
58 {
59 public:
60 	struct TestSpec
61 	{
62 		enum FramebufferType
63 		{
64 			FRAMEBUFFERTYPE_NATIVE = 0,
65 			FRAMEBUFFERTYPE_RENDERBUFFER
66 		};
67 
68 		string			name;
69 		string			description;
70 
71 		bool			useColorClear;
72 		bool			renderTriangles;
73 
74 		FramebufferType	framebufferType;
75 		GLenum			renderbufferFormat;
76 	};
77 
78 					ReadPixelsTest				(Context& context, const TestSpec& spec);
79 					~ReadPixelsTest				(void);
80 
81 	void			init						(void);
82 	void			deinit						(void);
83 
84 	IterateResult	iterate						(void);
85 
86 private:
87 	void						renderTriangle	(const tcu::Vec3& a, const tcu::Vec3& b, const tcu::Vec3& c);
88 	void						clearColor		(float r, float g, float b, float a);
89 
90 	de::Random					m_random;
91 	tcu::TestLog&				m_log;
92 	glu::ShaderProgram*			m_program;
93 
94 	TestSpec::FramebufferType	m_framebuffeType;
95 
96 	GLenum						m_renderbufferFormat;
97 	tcu::TextureChannelClass	m_texChannelClass;
98 
99 	bool						m_useColorClears;
100 	bool						m_renderTriangles;
101 
102 	GLfloat						m_colorScale;
103 };
104 
105 
ReadPixelsTest(Context & context,const TestSpec & spec)106 ReadPixelsTest::ReadPixelsTest (Context& context, const TestSpec& spec)
107 	: TestCase				(context, spec.name.c_str(), spec.description.c_str())
108 	, m_random				(deStringHash(spec.name.c_str()))
109 	, m_log					(m_testCtx.getLog())
110 	, m_program				(NULL)
111 	, m_framebuffeType		(spec.framebufferType)
112 	, m_renderbufferFormat	(spec.renderbufferFormat)
113 	, m_texChannelClass		(tcu::TEXTURECHANNELCLASS_LAST)
114 	, m_useColorClears		(spec.useColorClear)
115 	, m_renderTriangles		(spec.renderTriangles)
116 	, m_colorScale			(1.0f)
117 {
118 
119 	if (m_framebuffeType == TestSpec::FRAMEBUFFERTYPE_NATIVE)
120 	{
121 		m_colorScale = 1.0f;
122 	}
123 	else if (m_framebuffeType == TestSpec::FRAMEBUFFERTYPE_RENDERBUFFER)
124 	{
125 		m_texChannelClass = tcu::getTextureChannelClass(glu::mapGLInternalFormat(spec.renderbufferFormat).type);
126 		switch (m_texChannelClass)
127 		{
128 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
129 				m_colorScale = 1.0f;
130 				break;
131 
132 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
133 				m_colorScale = 100.0f;
134 				break;
135 
136 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
137 				m_colorScale = 100.0f;
138 				break;
139 
140 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
141 				m_colorScale = 100.0f;
142 				break;
143 
144 			default:
145 				DE_ASSERT(false);
146 		}
147 	}
148 	else
149 		DE_ASSERT(false);
150 }
151 
~ReadPixelsTest(void)152 ReadPixelsTest::~ReadPixelsTest (void)
153 {
154 }
155 
init(void)156 void ReadPixelsTest::init (void)
157 {
158 	// Check extensions
159 	if (m_framebuffeType == TestSpec::FRAMEBUFFERTYPE_RENDERBUFFER)
160 	{
161 		bool supported = false;
162 
163 		if (m_renderbufferFormat == GL_RGBA16F
164 			|| m_renderbufferFormat == GL_RG16F)
165 		{
166 			std::istringstream extensions(std::string((const char*)glGetString(GL_EXTENSIONS)));
167 			std::string extension;
168 
169 			while (std::getline(extensions, extension, ' '))
170 			{
171 				if (extension=="GL_EXT_color_buffer_half_float")
172 				{
173 					supported = true;
174 					break;
175 				}
176 				if (extension=="GL_EXT_color_buffer_float")
177 				{
178 					supported = true;
179 					break;
180 				}
181 			}
182 		}
183 		else if (m_renderbufferFormat == GL_RGBA32F
184 				|| m_renderbufferFormat == GL_RG32F
185 				|| m_renderbufferFormat == GL_R11F_G11F_B10F)
186 		{
187 			std::istringstream extensions(std::string((const char*)glGetString(GL_EXTENSIONS)));
188 			std::string extension;
189 
190 			while (std::getline(extensions, extension, ' '))
191 			{
192 				if (extension=="GL_EXT_color_buffer_float")
193 				{
194 					supported = true;
195 					break;
196 				}
197 			}
198 		}
199 		else
200 			supported = true;
201 
202 		if (!supported)
203 			throw tcu::NotSupportedError("Renderbuffer format not supported", "", __FILE__, __LINE__);
204 	}
205 
206 	std::string outtype = "";
207 
208 	if (m_framebuffeType == TestSpec::FRAMEBUFFERTYPE_NATIVE)
209 		outtype = "vec4";
210 	else if (m_framebuffeType == TestSpec::FRAMEBUFFERTYPE_RENDERBUFFER)
211 	{
212 		switch (m_texChannelClass)
213 		{
214 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
215 				outtype = "vec4";
216 				break;
217 
218 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
219 				outtype = "ivec4";
220 				break;
221 
222 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
223 				outtype = "uvec4";
224 				break;
225 
226 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
227 				outtype = "vec4";
228 				break;
229 
230 			default:
231 				DE_ASSERT(false);
232 		}
233 	}
234 	else
235 		DE_ASSERT(false);
236 
237 
238 	const char* vertexShaderSource =
239 	"#version 300 es\n"
240 	"in mediump vec3 a_position;\n"
241 	"in mediump vec4 a_color;\n"
242 	"uniform mediump float u_colorScale;\n"
243 	"out mediump vec4 v_color;\n"
244 	"void main(void)\n"
245 	"{\n"
246 	"\tgl_Position = vec4(a_position, 1.0);\n"
247 	"\tv_color = u_colorScale * a_color;\n"
248 	"}";
249 
250 	stringstream fragmentShaderSource;
251 
252 	fragmentShaderSource <<
253 	"#version 300 es\n"
254 	"in mediump vec4 v_color;\n";
255 
256 
257 	fragmentShaderSource << "layout (location = 0) out mediump " << outtype << " o_color;\n"
258 	"void main(void)\n"
259 	"{\n"
260 	"\to_color = " << outtype << "(v_color);\n"
261 	"}";
262 
263 	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource.str()));
264 
265 	if (!m_program->isOk())
266 	{
267 		m_log << *m_program;
268 		TCU_FAIL("Failed to compile shader");
269 	}
270 }
271 
deinit(void)272 void ReadPixelsTest::deinit (void)
273 {
274 	if (m_program)
275 		delete m_program;
276 	m_program = NULL;
277 }
278 
renderTriangle(const tcu::Vec3 & a,const tcu::Vec3 & b,const tcu::Vec3 & c)279 void ReadPixelsTest::renderTriangle (const tcu::Vec3& a, const tcu::Vec3& b, const tcu::Vec3& c)
280 {
281 	float positions[3*3];
282 
283 	positions[0] = a.x();
284 	positions[1] = a.y();
285 	positions[2] = a.z();
286 
287 	positions[3] = b.x();
288 	positions[4] = b.y();
289 	positions[5] = b.z();
290 
291 	positions[6] = c.x();
292 	positions[7] = c.y();
293 	positions[8] = c.z();
294 
295 	float colors[] = {
296 		1.0f, 0.0f, 0.0f, 1.0f,
297 		0.0f, 1.0f, 0.0f, 1.0f,
298 		0.0f, 0.0f, 1.0f, 1.0f
299 	};
300 
301 	GLU_CHECK_CALL(glUseProgram(m_program->getProgram()));
302 
303 	GLuint coordLoc = (GLuint)-1;
304 	GLuint colorLoc = (GLuint)-1;
305 	GLuint colorScaleLoc = (GLuint)-1;
306 
307 	colorScaleLoc = glGetUniformLocation(m_program->getProgram(), "u_colorScale");
308 	TCU_CHECK(colorScaleLoc != (GLuint)-1);
309 
310 	GLU_CHECK_CALL(glUniform1f(colorScaleLoc, m_colorScale));
311 
312 	coordLoc = glGetAttribLocation(m_program->getProgram(), "a_position");
313 	TCU_CHECK(coordLoc != (GLuint)-1);
314 
315 	colorLoc = glGetAttribLocation(m_program->getProgram(), "a_color");
316 	TCU_CHECK(colorLoc != (GLuint)-1);
317 
318 	GLU_CHECK_CALL(glEnableVertexAttribArray(colorLoc));
319 	GLU_CHECK_CALL(glEnableVertexAttribArray(coordLoc));
320 
321 	GLU_CHECK_CALL(glVertexAttribPointer(coordLoc, 3, GL_FLOAT, GL_FALSE, 0, positions));
322 	GLU_CHECK_CALL(glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, colors));
323 
324 	GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, 3));
325 
326 	GLU_CHECK_CALL(glDisableVertexAttribArray(colorLoc));
327 	GLU_CHECK_CALL(glDisableVertexAttribArray(coordLoc));
328 
329 }
330 
331 
clearColor(float r,float g,float b,float a)332 void ReadPixelsTest::clearColor (float r, float g, float b, float a)
333 {
334 	if (m_framebuffeType == TestSpec::FRAMEBUFFERTYPE_NATIVE)
335 	{
336 		GLU_CHECK_CALL(glClearColor(r, g, b, a));
337 		GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
338 	}
339 	else if (m_framebuffeType == TestSpec::FRAMEBUFFERTYPE_RENDERBUFFER)
340 	{
341 		switch (m_texChannelClass)
342 		{
343 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
344 			{
345 				GLU_CHECK_CALL(glClearColor(r, g, b, a));
346 				GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
347 				break;
348 			}
349 
350 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
351 			{
352 				GLint color[4] = { (GLint)r, (GLint)g, (GLint)b, (GLint)a };
353 
354 				GLU_CHECK_CALL(glClearBufferiv(GL_COLOR, 0, color));
355 				break;
356 			}
357 
358 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
359 			{
360 				GLuint color[4] = { (GLuint)r, (GLuint)g, (GLuint)b, (GLuint)a };
361 
362 				GLU_CHECK_CALL(glClearBufferuiv(GL_COLOR, 0, color));
363 				break;
364 			}
365 
366 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
367 			{
368 				GLfloat color[4] = { (GLfloat)r, (GLfloat)g, (GLfloat)b, (GLfloat)a };
369 
370 				GLU_CHECK_CALL(glClearBufferfv(GL_COLOR, 0, color));
371 				break;
372 			}
373 
374 			default:
375 				DE_ASSERT(false);
376 		}
377 	}
378 	else
379 		DE_ASSERT(false);
380 
381 }
382 
iterate(void)383 TestCase::IterateResult ReadPixelsTest::iterate(void)
384 {
385 	int width				= m_context.getRenderTarget().getWidth();
386 	int height				= m_context.getRenderTarget().getHeight();
387 
388 	GLuint framebuffer	= 0;
389 	GLuint renderbuffer	= 0;
390 
391 	switch (m_framebuffeType)
392 	{
393 		case TestSpec::FRAMEBUFFERTYPE_NATIVE:
394 			GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));
395 			break;
396 
397 		case TestSpec::FRAMEBUFFERTYPE_RENDERBUFFER:
398 		{
399 			GLU_CHECK_CALL(glGenFramebuffers(1, &framebuffer));
400 			GLU_CHECK_CALL(glGenRenderbuffers(1, &renderbuffer));
401 
402 			GLU_CHECK_CALL(glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer));
403 			GLU_CHECK_CALL(glRenderbufferStorage(GL_RENDERBUFFER, m_renderbufferFormat, width, height));
404 
405 			GLU_CHECK_CALL(glBindFramebuffer(GL_FRAMEBUFFER, framebuffer));
406 			GLU_CHECK_CALL(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer));
407 
408 			break;
409 		}
410 
411 		default:
412 			DE_ASSERT(false);
413 	}
414 
415 	clearColor(m_colorScale * 0.4f, m_colorScale * 1.0f, m_colorScale * 0.5f, m_colorScale * 1.0f);
416 
417 	if (m_useColorClears)
418 	{
419 		const int maxClearCount	= 10;
420 		const int minClearCount	= 6;
421 		const int minClearSize	= 15;
422 
423 		int clearCount = m_random.getInt(minClearCount, maxClearCount);
424 
425 		for (int clearNdx = 0; clearNdx < clearCount; clearNdx++)
426 		{
427 			int clearX = m_random.getInt(0, width - minClearSize);
428 			int clearY = m_random.getInt(0, height - minClearSize);
429 
430 			int clearWidth = m_random.getInt(minClearSize, width - clearX);
431 			int clearHeight = m_random.getInt(minClearSize, height - clearY);
432 
433 			float clearRed		= m_colorScale * m_random.getFloat();
434 			float clearGreen	= m_colorScale * m_random.getFloat();
435 			float clearBlue		= m_colorScale * m_random.getFloat();
436 			float clearAlpha	= m_colorScale * (0.5f + 0.5f * m_random.getFloat());
437 
438 			GLU_CHECK_CALL(glEnable(GL_SCISSOR_TEST));
439 			GLU_CHECK_CALL(glScissor(clearX, clearY, clearWidth, clearHeight));
440 
441 			clearColor(clearRed, clearGreen, clearBlue, clearAlpha);
442 		}
443 
444 		GLU_CHECK_CALL(glDisable(GL_SCISSOR_TEST));
445 	}
446 
447 	if (m_renderTriangles)
448 	{
449 		const int minTriangleCount = 4;
450 		const int maxTriangleCount = 10;
451 
452 		int triangleCount = m_random.getInt(minTriangleCount, maxTriangleCount);
453 
454 		for (int triangleNdx = 0; triangleNdx < triangleCount; triangleNdx++)
455 		{
456 			float x1 = 2.0f * m_random.getFloat() - 1.0f;
457 			float y1 = 2.0f * m_random.getFloat() - 1.0f;
458 			float z1 = 2.0f * m_random.getFloat() - 1.0f;
459 
460 			float x2 = 2.0f * m_random.getFloat() - 1.0f;
461 			float y2 = 2.0f * m_random.getFloat() - 1.0f;
462 			float z2 = 2.0f * m_random.getFloat() - 1.0f;
463 
464 			float x3 = 2.0f * m_random.getFloat() - 1.0f;
465 			float y3 = 2.0f * m_random.getFloat() - 1.0f;
466 			float z3 = 2.0f * m_random.getFloat() - 1.0f;
467 
468 			renderTriangle(tcu::Vec3(x1, y1, z1), tcu::Vec3(x2, y2, z2), tcu::Vec3(x3, y3, z3));
469 		}
470 	}
471 
472 	tcu::TextureFormat	readFormat;
473 	GLenum				readPixelsFormat;
474 	GLenum				readPixelsType;
475 	bool				floatCompare;
476 
477 
478 	if (m_framebuffeType == TestSpec::FRAMEBUFFERTYPE_NATIVE)
479 	{
480 		readFormat			= glu::mapGLTransferFormat(GL_RGBA, GL_UNSIGNED_BYTE);
481 		readPixelsFormat	= GL_RGBA;
482 		readPixelsType		= GL_UNSIGNED_BYTE;
483 		floatCompare		= false;
484 	}
485 	else if (m_framebuffeType == TestSpec::FRAMEBUFFERTYPE_RENDERBUFFER)
486 	{
487 		switch (m_texChannelClass)
488 		{
489 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
490 				readFormat			= glu::mapGLTransferFormat(GL_RGBA, GL_UNSIGNED_BYTE);
491 				readPixelsFormat	= GL_RGBA;
492 				readPixelsType		= GL_UNSIGNED_BYTE;
493 				floatCompare		= true;
494 				break;
495 
496 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
497 				readFormat			= glu::mapGLTransferFormat(GL_RGBA_INTEGER, GL_INT);
498 				readPixelsFormat	= GL_RGBA_INTEGER;
499 				readPixelsType		= GL_INT;
500 				floatCompare		= false;
501 				break;
502 
503 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
504 				readFormat			= glu::mapGLTransferFormat(GL_RGBA_INTEGER, GL_UNSIGNED_INT);
505 				readPixelsFormat	= GL_RGBA_INTEGER;
506 				readPixelsType		= GL_UNSIGNED_INT;
507 				floatCompare		= false;
508 				break;
509 
510 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
511 				readFormat			= glu::mapGLTransferFormat(GL_RGBA, GL_FLOAT);
512 				readPixelsFormat	= GL_RGBA;
513 				readPixelsType		= GL_FLOAT;
514 				floatCompare		= true;
515 				break;
516 
517 			default:
518 				DE_ASSERT(false);
519 				// Silence warnings
520 				readFormat			= glu::mapGLTransferFormat(GL_RGBA, GL_FLOAT);
521 				readPixelsFormat	= GL_RGBA;
522 				readPixelsType		= GL_FLOAT;
523 				floatCompare		= true;
524 		}
525 	}
526 	else
527 	{
528 		// Silence warnings
529 		readFormat			= glu::mapGLTransferFormat(GL_RGBA, GL_FLOAT);
530 		readPixelsFormat	= GL_RGBA;
531 		readPixelsType		= GL_FLOAT;
532 		floatCompare		= true;
533 		DE_ASSERT(false);
534 	}
535 
536 	tcu::Texture2D	readRefrence	(readFormat, width, height);
537 	const int		readDataSize	= readRefrence.getWidth() * readRefrence.getHeight() * readFormat.getPixelSize();
538 
539 	readRefrence.allocLevel(0);
540 
541 	GLuint pixelBuffer = (GLuint)-1;
542 
543 	GLU_CHECK_CALL(glGenBuffers(1, &pixelBuffer));
544 	GLU_CHECK_CALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, pixelBuffer));
545 	GLU_CHECK_CALL(glBufferData(GL_PIXEL_PACK_BUFFER, readDataSize, NULL, GL_STREAM_READ));
546 
547 	GLU_CHECK_CALL(glReadPixels(0, 0, width, height, readPixelsFormat, readPixelsType, 0));
548 
549 	const deUint8* bufferData = (const deUint8*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, readDataSize, GL_MAP_READ_BIT);
550 	GLU_CHECK_MSG("glMapBufferRange() failed");
551 
552 	tcu::ConstPixelBufferAccess readResult(readFormat, width, height, 1, bufferData);
553 
554 	GLU_CHECK_CALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));
555 
556 	GLU_CHECK_CALL(glReadPixels(0, 0, width, height, readPixelsFormat, readPixelsType, readRefrence.getLevel(0).getDataPtr()));
557 
558 	if (framebuffer)
559 		GLU_CHECK_CALL(glDeleteFramebuffers(1, &framebuffer));
560 
561 	if (renderbuffer)
562 		GLU_CHECK_CALL(glDeleteRenderbuffers(1, &renderbuffer));
563 
564 
565 	bool isOk = false;
566 
567 	if (floatCompare)
568 		isOk = tcu::floatThresholdCompare(m_log, "Result comparision", "Result of read pixels to memory compared with result of read pixels to buffer", readRefrence.getLevel(0), readResult, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::COMPARE_LOG_RESULT);
569 	else
570 		isOk = tcu::intThresholdCompare(m_log, "Result comparision", "Result of read pixels to memory compared with result of read pixels to buffer", readRefrence.getLevel(0), readResult, tcu::UVec4(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);
571 
572 	GLU_CHECK_CALL(glBindBuffer(GL_PIXEL_PACK_BUFFER, pixelBuffer));
573 	GLU_CHECK_CALL(glUnmapBuffer(GL_PIXEL_PACK_BUFFER));
574 	GLU_CHECK_CALL(glDeleteBuffers(1, &pixelBuffer));
575 
576 	if (isOk)
577 	{
578 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
579 		return STOP;
580 	}
581 	else
582 	{
583 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
584 		return STOP;
585 	}
586 }
587 
588 } // anonymous
589 
PixelBufferObjectTests(Context & context)590 PixelBufferObjectTests::PixelBufferObjectTests (Context& context)
591 	: TestCaseGroup (context, "pbo", "Pixel buffer objects tests")
592 {
593 }
594 
~PixelBufferObjectTests(void)595 PixelBufferObjectTests::~PixelBufferObjectTests (void)
596 {
597 }
598 
init(void)599 void PixelBufferObjectTests::init (void)
600 {
601 	TestCaseGroup* nativeFramebufferGroup = new TestCaseGroup(m_context, "native", "Tests with reading from native framebuffer");
602 
603 	ReadPixelsTest::TestSpec nativeFramebufferTests[] = {
604 		{
605 			"clears",
606 			"Simple read pixels test with color clears",
607 			true,
608 			false,
609 			ReadPixelsTest::TestSpec::FRAMEBUFFERTYPE_NATIVE,
610 			GL_NONE
611 		},
612 		{
613 			"triangles",
614 			"Simple read pixels test rendering triangles",
615 			false,
616 			true,
617 			ReadPixelsTest::TestSpec::FRAMEBUFFERTYPE_NATIVE,
618 			GL_NONE
619 		}
620 	};
621 
622 	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(nativeFramebufferTests); testNdx++)
623 	{
624 		nativeFramebufferGroup->addChild(new ReadPixelsTest(m_context, nativeFramebufferTests[testNdx]));
625 	}
626 
627 	addChild(nativeFramebufferGroup);
628 
629 	TestCaseGroup* renderbufferGroup = new TestCaseGroup(m_context, "renderbuffer", "Tests with reading from renderbuffer");
630 
631 	GLenum renderbufferFormats[] = {
632 		GL_RGBA8,
633 		GL_RGBA8I,
634 		GL_RGBA8UI,
635 		GL_RGBA16F,
636 		GL_RGBA16I,
637 		GL_RGBA16UI,
638 		GL_RGBA32F,
639 		GL_RGBA32I,
640 		GL_RGBA32UI,
641 
642 		GL_SRGB8_ALPHA8,
643 		GL_RGB10_A2,
644 		GL_RGB10_A2UI,
645 		GL_RGBA4,
646 		GL_RGB5_A1,
647 
648 		GL_RGB8,
649 		GL_RGB565,
650 
651 		GL_R11F_G11F_B10F,
652 
653 		GL_RG8,
654 		GL_RG8I,
655 		GL_RG8UI,
656 		GL_RG16F,
657 		GL_RG16I,
658 		GL_RG16UI,
659 		GL_RG32F,
660 		GL_RG32I,
661 		GL_RG32UI
662 	};
663 
664 	const char* renderbufferFormatsStr[] = {
665 		"rgba8",
666 		"rgba8i",
667 		"rgba8ui",
668 		"rgba16f",
669 		"rgba16i",
670 		"rgba16ui",
671 		"rgba32f",
672 		"rgba32i",
673 		"rgba32ui",
674 
675 		"srgb8_alpha8",
676 		"rgb10_a2",
677 		"rgb10_a2ui",
678 		"rgba4",
679 		"rgb5_a1",
680 
681 		"rgb8",
682 		"rgb565",
683 
684 		"r11f_g11f_b10f",
685 
686 		"rg8",
687 		"rg8i",
688 		"rg8ui",
689 		"rg16f",
690 		"rg16i",
691 		"rg16ui",
692 		"rg32f",
693 		"rg32i",
694 		"rg32ui"
695 	};
696 
697 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(renderbufferFormatsStr) == DE_LENGTH_OF_ARRAY(renderbufferFormats));
698 
699 	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(renderbufferFormats); formatNdx++)
700 	{
701 		for (int trianglesClears = 0; trianglesClears < 2; trianglesClears++)
702 		{
703 			ReadPixelsTest::TestSpec testSpec;
704 
705 			testSpec.name					= string(renderbufferFormatsStr [formatNdx]) + "_" + (trianglesClears == 0 ? "triangles" : "clears"),
706 			testSpec.description			= testSpec.name;
707 			testSpec.useColorClear			= trianglesClears == 1,
708 			testSpec.renderTriangles		= trianglesClears == 0,
709 			testSpec.framebufferType		= ReadPixelsTest::TestSpec::FRAMEBUFFERTYPE_RENDERBUFFER,
710 			testSpec.renderbufferFormat		= renderbufferFormats[formatNdx];
711 
712 			renderbufferGroup->addChild(new ReadPixelsTest(m_context, testSpec));
713 		}
714 	}
715 
716 	addChild(renderbufferGroup);
717 }
718 
719 } // Functional
720 } // gles3
721 } // deqp
722