Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix wrong gamma in WebkitGTK #888

Merged
merged 12 commits into from
Nov 13, 2021
Merged
2 changes: 1 addition & 1 deletion egui_glow/src/epi_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub fn run(app: Box<dyn epi::App>, native_options: &epi::NativeOptions) -> ! {
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))
.unwrap();
let mut integration = egui_winit::epi::EpiIntegration::new(
Expand Down
2 changes: 1 addition & 1 deletion egui_glow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ impl EguiGlow {
Self {
egui_ctx: Default::default(),
egui_winit: egui_winit::State::new(gl_window.window()),
painter: crate::Painter::new(gl, None)
painter: crate::Painter::new(gl, None, "")
.map_err(|error| {
eprintln!("some error occurred in initializing painter\n{}", error);
})
Expand Down
9 changes: 5 additions & 4 deletions egui_glow/src/misc_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 es_sig = "OpenGL ES ";
let version_string = gl.get_parameter_string(glow::VERSION);
Expand All @@ -200,7 +201,7 @@ pub(crate) unsafe fn need_to_emulate_vao(gl: &glow::Context) -> bool {
gl.supported_extensions()
.contains("OES_vertex_array_object")
} else {
false
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
Expand All @@ -214,7 +215,7 @@ pub(crate) unsafe fn need_to_emulate_vao(gl: &glow::Context) -> bool {
gl.supported_extensions()
.contains("OES_vertex_array_object")
} else {
false
true
}
} else {
glow_debug_print(format!("detected OpenGL:{}", version_string));
Expand All @@ -225,7 +226,7 @@ pub(crate) unsafe fn need_to_emulate_vao(gl: &glow::Context) -> bool {
gl.supported_extensions()
.contains("ARB_vertex_array_object")
} else {
false
true
}
}
}
27 changes: 19 additions & 8 deletions egui_glow/src/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,26 @@ impl Painter {
/// Create painter.
///
/// 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
/// will return `Err` below cases
/// * failed to compile shader
/// * failed to create postprocess on webgl with `sRGB` support
/// * failed to create buffer
pub fn new(gl: &glow::Context, pp_fb_extent: Option<[i32; 2]>) -> Result<Painter, String> {
let need_to_emulate_vao = unsafe { crate::misc_util::need_to_emulate_vao(gl) };
pub fn new(
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 is_webgl_1 = shader_version == ShaderVersion::Es100;
let header = shader_version.version();
glow_debug_print(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
(ShaderVersion::Es300, _) | (ShaderVersion::Es100, true) => unsafe {
Expand All @@ -83,7 +91,8 @@ impl Painter {
(
Some(PostProcess::new(
gl,
need_to_emulate_vao,
shader_prefix,
support_vao,
is_webgl_1,
width,
height,
Expand All @@ -106,8 +115,9 @@ impl Painter {
gl,
glow::VERTEX_SHADER,
&format!(
"{}\n{}\n{}",
"{}\n{}\n{}\n{}",
header,
shader_prefix,
shader_version.is_new_shader_interface(),
VERT_SRC
),
Expand All @@ -116,8 +126,9 @@ impl Painter {
gl,
glow::FRAGMENT_SHADER,
&format!(
"{}\n{}\n{}\n{}",
"{}\n{}\n{}\n{}\n{}",
header,
shader_prefix,
srgb_support_define,
shader_version.is_new_shader_interface(),
FRAG_SRC
Expand All @@ -136,10 +147,10 @@ impl Painter {
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_srgba_loc = gl.get_attrib_location(program, "a_srgba").unwrap();
let mut vertex_array = if need_to_emulate_vao {
crate::misc_util::VAO::emulated()
} else {
let mut vertex_array = if support_vao {
crate::misc_util::VAO::native(gl)
} else {
crate::misc_util::VAO::emulated()
};
vertex_array.bind_vertex_array(gl);
vertex_array.bind_buffer(gl, &vertex_buffer);
Expand Down
13 changes: 11 additions & 2 deletions egui_glow/src/post_process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub(crate) struct PostProcess {
impl PostProcess {
pub(crate) unsafe fn new(
gl: &glow::Context,
shader_prefix: &str,
need_to_emulate_vao: bool,
is_webgl_1: bool,
width: i32,
Expand Down Expand Up @@ -96,12 +97,20 @@ impl PostProcess {
let vert_shader = compile_shader(
gl,
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(
gl,
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())?;

Expand Down
4 changes: 4 additions & 0 deletions egui_glow/src/shader/post_fragment_100es.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ void main() {
gl_FragColor = texture2D(u_sampler, v_tc);

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 changes: 2 additions & 1 deletion egui_web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ All notable changes to the `egui_web` integration will be noted in this file.


## 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
### Added
Expand Down
1 change: 1 addition & 0 deletions egui_web/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ features = [
"TouchList",
"WebGl2RenderingContext",
"WebGlBuffer",
"WebglDebugRendererInfo",
"WebGlFramebuffer",
"WebGlProgram",
"WebGlRenderingContext",
Expand Down
28 changes: 25 additions & 3 deletions egui_web/src/glow_wrapping.rs
Original file line number Diff line number Diff line change
@@ -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 egui::{ClippedMesh, Rgba, Texture};
use egui_glow::glow;
use epi::TextureAllocator;
use wasm_bindgen::JsCast;
use wasm_bindgen::JsValue;
use web_sys::HtmlCanvasElement;

Expand All @@ -16,9 +19,29 @@ pub(crate) struct WrappedGlowPainter {
impl WrappedGlowPainter {
pub fn new(canvas_id: &str) -> Self {
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 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| {
console_error(format!(
"some error occurred in initializing glow painter\n {}",
Expand Down Expand Up @@ -82,7 +105,6 @@ impl crate::Painter for WrappedGlowPainter {
}

pub fn init_glow_context_from_canvas(canvas: &HtmlCanvasElement) -> glow::Context {
use wasm_bindgen::JsCast;
let ctx = canvas.get_context("webgl2");
if let Ok(ctx) = ctx {
crate::console_log("webgl found");
Expand Down
4 changes: 4 additions & 0 deletions egui_web/src/shader/post_fragment_100es.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ void main() {
gl_FragColor = texture2D(u_sampler, v_tc);

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
}
44 changes: 42 additions & 2 deletions egui_web/src/webgl1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use {
wasm_bindgen::{prelude::*, JsCast},
web_sys::{
ExtSRgb, WebGlBuffer, WebGlFramebuffer, WebGlProgram, WebGlRenderingContext, WebGlShader,
WebGlTexture,
WebGlTexture, WebglDebugRendererInfo,
},
};

use crate::console_log;
use egui::{
emath::vec2,
epaint::{Color32, Texture},
Expand Down Expand Up @@ -591,6 +592,17 @@ impl PostProcess {

gl.bind_texture(Gl::TEXTURE_2D, 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(
&gl,
Expand All @@ -600,7 +612,11 @@ impl PostProcess {
let frag_shader = compile_shader(
&gl,
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())?;

Expand Down Expand Up @@ -750,3 +766,27 @@ fn link_program<'a, T: IntoIterator<Item = &'a WebGlShader>>(
.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
}