Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/util/EGLWindow.cpp
1693 views
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/PlatformMethods.h"
17
#include "util/OSWindow.h"
18
19
namespace
20
{
21
constexpr EGLint kDefaultSwapInterval = 1;
22
} // anonymous namespace
23
24
// ConfigParameters implementation.
25
ConfigParameters::ConfigParameters()
26
: redBits(-1),
27
greenBits(-1),
28
blueBits(-1),
29
alphaBits(-1),
30
depthBits(-1),
31
stencilBits(-1),
32
componentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT),
33
multisample(false),
34
debug(false),
35
noError(false),
36
bindGeneratesResource(true),
37
clientArraysEnabled(true),
38
robustAccess(false),
39
samples(-1),
40
resetStrategy(EGL_NO_RESET_NOTIFICATION_EXT),
41
colorSpace(EGL_COLORSPACE_LINEAR),
42
swapInterval(kDefaultSwapInterval)
43
{}
44
45
ConfigParameters::~ConfigParameters() = default;
46
47
void ConfigParameters::reset()
48
{
49
*this = ConfigParameters();
50
}
51
52
// GLWindowBase implementation.
53
GLWindowBase::GLWindowBase(EGLint glesMajorVersion, EGLint glesMinorVersion)
54
: mClientMajorVersion(glesMajorVersion), mClientMinorVersion(glesMinorVersion)
55
{}
56
57
GLWindowBase::~GLWindowBase() = default;
58
59
// EGLWindow implementation.
60
EGLWindow::EGLWindow(EGLint glesMajorVersion, EGLint glesMinorVersion)
61
: GLWindowBase(glesMajorVersion, glesMinorVersion),
62
mConfig(0),
63
mDisplay(EGL_NO_DISPLAY),
64
mSurface(EGL_NO_SURFACE),
65
mContext(EGL_NO_CONTEXT),
66
mEGLMajorVersion(0),
67
mEGLMinorVersion(0)
68
{}
69
70
EGLWindow::~EGLWindow()
71
{
72
destroyGL();
73
}
74
75
void EGLWindow::swap()
76
{
77
eglSwapBuffers(mDisplay, mSurface);
78
}
79
80
EGLConfig EGLWindow::getConfig() const
81
{
82
return mConfig;
83
}
84
85
EGLDisplay EGLWindow::getDisplay() const
86
{
87
return mDisplay;
88
}
89
90
EGLSurface EGLWindow::getSurface() const
91
{
92
return mSurface;
93
}
94
95
EGLContext EGLWindow::getContext() const
96
{
97
return mContext;
98
}
99
100
bool EGLWindow::isContextVersion(EGLint glesMajorVersion, EGLint glesMinorVersion) const
101
{
102
return mClientMajorVersion == glesMajorVersion && mClientMinorVersion == glesMinorVersion;
103
}
104
105
bool EGLWindow::initializeGL(OSWindow *osWindow,
106
angle::Library *glWindowingLibrary,
107
angle::GLESDriverType driverType,
108
const EGLPlatformParameters &platformParams,
109
const ConfigParameters &configParams)
110
{
111
if (!initializeDisplay(osWindow, glWindowingLibrary, driverType, platformParams))
112
return false;
113
if (!initializeSurface(osWindow, glWindowingLibrary, configParams))
114
return false;
115
if (!initializeContext())
116
return false;
117
return true;
118
}
119
120
bool EGLWindow::initializeDisplay(OSWindow *osWindow,
121
angle::Library *glWindowingLibrary,
122
angle::GLESDriverType driverType,
123
const EGLPlatformParameters &params)
124
{
125
#if defined(ANGLE_USE_UTIL_LOADER)
126
PFNEGLGETPROCADDRESSPROC getProcAddress;
127
glWindowingLibrary->getAs("eglGetProcAddress", &getProcAddress);
128
if (!getProcAddress)
129
{
130
fprintf(stderr, "Cannot load eglGetProcAddress\n");
131
return false;
132
}
133
134
// Likely we will need to use a fallback to Library::getAs on non-ANGLE platforms.
135
angle::LoadEGL(getProcAddress);
136
#endif // defined(ANGLE_USE_UTIL_LOADER)
137
138
const char *extensionString =
139
static_cast<const char *>(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS));
140
141
std::vector<EGLAttrib> displayAttributes;
142
displayAttributes.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
143
displayAttributes.push_back(params.renderer);
144
displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE);
145
displayAttributes.push_back(params.majorVersion);
146
displayAttributes.push_back(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE);
147
displayAttributes.push_back(params.minorVersion);
148
149
if (params.deviceType != EGL_DONT_CARE)
150
{
151
displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
152
displayAttributes.push_back(params.deviceType);
153
}
154
155
if (params.presentPath != EGL_DONT_CARE)
156
{
157
if (strstr(extensionString, "EGL_ANGLE_experimental_present_path") == nullptr)
158
{
159
destroyGL();
160
return false;
161
}
162
163
displayAttributes.push_back(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE);
164
displayAttributes.push_back(params.presentPath);
165
}
166
167
// Set debug layer settings if requested.
168
if (params.debugLayersEnabled != EGL_DONT_CARE)
169
{
170
displayAttributes.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
171
displayAttributes.push_back(params.debugLayersEnabled);
172
}
173
174
const bool hasFeatureVirtualizationANGLE =
175
strstr(extensionString, "EGL_ANGLE_platform_angle_context_virtualization") != nullptr;
176
177
if (params.contextVirtualization != EGL_DONT_CARE)
178
{
179
if (hasFeatureVirtualizationANGLE)
180
{
181
displayAttributes.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
182
displayAttributes.push_back(params.contextVirtualization);
183
}
184
else
185
{
186
fprintf(stderr,
187
"EGL_ANGLE_platform_angle_context_virtualization extension not active\n");
188
}
189
}
190
191
if (params.platformMethods)
192
{
193
static_assert(sizeof(EGLAttrib) == sizeof(params.platformMethods),
194
"Unexpected pointer size");
195
displayAttributes.push_back(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX);
196
displayAttributes.push_back(reinterpret_cast<EGLAttrib>(params.platformMethods));
197
}
198
199
std::vector<const char *> disabledFeatureOverrides;
200
std::vector<const char *> enabledFeatureOverrides;
201
202
if (params.transformFeedbackFeature == EGL_FALSE)
203
{
204
disabledFeatureOverrides.push_back("supportsTransformFeedbackExtension");
205
disabledFeatureOverrides.push_back("supportsGeometryStreamsCapability");
206
disabledFeatureOverrides.push_back("emulateTransformFeedback");
207
}
208
209
if (params.allocateNonZeroMemoryFeature == EGL_TRUE)
210
{
211
enabledFeatureOverrides.push_back("allocateNonZeroMemory");
212
}
213
else if (params.allocateNonZeroMemoryFeature == EGL_FALSE)
214
{
215
disabledFeatureOverrides.push_back("allocateNonZeroMemory");
216
}
217
218
if (params.emulateCopyTexImage2DFromRenderbuffers == EGL_TRUE)
219
{
220
enabledFeatureOverrides.push_back("emulate_copyteximage2d_from_renderbuffers");
221
}
222
223
if (params.shaderStencilOutputFeature == EGL_FALSE)
224
{
225
disabledFeatureOverrides.push_back("has_shader_stencil_output");
226
}
227
228
if (params.genMultipleMipsPerPassFeature == EGL_FALSE)
229
{
230
disabledFeatureOverrides.push_back("gen_multiple_mips_per_pass");
231
}
232
233
if (params.supportsVulkanViewportFlip == EGL_TRUE)
234
{
235
enabledFeatureOverrides.push_back("supportsViewportFlip");
236
}
237
else if (params.supportsVulkanViewportFlip == EGL_FALSE)
238
{
239
disabledFeatureOverrides.push_back("supportsViewportFlip");
240
}
241
242
switch (params.emulatedPrerotation)
243
{
244
case 90:
245
enabledFeatureOverrides.push_back("emulatedPrerotation90");
246
break;
247
case 180:
248
enabledFeatureOverrides.push_back("emulatedPrerotation180");
249
break;
250
case 270:
251
enabledFeatureOverrides.push_back("emulatedPrerotation270");
252
break;
253
default:
254
break;
255
}
256
257
if (params.asyncCommandQueueFeatureVulkan == EGL_TRUE)
258
{
259
// TODO(jmadill): Update feature names. b/172704839
260
enabledFeatureOverrides.push_back("commandProcessor");
261
enabledFeatureOverrides.push_back("asynchronousCommandProcessing");
262
}
263
264
if (params.directSPIRVGeneration == EGL_TRUE)
265
{
266
enabledFeatureOverrides.push_back("directSPIRVGeneration");
267
}
268
269
if (params.directMetalGeneration == EGL_TRUE)
270
{
271
enabledFeatureOverrides.push_back("directMetalGeneration");
272
}
273
274
if (params.hasExplicitMemBarrierFeatureMtl == EGL_FALSE)
275
{
276
disabledFeatureOverrides.push_back("has_explicit_mem_barrier_mtl");
277
}
278
279
if (params.hasCheapRenderPassFeatureMtl == EGL_FALSE)
280
{
281
disabledFeatureOverrides.push_back("has_cheap_render_pass_mtl");
282
}
283
284
if (params.forceBufferGPUStorageFeatureMtl == EGL_TRUE)
285
{
286
enabledFeatureOverrides.push_back("force_buffer_gpu_storage_mtl");
287
}
288
289
if (params.emulatedVAOs == EGL_TRUE)
290
{
291
enabledFeatureOverrides.push_back("sync_vertex_arrays_to_default");
292
}
293
294
if (params.captureLimits == EGL_TRUE)
295
{
296
enabledFeatureOverrides.push_back("enable_capture_limits");
297
}
298
299
if (params.forceRobustResourceInit == EGL_TRUE)
300
{
301
enabledFeatureOverrides.push_back("forceRobustResourceInit");
302
}
303
304
if (params.forceInitShaderVariables == EGL_TRUE)
305
{
306
enabledFeatureOverrides.push_back("forceInitShaderVariables");
307
}
308
309
const bool hasFeatureControlANGLE =
310
strstr(extensionString, "EGL_ANGLE_feature_control") != nullptr;
311
312
if (!hasFeatureControlANGLE &&
313
(!enabledFeatureOverrides.empty() || !disabledFeatureOverrides.empty()))
314
{
315
fprintf(stderr, "Missing EGL_ANGLE_feature_control.\n");
316
destroyGL();
317
return false;
318
}
319
320
if (!disabledFeatureOverrides.empty())
321
{
322
disabledFeatureOverrides.push_back(nullptr);
323
324
displayAttributes.push_back(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE);
325
displayAttributes.push_back(reinterpret_cast<EGLAttrib>(disabledFeatureOverrides.data()));
326
}
327
328
if (hasFeatureControlANGLE)
329
{
330
// Always enable exposeNonConformantExtensionsAndVersions in ANGLE tests.
331
enabledFeatureOverrides.push_back("exposeNonConformantExtensionsAndVersions");
332
enabledFeatureOverrides.push_back(nullptr);
333
334
displayAttributes.push_back(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE);
335
displayAttributes.push_back(reinterpret_cast<EGLAttrib>(enabledFeatureOverrides.data()));
336
}
337
338
displayAttributes.push_back(EGL_NONE);
339
340
if (driverType == angle::GLESDriverType::SystemWGL)
341
return false;
342
343
if (driverType == angle::GLESDriverType::AngleEGL &&
344
strstr(extensionString, "EGL_ANGLE_platform_angle"))
345
{
346
mDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
347
reinterpret_cast<void *>(osWindow->getNativeDisplay()),
348
&displayAttributes[0]);
349
}
350
else
351
{
352
mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
353
}
354
355
if (mDisplay == EGL_NO_DISPLAY)
356
{
357
fprintf(stderr, "Failed to get display: 0x%X\n", eglGetError());
358
destroyGL();
359
return false;
360
}
361
362
if (eglInitialize(mDisplay, &mEGLMajorVersion, &mEGLMinorVersion) == EGL_FALSE)
363
{
364
fprintf(stderr, "eglInitialize failed: 0x%X\n", eglGetError());
365
destroyGL();
366
return false;
367
}
368
369
mPlatform = params;
370
return true;
371
}
372
373
bool EGLWindow::initializeSurface(OSWindow *osWindow,
374
angle::Library *glWindowingLibrary,
375
const ConfigParameters &params)
376
{
377
mConfigParams = params;
378
const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
379
380
std::vector<EGLint> configAttributes = {
381
EGL_SURFACE_TYPE,
382
EGL_WINDOW_BIT,
383
EGL_RED_SIZE,
384
(mConfigParams.redBits >= 0) ? mConfigParams.redBits : EGL_DONT_CARE,
385
EGL_GREEN_SIZE,
386
(mConfigParams.greenBits >= 0) ? mConfigParams.greenBits : EGL_DONT_CARE,
387
EGL_BLUE_SIZE,
388
(mConfigParams.blueBits >= 0) ? mConfigParams.blueBits : EGL_DONT_CARE,
389
EGL_ALPHA_SIZE,
390
(mConfigParams.alphaBits >= 0) ? mConfigParams.alphaBits : EGL_DONT_CARE,
391
EGL_DEPTH_SIZE,
392
(mConfigParams.depthBits >= 0) ? mConfigParams.depthBits : EGL_DONT_CARE,
393
EGL_STENCIL_SIZE,
394
(mConfigParams.stencilBits >= 0) ? mConfigParams.stencilBits : EGL_DONT_CARE,
395
EGL_SAMPLE_BUFFERS,
396
mConfigParams.multisample ? 1 : 0,
397
EGL_SAMPLES,
398
(mConfigParams.samples >= 0) ? mConfigParams.samples : EGL_DONT_CARE,
399
};
400
401
// Add dynamic attributes
402
bool hasPixelFormatFloat = strstr(displayExtensions, "EGL_EXT_pixel_format_float") != nullptr;
403
if (!hasPixelFormatFloat && mConfigParams.componentType != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)
404
{
405
fprintf(stderr, "Mising EGL_EXT_pixel_format_float.\n");
406
destroyGL();
407
return false;
408
}
409
if (hasPixelFormatFloat)
410
{
411
configAttributes.push_back(EGL_COLOR_COMPONENT_TYPE_EXT);
412
configAttributes.push_back(mConfigParams.componentType);
413
}
414
415
// Finish the attribute list
416
configAttributes.push_back(EGL_NONE);
417
418
if (!FindEGLConfig(mDisplay, configAttributes.data(), &mConfig))
419
{
420
fprintf(stderr, "Could not find a suitable EGL config!\n");
421
destroyGL();
422
return false;
423
}
424
425
eglGetConfigAttrib(mDisplay, mConfig, EGL_RED_SIZE, &mConfigParams.redBits);
426
eglGetConfigAttrib(mDisplay, mConfig, EGL_GREEN_SIZE, &mConfigParams.greenBits);
427
eglGetConfigAttrib(mDisplay, mConfig, EGL_BLUE_SIZE, &mConfigParams.blueBits);
428
eglGetConfigAttrib(mDisplay, mConfig, EGL_ALPHA_SIZE, &mConfigParams.alphaBits);
429
eglGetConfigAttrib(mDisplay, mConfig, EGL_DEPTH_SIZE, &mConfigParams.depthBits);
430
eglGetConfigAttrib(mDisplay, mConfig, EGL_STENCIL_SIZE, &mConfigParams.stencilBits);
431
eglGetConfigAttrib(mDisplay, mConfig, EGL_SAMPLES, &mConfigParams.samples);
432
433
std::vector<EGLint> surfaceAttributes;
434
if (strstr(displayExtensions, "EGL_NV_post_sub_buffer") != nullptr)
435
{
436
surfaceAttributes.push_back(EGL_POST_SUB_BUFFER_SUPPORTED_NV);
437
surfaceAttributes.push_back(EGL_TRUE);
438
}
439
440
bool hasRobustResourceInit =
441
strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr;
442
if (hasRobustResourceInit && mConfigParams.robustResourceInit.valid())
443
{
444
surfaceAttributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
445
surfaceAttributes.push_back(mConfigParams.robustResourceInit.value() ? EGL_TRUE
446
: EGL_FALSE);
447
}
448
449
bool hasGLColorSpace = strstr(displayExtensions, "EGL_KHR_gl_colorspace") != nullptr;
450
if (!hasGLColorSpace && mConfigParams.colorSpace != EGL_COLORSPACE_LINEAR)
451
{
452
fprintf(stderr, "Mising EGL_KHR_gl_colorspace.\n");
453
destroyGL();
454
return false;
455
}
456
if (hasGLColorSpace)
457
{
458
surfaceAttributes.push_back(EGL_GL_COLORSPACE_KHR);
459
surfaceAttributes.push_back(mConfigParams.colorSpace);
460
}
461
462
bool hasCreateSurfaceSwapInterval =
463
strstr(displayExtensions, "EGL_ANGLE_create_surface_swap_interval") != nullptr;
464
if (hasCreateSurfaceSwapInterval && mConfigParams.swapInterval != kDefaultSwapInterval)
465
{
466
surfaceAttributes.push_back(EGL_SWAP_INTERVAL_ANGLE);
467
surfaceAttributes.push_back(mConfigParams.swapInterval);
468
}
469
470
surfaceAttributes.push_back(EGL_NONE);
471
472
osWindow->resetNativeWindow();
473
474
mSurface = eglCreateWindowSurface(mDisplay, mConfig, osWindow->getNativeWindow(),
475
&surfaceAttributes[0]);
476
if (eglGetError() != EGL_SUCCESS || (mSurface == EGL_NO_SURFACE))
477
{
478
fprintf(stderr, "eglCreateWindowSurface failed: 0x%X\n", eglGetError());
479
destroyGL();
480
return false;
481
}
482
483
#if defined(ANGLE_USE_UTIL_LOADER)
484
angle::LoadGLES(eglGetProcAddress);
485
#endif // defined(ANGLE_USE_UTIL_LOADER)
486
487
return true;
488
}
489
490
GLWindowContext EGLWindow::getCurrentContextGeneric()
491
{
492
return reinterpret_cast<GLWindowContext>(mContext);
493
}
494
495
GLWindowContext EGLWindow::createContextGeneric(GLWindowContext share)
496
{
497
EGLContext shareContext = reinterpret_cast<EGLContext>(share);
498
return reinterpret_cast<GLWindowContext>(createContext(shareContext));
499
}
500
501
EGLContext EGLWindow::createContext(EGLContext share)
502
{
503
const char *displayExtensions = eglQueryString(mDisplay, EGL_EXTENSIONS);
504
505
// EGL_KHR_create_context is required to request a ES3+ context.
506
bool hasKHRCreateContext = strstr(displayExtensions, "EGL_KHR_create_context") != nullptr;
507
if (mClientMajorVersion > 2 && !(mEGLMajorVersion > 1 || mEGLMinorVersion >= 5) &&
508
!hasKHRCreateContext)
509
{
510
fprintf(stderr, "EGL_KHR_create_context incompatibility.\n");
511
return EGL_NO_CONTEXT;
512
}
513
514
// EGL_CONTEXT_OPENGL_DEBUG is only valid as of EGL 1.5.
515
bool hasDebug = mEGLMinorVersion >= 5;
516
if (mConfigParams.debug && !hasDebug)
517
{
518
fprintf(stderr, "EGL 1.5 is required for EGL_CONTEXT_OPENGL_DEBUG.\n");
519
return EGL_NO_CONTEXT;
520
}
521
522
bool hasWebGLCompatibility =
523
strstr(displayExtensions, "EGL_ANGLE_create_context_webgl_compatibility") != nullptr;
524
if (mConfigParams.webGLCompatibility.valid() && !hasWebGLCompatibility)
525
{
526
fprintf(stderr, "EGL_ANGLE_create_context_webgl_compatibility missing.\n");
527
return EGL_NO_CONTEXT;
528
}
529
530
bool hasCreateContextExtensionsEnabled =
531
strstr(displayExtensions, "EGL_ANGLE_create_context_extensions_enabled") != nullptr;
532
if (mConfigParams.extensionsEnabled.valid() && !hasCreateContextExtensionsEnabled)
533
{
534
fprintf(stderr, "EGL_ANGLE_create_context_extensions_enabled missing.\n");
535
return EGL_NO_CONTEXT;
536
}
537
538
bool hasRobustness = strstr(displayExtensions, "EGL_EXT_create_context_robustness") != nullptr;
539
if ((mConfigParams.robustAccess ||
540
mConfigParams.resetStrategy != EGL_NO_RESET_NOTIFICATION_EXT) &&
541
!hasRobustness)
542
{
543
fprintf(stderr, "EGL_EXT_create_context_robustness missing.\n");
544
return EGL_NO_CONTEXT;
545
}
546
547
bool hasBindGeneratesResource =
548
strstr(displayExtensions, "EGL_CHROMIUM_create_context_bind_generates_resource") != nullptr;
549
if (!mConfigParams.bindGeneratesResource && !hasBindGeneratesResource)
550
{
551
fprintf(stderr, "EGL_CHROMIUM_create_context_bind_generates_resource missing.\n");
552
return EGL_NO_CONTEXT;
553
}
554
555
bool hasClientArraysExtension =
556
strstr(displayExtensions, "EGL_ANGLE_create_context_client_arrays") != nullptr;
557
if (!mConfigParams.clientArraysEnabled && !hasClientArraysExtension)
558
{
559
// Non-default state requested without the extension present
560
fprintf(stderr, "EGL_ANGLE_create_context_client_arrays missing.\n");
561
return EGL_NO_CONTEXT;
562
}
563
564
bool hasProgramCacheControlExtension =
565
strstr(displayExtensions, "EGL_ANGLE_program_cache_control ") != nullptr;
566
if (mConfigParams.contextProgramCacheEnabled.valid() && !hasProgramCacheControlExtension)
567
{
568
fprintf(stderr, "EGL_ANGLE_program_cache_control missing.\n");
569
return EGL_NO_CONTEXT;
570
}
571
572
bool hasKHRCreateContextNoError =
573
strstr(displayExtensions, "EGL_KHR_create_context_no_error") != nullptr;
574
if (mConfigParams.noError && !hasKHRCreateContextNoError)
575
{
576
fprintf(stderr, "EGL_KHR_create_context_no_error missing.\n");
577
return EGL_NO_CONTEXT;
578
}
579
580
eglBindAPI(EGL_OPENGL_ES_API);
581
if (eglGetError() != EGL_SUCCESS)
582
{
583
fprintf(stderr, "Error on eglBindAPI.\n");
584
return EGL_NO_CONTEXT;
585
}
586
587
std::vector<EGLint> contextAttributes;
588
if (hasKHRCreateContext)
589
{
590
contextAttributes.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
591
contextAttributes.push_back(mClientMajorVersion);
592
593
contextAttributes.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
594
contextAttributes.push_back(mClientMinorVersion);
595
596
// Note that the Android loader currently doesn't handle this flag despite reporting 1.5.
597
// Work around this by only using the debug bit when we request a debug context.
598
if (hasDebug && mConfigParams.debug)
599
{
600
contextAttributes.push_back(EGL_CONTEXT_OPENGL_DEBUG);
601
contextAttributes.push_back(mConfigParams.debug ? EGL_TRUE : EGL_FALSE);
602
}
603
604
// TODO (http://anglebug.com/5809)
605
// Mesa does not allow EGL_CONTEXT_OPENGL_NO_ERROR_KHR for GLES1.
606
if (hasKHRCreateContextNoError && mConfigParams.noError)
607
{
608
contextAttributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
609
contextAttributes.push_back(mConfigParams.noError ? EGL_TRUE : EGL_FALSE);
610
}
611
612
if (mConfigParams.webGLCompatibility.valid())
613
{
614
contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
615
contextAttributes.push_back(mConfigParams.webGLCompatibility.value() ? EGL_TRUE
616
: EGL_FALSE);
617
}
618
619
if (mConfigParams.extensionsEnabled.valid())
620
{
621
contextAttributes.push_back(EGL_EXTENSIONS_ENABLED_ANGLE);
622
contextAttributes.push_back(mConfigParams.extensionsEnabled.value() ? EGL_TRUE
623
: EGL_FALSE);
624
}
625
626
if (hasRobustness)
627
{
628
contextAttributes.push_back(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
629
contextAttributes.push_back(mConfigParams.robustAccess ? EGL_TRUE : EGL_FALSE);
630
631
contextAttributes.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
632
contextAttributes.push_back(mConfigParams.resetStrategy);
633
}
634
635
if (hasBindGeneratesResource)
636
{
637
contextAttributes.push_back(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM);
638
contextAttributes.push_back(mConfigParams.bindGeneratesResource ? EGL_TRUE : EGL_FALSE);
639
}
640
641
if (hasClientArraysExtension)
642
{
643
contextAttributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE);
644
contextAttributes.push_back(mConfigParams.clientArraysEnabled ? EGL_TRUE : EGL_FALSE);
645
}
646
647
if (mConfigParams.contextProgramCacheEnabled.valid())
648
{
649
contextAttributes.push_back(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
650
contextAttributes.push_back(
651
mConfigParams.contextProgramCacheEnabled.value() ? EGL_TRUE : EGL_FALSE);
652
}
653
654
bool hasBackwardsCompatibleContextExtension =
655
strstr(displayExtensions, "EGL_ANGLE_create_context_backwards_compatible") != nullptr;
656
if (hasBackwardsCompatibleContextExtension)
657
{
658
// Always request the exact context version that the config wants
659
contextAttributes.push_back(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
660
contextAttributes.push_back(EGL_FALSE);
661
}
662
663
bool hasRobustResourceInit =
664
strstr(displayExtensions, "EGL_ANGLE_robust_resource_initialization") != nullptr;
665
if (hasRobustResourceInit && mConfigParams.robustResourceInit.valid())
666
{
667
contextAttributes.push_back(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE);
668
contextAttributes.push_back(mConfigParams.robustResourceInit.value() ? EGL_TRUE
669
: EGL_FALSE);
670
}
671
}
672
contextAttributes.push_back(EGL_NONE);
673
674
EGLContext context = eglCreateContext(mDisplay, mConfig, share, &contextAttributes[0]);
675
if (context == EGL_NO_CONTEXT)
676
{
677
fprintf(stderr, "eglCreateContext failed: 0x%X\n", eglGetError());
678
return EGL_NO_CONTEXT;
679
}
680
681
return context;
682
}
683
684
bool EGLWindow::initializeContext()
685
{
686
mContext = createContext(EGL_NO_CONTEXT);
687
if (mContext == EGL_NO_CONTEXT)
688
{
689
destroyGL();
690
return false;
691
}
692
693
if (!makeCurrent())
694
{
695
destroyGL();
696
return false;
697
}
698
699
return true;
700
}
701
702
void EGLWindow::destroyGL()
703
{
704
destroyContext();
705
destroySurface();
706
707
if (mDisplay != EGL_NO_DISPLAY)
708
{
709
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
710
eglTerminate(mDisplay);
711
mDisplay = EGL_NO_DISPLAY;
712
}
713
}
714
715
void EGLWindow::destroySurface()
716
{
717
if (mSurface != EGL_NO_SURFACE)
718
{
719
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
720
assert(mDisplay != EGL_NO_DISPLAY);
721
eglDestroySurface(mDisplay, mSurface);
722
mSurface = EGL_NO_SURFACE;
723
}
724
}
725
726
void EGLWindow::destroyContext()
727
{
728
if (mContext != EGL_NO_CONTEXT)
729
{
730
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
731
assert(mDisplay != EGL_NO_DISPLAY);
732
eglDestroyContext(mDisplay, mContext);
733
mContext = EGL_NO_CONTEXT;
734
}
735
}
736
737
bool EGLWindow::isGLInitialized() const
738
{
739
return mSurface != EGL_NO_SURFACE && mContext != EGL_NO_CONTEXT && mDisplay != EGL_NO_DISPLAY;
740
}
741
742
// Find an EGLConfig that is an exact match for the specified attributes. EGL_FALSE is returned if
743
// the EGLConfig is found. This indicates that the EGLConfig is not supported. Surface type is
744
// special-cased as it's possible for a config to return support for both EGL_WINDOW_BIT and
745
// EGL_PBUFFER_BIT even though only one of them is requested.
746
EGLBoolean EGLWindow::FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config)
747
{
748
EGLint numConfigs = 0;
749
eglGetConfigs(dpy, nullptr, 0, &numConfigs);
750
std::vector<EGLConfig> allConfigs(numConfigs);
751
eglGetConfigs(dpy, allConfigs.data(), static_cast<EGLint>(allConfigs.size()), &numConfigs);
752
753
for (size_t i = 0; i < allConfigs.size(); i++)
754
{
755
bool matchFound = true;
756
for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
757
{
758
if (curAttrib[1] == EGL_DONT_CARE)
759
{
760
continue;
761
}
762
763
EGLint actualValue = EGL_DONT_CARE;
764
eglGetConfigAttrib(dpy, allConfigs[i], curAttrib[0], &actualValue);
765
if ((curAttrib[0] == EGL_SURFACE_TYPE &&
766
(curAttrib[1] & actualValue) != curAttrib[1]) ||
767
(curAttrib[0] != EGL_SURFACE_TYPE && curAttrib[1] != actualValue))
768
{
769
matchFound = false;
770
break;
771
}
772
}
773
774
if (matchFound)
775
{
776
*config = allConfigs[i];
777
return EGL_TRUE;
778
}
779
}
780
781
return EGL_FALSE;
782
}
783
784
bool EGLWindow::makeCurrentGeneric(GLWindowContext context)
785
{
786
EGLContext eglContext = reinterpret_cast<EGLContext>(context);
787
return makeCurrent(eglContext);
788
}
789
790
bool EGLWindow::makeCurrent()
791
{
792
return makeCurrent(mContext);
793
}
794
795
bool EGLWindow::makeCurrent(EGLContext context)
796
{
797
if (eglMakeCurrent(mDisplay, mSurface, mSurface, context) == EGL_FALSE ||
798
eglGetError() != EGL_SUCCESS)
799
{
800
fprintf(stderr, "Error during eglMakeCurrent.\n");
801
return false;
802
}
803
804
return true;
805
}
806
807
bool EGLWindow::setSwapInterval(EGLint swapInterval)
808
{
809
if (eglSwapInterval(mDisplay, swapInterval) == EGL_FALSE || eglGetError() != EGL_SUCCESS)
810
{
811
fprintf(stderr, "Error during eglSwapInterval.\n");
812
return false;
813
}
814
815
return true;
816
}
817
818
bool EGLWindow::hasError() const
819
{
820
return eglGetError() != EGL_SUCCESS;
821
}
822
823
angle::GenericProc EGLWindow::getProcAddress(const char *name)
824
{
825
return eglGetProcAddress(name);
826
}
827
828
// static
829
void GLWindowBase::Delete(GLWindowBase **window)
830
{
831
delete *window;
832
*window = nullptr;
833
}
834
835
// static
836
EGLWindow *EGLWindow::New(EGLint glesMajorVersion, EGLint glesMinorVersion)
837
{
838
return new EGLWindow(glesMajorVersion, glesMinorVersion);
839
}
840
841
// static
842
void EGLWindow::Delete(EGLWindow **window)
843
{
844
delete *window;
845
*window = nullptr;
846
}
847
848