diff --git a/egui_glow/CHANGELOG.md b/egui_glow/CHANGELOG.md index 4d107dcb3736..c83a9c2e1768 100644 --- a/egui_glow/CHANGELOG.md +++ b/egui_glow/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to the `egui_glow` integration will be noted in this file. ## Unreleased * Added `set_texture_filter` method to `Painter` ((#1041)[https://github.com/emilk/egui/pull/1041]). +* Fix failure to run in Chrome ((#1092)[https://github.com/emilk/egui/pull/1092]). ## 0.16.0 - 2021-12-29 * Made winit/glutin an optional dependency ([#868](https://github.com/emilk/egui/pull/868)). diff --git a/egui_glow/src/misc_util.rs b/egui_glow/src/misc_util.rs index 4d5ddd30f864..bd091f5ca278 100644 --- a/egui_glow/src/misc_util.rs +++ b/egui_glow/src/misc_util.rs @@ -204,40 +204,36 @@ impl VAO { /// If returned true no need to emulate vao pub(crate) fn supports_vao(gl: &glow::Context) -> bool { - let web_sig = "WebGL "; - let es_sig = "OpenGL ES "; + const WEBGL_PREFIX: &str = "WebGL "; + const OPENGL_ES_PREFIX: &str = "OpenGL ES "; + let version_string = unsafe { gl.get_parameter_string(glow::VERSION) }; - if let Some(pos) = version_string.rfind(web_sig) { - let version_str = &version_string[pos + web_sig.len()..]; - glow_print(format!( - "detected WebGL prefix at {}:{}", - pos + web_sig.len(), - version_str - )); + glow_print(format!("GL version: {:?}.", version_string)); + + // Examples: + // * "WebGL 2.0 (OpenGL ES 3.0 Chromium)" + // * "WebGL 2.0" + + if let Some(pos) = version_string.rfind(WEBGL_PREFIX) { + let version_str = &version_string[pos + WEBGL_PREFIX.len()..]; if version_str.contains("1.0") { - //need to test OES_vertex_array_object . + // need to test OES_vertex_array_object . gl.supported_extensions() .contains("OES_vertex_array_object") } else { true } - } else if let Some(pos) = version_string.rfind(es_sig) { - //glow targets es2.0+ so we don't concern about OpenGL ES-CM,OpenGL ES-CL - glow_print(format!( - "detected OpenGL ES prefix at {}:{}", - pos + es_sig.len(), - &version_string[pos + es_sig.len()..] - )); + } else if version_string.contains(OPENGL_ES_PREFIX) { + // glow targets es2.0+ so we don't concern about OpenGL ES-CM,OpenGL ES-CL if version_string.contains("2.0") { - //need to test OES_vertex_array_object . + // need to test OES_vertex_array_object . gl.supported_extensions() .contains("OES_vertex_array_object") } else { true } } else { - glow_print(format!("detected OpenGL: {:?}", version_string)); - //from OpenGL 3 vao into core + // from OpenGL 3 vao into core if version_string.starts_with('2') { // I found APPLE_vertex_array_object , GL_ATI_vertex_array_object ,ARB_vertex_array_object // but APPLE's and ATI's very old extension. diff --git a/egui_glow/src/painter.rs b/egui_glow/src/painter.rs index 4319625d2d4c..bf8d8ce5ebe3 100644 --- a/egui_glow/src/painter.rs +++ b/egui_glow/src/painter.rs @@ -99,16 +99,16 @@ impl Painter { let shader_version = ShaderVersion::get(gl); let is_webgl_1 = shader_version == ShaderVersion::Es100; let header = shader_version.version(); - glow_print(format!("Shader header: {:?}", header)); + glow_print(format!("Shader header: {:?}.", header)); let srgb_support = gl.supported_extensions().contains("EXT_sRGB"); let (post_process, srgb_support_define) = match (shader_version, srgb_support) { - //WebGL2 support sRGB default + // WebGL2 support sRGB default (ShaderVersion::Es300, _) | (ShaderVersion::Es100, true) => unsafe { - //Add sRGB support marker for fragment shader + // Add sRGB support marker for fragment shader if let Some([width, height]) = pp_fb_extent { - glow_print("WebGL with sRGB enabled so turn on post process"); - //install post process to correct sRGB color + glow_print("WebGL with sRGB enabled. Turning on post processing for linear framebuffer blending."); + // install post process to correct sRGB color: ( Some(PostProcess::new( gl, @@ -125,9 +125,11 @@ impl Painter { (None, "") } }, - //WebGL1 without sRGB support disable postprocess and use fallback shader + + // WebGL1 without sRGB support disable postprocess and use fallback shader (ShaderVersion::Es100, false) => (None, ""), - //OpenGL 2.1 or above always support sRGB so add sRGB support marker + + // OpenGL 2.1 or above always support sRGB so add sRGB support marker _ => (None, "#define SRGB_SUPPORTED"), }; diff --git a/egui_glow/src/shader_version.rs b/egui_glow/src/shader_version.rs index 01b595a3b70a..de3a339d1f32 100644 --- a/egui_glow/src/shader_version.rs +++ b/egui_glow/src/shader_version.rs @@ -18,7 +18,7 @@ impl ShaderVersion { unsafe { gl.get_parameter_string(glow::SHADING_LANGUAGE_VERSION) }; let shader_version = Self::parse(&shading_lang_string); glow_print(format!( - "Shader version: {:?} ({:?})", + "Shader version: {:?} ({:?}).", shader_version, shading_lang_string )); shader_version diff --git a/egui_web/CHANGELOG.md b/egui_web/CHANGELOG.md index 68714197c8a5..78403a8c3f06 100644 --- a/egui_web/CHANGELOG.md +++ b/egui_web/CHANGELOG.md @@ -6,6 +6,7 @@ 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)). +* Fix glow failure Chrome ((#1092)[https://github.com/emilk/egui/pull/1092]). ## 0.16.0 - 2021-12-29 diff --git a/egui_web/src/glow_wrapping.rs b/egui_web/src/glow_wrapping.rs index 785e205dab00..2d24a635e156 100644 --- a/egui_web/src/glow_wrapping.rs +++ b/egui_web/src/glow_wrapping.rs @@ -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::() - .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::() .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::().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."); } diff --git a/egui_web/src/lib.rs b/egui_web/src/lib.rs index 36ea3f2472ff..8d1825834464 100644 --- a/egui_web/src/lib.rs +++ b/egui_web/src/lib.rs @@ -1238,6 +1238,18 @@ fn move_text_cursor(cursor: &Option, 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, 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; + } } } } diff --git a/egui_web/src/webgl1.rs b/egui_web/src/webgl1.rs index 7b847c7c90af..ce96a988b28b 100644 --- a/egui_web/src/webgl1.rs +++ b/egui_web/src/webgl1.rs @@ -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 { 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 {