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
This commit is contained in:
Emil Ernerfeldt 2021-12-31 15:17:55 +01:00 committed by GitHub
parent 8da592c6ab
commit b1fd6a44e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 94 additions and 65 deletions

View File

@ -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 <https://github.com/emilk/egui/blob/master/egui_glium/examples/native_texture.rs>.

View File

@ -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

View File

@ -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.

View File

@ -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).

View File

@ -117,7 +117,7 @@ pub fn start_web(canvas_id: &str, app: Box<dyn epi::App>) -> 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<dyn epi::App>, 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();

View File

@ -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:

View File

@ -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"] }

View File

@ -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

View File

@ -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

View File

@ -5,11 +5,13 @@ pub use egui::{pos2, Color32};
// ----------------------------------------------------------------------------
fn create_painter(canvas_id: &str) -> Result<Box<dyn Painter>, 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<Box<dyn Painter>, 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!");
}
// ----------------------------------------------------------------------------

View File

@ -62,7 +62,7 @@ fn requires_brightening(canvas: &web_sys::HtmlCanvasElement) -> bool {
.dyn_into::<WebGlRenderingContext>()
.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::<web_sys::WebGl2RenderingContext>().unwrap();
glow::Context::from_webgl2_context(gl_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 gl2_ctx = canvas
.get_context("webgl2")
.expect("Failed to query about WebGL2 context");
let gl_ctx = ctx.dyn_into::<web_sys::WebGlRenderingContext>().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");
}
}
if let Some(gl2_ctx) = gl2_ctx {
crate::console_log("WebGL2 found");
let gl2_ctx = gl2_ctx
.dyn_into::<web_sys::WebGl2RenderingContext>()
.unwrap();
glow::Context::from_webgl2_context(gl2_ctx)
} else {
panic!("tried webgl2 but something went wrong");
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::<web_sys::WebGlRenderingContext>().unwrap();
glow::Context::from_webgl1_context(gl1_ctx)
} else {
panic!("Failed to get WebGL context.");
}
}
}

View File

@ -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<egui::Pos2>, 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
}

View File

@ -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<Item = &'a WebGlShader>>(
.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
}

View File

@ -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)