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 "common/system_utils.h"
16 #include "platform/Platform.h"
17 #include "util/OSWindow.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 ¶ms)
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 const char *extensionString =
124 static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
125
126 std::vector<EGLAttrib> displayAttributes;
127 displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
128 displayAttributes.push_back(params.renderer);
129 displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
130 displayAttributes.push_back(params.majorVersion);
131 displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
132 displayAttributes.push_back(params.minorVersion);
133
134 if (params.deviceType != EGL_DONT_CARE)
135 {
136 displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
137 displayAttributes.push_back(params.deviceType);
138 }
139
140 if (params.presentPath != EGL_DONT_CARE)
141 {
142 if (strstr(extensionString, "EGL_ANGLE_experimental_present_path") == nullptr)
143 {
144 destroyGL();
145 return false;
146 }
147
148 displayAttributes.push_back(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE);
149 displayAttributes.push_back(params.presentPath);
150 }
151
152 // Set debug layer settings if requested.
153 if (params.debugLayersEnabled != EGL_DONT_CARE)
154 {
155 displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
156 displayAttributes.push_back(params.debugLayersEnabled);
157 }
158
159 if (params.contextVirtualization != EGL_DONT_CARE)
160 {
161 displayAttributes.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
162 displayAttributes.push_back(params.contextVirtualization);
163 }
164
165 if (params.platformMethods)
166 {
167 static_assert(sizeof(EGLAttrib) == sizeof(params.platformMethods),
168 "Unexpected pointer size");
169 displayAttributes.push_back(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX);
170 displayAttributes.push_back(reinterpret_cast<EGLAttrib>(params.platformMethods));
171 }
172
173 std::vector<const char *> disabledFeatureOverrides;
174 std::vector<const char *> enabledFeatureOverrides;
175
176 if (params.transformFeedbackFeature == EGL_FALSE)
177 {
178 disabledFeatureOverrides.push_back("supports_transform_feedback_extension");
179 disabledFeatureOverrides.push_back("emulate_transform_feedback");
180 }
181
182 if (params.allocateNonZeroMemoryFeature == EGL_TRUE)
183 {
184 enabledFeatureOverrides.push_back("allocate_non_zero_memory");
185 }
186 else if (params.allocateNonZeroMemoryFeature == EGL_FALSE)
187 {
188 disabledFeatureOverrides.push_back("allocate_non_zero_memory");
189 }
190
191 if (!disabledFeatureOverrides.empty())
192 {
193 if (strstr(extensionString, "EGL_ANGLE_feature_control") == nullptr)
194 {
195 std::cout << "Missing EGL_ANGLE_feature_control.\n";
196 destroyGL();
197 return false;
198 }
199
200 disabledFeatureOverrides.push_back(nullptr);
201
202 displayAttributes.push_back(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE);
203 displayAttributes.push_back(reinterpret_cast<EGLAttrib>(disabledFeatureOverrides.data()));
204 }
205
206 if (!enabledFeatureOverrides.empty())
207 {
208 if (strstr(extensionString, "EGL_ANGLE_feature_control") == nullptr)
209 {
210 std::cout << "Missing EGL_ANGLE_feature_control.\n";
211 destroyGL();
212 return false;
213 }
214
215 enabledFeatureOverrides.push_back(nullptr);
216
217 displayAttributes.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
218 displayAttributes.push_back(reinterpret_cast<EGLAttrib>(enabledFeatureOverrides.data()));
219 }
220
221 displayAttributes.push_back(EGL_NONE);
222
223 mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
224 reinterpret_cast<void *>(osWindow->getNativeDisplay()),
225 &displayAttributes[0]);
226 if (mDisplay == EGL_NO_DISPLAY)
227 {
228 destroyGL();
229 return false;
230 }
231
232 if (eglInitialize(mDisplay, &mEGLMajorVersion, &mEGLMinorVersion) == EGL_FALSE)
233 {
234 destroyGL();
235 return false;
236 }
237
238 mPlatform = params;
239 return true;
240 }
241
initializeSurface(OSWindow * osWindow,angle::Library * glWindowingLibrary,const ConfigParameters & params)242 bool EGLWindow::initializeSurface(OSWindow *osWindow,
243 angle::Library *glWindowingLibrary,
244 const ConfigParameters ¶ms)
245 {
246 mConfigParams = params;
247 const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
248
249 std::vector<EGLint> configAttributes = {
250 EGL_RED_SIZE,
251 (mConfigParams.redBits >= 0) ? mConfigParams.redBits : EGL_DONT_CARE,
252 EGL_GREEN_SIZE,
253 (mConfigParams.greenBits >= 0) ? mConfigParams.greenBits : EGL_DONT_CARE,
254 EGL_BLUE_SIZE,
255 (mConfigParams.blueBits >= 0) ? mConfigParams.blueBits : EGL_DONT_CARE,
256 EGL_ALPHA_SIZE,
257 (mConfigParams.alphaBits >= 0) ? mConfigParams.alphaBits : EGL_DONT_CARE,
258 EGL_DEPTH_SIZE,
259 (mConfigParams.depthBits >= 0) ? mConfigParams.depthBits : EGL_DONT_CARE,
260 EGL_STENCIL_SIZE,
261 (mConfigParams.stencilBits >= 0) ? mConfigParams.stencilBits : EGL_DONT_CARE,
262 EGL_SAMPLE_BUFFERS,
263 mConfigParams.multisample ? 1 : 0,
264 EGL_SAMPLES,
265 (mConfigParams.samples >= 0) ? mConfigParams.samples : EGL_DONT_CARE,
266 };
267
268 // Add dynamic attributes
269 bool hasPixelFormatFloat = strstr(displayExtensions, "EGL_EXT_pixel_format_float") != nullptr;
270 if (!hasPixelFormatFloat && mConfigParams.componentType != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)
271 {
272 destroyGL();
273 return false;
274 }
275 if (hasPixelFormatFloat)
276 {
277 configAttributes.push_back(EGL_COLOR_COMPONENT_TYPE_EXT);
278 configAttributes.push_back(mConfigParams.componentType);
279 }
280
281 // Finish the attribute list
282 configAttributes.push_back(EGL_NONE);
283
284 if (!FindEGLConfig(mDisplay, configAttributes.data(), &mConfig))
285 {
286 std::cout << "Could not find a suitable EGL config!" << std::endl;
287 destroyGL();
288 return false;
289 }
290
291 eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &mConfigParams.redBits);
292 eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &mConfigParams.greenBits);
293 eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &mConfigParams.blueBits);
294 eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &mConfigParams.alphaBits);
295 eglGetConfigAttrib(mDisplay, mConfig, EGL_DEPTH_SIZE, &mConfigParams.depthBits);
296 eglGetConfigAttrib(mDisplay, mConfig, EGL_STENCIL_SIZE, &mConfigParams.stencilBits);
297 eglGetConfigAttrib(mDisplay, mConfig, EGL_SAMPLES, &mConfigParams.samples);
298
299 std::vector<EGLint> surfaceAttributes;
300 if (strstr(displayExtensions, "EGL_NV_post_sub_buffer") != nullptr)
301 {
302 surfaceAttributes.push_back(EGL_POST_SUB_BUFFER_SUPPORTED_NV);
303 surfaceAttributes.push_back(EGL_TRUE);
304 }
305
306 bool hasRobustResourceInit =
307 strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr;
308 if (hasRobustResourceInit && mConfigParams.robustResourceInit.valid())
309 {
310 surfaceAttributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
311 surfaceAttributes.push_back(mConfigParams.robustResourceInit.value() ? EGL_TRUE
312 : EGL_FALSE);
313 }
314
315 surfaceAttributes.push_back(EGL_NONE);
316
317 osWindow->resetNativeWindow();
318
319 mSurface = eglCreateWindowSurface(mDisplay, mConfig, osWindow->getNativeWindow(),
320 &surfaceAttributes[0]);
321 if (eglGetError() != EGL_SUCCESS || (mSurface == EGL_NO_SURFACE))
322 {
323 destroyGL();
324 return false;
325 }
326
327 #if defined(ANGLE_USE_UTIL_LOADER)
328 angle::LoadGLES(eglGetProcAddress);
329 #endif // defined(ANGLE_USE_UTIL_LOADER)
330
331 return true;
332 }
333
createContext(EGLContext share) const334 EGLContext EGLWindow::createContext(EGLContext share) const
335 {
336 const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
337
338 // EGL_KHR_create_context is required to request a ES3+ context.
339 bool hasKHRCreateContext = strstr(displayExtensions, "EGL_KHR_create_context") != nullptr;
340 if (mClientMajorVersion > 2 && !(mEGLMajorVersion > 1 || mEGLMinorVersion >= 5) &&
341 !hasKHRCreateContext)
342 {
343 std::cerr << "EGL_KHR_create_context incompatibility.\n";
344 return EGL_NO_CONTEXT;
345 }
346
347 bool hasWebGLCompatibility =
348 strstr(displayExtensions, "EGL_ANGLE_create_context_webgl_compatibility") != nullptr;
349 if (mConfigParams.webGLCompatibility.valid() && !hasWebGLCompatibility)
350 {
351 std::cerr << "EGL_ANGLE_create_context_webgl_compatibility missing.\n";
352 return EGL_NO_CONTEXT;
353 }
354
355 bool hasCreateContextExtensionsEnabled =
356 strstr(displayExtensions, "EGL_ANGLE_create_context_extensions_enabled") != nullptr;
357 if (mConfigParams.extensionsEnabled.valid() && !hasCreateContextExtensionsEnabled)
358 {
359 std::cerr << "EGL_ANGLE_create_context_extensions_enabled missing.\n";
360 return EGL_NO_CONTEXT;
361 }
362
363 bool hasRobustness = strstr(displayExtensions, "EGL_EXT_create_context_robustness") != nullptr;
364 if ((mConfigParams.robustAccess ||
365 mConfigParams.resetStrategy != EGL_NO_RESET_NOTIFICATION_EXT) &&
366 !hasRobustness)
367 {
368 std::cerr << "EGL_EXT_create_context_robustness missing.\n";
369 return EGL_NO_CONTEXT;
370 }
371
372 bool hasBindGeneratesResource =
373 strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr;
374 if (!mConfigParams.bindGeneratesResource && !hasBindGeneratesResource)
375 {
376 std::cerr << "EGL_CHROMIUM_create_context_bind_generates_resource missing.\n";
377 return EGL_NO_CONTEXT;
378 }
379
380 bool hasClientArraysExtension =
381 strstr(displayExtensions, "EGL_ANGLE_create_context_client_arrays") != nullptr;
382 if (!mConfigParams.clientArraysEnabled && !hasClientArraysExtension)
383 {
384 // Non-default state requested without the extension present
385 std::cerr << "EGL_ANGLE_create_context_client_arrays missing.\n";
386 return EGL_NO_CONTEXT;
387 }
388
389 bool hasProgramCacheControlExtension =
390 strstr(displayExtensions, "EGL_ANGLE_program_cache_control ") != nullptr;
391 if (mConfigParams.contextProgramCacheEnabled.valid() && !hasProgramCacheControlExtension)
392 {
393 std::cerr << "EGL_ANGLE_program_cache_control missing.\n";
394 return EGL_NO_CONTEXT;
395 }
396
397 bool hasBackwardsCompatibleContextExtension =
398 strstr(displayExtensions, "EGL_ANGLE_create_context_backwards_compatible") != nullptr;
399 if (!hasProgramCacheControlExtension)
400 {
401 std::cerr << "EGL_ANGLE_create_context_backwards_compatible missing.\n";
402 return EGL_NO_CONTEXT;
403 }
404
405 eglBindAPI(EGL_OPENGL_ES_API);
406 if (eglGetError() != EGL_SUCCESS)
407 {
408 std::cerr << "Error on eglBindAPI.\n";
409 return EGL_NO_CONTEXT;
410 }
411
412 std::vector<EGLint> contextAttributes;
413 if (hasKHRCreateContext)
414 {
415 contextAttributes.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
416 contextAttributes.push_back(mClientMajorVersion);
417
418 contextAttributes.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
419 contextAttributes.push_back(mClientMinorVersion);
420
421 contextAttributes.push_back(EGL_CONTEXT_OPENGL_DEBUG);
422 contextAttributes.push_back(mConfigParams.debug ? EGL_TRUE : EGL_FALSE);
423
424 // TODO(jmadill): Check for the extension string.
425 // bool hasKHRCreateContextNoError = strstr(displayExtensions,
426 // "EGL_KHR_create_context_no_error") != nullptr;
427
428 contextAttributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
429 contextAttributes.push_back(mConfigParams.noError ? EGL_TRUE : EGL_FALSE);
430
431 if (mConfigParams.webGLCompatibility.valid())
432 {
433 contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
434 contextAttributes.push_back(mConfigParams.webGLCompatibility.value() ? EGL_TRUE
435 : EGL_FALSE);
436 }
437
438 if (mConfigParams.extensionsEnabled.valid())
439 {
440 contextAttributes.push_back(EGL_EXTENSIONS_ENABLED_ANGLE);
441 contextAttributes.push_back(mConfigParams.extensionsEnabled.value() ? EGL_TRUE
442 : EGL_FALSE);
443 }
444
445 if (hasRobustness)
446 {
447 contextAttributes.push_back(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
448 contextAttributes.push_back(mConfigParams.robustAccess ? EGL_TRUE : EGL_FALSE);
449
450 contextAttributes.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
451 contextAttributes.push_back(mConfigParams.resetStrategy);
452 }
453
454 if (hasBindGeneratesResource)
455 {
456 contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
457 contextAttributes.push_back(mConfigParams.bindGeneratesResource ? EGL_TRUE : EGL_FALSE);
458 }
459
460 if (hasClientArraysExtension)
461 {
462 contextAttributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE);
463 contextAttributes.push_back(mConfigParams.clientArraysEnabled ? EGL_TRUE : EGL_FALSE);
464 }
465
466 if (mConfigParams.contextProgramCacheEnabled.valid())
467 {
468 contextAttributes.push_back(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
469 contextAttributes.push_back(
470 mConfigParams.contextProgramCacheEnabled.value() ? EGL_TRUE : EGL_FALSE);
471 }
472
473 if (hasBackwardsCompatibleContextExtension)
474 {
475 // Always request the exact context version that the config wants
476 contextAttributes.push_back(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
477 contextAttributes.push_back(EGL_FALSE);
478 }
479
480 bool hasRobustResourceInit =
481 strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr;
482 if (hasRobustResourceInit && mConfigParams.robustResourceInit.valid())
483 {
484 contextAttributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
485 contextAttributes.push_back(mConfigParams.robustResourceInit.value() ? EGL_TRUE
486 : EGL_FALSE);
487 }
488 }
489 contextAttributes.push_back(EGL_NONE);
490
491 EGLContext context = eglCreateContext(mDisplay, mConfig, share, &contextAttributes[0]);
492 if (eglGetError() != EGL_SUCCESS)
493 {
494 std::cerr << "Error on eglCreateContext.\n";
495 return EGL_NO_CONTEXT;
496 }
497
498 return context;
499 }
500
initializeContext()501 bool EGLWindow::initializeContext()
502 {
503 mContext = createContext(EGL_NO_CONTEXT);
504 if (mContext == EGL_NO_CONTEXT)
505 {
506 destroyGL();
507 return false;
508 }
509
510 if (!makeCurrent())
511 {
512 destroyGL();
513 return false;
514 }
515
516 return true;
517 }
518
destroyGL()519 void EGLWindow::destroyGL()
520 {
521 destroyContext();
522 destroySurface();
523
524 if (mDisplay != EGL_NO_DISPLAY)
525 {
526 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
527 eglTerminate(mDisplay);
528 mDisplay = EGL_NO_DISPLAY;
529 }
530 }
531
destroySurface()532 void EGLWindow::destroySurface()
533 {
534 if (mSurface != EGL_NO_SURFACE)
535 {
536 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
537 assert(mDisplay != EGL_NO_DISPLAY);
538 eglDestroySurface(mDisplay, mSurface);
539 mSurface = EGL_NO_SURFACE;
540 }
541 }
542
destroyContext()543 void EGLWindow::destroyContext()
544 {
545 if (mContext != EGL_NO_CONTEXT)
546 {
547 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
548 assert(mDisplay != EGL_NO_DISPLAY);
549 eglDestroyContext(mDisplay, mContext);
550 mContext = EGL_NO_CONTEXT;
551 }
552 }
553
isGLInitialized() const554 bool EGLWindow::isGLInitialized() const
555 {
556 return mSurface != EGL_NO_SURFACE && mContext != EGL_NO_CONTEXT && mDisplay != EGL_NO_DISPLAY;
557 }
558
559 // Find an EGLConfig that is an exact match for the specified attributes. EGL_FALSE is returned if
560 // the EGLConfig is found. This indicates that the EGLConfig is not supported.
FindEGLConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * config)561 EGLBoolean EGLWindow::FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config)
562 {
563 EGLint numConfigs = 0;
564 eglGetConfigs(dpy, nullptr, 0, &numConfigs);
565 std::vector<EGLConfig> allConfigs(numConfigs);
566 eglGetConfigs(dpy, allConfigs.data(), static_cast<EGLint>(allConfigs.size()), &numConfigs);
567
568 for (size_t i = 0; i < allConfigs.size(); i++)
569 {
570 bool matchFound = true;
571 for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
572 {
573 if (curAttrib[1] == EGL_DONT_CARE)
574 {
575 continue;
576 }
577
578 EGLint actualValue = EGL_DONT_CARE;
579 eglGetConfigAttrib(dpy, allConfigs[i], curAttrib[0], &actualValue);
580 if (curAttrib[1] != actualValue)
581 {
582 matchFound = false;
583 break;
584 }
585 }
586
587 if (matchFound)
588 {
589 *config = allConfigs[i];
590 return EGL_TRUE;
591 }
592 }
593
594 return EGL_FALSE;
595 }
596
makeCurrent()597 bool EGLWindow::makeCurrent()
598 {
599 if (eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) == EGL_FALSE ||
600 eglGetError() != EGL_SUCCESS)
601 {
602 std::cerr << "Error during eglMakeCurrent.\n";
603 return false;
604 }
605
606 return true;
607 }
608
setSwapInterval(EGLint swapInterval)609 bool EGLWindow::setSwapInterval(EGLint swapInterval)
610 {
611 if (eglSwapInterval(mDisplay, swapInterval) == EGL_FALSE || eglGetError() != EGL_SUCCESS)
612 {
613 std::cerr << "Error during eglSwapInterval.\n";
614 return false;
615 }
616
617 return true;
618 }
619
hasError() const620 bool EGLWindow::hasError() const
621 {
622 return eglGetError() != EGL_SUCCESS;
623 }
624
625 // static
Delete(GLWindowBase ** window)626 void GLWindowBase::Delete(GLWindowBase **window)
627 {
628 delete *window;
629 *window = nullptr;
630 }
631
632 // static
New(EGLint glesMajorVersion,EGLint glesMinorVersion)633 EGLWindow *EGLWindow::New(EGLint glesMajorVersion, EGLint glesMinorVersion)
634 {
635 return new EGLWindow(glesMajorVersion, glesMinorVersion);
636 }
637
638 // static
Delete(EGLWindow ** window)639 void EGLWindow::Delete(EGLWindow **window)
640 {
641 delete *window;
642 *window = nullptr;
643 }
644