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