Buckets:
| /** | |
| * @license | |
| * Copyright 2012 The Emscripten Authors | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| /* | |
| * The EGL implementation supports only one EGLNativeDisplayType, the | |
| * EGL_DEFAULT_DISPLAY. This native display type returns the only supported | |
| * EGLDisplay handle with the magic value 62000. There is only a single | |
| * EGLConfig configuration supported, that has the magic value 62002. The | |
| * implementation only allows a single EGLContext to be created, that has the | |
| * magic value of 62004. (multiple creations silently return this same context) | |
| * The implementation only creates a single EGLSurface, a handle with the magic | |
| * value of 62006. (multiple creations silently return the same surface) | |
| */ | |
| {{{ | |
| // Magic ID for Emscripten 'default display' | |
| const eglDefaultDisplay = 62000; | |
| // Magic ID for the only EGLConfig supported by Emscripten | |
| const eglDefaultConfig = 62002; | |
| // Magic ID for Emscripten EGLContext | |
| const eglDefaultContext = 62004; | |
| }}} | |
| var LibraryEGL = { | |
| $EGL__deps: ['$Browser'], | |
| $EGL: { | |
| // This variable tracks the success status of the most recently invoked EGL function call. | |
| errorCode: 0x3000 /* EGL_SUCCESS */, | |
| defaultDisplayInitialized: false, | |
| currentContext: 0 /* EGL_NO_CONTEXT */, | |
| currentReadSurface: 0 /* EGL_NO_SURFACE */, | |
| currentDrawSurface: 0 /* EGL_NO_SURFACE */, | |
| contextAttributes: { | |
| alpha: false, | |
| depth: false, | |
| stencil: false, | |
| antialias: false | |
| }, | |
| stringCache: {}, | |
| setErrorCode(code) { | |
| EGL.errorCode = code; | |
| }, | |
| chooseConfig(display, attribList, config, config_size, numConfigs) { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| if (attribList) { | |
| // read attribList if it is non-null | |
| for (;;) { | |
| var param = {{{ makeGetValue('attribList', '0', 'i32') }}}; | |
| if (param == 0x3021 /*EGL_ALPHA_SIZE*/) { | |
| var alphaSize = {{{ makeGetValue('attribList', '4', 'i32') }}}; | |
| EGL.contextAttributes.alpha = (alphaSize > 0); | |
| } else if (param == 0x3025 /*EGL_DEPTH_SIZE*/) { | |
| var depthSize = {{{ makeGetValue('attribList', '4', 'i32') }}}; | |
| EGL.contextAttributes.depth = (depthSize > 0); | |
| } else if (param == 0x3026 /*EGL_STENCIL_SIZE*/) { | |
| var stencilSize = {{{ makeGetValue('attribList', '4', 'i32') }}}; | |
| EGL.contextAttributes.stencil = (stencilSize > 0); | |
| } else if (param == 0x3031 /*EGL_SAMPLES*/) { | |
| var samples = {{{ makeGetValue('attribList', '4', 'i32') }}}; | |
| EGL.contextAttributes.antialias = (samples > 0); | |
| } else if (param == 0x3032 /*EGL_SAMPLE_BUFFERS*/) { | |
| var samples = {{{ makeGetValue('attribList', '4', 'i32') }}}; | |
| EGL.contextAttributes.antialias = (samples == 1); | |
| } else if (param == 0x3100 /*EGL_CONTEXT_PRIORITY_LEVEL_IMG*/) { | |
| var requestedPriority = {{{ makeGetValue('attribList', '4', 'i32') }}}; | |
| EGL.contextAttributes.lowLatency = (requestedPriority != 0x3103 /*EGL_CONTEXT_PRIORITY_LOW_IMG*/); | |
| } else if (param == 0x3038 /*EGL_NONE*/) { | |
| break; | |
| } | |
| attribList += 8; | |
| } | |
| } | |
| if ((!config || !config_size) && !numConfigs) { | |
| EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); | |
| return 0; | |
| } | |
| if (numConfigs) { | |
| {{{ makeSetValue('numConfigs', '0', '1', 'i32') }}}; // Total number of supported configs: 1. | |
| } | |
| if (config && config_size > 0) { | |
| {{{ makeSetValue('config', '0', eglDefaultConfig /* Magic ID for the only EGLConfig supported by Emscripten */, '*') }}}; | |
| } | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1; | |
| }, | |
| }, | |
| // EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id); | |
| eglGetDisplay__proxy: 'sync', | |
| eglGetDisplay: (nativeDisplayType) => { | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| // Emscripten EGL implementation "emulates" X11, and eglGetDisplay is | |
| // expected to accept/receive a pointer to an X11 Display object (or | |
| // EGL_DEFAULT_DISPLAY). | |
| if (nativeDisplayType != 0 /* EGL_DEFAULT_DISPLAY */ && nativeDisplayType != 1 /* see library_xlib.js */) { | |
| return 0; // EGL_NO_DISPLAY | |
| } | |
| return {{{ eglDefaultDisplay }}}; | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor); | |
| eglInitialize__proxy: 'sync', | |
| eglInitialize: (display, majorVersion, minorVersion) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| if (majorVersion) { | |
| {{{ makeSetValue('majorVersion', '0', '1', 'i32') }}}; // Advertise EGL Major version: '1' | |
| } | |
| if (minorVersion) { | |
| {{{ makeSetValue('minorVersion', '0', '4', 'i32') }}}; // Advertise EGL Minor version: '4' | |
| } | |
| EGL.defaultDisplayInitialized = true; | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1; | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy); | |
| eglTerminate__proxy: 'sync', | |
| eglTerminate: (display) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| EGL.currentContext = 0; | |
| EGL.currentReadSurface = 0; | |
| EGL.currentDrawSurface = 0; | |
| EGL.defaultDisplayInitialized = false; | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1; | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); | |
| eglGetConfigs__proxy: 'sync', | |
| eglGetConfigs: (display, configs, config_size, numConfigs) => | |
| EGL.chooseConfig(display, 0, configs, config_size, numConfigs), | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); | |
| eglChooseConfig__proxy: 'sync', | |
| eglChooseConfig: (display, attrib_list, configs, config_size, numConfigs) => | |
| EGL.chooseConfig(display, attrib_list, configs, config_size, numConfigs), | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); | |
| eglGetConfigAttrib__proxy: 'sync', | |
| eglGetConfigAttrib: (display, config, attribute, value) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| if (config != {{{ eglDefaultConfig }}}) { | |
| EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */); | |
| return 0; | |
| } | |
| if (!value) { | |
| EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); | |
| return 0; | |
| } | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| switch (attribute) { | |
| case 0x3020: // EGL_BUFFER_SIZE | |
| {{{ makeSetValue('value', '0', 'EGL.contextAttributes.alpha ? 32 : 24' /* 8 bits for each R,G,B. 8 bits for alpha if enabled*/, 'i32') }}}; | |
| return 1; | |
| case 0x3021: // EGL_ALPHA_SIZE | |
| {{{ makeSetValue('value', '0', 'EGL.contextAttributes.alpha ? 8 : 0' /* 8 bits for alpha channel if enabled. */, 'i32') }}}; | |
| return 1; | |
| case 0x3022: // EGL_BLUE_SIZE | |
| {{{ makeSetValue('value', '0', '8' /* 8 bits for blue channel. */, 'i32') }}}; | |
| return 1; | |
| case 0x3023: // EGL_GREEN_SIZE | |
| {{{ makeSetValue('value', '0', '8' /* 8 bits for green channel. */, 'i32') }}}; | |
| return 1; | |
| case 0x3024: // EGL_RED_SIZE | |
| {{{ makeSetValue('value', '0', '8' /* 8 bits for red channel. */, 'i32') }}}; | |
| return 1; | |
| case 0x3025: // EGL_DEPTH_SIZE | |
| {{{ makeSetValue('value', '0', 'EGL.contextAttributes.depth ? 24 : 0' /* 24 bits for depth buffer if enabled. */, 'i32') }}}; | |
| return 1; | |
| case 0x3026: // EGL_STENCIL_SIZE | |
| {{{ makeSetValue('value', '0', 'EGL.contextAttributes.stencil ? 8 : 0' /* 8 bits for stencil buffer if enabled. */, 'i32') }}}; | |
| return 1; | |
| case 0x3027: // EGL_CONFIG_CAVEAT | |
| // We can return here one of EGL_NONE (0x3038), EGL_SLOW_CONFIG (0x3050) or EGL_NON_CONFORMANT_CONFIG (0x3051). | |
| {{{ makeSetValue('value', '0', '0x3038' /* EGL_NONE */, 'i32') }}}; | |
| return 1; | |
| case 0x3028: // EGL_CONFIG_ID | |
| {{{ makeSetValue('value', '0', eglDefaultConfig, 'i32') }}}; | |
| return 1; | |
| case 0x3029: // EGL_LEVEL | |
| {{{ makeSetValue('value', '0', '0' /* Z order/depth layer for this level. Not applicable for Emscripten. */, 'i32') }}}; | |
| return 1; | |
| case 0x302A: // EGL_MAX_PBUFFER_HEIGHT | |
| {{{ makeSetValue('value', '0', '4096', 'i32') }}}; | |
| return 1; | |
| case 0x302B: // EGL_MAX_PBUFFER_PIXELS | |
| {{{ makeSetValue('value', '0', '16777216' /* 4096 * 4096 */, 'i32') }}}; | |
| return 1; | |
| case 0x302C: // EGL_MAX_PBUFFER_WIDTH | |
| {{{ makeSetValue('value', '0', '4096', 'i32') }}}; | |
| return 1; | |
| case 0x302D: // EGL_NATIVE_RENDERABLE | |
| {{{ makeSetValue('value', '0', '0' /* This config does not allow co-rendering with other 'native' rendering APIs. */, 'i32') }}}; | |
| return 1; | |
| case 0x302E: // EGL_NATIVE_VISUAL_ID | |
| {{{ makeSetValue('value', '0', '0' /* N/A for Emscripten. */, 'i32') }}}; | |
| return 1; | |
| case 0x302F: // EGL_NATIVE_VISUAL_TYPE | |
| {{{ makeSetValue('value', '0', '0x3038' /* EGL_NONE */, 'i32') }}}; | |
| return 1; | |
| case 0x3031: // EGL_SAMPLES | |
| {{{ makeSetValue('value', '0', 'EGL.contextAttributes.antialias ? 4 : 0' /* 2x2 Multisampling */, 'i32') }}}; | |
| return 1; | |
| case 0x3032: // EGL_SAMPLE_BUFFERS | |
| {{{ makeSetValue('value', '0', 'EGL.contextAttributes.antialias ? 1 : 0' /* Multisampling enabled */, 'i32') }}}; | |
| return 1; | |
| case 0x3033: // EGL_SURFACE_TYPE | |
| {{{ makeSetValue('value', '0', '0x4' /* EGL_WINDOW_BIT */, 'i32') }}}; | |
| return 1; | |
| case 0x3034: // EGL_TRANSPARENT_TYPE | |
| // If this returns EGL_TRANSPARENT_RGB (0x3052), transparency is used through color-keying. No such thing applies to Emscripten canvas. | |
| {{{ makeSetValue('value', '0', '0x3038' /* EGL_NONE */, 'i32') }}}; | |
| return 1; | |
| case 0x3035: // EGL_TRANSPARENT_BLUE_VALUE | |
| case 0x3036: // EGL_TRANSPARENT_GREEN_VALUE | |
| case 0x3037: // EGL_TRANSPARENT_RED_VALUE | |
| // "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." | |
| {{{ makeSetValue('value', '0', '-1' /* Report a "does not apply" value. */, 'i32') }}}; | |
| return 1; | |
| case 0x3039: // EGL_BIND_TO_TEXTURE_RGB | |
| case 0x303A: // EGL_BIND_TO_TEXTURE_RGBA | |
| {{{ makeSetValue('value', '0', '0' /* Only pbuffers would be bindable, but these are not supported. */, 'i32') }}}; | |
| return 1; | |
| case 0x303B: // EGL_MIN_SWAP_INTERVAL | |
| {{{ makeSetValue('value', '0', '0', 'i32') }}}; | |
| return 1; | |
| case 0x303C: // EGL_MAX_SWAP_INTERVAL | |
| {{{ 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') }}}; | |
| return 1; | |
| case 0x303D: // EGL_LUMINANCE_SIZE | |
| case 0x303E: // EGL_ALPHA_MASK_SIZE | |
| {{{ makeSetValue('value', '0', '0' /* N/A in this config. */, 'i32') }}}; | |
| return 1; | |
| case 0x303F: // EGL_COLOR_BUFFER_TYPE | |
| // EGL has two types of buffers: EGL_RGB_BUFFER and EGL_LUMINANCE_BUFFER. | |
| {{{ makeSetValue('value', '0', '0x308E' /* EGL_RGB_BUFFER */, 'i32') }}}; | |
| return 1; | |
| case 0x3040: // EGL_RENDERABLE_TYPE | |
| // A bit combination of EGL_OPENGL_ES_BIT,EGL_OPENVG_BIT,EGL_OPENGL_ES2_BIT and EGL_OPENGL_BIT. | |
| {{{ makeSetValue('value', '0', '0x4' /* EGL_OPENGL_ES2_BIT */, 'i32') }}}; | |
| return 1; | |
| case 0x3042: // EGL_CONFORMANT | |
| // "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." | |
| {{{ makeSetValue('value', '0', '0' /* EGL_OPENGL_ES2_BIT */, 'i32') }}}; | |
| return 1; | |
| default: | |
| EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */); | |
| return 0; | |
| } | |
| }, | |
| // EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); | |
| eglCreateWindowSurface__proxy: 'sync', | |
| eglCreateWindowSurface: (display, config, win, attrib_list) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| if (config != {{{ eglDefaultConfig }}}) { | |
| EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */); | |
| return 0; | |
| } | |
| // TODO: Examine attrib_list! Parameters that can be present there are: | |
| // - EGL_RENDER_BUFFER (must be EGL_BACK_BUFFER) | |
| // - EGL_VG_COLORSPACE (can't be set) | |
| // - EGL_VG_ALPHA_FORMAT (can't be set) | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 62006; /* Magic ID for Emscripten 'default surface' */ | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface); | |
| eglDestroySurface__proxy: 'sync', | |
| eglDestroySurface: (display, surface) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| if (surface != 62006 /* Magic ID for the only EGLSurface supported by Emscripten */) { | |
| EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */); | |
| return 1; | |
| } | |
| if (EGL.currentReadSurface == surface) { | |
| EGL.currentReadSurface = 0; | |
| } | |
| if (EGL.currentDrawSurface == surface) { | |
| EGL.currentDrawSurface = 0; | |
| } | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1; /* Magic ID for Emscripten 'default surface' */ | |
| }, | |
| eglCreateContext__deps: ['$GL'], | |
| // EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); | |
| eglCreateContext__proxy: 'sync', | |
| eglCreateContext: (display, config, hmm, contextAttribs) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| // EGL 1.4 spec says default EGL_CONTEXT_CLIENT_VERSION is GLES1, but this is not supported by Emscripten. | |
| // So user must pass EGL_CONTEXT_CLIENT_VERSION == 2 to initialize EGL. | |
| var glesContextVersion = 1; | |
| for (;;) { | |
| var param = {{{ makeGetValue('contextAttribs', '0', 'i32') }}}; | |
| if (param == 0x3098 /*EGL_CONTEXT_CLIENT_VERSION*/) { | |
| glesContextVersion = {{{ makeGetValue('contextAttribs', '4', 'i32') }}}; | |
| } else if (param == 0x3038 /*EGL_NONE*/) { | |
| break; | |
| } else { | |
| /* EGL1.4 specifies only EGL_CONTEXT_CLIENT_VERSION as supported attribute */ | |
| EGL.setErrorCode(0x3004 /*EGL_BAD_ATTRIBUTE*/); | |
| return 0; | |
| } | |
| contextAttribs += 8; | |
| } | |
| #if MAX_WEBGL_VERSION >= 2 | |
| if (glesContextVersion < 2 || glesContextVersion > 3) { | |
| #else | |
| if (glesContextVersion != 2) { | |
| #endif | |
| #if GL_ASSERTIONS | |
| if (glesContextVersion == 3) { | |
| err('When initializing GLES3/WebGL2 via EGL, one must build with -sMAX_WEBGL_VERSION=2!'); | |
| } else { | |
| 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!`); | |
| } | |
| #endif | |
| EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */); | |
| return 0; /* EGL_NO_CONTEXT */ | |
| } | |
| EGL.contextAttributes.majorVersion = glesContextVersion - 1; // WebGL 1 is GLES 2, WebGL2 is GLES3 | |
| EGL.contextAttributes.minorVersion = 0; | |
| EGL.context = GL.createContext(Browser.getCanvas(), EGL.contextAttributes); | |
| if (EGL.context != 0) { | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| // Run callbacks so that GL emulation works | |
| GL.makeContextCurrent(EGL.context); | |
| Browser.useWebGL = true; | |
| Browser.moduleContextCreatedCallbacks.forEach((callback) => callback()); | |
| // Note: This function only creates a context, but it shall not make it active. | |
| GL.makeContextCurrent(null); | |
| return {{{ eglDefaultContext }}}; | |
| } else { | |
| 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. | |
| return 0; /* EGL_NO_CONTEXT */ | |
| } | |
| }, | |
| eglDestroyContext__deps: ['$GL'], | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext context); | |
| eglDestroyContext__proxy: 'sync', | |
| eglDestroyContext: (display, context) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| if (context != {{{ eglDefaultContext }}}) { | |
| EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */); | |
| return 0; | |
| } | |
| GL.deleteContext(EGL.context); | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| if (EGL.currentContext == context) { | |
| EGL.currentContext = 0; | |
| } | |
| return 1 /* EGL_TRUE */; | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); | |
| eglQuerySurface__proxy: 'sync', | |
| eglQuerySurface: (display, surface, attribute, value) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| if (surface != 62006 /* Magic ID for Emscripten 'default surface' */) { | |
| EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */); | |
| return 0; | |
| } | |
| if (!value) { | |
| EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); | |
| return 0; | |
| } | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| switch (attribute) { | |
| case 0x3028: // EGL_CONFIG_ID | |
| {{{ makeSetValue('value', '0', eglDefaultConfig, 'i32') }}}; | |
| return 1; | |
| case 0x3058: // EGL_LARGEST_PBUFFER | |
| // 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. | |
| // Existing Android implementation seems to do so at least. | |
| return 1; | |
| case 0x3057: // EGL_WIDTH | |
| {{{ makeSetValue('value', '0', "Browser.getCanvas().width", 'i32') }}}; | |
| return 1; | |
| case 0x3056: // EGL_HEIGHT | |
| {{{ makeSetValue('value', '0', "Browser.getCanvas().height", 'i32') }}}; | |
| return 1; | |
| case 0x3090: // EGL_HORIZONTAL_RESOLUTION | |
| {{{ makeSetValue('value', '0', '-1' /* EGL_UNKNOWN */, 'i32') }}}; | |
| return 1; | |
| case 0x3091: // EGL_VERTICAL_RESOLUTION | |
| {{{ makeSetValue('value', '0', '-1' /* EGL_UNKNOWN */, 'i32') }}}; | |
| return 1; | |
| case 0x3092: // EGL_PIXEL_ASPECT_RATIO | |
| {{{ makeSetValue('value', '0', '-1' /* EGL_UNKNOWN */, 'i32') }}}; | |
| return 1; | |
| case 0x3086: // EGL_RENDER_BUFFER | |
| // The main surface is bound to the visible canvas window - it's always backbuffered. | |
| // Alternative to EGL_BACK_BUFFER would be EGL_SINGLE_BUFFER. | |
| {{{ makeSetValue('value', '0', '0x3084' /* EGL_BACK_BUFFER */, 'i32') }}}; | |
| return 1; | |
| case 0x3099: // EGL_MULTISAMPLE_RESOLVE | |
| {{{ makeSetValue('value', '0', '0x309A' /* EGL_MULTISAMPLE_RESOLVE_DEFAULT */, 'i32') }}}; | |
| return 1; | |
| case 0x3093: // EGL_SWAP_BEHAVIOR | |
| // The two possibilities are EGL_BUFFER_PRESERVED and EGL_BUFFER_DESTROYED. Slightly unsure which is the | |
| // case for browser environment, but advertise the 'weaker' behavior to be sure. | |
| {{{ makeSetValue('value', '0', '0x3095' /* EGL_BUFFER_DESTROYED */, 'i32') }}}; | |
| return 1; | |
| case 0x3080: // EGL_TEXTURE_FORMAT | |
| case 0x3081: // EGL_TEXTURE_TARGET | |
| case 0x3082: // EGL_MIPMAP_TEXTURE | |
| case 0x3083: // EGL_MIPMAP_LEVEL | |
| // This is a window surface, not a pbuffer surface. Spec: | |
| // "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." | |
| // So pass-through. | |
| return 1; | |
| default: | |
| EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */); | |
| return 0; | |
| } | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); | |
| eglQueryContext__proxy: 'sync', | |
| eglQueryContext: (display, context, attribute, value) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| //\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy. | |
| if (context != {{{ eglDefaultContext }}}) { | |
| EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */); | |
| return 0; | |
| } | |
| if (!value) { | |
| EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); | |
| return 0; | |
| } | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| switch (attribute) { | |
| case 0x3028: // EGL_CONFIG_ID | |
| {{{ makeSetValue('value', '0', eglDefaultConfig, 'i32') }}}; | |
| return 1; | |
| case 0x3097: // EGL_CONTEXT_CLIENT_TYPE | |
| {{{ makeSetValue('value', '0', '0x30A0' /* EGL_OPENGL_ES_API */, 'i32') }}}; | |
| return 1; | |
| case 0x3098: // EGL_CONTEXT_CLIENT_VERSION | |
| {{{ makeSetValue('value', '0', 'EGL.contextAttributes.majorVersion + 1', 'i32') }}}; | |
| return 1; | |
| case 0x3086: // EGL_RENDER_BUFFER | |
| // The context is bound to the visible canvas window - it's always backbuffered. | |
| // Alternative to EGL_BACK_BUFFER would be EGL_SINGLE_BUFFER. | |
| {{{ makeSetValue('value', '0', '0x3084' /* EGL_BACK_BUFFER */, 'i32') }}}; | |
| return 1; | |
| default: | |
| EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */); | |
| return 0; | |
| } | |
| }, | |
| // EGLAPI EGLint EGLAPIENTRY eglGetError(void); | |
| eglGetError__proxy: 'sync', | |
| eglGetError: () => EGL.errorCode, | |
| // EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name); | |
| // The allocated strings are cached and never freed. | |
| eglQueryString__noleakcheck: true, | |
| eglQueryString__deps: ['$stringToNewUTF8'], | |
| eglQueryString__proxy: 'sync', | |
| eglQueryString: (display, name) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| //\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy. | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| if (EGL.stringCache[name]) return EGL.stringCache[name]; | |
| var ret; | |
| switch (name) { | |
| case 0x3053 /* EGL_VENDOR */: ret = stringToNewUTF8("Emscripten"); break; | |
| case 0x3054 /* EGL_VERSION */: ret = stringToNewUTF8("1.4 Emscripten EGL"); break; | |
| case 0x3055 /* EGL_EXTENSIONS */: ret = stringToNewUTF8(""); break; // Currently not supporting any EGL extensions. | |
| case 0x308D /* EGL_CLIENT_APIS */: ret = stringToNewUTF8("OpenGL_ES"); break; | |
| default: | |
| EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); | |
| return 0; | |
| } | |
| EGL.stringCache[name] = ret; | |
| return ret; | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api); | |
| eglBindAPI__proxy: 'sync', | |
| eglBindAPI: (api) => { | |
| if (api == 0x30A0 /* EGL_OPENGL_ES_API */) { | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1; | |
| } | |
| // if (api == 0x30A1 /* EGL_OPENVG_API */ || api == 0x30A2 /* EGL_OPENGL_API */) { | |
| EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); | |
| return 0; | |
| }, | |
| // EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void); | |
| eglQueryAPI__proxy: 'sync', | |
| eglQueryAPI: () => { | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 0x30A0; // EGL_OPENGL_ES_API | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void); | |
| eglWaitClient__proxy: 'sync', | |
| eglWaitClient: () => { | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1; | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine); | |
| eglWaitNative__proxy: 'sync', | |
| eglWaitNative: (nativeEngineId) => { | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1; | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void); | |
| eglWaitGL: 'eglWaitClient', | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval); | |
| eglSwapInterval__deps: ['emscripten_set_main_loop_timing'], | |
| eglSwapInterval__proxy: 'sync', | |
| eglSwapInterval: (display, interval) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0; | |
| } | |
| if (interval == 0) _emscripten_set_main_loop_timing({{{ cDefs.EM_TIMING_SETTIMEOUT }}}, 0); | |
| else _emscripten_set_main_loop_timing({{{ cDefs.EM_TIMING_RAF }}}, interval); | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1; | |
| }, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); | |
| eglMakeCurrent__deps: ['$GL'], | |
| eglMakeCurrent__proxy: 'sync', | |
| eglMakeCurrent: (display, draw, read, context) => { | |
| if (display != {{{ eglDefaultDisplay }}}) { | |
| EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); | |
| return 0 /* EGL_FALSE */; | |
| } | |
| //\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy. | |
| if (context != 0 && context != {{{ eglDefaultContext }}}) { | |
| EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */); | |
| return 0; | |
| } | |
| if ((read != 0 && read != 62006) || (draw != 0 && draw != 62006 /* Magic ID for Emscripten 'default surface' */)) { | |
| EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */); | |
| return 0; | |
| } | |
| GL.makeContextCurrent(context ? EGL.context : null); | |
| EGL.currentContext = context; | |
| EGL.currentDrawSurface = draw; | |
| EGL.currentReadSurface = read; | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1 /* EGL_TRUE */; | |
| }, | |
| // EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void); | |
| eglGetCurrentContext__proxy: 'sync', | |
| eglGetCurrentContext: () => EGL.currentContext, | |
| // EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw); | |
| eglGetCurrentSurface__proxy: 'sync', | |
| eglGetCurrentSurface: (readdraw) => { | |
| if (readdraw == 0x305A /* EGL_READ */) { | |
| return EGL.currentReadSurface; | |
| } else if (readdraw == 0x3059 /* EGL_DRAW */) { | |
| return EGL.currentDrawSurface; | |
| } else { | |
| EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); | |
| return 0 /* EGL_NO_SURFACE */; | |
| } | |
| }, | |
| // EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void); | |
| eglGetCurrentDisplay__proxy: 'sync', | |
| eglGetCurrentDisplay: () => EGL.currentContext ? {{{ eglDefaultDisplay }}} : 0, | |
| // EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface); | |
| eglSwapBuffers__deps: ['$GLctx'], | |
| eglSwapBuffers__proxy: 'sync', | |
| eglSwapBuffers: (dpy, surface) => { | |
| if (!EGL.defaultDisplayInitialized) { | |
| EGL.setErrorCode(0x3001 /* EGL_NOT_INITIALIZED */); | |
| } else if (!GLctx) { | |
| EGL.setErrorCode(0x3002 /* EGL_BAD_ACCESS */); | |
| } else if (GLctx.isContextLost()) { | |
| EGL.setErrorCode(0x300E /* EGL_CONTEXT_LOST */); | |
| } else { | |
| // According to documentation this does an implicit flush. | |
| // Due to discussion at https://github.com/emscripten-core/emscripten/pull/1871 | |
| // the flush was removed since this _may_ result in slowing code down. | |
| //_glFlush(); | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1 /* EGL_TRUE */; | |
| } | |
| return 0 /* EGL_FALSE */; | |
| }, | |
| eglReleaseThread__proxy: 'sync', | |
| eglReleaseThread: () => { | |
| // Equivalent to eglMakeCurrent with EGL_NO_CONTEXT and EGL_NO_SURFACE. | |
| EGL.currentContext = 0; | |
| EGL.currentReadSurface = 0; | |
| EGL.currentDrawSurface = 0; | |
| // EGL spec v1.4 p.55: | |
| // "calling eglGetError immediately following a successful call to eglReleaseThread should not be done. | |
| // Such a call will return EGL_SUCCESS - but will also result in reallocating per-thread state." | |
| EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); | |
| return 1 /* EGL_TRUE */; | |
| } | |
| }; | |
| autoAddDeps(LibraryEGL, '$EGL'); | |
| addToLibrary(LibraryEGL); | |
Xet Storage Details
- Size:
- 27.8 kB
- Xet hash:
- e7eea22c2620206c03708438ae68497faeecfefaf9f620c77321d29a85d0fb2e
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.