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 Simple surface construction test.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "teglCreateSurfaceTests.hpp"
     25 
     26 #include "egluNativeDisplay.hpp"
     27 #include "egluNativeWindow.hpp"
     28 #include "egluNativePixmap.hpp"
     29 #include "egluUtil.hpp"
     30 #include "egluUnique.hpp"
     31 
     32 #include "eglwLibrary.hpp"
     33 #include "eglwEnums.hpp"
     34 
     35 #include "teglSimpleConfigCase.hpp"
     36 #include "tcuTestContext.hpp"
     37 #include "tcuCommandLine.hpp"
     38 #include "tcuTestLog.hpp"
     39 
     40 #include "deStringUtil.hpp"
     41 #include "deSTLUtil.hpp"
     42 #include "deUniquePtr.hpp"
     43 
     44 #include <memory>
     45 
     46 namespace deqp
     47 {
     48 namespace egl
     49 {
     50 
     51 using std::vector;
     52 using tcu::TestLog;
     53 using namespace eglw;
     54 
     55 namespace
     56 {
     57 
     58 #define EGL_MAKE_VERSION(major, minor) (((major) << 12) | (minor))
     59 
     60 enum ApiType
     61 {
     62 	LEGACY,
     63 	EXTENSION,
     64 	EGL15
     65 };
     66 
     67 void checkEGLPlatformSupport (const Library& egl)
     68 {
     69 	const vector<std::string>	extensions	= eglu::getClientExtensions(egl);
     70 	if (!de::contains(extensions.begin(), extensions.end(), "EGL_EXT_platform_base"))
     71 		throw tcu::NotSupportedError("Platform extension 'EGL_EXT_platform_base' not supported", "", __FILE__, __LINE__);
     72 }
     73 
     74 void checkEGL15Support (const Library& egl, EGLDisplay display)
     75 {
     76 	// The EGL_VERSION string is laid out as follows:
     77 	// major_version.minor_version space vendor_specific_info
     78 	// Split version from vendor_specific_info
     79 	std::vector<std::string> tokens = de::splitString(egl.queryString(display, EGL_VERSION), ' ');
     80 	// split version into major & minor
     81 	std::vector<std::string> values = de::splitString(tokens[0], '.');
     82 	EGLint eglVersion = EGL_MAKE_VERSION(atoi(values[0].c_str()), atoi(values[1].c_str()));
     83 	if (eglVersion < EGL_MAKE_VERSION(1, 5))
     84 		throw tcu::NotSupportedError("EGL 1.5 not supported", "", __FILE__, __LINE__);
     85 }
     86 
     87 EGLSurface createWindowSurface (EGLDisplay display, EGLConfig config, eglu::NativeDisplay& nativeDisplay, eglu::NativeWindow& window, ApiType createType)
     88 {
     89 	const Library&	egl		= nativeDisplay.getLibrary();
     90 	EGLSurface		surface	= EGL_NO_SURFACE;
     91 
     92 	switch (createType)
     93 	{
     94 		case LEGACY:
     95 		{
     96 			surface = egl.createWindowSurface(display, config, window.getLegacyNative(), DE_NULL);
     97 			EGLU_CHECK_MSG(egl, "eglCreateWindowSurface() failed");
     98 		}
     99 		break;
    100 		case EXTENSION:
    101 		{
    102 			checkEGLPlatformSupport(egl);
    103 			void *nativeWindow = window.getPlatformExtension();
    104 			surface = egl.createPlatformWindowSurfaceEXT(display, config, nativeWindow, DE_NULL);
    105 			EGLU_CHECK_MSG(egl, "eglCreatePlatformWindowSurfaceEXT() failed");
    106 		}
    107 		break;
    108 		case EGL15:
    109 		{
    110 			checkEGL15Support(egl, display);
    111 			surface = egl.createPlatformWindowSurface(display, config, window.getPlatformNative(), DE_NULL);
    112 			EGLU_CHECK_MSG(egl, "eglCreatePlatformWindowSurface() failed");
    113 		}
    114 	}
    115 
    116 	return surface;
    117 }
    118 
    119 EGLSurface createPixmapSurface (EGLDisplay display, EGLConfig config, eglu::NativeDisplay& nativeDisplay, eglu::NativePixmap& pixmap, ApiType createType)
    120 {
    121 	const Library&	egl		= nativeDisplay.getLibrary();
    122 	EGLSurface		surface	= EGL_NO_SURFACE;
    123 
    124 	switch (createType)
    125 	{
    126 		case LEGACY:
    127 			surface = egl.createPixmapSurface(display, config, pixmap.getLegacyNative(), DE_NULL);
    128 			EGLU_CHECK_MSG(egl, "eglCreatePixmapSurface() failed");
    129 		break;
    130 		case EXTENSION:
    131 			checkEGLPlatformSupport(egl);
    132 			surface = egl.createPlatformPixmapSurfaceEXT(display, config, pixmap.getPlatformExtension(), DE_NULL);
    133 			EGLU_CHECK_MSG(egl, "eglCreatePlatformPixmapSurfaceEXT() failed");
    134 		break;
    135 		case EGL15:
    136 			surface = egl.createPlatformPixmapSurface(display, config, pixmap.getPlatformNative(), DE_NULL);
    137 			EGLU_CHECK_MSG(egl, "eglCreatePlatformPixmapSurface() failed");
    138 		break;
    139 	}
    140 
    141 	return surface;
    142 }
    143 
    144 class CreateWindowSurfaceCase : public SimpleConfigCase
    145 {
    146 public:
    147 	CreateWindowSurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, ApiType createType, const eglu::FilterList& filters)
    148 		: SimpleConfigCase	(eglTestCtx, name, description, filters)
    149 		, m_createType	(createType)
    150 	{
    151 	}
    152 
    153 	void executeForConfig (EGLDisplay display, EGLConfig config)
    154 	{
    155 		const Library&						egl				= m_eglTestCtx.getLibrary();
    156 		TestLog&							log				= m_testCtx.getLog();
    157 		EGLint								id				= eglu::getConfigID(egl, display, config);
    158 		const eglu::NativeWindowFactory&	windowFactory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
    159 
    160 		// \todo [2011-03-23 pyry] Iterate thru all possible combinations of EGL_RENDER_BUFFER, EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT
    161 
    162 		switch (m_createType)
    163 		{
    164 			case LEGACY:
    165 			{
    166 				if ((windowFactory.getCapabilities() & eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY) == 0)
    167 					TCU_THROW(NotSupportedError, "Native window doesn't support legacy eglCreateWindowSurface()");
    168 			}
    169 			break;
    170 			case EXTENSION:
    171 			{
    172 				if ((windowFactory.getCapabilities() & eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM_EXTENSION) == 0)
    173 					TCU_THROW(NotSupportedError, "Native window doesn't support eglCreatePlatformWindowSurfaceEXT()");
    174 			}
    175 			break;
    176 			case EGL15:
    177 			{
    178 				if ((windowFactory.getCapabilities() & eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM) == 0)
    179 					TCU_THROW(NotSupportedError, "Native window doesn't support eglCreatePlatformWindowSurface()");
    180 			}
    181 			break;
    182 		}
    183 
    184 		log << TestLog::Message << "Creating window surface with config ID " << id << TestLog::EndMessage;
    185 		EGLU_CHECK_MSG(egl, "init");
    186 
    187 		{
    188 			const int							width			= 64;
    189 			const int							height			= 64;
    190 			de::UniquePtr<eglu::NativeWindow>	window			(windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(width, height, eglu::parseWindowVisibility(m_testCtx.getCommandLine()))));
    191 			eglu::UniqueSurface					surface			(egl, display, createWindowSurface(display, config, m_eglTestCtx.getNativeDisplay(), *window, m_createType));
    192 
    193 			EGLint								windowWidth		= 0;
    194 			EGLint								windowHeight	= 0;
    195 
    196 			EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_WIDTH,		&windowWidth));
    197 			EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_HEIGHT,	&windowHeight));
    198 
    199 			if (windowWidth <= 0 || windowHeight <= 0)
    200 			{
    201 				log << TestLog::Message << "  Fail, invalid surface size " << windowWidth << "x" << windowHeight << TestLog::EndMessage;
    202 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface size");
    203 			}
    204 			else
    205 				log << TestLog::Message << "  Pass" << TestLog::EndMessage;
    206 		}
    207 	}
    208 
    209 private:
    210 	ApiType		m_createType;
    211 };
    212 
    213 class CreatePixmapSurfaceCase : public SimpleConfigCase
    214 {
    215 public:
    216 	CreatePixmapSurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, ApiType createType, const eglu::FilterList& filters)
    217 		: SimpleConfigCase(eglTestCtx, name, description, filters)
    218 		, m_createType	(createType)
    219 	{
    220 	}
    221 
    222 	void executeForConfig (EGLDisplay display, EGLConfig config)
    223 	{
    224 		const Library&						egl				= m_eglTestCtx.getLibrary();
    225 		TestLog&							log				= m_testCtx.getLog();
    226 		EGLint								id				= eglu::getConfigID(egl, display, config);
    227 		const eglu::NativePixmapFactory&	pixmapFactory	= eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
    228 
    229 		// \todo [2011-03-23 pyry] Iterate thru all possible combinations of EGL_RENDER_BUFFER, EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT
    230 
    231 		switch (m_createType)
    232 		{
    233 			case LEGACY:
    234 			{
    235 				if ((pixmapFactory.getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY) == 0)
    236 					TCU_THROW(NotSupportedError, "Native pixmap doesn't support legacy eglCreatePixmapSurface()");
    237 			}
    238 			break;
    239 			case EXTENSION:
    240 			{
    241 				if ((pixmapFactory.getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM_EXTENSION) == 0)
    242 					TCU_THROW(NotSupportedError, "Native pixmap doesn't support eglCreatePlatformPixmapSurfaceEXT()");
    243 			}
    244 			break;
    245 			case EGL15:
    246 			{
    247 				if ((pixmapFactory.getCapabilities() & eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM) == 0)
    248 					TCU_THROW(NotSupportedError, "Native pixmap doesn't support eglCreatePlatformPixmapSurface()");
    249 			}
    250 			break;
    251 		};
    252 
    253 		log << TestLog::Message << "Creating pixmap surface with config ID " << id << TestLog::EndMessage;
    254 		EGLU_CHECK_MSG(egl, "init");
    255 
    256 		{
    257 			const int							width			= 64;
    258 			const int							height			= 64;
    259 			de::UniquePtr<eglu::NativePixmap>	pixmap			(pixmapFactory.createPixmap(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, width, height));
    260 			eglu::UniqueSurface					surface			(egl, display, createPixmapSurface(display, config, m_eglTestCtx.getNativeDisplay(), *pixmap, m_createType));
    261 			EGLint								pixmapWidth		= 0;
    262 			EGLint								pixmapHeight	= 0;
    263 
    264 			EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_WIDTH,		&pixmapWidth));
    265 			EGLU_CHECK_CALL(egl, querySurface(display, *surface, EGL_HEIGHT,	&pixmapHeight));
    266 
    267 			if (pixmapWidth <= 0 || pixmapHeight <= 0)
    268 			{
    269 				log << TestLog::Message << "  Fail, invalid surface size " << pixmapWidth << "x" << pixmapHeight << TestLog::EndMessage;
    270 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid surface size");
    271 			}
    272 			else
    273 				log << TestLog::Message << "  Pass" << TestLog::EndMessage;
    274 		}
    275 	}
    276 
    277 private:
    278 	ApiType		m_createType;
    279 };
    280 
    281 class CreatePbufferSurfaceCase : public SimpleConfigCase
    282 {
    283 public:
    284 	CreatePbufferSurfaceCase (EglTestContext& eglTestCtx, const char* name, const char* description, const eglu::FilterList& filters)
    285 		: SimpleConfigCase(eglTestCtx, name, description, filters)
    286 	{
    287 	}
    288 
    289 	void executeForConfig (EGLDisplay display, EGLConfig config)
    290 	{
    291 		const Library&	egl		= m_eglTestCtx.getLibrary();
    292 		TestLog&		log		= m_testCtx.getLog();
    293 		EGLint			id		= eglu::getConfigID(egl, display, config);
    294 		int				width	= 64;
    295 		int				height	= 64;
    296 
    297 		// \todo [2011-03-23 pyry] Iterate thru all possible combinations of EGL_RENDER_BUFFER, EGL_VG_COLORSPACE and EGL_VG_ALPHA_FORMAT
    298 
    299 		log << TestLog::Message << "Creating pbuffer surface with config ID " << id << TestLog::EndMessage;
    300 		EGLU_CHECK_MSG(egl, "init");
    301 
    302 		// Clamp to maximums reported by implementation
    303 		width	= deMin32(width, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_WIDTH));
    304 		height	= deMin32(height, eglu::getConfigAttribInt(egl, display, config, EGL_MAX_PBUFFER_HEIGHT));
    305 
    306 		if (width == 0 || height == 0)
    307 		{
    308 			log << TestLog::Message << "  Fail, maximum pbuffer size of " << width << "x" << height << " reported" << TestLog::EndMessage;
    309 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid maximum pbuffer size");
    310 			return;
    311 		}
    312 
    313 		// \todo [2011-03-23 pyry] Texture-backed variants!
    314 
    315 		const EGLint attribs[] =
    316 		{
    317 			EGL_WIDTH,			width,
    318 			EGL_HEIGHT,			height,
    319 			EGL_TEXTURE_FORMAT,	EGL_NO_TEXTURE,
    320 			EGL_NONE
    321 		};
    322 
    323 		EGLSurface surface = egl.createPbufferSurface(display, config, attribs);
    324 		EGLU_CHECK_MSG(egl, "Failed to create pbuffer");
    325 		TCU_CHECK(surface != EGL_NO_SURFACE);
    326 		egl.destroySurface(display, surface);
    327 
    328 		log << TestLog::Message << "  Pass" << TestLog::EndMessage;
    329 	}
    330 };
    331 
    332 } // anonymous
    333 
    334 CreateSurfaceTests::CreateSurfaceTests (EglTestContext& eglTestCtx)
    335 	: TestCaseGroup(eglTestCtx, "create_surface", "Basic surface construction tests")
    336 {
    337 }
    338 
    339 CreateSurfaceTests::~CreateSurfaceTests (void)
    340 {
    341 }
    342 
    343 template <deUint32 Type>
    344 static bool surfaceType (const eglu::CandidateConfig& c)
    345 {
    346 	return (c.surfaceType() & Type) == Type;
    347 }
    348 
    349 void CreateSurfaceTests::init (void)
    350 {
    351 	// Window surfaces
    352 	{
    353 		tcu::TestCaseGroup* windowGroup = new tcu::TestCaseGroup(m_testCtx, "window", "Window surfaces");
    354 		addChild(windowGroup);
    355 
    356 		eglu::FilterList baseFilters;
    357 		baseFilters << surfaceType<EGL_WINDOW_BIT>;
    358 
    359 		vector<NamedFilterList> filterLists;
    360 		getDefaultFilterLists(filterLists, baseFilters);
    361 
    362 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
    363 			windowGroup->addChild(new CreateWindowSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), LEGACY, *i));
    364 	}
    365 
    366 	// Pixmap surfaces
    367 	{
    368 		tcu::TestCaseGroup* pixmapGroup = new tcu::TestCaseGroup(m_testCtx, "pixmap", "Pixmap surfaces");
    369 		addChild(pixmapGroup);
    370 
    371 		eglu::FilterList baseFilters;
    372 		baseFilters << surfaceType<EGL_PIXMAP_BIT>;
    373 
    374 		vector<NamedFilterList> filterLists;
    375 		getDefaultFilterLists(filterLists, baseFilters);
    376 
    377 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
    378 			pixmapGroup->addChild(new CreatePixmapSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), LEGACY, *i));
    379 	}
    380 
    381 	// Pbuffer surfaces
    382 	{
    383 		tcu::TestCaseGroup* pbufferGroup = new tcu::TestCaseGroup(m_testCtx, "pbuffer", "Pbuffer surfaces");
    384 		addChild(pbufferGroup);
    385 
    386 		eglu::FilterList baseFilters;
    387 		baseFilters << surfaceType<EGL_PBUFFER_BIT>;
    388 
    389 		vector<NamedFilterList> filterLists;
    390 		getDefaultFilterLists(filterLists, baseFilters);
    391 
    392 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
    393 			pbufferGroup->addChild(new CreatePbufferSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
    394 	}
    395 
    396 	// Window surfaces with new platform extension
    397 	{
    398 		tcu::TestCaseGroup* windowGroup = new tcu::TestCaseGroup(m_testCtx, "platform_ext_window", "Window surfaces with platform extension");
    399 		addChild(windowGroup);
    400 
    401 		eglu::FilterList baseFilters;
    402 		baseFilters << surfaceType<EGL_WINDOW_BIT>;
    403 
    404 		vector<NamedFilterList> filterLists;
    405 		getDefaultFilterLists(filterLists, baseFilters);
    406 
    407 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
    408 			windowGroup->addChild(new CreateWindowSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), EXTENSION, *i));
    409 	}
    410 
    411 	// Pixmap surfaces with new platform extension
    412 	{
    413 		tcu::TestCaseGroup* pixmapGroup = new tcu::TestCaseGroup(m_testCtx, "platform_ext_pixmap", "Pixmap surfaces with platform extension");
    414 		addChild(pixmapGroup);
    415 
    416 		eglu::FilterList baseFilters;
    417 		baseFilters << surfaceType<EGL_PIXMAP_BIT>;
    418 
    419 		vector<NamedFilterList> filterLists;
    420 		getDefaultFilterLists(filterLists, baseFilters);
    421 
    422 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
    423 			pixmapGroup->addChild(new CreatePixmapSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), EXTENSION, *i));
    424 	}
    425 	//
    426 	// Window surfaces with EGL 1.5 CreateWindowSurface
    427 	{
    428 		tcu::TestCaseGroup* windowGroup = new tcu::TestCaseGroup(m_testCtx, "platform_window", "Window surfaces with EGL 1.5");
    429 		addChild(windowGroup);
    430 
    431 		eglu::FilterList baseFilters;
    432 		baseFilters << surfaceType<EGL_WINDOW_BIT>;
    433 
    434 		vector<NamedFilterList> filterLists;
    435 		getDefaultFilterLists(filterLists, baseFilters);
    436 
    437 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
    438 			windowGroup->addChild(new CreateWindowSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), EGL15, *i));
    439 	}
    440 
    441 	// Pixmap surfaces with EGL 1.5 CreateWindowSurface
    442 	{
    443 		tcu::TestCaseGroup* pixmapGroup = new tcu::TestCaseGroup(m_testCtx, "platform_pixmap", "Pixmap surfaces with EGL 1.5");
    444 		addChild(pixmapGroup);
    445 
    446 		eglu::FilterList baseFilters;
    447 		baseFilters << surfaceType<EGL_PIXMAP_BIT>;
    448 
    449 		vector<NamedFilterList> filterLists;
    450 		getDefaultFilterLists(filterLists, baseFilters);
    451 
    452 		for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
    453 			pixmapGroup->addChild(new CreatePixmapSurfaceCase(m_eglTestCtx, i->getName(), i->getDescription(), EGL15, *i));
    454 	}
    455 }
    456 
    457 } // egl
    458 } // deqp
    459