b6f79c4b8fabb6309439b053f17df76832217777
[platform/upstream/VK-GL-CTS.git] / framework / egl / egluGLContextFactory.cpp
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 "egluHeaderWrapper.hpp"
34 #include "egluUtil.hpp"
35 #include "egluNativeWindow.hpp"
36 #include "egluNativePixmap.hpp"
37
38 #include "glwInitFunctions.hpp"
39 #include "glwInitES20Direct.hpp"
40 #include "glwInitES30Direct.hpp"
41
42 #include "deDynamicLibrary.hpp"
43 #include "deSTLUtil.hpp"
44
45 #include <string>
46 #include <string>
47 #include <sstream>
48
49 using std::string;
50 using std::vector;
51
52 #if !defined(EGL_KHR_create_context)
53         #define EGL_KHR_create_context 1
54         #define EGL_CONTEXT_MAJOR_VERSION_KHR                                           0x3098
55         #define EGL_CONTEXT_MINOR_VERSION_KHR                                           0x30FB
56         #define EGL_CONTEXT_FLAGS_KHR                                                           0x30FC
57         #define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR                                     0x30FD
58         #define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR      0x31BD
59         #define EGL_NO_RESET_NOTIFICATION_KHR                                           0x31BE
60         #define EGL_LOSE_CONTEXT_ON_RESET_KHR                                           0x31BF
61         #define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR                                        0x00000001
62         #define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR           0x00000002
63         #define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR                        0x00000004
64         #define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR                         0x00000001
65         #define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR        0x00000002
66         #define EGL_OPENGL_ES3_BIT_KHR                                                          0x00000040
67 #endif // EGL_KHR_create_context
68
69 // \todo [2014-03-12 pyry] Use command line arguments for libraries?
70
71 // Default library names
72 #if !defined(DEQP_GLES2_LIBRARY_PATH)
73 #       if (DE_OS == DE_OS_WIN32)
74 #               define DEQP_GLES2_LIBRARY_PATH "libGLESv2.dll"
75 #       else
76 #               define DEQP_GLES2_LIBRARY_PATH "libGLESv2.so"
77 #       endif
78 #endif
79
80 #if !defined(DEQP_GLES3_LIBRARY_PATH)
81 #       define DEQP_GLES3_LIBRARY_PATH DEQP_GLES2_LIBRARY_PATH
82 #endif
83
84 #if !defined(DEQP_OPENGL_LIBRARY_PATH)
85 #       if (DE_OS == DE_OS_WIN32)
86 #               define DEQP_OPENGL_LIBRARY_PATH "opengl32.dll"
87 #       else
88 #               define DEQP_OPENGL_LIBRARY_PATH "libGL.so"
89 #       endif
90 #endif
91
92 namespace eglu
93 {
94
95 namespace
96 {
97
98 enum
99 {
100         DEFAULT_OFFSCREEN_WIDTH         = 512,
101         DEFAULT_OFFSCREEN_HEIGHT        = 512
102 };
103
104 class GetProcFuncLoader : public glw::FunctionLoader
105 {
106 public:
107         glw::GenericFuncType get (const char* name) const
108         {
109                 return (glw::GenericFuncType)eglGetProcAddress(name);
110         }
111 };
112
113 class DynamicFuncLoader : public glw::FunctionLoader
114 {
115 public:
116         DynamicFuncLoader       (de::DynamicLibrary* library)
117                 : m_library(library)
118         {
119         }
120
121         glw::GenericFuncType get (const char* name) const
122         {
123                 return (glw::GenericFuncType)m_library->getFunction(name);
124         }
125
126 private:
127         de::DynamicLibrary*     m_library;
128 };
129
130 class RenderContext : public GLRenderContext
131 {
132 public:
133                                                                                 RenderContext                   (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config);
134         virtual                                                         ~RenderContext                  (void);
135
136         virtual glu::ContextType                        getType                                 (void) const { return m_glContextType;  }
137         virtual const glw::Functions&           getFunctions                    (void) const { return m_glFunctions;    }
138         virtual const tcu::RenderTarget&        getRenderTarget                 (void) const { return m_glRenderTarget; }
139         virtual void                                            postIterate                             (void);
140
141         virtual EGLDisplay                                      getEGLDisplay                   (void) const { return m_eglDisplay;             }
142         virtual EGLContext                                      getEGLContext                   (void) const { return m_eglContext;             }
143
144 private:
145         void                                                            create                                  (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config);
146         void                                                            destroy                                 (void);
147
148         const glu::ContextType                          m_glContextType;
149
150         NativeDisplay*                                          m_display;
151         NativeWindow*                                           m_window;
152         NativePixmap*                                           m_pixmap;
153
154         EGLDisplay                                                      m_eglDisplay;
155         EGLConfig                                                       m_eglConfig;
156         EGLSurface                                                      m_eglSurface;
157         EGLContext                                                      m_eglContext;
158
159         tcu::RenderTarget                                       m_glRenderTarget;
160         de::DynamicLibrary*                                     m_dynamicGLLibrary;
161         glw::Functions                                          m_glFunctions;
162 };
163
164 RenderContext::RenderContext (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config)
165         : m_glContextType               (config.type)
166         , m_display                             (DE_NULL)
167         , m_window                              (DE_NULL)
168         , m_pixmap                              (DE_NULL)
169
170         , m_eglDisplay                  (EGL_NO_DISPLAY)
171         , m_eglSurface                  (EGL_NO_SURFACE)
172         , m_eglContext                  (EGL_NO_CONTEXT)
173
174         , m_dynamicGLLibrary    (DE_NULL)
175 {
176         DE_ASSERT(displayFactory);
177
178         try
179         {
180                 create(displayFactory, windowFactory, pixmapFactory, config);
181         }
182         catch (...)
183         {
184                 destroy();
185                 throw;
186         }
187 }
188
189 RenderContext::~RenderContext(void)
190 {
191         try
192         {
193                 destroy();
194         }
195         catch (...)
196         {
197                 // destroy() calls EGL functions that are checked and may throw exceptions
198         }
199
200         delete m_window;
201         delete m_pixmap;
202         delete m_display;
203         delete m_dynamicGLLibrary;
204 }
205
206 bool configMatches (EGLDisplay display, EGLConfig eglConfig, const glu::RenderConfig& renderConfig)
207 {
208         // \todo [2014-03-12 pyry] Check other attributes like double-buffer bit.
209
210         {
211                 EGLint          renderableType          = 0;
212                 EGLint          requiredRenderable      = 0;
213
214                 if (glu::isContextTypeES(renderConfig.type))
215                 {
216                         if (renderConfig.type.getMajorVersion() == 2)
217                                 requiredRenderable = EGL_OPENGL_ES2_BIT;
218                         else if (renderConfig.type.getMajorVersion() == 3)
219                                 requiredRenderable = EGL_OPENGL_ES3_BIT_KHR;
220                         else
221                                 throw tcu::NotSupportedError("Unsupported OpenGL ES version");
222                 }
223                 else
224                 {
225                         DE_ASSERT(glu::isContextTypeGLCore(renderConfig.type) || glu::isContextTypeGLCompatibility(renderConfig.type));
226                         requiredRenderable = EGL_OPENGL_BIT;
227                 }
228
229                 EGLU_CHECK_CALL(eglGetConfigAttrib(display, eglConfig, EGL_RENDERABLE_TYPE, &renderableType));
230
231                 if ((renderableType & requiredRenderable) == 0)
232                         return false;
233         }
234
235         if (renderConfig.surfaceType != (glu::RenderConfig::SurfaceType)glu::RenderConfig::DONT_CARE)
236         {
237                 EGLint          surfaceType             = 0;
238                 EGLint          requiredSurface = 0;
239
240                 switch (renderConfig.surfaceType)
241                 {
242                         case glu::RenderConfig::SURFACETYPE_WINDOW:                             requiredSurface = EGL_WINDOW_BIT;       break;
243                         case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:   requiredSurface = EGL_PIXMAP_BIT;       break;
244                         case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:  requiredSurface = EGL_PBUFFER_BIT;      break;
245                         default:
246                                 DE_ASSERT(false);
247                 }
248
249                 EGLU_CHECK_CALL(eglGetConfigAttrib(display, eglConfig, EGL_SURFACE_TYPE, &surfaceType));
250
251                 if ((surfaceType & requiredSurface) == 0)
252                         return false;
253         }
254
255         {
256                 static const struct
257                 {
258                         int     glu::RenderConfig::*field;
259                         EGLint attrib;
260                 } s_attribs[] =
261                 {
262                         { &glu::RenderConfig::id,                       EGL_CONFIG_ID           },
263                         { &glu::RenderConfig::redBits,          EGL_RED_SIZE            },
264                         { &glu::RenderConfig::greenBits,        EGL_GREEN_SIZE          },
265                         { &glu::RenderConfig::blueBits,         EGL_BLUE_SIZE           },
266                         { &glu::RenderConfig::alphaBits,        EGL_ALPHA_SIZE          },
267                         { &glu::RenderConfig::depthBits,        EGL_DEPTH_SIZE          },
268                         { &glu::RenderConfig::stencilBits,      EGL_STENCIL_SIZE        },
269                         { &glu::RenderConfig::numSamples,       EGL_SAMPLES                     },
270                 };
271
272                 for (int attribNdx = 0; attribNdx < DE_LENGTH_OF_ARRAY(s_attribs); attribNdx++)
273                 {
274                         if (renderConfig.*s_attribs[attribNdx].field != glu::RenderConfig::DONT_CARE)
275                         {
276                                 EGLint value = 0;
277                                 EGLU_CHECK_CALL(eglGetConfigAttrib(display, eglConfig, s_attribs[attribNdx].attrib, &value));
278                                 if (value != renderConfig.*s_attribs[attribNdx].field)
279                                         return false;
280                         }
281                 }
282         }
283
284         return true;
285 }
286
287 EGLConfig chooseConfig (EGLDisplay display, const glu::RenderConfig& config)
288 {
289         const std::vector<EGLConfig> configs = eglu::getConfigs(display);
290
291         for (vector<EGLConfig>::const_iterator iter = configs.begin(); iter != configs.end(); ++iter)
292         {
293                 if (configMatches(display, *iter, config))
294                         return *iter;
295         }
296
297         throw tcu::NotSupportedError("Matching EGL config not found", DE_NULL, __FILE__, __LINE__);
298 }
299
300 static WindowParams::Visibility getNativeWindowVisibility (glu::RenderConfig::Visibility visibility)
301 {
302         using glu::RenderConfig;
303
304         switch (visibility)
305         {
306                 case RenderConfig::VISIBILITY_HIDDEN:           return WindowParams::VISIBILITY_HIDDEN;
307                 case RenderConfig::VISIBILITY_VISIBLE:          return WindowParams::VISIBILITY_VISIBLE;
308                 case RenderConfig::VISIBILITY_FULLSCREEN:       return WindowParams::VISIBILITY_FULLSCREEN;
309                 default:
310                         DE_ASSERT(visibility == (RenderConfig::Visibility)RenderConfig::DONT_CARE);
311                         return WindowParams::VISIBILITY_DONT_CARE;
312         }
313 }
314
315 typedef std::pair<NativeWindow*, EGLSurface> WindowSurfacePair;
316 typedef std::pair<NativePixmap*, EGLSurface> PixmapSurfacePair;
317
318 WindowSurfacePair createWindow (NativeDisplay* nativeDisplay, const NativeWindowFactory* windowFactory, EGLDisplay eglDisplay, EGLConfig eglConfig, const glu::RenderConfig& config)
319 {
320         const int                                               width                   = (config.width         == glu::RenderConfig::DONT_CARE ? WindowParams::SIZE_DONT_CARE  : config.width);
321         const int                                               height                  = (config.height        == glu::RenderConfig::DONT_CARE ? WindowParams::SIZE_DONT_CARE  : config.height);
322         const WindowParams::Visibility  visibility              = getNativeWindowVisibility(config.windowVisibility);
323         NativeWindow*                                   nativeWindow    = DE_NULL;
324         EGLSurface                                              surface                 = EGL_NO_SURFACE;
325         const EGLAttrib                                 attribList[]    = { EGL_NONE };
326
327         nativeWindow = windowFactory->createWindow(nativeDisplay, eglDisplay, eglConfig, &attribList[0], WindowParams(width, height, visibility));
328
329         try
330         {
331                 surface = eglu::createWindowSurface(*nativeDisplay, *nativeWindow, eglDisplay, eglConfig, attribList);
332         }
333         catch (...)
334         {
335                 delete nativeWindow;
336                 throw;
337         }
338
339         return WindowSurfacePair(nativeWindow, surface);
340 }
341
342 PixmapSurfacePair createPixmap (NativeDisplay* nativeDisplay, const NativePixmapFactory* pixmapFactory, EGLDisplay eglDisplay, EGLConfig eglConfig, const glu::RenderConfig& config)
343 {
344         const int                       width                   = (config.width         == glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_WIDTH       : config.width);
345         const int                       height                  = (config.height        == glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_HEIGHT      : config.height);
346         NativePixmap*           nativePixmap    = DE_NULL;
347         EGLSurface                      surface                 = EGL_NO_SURFACE;
348         const EGLAttrib         attribList[]    = { EGL_NONE };
349
350         nativePixmap = pixmapFactory->createPixmap(nativeDisplay, eglDisplay, eglConfig, &attribList[0], width, height);
351
352         try
353         {
354                 surface = eglu::createPixmapSurface(*nativeDisplay, *nativePixmap, eglDisplay, eglConfig, attribList);
355         }
356         catch (...)
357         {
358                 delete nativePixmap;
359                 throw;
360         }
361
362         return PixmapSurfacePair(nativePixmap, surface);
363 }
364
365 EGLSurface createPBuffer (EGLDisplay display, EGLConfig eglConfig, const glu::RenderConfig& config)
366 {
367         const int               width                   = (config.width         == glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_WIDTH       : config.width);
368         const int               height                  = (config.height        == glu::RenderConfig::DONT_CARE ? DEFAULT_OFFSCREEN_HEIGHT      : config.height);
369         EGLSurface              surface;
370         const EGLint    attribList[]    =
371         {
372                 EGL_WIDTH,      width,
373                 EGL_HEIGHT,     height,
374                 EGL_NONE
375         };
376
377         surface = eglCreatePbufferSurface(display, eglConfig, &(attribList[0]));
378         EGLU_CHECK_MSG("eglCreatePbufferSurface()");
379
380         return surface;
381 }
382
383 bool isClientExtensionSupported (EGLDisplay display, const std::string& extName)
384 {
385         const vector<string> exts = getClientExtensions(display);
386         return de::contains(exts.begin(), exts.end(), extName);
387 }
388
389 EGLContext createContext (EGLDisplay display, EGLContext eglConfig, const glu::RenderConfig& config)
390 {
391         const bool                      khrCreateContextSupported       = isClientExtensionSupported(display, "EGL_KHR_create_context");
392         EGLContext                      context                                         = EGL_NO_CONTEXT;
393         EGLenum                         api                                                     = EGL_NONE;
394         vector<EGLint>          attribList;
395
396         if (glu::isContextTypeES(config.type))
397         {
398                 api = EGL_OPENGL_ES_API;
399
400                 if (config.type.getMajorVersion() <= 2)
401                 {
402                         attribList.push_back(EGL_CONTEXT_CLIENT_VERSION);
403                         attribList.push_back(config.type.getMajorVersion());
404                 }
405                 else
406                 {
407                         if (!khrCreateContextSupported)
408                                 throw tcu::NotSupportedError("EGL_KHR_create_context is required for OpenGL ES 3.0 and newer", DE_NULL, __FILE__, __LINE__);
409
410                         attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
411                         attribList.push_back(config.type.getMajorVersion());
412                         attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
413                         attribList.push_back(config.type.getMinorVersion());
414                 }
415         }
416         else
417         {
418                 DE_ASSERT(glu::isContextTypeGLCore(config.type) || glu::isContextTypeGLCompatibility(config.type));
419
420                 if (!khrCreateContextSupported)
421                         throw tcu::NotSupportedError("EGL_KHR_create_context is required for OpenGL context creation", DE_NULL, __FILE__, __LINE__);
422
423                 api = EGL_OPENGL_API;
424
425                 attribList.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
426                 attribList.push_back(config.type.getMajorVersion());
427                 attribList.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
428                 attribList.push_back(config.type.getMinorVersion());
429                 attribList.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
430                 attribList.push_back(glu::isContextTypeGLCore(config.type) ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
431                                                                                                                                    : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
432         }
433
434         if (config.type.getFlags() != glu::ContextFlags(0))
435         {
436                 EGLint flags = 0;
437
438                 if (!khrCreateContextSupported)
439                         throw tcu::NotSupportedError("EGL_KHR_create_context is required for creating robust/debug/forward-compatible contexts");
440
441                 if ((config.type.getFlags() & glu::CONTEXT_DEBUG) != 0)
442                         flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
443
444                 if ((config.type.getFlags() & glu::CONTEXT_ROBUST) != 0)
445                         flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
446
447                 if ((config.type.getFlags() & glu::CONTEXT_FORWARD_COMPATIBLE) != 0)
448                 {
449                         if (!glu::isContextTypeGLCore(config.type))
450                                 throw tcu::NotSupportedError("Only OpenGL core contexts can be forward-compatible");
451
452                         flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
453                 }
454
455                 attribList.push_back(EGL_CONTEXT_FLAGS_KHR);
456                 attribList.push_back(flags);
457         }
458
459         attribList.push_back(EGL_NONE);
460
461         EGLU_CHECK_CALL(eglBindAPI(api));
462         context = eglCreateContext(display, eglConfig, EGL_NO_CONTEXT, &(attribList[0]));
463         EGLU_CHECK_MSG("eglCreateContext()");
464
465         return context;
466 }
467
468 void RenderContext::create (const NativeDisplayFactory* displayFactory, const NativeWindowFactory* windowFactory, const NativePixmapFactory* pixmapFactory, const glu::RenderConfig& config)
469 {
470         glu::RenderConfig::SurfaceType  surfaceType     = config.surfaceType;
471
472         DE_ASSERT(displayFactory);
473
474         m_display               = displayFactory->createDisplay();
475         m_eglDisplay    = eglu::getDisplay(*m_display);
476
477         {
478                 EGLint major = 0;
479                 EGLint minor = 0;
480                 EGLU_CHECK_CALL(eglInitialize(m_eglDisplay, &major, &minor));
481         }
482
483         m_eglConfig     = chooseConfig(m_eglDisplay, config);
484
485         if (surfaceType == glu::RenderConfig::SURFACETYPE_DONT_CARE)
486         {
487                 // Choose based on what selected configuration supports
488                 const EGLint supportedTypes = eglu::getConfigAttribInt(m_eglDisplay, m_eglConfig, EGL_SURFACE_TYPE);
489
490                 if ((supportedTypes & EGL_WINDOW_BIT) != 0)
491                         surfaceType = glu::RenderConfig::SURFACETYPE_WINDOW;
492                 else if ((supportedTypes & EGL_PBUFFER_BIT) != 0)
493                         surfaceType = glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC;
494                 else if ((supportedTypes & EGL_PIXMAP_BIT) != 0)
495                         surfaceType = glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE;
496                 else
497                         throw tcu::NotSupportedError("Selected EGL config doesn't support any surface types", DE_NULL, __FILE__, __LINE__);
498         }
499
500         switch (surfaceType)
501         {
502                 case glu::RenderConfig::SURFACETYPE_WINDOW:
503                 {
504                         if (windowFactory)
505                         {
506                                 const WindowSurfacePair windowSurface = createWindow(m_display, windowFactory, m_eglDisplay, m_eglConfig, config);
507                                 m_window                = windowSurface.first;
508                                 m_eglSurface    = windowSurface.second;
509                         }
510                         else
511                                 throw tcu::NotSupportedError("EGL platform doesn't support windows", DE_NULL, __FILE__, __LINE__);
512                         break;
513                 }
514
515                 case glu::RenderConfig::SURFACETYPE_OFFSCREEN_NATIVE:
516                 {
517                         if (pixmapFactory)
518                         {
519                                 const PixmapSurfacePair pixmapSurface = createPixmap(m_display, pixmapFactory, m_eglDisplay, m_eglConfig, config);
520                                 m_pixmap                = pixmapSurface.first;
521                                 m_eglSurface    = pixmapSurface.second;
522                         }
523                         else
524                                 throw tcu::NotSupportedError("EGL platform doesn't support pixmaps", DE_NULL, __FILE__, __LINE__);
525                         break;
526                 }
527
528                 case glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC:
529                         m_eglSurface = createPBuffer(m_eglDisplay, m_eglConfig, config);
530                         break;
531
532                 default:
533                         throw tcu::InternalError("Invalid surface type");
534         }
535
536         m_eglContext = createContext(m_eglDisplay, m_eglConfig, config);
537
538         EGLU_CHECK_CALL(eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
539
540         // Init core functions
541
542         if (isClientExtensionSupported(m_eglDisplay, "EGL_KHR_get_all_proc_addresses"))
543         {
544                 // Use eglGetProcAddress() for core functions
545                 GetProcFuncLoader funcLoader;
546                 glu::initCoreFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
547         }
548 #if !defined(DEQP_GLES2_RUNTIME_LOAD)
549         else if (config.type.getAPI() == glu::ApiType::es(2,0))
550         {
551                 glw::initES20Direct(&m_glFunctions);
552         }
553 #endif
554 #if !defined(DEQP_GLES3_RUNTIME_LOAD)
555         else if (config.type.getAPI() == glu::ApiType::es(3,0))
556         {
557                 glw::initES30Direct(&m_glFunctions);
558         }
559 #endif
560         else
561         {
562                 const char* libraryPath = DE_NULL;
563
564                 if (glu::isContextTypeES(config.type))
565                 {
566                         if (config.type.getMinorVersion() <= 2)
567                                 libraryPath = DEQP_GLES2_LIBRARY_PATH;
568                         else
569                                 libraryPath = DEQP_GLES3_LIBRARY_PATH;
570                 }
571                 else
572                         libraryPath = DEQP_OPENGL_LIBRARY_PATH;
573
574                 m_dynamicGLLibrary = new de::DynamicLibrary(libraryPath);
575
576                 DynamicFuncLoader funcLoader(m_dynamicGLLibrary);
577                 glu::initCoreFunctions(&m_glFunctions, &funcLoader, config.type.getAPI());
578         }
579
580         // Init extension functions
581         {
582                 GetProcFuncLoader extLoader;
583                 glu::initExtensionFunctions(&m_glFunctions, &extLoader, config.type.getAPI());
584         }
585
586         {
587                 EGLint                          width, height, depthBits, stencilBits, numSamples;
588                 tcu::PixelFormat        pixelFmt;
589
590                 eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH, &width);
591                 eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT, &height);
592
593                 eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_RED_SIZE,             &pixelFmt.redBits);
594                 eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_GREEN_SIZE,   &pixelFmt.greenBits);
595                 eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_BLUE_SIZE,    &pixelFmt.blueBits);
596                 eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_ALPHA_SIZE,   &pixelFmt.alphaBits);
597
598                 eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_DEPTH_SIZE,   &depthBits);
599                 eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_STENCIL_SIZE, &stencilBits);
600                 eglGetConfigAttrib(m_eglDisplay, m_eglConfig, EGL_SAMPLES,              &numSamples);
601
602                 EGLU_CHECK_MSG("Failed to query config attributes");
603
604                 m_glRenderTarget = tcu::RenderTarget(width, height, pixelFmt, depthBits, stencilBits, numSamples);
605         }
606 }
607
608 void RenderContext::destroy (void)
609 {
610         if (m_eglDisplay != EGL_NO_DISPLAY)
611         {
612                 EGLU_CHECK_CALL(eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
613
614                 if (m_eglSurface != EGL_NO_SURFACE)
615                         EGLU_CHECK_CALL(eglDestroySurface(m_eglDisplay, m_eglSurface));
616
617                 if (m_eglContext != EGL_NO_CONTEXT)
618                         EGLU_CHECK_CALL(eglDestroyContext(m_eglDisplay, m_eglContext));
619
620                 EGLU_CHECK_CALL(eglTerminate(m_eglDisplay));
621
622                 m_eglDisplay    = EGL_NO_DISPLAY;
623                 m_eglSurface    = EGL_NO_SURFACE;
624                 m_eglContext    = EGL_NO_CONTEXT;
625         }
626
627         delete m_window;
628         delete m_pixmap;
629         delete m_display;
630         delete m_dynamicGLLibrary;
631
632         m_window                        = DE_NULL;
633         m_pixmap                        = DE_NULL;
634         m_display                       = DE_NULL;
635         m_dynamicGLLibrary      = DE_NULL;
636 }
637
638 void RenderContext::postIterate (void)
639 {
640         if (m_window)
641         {
642                 EGLU_CHECK_CALL(eglSwapBuffers(m_eglDisplay, m_eglSurface));
643                 m_window->processEvents();
644         }
645         else
646         {
647                 // \todo [2014-05-02 mika] Should we call flush or finish? Old platform uses finish() but flush() is closer to the behaviour of eglSwapBuffers()
648                 m_glFunctions.flush();
649                 GLU_EXPECT_NO_ERROR(m_glFunctions.getError(), "glFlush()");
650         }
651 }
652
653 } // anonymous
654
655 GLContextFactory::GLContextFactory (const NativeDisplayFactoryRegistry& displayFactoryRegistry)
656         : glu::ContextFactory           ("egl", "EGL OpenGL Context")
657         , m_displayFactoryRegistry      (displayFactoryRegistry)
658 {
659 }
660
661 namespace
662 {
663
664 template<typename Factory>
665 const Factory* selectFactory (const tcu::FactoryRegistry<Factory>& registry, const char* objectTypeName, const char* cmdLineArg)
666 {
667         if (cmdLineArg[0] != 0)
668         {
669                 const Factory* factory = registry.getFactoryByName(cmdLineArg);
670
671                 if (factory)
672                         return factory;
673                 else
674                 {
675                         tcu::print("ERROR: Unknown or unsupported EGL %s type '%s'", objectTypeName, cmdLineArg);
676                         tcu::print("Available EGL %s types:\n", objectTypeName);
677                         for (size_t ndx = 0; ndx < registry.getFactoryCount(); ndx++)
678                                 tcu::print("  %s: %s\n", registry.getFactoryByIndex(ndx)->getName(), registry.getFactoryByIndex(ndx)->getDescription());
679
680                         throw tcu::NotSupportedError((string("Unsupported or unknown EGL ") + objectTypeName + " type '" + cmdLineArg + "'").c_str(), DE_NULL, __FILE__, __LINE__);
681                 }
682         }
683         else if (!registry.empty())
684                 return registry.getDefaultFactory();
685         else
686                 return DE_NULL;
687 }
688
689 } // anonymous
690
691 glu::RenderContext* GLContextFactory::createContext (const glu::RenderConfig& config, const tcu::CommandLine& cmdLine) const
692 {
693         const NativeDisplayFactory* displayFactory = selectFactory(m_displayFactoryRegistry, "display", cmdLine.getEGLDisplayType());
694
695         if (displayFactory)
696         {
697                 // \note windowFactory & pixmapFactory are not mandatory
698                 const NativeWindowFactory*      windowFactory   = selectFactory(displayFactory->getNativeWindowRegistry(), "window", cmdLine.getEGLWindowType());
699                 const NativePixmapFactory*      pixmapFactory   = selectFactory(displayFactory->getNativePixmapRegistry(), "pixmap", cmdLine.getEGLPixmapType());
700
701                 return new RenderContext(displayFactory, windowFactory, pixmapFactory, config);
702         }
703         else
704                 throw tcu::NotSupportedError("No EGL displays available", DE_NULL, __FILE__, __LINE__);
705 }
706
707 } // eglu