Home | History | Annotate | Download | only in egl
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program Tester Core
      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 GL context factory using EGL.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "egluGLContextFactory.hpp"
     25 
     26 #include "tcuRenderTarget.hpp"
     27 #include "tcuPlatform.hpp"
     28 #include "tcuCommandLine.hpp"
     29 
     30 #include "gluDefs.hpp"
     31 
     32 #include "egluDefs.hpp"
     33 #include "egluUtil.hpp"
     34 #include "egluGLUtil.hpp"
     35 #include "egluNativeWindow.hpp"
     36 #include "egluNativePixmap.hpp"
     37 #include "egluStrUtil.hpp"
     38 
     39 #include "eglwLibrary.hpp"
     40 #include "eglwEnums.hpp"
     41 
     42 #include "glwInitFunctions.hpp"
     43 #include "glwInitES20Direct.hpp"
     44 #include "glwInitES30Direct.hpp"
     45 
     46 #include "deDynamicLibrary.hpp"
     47 #include "deSTLUtil.hpp"
     48 
     49 #include <string>
     50 #include <string>
     51 #include <sstream>
     52 
     53 using std::string;
     54 using std::vector;
     55 
     56 // \todo [2014-03-12 pyry] Use command line arguments for libraries?
     57 
     58 // Default library names
     59 #if !defined(DEQP_GLES2_LIBRARY_PATH)
     60 #	if (DE_OS == DE_OS_WIN32)
     61 #		define DEQP_GLES2_LIBRARY_PATH "libGLESv2.dll"
     62 #	else
     63 #		define DEQP_GLES2_LIBRARY_PATH "libGLESv2.so"
     64 #	endif
     65 #endif
     66 
     67 #if !defined(DEQP_GLES3_LIBRARY_PATH)
     68 #	define DEQP_GLES3_LIBRARY_PATH DEQP_GLES2_LIBRARY_PATH
     69 #endif
     70 
     71 #if !defined(DEQP_OPENGL_LIBRARY_PATH)
     72 #	if (DE_OS == DE_OS_WIN32)
     73 #		define DEQP_OPENGL_LIBRARY_PATH "opengl32.dll"
     74 #	else
     75 #		define DEQP_OPENGL_LIBRARY_PATH "libGL.so"
     76 #	endif
     77 #endif
     78 
     79 namespace eglu
     80 {
     81 
     82 using namespace eglw;
     83 
     84 namespace
     85 {
     86 
     87 enum
     88 {
     89 	DEFAULT_OFFSCREEN_WIDTH		= 512,
     90 	DEFAULT_OFFSCREEN_HEIGHT	= 512
     91 };
     92 
     93 class GetProcFuncLoader : public glw::FunctionLoader
     94 {
     95 public:
     96 	GetProcFuncLoader (const Library& egl)
     97 		: m_egl(egl)
     98 	{
     99 	}
    100 
    101 	glw::GenericFuncType get (const char* name) const
    102 	{
    103 		return (glw::GenericFuncType)m_egl.getProcAddress(name);
    104 	}
    105 
    106 protected:
    107 	const Library& m_egl;
    108 };
    109 
    110 class DynamicFuncLoader : public glw::FunctionLoader
    111 {
    112 public:
    113 	DynamicFuncLoader	(de::DynamicLibrary* library)
    114 		: m_library(library)
    115 	{
    116 	}
    117 
    118 	glw::GenericFuncType get (const char* name) const
    119 	{
    120 		return (glw::GenericFuncType)m_library->getFunction(name);
    121 	}
    122 
    123 private:
    124 	de::DynamicLibrary*	m_library;
    125 };
    126 
    127 class RenderContext : public GLRenderContext
    128 {
    129 public:
    130 										RenderContext			(const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config);
    131 	virtual								~RenderContext			(void);
    132 
    133 	virtual glu::ContextType			getType					(void) const { return m_renderConfig.type;	}
    134 	virtual const glw::Functions&		getFunctions			(void) const { return m_glFunctions;		}
    135 	virtual const tcu::RenderTarget&	getRenderTarget			(void) const { return m_glRenderTarget;		}
    136 	virtual void						postIterate				(void);
    137 
    138 	virtual EGLDisplay					getEGLDisplay			(void) const { return m_eglDisplay;			}
    139 	virtual EGLContext					getEGLContext			(void) const { return m_eglContext;			}
    140 
    141 private:
    142 	void								create					(const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config);
    143 	void								destroy					(void);
    144 
    145 	const glu::RenderConfig				m_renderConfig;
    146 	const NativeWindowFactory* const	m_nativeWindowFactory;	// Stored in case window must be re-created
    147 
    148 	NativeDisplay*						m_display;
    149 	NativeWindow*						m_window;
    150 	NativePixmap*						m_pixmap;
    151 
    152 	EGLDisplay							m_eglDisplay;
    153 	EGLConfig							m_eglConfig;
    154 	EGLSurface							m_eglSurface;
    155 	EGLContext							m_eglContext;
    156 
    157 	tcu::RenderTarget					m_glRenderTarget;
    158 	de::DynamicLibrary*					m_dynamicGLLibrary;
    159 	glw::Functions						m_glFunctions;
    160 };
    161 
    162 RenderContext::RenderContext (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config)
    163 	: m_renderConfig		(config)
    164 	, m_nativeWindowFactory	(windowFactory)
    165 	, m_display				(DE_NULL)
    166 	, m_window				(DE_NULL)
    167 	, m_pixmap				(DE_NULL)
    168 
    169 	, m_eglDisplay			(EGL_NO_DISPLAY)
    170 	, m_eglSurface			(EGL_NO_SURFACE)
    171 	, m_eglContext			(EGL_NO_CONTEXT)
    172 
    173 	, m_dynamicGLLibrary	(DE_NULL)
    174 {
    175 	DE_ASSERT(displayFactory);
    176 
    177 	try
    178 	{
    179 		create(displayFactory, windowFactory, pixmapFactory, config);
    180 	}
    181 	catch (...)
    182 	{
    183 		destroy();
    184 		throw;
    185 	}
    186 }
    187 
    188 RenderContext::~RenderContext(void)
    189 {
    190 	try
    191 	{
    192 		destroy();
    193 	}
    194 	catch (...)
    195 	{
    196 		// destroy() calls EGL functions that are checked and may throw exceptions
    197 	}
    198 
    199 	delete m_window;
    200 	delete m_pixmap;
    201 	delete m_display;
    202 	delete m_dynamicGLLibrary;
    203 }
    204 
    205 static WindowParams::Visibility getNativeWindowVisibility (glu::RenderConfig::Visibility visibility)
    206 {
    207 	using glu::RenderConfig;
    208 
    209 	switch (visibility)
    210 	{
    211 		case RenderConfig::VISIBILITY_HIDDEN:		return WindowParams::VISIBILITY_HIDDEN;
    212 		case RenderConfig::VISIBILITY_VISIBLE:		return WindowParams::VISIBILITY_VISIBLE;
    213 		case RenderConfig::VISIBILITY_FULLSCREEN:	return WindowParams::VISIBILITY_FULLSCREEN;
    214 		default:
    215 			DE_ASSERT((int)visibility == RenderConfig::DONT_CARE);
    216 			return WindowParams::VISIBILITY_DONT_CARE;
    217 	}
    218 }
    219 
    220 typedef std::pair<NativeWindow*, EGLSurface> WindowSurfacePair;
    221 typedef std::pair<NativePixmap*, EGLSurface> PixmapSurfacePair;
    222 
    223 WindowSurfacePair createWindow (NativeDisplay* nativeDisplay, const NativeWindowFactory* windowFactory, EGLDisplay eglDisplay, EGLConfig eglConfig, const glu::RenderConfig& config)
    224 {
    225 	const int						width			= (config.width		== glu::RenderConfig::DONT_CARE ? WindowParams::SIZE_DONT_CARE	: config.width);
    226 	const int						height			= (config.height	== glu::RenderConfig::DONT_CARE ? WindowParams::SIZE_DONT_CARE	: config.height);
    227 	const WindowParams::Visibility	visibility		= getNativeWindowVisibility(config.windowVisibility);
    228 	NativeWindow*					nativeWindow	= DE_NULL;
    229 	EGLSurface						surface			= EGL_NO_SURFACE;
    230 	const EGLAttrib					attribList[]	= { EGL_NONE };
    231 
    232 	nativeWindow = windowFactory->createWindow(nativeDisplay, eglDisplay, eglConfig, &attribList[0], WindowParams(width, height, visibility));
    233 
    234 	try
    235 	{
    236 		surface = eglu::createWindowSurface(*nativeDisplay, *nativeWindow, eglDisplay, eglConfig, attribList);
    237 	}
    238 	catch (...)
    239 	{
    240 		delete nativeWindow;
    241 		throw;
    242 	}
    243 
    244 	return WindowSurfacePair(nativeWindow, surface);
    245 }
    246 
    247 PixmapSurfacePair createPixmap (NativeDisplay* nativeDisplay, const NativePixmapFactory* pixmapFactory, EGLDisplay eglDisplay, EGLConfig eglConfig, const glu::RenderConfig& config)
    248 {
    249 	const int			width			= (config.width		== glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_WIDTH	: config.width);
    250 	const int			height			= (config.height	== glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_HEIGHT	: config.height);
    251 	NativePixmap*		nativePixmap	= DE_NULL;
    252 	EGLSurface			surface			= EGL_NO_SURFACE;
    253 	const EGLAttrib		attribList[]	= { EGL_NONE };
    254 
    255 	nativePixmap = pixmapFactory->createPixmap(nativeDisplay, eglDisplay, eglConfig, &attribList[0], width, height);
    256 
    257 	try
    258 	{
    259 		surface = eglu::createPixmapSurface(*nativeDisplay, *nativePixmap, eglDisplay, eglConfig, attribList);
    260 	}
    261 	catch (...)
    262 	{
    263 		delete nativePixmap;
    264 		throw;
    265 	}
    266 
    267 	return PixmapSurfacePair(nativePixmap, surface);
    268 }
    269 
    270 EGLSurface createPBuffer (const Library& egl, EGLDisplay display, EGLConfig eglConfig, const glu::RenderConfig& config)
    271 {
    272 	const int		width			= (config.width		== glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_WIDTH	: config.width);
    273 	const int		height			= (config.height	== glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_HEIGHT	: config.height);
    274 	EGLSurface		surface;
    275 	const EGLint	attribList[]	=
    276 	{
    277 		EGL_WIDTH,	width,
    278 		EGL_HEIGHT,	height,
    279 		EGL_NONE
    280 	};
    281 
    282 	surface = egl.createPbufferSurface(display, eglConfig, &(attribList[0]));
    283 	EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()");
    284 
    285 	return surface;
    286 }
    287 
    288 void RenderContext::create (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config)
    289 {
    290 	glu::RenderConfig::SurfaceType	surfaceType	= config.surfaceType;
    291 
    292 	DE_ASSERT(displayFactory);
    293 
    294 	m_display		= displayFactory->createDisplay();
    295 	m_eglDisplay	= eglu::getDisplay(*m_display);
    296 
    297 	const Library& egl = m_display->getLibrary();
    298 
    299 	{
    300 		EGLint major = 0;
    301 		EGLint minor = 0;
    302 		EGLU_CHECK_CALL(egl, initialize(m_eglDisplay, &major, &minor));
    303 	}
    304 
    305 	m_eglConfig	= chooseConfig(egl, m_eglDisplay, config);
    306 
    307 	if (surfaceType == glu::RenderConfig::SURFACETYPE_DONT_CARE)
    308 	{
    309 		// Choose based on what selected configuration supports
    310 		const EGLint supportedTypes = eglu::getConfigAttribInt(egl, m_eglDisplay, m_eglConfig, EGL_SURFACE_TYPE);
    311 
    312 		if ((supportedTypes & EGL_WINDOW_BIT) != 0)
    313 			surfaceType = glu::RenderConfig::SURFACETYPE_WINDOW;
    314 		else if ((supportedTypes & EGL_PBUFFER_BIT) != 0)
    315 			surfaceType = glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC;
    316 		else if ((supportedTypes & EGL_PIXMAP_BIT) != 0)
    317 			surfaceType = glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE;
    318 		else
    319 			throw tcu::NotSupportedError("Selected EGL config doesn't support any surface types", DE_NULL, __FILE__, __LINE__);
    320 	}
    321 
    322 	switch (surfaceType)
    323 	{
    324 		case glu::RenderConfig::SURFACETYPE_WINDOW:
    325 		{
    326 			if (windowFactory)
    327 			{
    328 				const WindowSurfacePair windowSurface = createWindow(m_display, windowFactory, m_eglDisplay, m_eglConfig, config);
    329 				m_window		= windowSurface.first;
    330 				m_eglSurface	= windowSurface.second;
    331 			}
    332 			else
    333 				throw tcu::NotSupportedError("EGL platform doesn't support windows", DE_NULL, __FILE__, __LINE__);
    334 			break;
    335 		}
    336 
    337 		case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:
    338 		{
    339 			if (pixmapFactory)
    340 			{
    341 				const PixmapSurfacePair pixmapSurface = createPixmap(m_display, pixmapFactory, m_eglDisplay, m_eglConfig, config);
    342 				m_pixmap		= pixmapSurface.first;
    343 				m_eglSurface	= pixmapSurface.second;
    344 			}
    345 			else
    346 				throw tcu::NotSupportedError("EGL platform doesn't support pixmaps", DE_NULL, __FILE__, __LINE__);
    347 			break;
    348 		}
    349 
    350 		case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:
    351 			m_eglSurface = createPBuffer(egl, m_eglDisplay, m_eglConfig, config);
    352 			break;
    353 
    354 		default:
    355 			throw tcu::InternalError("Invalid surface type");
    356 	}
    357 
    358 	m_eglContext = createGLContext(egl, m_eglDisplay, m_eglConfig, config.type);
    359 
    360 	EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
    361 
    362 	// Init core functions
    363 
    364 	if (hasExtension(egl, m_eglDisplay, "EGL_KHR_get_all_proc_addresses"))
    365 	{
    366 		// Use eglGetProcAddress() for core functions
    367 		GetProcFuncLoader funcLoader(egl);
    368 		glu::initCoreFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
    369 	}
    370 #if !defined(DEQP_GLES2_RUNTIME_LOAD)
    371 	else if (config.type.getAPI() == glu::ApiType::es(2,0))
    372 	{
    373 		glw::initES20Direct(&m_glFunctions);
    374 	}
    375 #endif
    376 #if !defined(DEQP_GLES3_RUNTIME_LOAD)
    377 	else if (config.type.getAPI() == glu::ApiType::es(3,0))
    378 	{
    379 		glw::initES30Direct(&m_glFunctions);
    380 	}
    381 #endif
    382 	else
    383 	{
    384 		const char* libraryPath = DE_NULL;
    385 
    386 		if (glu::isContextTypeES(config.type))
    387 		{
    388 			if (config.type.getMinorVersion() <= 2)
    389 				libraryPath = DEQP_GLES2_LIBRARY_PATH;
    390 			else
    391 				libraryPath = DEQP_GLES3_LIBRARY_PATH;
    392 		}
    393 		else
    394 			libraryPath = DEQP_OPENGL_LIBRARY_PATH;
    395 
    396 		m_dynamicGLLibrary = new de::DynamicLibrary(libraryPath);
    397 
    398 		DynamicFuncLoader funcLoader(m_dynamicGLLibrary);
    399 		glu::initCoreFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
    400 	}
    401 
    402 	// Init extension functions
    403 	{
    404 		GetProcFuncLoader extLoader(egl);
    405 		glu::initExtensionFunctions(&m_glFunctions, &extLoader, config.type.getAPI());
    406 	}
    407 
    408 	{
    409 		EGLint				width, height, depthBits, stencilBits, numSamples;
    410 		tcu::PixelFormat	pixelFmt;
    411 
    412 		egl.querySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH,		&width);
    413 		egl.querySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT,	&height);
    414 
    415 		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_RED_SIZE,		&pixelFmt.redBits);
    416 		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_GREEN_SIZE,		&pixelFmt.greenBits);
    417 		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_BLUE_SIZE,		&pixelFmt.blueBits);
    418 		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_ALPHA_SIZE,		&pixelFmt.alphaBits);
    419 
    420 		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_DEPTH_SIZE,		&depthBits);
    421 		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_STENCIL_SIZE,	&stencilBits);
    422 		egl.getConfigAttrib(m_eglDisplay, m_eglConfig, EGL_SAMPLES,			&numSamples);
    423 
    424 		EGLU_CHECK_MSG(egl, "Failed to query config attributes");
    425 
    426 		m_glRenderTarget = tcu::RenderTarget(width, height, pixelFmt, depthBits, stencilBits, numSamples);
    427 	}
    428 }
    429 
    430 void RenderContext::destroy (void)
    431 {
    432 	const Library& egl = m_display->getLibrary();
    433 
    434 	if (m_eglDisplay != EGL_NO_DISPLAY)
    435 	{
    436 		EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
    437 
    438 		if (m_eglSurface != EGL_NO_SURFACE)
    439 			EGLU_CHECK_CALL(egl, destroySurface(m_eglDisplay, m_eglSurface));
    440 
    441 		if (m_eglContext != EGL_NO_CONTEXT)
    442 			EGLU_CHECK_CALL(egl, destroyContext(m_eglDisplay, m_eglContext));
    443 
    444 		EGLU_CHECK_CALL(egl, terminate(m_eglDisplay));
    445 
    446 		m_eglDisplay	= EGL_NO_DISPLAY;
    447 		m_eglSurface	= EGL_NO_SURFACE;
    448 		m_eglContext	= EGL_NO_CONTEXT;
    449 	}
    450 
    451 	delete m_window;
    452 	delete m_pixmap;
    453 	delete m_display;
    454 	delete m_dynamicGLLibrary;
    455 
    456 	m_window			= DE_NULL;
    457 	m_pixmap			= DE_NULL;
    458 	m_display			= DE_NULL;
    459 	m_dynamicGLLibrary	= DE_NULL;
    460 }
    461 
    462 void RenderContext::postIterate (void)
    463 {
    464 	const Library& egl = m_display->getLibrary();
    465 
    466 	if (m_window)
    467 	{
    468 		EGLBoolean	swapOk		= egl.swapBuffers(m_eglDisplay, m_eglSurface);
    469 		EGLint		error		= egl.getError();
    470 		const bool	badWindow	= error == EGL_BAD_SURFACE || error == EGL_BAD_NATIVE_WINDOW;
    471 
    472 		if (!swapOk && !badWindow)
    473 			throw tcu::ResourceError(string("eglSwapBuffers() failed: ") + getErrorStr(error).toString());
    474 
    475 		try
    476 		{
    477 			m_window->processEvents();
    478 		}
    479 		catch (const WindowDestroyedError&)
    480 		{
    481 			tcu::print("Warning: Window destroyed, recreating...\n");
    482 
    483 			EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
    484 			EGLU_CHECK_CALL(egl, destroySurface(m_eglDisplay, m_eglSurface));
    485 			m_eglSurface = EGL_NO_SURFACE;
    486 
    487 			delete m_window;
    488 			m_window = DE_NULL;
    489 
    490 			try
    491 			{
    492 				WindowSurfacePair windowSurface = createWindow(m_display, m_nativeWindowFactory, m_eglDisplay, m_eglConfig, m_renderConfig);
    493 				m_window		= windowSurface.first;
    494 				m_eglSurface	= windowSurface.second;
    495 
    496 				EGLU_CHECK_CALL(egl, makeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
    497 
    498 				swapOk	= EGL_TRUE;
    499 				error	= EGL_SUCCESS;
    500 			}
    501 			catch (const std::exception& e)
    502 			{
    503 				if (m_eglSurface)
    504 				{
    505 					egl.makeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    506 					egl.destroySurface(m_eglDisplay, m_eglSurface);
    507 					m_eglSurface = EGL_NO_SURFACE;
    508 				}
    509 
    510 				delete m_window;
    511 				m_window = DE_NULL;
    512 
    513 				throw tcu::ResourceError(string("Failed to re-create window: ") + e.what());
    514 			}
    515 		}
    516 
    517 		if (!swapOk)
    518 		{
    519 			DE_ASSERT(badWindow);
    520 			throw tcu::ResourceError(string("eglSwapBuffers() failed: ") + getErrorStr(error).toString());
    521 		}
    522 
    523 		// Refresh dimensions
    524 		{
    525 			int	newWidth	= 0;
    526 			int	newHeight	= 0;
    527 
    528 			egl.querySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH,		&newWidth);
    529 			egl.querySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT,	&newHeight);
    530 			EGLU_CHECK_MSG(egl, "Failed to query window size");
    531 
    532 			if (newWidth	!= m_glRenderTarget.getWidth() ||
    533 				newHeight	!= m_glRenderTarget.getHeight())
    534 			{
    535 				tcu::print("Warning: Window size changed (%dx%d -> %dx%d), test results might be invalid!\n",
    536 						   m_glRenderTarget.getWidth(), m_glRenderTarget.getHeight(), newWidth, newHeight);
    537 
    538 				m_glRenderTarget = tcu::RenderTarget(newWidth, newHeight,
    539 													 m_glRenderTarget.getPixelFormat(),
    540 													 m_glRenderTarget.getDepthBits(),
    541 													 m_glRenderTarget.getStencilBits(),
    542 													 m_glRenderTarget.getNumSamples());
    543 			}
    544 		}
    545 	}
    546 	else
    547 		m_glFunctions.flush();
    548 }
    549 
    550 } // anonymous
    551 
    552 GLContextFactory::GLContextFactory (const NativeDisplayFactoryRegistry& displayFactoryRegistry)
    553 	: glu::ContextFactory		("egl", "EGL OpenGL Context")
    554 	, m_displayFactoryRegistry	(displayFactoryRegistry)
    555 {
    556 }
    557 
    558 glu::RenderContext* GLContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine) const
    559 {
    560 	const NativeDisplayFactory& displayFactory = selectNativeDisplayFactory(m_displayFactoryRegistry, cmdLine);
    561 
    562 	const NativeWindowFactory*	windowFactory;
    563 	const NativePixmapFactory*	pixmapFactory;
    564 
    565 	try
    566 	{
    567 		windowFactory = &selectNativeWindowFactory(displayFactory, cmdLine);
    568 	}
    569 	catch (const tcu::NotSupportedError&)
    570 	{
    571 		windowFactory = DE_NULL;
    572 	}
    573 
    574 	try
    575 	{
    576 		pixmapFactory = &selectNativePixmapFactory(displayFactory, cmdLine);
    577 	}
    578 	catch (const tcu::NotSupportedError&)
    579 	{
    580 		pixmapFactory = DE_NULL;
    581 	}
    582 
    583 	return new RenderContext(&displayFactory, windowFactory, pixmapFactory, config);
    584 }
    585 
    586 } // eglu
    587