diff --git a/.github/workflows/build-emscripten.yml b/.github/workflows/build-emscripten.yml index c873b6cab84..698ea879627 100644 --- a/.github/workflows/build-emscripten.yml +++ b/.github/workflows/build-emscripten.yml @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Docker Step - run: "docker run -di --name emscripten -v $PWD:/src emscripten/emsdk:1.40.0 bash" + run: "docker run -di --name emscripten -v $PWD:/src emscripten/emsdk:3.1.21 bash" - name: Download libs run: ./scripts/$TARGET/download_libs.sh - name: Install dependencies diff --git a/addons/ofxEmscripten/libs/html5audio/lib/emscripten/library_html5audio.js b/addons/ofxEmscripten/libs/html5audio/lib/emscripten/library_html5audio.js index a984e36422e..b6b24108952 100644 --- a/addons/ofxEmscripten/libs/html5audio/lib/emscripten/library_html5audio.js +++ b/addons/ofxEmscripten/libs/html5audio/lib/emscripten/library_html5audio.js @@ -199,7 +199,7 @@ var LibraryHTML5Audio = { } } - dynCall('viiii',callback, [bufferSize,inputChannels,outputChannels,userData]); + {{{ makeDynCall('viiii', 'callback') }}}(bufferSize,inputChannels,outputChannels,userData); if(outputChannels>0){ for(c=0;c attribList = - { - EGL_RED_SIZE, EGL_DONT_CARE, - EGL_GREEN_SIZE, EGL_DONT_CARE, - EGL_BLUE_SIZE, EGL_DONT_CARE, - EGL_ALPHA_SIZE, EGL_DONT_CARE, - EGL_DEPTH_SIZE, EGL_DONT_CARE, - EGL_STENCIL_SIZE, EGL_DONT_CARE, - EGL_SAMPLE_BUFFERS, EGL_DONT_CARE, - EGL_NONE - }; + setWindowShape(settings.getWidth(),settings.getHeight()); + EmscriptenWebGLContextAttributes attrs; + emscripten_webgl_init_context_attributes(&attrs); + +/// when setting explicitSwapControl to 0 it is emscripten that is in charge of swapping on each render call. + attrs.explicitSwapControl = 0; + attrs.depth = 1; + attrs.stencil = 1; + attrs.antialias = 1; + attrs.majorVersion = 2; + attrs.minorVersion = 0; + attrs.alpha = 0; + + context = emscripten_webgl_create_context("#canvas", &attrs); + assert(context); + + makeCurrent(); + + _renderer = make_shared(this); + ((ofGLProgrammableRenderer*)_renderer.get())->setup(2,0); + + emscripten_set_keydown_callback("#canvas",this,1,&keydown_cb); + emscripten_set_keyup_callback("#canvas",this,1,&keyup_cb); - // We'll try these depth sizes in order ending with EGL_DONT_CARE if we don't get anything higher. - std::vector depthPreference = {24, 16, EGL_DONT_CARE}; - - // Find the index for the value EGL_DEPTH_SIZE uses, so we can try a few different values till we get a successful config. - int attribListDepthIndex = -1; - for(int i = 0; i < attribList.size(); i++){ - if( attribList[i] == EGL_DEPTH_SIZE ){ - attribListDepthIndex = i+1; - break; - } - } - - // Get Display - display = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY); - if ( display == EGL_NO_DISPLAY ){ - ofLogError() << "coudln't get display"; - return; - } - - // Initialize EGL - if ( !eglInitialize(display, &majorVersion, &minorVersion) ){ - ofLogError() << "couldn't initialize display"; - return; - } - - // Get configs - if ( !eglGetConfigs(display, NULL, 0, &numConfigs) ){ - ofLogError() << "couldn't get configs"; - return; - } - - // Choose the config based on our attribute list - // Try higher EGL_DEPTH_SIZE first - for(int i = 0; i < depthPreference.size(); i++){ - // Set EGL_DEPTH_SIZE - attribList[attribListDepthIndex] = depthPreference[i]; - - // Try out that depth value - if ( !eglChooseConfig(display, &attribList[0], &config, 1, &numConfigs) ){ - - // Finally fail like we did before if no preference works - if( depthPreference[i] == EGL_DONT_CARE ){ - ofLogError() << "couldn't choose display"; - return; - } - - }else{ - // Got a good configuration. Stop searching. - break; - } - } - - // Create a surface - surface = eglCreateWindowSurface(display, config, NULL, NULL); - if ( surface == EGL_NO_SURFACE ){ - ofLogError() << "couldn't create surface"; - return; - } - - // Create a GL context - context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs ); - if ( context == EGL_NO_CONTEXT ){ - ofLogError() << "couldn't create context"; - return; - } - - // Make the context current - if ( !eglMakeCurrent(display, surface, surface, context) ){ - ofLogError() << "couldn't make current display"; - return; - } - - setWindowShape(settings.getWidth(),settings.getHeight()); + emscripten_set_mousedown_callback("#canvas",this,1,&mousedown_cb); + emscripten_set_mouseup_callback("#canvas",this,1,&mouseup_cb); + emscripten_set_mousemove_callback("#canvas",this,1,&mousemoved_cb); + emscripten_set_mouseenter_callback("#canvas",this,1,&mouseenter_cb); + emscripten_set_mouseleave_callback("#canvas",this,1,&mouseleave_cb); - _renderer = make_shared(this); - ((ofGLProgrammableRenderer*)_renderer.get())->setup(2,0); + emscripten_set_touchstart_callback("#canvas",this,1,&touch_cb); + emscripten_set_touchend_callback("#canvas",this,1,&touch_cb); + emscripten_set_touchmove_callback("#canvas",this,1,&touch_cb); + emscripten_set_touchcancel_callback("#canvas",this,1,&touch_cb); - emscripten_set_keydown_callback(0,this,1,&keydown_cb); - emscripten_set_keyup_callback(0,this,1,&keyup_cb); - emscripten_set_mousedown_callback(0,this,1,&mousedown_cb); - emscripten_set_mouseup_callback(0,this,1,&mouseup_cb); - emscripten_set_mousemove_callback(0,this,1,&mousemoved_cb); - - emscripten_set_touchstart_callback(0,this,1,&touch_cb); - emscripten_set_touchend_callback(0,this,1,&touch_cb); - emscripten_set_touchmove_callback(0,this,1,&touch_cb); - emscripten_set_touchcancel_callback(0,this,1,&touch_cb); } void ofxAppEmscriptenWindow::loop(){ instance->events().notifySetup(); - // Emulate loop via callbacks - emscripten_set_main_loop( display_cb, -1, 1 ); + emscripten_set_main_loop( display_cb, -1, 1); } void ofxAppEmscriptenWindow::update(){ + if (bSetMainLoopTiming) { + emscripten_set_main_loop_timing(1, 2); + bSetMainLoopTiming = false; + } events().notifyUpdate(); } void ofxAppEmscriptenWindow::draw(){ - /////////////////////////////////////////////////////////////////////////////////////// // set viewport, clear the screen renderer()->startRender(); if( bEnableSetupScreen ) renderer()->setupScreen(); @@ -182,13 +87,6 @@ void ofxAppEmscriptenWindow::draw(){ events().notifyDraw(); renderer()->finishRender(); - - - EGLBoolean success = eglSwapBuffers( display, surface ); - if( !success ) { - EGLint error = eglGetError(); - ofLogNotice("of::emscripten::EGLPage") << "display(): eglSwapBuffers failed: " << eglErrorString(error); - } } void ofxAppEmscriptenWindow::display_cb(){ @@ -217,28 +115,62 @@ int ofxAppEmscriptenWindow::keyup_cb(int eventType, const EmscriptenKeyboardEven } int ofxAppEmscriptenWindow::mousedown_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData){ - instance->events().notifyMousePressed(ofGetMouseX(),ofGetMouseY(),mouseEvent->button); + int canvas_width, canvas_height; + emscripten_get_canvas_element_size("#canvas", &canvas_width, &canvas_height); + double css_width, css_height; + emscripten_get_element_css_size("#canvas", &css_width, &css_height); + instance->events().notifyMousePressed(mouseEvent->targetX * (canvas_width / css_width), mouseEvent->targetY * (canvas_height / css_height),mouseEvent->button); return 0; } int ofxAppEmscriptenWindow::mouseup_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData){ - instance->events().notifyMouseReleased(ofGetMouseX(),ofGetMouseY(),mouseEvent->button); + int canvas_width, canvas_height; + emscripten_get_canvas_element_size("#canvas", &canvas_width, &canvas_height); + double css_width, css_height; + emscripten_get_element_css_size("#canvas", &css_width, &css_height); + instance->events().notifyMouseReleased(mouseEvent->targetX * (canvas_width / css_width), mouseEvent->targetY * (canvas_height / css_height),0); return 0; - } int ofxAppEmscriptenWindow::mousemoved_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData){ + int canvas_width, canvas_height; + emscripten_get_canvas_element_size("#canvas", &canvas_width, &canvas_height); + double css_width, css_height; + emscripten_get_element_css_size("#canvas", &css_width, &css_height); if(ofGetMousePressed()){ - instance->events().notifyMouseDragged(mouseEvent->canvasX,mouseEvent->canvasY,0); + instance->events().notifyMouseDragged(mouseEvent->targetX * (canvas_width / css_width), mouseEvent->targetY * (canvas_height / css_height),0); }else{ - instance->events().notifyMouseMoved(mouseEvent->canvasX,mouseEvent->canvasY); + instance->events().notifyMouseMoved(mouseEvent->targetX * (canvas_width / css_width), mouseEvent->targetY * (canvas_height / css_height)); } return 0; +} +int ofxAppEmscriptenWindow::mouseenter_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData){ + int canvas_width, canvas_height; + emscripten_get_canvas_element_size("#canvas", &canvas_width, &canvas_height); + double css_width, css_height; + emscripten_get_element_css_size("#canvas", &css_width, &css_height); + instance->events().notifyMouseEntered(mouseEvent->targetX * (canvas_width / css_width), mouseEvent->targetY * (canvas_height / css_height)); + if(mouseEvent->buttons == 0){ + instance->events().notifyMouseReleased(mouseEvent->targetX * (canvas_width / css_width), mouseEvent->targetY * (canvas_height / css_height), mouseEvent->button); + } + return 0; } -int ofxAppEmscriptenWindow::touch_cb(int eventType, const EmscriptenTouchEvent* e, void* userData) { +int ofxAppEmscriptenWindow::mouseleave_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData){ + int canvas_width, canvas_height; + emscripten_get_canvas_element_size("#canvas", &canvas_width, &canvas_height); + double css_width, css_height; + emscripten_get_element_css_size("#canvas", &css_width, &css_height); + instance->events().notifyMouseExited(mouseEvent->targetX * (canvas_width / css_width), mouseEvent->targetY * (canvas_height / css_height)); + return 0; +} +int ofxAppEmscriptenWindow::touch_cb(int eventType, const EmscriptenTouchEvent* e, void* userData) { + int canvas_width, canvas_height; + emscripten_get_canvas_element_size("#canvas", &canvas_width, &canvas_height); + double css_width, css_height; + emscripten_get_element_css_size("#canvas", &css_width, &css_height); ofTouchEventArgs::Type touchArgsType; switch (eventType) { case EMSCRIPTEN_EVENT_TOUCHSTART: @@ -261,8 +193,8 @@ int ofxAppEmscriptenWindow::touch_cb(int eventType, const EmscriptenTouchEvent* ofTouchEventArgs touchArgs; touchArgs.type = touchArgsType; touchArgs.id = i; - touchArgs.x = e->touches[i].canvasX; - touchArgs.y = e->touches[i].canvasY; + touchArgs.x = std::ceil(e->touches[i].targetX * (canvas_width / css_width)); + touchArgs.y = std::ceil(e->touches[i].targetY* (canvas_height / css_height)); instance->events().notifyTouchEvent(touchArgs); } return 0; @@ -272,30 +204,18 @@ void ofxAppEmscriptenWindow::hideCursor(){ emscripten_hide_mouse(); } - -void ofxAppEmscriptenWindow::showCursor(){ - -} - -void ofxAppEmscriptenWindow::setWindowPosition(int x, int y){ - -} - void ofxAppEmscriptenWindow::setWindowShape(int w, int h){ - emscripten_set_canvas_element_size(NULL,w,h); + emscripten_set_canvas_size(w,h); } - - glm::vec2 ofxAppEmscriptenWindow::getWindowPosition(){ return glm::vec2(0,0); } - glm::vec2 ofxAppEmscriptenWindow::getWindowSize(){ int width; int height; - emscripten_get_canvas_element_size(NULL, &width, &height); + emscripten_get_canvas_element_size("#canvas", &width, &height); return glm::vec2(width,height); } @@ -303,10 +223,6 @@ glm::vec2 ofxAppEmscriptenWindow::getScreenSize(){ return getWindowSize(); } -void ofxAppEmscriptenWindow::setOrientation(ofOrientation orientation){ - -} - ofOrientation ofxAppEmscriptenWindow::getOrientation(){ return OF_ORIENTATION_DEFAULT; } @@ -324,10 +240,6 @@ int ofxAppEmscriptenWindow::getHeight(){ return getWindowSize().y; } -void ofxAppEmscriptenWindow::setWindowTitle(string title){ - -} - ofWindowMode ofxAppEmscriptenWindow::getWindowMode(){ return OF_WINDOW; } @@ -359,27 +271,26 @@ void ofxAppEmscriptenWindow::disableSetupScreen(){ bEnableSetupScreen = false; } -void ofxAppEmscriptenWindow::setVerticalSync(bool enabled){ - eglSwapInterval(display, enabled ? 1 : 0); -} -EGLDisplay ofxAppEmscriptenWindow::getEGLDisplay(){ - return display; +ofCoreEvents & ofxAppEmscriptenWindow::events(){ + return _events; } - -EGLContext ofxAppEmscriptenWindow::getEGLContext(){ - return context; +shared_ptr & ofxAppEmscriptenWindow::renderer(){ + return _renderer; } -EGLSurface ofxAppEmscriptenWindow::getEGLSurface(){ - return surface; +void ofxAppEmscriptenWindow::makeCurrent(){ + if(context != 0){ + emscripten_webgl_make_context_current(context); + } } -ofCoreEvents & ofxAppEmscriptenWindow::events(){ - return _events; +void ofxAppEmscriptenWindow::startRender(){ + renderer()->startRender(); } -shared_ptr & ofxAppEmscriptenWindow::renderer(){ - return _renderer; +void ofxAppEmscriptenWindow::finishRender(){ + renderer()->finishRender(); } + diff --git a/addons/ofxEmscripten/src/ofxAppEmscriptenWindow.h b/addons/ofxEmscripten/src/ofxAppEmscriptenWindow.h index 0443d80ac18..d2b1c538d05 100644 --- a/addons/ofxEmscripten/src/ofxAppEmscriptenWindow.h +++ b/addons/ofxEmscripten/src/ofxAppEmscriptenWindow.h @@ -14,6 +14,7 @@ #include "EGL/egl.h" #include #include +#include // For Emscripten WebGL API headers (see also webgl/webgl1_ext.h and webgl/webgl2.h) class ofxAppEmscriptenWindow: public ofAppBaseGLESWindow { public: @@ -30,16 +31,16 @@ class ofxAppEmscriptenWindow: public ofAppBaseGLESWindow { void setup(const ofGLESWindowSettings & settings); void hideCursor(); - void showCursor(); + // void showCursor(); - void setWindowPosition(int x, int y); + // void setWindowPosition(int x, int y); void setWindowShape(int w, int h); glm::vec2 getWindowPosition(); glm::vec2 getWindowSize(); glm::vec2 getScreenSize(); - void setOrientation(ofOrientation orientation); + ofOrientation getOrientation(); bool doesHWOrientation(); @@ -47,7 +48,7 @@ class ofxAppEmscriptenWindow: public ofAppBaseGLESWindow { int getWidth(); int getHeight(); - void setWindowTitle(std::string title); + ofWindowMode getWindowMode(); @@ -57,33 +58,50 @@ class ofxAppEmscriptenWindow: public ofAppBaseGLESWindow { void enableSetupScreen(); void disableSetupScreen(); - void setVerticalSync(bool enabled); + void setVerticalSync(bool enabled){} - EGLDisplay getEGLDisplay(); - EGLContext getEGLContext(); - EGLSurface getEGLSurface(); ofCoreEvents & events(); std::shared_ptr & renderer(); + + void update(); + void draw(); + + virtual void makeCurrent(); + virtual void startRender(); + virtual void finishRender(); + + + bool bIsSetup = false; private: + static ofxAppEmscriptenWindow * instance; + + + // static int getUniqueId(); static void display_cb(); static int keydown_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData); static int keyup_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData); + static int mousedown_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); static int mouseup_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); static int mousemoved_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); - static int touch_cb(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData); - void update(); - void draw(); - EGLDisplay display; - EGLContext context; - EGLSurface surface; - static ofxAppEmscriptenWindow * instance; - bool bEnableSetupScreen; + static int mouseenter_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); + static int mouseleave_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); + + static int touch_cb(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData); + + int id; + + + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = 0; + + bool bSetMainLoopTiming = true; + bool bEnableSetupScreen = true; ofCoreEvents _events; std::shared_ptr _renderer; }; #endif /* OFAPPEMSCRIPTENWINDOW_H_ */ + diff --git a/libs/openFrameworksCompiled/project/emscripten/config.emscripten.default.mk b/libs/openFrameworksCompiled/project/emscripten/config.emscripten.default.mk index 0f3d1ef316a..779264bf0a8 100644 --- a/libs/openFrameworksCompiled/project/emscripten/config.emscripten.default.mk +++ b/libs/openFrameworksCompiled/project/emscripten/config.emscripten.default.mk @@ -64,8 +64,8 @@ PLATFORM_REQUIRED_ADDONS = ofxEmscripten ################################################################################ # Code Generation Option Flags (http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html) -PLATFORM_CFLAGS = -Wall -std=c++17 -Wno-warn-absolute-paths - +PLATFORM_CFLAGS = +PLATFORM_CXXFLAGS = -Wall -std=c++17 -Wno-warn-absolute-paths ################################################################################ # PLATFORM LDFLAGS @@ -81,6 +81,9 @@ else PLATFORM_EMSCRIPTEN_TOTAL_MEMORY=134217728 endif +CUR_CC = $(CC) +CC := $(CUR_CC) -r + ifdef USE_CCACHE ifeq ($(findstring ccache, $(CC)),) ORIGINAL_CC = $(CC) @@ -90,7 +93,7 @@ ifdef USE_CCACHE endif endif -PLATFORM_LDFLAGS = -Wl --gc-sections --preload-file bin/data@data --emrun -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=0 +PLATFORM_LDFLAGS = -Wl --gc-sections --preload-file bin/data@data --emrun --bind --profiling-funcs -s USE_FREETYPE=1 PLATFORM_LDFLAGS += --js-library $(OF_ADDONS_PATH)/ofxEmscripten/libs/html5video/lib/emscripten/library_html5video.js PLATFORM_LDFLAGS += --js-library $(OF_ADDONS_PATH)/ofxEmscripten/libs/html5audio/lib/emscripten/library_html5audio.js @@ -164,13 +167,12 @@ PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/openFrameworks/graphics/ofCairoRende PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/openFrameworks/gl/ofGLRenderer.cpp PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/openFrameworks/utils/ofThread.cpp PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/openFrameworks/utils/ofThreadChannel.cpp - # third party PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/glew/% PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/boost/include/boost/% PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/videoInput/% -PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/assimp/% PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/fmod/% +PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/freetype/lib/% ################################################################################ # PLATFORM HEADER SEARCH PATHS diff --git a/libs/openFrameworksCompiled/project/emscripten/template.html b/libs/openFrameworksCompiled/project/emscripten/template.html index 7b09ee508ef..d6debad1ff7 100644 --- a/libs/openFrameworksCompiled/project/emscripten/template.html +++ b/libs/openFrameworksCompiled/project/emscripten/template.html @@ -117,8 +117,8 @@ Resize canvas - Lock/hide mouse pointer     - Lock/hide mouse pointer     + @@ -129,7 +129,7 @@
- +
@@ -181,7 +181,7 @@ if (text === Module.setStatus.text) return; var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/); var now = Date.now(); - if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon + if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon if (m) { text = m[1]; progressElement.value = parseInt(m[2])*100;