Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ iter_on_single_items = "warn"
iter_over_hash_type = "warn"
iter_without_into_iter = "warn"
large_digit_groups = "warn"
large_futures = "warn"
large_include_file = "warn"
large_stack_arrays = "warn"
large_stack_frames = "warn"
Expand Down Expand Up @@ -329,6 +330,7 @@ unnecessary_semicolon = "warn"
unnecessary_struct_initialization = "warn"
unnecessary_wraps = "warn"
unnested_or_patterns = "warn"
unused_async = "warn"
unused_peekable = "warn"
unused_rounding = "warn"
unused_self = "warn"
Expand Down
18 changes: 14 additions & 4 deletions crates/eframe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ workspace = true
default = [
"accesskit",
"default_fonts",
"glow",
"wayland", # Required for Linux support (including CI!)
"web_screen_reader",
"wgpu",
"winit/default",
"x11",
]
Expand All @@ -52,7 +52,11 @@ android-native-activity = ["egui-winit/android-native-activity"]
## If you plan on specifying your own fonts you may disable this feature.
default_fonts = ["egui/default_fonts"]

## Use [`glow`](https://github.com/grovesNL/glow) for painting, via [`egui_glow`](https://github.com/emilk/egui/tree/main/crates/egui_glow).
## Enable [`glow`](https://github.com/grovesNL/glow) for painting, via [`egui_glow`](https://github.com/emilk/egui/tree/main/crates/egui_glow).
##
## There is generally no need to enable both the `wgpu` and `glow` features,
## but if you do you can pick the renderer to use with [`NativeOptions::renderer`]
## and `WebOptions::renderer`.
glow = ["dep:egui_glow", "dep:glow", "dep:glutin-winit", "dep:glutin"]

## Enable saving app state to disk.
Expand All @@ -74,9 +78,15 @@ wayland = [
## For other platforms, use the `accesskit` feature instead.
web_screen_reader = ["web-sys/SpeechSynthesis", "web-sys/SpeechSynthesisUtterance"]

## Use [`wgpu`](https://docs.rs/wgpu) for painting (via [`egui-wgpu`](https://github.com/emilk/egui/tree/main/crates/egui-wgpu)).
## Enable [`wgpu`](https://docs.rs/wgpu) for painting (via [`egui-wgpu`](https://github.com/emilk/egui/tree/main/crates/egui-wgpu)).
##
## There is generally no need to enable both the `wgpu` and `glow` features,
## but if you do you can pick the renderer to use with [`NativeOptions::renderer`]
## and `WebOptions::renderer`.
##
## This overrides the `glow` feature.
## Switching from `wgpu (the default)` to `glow` can significantly reduce your binary size
## (including the .wasm of a web app).
## See <https://github.com/emilk/egui/issues/5889> for more details.
##
## By default, eframe will prefer WebGPU over WebGL, but
## you can configure this at run-time with [`NativeOptions::wgpu_options`].
Expand Down
11 changes: 9 additions & 2 deletions crates/eframe/src/epi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,10 @@ impl Default for NativeOptions {
/// Options when using `eframe` in a web page.
#[cfg(target_arch = "wasm32")]
pub struct WebOptions {
/// What rendering backend to use.
#[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))]
pub renderer: Renderer,

/// Sets the number of bits in the depth buffer.
///
/// `egui` doesn't need the depth buffer, so the default value is 0.
Expand Down Expand Up @@ -519,6 +523,9 @@ pub struct WebOptions {
impl Default for WebOptions {
fn default() -> Self {
Self {
#[cfg(any(feature = "glow", feature = "wgpu_no_default_features"))]
renderer: Renderer::default(),

depth_buffer: 0,

#[cfg(feature = "glow")]
Expand Down Expand Up @@ -592,8 +599,8 @@ impl Default for Renderer {
#[cfg(feature = "wgpu_no_default_features")]
return Self::Wgpu;

// By default, only the `glow` feature is enabled, so if the user added `wgpu` to the feature list
// they probably wanted to use wgpu:
// It's weird that the user has enabled both glow and wgpu,
// but let's pick the better of the two (wgpu):
#[cfg(feature = "glow")]
#[cfg(feature = "wgpu_no_default_features")]
return Self::Wgpu;
Expand Down
62 changes: 48 additions & 14 deletions crates/eframe/src/web/app_runner.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use egui::{TexturesDelta, UserData, ViewportCommand};

use crate::{App, epi};
use crate::{App, epi, web::web_painter::WebPainter};

use super::{NeedRepaint, now_sec, text_agent::TextAgent, web_painter::WebPainter as _};
use super::{NeedRepaint, now_sec, text_agent::TextAgent};

pub struct AppRunner {
#[allow(dead_code, clippy::allow_attributes)]
pub(crate) web_options: crate::WebOptions,
pub(crate) frame: epi::Frame,
egui_ctx: egui::Context,
painter: super::ActiveWebPainter,
painter: Box<dyn WebPainter>,
pub(crate) input: super::WebInput,
app: Box<dyn epi::App>,
pub(crate) needs_repaint: std::sync::Arc<NeedRepaint>,
Expand All @@ -34,14 +34,52 @@ impl Drop for AppRunner {
impl AppRunner {
/// # Errors
/// Failure to initialize WebGL renderer, or failure to create app.
#[cfg_attr(
not(feature = "wgpu_no_default_features"),
expect(clippy::unused_async)
)]
pub async fn new(
canvas: web_sys::HtmlCanvasElement,
web_options: crate::WebOptions,
app_creator: epi::AppCreator<'static>,
text_agent: TextAgent,
) -> Result<Self, String> {
let egui_ctx = egui::Context::default();
let painter = super::ActiveWebPainter::new(egui_ctx.clone(), canvas, &web_options).await?;

#[allow(clippy::allow_attributes, unused_assignments)]
#[cfg(feature = "glow")]
let mut gl = None;

#[allow(clippy::allow_attributes, unused_assignments)]
#[cfg(feature = "wgpu_no_default_features")]
let mut wgpu_render_state = None;

let painter = match web_options.renderer {
#[cfg(feature = "glow")]
epi::Renderer::Glow => {
log::debug!("Using the glow renderer");
let painter = super::web_painter_glow::WebPainterGlow::new(
egui_ctx.clone(),
canvas,
&web_options,
)?;
gl = Some(painter.gl().clone());
Box::new(painter) as Box<dyn WebPainter>
}

#[cfg(feature = "wgpu_no_default_features")]
epi::Renderer::Wgpu => {
log::debug!("Using the wgpu renderer");
let painter = super::web_painter_wgpu::WebPainterWgpu::new(
egui_ctx.clone(),
canvas,
&web_options,
)
.await?;
wgpu_render_state = painter.render_state();
Box::new(painter) as Box<dyn WebPainter>
}
};

let info = epi::IntegrationInfo {
web_info: epi::WebInfo {
Expand Down Expand Up @@ -79,15 +117,13 @@ impl AppRunner {
storage: Some(&storage),

#[cfg(feature = "glow")]
gl: Some(painter.gl().clone()),
gl: gl.clone(),

#[cfg(feature = "glow")]
get_proc_address: None,

#[cfg(all(feature = "wgpu_no_default_features", not(feature = "glow")))]
wgpu_render_state: painter.render_state(),
#[cfg(all(feature = "wgpu_no_default_features", feature = "glow"))]
wgpu_render_state: None,
#[cfg(feature = "wgpu_no_default_features")]
wgpu_render_state: wgpu_render_state.clone(),
};
let app = app_creator(&cc).map_err(|err| err.to_string())?;

Expand All @@ -96,12 +132,10 @@ impl AppRunner {
storage: Some(Box::new(storage)),

#[cfg(feature = "glow")]
gl: Some(painter.gl().clone()),
gl,

#[cfg(all(feature = "wgpu_no_default_features", not(feature = "glow")))]
wgpu_render_state: painter.render_state(),
#[cfg(all(feature = "wgpu_no_default_features", feature = "glow"))]
wgpu_render_state: None,
#[cfg(feature = "wgpu_no_default_features")]
wgpu_render_state,
};

let needs_repaint: std::sync::Arc<NeedRepaint> =
Expand Down
4 changes: 0 additions & 4 deletions crates/eframe/src/web/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,9 @@ mod web_painter;

#[cfg(feature = "glow")]
mod web_painter_glow;
#[cfg(feature = "glow")]
pub(crate) type ActiveWebPainter = web_painter_glow::WebPainterGlow;

#[cfg(feature = "wgpu_no_default_features")]
mod web_painter_wgpu;
#[cfg(all(feature = "wgpu_no_default_features", not(feature = "glow")))]
pub(crate) type ActiveWebPainter = web_painter_wgpu::WebPainterWgpu;

pub use backend::*;

Expand Down
2 changes: 1 addition & 1 deletion crates/eframe/src/web/web_painter_glow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl WebPainterGlow {
self.painter.gl()
}

pub async fn new(
pub fn new(
_ctx: egui::Context,
canvas: HtmlCanvasElement,
options: &WebOptions,
Expand Down
14 changes: 7 additions & 7 deletions crates/eframe/src/web/web_painter_wgpu.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use std::sync::Arc;

use super::web_painter::WebPainter;
use crate::WebOptions;
use egui::{Event, UserData, ViewportId};
use egui_wgpu::capture::{CaptureReceiver, CaptureSender, CaptureState, capture_channel};
use egui_wgpu::{RenderState, SurfaceErrorAction};
use egui_wgpu::{
RenderState, SurfaceErrorAction,
capture::{CaptureReceiver, CaptureSender, CaptureState, capture_channel},
};
use wasm_bindgen::JsValue;
use web_sys::HtmlCanvasElement;

use super::web_painter::WebPainter;

pub(crate) struct WebPainterWgpu {
canvas: HtmlCanvasElement,
surface: wgpu::Surface<'static>,
Expand All @@ -23,7 +25,6 @@ pub(crate) struct WebPainterWgpu {
}

impl WebPainterWgpu {
#[expect(unused)] // only used if `wgpu` is the only active feature.
pub fn render_state(&self) -> Option<RenderState> {
self.render_state.clone()
}
Expand Down Expand Up @@ -55,11 +56,10 @@ impl WebPainterWgpu {
})
}

#[expect(unused)] // only used if `wgpu` is the only active feature.
pub async fn new(
ctx: egui::Context,
canvas: web_sys::HtmlCanvasElement,
options: &WebOptions,
options: &crate::WebOptions,
) -> Result<Self, String> {
log::debug!("Creating wgpu painter");

Expand Down
2 changes: 1 addition & 1 deletion crates/egui_demo_app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ crate-type = ["cdylib", "rlib"]


[features]
default = ["glow", "persistence"]
default = ["wgpu", "persistence"]

# image_viewer adds about 0.9 MB of WASM
web_app = ["http", "persistence"]
Expand Down
18 changes: 8 additions & 10 deletions scripts/build_demo_web.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ OPEN=false
OPTIMIZE=false
BUILD=debug
BUILD_FLAGS=""
WGPU=false
GLOW=false
WASM_OPT_FLAGS="-O2 --fast-math"

while test $# -gt 0; do
case "$1" in
-h|--help)
echo "build_demo_web.sh [--release] [--wgpu] [--open]"
echo "build_demo_web.sh [--release] [--glow] [--open]"
echo ""
echo " -g: Keep debug symbols even with --release."
echo " These are useful profiling and size trimming."
Expand All @@ -29,9 +29,7 @@ while test $# -gt 0; do
echo " --release: Build with --release, and then run wasm-opt."
echo " NOTE: --release also removes debug symbols, unless you also use -g."
echo ""
echo " --wgpu: Build a binary using wgpu instead of glow/webgl."
echo " The resulting binary will automatically use WebGPU if available and"
echo " fall back to a WebGL emulation layer otherwise."
echo " --glow: Build a binary using glow instead of wgpu."
exit 0
;;

Expand All @@ -52,9 +50,9 @@ while test $# -gt 0; do
BUILD_FLAGS="--release"
;;

--wgpu)
--glow)
shift
WGPU=true
GLOW=true
;;

*)
Expand All @@ -66,10 +64,10 @@ done

OUT_FILE_NAME="egui_demo_app"

if [[ "${WGPU}" == true ]]; then
FEATURES="${FEATURES},wgpu"
else
if [[ "${GLOW}" == true ]]; then
FEATURES="${FEATURES},glow"
else
FEATURES="${FEATURES},wgpu"
fi

FINAL_WASM_PATH=web_demo/${OUT_FILE_NAME}_bg.wasm
Expand Down
Loading