Skip to content

Commit 008a971

Browse files
Fix wrong gamma in WebkitGTK (#888)
Closes #794 Also refactor and improve VAO support detection Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
1 parent 4d4c75c commit 008a971

11 files changed

+115
-22
lines changed

egui_glow/src/epi_backend.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub fn run(app: Box<dyn epi::App>, native_options: &epi::NativeOptions) -> ! {
5858
event_loop.create_proxy(),
5959
)));
6060

61-
let mut painter = crate::Painter::new(&gl, None)
61+
let mut painter = crate::Painter::new(&gl, None, "")
6262
.map_err(|error| eprintln!("some OpenGL error occurred {}\n", error))
6363
.unwrap();
6464
let mut integration = egui_winit::epi::EpiIntegration::new(

egui_glow/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl EguiGlow {
123123
Self {
124124
egui_ctx: Default::default(),
125125
egui_winit: egui_winit::State::new(gl_window.window()),
126-
painter: crate::Painter::new(gl, None)
126+
painter: crate::Painter::new(gl, None, "")
127127
.map_err(|error| {
128128
eprintln!("some error occurred in initializing painter\n{}", error);
129129
})

egui_glow/src/misc_util.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ impl VAO {
184184
}
185185
}
186186

187-
pub(crate) unsafe fn need_to_emulate_vao(gl: &glow::Context) -> bool {
187+
/// If returned true no need to emulate vao
188+
pub(crate) unsafe fn support_vao(gl: &glow::Context) -> bool {
188189
let web_sig = "WebGL ";
189190
let es_sig = "OpenGL ES ";
190191
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 {
200201
gl.supported_extensions()
201202
.contains("OES_vertex_array_object")
202203
} else {
203-
false
204+
true
204205
}
205206
} else if let Some(pos) = version_string.rfind(es_sig) {
206207
//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 {
214215
gl.supported_extensions()
215216
.contains("OES_vertex_array_object")
216217
} else {
217-
false
218+
true
218219
}
219220
} else {
220221
glow_debug_print(format!("detected OpenGL:{}", version_string));
@@ -225,7 +226,7 @@ pub(crate) unsafe fn need_to_emulate_vao(gl: &glow::Context) -> bool {
225226
gl.supported_extensions()
226227
.contains("ARB_vertex_array_object")
227228
} else {
228-
false
229+
true
229230
}
230231
}
231232
}

egui_glow/src/painter.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,26 @@ impl Painter {
6161
/// Create painter.
6262
///
6363
/// Set `pp_fb_extent` to the framebuffer size to enable `sRGB` support on OpenGL ES and WebGL.
64+
/// Set `shader_prefix` if you want to turn on shader workaround e.g. `"#define EPIPHANY_WORKAROUND\n"`.
65+
///
66+
/// this fix [Everything is super dark in epiphany](https://github.com/emilk/egui/issues/794)
6467
/// # Errors
6568
/// will return `Err` below cases
6669
/// * failed to compile shader
6770
/// * failed to create postprocess on webgl with `sRGB` support
6871
/// * failed to create buffer
69-
pub fn new(gl: &glow::Context, pp_fb_extent: Option<[i32; 2]>) -> Result<Painter, String> {
70-
let need_to_emulate_vao = unsafe { crate::misc_util::need_to_emulate_vao(gl) };
72+
pub fn new(
73+
gl: &glow::Context,
74+
pp_fb_extent: Option<[i32; 2]>,
75+
shader_prefix: &str,
76+
) -> Result<Painter, String> {
77+
let support_vao = unsafe { crate::misc_util::support_vao(gl) };
7178
let shader_version = ShaderVersion::get(gl);
7279
let is_webgl_1 = shader_version == ShaderVersion::Es100;
7380
let header = shader_version.version();
7481
glow_debug_print(header);
7582
let srgb_support = gl.supported_extensions().contains("EXT_sRGB");
83+
7684
let (post_process, srgb_support_define) = match (shader_version, srgb_support) {
7785
//WebGL2 support sRGB default
7886
(ShaderVersion::Es300, _) | (ShaderVersion::Es100, true) => unsafe {
@@ -83,7 +91,8 @@ impl Painter {
8391
(
8492
Some(PostProcess::new(
8593
gl,
86-
need_to_emulate_vao,
94+
shader_prefix,
95+
support_vao,
8796
is_webgl_1,
8897
width,
8998
height,
@@ -106,8 +115,9 @@ impl Painter {
106115
gl,
107116
glow::VERTEX_SHADER,
108117
&format!(
109-
"{}\n{}\n{}",
118+
"{}\n{}\n{}\n{}",
110119
header,
120+
shader_prefix,
111121
shader_version.is_new_shader_interface(),
112122
VERT_SRC
113123
),
@@ -116,8 +126,9 @@ impl Painter {
116126
gl,
117127
glow::FRAGMENT_SHADER,
118128
&format!(
119-
"{}\n{}\n{}\n{}",
129+
"{}\n{}\n{}\n{}\n{}",
120130
header,
131+
shader_prefix,
121132
srgb_support_define,
122133
shader_version.is_new_shader_interface(),
123134
FRAG_SRC
@@ -136,10 +147,10 @@ impl Painter {
136147
let a_pos_loc = gl.get_attrib_location(program, "a_pos").unwrap();
137148
let a_tc_loc = gl.get_attrib_location(program, "a_tc").unwrap();
138149
let a_srgba_loc = gl.get_attrib_location(program, "a_srgba").unwrap();
139-
let mut vertex_array = if need_to_emulate_vao {
140-
crate::misc_util::VAO::emulated()
141-
} else {
150+
let mut vertex_array = if support_vao {
142151
crate::misc_util::VAO::native(gl)
152+
} else {
153+
crate::misc_util::VAO::emulated()
143154
};
144155
vertex_array.bind_vertex_array(gl);
145156
vertex_array.bind_buffer(gl, &vertex_buffer);

egui_glow/src/post_process.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub(crate) struct PostProcess {
1919
impl PostProcess {
2020
pub(crate) unsafe fn new(
2121
gl: &glow::Context,
22+
shader_prefix: &str,
2223
need_to_emulate_vao: bool,
2324
is_webgl_1: bool,
2425
width: i32,
@@ -96,12 +97,20 @@ impl PostProcess {
9697
let vert_shader = compile_shader(
9798
gl,
9899
glow::VERTEX_SHADER,
99-
include_str!("shader/post_vertex_100es.glsl"),
100+
&format!(
101+
"{}\n{}",
102+
shader_prefix,
103+
include_str!("shader/post_vertex_100es.glsl")
104+
),
100105
)?;
101106
let frag_shader = compile_shader(
102107
gl,
103108
glow::FRAGMENT_SHADER,
104-
include_str!("shader/post_fragment_100es.glsl"),
109+
&format!(
110+
"{}\n{}",
111+
shader_prefix,
112+
include_str!("shader/post_fragment_100es.glsl")
113+
),
105114
)?;
106115
let program = link_program(gl, [vert_shader, frag_shader].iter())?;
107116

egui_glow/src/shader/post_fragment_100es.glsl

+4
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ void main() {
1919
gl_FragColor = texture2D(u_sampler, v_tc);
2020

2121
gl_FragColor = srgba_from_linear(gl_FragColor) / 255.;
22+
#ifdef WEBKITGTK_WORKAROUND
23+
//this is better than double apply
24+
gl_FragColor = vec4(pow(gl_FragColor.rgb,vec3(1.0/2.2)),gl_FragColor.a);
25+
#endif
2226
}

egui_web/CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ All notable changes to the `egui_web` integration will be noted in this file.
44

55

66
## Unreleased
7-
*Add feature `glow` to switch to a [`glow`](https://github.com/grovesNL/glow) based painter ([#868](https://github.com/emilk/egui/pull/868)).
7+
* 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/)).
8+
* Add feature `glow` to switch to a [`glow`](https://github.com/grovesNL/glow) based painter ([#868](https://github.com/emilk/egui/pull/868)).
89

910
## 0.15.0 - 2021-10-24
1011
### Added

egui_web/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ features = [
8888
"TouchList",
8989
"WebGl2RenderingContext",
9090
"WebGlBuffer",
91+
"WebglDebugRendererInfo",
9192
"WebGlFramebuffer",
9293
"WebGlProgram",
9394
"WebGlRenderingContext",

egui_web/src/glow_wrapping.rs

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
use crate::web_sys::{WebGl2RenderingContext, WebGlRenderingContext};
1+
#[cfg(not(target_arch = "wasm32"))]
2+
use crate::web_sys::WebGl2RenderingContext;
3+
use crate::web_sys::WebGlRenderingContext;
24
use crate::{canvas_element_or_die, console_error};
35
use egui::{ClippedMesh, Rgba, Texture};
46
use egui_glow::glow;
57
use epi::TextureAllocator;
8+
use wasm_bindgen::JsCast;
69
use wasm_bindgen::JsValue;
710
use web_sys::HtmlCanvasElement;
811

@@ -16,9 +19,29 @@ pub(crate) struct WrappedGlowPainter {
1619
impl WrappedGlowPainter {
1720
pub fn new(canvas_id: &str) -> Self {
1821
let canvas = canvas_element_or_die(canvas_id);
22+
// detect WebKitGTK
23+
//WebKitGTK currently support only webgl,so request webgl context.
24+
// WebKitGTK use WebKit default unmasked vendor and renderer
25+
// but safari use same vendor and renderer
26+
// so exclude "Mac OS X" user-agent.
27+
let gl = canvas
28+
.get_context("webgl")
29+
.unwrap()
30+
.unwrap()
31+
.dyn_into::<WebGlRenderingContext>()
32+
.unwrap();
33+
let user_agent = web_sys::window().unwrap().navigator().user_agent().unwrap();
34+
let webkit_gtk_wr = if !user_agent.contains("Mac OS X")
35+
&& crate::webgl1::detect_safari_and_webkit_gtk(&gl)
36+
{
37+
"#define WEBKITGTK_WORKAROUND"
38+
} else {
39+
""
40+
};
41+
1942
let gl_ctx = init_glow_context_from_canvas(&canvas);
2043
let dimension = [canvas.width() as i32, canvas.height() as i32];
21-
let painter = egui_glow::Painter::new(&gl_ctx, Some(dimension))
44+
let painter = egui_glow::Painter::new(&gl_ctx, Some(dimension), webkit_gtk_wr)
2245
.map_err(|error| {
2346
console_error(format!(
2447
"some error occurred in initializing glow painter\n {}",
@@ -82,7 +105,6 @@ impl crate::Painter for WrappedGlowPainter {
82105
}
83106

84107
pub fn init_glow_context_from_canvas(canvas: &HtmlCanvasElement) -> glow::Context {
85-
use wasm_bindgen::JsCast;
86108
let ctx = canvas.get_context("webgl2");
87109
if let Ok(ctx) = ctx {
88110
crate::console_log("webgl found");

egui_web/src/shader/post_fragment_100es.glsl

+4
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,8 @@ void main() {
1919
gl_FragColor = texture2D(u_sampler, v_tc);
2020

2121
gl_FragColor = srgba_from_linear(gl_FragColor) / 255.;
22+
#ifdef WEBKITGTK_WORKAROUND
23+
//this is better than double apply
24+
gl_FragColor = vec4(pow(gl_FragColor.rgb,vec3(1.0/2.2)),gl_FragColor.a);
25+
#endif
2226
}

egui_web/src/webgl1.rs

+42-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use {
33
wasm_bindgen::{prelude::*, JsCast},
44
web_sys::{
55
ExtSRgb, WebGlBuffer, WebGlFramebuffer, WebGlProgram, WebGlRenderingContext, WebGlShader,
6-
WebGlTexture,
6+
WebGlTexture, WebglDebugRendererInfo,
77
},
88
};
99

10+
use crate::console_log;
1011
use egui::{
1112
emath::vec2,
1213
epaint::{Color32, Texture},
@@ -591,6 +592,17 @@ impl PostProcess {
591592

592593
gl.bind_texture(Gl::TEXTURE_2D, None);
593594
gl.bind_framebuffer(Gl::FRAMEBUFFER, None);
595+
// detect WebKitGTK
596+
// WebKitGTK use WebKit default unmasked vendor and renderer
597+
// but safari use same vendor and renderer
598+
// so exclude "Mac OS X " user-agent.
599+
let user_agent = web_sys::window().unwrap().navigator().user_agent().unwrap();
600+
let webkit_gtk_wr = if !user_agent.contains("Mac OS X") && detect_safari_and_webkit_gtk(&gl)
601+
{
602+
"#define WEBKITGTK_WORKAROUND"
603+
} else {
604+
""
605+
};
594606

595607
let vert_shader = compile_shader(
596608
&gl,
@@ -600,7 +612,11 @@ impl PostProcess {
600612
let frag_shader = compile_shader(
601613
&gl,
602614
Gl::FRAGMENT_SHADER,
603-
include_str!("shader/post_fragment_100es.glsl"),
615+
&format!(
616+
"{}{}",
617+
webkit_gtk_wr,
618+
include_str!("shader/post_fragment_100es.glsl")
619+
),
604620
)?;
605621
let program = link_program(&gl, [vert_shader, frag_shader].iter())?;
606622

@@ -750,3 +766,27 @@ fn link_program<'a, T: IntoIterator<Item = &'a WebGlShader>>(
750766
.unwrap_or_else(|| "Unknown error creating program object".into()))
751767
}
752768
}
769+
770+
/// detecting Safari and webkitGTK.
771+
///
772+
/// Safari and webkitGTK use unmasked renderer :Apple GPU
773+
///
774+
/// If we detect safari or webkitGTK returns true.
775+
///
776+
/// This function used to avoid displaying linear color with `sRGB` supported systems.
777+
pub(crate) fn detect_safari_and_webkit_gtk(gl: &web_sys::WebGlRenderingContext) -> bool {
778+
if gl
779+
.get_extension("WEBGL_debug_renderer_info")
780+
.unwrap()
781+
.is_some()
782+
{
783+
let renderer: JsValue = gl
784+
.get_parameter(WebglDebugRendererInfo::UNMASKED_RENDERER_WEBGL)
785+
.unwrap();
786+
if renderer.as_string().unwrap().contains("Apple") {
787+
console_log("Enabling webkitGTK workaround");
788+
return true;
789+
}
790+
}
791+
false
792+
}

0 commit comments

Comments
 (0)