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 Config query tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "teglQueryContextTests.hpp"
     25 #include "teglRenderCase.hpp"
     26 #include "teglRenderCase.hpp"
     27 #include "egluCallLogWrapper.hpp"
     28 #include "egluStrUtil.hpp"
     29 #include "tcuCommandLine.hpp"
     30 #include "tcuTestLog.hpp"
     31 #include "tcuTestContext.hpp"
     32 
     33 #include "egluUtil.hpp"
     34 #include "egluNativeDisplay.hpp"
     35 #include "egluNativeWindow.hpp"
     36 #include "egluNativePixmap.hpp"
     37 
     38 #include "eglwLibrary.hpp"
     39 #include "eglwEnums.hpp"
     40 
     41 #include "deUniquePtr.hpp"
     42 #include "deSTLUtil.hpp"
     43 
     44 #include <vector>
     45 
     46 namespace deqp
     47 {
     48 namespace egl
     49 {
     50 
     51 using std::vector;
     52 using eglu::ConfigInfo;
     53 using tcu::TestLog;
     54 using namespace eglw;
     55 
     56 static EGLint getClientTypeFromAPIBit (EGLint apiBit)
     57 {
     58 	switch (apiBit)
     59 	{
     60 		case EGL_OPENGL_BIT:		return EGL_OPENGL_API;
     61 		case EGL_OPENGL_ES_BIT:		return EGL_OPENGL_ES_API;
     62 		case EGL_OPENGL_ES2_BIT:	return EGL_OPENGL_ES_API;
     63 		case EGL_OPENGL_ES3_BIT:	return EGL_OPENGL_ES_API;
     64 		case EGL_OPENVG_BIT:		return EGL_OPENVG_API;
     65 		default:
     66 			DE_ASSERT(false);
     67 			return 0;
     68 	}
     69 }
     70 
     71 static EGLint getMinClientMajorVersion (EGLint apiBit)
     72 {
     73 	switch (apiBit)
     74 	{
     75 		case EGL_OPENGL_BIT:		return 1;
     76 		case EGL_OPENGL_ES_BIT:		return 1;
     77 		case EGL_OPENGL_ES2_BIT:	return 2;
     78 		case EGL_OPENGL_ES3_BIT:	return 3;
     79 		case EGL_OPENVG_BIT:		return 1;
     80 		default:
     81 			DE_ASSERT(false);
     82 			return 0;
     83 	}
     84 }
     85 
     86 class GetCurrentContextCase : public SingleContextRenderCase, private eglu::CallLogWrapper
     87 {
     88 public:
     89 	GetCurrentContextCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask)
     90 		: SingleContextRenderCase	(eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters)
     91 		, eglu::CallLogWrapper		(eglTestCtx.getLibrary(), m_testCtx.getLog())
     92 	{
     93 	}
     94 
     95 	void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config)
     96 	{
     97 		const Library&	egl	= m_eglTestCtx.getLibrary();
     98 		TestLog&		log	= m_testCtx.getLog();
     99 
    100 		DE_UNREF(display);
    101 		DE_UNREF(surface);
    102 		DE_UNREF(config);
    103 
    104 		enableLogging(true);
    105 
    106 		const EGLContext	gotContext	= eglGetCurrentContext();
    107 		EGLU_CHECK_MSG(egl, "eglGetCurrentContext");
    108 
    109 		if (gotContext == context)
    110 		{
    111 			log << TestLog::Message << "  Pass" << TestLog::EndMessage;
    112 		}
    113 		else if (gotContext == EGL_NO_CONTEXT)
    114 		{
    115 			log << TestLog::Message << "  Fail, got EGL_NO_CONTEXT" << TestLog::EndMessage;
    116 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected EGL_NO_CONTEXT");
    117 		}
    118 		else if (gotContext != context)
    119 		{
    120 			log << TestLog::Message << "  Fail, call returned the wrong context. Expected: " << tcu::toHex(context) << ", got: " << tcu::toHex(gotContext) << TestLog::EndMessage;
    121 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid context");
    122 		}
    123 
    124 		enableLogging(false);
    125 	}
    126 };
    127 
    128 class GetCurrentSurfaceCase : public SingleContextRenderCase, private eglu::CallLogWrapper
    129 {
    130 public:
    131 	GetCurrentSurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask)
    132 		: SingleContextRenderCase	(eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters)
    133 		, eglu::CallLogWrapper		(eglTestCtx.getLibrary(), m_testCtx.getLog())
    134 	{
    135 	}
    136 
    137 	void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config)
    138 	{
    139 		const Library&	egl	= m_eglTestCtx.getLibrary();
    140 		TestLog&		log	= m_testCtx.getLog();
    141 
    142 		DE_UNREF(display);
    143 		DE_UNREF(context);
    144 		DE_UNREF(config);
    145 
    146 		enableLogging(true);
    147 
    148 		const EGLContext	gotReadSurface	= eglGetCurrentSurface(EGL_READ);
    149 		EGLU_CHECK_MSG(egl, "eglGetCurrentSurface(EGL_READ)");
    150 
    151 		const EGLContext	gotDrawSurface	= eglGetCurrentSurface(EGL_DRAW);
    152 		EGLU_CHECK_MSG(egl, "eglGetCurrentSurface(EGL_DRAW)");
    153 
    154 		if (gotReadSurface == surface && gotDrawSurface == surface)
    155 		{
    156 			log << TestLog::Message << "  Pass" << TestLog::EndMessage;
    157 		}
    158 		else
    159 		{
    160 			log << TestLog::Message << "  Fail, read surface: " << tcu::toHex(gotReadSurface)
    161 									<< ", draw surface: " << tcu::toHex(gotDrawSurface)
    162 									<< ", expected: " << tcu::toHex(surface) << TestLog::EndMessage;
    163 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface");
    164 		}
    165 
    166 		enableLogging(false);
    167 	}
    168 };
    169 
    170 class GetCurrentDisplayCase : public SingleContextRenderCase, private eglu::CallLogWrapper
    171 {
    172 public:
    173 	GetCurrentDisplayCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask)
    174 		: SingleContextRenderCase	(eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters)
    175 		, eglu::CallLogWrapper		(eglTestCtx.getLibrary(), m_testCtx.getLog())
    176 	{
    177 	}
    178 
    179 	void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config)
    180 	{
    181 		const Library&	egl	= m_eglTestCtx.getLibrary();
    182 		TestLog&		log	= m_testCtx.getLog();
    183 
    184 		DE_UNREF(surface && context);
    185 		DE_UNREF(config);
    186 
    187 		enableLogging(true);
    188 
    189 		const EGLDisplay	gotDisplay	= eglGetCurrentDisplay();
    190 		EGLU_CHECK_MSG(egl, "eglGetCurrentDisplay");
    191 
    192 		if (gotDisplay == display)
    193 		{
    194 			log << TestLog::Message << "  Pass" << TestLog::EndMessage;
    195 		}
    196 		else if (gotDisplay == EGL_NO_DISPLAY)
    197 		{
    198 			log << TestLog::Message << "  Fail, got EGL_NO_DISPLAY" << TestLog::EndMessage;
    199 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected EGL_NO_DISPLAY");
    200 		}
    201 		else if (gotDisplay != display)
    202 		{
    203 			log << TestLog::Message << "  Fail, call returned the wrong display. Expected: " << tcu::toHex(display) << ", got: " << tcu::toHex(gotDisplay) << TestLog::EndMessage;
    204 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid display");
    205 		}
    206 
    207 		enableLogging(false);
    208 	}
    209 };
    210 
    211 class QueryContextCase : public SingleContextRenderCase, private eglu::CallLogWrapper
    212 {
    213 public:
    214 	QueryContextCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters, EGLint surfaceTypeMask)
    215 		: SingleContextRenderCase	(eglTestCtx, name, description, getBuildClientAPIMask(), surfaceTypeMask, filters)
    216 		, eglu::CallLogWrapper		(eglTestCtx.getLibrary(), m_testCtx.getLog())
    217 	{
    218 	}
    219 
    220 	EGLint getContextAttrib (EGLDisplay display, EGLContext context, EGLint attrib)
    221 	{
    222 		const Library&	egl	= m_eglTestCtx.getLibrary();
    223 		EGLint			value;
    224 		EGLU_CHECK_CALL(egl, queryContext(display, context, attrib, &value));
    225 
    226 		return value;
    227 	}
    228 
    229 	void executeForContext (EGLDisplay display, EGLContext context, EGLSurface surface, const Config& config)
    230 	{
    231 		const Library&		egl		= m_eglTestCtx.getLibrary();
    232 		TestLog&			log		= m_testCtx.getLog();
    233 		const eglu::Version	version	= eglu::getVersion(egl, display);
    234 
    235 		DE_UNREF(surface);
    236 		enableLogging(true);
    237 
    238 		// Config ID
    239 		{
    240 			const EGLint	configID		= getContextAttrib(display, context, EGL_CONFIG_ID);
    241 			const EGLint	surfaceConfigID	= eglu::getConfigAttribInt(egl, display, config.config, EGL_CONFIG_ID);
    242 
    243 			if (configID != surfaceConfigID)
    244 			{
    245 				log << TestLog::Message << "  Fail, config ID doesn't match the one used to create the context." << TestLog::EndMessage;
    246 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid config ID");
    247 			}
    248 		}
    249 
    250 		// Client API type
    251 		if (version >= eglu::Version(1, 2))
    252 		{
    253 			const EGLint	clientType		= getContextAttrib(display, context, EGL_CONTEXT_CLIENT_TYPE);
    254 
    255 			if (clientType != getClientTypeFromAPIBit(config.apiBits))
    256 			{
    257 				log << TestLog::Message << "  Fail, client API type doesn't match." << TestLog::EndMessage;
    258 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid client API type");
    259 			}
    260 		}
    261 
    262 		// Client API version
    263 		if (version >= eglu::Version(1, 3))
    264 		{
    265 			const EGLint	clientVersion	= getContextAttrib(display, context, EGL_CONTEXT_CLIENT_VERSION);
    266 
    267 			// \todo [2014-10-21 mika] Query actual supported api version from client api to make this check stricter.
    268 			if (clientVersion < getMinClientMajorVersion(config.apiBits))
    269 			{
    270 				log << TestLog::Message << "  Fail, client API version doesn't match." << TestLog::EndMessage;
    271 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid client API version");
    272 			}
    273 		}
    274 
    275 		// Render buffer
    276 		if (version >= eglu::Version(1, 2))
    277 		{
    278 			const EGLint	renderBuffer	= getContextAttrib(display, context, EGL_RENDER_BUFFER);
    279 
    280 			if (config.surfaceTypeBit == EGL_PIXMAP_BIT && renderBuffer != EGL_SINGLE_BUFFER)
    281 			{
    282 				log << TestLog::Message << "  Fail, render buffer should be EGL_SINGLE_BUFFER for a pixmap surface." << TestLog::EndMessage;
    283 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer");
    284 			}
    285 			else if (config.surfaceTypeBit == EGL_PBUFFER_BIT && renderBuffer != EGL_BACK_BUFFER)
    286 			{
    287 				log << TestLog::Message << "  Fail, render buffer should be EGL_BACK_BUFFER for a pbuffer surface." << TestLog::EndMessage;
    288 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer");
    289 			}
    290 			else if (config.surfaceTypeBit == EGL_WINDOW_BIT && renderBuffer != EGL_SINGLE_BUFFER && renderBuffer != EGL_BACK_BUFFER)
    291 			{
    292 				log << TestLog::Message << "  Fail, render buffer should be either EGL_SINGLE_BUFFER or EGL_BACK_BUFFER for a window surface." << TestLog::EndMessage;
    293 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid render buffer");
    294 			}
    295 		}
    296 
    297 		enableLogging(false);
    298 
    299 		log << TestLog::Message << "  Pass" << TestLog::EndMessage;
    300 	}
    301 };
    302 
    303 class QueryAPICase : public TestCase, private eglu::CallLogWrapper
    304 {
    305 public:
    306 	QueryAPICase (EglTestContext& eglTestCtx, const char* name, const char* description)
    307 		: TestCase		(eglTestCtx, name, description)
    308 		, CallLogWrapper(eglTestCtx.getLibrary(), eglTestCtx.getTestContext().getLog())
    309 	{
    310 	}
    311 
    312 	void init (void)
    313 	{
    314 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    315 	}
    316 
    317 	IterateResult iterate (void)
    318 	{
    319 		const Library&			egl				= m_eglTestCtx.getLibrary();
    320 		EGLDisplay				display			= eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
    321 		tcu::TestLog&			log				= m_testCtx.getLog();
    322 		const EGLenum			apis[]			= { EGL_OPENGL_API, EGL_OPENGL_ES_API, EGL_OPENVG_API };
    323 		const vector<EGLenum>	supportedAPIs	= eglu::getClientAPIs(egl, display);
    324 
    325 		enableLogging(true);
    326 
    327 		{
    328 			const EGLenum	api	= eglQueryAPI();
    329 
    330 			if (api != EGL_OPENGL_ES_API && (de::contains(supportedAPIs.begin(), supportedAPIs.end(), EGL_OPENGL_ES_API)))
    331 			{
    332 				log << TestLog::Message << "  Fail, initial value should be EGL_OPENGL_ES_API if OpenGL ES is supported." << TestLog::EndMessage;
    333 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid default value");
    334 			}
    335 			else if (api != EGL_NONE && !(de::contains(supportedAPIs.begin(), supportedAPIs.end(), EGL_OPENGL_ES_API)))
    336 			{
    337 				log << TestLog::Message << "  Fail, initial value should be EGL_NONE if OpenGL ES is not supported." << TestLog::EndMessage;
    338 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid default value");
    339 			}
    340 		}
    341 
    342 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(apis); ndx++)
    343 		{
    344 			const EGLenum	api	= apis[ndx];
    345 
    346 			log << TestLog::Message << TestLog::EndMessage;
    347 
    348 			if (de::contains(supportedAPIs.begin(), supportedAPIs.end(), api))
    349 			{
    350 				egl.bindAPI(api);
    351 
    352 				if (api != egl.queryAPI())
    353 				{
    354 					log << TestLog::Message << "  Fail, return value does not match previously bound API." << TestLog::EndMessage;
    355 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid return value");
    356 				}
    357 			}
    358 			else
    359 			{
    360 				log << TestLog::Message << eglu::getAPIStr(api) << " not supported." << TestLog::EndMessage;
    361 			}
    362 		}
    363 
    364 		enableLogging(false);
    365 		eglTerminate(display);
    366 		return STOP;
    367 	}
    368 };
    369 
    370 QueryContextTests::QueryContextTests (EglTestContext& eglTestCtx)
    371 	: TestCaseGroup(eglTestCtx, "query_context", "Rendering context query tests")
    372 {
    373 }
    374 
    375 QueryContextTests::~QueryContextTests (void)
    376 {
    377 }
    378 
    379 template<class QueryContextClass>
    380 void createQueryContextGroups (EglTestContext& eglTestCtx, tcu::TestCaseGroup* group)
    381 {
    382 	std::vector<RenderFilterList> filterLists;
    383 
    384 	getDefaultRenderFilterLists(filterLists, eglu::FilterList());
    385 
    386 	for (std::vector<RenderFilterList>::const_iterator listIter = filterLists.begin(); listIter != filterLists.end(); listIter++)
    387 		group->addChild(new QueryContextClass(eglTestCtx, listIter->getName(), "", *listIter, listIter->getSurfaceTypeMask()));
    388 }
    389 
    390 void QueryContextTests::init (void)
    391 {
    392 	{
    393 		tcu::TestCaseGroup* simpleGroup = new tcu::TestCaseGroup(m_testCtx, "simple", "Simple API tests");
    394 		addChild(simpleGroup);
    395 
    396 		simpleGroup->addChild(new QueryAPICase(m_eglTestCtx, "query_api", "eglQueryAPI() test"));
    397 	}
    398 
    399 	// eglGetCurrentContext
    400 	{
    401 		tcu::TestCaseGroup* getCurrentContextGroup = new tcu::TestCaseGroup(m_testCtx, "get_current_context", "eglGetCurrentContext() tests");
    402 		addChild(getCurrentContextGroup);
    403 
    404 		createQueryContextGroups<GetCurrentContextCase>(m_eglTestCtx, getCurrentContextGroup);
    405 	}
    406 
    407 	// eglGetCurrentSurface
    408 	{
    409 		tcu::TestCaseGroup* getCurrentSurfaceGroup = new tcu::TestCaseGroup(m_testCtx, "get_current_surface", "eglGetCurrentSurface() tests");
    410 		addChild(getCurrentSurfaceGroup);
    411 
    412 		createQueryContextGroups<GetCurrentSurfaceCase>(m_eglTestCtx, getCurrentSurfaceGroup);
    413 	}
    414 
    415 	// eglGetCurrentDisplay
    416 	{
    417 		tcu::TestCaseGroup* getCurrentDisplayGroup = new tcu::TestCaseGroup(m_testCtx, "get_current_display", "eglGetCurrentDisplay() tests");
    418 		addChild(getCurrentDisplayGroup);
    419 
    420 		createQueryContextGroups<GetCurrentDisplayCase>(m_eglTestCtx, getCurrentDisplayGroup);
    421 	}
    422 
    423 	// eglQueryContext
    424 	{
    425 		tcu::TestCaseGroup* queryContextGroup = new tcu::TestCaseGroup(m_testCtx, "query_context", "eglQueryContext() tests");
    426 		addChild(queryContextGroup);
    427 
    428 		createQueryContextGroups<QueryContextCase>(m_eglTestCtx, queryContextGroup);
    429 	}
    430 }
    431 
    432 } // egl
    433 } // deqp
    434