Fix wrong gamma in WebkitGTK (#888)
Closes https://github.com/emilk/egui/issues/794 Also refactor and improve VAO support detection Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
parent
4d4c75c6f1
commit
008a971e73
11 changed files with 115 additions and 22 deletions
|
@ -58,7 +58,7 @@ pub fn run(app: Box<dyn epi::App>, native_options: &epi::NativeOptions) -> ! {
|
||||||
event_loop.create_proxy(),
|
event_loop.create_proxy(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
let mut painter = crate::Painter::new(&gl, None)
|
let mut painter = crate::Painter::new(&gl, None, "")
|
||||||
.map_err(|error| eprintln!("some OpenGL error occurred {}\n", error))
|
.map_err(|error| eprintln!("some OpenGL error occurred {}\n", error))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut integration = egui_winit::epi::EpiIntegration::new(
|
let mut integration = egui_winit::epi::EpiIntegration::new(
|
||||||
|
|
|
@ -123,7 +123,7 @@ impl EguiGlow {
|
||||||
Self {
|
Self {
|
||||||
egui_ctx: Default::default(),
|
egui_ctx: Default::default(),
|
||||||
egui_winit: egui_winit::State::new(gl_window.window()),
|
egui_winit: egui_winit::State::new(gl_window.window()),
|
||||||
painter: crate::Painter::new(gl, None)
|
painter: crate::Painter::new(gl, None, "")
|
||||||
.map_err(|error| {
|
.map_err(|error| {
|
||||||
eprintln!("some error occurred in initializing painter\n{}", error);
|
eprintln!("some error occurred in initializing painter\n{}", error);
|
||||||
})
|
})
|
||||||
|
|
|
@ -184,7 +184,8 @@ impl VAO {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn need_to_emulate_vao(gl: &glow::Context) -> bool {
|
/// If returned true no need to emulate vao
|
||||||
|
pub(crate) unsafe fn support_vao(gl: &glow::Context) -> bool {
|
||||||
let web_sig = "WebGL ";
|
let web_sig = "WebGL ";
|
||||||
let es_sig = "OpenGL ES ";
|
let es_sig = "OpenGL ES ";
|
||||||
let version_string = gl.get_parameter_string(glow::VERSION);
|
let version_string = gl.get_parameter_string(glow::VERSION);
|
||||||
|
@ -200,7 +201,7 @@ pub(crate) unsafe fn need_to_emulate_vao(gl: &glow::Context) -> bool {
|
||||||
gl.supported_extensions()
|
gl.supported_extensions()
|
||||||
.contains("OES_vertex_array_object")
|
.contains("OES_vertex_array_object")
|
||||||
} else {
|
} else {
|
||||||
false
|
true
|
||||||
}
|
}
|
||||||
} else if let Some(pos) = version_string.rfind(es_sig) {
|
} 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 targets es2.0+ so we don't concern about OpenGL ES-CM,OpenGL ES-CL
|
||||||
|
@ -214,7 +215,7 @@ pub(crate) unsafe fn need_to_emulate_vao(gl: &glow::Context) -> bool {
|
||||||
gl.supported_extensions()
|
gl.supported_extensions()
|
||||||
.contains("OES_vertex_array_object")
|
.contains("OES_vertex_array_object")
|
||||||
} else {
|
} else {
|
||||||
false
|
true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
glow_debug_print(format!("detected OpenGL:{}", version_string));
|
glow_debug_print(format!("detected OpenGL:{}", version_string));
|
||||||
|
@ -225,7 +226,7 @@ pub(crate) unsafe fn need_to_emulate_vao(gl: &glow::Context) -> bool {
|
||||||
gl.supported_extensions()
|
gl.supported_extensions()
|
||||||
.contains("ARB_vertex_array_object")
|
.contains("ARB_vertex_array_object")
|
||||||
} else {
|
} else {
|
||||||
false
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,18 +61,26 @@ impl Painter {
|
||||||
/// Create painter.
|
/// Create painter.
|
||||||
///
|
///
|
||||||
/// Set `pp_fb_extent` to the framebuffer size to enable `sRGB` support on OpenGL ES and WebGL.
|
/// Set `pp_fb_extent` to the framebuffer size to enable `sRGB` support on OpenGL ES and WebGL.
|
||||||
|
/// Set `shader_prefix` if you want to turn on shader workaround e.g. `"#define EPIPHANY_WORKAROUND\n"`.
|
||||||
|
///
|
||||||
|
/// this fix [Everything is super dark in epiphany](https://github.com/emilk/egui/issues/794)
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// will return `Err` below cases
|
/// will return `Err` below cases
|
||||||
/// * failed to compile shader
|
/// * failed to compile shader
|
||||||
/// * failed to create postprocess on webgl with `sRGB` support
|
/// * failed to create postprocess on webgl with `sRGB` support
|
||||||
/// * failed to create buffer
|
/// * failed to create buffer
|
||||||
pub fn new(gl: &glow::Context, pp_fb_extent: Option<[i32; 2]>) -> Result<Painter, String> {
|
pub fn new(
|
||||||
let need_to_emulate_vao = unsafe { crate::misc_util::need_to_emulate_vao(gl) };
|
gl: &glow::Context,
|
||||||
|
pp_fb_extent: Option<[i32; 2]>,
|
||||||
|
shader_prefix: &str,
|
||||||
|
) -> Result<Painter, String> {
|
||||||
|
let support_vao = unsafe { crate::misc_util::support_vao(gl) };
|
||||||
let shader_version = ShaderVersion::get(gl);
|
let shader_version = ShaderVersion::get(gl);
|
||||||
let is_webgl_1 = shader_version == ShaderVersion::Es100;
|
let is_webgl_1 = shader_version == ShaderVersion::Es100;
|
||||||
let header = shader_version.version();
|
let header = shader_version.version();
|
||||||
glow_debug_print(header);
|
glow_debug_print(header);
|
||||||
let srgb_support = gl.supported_extensions().contains("EXT_sRGB");
|
let srgb_support = gl.supported_extensions().contains("EXT_sRGB");
|
||||||
|
|
||||||
let (post_process, srgb_support_define) = match (shader_version, srgb_support) {
|
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 {
|
(ShaderVersion::Es300, _) | (ShaderVersion::Es100, true) => unsafe {
|
||||||
|
@ -83,7 +91,8 @@ impl Painter {
|
||||||
(
|
(
|
||||||
Some(PostProcess::new(
|
Some(PostProcess::new(
|
||||||
gl,
|
gl,
|
||||||
need_to_emulate_vao,
|
shader_prefix,
|
||||||
|
support_vao,
|
||||||
is_webgl_1,
|
is_webgl_1,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
@ -106,8 +115,9 @@ impl Painter {
|
||||||
gl,
|
gl,
|
||||||
glow::VERTEX_SHADER,
|
glow::VERTEX_SHADER,
|
||||||
&format!(
|
&format!(
|
||||||
"{}\n{}\n{}",
|
"{}\n{}\n{}\n{}",
|
||||||
header,
|
header,
|
||||||
|
shader_prefix,
|
||||||
shader_version.is_new_shader_interface(),
|
shader_version.is_new_shader_interface(),
|
||||||
VERT_SRC
|
VERT_SRC
|
||||||
),
|
),
|
||||||
|
@ -116,8 +126,9 @@ impl Painter {
|
||||||
gl,
|
gl,
|
||||||
glow::FRAGMENT_SHADER,
|
glow::FRAGMENT_SHADER,
|
||||||
&format!(
|
&format!(
|
||||||
"{}\n{}\n{}\n{}",
|
"{}\n{}\n{}\n{}\n{}",
|
||||||
header,
|
header,
|
||||||
|
shader_prefix,
|
||||||
srgb_support_define,
|
srgb_support_define,
|
||||||
shader_version.is_new_shader_interface(),
|
shader_version.is_new_shader_interface(),
|
||||||
FRAG_SRC
|
FRAG_SRC
|
||||||
|
@ -136,10 +147,10 @@ impl Painter {
|
||||||
let a_pos_loc = gl.get_attrib_location(program, "a_pos").unwrap();
|
let a_pos_loc = gl.get_attrib_location(program, "a_pos").unwrap();
|
||||||
let a_tc_loc = gl.get_attrib_location(program, "a_tc").unwrap();
|
let a_tc_loc = gl.get_attrib_location(program, "a_tc").unwrap();
|
||||||
let a_srgba_loc = gl.get_attrib_location(program, "a_srgba").unwrap();
|
let a_srgba_loc = gl.get_attrib_location(program, "a_srgba").unwrap();
|
||||||
let mut vertex_array = if need_to_emulate_vao {
|
let mut vertex_array = if support_vao {
|
||||||
crate::misc_util::VAO::emulated()
|
|
||||||
} else {
|
|
||||||
crate::misc_util::VAO::native(gl)
|
crate::misc_util::VAO::native(gl)
|
||||||
|
} else {
|
||||||
|
crate::misc_util::VAO::emulated()
|
||||||
};
|
};
|
||||||
vertex_array.bind_vertex_array(gl);
|
vertex_array.bind_vertex_array(gl);
|
||||||
vertex_array.bind_buffer(gl, &vertex_buffer);
|
vertex_array.bind_buffer(gl, &vertex_buffer);
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub(crate) struct PostProcess {
|
||||||
impl PostProcess {
|
impl PostProcess {
|
||||||
pub(crate) unsafe fn new(
|
pub(crate) unsafe fn new(
|
||||||
gl: &glow::Context,
|
gl: &glow::Context,
|
||||||
|
shader_prefix: &str,
|
||||||
need_to_emulate_vao: bool,
|
need_to_emulate_vao: bool,
|
||||||
is_webgl_1: bool,
|
is_webgl_1: bool,
|
||||||
width: i32,
|
width: i32,
|
||||||
|
@ -96,12 +97,20 @@ impl PostProcess {
|
||||||
let vert_shader = compile_shader(
|
let vert_shader = compile_shader(
|
||||||
gl,
|
gl,
|
||||||
glow::VERTEX_SHADER,
|
glow::VERTEX_SHADER,
|
||||||
include_str!("shader/post_vertex_100es.glsl"),
|
&format!(
|
||||||
|
"{}\n{}",
|
||||||
|
shader_prefix,
|
||||||
|
include_str!("shader/post_vertex_100es.glsl")
|
||||||
|
),
|
||||||
)?;
|
)?;
|
||||||
let frag_shader = compile_shader(
|
let frag_shader = compile_shader(
|
||||||
gl,
|
gl,
|
||||||
glow::FRAGMENT_SHADER,
|
glow::FRAGMENT_SHADER,
|
||||||
include_str!("shader/post_fragment_100es.glsl"),
|
&format!(
|
||||||
|
"{}\n{}",
|
||||||
|
shader_prefix,
|
||||||
|
include_str!("shader/post_fragment_100es.glsl")
|
||||||
|
),
|
||||||
)?;
|
)?;
|
||||||
let program = link_program(gl, [vert_shader, frag_shader].iter())?;
|
let program = link_program(gl, [vert_shader, frag_shader].iter())?;
|
||||||
|
|
||||||
|
|
|
@ -19,4 +19,8 @@ void main() {
|
||||||
gl_FragColor = texture2D(u_sampler, v_tc);
|
gl_FragColor = texture2D(u_sampler, v_tc);
|
||||||
|
|
||||||
gl_FragColor = srgba_from_linear(gl_FragColor) / 255.;
|
gl_FragColor = srgba_from_linear(gl_FragColor) / 255.;
|
||||||
|
#ifdef WEBKITGTK_WORKAROUND
|
||||||
|
//this is better than double apply
|
||||||
|
gl_FragColor = vec4(pow(gl_FragColor.rgb,vec3(1.0/2.2)),gl_FragColor.a);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ All notable changes to the `egui_web` integration will be noted in this file.
|
||||||
|
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
*Add feature `glow` to switch to a [`glow`](https://github.com/grovesNL/glow) based painter ([#868](https://github.com/emilk/egui/pull/868)).
|
* Fix [dark rendering in epiphany](https://github.com/emilk/egui/issues/794) for WebGL1 and glow based painter ([#888](https://github.com/emilk/egui/pull/888/)).
|
||||||
|
* Add feature `glow` to switch to a [`glow`](https://github.com/grovesNL/glow) based painter ([#868](https://github.com/emilk/egui/pull/868)).
|
||||||
|
|
||||||
## 0.15.0 - 2021-10-24
|
## 0.15.0 - 2021-10-24
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -88,6 +88,7 @@ features = [
|
||||||
"TouchList",
|
"TouchList",
|
||||||
"WebGl2RenderingContext",
|
"WebGl2RenderingContext",
|
||||||
"WebGlBuffer",
|
"WebGlBuffer",
|
||||||
|
"WebglDebugRendererInfo",
|
||||||
"WebGlFramebuffer",
|
"WebGlFramebuffer",
|
||||||
"WebGlProgram",
|
"WebGlProgram",
|
||||||
"WebGlRenderingContext",
|
"WebGlRenderingContext",
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use crate::web_sys::{WebGl2RenderingContext, WebGlRenderingContext};
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
use crate::web_sys::WebGl2RenderingContext;
|
||||||
|
use crate::web_sys::WebGlRenderingContext;
|
||||||
use crate::{canvas_element_or_die, console_error};
|
use crate::{canvas_element_or_die, console_error};
|
||||||
use egui::{ClippedMesh, Rgba, Texture};
|
use egui::{ClippedMesh, Rgba, Texture};
|
||||||
use egui_glow::glow;
|
use egui_glow::glow;
|
||||||
use epi::TextureAllocator;
|
use epi::TextureAllocator;
|
||||||
|
use wasm_bindgen::JsCast;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
use web_sys::HtmlCanvasElement;
|
use web_sys::HtmlCanvasElement;
|
||||||
|
|
||||||
|
@ -16,9 +19,29 @@ pub(crate) struct WrappedGlowPainter {
|
||||||
impl WrappedGlowPainter {
|
impl WrappedGlowPainter {
|
||||||
pub fn new(canvas_id: &str) -> Self {
|
pub fn new(canvas_id: &str) -> Self {
|
||||||
let canvas = canvas_element_or_die(canvas_id);
|
let canvas = canvas_element_or_die(canvas_id);
|
||||||
|
// 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();
|
||||||
|
let webkit_gtk_wr = if !user_agent.contains("Mac OS X")
|
||||||
|
&& crate::webgl1::detect_safari_and_webkit_gtk(&gl)
|
||||||
|
{
|
||||||
|
"#define WEBKITGTK_WORKAROUND"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
let gl_ctx = 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 dimension = [canvas.width() as i32, canvas.height() as i32];
|
||||||
let painter = egui_glow::Painter::new(&gl_ctx, Some(dimension))
|
let painter = egui_glow::Painter::new(&gl_ctx, Some(dimension), webkit_gtk_wr)
|
||||||
.map_err(|error| {
|
.map_err(|error| {
|
||||||
console_error(format!(
|
console_error(format!(
|
||||||
"some error occurred in initializing glow painter\n {}",
|
"some error occurred in initializing glow painter\n {}",
|
||||||
|
@ -82,7 +105,6 @@ impl crate::Painter for WrappedGlowPainter {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_glow_context_from_canvas(canvas: &HtmlCanvasElement) -> glow::Context {
|
pub fn init_glow_context_from_canvas(canvas: &HtmlCanvasElement) -> glow::Context {
|
||||||
use wasm_bindgen::JsCast;
|
|
||||||
let ctx = canvas.get_context("webgl2");
|
let ctx = canvas.get_context("webgl2");
|
||||||
if let Ok(ctx) = ctx {
|
if let Ok(ctx) = ctx {
|
||||||
crate::console_log("webgl found");
|
crate::console_log("webgl found");
|
||||||
|
|
|
@ -19,4 +19,8 @@ void main() {
|
||||||
gl_FragColor = texture2D(u_sampler, v_tc);
|
gl_FragColor = texture2D(u_sampler, v_tc);
|
||||||
|
|
||||||
gl_FragColor = srgba_from_linear(gl_FragColor) / 255.;
|
gl_FragColor = srgba_from_linear(gl_FragColor) / 255.;
|
||||||
|
#ifdef WEBKITGTK_WORKAROUND
|
||||||
|
//this is better than double apply
|
||||||
|
gl_FragColor = vec4(pow(gl_FragColor.rgb,vec3(1.0/2.2)),gl_FragColor.a);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,11 @@ use {
|
||||||
wasm_bindgen::{prelude::*, JsCast},
|
wasm_bindgen::{prelude::*, JsCast},
|
||||||
web_sys::{
|
web_sys::{
|
||||||
ExtSRgb, WebGlBuffer, WebGlFramebuffer, WebGlProgram, WebGlRenderingContext, WebGlShader,
|
ExtSRgb, WebGlBuffer, WebGlFramebuffer, WebGlProgram, WebGlRenderingContext, WebGlShader,
|
||||||
WebGlTexture,
|
WebGlTexture, WebglDebugRendererInfo,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::console_log;
|
||||||
use egui::{
|
use egui::{
|
||||||
emath::vec2,
|
emath::vec2,
|
||||||
epaint::{Color32, Texture},
|
epaint::{Color32, Texture},
|
||||||
|
@ -591,6 +592,17 @@ impl PostProcess {
|
||||||
|
|
||||||
gl.bind_texture(Gl::TEXTURE_2D, None);
|
gl.bind_texture(Gl::TEXTURE_2D, None);
|
||||||
gl.bind_framebuffer(Gl::FRAMEBUFFER, None);
|
gl.bind_framebuffer(Gl::FRAMEBUFFER, None);
|
||||||
|
// 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();
|
||||||
|
let webkit_gtk_wr = if !user_agent.contains("Mac OS X") && detect_safari_and_webkit_gtk(&gl)
|
||||||
|
{
|
||||||
|
"#define WEBKITGTK_WORKAROUND"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
};
|
||||||
|
|
||||||
let vert_shader = compile_shader(
|
let vert_shader = compile_shader(
|
||||||
&gl,
|
&gl,
|
||||||
|
@ -600,7 +612,11 @@ impl PostProcess {
|
||||||
let frag_shader = compile_shader(
|
let frag_shader = compile_shader(
|
||||||
&gl,
|
&gl,
|
||||||
Gl::FRAGMENT_SHADER,
|
Gl::FRAGMENT_SHADER,
|
||||||
include_str!("shader/post_fragment_100es.glsl"),
|
&format!(
|
||||||
|
"{}{}",
|
||||||
|
webkit_gtk_wr,
|
||||||
|
include_str!("shader/post_fragment_100es.glsl")
|
||||||
|
),
|
||||||
)?;
|
)?;
|
||||||
let program = link_program(&gl, [vert_shader, frag_shader].iter())?;
|
let program = link_program(&gl, [vert_shader, frag_shader].iter())?;
|
||||||
|
|
||||||
|
@ -750,3 +766,27 @@ fn link_program<'a, T: IntoIterator<Item = &'a WebGlShader>>(
|
||||||
.unwrap_or_else(|| "Unknown error creating program object".into()))
|
.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 detect_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") {
|
||||||
|
console_log("Enabling webkitGTK workaround");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue