1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL 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 Test EGL_SWAP_BEHAVIOR_PRESERVED_BIT.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglPreservingSwapTests.hpp"
25 
26 #include "tcuImageCompare.hpp"
27 #include "tcuTestLog.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuTextureUtil.hpp"
30 
31 #include "egluNativeWindow.hpp"
32 #include "egluUtil.hpp"
33 
34 #include "eglwLibrary.hpp"
35 #include "eglwEnums.hpp"
36 
37 #include "gluDefs.hpp"
38 #include "gluRenderContext.hpp"
39 #include "gluShaderProgram.hpp"
40 
41 #include "glwDefs.hpp"
42 #include "glwEnums.hpp"
43 #include "glwFunctions.hpp"
44 
45 #include "deRandom.hpp"
46 
47 #include "deString.h"
48 
49 #include <vector>
50 #include <string>
51 
52 using std::vector;
53 using std::string;
54 
55 using namespace eglw;
56 
57 namespace deqp
58 {
59 namespace egl
60 {
61 
62 namespace
63 {
64 class GLES2Program;
65 class ReferenceProgram;
66 
67 class PreservingSwapTest : public TestCase
68 {
69 public:
70 	enum DrawType
71 	{
72 		DRAWTYPE_NONE = 0,
73 		DRAWTYPE_GLES2_CLEAR,
74 		DRAWTYPE_GLES2_RENDER
75 	};
76 
77 					PreservingSwapTest	(EglTestContext& eglTestCtx, bool preserveColorbuffer, bool readPixelsBeforeSwap, DrawType preSwapDrawType, DrawType postSwapDrawType, const char* name, const char* description);
78 					~PreservingSwapTest	(void);
79 
80 	void			init				(void);
81 	void			deinit				(void);
82 	IterateResult	iterate				(void);
83 
84 private:
85 	const int					m_seed;
86 	const bool					m_preserveColorbuffer;
87 	const bool					m_readPixelsBeforeSwap;
88 	const DrawType				m_preSwapDrawType;
89 	const DrawType				m_postSwapDrawType;
90 
91 	EGLDisplay					m_eglDisplay;
92 	eglu::NativeWindow*			m_window;
93 	EGLSurface					m_eglSurface;
94 	EGLConfig					m_eglConfig;
95 	EGLContext					m_eglContext;
96 	glw::Functions				m_gl;
97 
98 	GLES2Program*				m_gles2Program;
99 	ReferenceProgram*			m_refProgram;
100 
101 	void initEGLSurface	(EGLConfig config);
102 	void initEGLContext (EGLConfig config);
103 };
104 
105 class GLES2Program
106 {
107 public:
108 					GLES2Program	(const glw::Functions& gl);
109 					~GLES2Program	(void);
110 
111 	void			render			(int width, int height, float x1, float y1, float x2, float y2, PreservingSwapTest::DrawType drawType);
112 
113 private:
114 	const glw::Functions&	m_gl;
115 	glu::ShaderProgram		m_glProgram;
116 	glw::GLuint				m_coordLoc;
117 	glw::GLuint				m_colorLoc;
118 
119 	GLES2Program&			operator=		(const GLES2Program&);
120 							GLES2Program	(const GLES2Program&);
121 };
122 
getSources(void)123 static glu::ProgramSources getSources (void)
124 {
125 	const char* const vertexShaderSource =
126 		"attribute mediump vec4 a_pos;\n"
127 		"attribute mediump vec4 a_color;\n"
128 		"varying mediump vec4 v_color;\n"
129 		"void main(void)\n"
130 		"{\n"
131 		"\tv_color = a_color;\n"
132 		"\tgl_Position = a_pos;\n"
133 		"}";
134 
135 	const char* const fragmentShaderSource =
136 		"varying mediump vec4 v_color;\n"
137 		"void main(void)\n"
138 		"{\n"
139 		"\tgl_FragColor = v_color;\n"
140 		"}";
141 
142 	return glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource);
143 }
144 
GLES2Program(const glw::Functions & gl)145 GLES2Program::GLES2Program (const glw::Functions& gl)
146 	: m_gl			(gl)
147 	, m_glProgram	(gl, getSources())
148 	, m_coordLoc	((glw::GLuint)-1)
149 	, m_colorLoc	((glw::GLuint)-1)
150 {
151 	m_colorLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_color");
152 	m_coordLoc = m_gl.getAttribLocation(m_glProgram.getProgram(), "a_pos");
153 	GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to get attribute locations");
154 }
155 
~GLES2Program(void)156 GLES2Program::~GLES2Program (void)
157 {
158 }
159 
render(int width,int height,float x1,float y1,float x2,float y2,PreservingSwapTest::DrawType drawType)160 void GLES2Program::render (int width, int height, float x1, float y1, float x2, float y2, PreservingSwapTest::DrawType drawType)
161 {
162 	if (drawType == PreservingSwapTest::DRAWTYPE_GLES2_RENDER)
163 	{
164 		const glw::GLfloat coords[] =
165 		{
166 			x1, y1, 0.0f, 1.0f,
167 			x1, y2, 0.0f, 1.0f,
168 			x2, y2, 0.0f, 1.0f,
169 
170 			x2, y2, 0.0f, 1.0f,
171 			x2, y1, 0.0f, 1.0f,
172 			x1, y1, 0.0f, 1.0f
173 		};
174 
175 		const glw::GLubyte colors[] =
176 		{
177 			127,	127,	127,	255,
178 			127,	127,	127,	255,
179 			127,	127,	127,	255,
180 
181 			127,	127,	127,	255,
182 			127,	127,	127,	255,
183 			127,	127,	127,	255
184 		};
185 
186 		m_gl.useProgram(m_glProgram.getProgram());
187 		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
188 
189 		m_gl.enableVertexAttribArray(m_coordLoc);
190 		m_gl.enableVertexAttribArray(m_colorLoc);
191 		GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to enable attributes");
192 
193 		m_gl.vertexAttribPointer(m_coordLoc, 4, GL_FLOAT, GL_FALSE, 0, coords);
194 		m_gl.vertexAttribPointer(m_colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors);
195 		GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to set attribute pointers");
196 
197 		m_gl.drawArrays(GL_TRIANGLES, 0, 6);
198 		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDrawArrays() failed");
199 
200 		m_gl.disableVertexAttribArray(m_coordLoc);
201 		m_gl.disableVertexAttribArray(m_colorLoc);
202 		GLU_EXPECT_NO_ERROR(m_gl.getError(), "Failed to disable attributes");
203 
204 		m_gl.useProgram(0);
205 		GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUseProgram() failed");
206 	}
207 	else if (drawType == PreservingSwapTest::DRAWTYPE_GLES2_CLEAR)
208 	{
209 		const int ox	= width/2;
210 		const int oy	= height/2;
211 
212 		const int px	= width;
213 		const int py	= height;
214 
215 		const int x1i	= (int)((px/2.0f) * x1 + ox);
216 		const int y1i	= (int)((py/2.0f) * y1 + oy);
217 
218 		const int x2i	= (int)((px/2.0f) * x2 + ox);
219 		const int y2i	= (int)((py/2.0f) * y2 + oy);
220 
221 		m_gl.enable(GL_SCISSOR_TEST);
222 		m_gl.scissor(x1i, y1i, x2i-x1i, y2i-y1i);
223 		m_gl.clearColor(0.5f, 0.5f, 0.5f, 1.0f);
224 		m_gl.clear(GL_COLOR_BUFFER_BIT);
225 		m_gl.disable(GL_SCISSOR_TEST);
226 	}
227 	else
228 		DE_ASSERT(false);
229 }
230 
231 class ReferenceProgram
232 {
233 public:
234 			ReferenceProgram	(void);
235 			~ReferenceProgram	(void);
236 
237 	void	render				(tcu::Surface* target, float x1, float y1, float x2, float y2, PreservingSwapTest::DrawType drawType);
238 
239 private:
240 						ReferenceProgram	(const ReferenceProgram&);
241 	ReferenceProgram&	operator=			(const ReferenceProgram&);
242 };
243 
ReferenceProgram(void)244 ReferenceProgram::ReferenceProgram (void)
245 {
246 }
247 
~ReferenceProgram(void)248 ReferenceProgram::~ReferenceProgram (void)
249 {
250 }
251 
render(tcu::Surface * target,float x1,float y1,float x2,float y2,PreservingSwapTest::DrawType drawType)252 void ReferenceProgram::render (tcu::Surface* target, float x1, float y1, float x2, float y2, PreservingSwapTest::DrawType drawType)
253 {
254 	if (drawType == PreservingSwapTest::DRAWTYPE_GLES2_RENDER || drawType == PreservingSwapTest::DRAWTYPE_GLES2_CLEAR)
255 	{
256 		const int ox	= target->getWidth()/2;
257 		const int oy	= target->getHeight()/2;
258 
259 		const int px	= target->getWidth();
260 		const int py	= target->getHeight();
261 
262 		const int x1i	= (int)((px/2.0) * x1 + ox);
263 		const int y1i	= (int)((py/2.0) * y1 + oy);
264 
265 		const int x2i	= (int)((px/2.0) * x2 + ox);
266 		const int y2i	= (int)((py/2.0) * y2 + oy);
267 
268 		const tcu::RGBA	color(127, 127, 127, 255);
269 
270 		for (int y = y1i; y <= y2i; y++)
271 		{
272 			for (int x = x1i; x <= x2i; x++)
273 				target->setPixel(x, y, color);
274 		}
275 	}
276 	else
277 		DE_ASSERT(false);
278 }
279 
PreservingSwapTest(EglTestContext & eglTestCtx,bool preserveColorbuffer,bool readPixelsBeforeSwap,DrawType preSwapDrawType,DrawType postSwapDrawType,const char * name,const char * description)280 PreservingSwapTest::PreservingSwapTest (EglTestContext& eglTestCtx, bool preserveColorbuffer, bool readPixelsBeforeSwap, DrawType preSwapDrawType, DrawType postSwapDrawType, const char* name, const char* description)
281 	: TestCase					(eglTestCtx, name, description)
282 	, m_seed					(deStringHash(name))
283 	, m_preserveColorbuffer		(preserveColorbuffer)
284 	, m_readPixelsBeforeSwap	(readPixelsBeforeSwap)
285 	, m_preSwapDrawType			(preSwapDrawType)
286 	, m_postSwapDrawType		(postSwapDrawType)
287 	, m_eglDisplay				(EGL_NO_DISPLAY)
288 	, m_window					(DE_NULL)
289 	, m_eglSurface				(EGL_NO_SURFACE)
290 	, m_eglContext				(EGL_NO_CONTEXT)
291 	, m_gles2Program			(DE_NULL)
292 	, m_refProgram				(DE_NULL)
293 {
294 }
295 
~PreservingSwapTest(void)296 PreservingSwapTest::~PreservingSwapTest (void)
297 {
298 	deinit();
299 }
300 
getEGLConfig(const Library & egl,EGLDisplay eglDisplay,bool preserveColorbuffer)301 EGLConfig getEGLConfig (const Library& egl, EGLDisplay eglDisplay, bool preserveColorbuffer)
302 {
303 	const EGLint attribList[] =
304 	{
305 		EGL_SURFACE_TYPE,		EGL_WINDOW_BIT | (preserveColorbuffer ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
306 		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
307 		EGL_NONE
308 	};
309 
310 	return eglu::chooseSingleConfig(egl, eglDisplay, &attribList[0]);
311 }
312 
clearColorScreen(const glw::Functions & gl,float red,float green,float blue,float alpha)313 void clearColorScreen (const glw::Functions& gl, float red, float green, float blue, float alpha)
314 {
315 	gl.clearColor(red, green, blue, alpha);
316 	gl.clear(GL_COLOR_BUFFER_BIT);
317 }
318 
clearColorReference(tcu::Surface * ref,float red,float green,float blue,float alpha)319 void clearColorReference (tcu::Surface* ref, float red, float green, float blue, float alpha)
320 {
321 	tcu::clear(ref->getAccess(), tcu::Vec4(red, green, blue, alpha));
322 }
323 
readPixels(const glw::Functions & gl,tcu::Surface * screen)324 void readPixels (const glw::Functions& gl, tcu::Surface* screen)
325 {
326 	gl.readPixels(0, 0, screen->getWidth(), screen->getHeight(),  GL_RGBA, GL_UNSIGNED_BYTE, screen->getAccess().getDataPtr());
327 }
328 
initEGLSurface(EGLConfig config)329 void PreservingSwapTest::initEGLSurface (EGLConfig config)
330 {
331 	const eglu::NativeWindowFactory&	factory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
332 
333 	m_window		= factory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_eglDisplay, config, DE_NULL, eglu::WindowParams(480, 480, eglu::parseWindowVisibility(m_testCtx.getCommandLine())));
334 	m_eglSurface	= eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *m_window, m_eglDisplay, config, DE_NULL);
335 }
336 
initEGLContext(EGLConfig config)337 void PreservingSwapTest::initEGLContext (EGLConfig config)
338 {
339 	const Library&	egl				= m_eglTestCtx.getLibrary();
340 	const EGLint	attribList[]	=
341 	{
342 		EGL_CONTEXT_CLIENT_VERSION, 2,
343 		EGL_NONE
344 	};
345 
346 	egl.bindAPI(EGL_OPENGL_ES_API);
347 	m_eglContext = egl.createContext(m_eglDisplay, config, EGL_NO_CONTEXT, attribList);
348 	EGLU_CHECK_MSG(egl, "eglCreateContext");
349 
350 	DE_ASSERT(m_eglSurface != EGL_NO_SURFACE);
351 	egl.makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
352 	EGLU_CHECK_MSG(egl, "eglMakeCurrent");
353 }
354 
init(void)355 void PreservingSwapTest::init (void)
356 {
357 	m_eglDisplay	= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
358 	m_eglConfig		= getEGLConfig(m_eglTestCtx.getLibrary(), m_eglDisplay, m_preserveColorbuffer);
359 
360 	if (m_eglConfig == DE_NULL)
361 		TCU_THROW(NotSupportedError, "No supported config found");
362 
363 	initEGLSurface(m_eglConfig);
364 	initEGLContext(m_eglConfig);
365 
366 	m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2,0));
367 
368 	m_gles2Program	= new GLES2Program(m_gl);
369 	m_refProgram	= new ReferenceProgram();
370 }
371 
deinit(void)372 void PreservingSwapTest::deinit (void)
373 {
374 	const Library& egl = m_eglTestCtx.getLibrary();
375 
376 	delete m_refProgram;
377 	m_refProgram = DE_NULL;
378 
379 	delete m_gles2Program;
380 	m_gles2Program = DE_NULL;
381 
382 	if (m_eglContext != EGL_NO_CONTEXT)
383 	{
384 		egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
385 		egl.destroyContext(m_eglDisplay, m_eglContext);
386 		m_eglContext = EGL_NO_CONTEXT;
387 	}
388 
389 	if (m_eglSurface != EGL_NO_SURFACE)
390 	{
391 		egl.destroySurface(m_eglDisplay, m_eglSurface);
392 		m_eglSurface = EGL_NO_SURFACE;
393 	}
394 
395 	if (m_eglDisplay != EGL_NO_DISPLAY)
396 	{
397 		egl.terminate(m_eglDisplay);
398 		m_eglDisplay = EGL_NO_DISPLAY;
399 	}
400 
401 	delete m_window;
402 	m_window = DE_NULL;
403 }
404 
compareToReference(tcu::TestLog & log,const char * name,const char * description,const tcu::Surface & reference,const tcu::Surface & screen,int x,int y,int width,int height)405 bool compareToReference (tcu::TestLog& log, const char* name, const char* description, const tcu::Surface& reference, const tcu::Surface& screen, int x, int y, int width, int height)
406 {
407 	return tcu::fuzzyCompare(log, name, description,
408 							 getSubregion(reference.getAccess(), x, y, width, height),
409 							 getSubregion(screen.getAccess(), x, y, width, height),
410 							 0.05f, tcu::COMPARE_LOG_RESULT);
411 }
412 
comparePreAndPostSwapFramebuffers(tcu::TestLog & log,const tcu::Surface & preSwap,const tcu::Surface & postSwap)413 bool comparePreAndPostSwapFramebuffers (tcu::TestLog& log, const tcu::Surface& preSwap, const tcu::Surface& postSwap)
414 {
415 	return tcu::pixelThresholdCompare(log, "Pre- / Post framebuffer compare", "Compare pre- and post-swap framebuffers", preSwap, postSwap, tcu::RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);
416 }
417 
iterate(void)418 TestCase::IterateResult PreservingSwapTest::iterate (void)
419 {
420 	const Library&	egl				= m_eglTestCtx.getLibrary();
421 	tcu::TestLog&	log				= m_testCtx.getLog();
422 	de::Random		rnd(m_seed);
423 
424 	const int		width			= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_WIDTH);
425 	const int		height			= eglu::querySurfaceInt(egl, m_eglDisplay, m_eglSurface, EGL_HEIGHT);
426 
427 	const float		clearRed		= rnd.getFloat();
428 	const float		clearGreen		= rnd.getFloat();
429 	const float		clearBlue		= rnd.getFloat();
430 	const float		clearAlpha		= 1.0f;
431 
432 	const float		preSwapX1		= -0.9f * rnd.getFloat();
433 	const float		preSwapY1		= -0.9f * rnd.getFloat();
434 	const float		preSwapX2		= 0.9f * rnd.getFloat();
435 	const float		preSwapY2		= 0.9f * rnd.getFloat();
436 
437 	const float		postSwapX1		= -0.9f * rnd.getFloat();
438 	const float		postSwapY1		= -0.9f * rnd.getFloat();
439 	const float		postSwapX2		= 0.9f * rnd.getFloat();
440 	const float		postSwapY2		= 0.9f * rnd.getFloat();
441 
442 	tcu::Surface	postSwapFramebufferReference(width, height);
443 	tcu::Surface	preSwapFramebufferReference(width, height);
444 
445 	tcu::Surface	postSwapFramebuffer(width, height);
446 	tcu::Surface	preSwapFramebuffer(width, height);
447 
448 	if (m_preserveColorbuffer)
449 		EGLU_CHECK_CALL(egl, surfaceAttrib(m_eglDisplay, m_eglSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED));
450 
451 	EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
452 
453 	clearColorScreen(m_gl, clearRed, clearGreen, clearBlue, clearAlpha);
454 
455 	if (m_readPixelsBeforeSwap)
456 		clearColorReference(&preSwapFramebufferReference, clearRed, clearGreen, clearBlue, clearAlpha);
457 
458 	clearColorReference(&postSwapFramebufferReference, clearRed, clearGreen, clearBlue, clearAlpha);
459 
460 	if (m_preSwapDrawType != DRAWTYPE_NONE)
461 	{
462 		m_gles2Program->render(width, height, preSwapX1, preSwapY1, preSwapX2, preSwapY2, m_preSwapDrawType);
463 		m_refProgram->render(&postSwapFramebufferReference, preSwapX1, preSwapY1, preSwapX2, preSwapY2, m_preSwapDrawType);
464 	}
465 
466 	if (m_readPixelsBeforeSwap)
467 	{
468 		if (m_preSwapDrawType != DRAWTYPE_NONE)
469 			m_refProgram->render(&preSwapFramebufferReference, preSwapX1, preSwapY1, preSwapX2, preSwapY2, m_preSwapDrawType);
470 
471 		readPixels(m_gl, &preSwapFramebuffer);
472 	}
473 
474 	EGLU_CHECK_CALL(egl, swapBuffers(m_eglDisplay, m_eglSurface));
475 
476 	if (m_postSwapDrawType != DRAWTYPE_NONE)
477 	{
478 		m_refProgram->render(&postSwapFramebufferReference, postSwapX1, postSwapY1, postSwapX2, postSwapY2, m_postSwapDrawType);
479 		m_gles2Program->render(width, height, postSwapX1, postSwapY1, postSwapX2, postSwapY2, m_postSwapDrawType);
480 	}
481 
482 	readPixels(m_gl, &postSwapFramebuffer);
483 
484 	bool isOk = true;
485 
486 	if (m_preserveColorbuffer)
487 	{
488 		if (m_readPixelsBeforeSwap)
489 			isOk = isOk && compareToReference(log, "Compare pre-swap framebuffer to reference", "Compare pre-swap framebuffer to reference", preSwapFramebufferReference, preSwapFramebuffer, 0, 0, width, height);
490 
491 		isOk = isOk && compareToReference(log, "Compare post-swap framebuffer to reference", "Compare post-swap framebuffer to reference", postSwapFramebufferReference, postSwapFramebuffer, 0, 0, width, height);
492 
493 		if (m_readPixelsBeforeSwap && m_postSwapDrawType == PreservingSwapTest::DRAWTYPE_NONE)
494 			isOk = isOk && comparePreAndPostSwapFramebuffers(log, preSwapFramebuffer, postSwapFramebuffer);
495 	}
496 	else
497 	{
498 		const int ox	= width/2;
499 		const int oy	= height/2;
500 
501 		const int px	= width;
502 		const int py	= height;
503 
504 		const int x1i	= (int)((px/2.0f) * postSwapX1 + ox);
505 		const int y1i	= (int)((py/2.0f) * postSwapY1 + oy);
506 
507 		const int x2i	= (int)((px/2.0f) * postSwapX2 + ox);
508 		const int y2i	= (int)((py/2.0f) * postSwapY2 + oy);
509 
510 		if (m_readPixelsBeforeSwap)
511 			isOk = isOk && compareToReference(log, "Compare pre-swap framebuffer to reference", "Compare pre-swap framebuffer to reference", preSwapFramebufferReference, preSwapFramebuffer, 0, 0, width, height);
512 
513 		DE_ASSERT(m_postSwapDrawType != DRAWTYPE_NONE);
514 		isOk = isOk && compareToReference(log, "Compare valid are of post-swap framebuffer to reference", "Compare valid area of post-swap framebuffer to reference", postSwapFramebufferReference, postSwapFramebuffer, x1i, y1i, x2i - x1i, y2i - y1i);
515 	}
516 
517 	if (isOk)
518 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
519 	else
520 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
521 
522 	return STOP;
523 }
524 
generateTestName(PreservingSwapTest::DrawType preSwapDrawType,PreservingSwapTest::DrawType postSwapDrawType)525 string generateTestName (PreservingSwapTest::DrawType preSwapDrawType, PreservingSwapTest::DrawType postSwapDrawType)
526 {
527 	std::ostringstream stream;
528 
529 	if (preSwapDrawType == PreservingSwapTest::DRAWTYPE_NONE && postSwapDrawType == PreservingSwapTest::DRAWTYPE_NONE)
530 		stream << "no_draw";
531 	else
532 	{
533 		switch (preSwapDrawType)
534 		{
535 			case PreservingSwapTest::DRAWTYPE_NONE:
536 				// Do nothing
537 				break;
538 
539 			case PreservingSwapTest::DRAWTYPE_GLES2_RENDER:
540 				stream << "pre_render";
541 				break;
542 
543 			case PreservingSwapTest::DRAWTYPE_GLES2_CLEAR:
544 				stream << "pre_clear";
545 				break;
546 
547 			default:
548 				DE_ASSERT(false);
549 		}
550 
551 		if (preSwapDrawType != PreservingSwapTest::DRAWTYPE_NONE && postSwapDrawType != PreservingSwapTest::DRAWTYPE_NONE)
552 			stream << "_";
553 
554 		switch (postSwapDrawType)
555 		{
556 			case PreservingSwapTest::DRAWTYPE_NONE:
557 				// Do nothing
558 				break;
559 
560 			case PreservingSwapTest::DRAWTYPE_GLES2_RENDER:
561 				stream << "post_render";
562 				break;
563 
564 			case PreservingSwapTest::DRAWTYPE_GLES2_CLEAR:
565 				stream << "post_clear";
566 				break;
567 
568 			default:
569 				DE_ASSERT(false);
570 		}
571 	}
572 
573 	return stream.str();
574 }
575 
576 } // anonymous
577 
PreservingSwapTests(EglTestContext & eglTestCtx)578 PreservingSwapTests::PreservingSwapTests (EglTestContext& eglTestCtx)
579 	: TestCaseGroup(eglTestCtx, "preserve_swap", "Color buffer preserving swap tests")
580 {
581 }
582 
init(void)583 void PreservingSwapTests::init (void)
584 {
585 	const PreservingSwapTest::DrawType preSwapDrawTypes[] =
586 	{
587 		PreservingSwapTest::DRAWTYPE_NONE,
588 		PreservingSwapTest::DRAWTYPE_GLES2_CLEAR,
589 		PreservingSwapTest::DRAWTYPE_GLES2_RENDER
590 	};
591 
592 	const PreservingSwapTest::DrawType postSwapDrawTypes[] =
593 	{
594 		PreservingSwapTest::DRAWTYPE_NONE,
595 		PreservingSwapTest::DRAWTYPE_GLES2_CLEAR,
596 		PreservingSwapTest::DRAWTYPE_GLES2_RENDER
597 	};
598 
599 	for (int preserveNdx = 0; preserveNdx < 2; preserveNdx++)
600 	{
601 		const bool				preserve		= (preserveNdx == 0);
602 		TestCaseGroup* const	preserveGroup	= new TestCaseGroup(m_eglTestCtx, (preserve ? "preserve" : "no_preserve"), "");
603 
604 		for (int readPixelsNdx = 0; readPixelsNdx < 2; readPixelsNdx++)
605 		{
606 			const bool				readPixelsBeforeSwap		= (readPixelsNdx == 1);
607 			TestCaseGroup* const	readPixelsBeforeSwapGroup	= new TestCaseGroup(m_eglTestCtx, (readPixelsBeforeSwap ? "read_before_swap" : "no_read_before_swap"), "");
608 
609 			for (int preSwapDrawTypeNdx = 0; preSwapDrawTypeNdx < DE_LENGTH_OF_ARRAY(preSwapDrawTypes); preSwapDrawTypeNdx++)
610 			{
611 				const PreservingSwapTest::DrawType preSwapDrawType = preSwapDrawTypes[preSwapDrawTypeNdx];
612 
613 				for (int postSwapDrawTypeNdx = 0; postSwapDrawTypeNdx < DE_LENGTH_OF_ARRAY(postSwapDrawTypes); postSwapDrawTypeNdx++)
614 				{
615 					const PreservingSwapTest::DrawType postSwapDrawType = postSwapDrawTypes[postSwapDrawTypeNdx];
616 
617 					// If not preserving and rendering after swap, then there is nothing to verify
618 					if (!preserve && postSwapDrawType == PreservingSwapTest::DRAWTYPE_NONE)
619 						continue;
620 
621 					const std::string name = generateTestName(preSwapDrawType, postSwapDrawType);
622 
623 					readPixelsBeforeSwapGroup->addChild(new PreservingSwapTest(m_eglTestCtx, preserve, readPixelsBeforeSwap, preSwapDrawType, postSwapDrawType, name.c_str(), ""));
624 				}
625 			}
626 
627 			preserveGroup->addChild(readPixelsBeforeSwapGroup);
628 		}
629 
630 		addChild(preserveGroup);
631 	}
632 }
633 
634 } // egl
635 } // deqp
636