mirror of
https://github.com/emilk/egui.git
synced 2026-08-30 05:10:03 -04:00
Fix bugs in glow on web (#1092)
* Re-add check of WEBGL_debug_renderer_info to avoid OpenGL error I removed this check in https://github.com/emilk/egui/pull/1020 because it produced a warning on Firefox. Better a warning than an OpenGL error though. * Bug fix: don't ask for webgl context and then later for webgl2 context The browser will only allow the first thing we check, so this will prevent webgl2 from working.
This commit is contained in:
@@ -5,11 +5,10 @@ use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen::JsValue;
|
||||
use web_sys::HtmlCanvasElement;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use web_sys::WebGl2RenderingContext;
|
||||
use web_sys::WebGlRenderingContext;
|
||||
use web_sys::{WebGl2RenderingContext, WebGlRenderingContext};
|
||||
|
||||
pub(crate) struct WrappedGlowPainter {
|
||||
pub(crate) gl_ctx: glow::Context,
|
||||
pub(crate) glow_ctx: glow::Context,
|
||||
pub(crate) canvas: HtmlCanvasElement,
|
||||
pub(crate) canvas_id: String,
|
||||
pub(crate) painter: egui_glow::Painter,
|
||||
@@ -19,16 +18,10 @@ impl WrappedGlowPainter {
|
||||
pub fn new(canvas_id: &str) -> Self {
|
||||
let canvas = canvas_element_or_die(canvas_id);
|
||||
|
||||
let shader_prefix = if requires_brightening(&canvas) {
|
||||
crate::console_log("Enabling webkitGTK brightening workaround");
|
||||
"#define APPLY_BRIGHTENING_GAMMA"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let (glow_ctx, shader_prefix) = init_glow_context_from_canvas(&canvas);
|
||||
|
||||
let gl_ctx = init_glow_context_from_canvas(&canvas);
|
||||
let dimension = [canvas.width() as i32, canvas.height() as i32];
|
||||
let painter = egui_glow::Painter::new(&gl_ctx, Some(dimension), shader_prefix)
|
||||
let painter = egui_glow::Painter::new(&glow_ctx, Some(dimension), shader_prefix)
|
||||
.map_err(|error| {
|
||||
console_error(format!(
|
||||
"some error occurred in initializing glow painter\n {}",
|
||||
@@ -38,7 +31,7 @@ impl WrappedGlowPainter {
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
gl_ctx,
|
||||
glow_ctx,
|
||||
canvas,
|
||||
canvas_id: canvas_id.to_owned(),
|
||||
painter,
|
||||
@@ -46,28 +39,9 @@ impl WrappedGlowPainter {
|
||||
}
|
||||
}
|
||||
|
||||
fn requires_brightening(canvas: &web_sys::HtmlCanvasElement) -> bool {
|
||||
// See https://github.com/emilk/egui/issues/794
|
||||
|
||||
// detect WebKitGTK
|
||||
|
||||
// WebKitGTK currently support only webgl,so request webgl context.
|
||||
// WebKitGTK use WebKit default unmasked vendor and renderer
|
||||
// but safari use same vendor and renderer
|
||||
// so exclude "Mac OS X" user-agent.
|
||||
let gl = canvas
|
||||
.get_context("webgl")
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.dyn_into::<WebGlRenderingContext>()
|
||||
.unwrap();
|
||||
let user_agent = web_sys::window().unwrap().navigator().user_agent().unwrap();
|
||||
crate::is_safari_and_webkit_gtk(&gl) && !user_agent.contains("Mac OS X")
|
||||
}
|
||||
|
||||
impl crate::Painter for WrappedGlowPainter {
|
||||
fn set_texture(&mut self, tex_id: u64, image: epi::Image) {
|
||||
self.painter.set_texture(&self.gl_ctx, tex_id, &image);
|
||||
self.painter.set_texture(&self.glow_ctx, tex_id, &image);
|
||||
}
|
||||
|
||||
fn free_texture(&mut self, tex_id: u64) {
|
||||
@@ -87,12 +61,12 @@ impl crate::Painter for WrappedGlowPainter {
|
||||
}
|
||||
|
||||
fn upload_egui_texture(&mut self, font_image: &FontImage) {
|
||||
self.painter.upload_egui_texture(&self.gl_ctx, font_image)
|
||||
self.painter.upload_egui_texture(&self.glow_ctx, font_image)
|
||||
}
|
||||
|
||||
fn clear(&mut self, clear_color: Rgba) {
|
||||
let canvas_dimension = [self.canvas.width(), self.canvas.height()];
|
||||
egui_glow::painter::clear(&self.gl_ctx, canvas_dimension, clear_color)
|
||||
egui_glow::painter::clear(&self.glow_ctx, canvas_dimension, clear_color)
|
||||
}
|
||||
|
||||
fn paint_meshes(
|
||||
@@ -102,7 +76,7 @@ impl crate::Painter for WrappedGlowPainter {
|
||||
) -> Result<(), JsValue> {
|
||||
let canvas_dimension = [self.canvas.width(), self.canvas.height()];
|
||||
self.painter.paint_meshes(
|
||||
&self.gl_ctx,
|
||||
&self.glow_ctx,
|
||||
canvas_dimension,
|
||||
pixels_per_point,
|
||||
clipped_meshes,
|
||||
@@ -115,26 +89,39 @@ impl crate::Painter for WrappedGlowPainter {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_glow_context_from_canvas(canvas: &HtmlCanvasElement) -> glow::Context {
|
||||
/// Returns glow context and shader prefix.
|
||||
fn init_glow_context_from_canvas(canvas: &HtmlCanvasElement) -> (glow::Context, &str) {
|
||||
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");
|
||||
crate::console_log("WebGL2 found.");
|
||||
let gl2_ctx = gl2_ctx
|
||||
.dyn_into::<web_sys::WebGl2RenderingContext>()
|
||||
.unwrap();
|
||||
glow::Context::from_webgl2_context(gl2_ctx)
|
||||
let glow_ctx = glow::Context::from_webgl2_context(gl2_ctx);
|
||||
let shader_prefix = "";
|
||||
(glow_ctx, shader_prefix)
|
||||
} 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 WebGL1");
|
||||
crate::console_log("WebGL2 not available - falling back to WebGL1.");
|
||||
let gl1_ctx = gl1.dyn_into::<web_sys::WebGlRenderingContext>().unwrap();
|
||||
glow::Context::from_webgl1_context(gl1_ctx)
|
||||
|
||||
let shader_prefix = if crate::webgl1_requires_brightening(&gl1_ctx) {
|
||||
crate::console_log("Enabling webkitGTK brightening workaround.");
|
||||
"#define APPLY_BRIGHTENING_GAMMA"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
let glow_ctx = glow::Context::from_webgl1_context(gl1_ctx);
|
||||
|
||||
(glow_ctx, shader_prefix)
|
||||
} else {
|
||||
panic!("Failed to get WebGL context.");
|
||||
}
|
||||
|
||||
@@ -1238,6 +1238,18 @@ fn move_text_cursor(cursor: &Option<egui::Pos2>, canvas_id: &str) -> Option<()>
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn webgl1_requires_brightening(gl: &web_sys::WebGlRenderingContext) -> bool {
|
||||
// See https://github.com/emilk/egui/issues/794
|
||||
|
||||
// detect WebKitGTK
|
||||
|
||||
// WebKitGTK use WebKit default unmasked vendor and renderer
|
||||
// but safari use same vendor and renderer
|
||||
// so exclude "Mac OS X" user-agent.
|
||||
let user_agent = web_sys::window().unwrap().navigator().user_agent().unwrap();
|
||||
!user_agent.contains("Mac OS X") && crate::is_safari_and_webkit_gtk(gl)
|
||||
}
|
||||
|
||||
/// detecting Safari and webkitGTK.
|
||||
///
|
||||
/// Safari and webkitGTK use unmasked renderer :Apple GPU
|
||||
@@ -1245,12 +1257,22 @@ fn move_text_cursor(cursor: &Option<egui::Pos2>, canvas_id: &str) -> Option<()>
|
||||
/// 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)
|
||||
fn is_safari_and_webkit_gtk(gl: &web_sys::WebGlRenderingContext) -> bool {
|
||||
// This call produces a warning in Firefox ("WEBGL_debug_renderer_info is deprecated in Firefox and will be removed.")
|
||||
// but unless we call it we get errors in Chrome when we call `get_parameter` below.
|
||||
// TODO: do something smart based on user agent?
|
||||
if gl
|
||||
.get_extension("WEBGL_debug_renderer_info")
|
||||
.unwrap()
|
||||
.is_some()
|
||||
{
|
||||
if let Some(renderer) = renderer.as_string() {
|
||||
if renderer.contains("Apple") {
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,13 +475,6 @@ struct PostProcess {
|
||||
program: WebGlProgram,
|
||||
}
|
||||
|
||||
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::is_safari_and_webkit_gtk(gl) && !user_agent.contains("Mac OS X")
|
||||
}
|
||||
|
||||
impl PostProcess {
|
||||
fn new(gl: Gl, width: i32, height: i32) -> Result<PostProcess, JsValue> {
|
||||
let fbo = gl
|
||||
@@ -519,7 +512,7 @@ impl PostProcess {
|
||||
gl.bind_texture(Gl::TEXTURE_2D, None);
|
||||
gl.bind_framebuffer(Gl::FRAMEBUFFER, None);
|
||||
|
||||
let shader_prefix = if requires_brightening(&gl) {
|
||||
let shader_prefix = if crate::webgl1_requires_brightening(&gl) {
|
||||
crate::console_log("Enabling webkitGTK brightening workaround");
|
||||
"#define APPLY_BRIGHTENING_GAMMA"
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user