From b1fd6a44e82c8cde7fab0b952851d2d2fd785349 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 31 Dec 2021 15:17:55 +0100 Subject: [PATCH] Switch to using glow as the default renderer both on native and the web (#1020) * Switch to using glow as the default renderer both on native and the web * Simplify code to find WebGL context for glow * egui_web: make webgl an opt-in feature * Stop using deprecated WEBGL_debug_renderer_info --- README.md | 4 +-- eframe/CHANGELOG.md | 2 ++ eframe/Cargo.toml | 4 +-- eframe/README.md | 4 +-- eframe/src/lib.rs | 21 ++++++++++++++-- egui/src/context.rs | 2 +- egui_demo_app/Cargo.toml | 4 ++- egui_web/CHANGELOG.md | 2 ++ egui_web/Cargo.toml | 9 +++++-- egui_web/src/backend.rs | 9 +++++-- egui_web/src/glow_wrapping.rs | 46 ++++++++++++++++------------------- egui_web/src/lib.rs | 23 ++++++++++++++++++ egui_web/src/webgl1.rs | 27 ++------------------ sh/check.sh | 2 +- 14 files changed, 94 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index a98c111a0dd..ab50bdd02e5 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ If you have questions, use [GitHub Discussions](https://github.com/emilk/egui/di To test the demo app locally, run `cargo run --release -p egui_demo_app`. -The native backend is [`egui_glium`](https://github.com/emilk/egui/tree/master/egui_glium) (using [`glium`](https://github.com/glium/glium)) and should work out-of-the-box on Mac and Windows, but on Linux you need to first run: +The native backend is [`egui_glow`](https://github.com/emilk/egui/tree/master/egui_glow) (using [`glow`](https://crates.io/crates/glow)) and should work out-of-the-box on Mac and Windows, but on Linux you need to first run: `sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libspeechd-dev libxkbcommon-dev libssl-dev` @@ -322,7 +322,7 @@ On Linux and Mac, Firefox will copy the WebGL render target from GPU, to CPU and To alleviate the above mentioned performance issues the default max-width of an egui web app is 1024 points. You can change this by overriding the `fn max_size_points` of [`epi::App`](https://docs.rs/epi/latest/epi/trait.App.html). ### How do I render 3D stuff in an egui area? -egui can't do 3D graphics itself, but if you use a 3D library (e.g. [`glium`](https://github.com/glium/glium) using [`egui_glium`](https://github.com/emilk/egui/tree/master/egui_glium), or [`miniquad`](https://github.com/not-fl3/miniquad) using [`egui-miniquad`](https://github.com/not-fl3/egui-miniquad)) you can render your 3D content to a texture, then display it using [`ui.image(…)`](https://docs.rs/egui/latest/egui/struct.Ui.html#method.image). You first need to convert the native texture to an [`egui::TextureId`](https://docs.rs/egui/latest/egui/enum.TextureId.html), and how to do this depends on the integration you use (e.g. [`register_glium_texture`](https://docs.rs/egui_glium/latest/egui_glium/struct.Painter.html#method.register_glium_texture)). +egui can't do 3D graphics itself, but if you use a 3D library (e.g. [`glium`](https://github.com/glium/glium) using [`egui_glium`](https://github.com/emilk/egui/tree/master/egui_glium), or [`miniquad`](https://github.com/not-fl3/miniquad) using [`egui-miniquad`](https://github.com/not-fl3/egui-miniquad)) you can render your 3D content to a texture, then display it using [`ui.image(…)`](https://docs.rs/egui/latest/egui/struct.Ui.html#method.image). You first need to convert the native texture to an [`egui::TextureId`](https://docs.rs/egui/latest/egui/enum.TextureId.html), and how to do this depends on the integration you use (e.g. [`register_glium_texture`](https://docs.rs/epi/latest/epi/trait.NativeTexture.html#tymethod.register_native_texture)). There is an example for showing a native glium texture in an egui window at . diff --git a/eframe/CHANGELOG.md b/eframe/CHANGELOG.md index 95bdd158f10..a648096558c 100644 --- a/eframe/CHANGELOG.md +++ b/eframe/CHANGELOG.md @@ -5,6 +5,8 @@ NOTE: [`egui_web`](egui_web/CHANGELOG.md), [`egui-winit`](egui-winit/CHANGELOG.m ## Unreleased +* The default native backend is now `egui_glow` (instead of `egui_glium`) ([#1020](https://github.com/emilk/egui/pull/1020)). +* The default web painter is now `egui_glow` (instead of WebGL) ([#1020](https://github.com/emilk/egui/pull/1020)). ## 0.16.0 - 2021-12-29 diff --git a/eframe/Cargo.toml b/eframe/Cargo.toml index 0d61fc36108..a01d380a239 100644 --- a/eframe/Cargo.toml +++ b/eframe/Cargo.toml @@ -35,14 +35,14 @@ egui_glow = { version = "0.16.0", path = "../egui_glow", default-features = fals # web: [target.'cfg(target_arch = "wasm32")'.dependencies] -egui_web = { version = "0.16.0", path = "../egui_web", default-features = false } +egui_web = { version = "0.16.0", path = "../egui_web", default-features = false, features = ["glow"] } [dev-dependencies] image = { version = "0.23", default-features = false, features = ["png"] } rfd = "0.6" [features] -default = ["default_fonts", "egui_glium"] +default = ["default_fonts", "egui_glow"] # If set, egui will use `include_bytes!` to bundle some fonts. # If you plan on specifying your own fonts you may disable this feature. diff --git a/eframe/README.md b/eframe/README.md index 0d8908a84de..9bdf221c855 100644 --- a/eframe/README.md +++ b/eframe/README.md @@ -28,10 +28,10 @@ sudo apt-get install libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev lib ## Alternatives -The default native backend for `eframe` is currently [`egui_glium`](https://github.com/emilk/egui/tree/master/egui_glium), but you can try out the new [`egui_glow`](https://github.com/emilk/egui/tree/master/egui_glow) backend by putting this in your `Cargo.toml`: +The default native backend for `eframe` is currently [`egui_glow`](https://github.com/emilk/egui/tree/master/egui_glow), but you can switch to the previous [`egui_glium`](https://github.com/emilk/egui/tree/master/egui_glium) backend by putting this in your `Cargo.toml`: ``` toml -eframe = { version = "*", default-features = false, features = ["default_fonts", "egui_glow"] } +eframe = { version = "*", default-features = false, features = ["default_fonts", "egui_glium"] } ``` `eframe` is not the only way to write an app using `egui`! You can also try [`egui-miniquad`](https://github.com/not-fl3/egui-miniquad) and [`egui_sdl2_gl`](https://github.com/ArjunNair/egui_sdl2_gl). diff --git a/eframe/src/lib.rs b/eframe/src/lib.rs index 8e12791c40d..2fff75192fb 100644 --- a/eframe/src/lib.rs +++ b/eframe/src/lib.rs @@ -117,7 +117,7 @@ pub fn start_web(canvas_id: &str, app: Box) -> Result<(), wasm_bin // ---------------------------------------------------------------------------- // When compiling natively -/// Call from `fn main` like this: ` +/// Call from `fn main` like this: /// ``` no_run /// use eframe::{epi, egui}; /// @@ -148,8 +148,25 @@ pub fn run_native(app: Box, native_options: epi::NativeOptions) -> egui_glium::run(app, &native_options) } -/// Call from `fn main` like this: ` +/// Call from `fn main` like this: /// ``` no_run +/// use eframe::{epi, egui}; +/// +/// #[derive(Default)] +/// struct MyEguiApp {} +/// +/// impl epi::App for MyEguiApp { +/// fn name(&self) -> &str { +/// "My egui App" +/// } +/// +/// fn update(&mut self, ctx: &egui::CtxRef, frame: &epi::Frame) { +/// egui::CentralPanel::default().show(ctx, |ui| { +/// ui.heading("Hello World!"); +/// }); +/// } +///} +/// /// fn main() { /// let app = MyEguiApp::default(); /// let native_options = eframe::NativeOptions::default(); diff --git a/egui/src/context.rs b/egui/src/context.rs index 27a454f8db1..9e28348db1c 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -100,7 +100,7 @@ impl CtxRef { /// This will modify the internal reference to point to a new generation of [`Context`]. /// Any old clones of this [`CtxRef`] will refer to the old [`Context`], which will not get new input. /// - /// You can alternatively run [`Self::begin_single_pass_frame`] and [`Self::end_single_pass_frame`]. + /// You can alternatively run [`Self::begin_frame`] and [`Self::end_frame`]. /// /// ``` rust /// // One egui context that you keep reusing: diff --git a/egui_demo_app/Cargo.toml b/egui_demo_app/Cargo.toml index d270e09621c..982faa5b6ba 100644 --- a/egui_demo_app/Cargo.toml +++ b/egui_demo_app/Cargo.toml @@ -12,7 +12,9 @@ crate-type = ["cdylib", "rlib"] [dependencies] eframe = { version = "0.16.0", path = "../eframe" } -# eframe = { version = "0.16.0", path = "../eframe", default-features = false, features = ["default_fonts", "egui_glow"] } + +# To use the old glium backend instead: +# eframe = { version = "0.16.0", path = "../eframe", default-features = false, features = ["default_fonts", "egui_glium"] } egui_demo_lib = { version = "0.16.0", path = "../egui_demo_lib", features = ["extra_debug_asserts"] } diff --git a/egui_web/CHANGELOG.md b/egui_web/CHANGELOG.md index 31f7a7568d5..68714197c8a 100644 --- a/egui_web/CHANGELOG.md +++ b/egui_web/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to the `egui_web` integration will be noted in this file. ## Unreleased +* The default painter is now glow instead of WebGL ([#1020](https://github.com/emilk/egui/pull/1020)). +* Made the WebGL painter opt-in ([#1020](https://github.com/emilk/egui/pull/1020)). ## 0.16.0 - 2021-12-29 diff --git a/egui_web/Cargo.toml b/egui_web/Cargo.toml index 057d8659e0b..ae60cf96da6 100644 --- a/egui_web/Cargo.toml +++ b/egui_web/Cargo.toml @@ -39,13 +39,18 @@ wasm-bindgen = "0.2" wasm-bindgen-futures = "0.4" [features] -default = ["default_fonts"] +default = ["default_fonts", "glow"] # If set, egui will use `include_bytes!` to bundle some fonts. # If you plan on specifying your own fonts you may disable this feature. default_fonts = ["egui/default_fonts"] -# Use glow as the renderer + +# Use glow as the renderer. glow = ["egui_glow", "egui_glow/epi"] + +# Alternative to the glow renderer. +webgl = [] + persistence = ["egui/persistence", "ron", "serde"] screen_reader = ["tts"] # experimental diff --git a/egui_web/src/backend.rs b/egui_web/src/backend.rs index 4ed7afbd8e2..259df51df12 100644 --- a/egui_web/src/backend.rs +++ b/egui_web/src/backend.rs @@ -5,11 +5,13 @@ pub use egui::{pos2, Color32}; // ---------------------------------------------------------------------------- fn create_painter(canvas_id: &str) -> Result, JsValue> { - #[cfg(feature = "glow")] + // Glow takes precedence: + #[cfg(all(feature = "glow"))] return Ok(Box::new(crate::glow_wrapping::WrappedGlowPainter::new( canvas_id, ))); - #[cfg(not(feature = "glow"))] + + #[cfg(all(feature = "webgl", not(feature = "glow")))] if let Ok(webgl2_painter) = webgl2::WebGl2Painter::new(canvas_id) { console_log("Using WebGL2 backend"); Ok(Box::new(webgl2_painter)) @@ -18,6 +20,9 @@ fn create_painter(canvas_id: &str) -> Result, JsValue> { let webgl1_painter = webgl1::WebGlPainter::new(canvas_id)?; Ok(Box::new(webgl1_painter)) } + + #[cfg(all(not(feature = "webgl"), not(feature = "glow")))] + compile_error!("Either the 'glow' or 'webgl' feature of egui_web must be enabled!"); } // ---------------------------------------------------------------------------- diff --git a/egui_web/src/glow_wrapping.rs b/egui_web/src/glow_wrapping.rs index c7d8426b6f4..ac2eba798e6 100644 --- a/egui_web/src/glow_wrapping.rs +++ b/egui_web/src/glow_wrapping.rs @@ -62,7 +62,7 @@ fn requires_brightening(canvas: &web_sys::HtmlCanvasElement) -> bool { .dyn_into::() .unwrap(); let user_agent = web_sys::window().unwrap().navigator().user_agent().unwrap(); - crate::webgl1::is_safari_and_webkit_gtk(&gl) && !user_agent.contains("Mac OS X") + crate::is_safari_and_webkit_gtk(&gl) && !user_agent.contains("Mac OS X") } impl crate::Painter for WrappedGlowPainter { @@ -116,32 +116,28 @@ impl crate::Painter for WrappedGlowPainter { } pub fn init_glow_context_from_canvas(canvas: &HtmlCanvasElement) -> glow::Context { - let ctx = canvas.get_context("webgl2"); - if let Ok(ctx) = ctx { - crate::console_log("webgl found"); - if let Some(ctx) = ctx { - crate::console_log("webgl 2 selected"); - let gl_ctx = ctx.dyn_into::().unwrap(); - glow::Context::from_webgl2_context(gl_ctx) + let gl2_ctx = canvas + .get_context("webgl2") + .expect("Failed to query about WebGL2 context"); + + if let Some(gl2_ctx) = gl2_ctx { + crate::console_log("WebGL2 found"); + let gl2_ctx = gl2_ctx + .dyn_into::() + .unwrap(); + glow::Context::from_webgl2_context(gl2_ctx) + } else { + let gl1 = canvas + .get_context("webgl") + .expect("Failed to query about WebGL1 context"); + + if let Some(gl1) = gl1 { + crate::console_log("WebGL2 not available - falling back to WebGL2"); + let gl1_ctx = gl1.dyn_into::().unwrap(); + glow::Context::from_webgl1_context(gl1_ctx) } else { - let ctx = canvas.get_context("webgl"); - if let Ok(ctx) = ctx { - crate::console_log("falling back to webgl1"); - if let Some(ctx) = ctx { - crate::console_log("webgl1 selected"); - - let gl_ctx = ctx.dyn_into::().unwrap(); - crate::console_log("success"); - glow::Context::from_webgl1_context(gl_ctx) - } else { - panic!("tried webgl1 but can't get context"); - } - } else { - panic!("tried webgl1 but can't get context"); - } + panic!("Failed to get WebGL context."); } - } else { - panic!("tried webgl2 but something went wrong"); } } diff --git a/egui_web/src/lib.rs b/egui_web/src/lib.rs index 6815ebb1a8c..36ea3f2472f 100644 --- a/egui_web/src/lib.rs +++ b/egui_web/src/lib.rs @@ -19,7 +19,10 @@ pub mod backend; mod glow_wrapping; mod painter; pub mod screen_reader; + +#[cfg(feature = "webgl")] pub mod webgl1; +#[cfg(feature = "webgl")] pub mod webgl2; pub use backend::*; @@ -1234,3 +1237,23 @@ fn move_text_cursor(cursor: &Option, canvas_id: &str) -> Option<()> style.set_property("left", "0px").ok() } } + +/// detecting Safari and webkitGTK. +/// +/// Safari and webkitGTK use unmasked renderer :Apple GPU +/// +/// If we detect safari or webkitGTK returns true. +/// +/// This function used to avoid displaying linear color with `sRGB` supported systems. +pub(crate) fn is_safari_and_webkit_gtk(gl: &web_sys::WebGlRenderingContext) -> bool { + if let Ok(renderer) = gl.get_parameter(web_sys::WebglDebugRendererInfo::UNMASKED_RENDERER_WEBGL) + { + if let Some(renderer) = renderer.as_string() { + if renderer.contains("Apple") { + return true; + } + } + } + + false +} diff --git a/egui_web/src/webgl1.rs b/egui_web/src/webgl1.rs index a1c4f8eb530..7b847c7c90a 100644 --- a/egui_web/src/webgl1.rs +++ b/egui_web/src/webgl1.rs @@ -5,7 +5,7 @@ use { wasm_bindgen::{prelude::*, JsCast}, web_sys::{ ExtSRgb, WebGlBuffer, WebGlFramebuffer, WebGlProgram, WebGlRenderingContext, WebGlShader, - WebGlTexture, WebglDebugRendererInfo, + WebGlTexture, }, }; @@ -479,7 +479,7 @@ fn requires_brightening(gl: &web_sys::WebGlRenderingContext) -> bool { // See https://github.com/emilk/egui/issues/794 let user_agent = web_sys::window().unwrap().navigator().user_agent().unwrap(); - crate::webgl1::is_safari_and_webkit_gtk(gl) && !user_agent.contains("Mac OS X") + crate::is_safari_and_webkit_gtk(gl) && !user_agent.contains("Mac OS X") } impl PostProcess { @@ -688,26 +688,3 @@ fn link_program<'a, T: IntoIterator>( .unwrap_or_else(|| "Unknown error creating program object".into())) } } - -/// detecting Safari and webkitGTK. -/// -/// Safari and webkitGTK use unmasked renderer :Apple GPU -/// -/// If we detect safari or webkitGTK returns true. -/// -/// This function used to avoid displaying linear color with `sRGB` supported systems. -pub(crate) fn is_safari_and_webkit_gtk(gl: &web_sys::WebGlRenderingContext) -> bool { - if gl - .get_extension("WEBGL_debug_renderer_info") - .unwrap() - .is_some() - { - let renderer: JsValue = gl - .get_parameter(WebglDebugRendererInfo::UNMASKED_RENDERER_WEBGL) - .unwrap(); - if renderer.as_string().unwrap().contains("Apple") { - return true; - } - } - false -} diff --git a/sh/check.sh b/sh/check.sh index f106330a042..a8225b6ca79 100755 --- a/sh/check.sh +++ b/sh/check.sh @@ -26,7 +26,7 @@ cargo doc -p egui_web --target wasm32-unknown-unknown --lib --no-deps --all-feat (cd egui && cargo check --no-default-features --features "multi_threaded,serialize") (cd eframe && cargo check --no-default-features --features "egui_glow") (cd epi && cargo check --no-default-features) -(cd egui_web && cargo check --no-default-features) +# (cd egui_web && cargo check --no-default-features) # we need to pick webgl or glow backend # (cd egui-winit && cargo check --no-default-features) # we don't pick singlethreaded or multithreaded (cd egui_glium && cargo check --no-default-features) (cd egui_glow && cargo check --no-default-features)