Browse Source

Merge pull request #54500 from Faless/js/4.x_webgl

Rémi Verschelde 3 years ago
parent
commit
c6d2768a19

+ 5 - 12
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)

+ 1 - 1
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; }

+ 2 - 3
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")

+ 1 - 1
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

+ 5 - 5
misc/dist/html/editor.html

@@ -281,8 +281,7 @@
 				<label for="videoMode" style="margin-right: 1rem">Video driver:</label>
 				<select id="videoMode">
 					<option value="" selected="selected">Auto</option>
-					<option value="GLES2">WebGL</option>
-					<option value="GLES3">WebGL 2</option>
+					<option value="opengl3">WebGL 2</option>
 				</select>
 				<br />
 				<br />
@@ -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');

+ 7 - 14
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']",
-        ]
-    )

+ 54 - 48
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<InputEventMouseButton> 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<InputEventMouseMotion> 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<String> DisplayServerJavaScript::get_rendering_drivers_func() {
 	Vector<String> 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);
-
-	if (p_desired.layered) {
-		set_window_per_pixel_transparency_enabled(true);
-	}
-
-	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;
+#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;
+
+		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();
+		}
 	}
-
-	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
 }

+ 5 - 2
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<InputEventWithModifiers> 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;

+ 1 - 0
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;