• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include "util/EGLWindow.h"
8 
9 #include <cassert>
10 #include <iostream>
11 #include <vector>
12 
13 #include <string.h>
14 
15 #include "platform/Platform.h"
16 #include "util/OSWindow.h"
17 #include "util/system_utils.h"
18 
19 // ConfigParameters implementation.
ConfigParameters()20 ConfigParameters::ConfigParameters()
21     : redBits(-1),
22       greenBits(-1),
23       blueBits(-1),
24       alphaBits(-1),
25       depthBits(-1),
26       stencilBits(-1),
27       componentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT),
28       multisample(false),
29       debug(false),
30       noError(false),
31       bindGeneratesResource(true),
32       clientArraysEnabled(true),
33       robustAccess(false),
34       samples(-1),
35       resetStrategy(EGL_NO_RESET_NOTIFICATION_EXT)
36 {}
37 
38 ConfigParameters::~ConfigParameters() = default;
39 
reset()40 void ConfigParameters::reset()
41 {
42     *this = ConfigParameters();
43 }
44 
45 // GLWindowBase implementation.
GLWindowBase(EGLint glesMajorVersion,EGLint glesMinorVersion)46 GLWindowBase::GLWindowBase(EGLint glesMajorVersion, EGLint glesMinorVersion)
47     : mClientMajorVersion(glesMajorVersion), mClientMinorVersion(glesMinorVersion)
48 {}
49 
50 GLWindowBase::~GLWindowBase() = default;
51 
52 // EGLWindow implementation.
EGLWindow(EGLint glesMajorVersion,EGLint glesMinorVersion)53 EGLWindow::EGLWindow(EGLint glesMajorVersion, EGLint glesMinorVersion)
54     : GLWindowBase(glesMajorVersion, glesMinorVersion),
55       mConfig(0),
56       mDisplay(EGL_NO_DISPLAY),
57       mSurface(EGL_NO_SURFACE),
58       mContext(EGL_NO_CONTEXT),
59       mEGLMajorVersion(0),
60       mEGLMinorVersion(0)
61 {}
62 
~EGLWindow()63 EGLWindow::~EGLWindow()
64 {
65     destroyGL();
66 }
67 
swap()68 void EGLWindow::swap()
69 {
70     eglSwapBuffers(mDisplay, mSurface);
71 }
72 
getConfig() const73 EGLConfig EGLWindow::getConfig() const
74 {
75     return mConfig;
76 }
77 
getDisplay() const78 EGLDisplay EGLWindow::getDisplay() const
79 {
80     return mDisplay;
81 }
82 
getSurface() const83 EGLSurface EGLWindow::getSurface() const
84 {
85     return mSurface;
86 }
87 
getContext() const88 EGLContext EGLWindow::getContext() const
89 {
90     return mContext;
91 }
92 
initializeGL(OSWindow * osWindow,angle::Library * glWindowingLibrary,const EGLPlatformParameters & platformParams,const ConfigParameters & configParams)93 bool EGLWindow::initializeGL(OSWindow *osWindow,
94                              angle::Library *glWindowingLibrary,
95                              const EGLPlatformParameters &platformParams,
96                              const ConfigParameters &configParams)
97 {
98     if (!initializeDisplay(osWindow, glWindowingLibrary, platformParams))
99         return false;
100     if (!initializeSurface(osWindow, glWindowingLibrary, configParams))
101         return false;
102     if (!initializeContext())
103         return false;
104     return true;
105 }
106 
initializeDisplay(OSWindow * osWindow,angle::Library * glWindowingLibrary,const EGLPlatformParameters & params)107 bool EGLWindow::initializeDisplay(OSWindow *osWindow,
108                                   angle::Library *glWindowingLibrary,
109                                   const EGLPlatformParameters &params)
110 {
111 #if defined(ANGLE_USE_UTIL_LOADER)
112     PFNEGLGETPROCADDRESSPROC getProcAddress;
113     glWindowingLibrary->getAs("eglGetProcAddress", &getProcAddress);
114     if (!getProcAddress)
115     {
116         return false;
117     }
118 
119     // Likely we will need to use a fallback to Library::getAs on non-ANGLE platforms.
120     angle::LoadEGL(getProcAddress);
121 #endif  // defined(ANGLE_USE_UTIL_LOADER)
122 
123     std::vector<EGLAttrib> displayAttributes;
124     displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
125     displayAttributes.push_back(params.renderer);
126     displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
127     displayAttributes.push_back(params.majorVersion);
128     displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
129     displayAttributes.push_back(params.minorVersion);
130 
131     if (params.deviceType != EGL_DONT_CARE)
132     {
133         displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
134         displayAttributes.push_back(params.deviceType);
135     }
136 
137     if (params.presentPath != EGL_DONT_CARE)
138     {
139         const char *extensionString =
140             static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
141         if (strstr(extensionString, "EGL_ANGLE_experimental_present_path") == nullptr)
142         {
143             destroyGL();
144             return false;
145         }
146 
147         displayAttributes.push_back(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE);
148         displayAttributes.push_back(params.presentPath);
149     }
150 
151     // Set debug layer settings if requested.
152     if (params.debugLayersEnabled != EGL_DONT_CARE)
153     {
154         displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
155         displayAttributes.push_back(params.debugLayersEnabled);
156     }
157 
158     if (params.contextVirtualization != EGL_DONT_CARE)
159     {
160         displayAttributes.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
161         displayAttributes.push_back(params.contextVirtualization);
162     }
163 
164     if (params.platformMethods)
165     {
166         static_assert(sizeof(EGLAttrib) == sizeof(params.platformMethods),
167                       "Unexpected pointer size");
168         displayAttributes.push_back(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX);
169         displayAttributes.push_back(reinterpret_cast<EGLAttrib>(params.platformMethods));
170     }
171 
172     displayAttributes.push_back(EGL_NONE);
173 
174     mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
175                                      reinterpret_cast<void *>(osWindow->getNativeDisplay()),
176                                      &displayAttributes[0]);
177     if (mDisplay == EGL_NO_DISPLAY)
178     {
179         destroyGL();
180         return false;
181     }
182 
183     if (eglInitialize(mDisplay, &mEGLMajorVersion, &mEGLMinorVersion) == EGL_FALSE)
184     {
185         destroyGL();
186         return false;
187     }
188 
189     mPlatform = params;
190     return true;
191 }
192 
initializeSurface(OSWindow * osWindow,angle::Library * glWindowingLibrary,const ConfigParameters & params)193 bool EGLWindow::initializeSurface(OSWindow *osWindow,
194                                   angle::Library *glWindowingLibrary,
195                                   const ConfigParameters &params)
196 {
197     mConfigParams                 = params;
198     const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
199 
200     std::vector<EGLint> configAttributes = {
201         EGL_RED_SIZE,
202         (mConfigParams.redBits >= 0) ? mConfigParams.redBits : EGL_DONT_CARE,
203         EGL_GREEN_SIZE,
204         (mConfigParams.greenBits >= 0) ? mConfigParams.greenBits : EGL_DONT_CARE,
205         EGL_BLUE_SIZE,
206         (mConfigParams.blueBits >= 0) ? mConfigParams.blueBits : EGL_DONT_CARE,
207         EGL_ALPHA_SIZE,
208         (mConfigParams.alphaBits >= 0) ? mConfigParams.alphaBits : EGL_DONT_CARE,
209         EGL_DEPTH_SIZE,
210         (mConfigParams.depthBits >= 0) ? mConfigParams.depthBits : EGL_DONT_CARE,
211         EGL_STENCIL_SIZE,
212         (mConfigParams.stencilBits >= 0) ? mConfigParams.stencilBits : EGL_DONT_CARE,
213         EGL_SAMPLE_BUFFERS,
214         mConfigParams.multisample ? 1 : 0,
215         EGL_SAMPLES,
216         (mConfigParams.samples >= 0) ? mConfigParams.samples : EGL_DONT_CARE,
217     };
218 
219     // Add dynamic attributes
220     bool hasPixelFormatFloat = strstr(displayExtensions, "EGL_EXT_pixel_format_float") != nullptr;
221     if (!hasPixelFormatFloat && mConfigParams.componentType != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)
222     {
223         destroyGL();
224         return false;
225     }
226     if (hasPixelFormatFloat)
227     {
228         configAttributes.push_back(EGL_COLOR_COMPONENT_TYPE_EXT);
229         configAttributes.push_back(mConfigParams.componentType);
230     }
231 
232     // Finish the attribute list
233     configAttributes.push_back(EGL_NONE);
234 
235     if (!FindEGLConfig(mDisplay, configAttributes.data(), &mConfig))
236     {
237         std::cout << "Could not find a suitable EGL config!" << std::endl;
238         destroyGL();
239         return false;
240     }
241 
242     eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &mConfigParams.redBits);
243     eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &mConfigParams.greenBits);
244     eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &mConfigParams.blueBits);
245     eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &mConfigParams.alphaBits);
246     eglGetConfigAttrib(mDisplay, mConfig, EGL_DEPTH_SIZE, &mConfigParams.depthBits);
247     eglGetConfigAttrib(mDisplay, mConfig, EGL_STENCIL_SIZE, &mConfigParams.stencilBits);
248     eglGetConfigAttrib(mDisplay, mConfig, EGL_SAMPLES, &mConfigParams.samples);
249 
250     std::vector<EGLint> surfaceAttributes;
251     if (strstr(displayExtensions, "EGL_NV_post_sub_buffer") != nullptr)
252     {
253         surfaceAttributes.push_back(EGL_POST_SUB_BUFFER_SUPPORTED_NV);
254         surfaceAttributes.push_back(EGL_TRUE);
255     }
256 
257     bool hasRobustResourceInit =
258         strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr;
259     if (hasRobustResourceInit && mConfigParams.robustResourceInit.valid())
260     {
261         surfaceAttributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
262         surfaceAttributes.push_back(mConfigParams.robustResourceInit.value() ? EGL_TRUE
263                                                                              : EGL_FALSE);
264     }
265 
266     surfaceAttributes.push_back(EGL_NONE);
267 
268     osWindow->resetNativeWindow();
269 
270     mSurface = eglCreateWindowSurface(mDisplay, mConfig, osWindow->getNativeWindow(),
271                                       &surfaceAttributes[0]);
272     if (eglGetError() != EGL_SUCCESS || (mSurface == EGL_NO_SURFACE))
273     {
274         destroyGL();
275         return false;
276     }
277 
278 #if defined(ANGLE_USE_UTIL_LOADER)
279     angle::LoadGLES(eglGetProcAddress);
280 #endif  // defined(ANGLE_USE_UTIL_LOADER)
281 
282     return true;
283 }
284 
createContext(EGLContext share) const285 EGLContext EGLWindow::createContext(EGLContext share) const
286 {
287     const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
288 
289     // EGL_KHR_create_context is required to request a ES3+ context.
290     bool hasKHRCreateContext = strstr(displayExtensions, "EGL_KHR_create_context") != nullptr;
291     if (mClientMajorVersion > 2 && !(mEGLMajorVersion > 1 || mEGLMinorVersion >= 5) &&
292         !hasKHRCreateContext)
293     {
294         std::cerr << "EGL_KHR_create_context incompatibility.\n";
295         return EGL_NO_CONTEXT;
296     }
297 
298     bool hasWebGLCompatibility =
299         strstr(displayExtensions, "EGL_ANGLE_create_context_webgl_compatibility") != nullptr;
300     if (mConfigParams.webGLCompatibility.valid() && !hasWebGLCompatibility)
301     {
302         std::cerr << "EGL_ANGLE_create_context_webgl_compatibility missing.\n";
303         return EGL_NO_CONTEXT;
304     }
305 
306     bool hasCreateContextExtensionsEnabled =
307         strstr(displayExtensions, "EGL_ANGLE_create_context_extensions_enabled") != nullptr;
308     if (mConfigParams.extensionsEnabled.valid() && !hasCreateContextExtensionsEnabled)
309     {
310         std::cerr << "EGL_ANGLE_create_context_extensions_enabled missing.\n";
311         return EGL_NO_CONTEXT;
312     }
313 
314     bool hasRobustness = strstr(displayExtensions, "EGL_EXT_create_context_robustness") != nullptr;
315     if ((mConfigParams.robustAccess ||
316          mConfigParams.resetStrategy != EGL_NO_RESET_NOTIFICATION_EXT) &&
317         !hasRobustness)
318     {
319         std::cerr << "EGL_EXT_create_context_robustness missing.\n";
320         return EGL_NO_CONTEXT;
321     }
322 
323     bool hasBindGeneratesResource =
324         strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr;
325     if (!mConfigParams.bindGeneratesResource && !hasBindGeneratesResource)
326     {
327         std::cerr << "EGL_CHROMIUM_create_context_bind_generates_resource missing.\n";
328         return EGL_NO_CONTEXT;
329     }
330 
331     bool hasClientArraysExtension =
332         strstr(displayExtensions, "EGL_ANGLE_create_context_client_arrays") != nullptr;
333     if (!mConfigParams.clientArraysEnabled && !hasClientArraysExtension)
334     {
335         // Non-default state requested without the extension present
336         std::cerr << "EGL_ANGLE_create_context_client_arrays missing.\n";
337         return EGL_NO_CONTEXT;
338     }
339 
340     bool hasProgramCacheControlExtension =
341         strstr(displayExtensions, "EGL_ANGLE_program_cache_control ") != nullptr;
342     if (mConfigParams.contextProgramCacheEnabled.valid() && !hasProgramCacheControlExtension)
343     {
344         std::cerr << "EGL_ANGLE_program_cache_control missing.\n";
345         return EGL_NO_CONTEXT;
346     }
347 
348     bool hasBackwardsCompatibleContextExtension =
349         strstr(displayExtensions, "EGL_ANGLE_create_context_backwards_compatible") != nullptr;
350     if (!hasProgramCacheControlExtension)
351     {
352         std::cerr << "EGL_ANGLE_create_context_backwards_compatible missing.\n";
353         return EGL_NO_CONTEXT;
354     }
355 
356     eglBindAPI(EGL_OPENGL_ES_API);
357     if (eglGetError() != EGL_SUCCESS)
358     {
359         std::cerr << "Error on eglBindAPI.\n";
360         return EGL_NO_CONTEXT;
361     }
362 
363     std::vector<EGLint> contextAttributes;
364     if (hasKHRCreateContext)
365     {
366         contextAttributes.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
367         contextAttributes.push_back(mClientMajorVersion);
368 
369         contextAttributes.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
370         contextAttributes.push_back(mClientMinorVersion);
371 
372         contextAttributes.push_back(EGL_CONTEXT_OPENGL_DEBUG);
373         contextAttributes.push_back(mConfigParams.debug ? EGL_TRUE : EGL_FALSE);
374 
375         // TODO(jmadill): Check for the extension string.
376         // bool hasKHRCreateContextNoError = strstr(displayExtensions,
377         // "EGL_KHR_create_context_no_error") != nullptr;
378 
379         contextAttributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
380         contextAttributes.push_back(mConfigParams.noError ? EGL_TRUE : EGL_FALSE);
381 
382         if (mConfigParams.webGLCompatibility.valid())
383         {
384             contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
385             contextAttributes.push_back(mConfigParams.webGLCompatibility.value() ? EGL_TRUE
386                                                                                  : EGL_FALSE);
387         }
388 
389         if (mConfigParams.extensionsEnabled.valid())
390         {
391             contextAttributes.push_back(EGL_EXTENSIONS_ENABLED_ANGLE);
392             contextAttributes.push_back(mConfigParams.extensionsEnabled.value() ? EGL_TRUE
393                                                                                 : EGL_FALSE);
394         }
395 
396         if (hasRobustness)
397         {
398             contextAttributes.push_back(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
399             contextAttributes.push_back(mConfigParams.robustAccess ? EGL_TRUE : EGL_FALSE);
400 
401             contextAttributes.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
402             contextAttributes.push_back(mConfigParams.resetStrategy);
403         }
404 
405         if (hasBindGeneratesResource)
406         {
407             contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
408             contextAttributes.push_back(mConfigParams.bindGeneratesResource ? EGL_TRUE : EGL_FALSE);
409         }
410 
411         if (hasClientArraysExtension)
412         {
413             contextAttributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE);
414             contextAttributes.push_back(mConfigParams.clientArraysEnabled ? EGL_TRUE : EGL_FALSE);
415         }
416 
417         if (mConfigParams.contextProgramCacheEnabled.valid())
418         {
419             contextAttributes.push_back(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
420             contextAttributes.push_back(
421                 mConfigParams.contextProgramCacheEnabled.value() ? EGL_TRUE : EGL_FALSE);
422         }
423 
424         if (hasBackwardsCompatibleContextExtension)
425         {
426             // Always request the exact context version that the config wants
427             contextAttributes.push_back(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
428             contextAttributes.push_back(EGL_FALSE);
429         }
430 
431         bool hasRobustResourceInit =
432             strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr;
433         if (hasRobustResourceInit && mConfigParams.robustResourceInit.valid())
434         {
435             contextAttributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
436             contextAttributes.push_back(mConfigParams.robustResourceInit.value() ? EGL_TRUE
437                                                                                  : EGL_FALSE);
438         }
439     }
440     contextAttributes.push_back(EGL_NONE);
441 
442     EGLContext context = eglCreateContext(mDisplay, mConfig, nullptr, &contextAttributes[0]);
443     if (eglGetError() != EGL_SUCCESS)
444     {
445         std::cerr << "Error on eglCreateContext.\n";
446         return EGL_NO_CONTEXT;
447     }
448 
449     return context;
450 }
451 
initializeContext()452 bool EGLWindow::initializeContext()
453 {
454     mContext = createContext(EGL_NO_CONTEXT);
455     if (mContext == EGL_NO_CONTEXT)
456     {
457         destroyGL();
458         return false;
459     }
460 
461     if (!makeCurrent())
462     {
463         destroyGL();
464         return false;
465     }
466 
467     return true;
468 }
469 
destroyGL()470 void EGLWindow::destroyGL()
471 {
472     destroyContext();
473     destroySurface();
474 
475     if (mDisplay != EGL_NO_DISPLAY)
476     {
477         eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
478         eglTerminate(mDisplay);
479         mDisplay = EGL_NO_DISPLAY;
480     }
481 }
482 
destroySurface()483 void EGLWindow::destroySurface()
484 {
485     if (mSurface != EGL_NO_SURFACE)
486     {
487         eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
488         assert(mDisplay != EGL_NO_DISPLAY);
489         eglDestroySurface(mDisplay, mSurface);
490         mSurface = EGL_NO_SURFACE;
491     }
492 }
493 
destroyContext()494 void EGLWindow::destroyContext()
495 {
496     if (mContext != EGL_NO_CONTEXT)
497     {
498         eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
499         assert(mDisplay != EGL_NO_DISPLAY);
500         eglDestroyContext(mDisplay, mContext);
501         mContext = EGL_NO_CONTEXT;
502     }
503 }
504 
isGLInitialized() const505 bool EGLWindow::isGLInitialized() const
506 {
507     return mSurface != EGL_NO_SURFACE && mContext != EGL_NO_CONTEXT && mDisplay != EGL_NO_DISPLAY;
508 }
509 
510 // Find an EGLConfig that is an exact match for the specified attributes. EGL_FALSE is returned if
511 // the EGLConfig is found.  This indicates that the EGLConfig is not supported.
FindEGLConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * config)512 EGLBoolean EGLWindow::FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config)
513 {
514     EGLint numConfigs = 0;
515     eglGetConfigs(dpy, nullptr, 0, &numConfigs);
516     std::vector<EGLConfig> allConfigs(numConfigs);
517     eglGetConfigs(dpy, allConfigs.data(), static_cast<EGLint>(allConfigs.size()), &numConfigs);
518 
519     for (size_t i = 0; i < allConfigs.size(); i++)
520     {
521         bool matchFound = true;
522         for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
523         {
524             if (curAttrib[1] == EGL_DONT_CARE)
525             {
526                 continue;
527             }
528 
529             EGLint actualValue = EGL_DONT_CARE;
530             eglGetConfigAttrib(dpy, allConfigs[i], curAttrib[0], &actualValue);
531             if (curAttrib[1] != actualValue)
532             {
533                 matchFound = false;
534                 break;
535             }
536         }
537 
538         if (matchFound)
539         {
540             *config = allConfigs[i];
541             return EGL_TRUE;
542         }
543     }
544 
545     return EGL_FALSE;
546 }
547 
makeCurrent()548 bool EGLWindow::makeCurrent()
549 {
550     if (eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) == EGL_FALSE ||
551         eglGetError() != EGL_SUCCESS)
552     {
553         std::cerr << "Error during eglMakeCurrent.\n";
554         return false;
555     }
556 
557     return true;
558 }
559 
setSwapInterval(EGLint swapInterval)560 bool EGLWindow::setSwapInterval(EGLint swapInterval)
561 {
562     if (eglSwapInterval(mDisplay, swapInterval) == EGL_FALSE || eglGetError() != EGL_SUCCESS)
563     {
564         std::cerr << "Error during eglSwapInterval.\n";
565         return false;
566     }
567 
568     return true;
569 }
570 
hasError() const571 bool EGLWindow::hasError() const
572 {
573     return eglGetError() != EGL_SUCCESS;
574 }
575 
CheckExtensionExists(const char * allExtensions,const std::string & extName)576 bool CheckExtensionExists(const char *allExtensions, const std::string &extName)
577 {
578     const std::string paddedExtensions = std::string(" ") + allExtensions + std::string(" ");
579     return paddedExtensions.find(std::string(" ") + extName + std::string(" ")) !=
580            std::string::npos;
581 }
582 
583 // static
Delete(GLWindowBase ** window)584 void GLWindowBase::Delete(GLWindowBase **window)
585 {
586     delete *window;
587     *window = nullptr;
588 }
589 
590 // static
New(EGLint glesMajorVersion,EGLint glesMinorVersion)591 EGLWindow *EGLWindow::New(EGLint glesMajorVersion, EGLint glesMinorVersion)
592 {
593     return new EGLWindow(glesMajorVersion, glesMinorVersion);
594 }
595 
596 // static
Delete(EGLWindow ** window)597 void EGLWindow::Delete(EGLWindow **window)
598 {
599     delete *window;
600     *window = nullptr;
601 }
602