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