Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/src/lib/libegl.js
4150 views
1
/**
2
* @license
3
* Copyright 2012 The Emscripten Authors
4
* SPDX-License-Identifier: MIT
5
*/
6
7
/*
8
* The EGL implementation supports only one EGLNativeDisplayType, the
9
* EGL_DEFAULT_DISPLAY. This native display type returns the only supported
10
* EGLDisplay handle with the magic value 62000. There is only a single
11
* EGLConfig configuration supported, that has the magic value 62002. The
12
* implementation only allows a single EGLContext to be created, that has the
13
* magic value of 62004. (multiple creations silently return this same context)
14
* The implementation only creates a single EGLSurface, a handle with the magic
15
* value of 62006. (multiple creations silently return the same surface)
16
*/
17
18
{{{
19
// Magic ID for Emscripten 'default display'
20
const eglDefaultDisplay = 62000;
21
// Magic ID for the only EGLConfig supported by Emscripten
22
const eglDefaultConfig = 62002;
23
// Magic ID for Emscripten EGLContext
24
const eglDefaultContext = 62004;
25
}}}
26
27
var LibraryEGL = {
28
$EGL__deps: ['$Browser'],
29
$EGL: {
30
// This variable tracks the success status of the most recently invoked EGL function call.
31
errorCode: 0x3000 /* EGL_SUCCESS */,
32
defaultDisplayInitialized: false,
33
currentContext: 0 /* EGL_NO_CONTEXT */,
34
currentReadSurface: 0 /* EGL_NO_SURFACE */,
35
currentDrawSurface: 0 /* EGL_NO_SURFACE */,
36
37
contextAttributes: {
38
alpha: false,
39
depth: false,
40
stencil: false,
41
antialias: false
42
},
43
44
stringCache: {},
45
46
setErrorCode(code) {
47
EGL.errorCode = code;
48
},
49
50
chooseConfig(display, attribList, config, config_size, numConfigs) {
51
if (display != {{{ eglDefaultDisplay }}}) {
52
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
53
return 0;
54
}
55
56
if (attribList) {
57
// read attribList if it is non-null
58
for (;;) {
59
var param = {{{ makeGetValue('attribList', '0', 'i32') }}};
60
if (param == 0x3021 /*EGL_ALPHA_SIZE*/) {
61
var alphaSize = {{{ makeGetValue('attribList', '4', 'i32') }}};
62
EGL.contextAttributes.alpha = (alphaSize > 0);
63
} else if (param == 0x3025 /*EGL_DEPTH_SIZE*/) {
64
var depthSize = {{{ makeGetValue('attribList', '4', 'i32') }}};
65
EGL.contextAttributes.depth = (depthSize > 0);
66
} else if (param == 0x3026 /*EGL_STENCIL_SIZE*/) {
67
var stencilSize = {{{ makeGetValue('attribList', '4', 'i32') }}};
68
EGL.contextAttributes.stencil = (stencilSize > 0);
69
} else if (param == 0x3031 /*EGL_SAMPLES*/) {
70
var samples = {{{ makeGetValue('attribList', '4', 'i32') }}};
71
EGL.contextAttributes.antialias = (samples > 0);
72
} else if (param == 0x3032 /*EGL_SAMPLE_BUFFERS*/) {
73
var samples = {{{ makeGetValue('attribList', '4', 'i32') }}};
74
EGL.contextAttributes.antialias = (samples == 1);
75
} else if (param == 0x3100 /*EGL_CONTEXT_PRIORITY_LEVEL_IMG*/) {
76
var requestedPriority = {{{ makeGetValue('attribList', '4', 'i32') }}};
77
EGL.contextAttributes.lowLatency = (requestedPriority != 0x3103 /*EGL_CONTEXT_PRIORITY_LOW_IMG*/);
78
} else if (param == 0x3038 /*EGL_NONE*/) {
79
break;
80
}
81
attribList += 8;
82
}
83
}
84
85
if ((!config || !config_size) && !numConfigs) {
86
EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);
87
return 0;
88
}
89
if (numConfigs) {
90
{{{ makeSetValue('numConfigs', '0', '1', 'i32') }}}; // Total number of supported configs: 1.
91
}
92
if (config && config_size > 0) {
93
{{{ makeSetValue('config', '0', eglDefaultConfig /* Magic ID for the only EGLConfig supported by Emscripten */, '*') }}};
94
}
95
96
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
97
return 1;
98
},
99
},
100
101
// EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);
102
eglGetDisplay__proxy: 'sync',
103
eglGetDisplay: (nativeDisplayType) => {
104
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
105
// Emscripten EGL implementation "emulates" X11, and eglGetDisplay is
106
// expected to accept/receive a pointer to an X11 Display object (or
107
// EGL_DEFAULT_DISPLAY).
108
if (nativeDisplayType != 0 /* EGL_DEFAULT_DISPLAY */ && nativeDisplayType != 1 /* see library_xlib.js */) {
109
return 0; // EGL_NO_DISPLAY
110
}
111
return {{{ eglDefaultDisplay }}};
112
},
113
114
// EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
115
eglInitialize__proxy: 'sync',
116
eglInitialize: (display, majorVersion, minorVersion) => {
117
if (display != {{{ eglDefaultDisplay }}}) {
118
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
119
return 0;
120
}
121
if (majorVersion) {
122
{{{ makeSetValue('majorVersion', '0', '1', 'i32') }}}; // Advertise EGL Major version: '1'
123
}
124
if (minorVersion) {
125
{{{ makeSetValue('minorVersion', '0', '4', 'i32') }}}; // Advertise EGL Minor version: '4'
126
}
127
EGL.defaultDisplayInitialized = true;
128
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
129
return 1;
130
},
131
132
// EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);
133
eglTerminate__proxy: 'sync',
134
eglTerminate: (display) => {
135
if (display != {{{ eglDefaultDisplay }}}) {
136
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
137
return 0;
138
}
139
EGL.currentContext = 0;
140
EGL.currentReadSurface = 0;
141
EGL.currentDrawSurface = 0;
142
EGL.defaultDisplayInitialized = false;
143
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
144
return 1;
145
},
146
147
// EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
148
eglGetConfigs__proxy: 'sync',
149
eglGetConfigs: (display, configs, config_size, numConfigs) =>
150
EGL.chooseConfig(display, 0, configs, config_size, numConfigs),
151
152
// EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
153
eglChooseConfig__proxy: 'sync',
154
eglChooseConfig: (display, attrib_list, configs, config_size, numConfigs) =>
155
EGL.chooseConfig(display, attrib_list, configs, config_size, numConfigs),
156
157
// EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
158
eglGetConfigAttrib__proxy: 'sync',
159
eglGetConfigAttrib: (display, config, attribute, value) => {
160
if (display != {{{ eglDefaultDisplay }}}) {
161
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
162
return 0;
163
}
164
if (config != {{{ eglDefaultConfig }}}) {
165
EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */);
166
return 0;
167
}
168
if (!value) {
169
EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);
170
return 0;
171
}
172
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
173
switch (attribute) {
174
case 0x3020: // EGL_BUFFER_SIZE
175
{{{ makeSetValue('value', '0', 'EGL.contextAttributes.alpha ? 32 : 24' /* 8 bits for each R,G,B. 8 bits for alpha if enabled*/, 'i32') }}};
176
return 1;
177
case 0x3021: // EGL_ALPHA_SIZE
178
{{{ makeSetValue('value', '0', 'EGL.contextAttributes.alpha ? 8 : 0' /* 8 bits for alpha channel if enabled. */, 'i32') }}};
179
return 1;
180
case 0x3022: // EGL_BLUE_SIZE
181
{{{ makeSetValue('value', '0', '8' /* 8 bits for blue channel. */, 'i32') }}};
182
return 1;
183
case 0x3023: // EGL_GREEN_SIZE
184
{{{ makeSetValue('value', '0', '8' /* 8 bits for green channel. */, 'i32') }}};
185
return 1;
186
case 0x3024: // EGL_RED_SIZE
187
{{{ makeSetValue('value', '0', '8' /* 8 bits for red channel. */, 'i32') }}};
188
return 1;
189
case 0x3025: // EGL_DEPTH_SIZE
190
{{{ makeSetValue('value', '0', 'EGL.contextAttributes.depth ? 24 : 0' /* 24 bits for depth buffer if enabled. */, 'i32') }}};
191
return 1;
192
case 0x3026: // EGL_STENCIL_SIZE
193
{{{ makeSetValue('value', '0', 'EGL.contextAttributes.stencil ? 8 : 0' /* 8 bits for stencil buffer if enabled. */, 'i32') }}};
194
return 1;
195
case 0x3027: // EGL_CONFIG_CAVEAT
196
// We can return here one of EGL_NONE (0x3038), EGL_SLOW_CONFIG (0x3050) or EGL_NON_CONFORMANT_CONFIG (0x3051).
197
{{{ makeSetValue('value', '0', '0x3038' /* EGL_NONE */, 'i32') }}};
198
return 1;
199
case 0x3028: // EGL_CONFIG_ID
200
{{{ makeSetValue('value', '0', eglDefaultConfig, 'i32') }}};
201
return 1;
202
case 0x3029: // EGL_LEVEL
203
{{{ makeSetValue('value', '0', '0' /* Z order/depth layer for this level. Not applicable for Emscripten. */, 'i32') }}};
204
return 1;
205
case 0x302A: // EGL_MAX_PBUFFER_HEIGHT
206
{{{ makeSetValue('value', '0', '4096', 'i32') }}};
207
return 1;
208
case 0x302B: // EGL_MAX_PBUFFER_PIXELS
209
{{{ makeSetValue('value', '0', '16777216' /* 4096 * 4096 */, 'i32') }}};
210
return 1;
211
case 0x302C: // EGL_MAX_PBUFFER_WIDTH
212
{{{ makeSetValue('value', '0', '4096', 'i32') }}};
213
return 1;
214
case 0x302D: // EGL_NATIVE_RENDERABLE
215
{{{ makeSetValue('value', '0', '0' /* This config does not allow co-rendering with other 'native' rendering APIs. */, 'i32') }}};
216
return 1;
217
case 0x302E: // EGL_NATIVE_VISUAL_ID
218
{{{ makeSetValue('value', '0', '0' /* N/A for Emscripten. */, 'i32') }}};
219
return 1;
220
case 0x302F: // EGL_NATIVE_VISUAL_TYPE
221
{{{ makeSetValue('value', '0', '0x3038' /* EGL_NONE */, 'i32') }}};
222
return 1;
223
case 0x3031: // EGL_SAMPLES
224
{{{ makeSetValue('value', '0', 'EGL.contextAttributes.antialias ? 4 : 0' /* 2x2 Multisampling */, 'i32') }}};
225
return 1;
226
case 0x3032: // EGL_SAMPLE_BUFFERS
227
{{{ makeSetValue('value', '0', 'EGL.contextAttributes.antialias ? 1 : 0' /* Multisampling enabled */, 'i32') }}};
228
return 1;
229
case 0x3033: // EGL_SURFACE_TYPE
230
{{{ makeSetValue('value', '0', '0x4' /* EGL_WINDOW_BIT */, 'i32') }}};
231
return 1;
232
case 0x3034: // EGL_TRANSPARENT_TYPE
233
// If this returns EGL_TRANSPARENT_RGB (0x3052), transparency is used through color-keying. No such thing applies to Emscripten canvas.
234
{{{ makeSetValue('value', '0', '0x3038' /* EGL_NONE */, 'i32') }}};
235
return 1;
236
case 0x3035: // EGL_TRANSPARENT_BLUE_VALUE
237
case 0x3036: // EGL_TRANSPARENT_GREEN_VALUE
238
case 0x3037: // EGL_TRANSPARENT_RED_VALUE
239
// "If EGL_TRANSPARENT_TYPE is EGL_NONE, then the values for EGL_TRANSPARENT_RED_VALUE, EGL_TRANSPARENT_GREEN_VALUE, and EGL_TRANSPARENT_BLUE_VALUE are undefined."
240
{{{ makeSetValue('value', '0', '-1' /* Report a "does not apply" value. */, 'i32') }}};
241
return 1;
242
case 0x3039: // EGL_BIND_TO_TEXTURE_RGB
243
case 0x303A: // EGL_BIND_TO_TEXTURE_RGBA
244
{{{ makeSetValue('value', '0', '0' /* Only pbuffers would be bindable, but these are not supported. */, 'i32') }}};
245
return 1;
246
case 0x303B: // EGL_MIN_SWAP_INTERVAL
247
{{{ makeSetValue('value', '0', '0', 'i32') }}};
248
return 1;
249
case 0x303C: // EGL_MAX_SWAP_INTERVAL
250
{{{ makeSetValue('value', '0', '1' /* TODO: Currently this is not strictly true, since user can specify custom presentation interval in JS requestAnimationFrame/emscripten_set_main_loop. */, 'i32') }}};
251
return 1;
252
case 0x303D: // EGL_LUMINANCE_SIZE
253
case 0x303E: // EGL_ALPHA_MASK_SIZE
254
{{{ makeSetValue('value', '0', '0' /* N/A in this config. */, 'i32') }}};
255
return 1;
256
case 0x303F: // EGL_COLOR_BUFFER_TYPE
257
// EGL has two types of buffers: EGL_RGB_BUFFER and EGL_LUMINANCE_BUFFER.
258
{{{ makeSetValue('value', '0', '0x308E' /* EGL_RGB_BUFFER */, 'i32') }}};
259
return 1;
260
case 0x3040: // EGL_RENDERABLE_TYPE
261
// A bit combination of EGL_OPENGL_ES_BIT,EGL_OPENVG_BIT,EGL_OPENGL_ES2_BIT and EGL_OPENGL_BIT.
262
{{{ makeSetValue('value', '0', '0x4' /* EGL_OPENGL_ES2_BIT */, 'i32') }}};
263
return 1;
264
case 0x3042: // EGL_CONFORMANT
265
// "EGL_CONFORMANT is a mask indicating if a client API context created with respect to the corresponding EGLConfig will pass the required conformance tests for that API."
266
{{{ makeSetValue('value', '0', '0' /* EGL_OPENGL_ES2_BIT */, 'i32') }}};
267
return 1;
268
default:
269
EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */);
270
return 0;
271
}
272
},
273
274
// EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
275
eglCreateWindowSurface__proxy: 'sync',
276
eglCreateWindowSurface: (display, config, win, attrib_list) => {
277
if (display != {{{ eglDefaultDisplay }}}) {
278
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
279
return 0;
280
}
281
if (config != {{{ eglDefaultConfig }}}) {
282
EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */);
283
return 0;
284
}
285
// TODO: Examine attrib_list! Parameters that can be present there are:
286
// - EGL_RENDER_BUFFER (must be EGL_BACK_BUFFER)
287
// - EGL_VG_COLORSPACE (can't be set)
288
// - EGL_VG_ALPHA_FORMAT (can't be set)
289
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
290
return 62006; /* Magic ID for Emscripten 'default surface' */
291
},
292
293
// EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface);
294
eglDestroySurface__proxy: 'sync',
295
eglDestroySurface: (display, surface) => {
296
if (display != {{{ eglDefaultDisplay }}}) {
297
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
298
return 0;
299
}
300
if (surface != 62006 /* Magic ID for the only EGLSurface supported by Emscripten */) {
301
EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */);
302
return 1;
303
}
304
if (EGL.currentReadSurface == surface) {
305
EGL.currentReadSurface = 0;
306
}
307
if (EGL.currentDrawSurface == surface) {
308
EGL.currentDrawSurface = 0;
309
}
310
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
311
return 1; /* Magic ID for Emscripten 'default surface' */
312
},
313
314
eglCreateContext__deps: ['$GL'],
315
316
// EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
317
eglCreateContext__proxy: 'sync',
318
eglCreateContext: (display, config, hmm, contextAttribs) => {
319
if (display != {{{ eglDefaultDisplay }}}) {
320
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
321
return 0;
322
}
323
324
// EGL 1.4 spec says default EGL_CONTEXT_CLIENT_VERSION is GLES1, but this is not supported by Emscripten.
325
// So user must pass EGL_CONTEXT_CLIENT_VERSION == 2 to initialize EGL.
326
var glesContextVersion = 1;
327
for (;;) {
328
var param = {{{ makeGetValue('contextAttribs', '0', 'i32') }}};
329
if (param == 0x3098 /*EGL_CONTEXT_CLIENT_VERSION*/) {
330
glesContextVersion = {{{ makeGetValue('contextAttribs', '4', 'i32') }}};
331
} else if (param == 0x3038 /*EGL_NONE*/) {
332
break;
333
} else {
334
/* EGL1.4 specifies only EGL_CONTEXT_CLIENT_VERSION as supported attribute */
335
EGL.setErrorCode(0x3004 /*EGL_BAD_ATTRIBUTE*/);
336
return 0;
337
}
338
contextAttribs += 8;
339
}
340
#if MAX_WEBGL_VERSION >= 2
341
if (glesContextVersion < 2 || glesContextVersion > 3) {
342
#else
343
if (glesContextVersion != 2) {
344
#endif
345
#if GL_ASSERTIONS
346
if (glesContextVersion == 3) {
347
err('When initializing GLES3/WebGL2 via EGL, one must build with -sMAX_WEBGL_VERSION=2!');
348
} else {
349
err(`When initializing GLES2/WebGL1 via EGL, one must pass EGL_CONTEXT_CLIENT_VERSION = 2 to GL context attributes! GLES version ${glesContextVersion} is not supported!`);
350
}
351
#endif
352
EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */);
353
return 0; /* EGL_NO_CONTEXT */
354
}
355
356
EGL.contextAttributes.majorVersion = glesContextVersion - 1; // WebGL 1 is GLES 2, WebGL2 is GLES3
357
EGL.contextAttributes.minorVersion = 0;
358
359
EGL.context = GL.createContext(Browser.getCanvas(), EGL.contextAttributes);
360
361
if (EGL.context != 0) {
362
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
363
364
// Run callbacks so that GL emulation works
365
GL.makeContextCurrent(EGL.context);
366
Browser.useWebGL = true;
367
Browser.moduleContextCreatedCallbacks.forEach((callback) => callback());
368
369
// Note: This function only creates a context, but it shall not make it active.
370
GL.makeContextCurrent(null);
371
return {{{ eglDefaultContext }}};
372
} else {
373
EGL.setErrorCode(0x3009 /* EGL_BAD_MATCH */); // By the EGL 1.4 spec, an implementation that does not support GLES2 (WebGL in this case), this error code is set.
374
return 0; /* EGL_NO_CONTEXT */
375
}
376
},
377
378
eglDestroyContext__deps: ['$GL'],
379
380
// EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext context);
381
eglDestroyContext__proxy: 'sync',
382
eglDestroyContext: (display, context) => {
383
if (display != {{{ eglDefaultDisplay }}}) {
384
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
385
return 0;
386
}
387
if (context != {{{ eglDefaultContext }}}) {
388
EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */);
389
return 0;
390
}
391
392
GL.deleteContext(EGL.context);
393
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
394
if (EGL.currentContext == context) {
395
EGL.currentContext = 0;
396
}
397
return 1 /* EGL_TRUE */;
398
},
399
400
// EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
401
eglQuerySurface__proxy: 'sync',
402
eglQuerySurface: (display, surface, attribute, value) => {
403
if (display != {{{ eglDefaultDisplay }}}) {
404
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
405
return 0;
406
}
407
if (surface != 62006 /* Magic ID for Emscripten 'default surface' */) {
408
EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */);
409
return 0;
410
}
411
if (!value) {
412
EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);
413
return 0;
414
}
415
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
416
switch (attribute) {
417
case 0x3028: // EGL_CONFIG_ID
418
{{{ makeSetValue('value', '0', eglDefaultConfig, 'i32') }}};
419
return 1;
420
case 0x3058: // EGL_LARGEST_PBUFFER
421
// Odd EGL API: If surface is not a pbuffer surface, 'value' should not be written to. It's not specified as an error, so true should(?) be returned.
422
// Existing Android implementation seems to do so at least.
423
return 1;
424
case 0x3057: // EGL_WIDTH
425
{{{ makeSetValue('value', '0', "Browser.getCanvas().width", 'i32') }}};
426
return 1;
427
case 0x3056: // EGL_HEIGHT
428
{{{ makeSetValue('value', '0', "Browser.getCanvas().height", 'i32') }}};
429
return 1;
430
case 0x3090: // EGL_HORIZONTAL_RESOLUTION
431
{{{ makeSetValue('value', '0', '-1' /* EGL_UNKNOWN */, 'i32') }}};
432
return 1;
433
case 0x3091: // EGL_VERTICAL_RESOLUTION
434
{{{ makeSetValue('value', '0', '-1' /* EGL_UNKNOWN */, 'i32') }}};
435
return 1;
436
case 0x3092: // EGL_PIXEL_ASPECT_RATIO
437
{{{ makeSetValue('value', '0', '-1' /* EGL_UNKNOWN */, 'i32') }}};
438
return 1;
439
case 0x3086: // EGL_RENDER_BUFFER
440
// The main surface is bound to the visible canvas window - it's always backbuffered.
441
// Alternative to EGL_BACK_BUFFER would be EGL_SINGLE_BUFFER.
442
{{{ makeSetValue('value', '0', '0x3084' /* EGL_BACK_BUFFER */, 'i32') }}};
443
return 1;
444
case 0x3099: // EGL_MULTISAMPLE_RESOLVE
445
{{{ makeSetValue('value', '0', '0x309A' /* EGL_MULTISAMPLE_RESOLVE_DEFAULT */, 'i32') }}};
446
return 1;
447
case 0x3093: // EGL_SWAP_BEHAVIOR
448
// The two possibilities are EGL_BUFFER_PRESERVED and EGL_BUFFER_DESTROYED. Slightly unsure which is the
449
// case for browser environment, but advertise the 'weaker' behavior to be sure.
450
{{{ makeSetValue('value', '0', '0x3095' /* EGL_BUFFER_DESTROYED */, 'i32') }}};
451
return 1;
452
case 0x3080: // EGL_TEXTURE_FORMAT
453
case 0x3081: // EGL_TEXTURE_TARGET
454
case 0x3082: // EGL_MIPMAP_TEXTURE
455
case 0x3083: // EGL_MIPMAP_LEVEL
456
// This is a window surface, not a pbuffer surface. Spec:
457
// "Querying EGL_TEXTURE_FORMAT, EGL_TEXTURE_TARGET, EGL_MIPMAP_TEXTURE, or EGL_MIPMAP_LEVEL for a non-pbuffer surface is not an error, but value is not modified."
458
// So pass-through.
459
return 1;
460
default:
461
EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */);
462
return 0;
463
}
464
},
465
466
// EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
467
eglQueryContext__proxy: 'sync',
468
eglQueryContext: (display, context, attribute, value) => {
469
if (display != {{{ eglDefaultDisplay }}}) {
470
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
471
return 0;
472
}
473
//\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy.
474
if (context != {{{ eglDefaultContext }}}) {
475
EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */);
476
return 0;
477
}
478
if (!value) {
479
EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);
480
return 0;
481
}
482
483
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
484
switch (attribute) {
485
case 0x3028: // EGL_CONFIG_ID
486
{{{ makeSetValue('value', '0', eglDefaultConfig, 'i32') }}};
487
return 1;
488
case 0x3097: // EGL_CONTEXT_CLIENT_TYPE
489
{{{ makeSetValue('value', '0', '0x30A0' /* EGL_OPENGL_ES_API */, 'i32') }}};
490
return 1;
491
case 0x3098: // EGL_CONTEXT_CLIENT_VERSION
492
{{{ makeSetValue('value', '0', 'EGL.contextAttributes.majorVersion + 1', 'i32') }}};
493
return 1;
494
case 0x3086: // EGL_RENDER_BUFFER
495
// The context is bound to the visible canvas window - it's always backbuffered.
496
// Alternative to EGL_BACK_BUFFER would be EGL_SINGLE_BUFFER.
497
{{{ makeSetValue('value', '0', '0x3084' /* EGL_BACK_BUFFER */, 'i32') }}};
498
return 1;
499
default:
500
EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */);
501
return 0;
502
}
503
},
504
505
// EGLAPI EGLint EGLAPIENTRY eglGetError(void);
506
eglGetError__proxy: 'sync',
507
eglGetError: () => EGL.errorCode,
508
509
// EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);
510
// The allocated strings are cached and never freed.
511
eglQueryString__noleakcheck: true,
512
eglQueryString__deps: ['$stringToNewUTF8'],
513
eglQueryString__proxy: 'sync',
514
eglQueryString: (display, name) => {
515
if (display != {{{ eglDefaultDisplay }}}) {
516
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
517
return 0;
518
}
519
//\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy.
520
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
521
if (EGL.stringCache[name]) return EGL.stringCache[name];
522
var ret;
523
switch (name) {
524
case 0x3053 /* EGL_VENDOR */: ret = stringToNewUTF8("Emscripten"); break;
525
case 0x3054 /* EGL_VERSION */: ret = stringToNewUTF8("1.4 Emscripten EGL"); break;
526
case 0x3055 /* EGL_EXTENSIONS */: ret = stringToNewUTF8(""); break; // Currently not supporting any EGL extensions.
527
case 0x308D /* EGL_CLIENT_APIS */: ret = stringToNewUTF8("OpenGL_ES"); break;
528
default:
529
EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);
530
return 0;
531
}
532
EGL.stringCache[name] = ret;
533
return ret;
534
},
535
536
// EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);
537
eglBindAPI__proxy: 'sync',
538
eglBindAPI: (api) => {
539
if (api == 0x30A0 /* EGL_OPENGL_ES_API */) {
540
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
541
return 1;
542
}
543
// if (api == 0x30A1 /* EGL_OPENVG_API */ || api == 0x30A2 /* EGL_OPENGL_API */) {
544
EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);
545
return 0;
546
},
547
548
// EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);
549
eglQueryAPI__proxy: 'sync',
550
eglQueryAPI: () => {
551
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
552
return 0x30A0; // EGL_OPENGL_ES_API
553
},
554
555
// EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);
556
eglWaitClient__proxy: 'sync',
557
eglWaitClient: () => {
558
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
559
return 1;
560
},
561
562
// EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);
563
eglWaitNative__proxy: 'sync',
564
eglWaitNative: (nativeEngineId) => {
565
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
566
return 1;
567
},
568
569
570
// EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);
571
eglWaitGL: 'eglWaitClient',
572
573
// EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);
574
eglSwapInterval__deps: ['emscripten_set_main_loop_timing'],
575
eglSwapInterval__proxy: 'sync',
576
eglSwapInterval: (display, interval) => {
577
if (display != {{{ eglDefaultDisplay }}}) {
578
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
579
return 0;
580
}
581
if (interval == 0) _emscripten_set_main_loop_timing({{{ cDefs.EM_TIMING_SETTIMEOUT }}}, 0);
582
else _emscripten_set_main_loop_timing({{{ cDefs.EM_TIMING_RAF }}}, interval);
583
584
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
585
return 1;
586
},
587
588
// EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
589
eglMakeCurrent__deps: ['$GL'],
590
eglMakeCurrent__proxy: 'sync',
591
eglMakeCurrent: (display, draw, read, context) => {
592
if (display != {{{ eglDefaultDisplay }}}) {
593
EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
594
return 0 /* EGL_FALSE */;
595
}
596
//\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy.
597
if (context != 0 && context != {{{ eglDefaultContext }}}) {
598
EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */);
599
return 0;
600
}
601
if ((read != 0 && read != 62006) || (draw != 0 && draw != 62006 /* Magic ID for Emscripten 'default surface' */)) {
602
EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */);
603
return 0;
604
}
605
606
GL.makeContextCurrent(context ? EGL.context : null);
607
608
EGL.currentContext = context;
609
EGL.currentDrawSurface = draw;
610
EGL.currentReadSurface = read;
611
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
612
return 1 /* EGL_TRUE */;
613
},
614
615
// EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);
616
eglGetCurrentContext__proxy: 'sync',
617
eglGetCurrentContext: () => EGL.currentContext,
618
619
// EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);
620
eglGetCurrentSurface__proxy: 'sync',
621
eglGetCurrentSurface: (readdraw) => {
622
if (readdraw == 0x305A /* EGL_READ */) {
623
return EGL.currentReadSurface;
624
} else if (readdraw == 0x3059 /* EGL_DRAW */) {
625
return EGL.currentDrawSurface;
626
} else {
627
EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);
628
return 0 /* EGL_NO_SURFACE */;
629
}
630
},
631
632
// EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);
633
eglGetCurrentDisplay__proxy: 'sync',
634
eglGetCurrentDisplay: () => EGL.currentContext ? {{{ eglDefaultDisplay }}} : 0,
635
636
// EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
637
eglSwapBuffers__deps: ['$GLctx'],
638
eglSwapBuffers__proxy: 'sync',
639
eglSwapBuffers: (dpy, surface) => {
640
#if PROXY_TO_WORKER
641
if (Browser.doSwapBuffers) Browser.doSwapBuffers();
642
#endif
643
644
if (!EGL.defaultDisplayInitialized) {
645
EGL.setErrorCode(0x3001 /* EGL_NOT_INITIALIZED */);
646
} else if (!GLctx) {
647
EGL.setErrorCode(0x3002 /* EGL_BAD_ACCESS */);
648
} else if (GLctx.isContextLost()) {
649
EGL.setErrorCode(0x300E /* EGL_CONTEXT_LOST */);
650
} else {
651
// According to documentation this does an implicit flush.
652
// Due to discussion at https://github.com/emscripten-core/emscripten/pull/1871
653
// the flush was removed since this _may_ result in slowing code down.
654
//_glFlush();
655
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
656
return 1 /* EGL_TRUE */;
657
}
658
return 0 /* EGL_FALSE */;
659
},
660
661
eglReleaseThread__proxy: 'sync',
662
eglReleaseThread: () => {
663
// Equivalent to eglMakeCurrent with EGL_NO_CONTEXT and EGL_NO_SURFACE.
664
EGL.currentContext = 0;
665
EGL.currentReadSurface = 0;
666
EGL.currentDrawSurface = 0;
667
// EGL spec v1.4 p.55:
668
// "calling eglGetError immediately following a successful call to eglReleaseThread should not be done.
669
// Such a call will return EGL_SUCCESS - but will also result in reallocating per-thread state."
670
EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
671
return 1 /* EGL_TRUE */;
672
}
673
};
674
675
autoAddDeps(LibraryEGL, '$EGL');
676
677
addToLibrary(LibraryEGL);
678
679