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 Tests for mapping client coordinates to native surface coordinates
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "teglNativeCoordMappingTests.hpp"
     25 
     26 #include "teglSimpleConfigCase.hpp"
     27 
     28 #include "tcuSurface.hpp"
     29 #include "tcuTexture.hpp"
     30 
     31 #include "egluNativeDisplay.hpp"
     32 #include "egluNativeWindow.hpp"
     33 #include "egluNativePixmap.hpp"
     34 #include "egluUnique.hpp"
     35 #include "egluUtil.hpp"
     36 
     37 #include "eglwLibrary.hpp"
     38 #include "eglwEnums.hpp"
     39 
     40 #include "gluDefs.hpp"
     41 #include "glwFunctions.hpp"
     42 #include "glwEnums.hpp"
     43 
     44 #include "tcuImageCompare.hpp"
     45 #include "tcuTestLog.hpp"
     46 #include "tcuTexture.hpp"
     47 #include "tcuTextureUtil.hpp"
     48 
     49 #include "deUniquePtr.hpp"
     50 #include "deStringUtil.hpp"
     51 
     52 #include "deThread.hpp"
     53 #include "deMath.h"
     54 
     55 #include <vector>
     56 #include <string>
     57 
     58 using tcu::TestLog;
     59 using std::vector;
     60 using std::string;
     61 
     62 using namespace eglw;
     63 
     64 namespace deqp
     65 {
     66 namespace egl
     67 {
     68 namespace
     69 {
     70 
     71 EGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config)
     72 {
     73 	EGLContext		context			= EGL_NO_CONTEXT;
     74 	const EGLint	attribList[]	=
     75 	{
     76 		EGL_CONTEXT_CLIENT_VERSION, 2,
     77 		EGL_NONE
     78 	};
     79 
     80 	EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
     81 
     82 	context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList);
     83 	EGLU_CHECK_MSG(egl, "eglCreateContext() failed");
     84 	TCU_CHECK(context);
     85 
     86 	return context;
     87 }
     88 
     89 deUint32 createGLES2Program (const glw::Functions& gl, TestLog& log)
     90 {
     91 	const char* const vertexShaderSource =
     92 	"attribute highp vec2 a_pos;\n"
     93 	"void main (void)\n"
     94 	"{\n"
     95 	"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
     96 	"}";
     97 
     98 	const char* const fragmentShaderSource =
     99 	"void main (void)\n"
    100 	"{\n"
    101 	"\tgl_FragColor = vec4(1.0);\n"
    102 	"}";
    103 
    104 	deUint32	program			= 0;
    105 	deUint32	vertexShader	= 0;
    106 	deUint32	fragmentShader	= 0;
    107 
    108 	deInt32		vertexCompileStatus;
    109 	string		vertexInfoLog;
    110 	deInt32		fragmentCompileStatus;
    111 	string		fragmentInfoLog;
    112 	deInt32		linkStatus;
    113 	string		programInfoLog;
    114 
    115 	try
    116 	{
    117 		program			= gl.createProgram();
    118 		vertexShader	= gl.createShader(GL_VERTEX_SHADER);
    119 		fragmentShader	= gl.createShader(GL_FRAGMENT_SHADER);
    120 
    121 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");
    122 
    123 		gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
    124 		gl.compileShader(vertexShader);
    125 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");
    126 
    127 		gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
    128 		gl.compileShader(fragmentShader);
    129 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");
    130 
    131 		{
    132 			deInt32		infoLogLength = 0;
    133 
    134 			gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
    135 			gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
    136 
    137 			vertexInfoLog.resize(infoLogLength, '\0');
    138 
    139 			gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0]));
    140 			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");
    141 
    142 			vertexInfoLog.resize(infoLogLength);
    143 		}
    144 
    145 		{
    146 			deInt32		infoLogLength = 0;
    147 
    148 			gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
    149 			gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
    150 
    151 			fragmentInfoLog.resize(infoLogLength, '\0');
    152 
    153 			gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0]));
    154 			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");
    155 
    156 			fragmentInfoLog.resize(infoLogLength);
    157 		}
    158 
    159 		gl.attachShader(program, vertexShader);
    160 		gl.attachShader(program, fragmentShader);
    161 		gl.linkProgram(program);
    162 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");
    163 
    164 		{
    165 			deInt32		infoLogLength = 0;
    166 
    167 			gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
    168 			gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
    169 
    170 			programInfoLog.resize(infoLogLength, '\0');
    171 
    172 			gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
    173 			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");
    174 
    175 			programInfoLog.resize(infoLogLength);
    176 		}
    177 
    178 		if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
    179 		{
    180 
    181 			log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());
    182 
    183 			log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
    184 			log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog);
    185 
    186 			log.endShaderProgram();
    187 		}
    188 
    189 		gl.deleteShader(vertexShader);
    190 		gl.deleteShader(fragmentShader);
    191 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");
    192 
    193 		TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
    194 	}
    195 	catch (...)
    196 	{
    197 		if (program)
    198 			gl.deleteProgram(program);
    199 
    200 		if (vertexShader)
    201 			gl.deleteShader(vertexShader);
    202 
    203 		if (fragmentShader)
    204 			gl.deleteShader(fragmentShader);
    205 
    206 		throw;
    207 	}
    208 
    209 	return program;
    210 }
    211 
    212 void clear (const glw::Functions& gl, const tcu::Vec4& color, int x, int y, int width, int height)
    213 {
    214 	gl.enable(GL_SCISSOR_TEST);
    215 	gl.scissor(x, y, width, height);
    216 	gl.clearColor(color.x(), color.y(), color.z(), color.w());
    217 	gl.clear(GL_COLOR_BUFFER_BIT);
    218 	GLU_EXPECT_NO_ERROR(gl.getError(), "Color clear failed");
    219 }
    220 
    221 tcu::Vec2 toGLCoord (int width, int height, int x, int y)
    222 {
    223 	const float xf = ((2.0f * float(x)) / (float)width)  - 1.0f;
    224 	const float yf = ((2.0f * float(y)) / (float)height) - 1.0f;
    225 
    226 	return tcu::Vec2(xf, yf);
    227 }
    228 
    229 void render (const glw::Functions& gl, deUint32 program, int targetWidth, int targetHeight, int x, int y, int width, int height)
    230 {
    231 	const tcu::Vec2 positions[] =
    232 	{
    233 		toGLCoord(targetWidth, targetHeight, x,			y),
    234 		toGLCoord(targetWidth, targetHeight, x+width,	y),
    235 		toGLCoord(targetWidth, targetHeight, x+width,	y+height),
    236 
    237 		toGLCoord(targetWidth, targetHeight, x+width,	y+height),
    238 		toGLCoord(targetWidth, targetHeight, x,			y+height),
    239 		toGLCoord(targetWidth, targetHeight, x,			y)
    240 	};
    241 
    242 	deUint32 posLocation;
    243 
    244 	gl.useProgram(program);
    245 	posLocation	= gl.getAttribLocation(program, "a_pos");
    246 	gl.enableVertexAttribArray(posLocation);
    247 	gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, positions);
    248 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");
    249 
    250 	gl.viewport(0, 0, targetWidth, targetHeight);
    251 	gl.drawArrays(GL_TRIANGLES, 0, 6);
    252 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
    253 }
    254 
    255 bool compareColor (const tcu::Vec4& a, const tcu::Vec4& b)
    256 {
    257 	const float threshold = 0.005f;
    258 
    259 	return deFloatAbs(a.x() - b.x()) < threshold &&  deFloatAbs(a.y() - b.y()) < threshold && deFloatAbs(a.z() - b.z()) < threshold && deFloatAbs(a.w() - b.w()) < threshold;
    260 }
    261 
    262 bool validate (TestLog& log, const tcu::TextureLevel& result, int rectX, int rectY, int rectW, int rectH)
    263 {
    264 	const tcu::Vec4		black		(0.0f, 0.0f, 0.0f, 1.0f);
    265 	const tcu::Vec4		white		(1.0f, 1.0f, 1.0f, 1.0f);
    266 	tcu::Surface		errorMask	(result.getWidth(), result.getHeight());
    267 	bool				isOk		= true;
    268 
    269 	for (int y = 0; y < result.getHeight(); y++)
    270 	{
    271 		for (int x = 0; x < result.getWidth(); x++)
    272 		{
    273 			const tcu::Vec4 resultColor = result.getAccess().getPixel(x, y);
    274 
    275 			if (x > rectX && x < rectX + rectW - 1 && y > rectY && y < rectY + rectH - 1)
    276 			{
    277 				if (!compareColor(resultColor, white))
    278 				{
    279 					errorMask.setPixel(x, y, tcu::RGBA(255, 0, 0, 255));
    280 					isOk = false;
    281 				}
    282 				else
    283 					errorMask.setPixel(x, y, tcu::RGBA(0, 255, 0, 255));
    284 			}
    285 			else if (x < rectX-1 || x > rectX + rectW || y < rectY-1 || y > rectY + rectH)
    286 			{
    287 				if (!compareColor(resultColor, black))
    288 				{
    289 					errorMask.setPixel(x, y, tcu::RGBA(255, 0, 0, 255));
    290 					isOk = false;
    291 				}
    292 				else
    293 					errorMask.setPixel(x, y, tcu::RGBA(0, 255, 0, 255));
    294 			}
    295 			else
    296 			{
    297 				// Pixel is close to edge of reference rectangle
    298 
    299 				if (!compareColor(resultColor, black) && !compareColor(resultColor, white))
    300 				{
    301 					errorMask.setPixel(x, y, tcu::RGBA(255, 0, 0, 255));
    302 					isOk = false;
    303 				}
    304 				else
    305 					errorMask.setPixel(x, y, tcu::RGBA(0, 255, 0, 255));
    306 			}
    307 		}
    308 	}
    309 
    310 	log << TestLog::Image("Result", "Result of rendering", result.getAccess());
    311 
    312 	if (!isOk)
    313 		log << TestLog::Image("Error Mask", "Error Mask", errorMask.getAccess());
    314 
    315 	return isOk;
    316 }
    317 
    318 class NativeCoordMappingCase : public SimpleConfigCase
    319 {
    320 public:
    321 	enum NativeType
    322 	{
    323 		NATIVETYPE_WINDOW = 0,
    324 		NATIVETYPE_PIXMAP,
    325 		NATIVETYPE_PBUFFER_COPY_TO_PIXMAP
    326 	};
    327 
    328 				NativeCoordMappingCase	(EglTestContext& eglTestCtx, const char* name, const char* description, bool render, NativeType nativeType, const eglu::FilterList& filters);
    329 				~NativeCoordMappingCase	(void);
    330 
    331 private:
    332 	void		executeForConfig		(EGLDisplay display, EGLConfig config);
    333 
    334 	NativeType	m_nativeType;
    335 	bool		m_render;
    336 };
    337 
    338 NativeCoordMappingCase::NativeCoordMappingCase (EglTestContext& eglTestCtx, const char* name, const char* description, bool render, NativeType nativeType, const eglu::FilterList& filters)
    339 	: SimpleConfigCase	(eglTestCtx, name, description, filters)
    340 	, m_nativeType		(nativeType)
    341 	, m_render			(render)
    342 {
    343 }
    344 
    345 NativeCoordMappingCase::~NativeCoordMappingCase	(void)
    346 {
    347 	deinit();
    348 }
    349 
    350 void logConfigInfo (TestLog& log, const Library& egl, EGLDisplay display, EGLConfig config, NativeCoordMappingCase::NativeType nativeType, int waitFrames)
    351 {
    352 	log << TestLog::Message << "EGL_RED_SIZE: "		<< eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE)		<< TestLog::EndMessage;
    353 	log << TestLog::Message << "EGL_GREEN_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE)	<< TestLog::EndMessage;
    354 	log << TestLog::Message << "EGL_BLUE_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE)	<< TestLog::EndMessage;
    355 	log << TestLog::Message << "EGL_ALPHA_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE)	<< TestLog::EndMessage;
    356 	log << TestLog::Message << "EGL_DEPTH_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE)	<< TestLog::EndMessage;
    357 	log << TestLog::Message << "EGL_STENCIL_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE)	<< TestLog::EndMessage;
    358 	log << TestLog::Message << "EGL_SAMPLES: "		<< eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES)		<< TestLog::EndMessage;
    359 
    360 	if (nativeType == NativeCoordMappingCase::NATIVETYPE_WINDOW)
    361 		log << TestLog::Message << "Waiting " << waitFrames * 16 << "ms after eglSwapBuffers() and glFinish() for frame to become visible" << TestLog::EndMessage;
    362 }
    363 
    364 bool testNativeWindow (TestLog& log, eglu::NativeDisplay& nativeDisplay, eglu::NativeWindow& nativeWindow, EGLDisplay display, EGLContext context, EGLConfig config, const glw::Functions& gl, bool renderColor, int waitFrames)
    365 {
    366 	const int			rectX		= 8;
    367 	const int			rectY		= 16;
    368 	const int			rectW		= 64;
    369 	const int			rectH		= 72;
    370 
    371 	const Library&		egl			= nativeDisplay.getLibrary();
    372 	const tcu::IVec2	screenSize	= nativeWindow.getScreenSize();
    373 	eglu::UniqueSurface	surface		(egl, display, eglu::createWindowSurface(nativeDisplay, nativeWindow, display, config, DE_NULL));
    374 	const tcu::IVec2	surfaceSize = eglu::getSurfaceSize(egl, display, *surface);
    375 	deUint32			program		= 0;
    376 	bool				isOk		= true;
    377 	tcu::TextureLevel	result;
    378 
    379 	try
    380 	{
    381 		EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, context));
    382 
    383 		if (renderColor)
    384 			program = createGLES2Program(gl, log);
    385 
    386 		clear(gl, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, surfaceSize.x(), surfaceSize.y());
    387 
    388 		if (renderColor)
    389 			render(gl, program, surfaceSize.x(), surfaceSize.y(), rectX, rectY, rectW, rectH);
    390 		else
    391 			clear(gl, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), rectX, rectY, rectW, rectH);
    392 
    393 		EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
    394 		EGLU_CHECK_CALL(egl, waitClient());
    395 		deSleep(waitFrames*16);
    396 		nativeWindow.readScreenPixels(&result);
    397 
    398 		if (!validate(log, result, rectX, screenSize.y() - rectY - rectH, rectW, rectH))
    399 			isOk = false;
    400 
    401 		EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
    402 	}
    403 	catch (...)
    404 	{
    405 		if (program)
    406 			gl.deleteProgram(program);
    407 		throw;
    408 	}
    409 
    410 	return isOk;
    411 }
    412 
    413 bool testNativePixmap (TestLog& log, eglu::NativeDisplay& nativeDisplay, eglu::NativePixmap& nativePixmap, int width, int height, EGLDisplay display, EGLContext context, EGLConfig config, const glw::Functions& gl, bool renderColor)
    414 {
    415 	const int			rectX		= 8;
    416 	const int			rectY		= 16;
    417 	const int			rectW		= 64;
    418 	const int			rectH		= 72;
    419 
    420 	const Library&		egl			= nativeDisplay.getLibrary();
    421 	eglu::UniqueSurface	surface		(egl, display, eglu::createPixmapSurface(nativeDisplay, nativePixmap, display, config, DE_NULL));
    422 	deUint32			program		= 0;
    423 	bool				isOk		= true;
    424 	tcu::TextureLevel	result;
    425 
    426 	try
    427 	{
    428 		EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, context));
    429 
    430 		if (renderColor)
    431 			program = createGLES2Program(gl, log);
    432 
    433 		clear(gl, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, width, height);
    434 
    435 		if (renderColor)
    436 			render(gl, program, width, height, rectX, rectY, rectW, rectH);
    437 		else
    438 			clear(gl, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), rectX, rectY, rectW, rectH);
    439 
    440 		EGLU_CHECK_CALL(egl, waitClient());
    441 		nativePixmap.readPixels(&result);
    442 
    443 		if (!validate(log, result, rectX, height - 1 - rectY - rectH, rectW, rectH))
    444 			isOk = false;
    445 
    446 		EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
    447 	}
    448 	catch (...)
    449 	{
    450 		if (program)
    451 			gl.deleteProgram(program);
    452 		throw;
    453 	}
    454 
    455 	return isOk;
    456 }
    457 
    458 bool testNativePixmapCopy (TestLog& log, const Library& egl, eglu::NativePixmap& nativePixmap, int width, int height, EGLDisplay display, EGLContext context, EGLConfig config, const glw::Functions& gl, bool renderColor)
    459 {
    460 	const int			rectX		= 8;
    461 	const int			rectY		= 16;
    462 	const int			rectW		= 64;
    463 	const int			rectH		= 72;
    464 
    465 	eglu::UniqueSurface	surface		(egl, display, egl.createPbufferSurface(display, config, DE_NULL));
    466 	deUint32			program		= 0;
    467 	bool				isOk		= true;
    468 	tcu::TextureLevel	result;
    469 
    470 	try
    471 	{
    472 		EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, context));
    473 
    474 		if (renderColor)
    475 			program = createGLES2Program(gl, log);
    476 
    477 		clear(gl, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0, 0, width, height);
    478 
    479 		if (renderColor)
    480 			render(gl, program, width, height, rectX, rectY, rectW, rectH);
    481 		else
    482 			clear(gl, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), rectX, rectY, rectW, rectH);
    483 
    484 		EGLU_CHECK_CALL(egl, copyBuffers(display, *surface, nativePixmap.getLegacyNative()));
    485 		EGLU_CHECK_CALL(egl, waitClient());
    486 		nativePixmap.readPixels(&result);
    487 
    488 		if (!validate(log, result, rectX, height - 1 - rectY, rectW, rectH))
    489 			isOk = false;
    490 
    491 		EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
    492 	}
    493 	catch (...)
    494 	{
    495 		if (program)
    496 			gl.deleteProgram(program);
    497 		throw;
    498 	}
    499 
    500 	return isOk;
    501 }
    502 
    503 void NativeCoordMappingCase::executeForConfig (EGLDisplay display, EGLConfig config)
    504 {
    505 	const Library&						egl				= m_eglTestCtx.getLibrary();
    506 	const string						configIdStr		(de::toString(eglu::getConfigAttribInt(egl, display, config, EGL_CONFIG_ID)));
    507 	tcu::ScopedLogSection				logSection		(m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str());
    508 	const int							waitFrames		= 5;
    509 	const int							width			= 128;
    510 	const int							height			= 128;
    511 	const eglu::NativeWindowFactory*	windowFactory;
    512 	const eglu::NativePixmapFactory*	pixmapFactory;
    513 
    514 	logConfigInfo(m_testCtx.getLog(), egl, display, config, m_nativeType, waitFrames);
    515 
    516 	try
    517 	{
    518 		windowFactory = &eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
    519 
    520 		if ((windowFactory->getCapabilities() & eglu::NativeWindow::CAPABILITY_READ_SCREEN_PIXELS) == 0)
    521 			TCU_THROW(NotSupportedError, "Native window doesn't support readPixels()");
    522 	}
    523 	catch (const tcu::NotSupportedError&)
    524 	{
    525 		if (m_nativeType == NATIVETYPE_WINDOW)
    526 			throw;
    527 		else
    528 			windowFactory = DE_NULL;
    529 	}
    530 
    531 	try
    532 	{
    533 		pixmapFactory = &eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
    534 
    535 		if (m_nativeType == NATIVETYPE_PIXMAP)
    536 		{
    537 			if ((pixmapFactory->getCapabilities() & eglu::NativePixmap::CAPABILITY_READ_PIXELS) == 0)
    538 				TCU_THROW(NotSupportedError, "Native pixmap doesn't support readPixels()");
    539 		}
    540 		else if (m_nativeType == NATIVETYPE_PBUFFER_COPY_TO_PIXMAP)
    541 		{
    542 			if ((pixmapFactory->getCapabilities() & eglu::NativePixmap::CAPABILITY_READ_PIXELS) == 0 ||
    543 				(pixmapFactory->getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY) == 0)
    544 				TCU_THROW(NotSupportedError, "Native pixmap doesn't support readPixels() or legacy create surface");
    545 		}
    546 	}
    547 	catch (const tcu::NotSupportedError&)
    548 	{
    549 		if (m_nativeType == NATIVETYPE_PIXMAP || m_nativeType == NATIVETYPE_PBUFFER_COPY_TO_PIXMAP)
    550 			throw;
    551 		else
    552 			pixmapFactory = DE_NULL;
    553 	}
    554 
    555 	DE_ASSERT(m_nativeType != NATIVETYPE_WINDOW || windowFactory);
    556 	DE_ASSERT((m_nativeType != NATIVETYPE_PIXMAP && m_nativeType != NATIVETYPE_PBUFFER_COPY_TO_PIXMAP) || pixmapFactory);
    557 
    558 	eglu::UniqueContext 	context		(egl, display, createGLES2Context(egl, display, config));
    559 	glw::Functions			gl;
    560 
    561 	m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
    562 
    563 	switch (m_nativeType)
    564 	{
    565 		case NATIVETYPE_WINDOW:
    566 		{
    567 			de::UniquePtr<eglu::NativeWindow>	nativeWindow	(windowFactory->createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(width, height, eglu::WindowParams::VISIBILITY_VISIBLE)));
    568 
    569 			if (!testNativeWindow(m_testCtx.getLog(), m_eglTestCtx.getNativeDisplay(), *nativeWindow, display, *context, config, gl, m_render, waitFrames))
    570 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color rendered");
    571 
    572 			break;
    573 		}
    574 
    575 		case NATIVETYPE_PIXMAP:
    576 		{
    577 			de::UniquePtr<eglu::NativePixmap> nativePixmap		(pixmapFactory->createPixmap(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, width, height));
    578 
    579 			if (!testNativePixmap(m_testCtx.getLog(), m_eglTestCtx.getNativeDisplay(), *nativePixmap, width, height, display, *context, config, gl, m_render))
    580 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color rendered");
    581 
    582 			break;
    583 		}
    584 
    585 		case NATIVETYPE_PBUFFER_COPY_TO_PIXMAP:
    586 		{
    587 			de::UniquePtr<eglu::NativePixmap> nativePixmap		(pixmapFactory->createPixmap(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, width, height));
    588 
    589 			if (!testNativePixmapCopy(m_testCtx.getLog(), egl, *nativePixmap, width, height, display, *context, config, gl, m_render))
    590 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid color rendered");
    591 
    592 			break;
    593 		}
    594 
    595 		default:
    596 			DE_ASSERT(DE_FALSE);
    597 	}
    598 }
    599 
    600 template <deUint32 Type>
    601 static bool surfaceType (const eglu::CandidateConfig& c)
    602 {
    603 	return (c.surfaceType() & Type) == Type;
    604 }
    605 
    606 void addTestGroups (EglTestContext& eglTestCtx, TestCaseGroup* group, NativeCoordMappingCase::NativeType type)
    607 {
    608 	eglu::FilterList baseFilters;
    609 
    610 	switch (type)
    611 	{
    612 		case NativeCoordMappingCase::NATIVETYPE_WINDOW:
    613 			baseFilters << surfaceType<EGL_WINDOW_BIT>;
    614 			break;
    615 
    616 		case NativeCoordMappingCase::NATIVETYPE_PIXMAP:
    617 			baseFilters << surfaceType<EGL_PIXMAP_BIT>;
    618 			break;
    619 
    620 		case NativeCoordMappingCase::NATIVETYPE_PBUFFER_COPY_TO_PIXMAP:
    621 			baseFilters << surfaceType<EGL_PBUFFER_BIT>;
    622 			break;
    623 
    624 		default:
    625 			DE_ASSERT(DE_FALSE);
    626 	}
    627 
    628 	vector<NamedFilterList> filterLists;
    629 	getDefaultFilterLists(filterLists, baseFilters);
    630 
    631 	for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
    632 	{
    633 		group->addChild(new NativeCoordMappingCase(eglTestCtx, (string(i->getName()) + "_clear").c_str(), i->getDescription(), false, type, *i));
    634 		group->addChild(new NativeCoordMappingCase(eglTestCtx, (string(i->getName()) + "_render").c_str(), i->getDescription(), true, type, *i));
    635 	}
    636 }
    637 
    638 } // anonymous
    639 
    640 NativeCoordMappingTests::NativeCoordMappingTests (EglTestContext& eglTestCtx)
    641 	: TestCaseGroup(eglTestCtx, "native_coord_mapping", "Tests for mapping client coordinates to native surface")
    642 {
    643 }
    644 
    645 void NativeCoordMappingTests::init (void)
    646 {
    647 	{
    648 		TestCaseGroup* windowGroup = new TestCaseGroup(m_eglTestCtx, "native_window", "Tests for mapping client color to native window");
    649 		addTestGroups(m_eglTestCtx, windowGroup, NativeCoordMappingCase::NATIVETYPE_WINDOW);
    650 		addChild(windowGroup);
    651 	}
    652 
    653 	{
    654 		TestCaseGroup* pixmapGroup = new TestCaseGroup(m_eglTestCtx, "native_pixmap", "Tests for mapping client color to native pixmap");
    655 		addTestGroups(m_eglTestCtx, pixmapGroup, NativeCoordMappingCase::NATIVETYPE_PIXMAP);
    656 		addChild(pixmapGroup);
    657 	}
    658 
    659 	{
    660 		TestCaseGroup* pbufferGroup = new TestCaseGroup(m_eglTestCtx, "pbuffer_to_native_pixmap", "Tests for mapping client color to native pixmap with eglCopyBuffers()");
    661 		addTestGroups(m_eglTestCtx, pbufferGroup, NativeCoordMappingCase::NATIVETYPE_PBUFFER_COPY_TO_PIXMAP);
    662 		addChild(pbufferGroup);
    663 	}
    664 }
    665 
    666 } // egl
    667 } // deqp
    668