2022-01-15 12:59:52 +00:00
|
|
|
use egui::{ClippedMesh, Rgba};
|
2021-11-03 18:17:07 +00:00
|
|
|
use egui_glow::glow;
|
2021-11-13 11:32:01 +00:00
|
|
|
use wasm_bindgen::JsCast;
|
2021-11-03 18:17:07 +00:00
|
|
|
use wasm_bindgen::JsValue;
|
|
|
|
use web_sys::HtmlCanvasElement;
|
2021-12-26 20:21:28 +00:00
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2022-01-10 22:19:30 +00:00
|
|
|
use web_sys::{WebGl2RenderingContext, WebGlRenderingContext};
|
2021-11-03 18:17:07 +00:00
|
|
|
|
|
|
|
pub(crate) struct WrappedGlowPainter {
|
2022-01-10 22:19:30 +00:00
|
|
|
pub(crate) glow_ctx: glow::Context,
|
2021-11-03 18:17:07 +00:00
|
|
|
pub(crate) canvas: HtmlCanvasElement,
|
|
|
|
pub(crate) canvas_id: String,
|
|
|
|
pub(crate) painter: egui_glow::Painter,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl WrappedGlowPainter {
|
2022-01-31 18:15:48 +00:00
|
|
|
pub fn new(canvas_id: &str) -> Result<Self, String> {
|
|
|
|
let canvas = crate::canvas_element_or_die(canvas_id);
|
2021-11-13 11:55:48 +00:00
|
|
|
|
2022-01-31 18:15:48 +00:00
|
|
|
let (glow_ctx, shader_prefix) = init_glow_context_from_canvas(&canvas)?;
|
2021-11-13 11:32:01 +00:00
|
|
|
|
2021-11-03 18:17:07 +00:00
|
|
|
let dimension = [canvas.width() as i32, canvas.height() as i32];
|
2022-01-10 22:19:30 +00:00
|
|
|
let painter = egui_glow::Painter::new(&glow_ctx, Some(dimension), shader_prefix)
|
2022-01-31 18:15:48 +00:00
|
|
|
.map_err(|error| format!("Error starting glow painter: {}", error))?;
|
|
|
|
|
|
|
|
Ok(Self {
|
2022-01-10 22:19:30 +00:00
|
|
|
glow_ctx,
|
2021-11-03 18:17:07 +00:00
|
|
|
canvas,
|
|
|
|
canvas_id: canvas_id.to_owned(),
|
|
|
|
painter,
|
2022-01-31 18:15:48 +00:00
|
|
|
})
|
2021-11-03 18:17:07 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-13 11:55:48 +00:00
|
|
|
|
2022-03-11 18:15:06 +00:00
|
|
|
impl crate::WebPainter for WrappedGlowPainter {
|
|
|
|
fn name(&self) -> &'static str {
|
|
|
|
"egui_web"
|
|
|
|
}
|
|
|
|
|
2022-01-24 13:32:36 +00:00
|
|
|
fn max_texture_side(&self) -> usize {
|
|
|
|
self.painter.max_texture_side()
|
|
|
|
}
|
|
|
|
|
2022-03-11 18:15:06 +00:00
|
|
|
fn canvas_id(&self) -> &str {
|
|
|
|
&self.canvas_id
|
|
|
|
}
|
|
|
|
|
2022-01-22 10:23:12 +00:00
|
|
|
fn set_texture(&mut self, tex_id: egui::TextureId, delta: &egui::epaint::ImageDelta) {
|
|
|
|
self.painter.set_texture(&self.glow_ctx, tex_id, delta);
|
2021-12-26 20:21:28 +00:00
|
|
|
}
|
|
|
|
|
2022-01-15 12:59:52 +00:00
|
|
|
fn free_texture(&mut self, tex_id: egui::TextureId) {
|
|
|
|
self.painter.free_texture(&self.glow_ctx, tex_id);
|
2021-11-03 18:17:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn clear(&mut self, clear_color: Rgba) {
|
|
|
|
let canvas_dimension = [self.canvas.width(), self.canvas.height()];
|
2022-01-10 22:19:30 +00:00
|
|
|
egui_glow::painter::clear(&self.glow_ctx, canvas_dimension, clear_color)
|
2021-11-03 18:17:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn paint_meshes(
|
|
|
|
&mut self,
|
|
|
|
clipped_meshes: Vec<ClippedMesh>,
|
|
|
|
pixels_per_point: f32,
|
|
|
|
) -> Result<(), JsValue> {
|
|
|
|
let canvas_dimension = [self.canvas.width(), self.canvas.height()];
|
|
|
|
self.painter.paint_meshes(
|
2022-01-10 22:19:30 +00:00
|
|
|
&self.glow_ctx,
|
2021-12-26 20:21:28 +00:00
|
|
|
canvas_dimension,
|
2021-11-03 18:17:07 +00:00
|
|
|
pixels_per_point,
|
|
|
|
clipped_meshes,
|
|
|
|
);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-10 22:19:30 +00:00
|
|
|
/// Returns glow context and shader prefix.
|
2022-01-31 18:15:48 +00:00
|
|
|
fn init_glow_context_from_canvas(
|
|
|
|
canvas: &HtmlCanvasElement,
|
|
|
|
) -> Result<(glow::Context, &'static str), String> {
|
2022-01-22 07:59:06 +00:00
|
|
|
const BEST_FIRST: bool = true;
|
|
|
|
|
|
|
|
let result = if BEST_FIRST {
|
|
|
|
// Trying WebGl2 first
|
|
|
|
init_webgl2(canvas).or_else(|| init_webgl1(canvas))
|
|
|
|
} else {
|
|
|
|
// Trying WebGl1 first (useful for testing).
|
2022-02-01 11:27:39 +00:00
|
|
|
tracing::warn!("Looking for WebGL1 first");
|
2022-01-22 07:59:06 +00:00
|
|
|
init_webgl1(canvas).or_else(|| init_webgl2(canvas))
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(result) = result {
|
2022-01-31 18:15:48 +00:00
|
|
|
Ok(result)
|
2022-01-22 07:59:06 +00:00
|
|
|
} else {
|
2022-01-31 18:15:48 +00:00
|
|
|
Err("WebGL isn't supported".into())
|
2022-01-22 07:59:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn init_webgl1(canvas: &HtmlCanvasElement) -> Option<(glow::Context, &'static str)> {
|
|
|
|
let gl1_ctx = canvas
|
|
|
|
.get_context("webgl")
|
|
|
|
.expect("Failed to query about WebGL2 context");
|
|
|
|
|
|
|
|
let gl1_ctx = gl1_ctx?;
|
2022-02-01 11:27:39 +00:00
|
|
|
tracing::debug!("WebGL1 selected.");
|
2022-01-22 07:59:06 +00:00
|
|
|
|
|
|
|
let gl1_ctx = gl1_ctx
|
|
|
|
.dyn_into::<web_sys::WebGlRenderingContext>()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let shader_prefix = if crate::webgl1_requires_brightening(&gl1_ctx) {
|
2022-02-01 11:27:39 +00:00
|
|
|
tracing::debug!("Enabling webkitGTK brightening workaround.");
|
2022-01-22 07:59:06 +00:00
|
|
|
"#define APPLY_BRIGHTENING_GAMMA"
|
|
|
|
} else {
|
|
|
|
""
|
|
|
|
};
|
|
|
|
|
|
|
|
let glow_ctx = glow::Context::from_webgl1_context(gl1_ctx);
|
|
|
|
|
|
|
|
Some((glow_ctx, shader_prefix))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn init_webgl2(canvas: &HtmlCanvasElement) -> Option<(glow::Context, &'static str)> {
|
2021-12-31 14:17:55 +00:00
|
|
|
let gl2_ctx = canvas
|
|
|
|
.get_context("webgl2")
|
|
|
|
.expect("Failed to query about WebGL2 context");
|
|
|
|
|
2022-01-22 07:59:06 +00:00
|
|
|
let gl2_ctx = gl2_ctx?;
|
2022-02-01 11:27:39 +00:00
|
|
|
tracing::debug!("WebGL2 selected.");
|
2022-01-22 07:59:06 +00:00
|
|
|
|
|
|
|
let gl2_ctx = gl2_ctx
|
|
|
|
.dyn_into::<web_sys::WebGl2RenderingContext>()
|
|
|
|
.unwrap();
|
|
|
|
let glow_ctx = glow::Context::from_webgl2_context(gl2_ctx);
|
|
|
|
let shader_prefix = "";
|
|
|
|
|
|
|
|
Some((glow_ctx, shader_prefix))
|
2021-11-03 18:17:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
trait DummyWebGLConstructor {
|
|
|
|
fn from_webgl1_context(context: web_sys::WebGlRenderingContext) -> Self;
|
|
|
|
|
|
|
|
fn from_webgl2_context(context: web_sys::WebGl2RenderingContext) -> Self;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
|
|
impl DummyWebGLConstructor for glow::Context {
|
|
|
|
fn from_webgl1_context(_context: WebGlRenderingContext) -> Self {
|
2022-01-22 07:59:06 +00:00
|
|
|
panic!("you can't use egui_web(glow) on native")
|
2021-11-03 18:17:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn from_webgl2_context(_context: WebGl2RenderingContext) -> Self {
|
2022-01-22 07:59:06 +00:00
|
|
|
panic!("you can't use egui_web(glow) on native")
|
2021-11-03 18:17:07 +00:00
|
|
|
}
|
|
|
|
}
|