/**1* @license2* Copyright 2012 The Emscripten Authors3* SPDX-License-Identifier: MIT4*/56/*7* The EGL implementation supports only one EGLNativeDisplayType, the8* EGL_DEFAULT_DISPLAY. This native display type returns the only supported9* EGLDisplay handle with the magic value 62000. There is only a single10* EGLConfig configuration supported, that has the magic value 62002. The11* implementation only allows a single EGLContext to be created, that has the12* magic value of 62004. (multiple creations silently return this same context)13* The implementation only creates a single EGLSurface, a handle with the magic14* value of 62006. (multiple creations silently return the same surface)15*/1617{{{18// Magic ID for Emscripten 'default display'19const eglDefaultDisplay = 62000;20// Magic ID for the only EGLConfig supported by Emscripten21const eglDefaultConfig = 62002;22// Magic ID for Emscripten EGLContext23const eglDefaultContext = 62004;24}}}2526var LibraryEGL = {27$EGL__deps: ['$Browser'],28$EGL: {29// This variable tracks the success status of the most recently invoked EGL function call.30errorCode: 0x3000 /* EGL_SUCCESS */,31defaultDisplayInitialized: false,32currentContext: 0 /* EGL_NO_CONTEXT */,33currentReadSurface: 0 /* EGL_NO_SURFACE */,34currentDrawSurface: 0 /* EGL_NO_SURFACE */,3536contextAttributes: {37alpha: false,38depth: false,39stencil: false,40antialias: false41},4243stringCache: {},4445setErrorCode(code) {46EGL.errorCode = code;47},4849chooseConfig(display, attribList, config, config_size, numConfigs) {50if (display != {{{ eglDefaultDisplay }}}) {51EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);52return 0;53}5455if (attribList) {56// read attribList if it is non-null57for (;;) {58var param = {{{ makeGetValue('attribList', '0', 'i32') }}};59if (param == 0x3021 /*EGL_ALPHA_SIZE*/) {60var alphaSize = {{{ makeGetValue('attribList', '4', 'i32') }}};61EGL.contextAttributes.alpha = (alphaSize > 0);62} else if (param == 0x3025 /*EGL_DEPTH_SIZE*/) {63var depthSize = {{{ makeGetValue('attribList', '4', 'i32') }}};64EGL.contextAttributes.depth = (depthSize > 0);65} else if (param == 0x3026 /*EGL_STENCIL_SIZE*/) {66var stencilSize = {{{ makeGetValue('attribList', '4', 'i32') }}};67EGL.contextAttributes.stencil = (stencilSize > 0);68} else if (param == 0x3031 /*EGL_SAMPLES*/) {69var samples = {{{ makeGetValue('attribList', '4', 'i32') }}};70EGL.contextAttributes.antialias = (samples > 0);71} else if (param == 0x3032 /*EGL_SAMPLE_BUFFERS*/) {72var samples = {{{ makeGetValue('attribList', '4', 'i32') }}};73EGL.contextAttributes.antialias = (samples == 1);74} else if (param == 0x3100 /*EGL_CONTEXT_PRIORITY_LEVEL_IMG*/) {75var requestedPriority = {{{ makeGetValue('attribList', '4', 'i32') }}};76EGL.contextAttributes.lowLatency = (requestedPriority != 0x3103 /*EGL_CONTEXT_PRIORITY_LOW_IMG*/);77} else if (param == 0x3038 /*EGL_NONE*/) {78break;79}80attribList += 8;81}82}8384if ((!config || !config_size) && !numConfigs) {85EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);86return 0;87}88if (numConfigs) {89{{{ makeSetValue('numConfigs', '0', '1', 'i32') }}}; // Total number of supported configs: 1.90}91if (config && config_size > 0) {92{{{ makeSetValue('config', '0', eglDefaultConfig /* Magic ID for the only EGLConfig supported by Emscripten */, '*') }}};93}9495EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);96return 1;97},98},99100// EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id);101eglGetDisplay__proxy: 'sync',102eglGetDisplay: (nativeDisplayType) => {103EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);104// Emscripten EGL implementation "emulates" X11, and eglGetDisplay is105// expected to accept/receive a pointer to an X11 Display object (or106// EGL_DEFAULT_DISPLAY).107if (nativeDisplayType != 0 /* EGL_DEFAULT_DISPLAY */ && nativeDisplayType != 1 /* see library_xlib.js */) {108return 0; // EGL_NO_DISPLAY109}110return {{{ eglDefaultDisplay }}};111},112113// EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);114eglInitialize__proxy: 'sync',115eglInitialize: (display, majorVersion, minorVersion) => {116if (display != {{{ eglDefaultDisplay }}}) {117EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);118return 0;119}120if (majorVersion) {121{{{ makeSetValue('majorVersion', '0', '1', 'i32') }}}; // Advertise EGL Major version: '1'122}123if (minorVersion) {124{{{ makeSetValue('minorVersion', '0', '4', 'i32') }}}; // Advertise EGL Minor version: '4'125}126EGL.defaultDisplayInitialized = true;127EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);128return 1;129},130131// EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy);132eglTerminate__proxy: 'sync',133eglTerminate: (display) => {134if (display != {{{ eglDefaultDisplay }}}) {135EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);136return 0;137}138EGL.currentContext = 0;139EGL.currentReadSurface = 0;140EGL.currentDrawSurface = 0;141EGL.defaultDisplayInitialized = false;142EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);143return 1;144},145146// EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);147eglGetConfigs__proxy: 'sync',148eglGetConfigs: (display, configs, config_size, numConfigs) =>149EGL.chooseConfig(display, 0, configs, config_size, numConfigs),150151// EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);152eglChooseConfig__proxy: 'sync',153eglChooseConfig: (display, attrib_list, configs, config_size, numConfigs) =>154EGL.chooseConfig(display, attrib_list, configs, config_size, numConfigs),155156// EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);157eglGetConfigAttrib__proxy: 'sync',158eglGetConfigAttrib: (display, config, attribute, value) => {159if (display != {{{ eglDefaultDisplay }}}) {160EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);161return 0;162}163if (config != {{{ eglDefaultConfig }}}) {164EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */);165return 0;166}167if (!value) {168EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);169return 0;170}171EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);172switch (attribute) {173case 0x3020: // EGL_BUFFER_SIZE174{{{ makeSetValue('value', '0', 'EGL.contextAttributes.alpha ? 32 : 24' /* 8 bits for each R,G,B. 8 bits for alpha if enabled*/, 'i32') }}};175return 1;176case 0x3021: // EGL_ALPHA_SIZE177{{{ makeSetValue('value', '0', 'EGL.contextAttributes.alpha ? 8 : 0' /* 8 bits for alpha channel if enabled. */, 'i32') }}};178return 1;179case 0x3022: // EGL_BLUE_SIZE180{{{ makeSetValue('value', '0', '8' /* 8 bits for blue channel. */, 'i32') }}};181return 1;182case 0x3023: // EGL_GREEN_SIZE183{{{ makeSetValue('value', '0', '8' /* 8 bits for green channel. */, 'i32') }}};184return 1;185case 0x3024: // EGL_RED_SIZE186{{{ makeSetValue('value', '0', '8' /* 8 bits for red channel. */, 'i32') }}};187return 1;188case 0x3025: // EGL_DEPTH_SIZE189{{{ makeSetValue('value', '0', 'EGL.contextAttributes.depth ? 24 : 0' /* 24 bits for depth buffer if enabled. */, 'i32') }}};190return 1;191case 0x3026: // EGL_STENCIL_SIZE192{{{ makeSetValue('value', '0', 'EGL.contextAttributes.stencil ? 8 : 0' /* 8 bits for stencil buffer if enabled. */, 'i32') }}};193return 1;194case 0x3027: // EGL_CONFIG_CAVEAT195// We can return here one of EGL_NONE (0x3038), EGL_SLOW_CONFIG (0x3050) or EGL_NON_CONFORMANT_CONFIG (0x3051).196{{{ makeSetValue('value', '0', '0x3038' /* EGL_NONE */, 'i32') }}};197return 1;198case 0x3028: // EGL_CONFIG_ID199{{{ makeSetValue('value', '0', eglDefaultConfig, 'i32') }}};200return 1;201case 0x3029: // EGL_LEVEL202{{{ makeSetValue('value', '0', '0' /* Z order/depth layer for this level. Not applicable for Emscripten. */, 'i32') }}};203return 1;204case 0x302A: // EGL_MAX_PBUFFER_HEIGHT205{{{ makeSetValue('value', '0', '4096', 'i32') }}};206return 1;207case 0x302B: // EGL_MAX_PBUFFER_PIXELS208{{{ makeSetValue('value', '0', '16777216' /* 4096 * 4096 */, 'i32') }}};209return 1;210case 0x302C: // EGL_MAX_PBUFFER_WIDTH211{{{ makeSetValue('value', '0', '4096', 'i32') }}};212return 1;213case 0x302D: // EGL_NATIVE_RENDERABLE214{{{ makeSetValue('value', '0', '0' /* This config does not allow co-rendering with other 'native' rendering APIs. */, 'i32') }}};215return 1;216case 0x302E: // EGL_NATIVE_VISUAL_ID217{{{ makeSetValue('value', '0', '0' /* N/A for Emscripten. */, 'i32') }}};218return 1;219case 0x302F: // EGL_NATIVE_VISUAL_TYPE220{{{ makeSetValue('value', '0', '0x3038' /* EGL_NONE */, 'i32') }}};221return 1;222case 0x3031: // EGL_SAMPLES223{{{ makeSetValue('value', '0', 'EGL.contextAttributes.antialias ? 4 : 0' /* 2x2 Multisampling */, 'i32') }}};224return 1;225case 0x3032: // EGL_SAMPLE_BUFFERS226{{{ makeSetValue('value', '0', 'EGL.contextAttributes.antialias ? 1 : 0' /* Multisampling enabled */, 'i32') }}};227return 1;228case 0x3033: // EGL_SURFACE_TYPE229{{{ makeSetValue('value', '0', '0x4' /* EGL_WINDOW_BIT */, 'i32') }}};230return 1;231case 0x3034: // EGL_TRANSPARENT_TYPE232// If this returns EGL_TRANSPARENT_RGB (0x3052), transparency is used through color-keying. No such thing applies to Emscripten canvas.233{{{ makeSetValue('value', '0', '0x3038' /* EGL_NONE */, 'i32') }}};234return 1;235case 0x3035: // EGL_TRANSPARENT_BLUE_VALUE236case 0x3036: // EGL_TRANSPARENT_GREEN_VALUE237case 0x3037: // EGL_TRANSPARENT_RED_VALUE238// "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."239{{{ makeSetValue('value', '0', '-1' /* Report a "does not apply" value. */, 'i32') }}};240return 1;241case 0x3039: // EGL_BIND_TO_TEXTURE_RGB242case 0x303A: // EGL_BIND_TO_TEXTURE_RGBA243{{{ makeSetValue('value', '0', '0' /* Only pbuffers would be bindable, but these are not supported. */, 'i32') }}};244return 1;245case 0x303B: // EGL_MIN_SWAP_INTERVAL246{{{ makeSetValue('value', '0', '0', 'i32') }}};247return 1;248case 0x303C: // EGL_MAX_SWAP_INTERVAL249{{{ 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') }}};250return 1;251case 0x303D: // EGL_LUMINANCE_SIZE252case 0x303E: // EGL_ALPHA_MASK_SIZE253{{{ makeSetValue('value', '0', '0' /* N/A in this config. */, 'i32') }}};254return 1;255case 0x303F: // EGL_COLOR_BUFFER_TYPE256// EGL has two types of buffers: EGL_RGB_BUFFER and EGL_LUMINANCE_BUFFER.257{{{ makeSetValue('value', '0', '0x308E' /* EGL_RGB_BUFFER */, 'i32') }}};258return 1;259case 0x3040: // EGL_RENDERABLE_TYPE260// A bit combination of EGL_OPENGL_ES_BIT,EGL_OPENVG_BIT,EGL_OPENGL_ES2_BIT and EGL_OPENGL_BIT.261{{{ makeSetValue('value', '0', '0x4' /* EGL_OPENGL_ES2_BIT */, 'i32') }}};262return 1;263case 0x3042: // EGL_CONFORMANT264// "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."265{{{ makeSetValue('value', '0', '0' /* EGL_OPENGL_ES2_BIT */, 'i32') }}};266return 1;267default:268EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */);269return 0;270}271},272273// EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);274eglCreateWindowSurface__proxy: 'sync',275eglCreateWindowSurface: (display, config, win, attrib_list) => {276if (display != {{{ eglDefaultDisplay }}}) {277EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);278return 0;279}280if (config != {{{ eglDefaultConfig }}}) {281EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */);282return 0;283}284// TODO: Examine attrib_list! Parameters that can be present there are:285// - EGL_RENDER_BUFFER (must be EGL_BACK_BUFFER)286// - EGL_VG_COLORSPACE (can't be set)287// - EGL_VG_ALPHA_FORMAT (can't be set)288EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);289return 62006; /* Magic ID for Emscripten 'default surface' */290},291292// EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface);293eglDestroySurface__proxy: 'sync',294eglDestroySurface: (display, surface) => {295if (display != {{{ eglDefaultDisplay }}}) {296EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);297return 0;298}299if (surface != 62006 /* Magic ID for the only EGLSurface supported by Emscripten */) {300EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */);301return 1;302}303if (EGL.currentReadSurface == surface) {304EGL.currentReadSurface = 0;305}306if (EGL.currentDrawSurface == surface) {307EGL.currentDrawSurface = 0;308}309EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);310return 1; /* Magic ID for Emscripten 'default surface' */311},312313eglCreateContext__deps: ['$GL'],314315// EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);316eglCreateContext__proxy: 'sync',317eglCreateContext: (display, config, hmm, contextAttribs) => {318if (display != {{{ eglDefaultDisplay }}}) {319EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);320return 0;321}322323// EGL 1.4 spec says default EGL_CONTEXT_CLIENT_VERSION is GLES1, but this is not supported by Emscripten.324// So user must pass EGL_CONTEXT_CLIENT_VERSION == 2 to initialize EGL.325var glesContextVersion = 1;326for (;;) {327var param = {{{ makeGetValue('contextAttribs', '0', 'i32') }}};328if (param == 0x3098 /*EGL_CONTEXT_CLIENT_VERSION*/) {329glesContextVersion = {{{ makeGetValue('contextAttribs', '4', 'i32') }}};330} else if (param == 0x3038 /*EGL_NONE*/) {331break;332} else {333/* EGL1.4 specifies only EGL_CONTEXT_CLIENT_VERSION as supported attribute */334EGL.setErrorCode(0x3004 /*EGL_BAD_ATTRIBUTE*/);335return 0;336}337contextAttribs += 8;338}339#if MAX_WEBGL_VERSION >= 2340if (glesContextVersion < 2 || glesContextVersion > 3) {341#else342if (glesContextVersion != 2) {343#endif344#if GL_ASSERTIONS345if (glesContextVersion == 3) {346err('When initializing GLES3/WebGL2 via EGL, one must build with -sMAX_WEBGL_VERSION=2!');347} else {348err(`When initializing GLES2/WebGL1 via EGL, one must pass EGL_CONTEXT_CLIENT_VERSION = 2 to GL context attributes! GLES version ${glesContextVersion} is not supported!`);349}350#endif351EGL.setErrorCode(0x3005 /* EGL_BAD_CONFIG */);352return 0; /* EGL_NO_CONTEXT */353}354355EGL.contextAttributes.majorVersion = glesContextVersion - 1; // WebGL 1 is GLES 2, WebGL2 is GLES3356EGL.contextAttributes.minorVersion = 0;357358EGL.context = GL.createContext(Browser.getCanvas(), EGL.contextAttributes);359360if (EGL.context != 0) {361EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);362363// Run callbacks so that GL emulation works364GL.makeContextCurrent(EGL.context);365Browser.useWebGL = true;366Browser.moduleContextCreatedCallbacks.forEach((callback) => callback());367368// Note: This function only creates a context, but it shall not make it active.369GL.makeContextCurrent(null);370return {{{ eglDefaultContext }}};371} else {372EGL.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.373return 0; /* EGL_NO_CONTEXT */374}375},376377eglDestroyContext__deps: ['$GL'],378379// EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext context);380eglDestroyContext__proxy: 'sync',381eglDestroyContext: (display, context) => {382if (display != {{{ eglDefaultDisplay }}}) {383EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);384return 0;385}386if (context != {{{ eglDefaultContext }}}) {387EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */);388return 0;389}390391GL.deleteContext(EGL.context);392EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);393if (EGL.currentContext == context) {394EGL.currentContext = 0;395}396return 1 /* EGL_TRUE */;397},398399// EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);400eglQuerySurface__proxy: 'sync',401eglQuerySurface: (display, surface, attribute, value) => {402if (display != {{{ eglDefaultDisplay }}}) {403EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);404return 0;405}406if (surface != 62006 /* Magic ID for Emscripten 'default surface' */) {407EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */);408return 0;409}410if (!value) {411EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);412return 0;413}414EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);415switch (attribute) {416case 0x3028: // EGL_CONFIG_ID417{{{ makeSetValue('value', '0', eglDefaultConfig, 'i32') }}};418return 1;419case 0x3058: // EGL_LARGEST_PBUFFER420// 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.421// Existing Android implementation seems to do so at least.422return 1;423case 0x3057: // EGL_WIDTH424{{{ makeSetValue('value', '0', "Browser.getCanvas().width", 'i32') }}};425return 1;426case 0x3056: // EGL_HEIGHT427{{{ makeSetValue('value', '0', "Browser.getCanvas().height", 'i32') }}};428return 1;429case 0x3090: // EGL_HORIZONTAL_RESOLUTION430{{{ makeSetValue('value', '0', '-1' /* EGL_UNKNOWN */, 'i32') }}};431return 1;432case 0x3091: // EGL_VERTICAL_RESOLUTION433{{{ makeSetValue('value', '0', '-1' /* EGL_UNKNOWN */, 'i32') }}};434return 1;435case 0x3092: // EGL_PIXEL_ASPECT_RATIO436{{{ makeSetValue('value', '0', '-1' /* EGL_UNKNOWN */, 'i32') }}};437return 1;438case 0x3086: // EGL_RENDER_BUFFER439// The main surface is bound to the visible canvas window - it's always backbuffered.440// Alternative to EGL_BACK_BUFFER would be EGL_SINGLE_BUFFER.441{{{ makeSetValue('value', '0', '0x3084' /* EGL_BACK_BUFFER */, 'i32') }}};442return 1;443case 0x3099: // EGL_MULTISAMPLE_RESOLVE444{{{ makeSetValue('value', '0', '0x309A' /* EGL_MULTISAMPLE_RESOLVE_DEFAULT */, 'i32') }}};445return 1;446case 0x3093: // EGL_SWAP_BEHAVIOR447// The two possibilities are EGL_BUFFER_PRESERVED and EGL_BUFFER_DESTROYED. Slightly unsure which is the448// case for browser environment, but advertise the 'weaker' behavior to be sure.449{{{ makeSetValue('value', '0', '0x3095' /* EGL_BUFFER_DESTROYED */, 'i32') }}};450return 1;451case 0x3080: // EGL_TEXTURE_FORMAT452case 0x3081: // EGL_TEXTURE_TARGET453case 0x3082: // EGL_MIPMAP_TEXTURE454case 0x3083: // EGL_MIPMAP_LEVEL455// This is a window surface, not a pbuffer surface. Spec:456// "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."457// So pass-through.458return 1;459default:460EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */);461return 0;462}463},464465// EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);466eglQueryContext__proxy: 'sync',467eglQueryContext: (display, context, attribute, value) => {468if (display != {{{ eglDefaultDisplay }}}) {469EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);470return 0;471}472//\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy.473if (context != {{{ eglDefaultContext }}}) {474EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */);475return 0;476}477if (!value) {478EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);479return 0;480}481482EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);483switch (attribute) {484case 0x3028: // EGL_CONFIG_ID485{{{ makeSetValue('value', '0', eglDefaultConfig, 'i32') }}};486return 1;487case 0x3097: // EGL_CONTEXT_CLIENT_TYPE488{{{ makeSetValue('value', '0', '0x30A0' /* EGL_OPENGL_ES_API */, 'i32') }}};489return 1;490case 0x3098: // EGL_CONTEXT_CLIENT_VERSION491{{{ makeSetValue('value', '0', 'EGL.contextAttributes.majorVersion + 1', 'i32') }}};492return 1;493case 0x3086: // EGL_RENDER_BUFFER494// The context is bound to the visible canvas window - it's always backbuffered.495// Alternative to EGL_BACK_BUFFER would be EGL_SINGLE_BUFFER.496{{{ makeSetValue('value', '0', '0x3084' /* EGL_BACK_BUFFER */, 'i32') }}};497return 1;498default:499EGL.setErrorCode(0x3004 /* EGL_BAD_ATTRIBUTE */);500return 0;501}502},503504// EGLAPI EGLint EGLAPIENTRY eglGetError(void);505eglGetError__proxy: 'sync',506eglGetError: () => EGL.errorCode,507508// EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name);509// The allocated strings are cached and never freed.510eglQueryString__noleakcheck: true,511eglQueryString__deps: ['$stringToNewUTF8'],512eglQueryString__proxy: 'sync',513eglQueryString: (display, name) => {514if (display != {{{ eglDefaultDisplay }}}) {515EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);516return 0;517}518//\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy.519EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);520if (EGL.stringCache[name]) return EGL.stringCache[name];521var ret;522switch (name) {523case 0x3053 /* EGL_VENDOR */: ret = stringToNewUTF8("Emscripten"); break;524case 0x3054 /* EGL_VERSION */: ret = stringToNewUTF8("1.4 Emscripten EGL"); break;525case 0x3055 /* EGL_EXTENSIONS */: ret = stringToNewUTF8(""); break; // Currently not supporting any EGL extensions.526case 0x308D /* EGL_CLIENT_APIS */: ret = stringToNewUTF8("OpenGL_ES"); break;527default:528EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);529return 0;530}531EGL.stringCache[name] = ret;532return ret;533},534535// EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api);536eglBindAPI__proxy: 'sync',537eglBindAPI: (api) => {538if (api == 0x30A0 /* EGL_OPENGL_ES_API */) {539EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);540return 1;541}542// if (api == 0x30A1 /* EGL_OPENVG_API */ || api == 0x30A2 /* EGL_OPENGL_API */) {543EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);544return 0;545},546547// EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void);548eglQueryAPI__proxy: 'sync',549eglQueryAPI: () => {550EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);551return 0x30A0; // EGL_OPENGL_ES_API552},553554// EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void);555eglWaitClient__proxy: 'sync',556eglWaitClient: () => {557EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);558return 1;559},560561// EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine);562eglWaitNative__proxy: 'sync',563eglWaitNative: (nativeEngineId) => {564EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);565return 1;566},567568569// EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void);570eglWaitGL: 'eglWaitClient',571572// EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval);573eglSwapInterval__deps: ['emscripten_set_main_loop_timing'],574eglSwapInterval__proxy: 'sync',575eglSwapInterval: (display, interval) => {576if (display != {{{ eglDefaultDisplay }}}) {577EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);578return 0;579}580if (interval == 0) _emscripten_set_main_loop_timing({{{ cDefs.EM_TIMING_SETTIMEOUT }}}, 0);581else _emscripten_set_main_loop_timing({{{ cDefs.EM_TIMING_RAF }}}, interval);582583EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);584return 1;585},586587// EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);588eglMakeCurrent__deps: ['$GL'],589eglMakeCurrent__proxy: 'sync',590eglMakeCurrent: (display, draw, read, context) => {591if (display != {{{ eglDefaultDisplay }}}) {592EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);593return 0 /* EGL_FALSE */;594}595//\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy.596if (context != 0 && context != {{{ eglDefaultContext }}}) {597EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */);598return 0;599}600if ((read != 0 && read != 62006) || (draw != 0 && draw != 62006 /* Magic ID for Emscripten 'default surface' */)) {601EGL.setErrorCode(0x300D /* EGL_BAD_SURFACE */);602return 0;603}604605GL.makeContextCurrent(context ? EGL.context : null);606607EGL.currentContext = context;608EGL.currentDrawSurface = draw;609EGL.currentReadSurface = read;610EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);611return 1 /* EGL_TRUE */;612},613614// EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void);615eglGetCurrentContext__proxy: 'sync',616eglGetCurrentContext: () => EGL.currentContext,617618// EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw);619eglGetCurrentSurface__proxy: 'sync',620eglGetCurrentSurface: (readdraw) => {621if (readdraw == 0x305A /* EGL_READ */) {622return EGL.currentReadSurface;623} else if (readdraw == 0x3059 /* EGL_DRAW */) {624return EGL.currentDrawSurface;625} else {626EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);627return 0 /* EGL_NO_SURFACE */;628}629},630631// EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void);632eglGetCurrentDisplay__proxy: 'sync',633eglGetCurrentDisplay: () => EGL.currentContext ? {{{ eglDefaultDisplay }}} : 0,634635// EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);636eglSwapBuffers__deps: ['$GLctx'],637eglSwapBuffers__proxy: 'sync',638eglSwapBuffers: (dpy, surface) => {639#if PROXY_TO_WORKER640if (Browser.doSwapBuffers) Browser.doSwapBuffers();641#endif642643if (!EGL.defaultDisplayInitialized) {644EGL.setErrorCode(0x3001 /* EGL_NOT_INITIALIZED */);645} else if (!GLctx) {646EGL.setErrorCode(0x3002 /* EGL_BAD_ACCESS */);647} else if (GLctx.isContextLost()) {648EGL.setErrorCode(0x300E /* EGL_CONTEXT_LOST */);649} else {650// According to documentation this does an implicit flush.651// Due to discussion at https://github.com/emscripten-core/emscripten/pull/1871652// the flush was removed since this _may_ result in slowing code down.653//_glFlush();654EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);655return 1 /* EGL_TRUE */;656}657return 0 /* EGL_FALSE */;658},659660eglReleaseThread__proxy: 'sync',661eglReleaseThread: () => {662// Equivalent to eglMakeCurrent with EGL_NO_CONTEXT and EGL_NO_SURFACE.663EGL.currentContext = 0;664EGL.currentReadSurface = 0;665EGL.currentDrawSurface = 0;666// EGL spec v1.4 p.55:667// "calling eglGetError immediately following a successful call to eglReleaseThread should not be done.668// Such a call will return EGL_SUCCESS - but will also result in reallocating per-thread state."669EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);670return 1 /* EGL_TRUE */;671}672};673674autoAddDeps(LibraryEGL, '$EGL');675676addToLibrary(LibraryEGL);677678679