diff --git a/SConstruct b/SConstruct index fea0e0ab285..f7d589e7998 100644 --- a/SConstruct +++ b/SConstruct @@ -16,7 +16,6 @@ from collections import OrderedDict import methods import glsl_builders import gles3_builders -from platform_methods import run_in_subprocess # Scan possible build platforms @@ -706,20 +705,14 @@ if selected_platform in platform_list: suffix="glsl.gen.h", src_suffix=".glsl", ), + "GLES3_GLSL": env.Builder( + action=env.Run(gles3_builders.build_gles3_headers, 'Building GLES3 GLSL header: "$TARGET"'), + suffix="glsl.gen.h", + src_suffix=".glsl", + ), } env.Append(BUILDERS=GLSL_BUILDERS) - if not env["platform"] == "server": - env.Append( - BUILDERS={ - "GLES3_GLSL": env.Builder( - action=run_in_subprocess(gles3_builders.build_gles3_headers), - suffix="glsl.gen.h", - src_suffix=".glsl", - ) - } - ) - scons_cache_path = os.environ.get("SCONS_CACHE") if scons_cache_path != None: CacheDir(scons_cache_path) diff --git a/core/os/os.h b/core/os/os.h index abfa7ac9930..3042696ccee 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -243,7 +243,7 @@ public: void set_stdout_enabled(bool p_enabled); void set_stderr_enabled(bool p_enabled); - bool is_single_window() const; + virtual bool is_single_window() const; virtual void disable_crash_handler() {} virtual bool is_disable_crash_handler() const { return false; } diff --git a/drivers/SCsub b/drivers/SCsub index 714d4110de3..dd81fc645c4 100644 --- a/drivers/SCsub +++ b/drivers/SCsub @@ -25,10 +25,9 @@ SConscript("winmidi/SCsub") # Graphics drivers if env["vulkan"]: SConscript("vulkan/SCsub") - SConscript("gles3/SCsub") +if env["opengl3"]: SConscript("gl_context/SCsub") -else: - SConscript("dummy/SCsub") + SConscript("gles3/SCsub") # Core dependencies SConscript("png/SCsub") diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 10093d42a3d..92c9dfb9ae6 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -68,7 +68,7 @@ #endif #endif -#ifndef IPHONE_ENABLED +#if !defined(IPHONE_ENABLED) && !defined(JAVASCRIPT_ENABLED) // We include EGL below to get debug callback on GLES2 platforms, // but EGL is not available on iOS. #define CAN_DEBUG diff --git a/misc/dist/html/editor.html b/misc/dist/html/editor.html index 69e267f665c..8b077a57253 100644 --- a/misc/dist/html/editor.html +++ b/misc/dist/html/editor.html @@ -281,8 +281,7 @@

@@ -562,8 +561,9 @@ const is_project_manager = args.filter(function(v) { return v == '--project-manager' }).length != 0; const is_game = !is_editor && !is_project_manager; if (video_driver) { - args.push('--video-driver', video_driver); + args.push('--rendering-driver', video_driver); } + if (is_game) { if (game) { console.error("A game is already running. Close it first"); @@ -651,9 +651,9 @@ selectVideoMode(); showTab('editor'); setLoaderEnabled(false); - const args = ['--project-manager']; + const args = ['--project-manager', '--single-window']; if (video_driver) { - args.push('--video-driver', video_driver); + args.push('--rendering-driver', video_driver); } editor.start({'args': args, 'persistentDrops': true}).then(function() { setStatusMode('hidden'); diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index 891ae419bd5..b57f3b3f16e 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -180,6 +180,13 @@ def configure(env): env.Prepend(CPPPATH=["#platform/javascript"]) env.Append(CPPDEFINES=["JAVASCRIPT_ENABLED", "UNIX_ENABLED"]) + if env["opengl3"]: + env.AppendUnique(CPPDEFINES=["GLES3_ENABLED"]) + # This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1. + env.Append(LINKFLAGS=["-s", "USE_WEBGL2=1"]) + # Allow use to take control of swapping WebGL buffers. + env.Append(LINKFLAGS=["-s", "OFFSCREEN_FRAMEBUFFER=1"]) + if env["javascript_eval"]: env.Append(CPPDEFINES=["JAVASCRIPT_EVAL_ENABLED"]) @@ -218,25 +225,11 @@ def configure(env): # us since we don't know requirements at compile-time. env.Append(LINKFLAGS=["-s", "ALLOW_MEMORY_GROWTH=1"]) - # This setting just makes WebGL 2 APIs available, it does NOT disable WebGL 1. - env.Append(LINKFLAGS=["-s", "USE_WEBGL2=1"]) - # Do not call main immediately when the support code is ready. env.Append(LINKFLAGS=["-s", "INVOKE_RUN=0"]) - # Allow use to take control of swapping WebGL buffers. - env.Append(LINKFLAGS=["-s", "OFFSCREEN_FRAMEBUFFER=1"]) - # callMain for manual start, cwrap for the mono version. env.Append(LINKFLAGS=["-s", "EXPORTED_RUNTIME_METHODS=['callMain','cwrap']"]) # Add code that allow exiting runtime. env.Append(LINKFLAGS=["-s", "EXIT_RUNTIME=1"]) - - # TODO remove once we have GLES support back (temporary fix undefined symbols due to dead code elimination). - env.Append( - LINKFLAGS=[ - "-s", - "EXPORTED_FUNCTIONS=['_main', '_emscripten_webgl_get_current_context']", - ] - ) diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index d12e1aeee8d..7648ddaf43e 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -30,6 +30,9 @@ #include "platform/javascript/display_server_javascript.h" +#ifdef GLES3_ENABLED +#include "drivers/gles3/rasterizer_gles3.h" +#endif #include "platform/javascript/os_javascript.h" #include "servers/rendering/rasterizer_dummy.h" @@ -50,14 +53,6 @@ DisplayServerJavaScript *DisplayServerJavaScript::get_singleton() { } // Window (canvas) -void DisplayServerJavaScript::focus_canvas() { - godot_js_display_canvas_focus(); -} - -bool DisplayServerJavaScript::is_canvas_focused() { - return godot_js_display_canvas_is_focused() != 0; -} - bool DisplayServerJavaScript::check_size_force_redraw() { return godot_js_display_size_update() != 0; } @@ -141,11 +136,12 @@ void DisplayServerJavaScript::key_callback(int p_pressed, int p_repeat, int p_mo int DisplayServerJavaScript::mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers) { DisplayServerJavaScript *ds = get_singleton(); + Point2 pos(p_x, p_y); + Input::get_singleton()->set_mouse_position(pos); Ref ev; ev.instantiate(); - ev->set_pressed(p_pressed); - ev->set_position(Point2(p_x, p_y)); - ev->set_global_position(ev->get_position()); + ev->set_position(pos); + ev->set_global_position(pos); ev->set_pressed(p_pressed); dom2godot_mod(ev, p_modifiers); @@ -222,13 +218,15 @@ void DisplayServerJavaScript::mouse_move_callback(double p_x, double p_y, double return; } + Point2 pos(p_x, p_y); + Input::get_singleton()->set_mouse_position(pos); Ref ev; ev.instantiate(); dom2godot_mod(ev, p_modifiers); ev->set_button_mask(input_mask); - ev->set_position(Point2(p_x, p_y)); - ev->set_global_position(ev->get_position()); + ev->set_position(pos); + ev->set_global_position(pos); ev->set_relative(Vector2(p_rel_x, p_rel_y)); Input::get_singleton()->set_mouse_position(ev->get_position()); @@ -397,6 +395,10 @@ DisplayServer::MouseMode DisplayServerJavaScript::mouse_get_mode() const { return MOUSE_MODE_VISIBLE; } +Point2i DisplayServerJavaScript::mouse_get_position() const { + return Input::get_singleton()->get_mouse_position(); +} + // Wheel int DisplayServerJavaScript::mouse_wheel_callback(double p_delta_x, double p_delta_y) { if (!godot_js_display_canvas_is_focused()) { @@ -580,7 +582,9 @@ void DisplayServerJavaScript::process_joypads() { Vector DisplayServerJavaScript::get_rendering_drivers_func() { Vector drivers; - drivers.push_back("dummy"); +#ifdef GLES3_ENABLED + drivers.push_back("opengl3"); +#endif return drivers; } @@ -678,40 +682,34 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive // Expose method for requesting quit. godot_js_os_request_quit_cb(request_quit_callback); - RasterizerDummy::make_current(); // TODO OpenGL in Godot 4.0... or webgpu? -#if 0 - EmscriptenWebGLContextAttributes attributes; - emscripten_webgl_init_context_attributes(&attributes); - attributes.alpha = GLOBAL_GET("display/window/per_pixel_transparency/allowed"); - attributes.antialias = false; - ERR_FAIL_INDEX_V(p_video_driver, VIDEO_DRIVER_MAX, ERR_INVALID_PARAMETER); +#ifdef GLES3_ENABLED + // TODO "vulkan" defaults to webgl2 for now. + bool wants_webgl2 = p_rendering_driver == "opengl3" || p_rendering_driver == "vulkan"; + bool webgl2_init_failed = wants_webgl2 && !godot_js_display_has_webgl(2); + if (wants_webgl2 && !webgl2_init_failed) { + EmscriptenWebGLContextAttributes attributes; + emscripten_webgl_init_context_attributes(&attributes); + //attributes.alpha = GLOBAL_GET("display/window/per_pixel_transparency/allowed"); + attributes.alpha = true; + attributes.antialias = false; + attributes.majorVersion = 2; - if (p_desired.layered) { - set_window_per_pixel_transparency_enabled(true); + webgl_ctx = emscripten_webgl_create_context(canvas_id, &attributes); + if (emscripten_webgl_make_context_current(webgl_ctx) != EMSCRIPTEN_RESULT_SUCCESS) { + webgl2_init_failed = true; + } else { + RasterizerGLES3::make_current(); + } } - - bool gl_initialization_error = false; - - if (RasterizerGLES3::is_viable() == OK) { - attributes.majorVersion = 1; - RasterizerGLES3::register_config(); - RasterizerGLES3::make_current(); - } else { - gl_initialization_error = true; - } - - EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(canvas_id, &attributes); - if (emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS) { - gl_initialization_error = true; - } - - if (gl_initialization_error) { - OS::get_singleton()->alert("Your browser does not seem to support WebGL. Please update your browser version.", + if (webgl2_init_failed) { + OS::get_singleton()->alert("Your browser does not seem to support WebGL2. Please update your browser version.", "Unable to initialize video driver"); - return ERR_UNAVAILABLE; } - - video_driver_index = p_video_driver; + if (!wants_webgl2 || webgl2_init_failed) { + RasterizerDummy::make_current(); + } +#else + RasterizerDummy::make_current(); #endif // JS Input interface (js/libs/library_godot_input.js) @@ -738,8 +736,12 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive } DisplayServerJavaScript::~DisplayServerJavaScript() { - //emscripten_webgl_commit_frame(); - //emscripten_webgl_destroy_context(webgl_ctx); +#ifdef GLES3_ENABLED + if (webgl_ctx) { + emscripten_webgl_commit_frame(); + emscripten_webgl_destroy_context(webgl_ctx); + } +#endif } bool DisplayServerJavaScript::has_feature(Feature p_feature) const { @@ -968,5 +970,9 @@ bool DisplayServerJavaScript::get_swap_cancel_ok() { } void DisplayServerJavaScript::swap_buffers() { - //emscripten_webgl_commit_frame(); +#ifdef GLES3_ENABLED + if (webgl_ctx) { + emscripten_webgl_commit_frame(); + } +#endif } diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h index 80ce772a790..843bb619842 100644 --- a/platform/javascript/display_server_javascript.h +++ b/platform/javascript/display_server_javascript.h @@ -51,6 +51,10 @@ private: }; JSKeyEvent key_event; +#ifdef GLES3_ENABLED + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE webgl_ctx = 0; +#endif + WindowMode window_mode = WINDOW_MODE_WINDOWED; ObjectID window_attached_instance_id = {}; @@ -72,8 +76,6 @@ private: bool swap_cancel_ok = false; // utilities - static void focus_canvas(); - static bool is_canvas_focused(); static void dom2godot_mod(Ref ev, int p_mod); static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape); @@ -121,6 +123,7 @@ public: // mouse virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual Point2i mouse_get_position() const override; // touch virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index aacf87e6c56..fbab95d33bd 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -90,6 +90,7 @@ public: String get_user_data_dir() const override; bool is_userfs_persistent() const override; + bool is_single_window() const override { return true; } void alert(const String &p_alert, const String &p_title = "ALERT!") override;