Take Glow context using Arc. (#1640)
This allows usage with a Glow context that is passed between threads.
This commit is contained in:
parent
a29154233b
commit
b2510676b9
11 changed files with 27 additions and 31 deletions
|
@ -37,3 +37,6 @@ opt-level = 2 # fast and small wasm, basically same as `opt-level = 's'`
|
||||||
# opt-level = 3 # unecessarily large wasm for no performance gain
|
# opt-level = 3 # unecessarily large wasm for no performance gain
|
||||||
|
|
||||||
# debug = true # include debug symbols, useful when profiling wasm
|
# debug = true # include debug symbols, useful when profiling wasm
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
three-d = { git = "https://github.com/asny/three-d.git", rev = "7ac4f3e1e14335290e505a5799a0b88717474678" }
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub struct CreationContext<'s> {
|
||||||
/// The [`glow::Context`] allows you to initialize OpenGL resources (e.g. shaders) that
|
/// The [`glow::Context`] allows you to initialize OpenGL resources (e.g. shaders) that
|
||||||
/// you might want to use later from a [`egui::PaintCallback`].
|
/// you might want to use later from a [`egui::PaintCallback`].
|
||||||
#[cfg(feature = "glow")]
|
#[cfg(feature = "glow")]
|
||||||
pub gl: Option<std::rc::Rc<glow::Context>>,
|
pub gl: Option<std::sync::Arc<glow::Context>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -334,7 +334,7 @@ pub struct Frame {
|
||||||
/// A reference to the underlying [`glow`] (OpenGL) context.
|
/// A reference to the underlying [`glow`] (OpenGL) context.
|
||||||
#[cfg(feature = "glow")]
|
#[cfg(feature = "glow")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub gl: Option<std::rc::Rc<glow::Context>>,
|
pub gl: Option<std::sync::Arc<glow::Context>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
|
@ -371,7 +371,7 @@ impl Frame {
|
||||||
/// To get a [`glow`] context you need to compile with the `glow` feature flag,
|
/// To get a [`glow`] context you need to compile with the `glow` feature flag,
|
||||||
/// and run eframe with the glow backend.
|
/// and run eframe with the glow backend.
|
||||||
#[cfg(feature = "glow")]
|
#[cfg(feature = "glow")]
|
||||||
pub fn gl(&self) -> Option<&std::rc::Rc<glow::Context>> {
|
pub fn gl(&self) -> Option<&std::sync::Arc<glow::Context>> {
|
||||||
self.gl.as_ref()
|
self.gl.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,7 @@ impl EpiIntegration {
|
||||||
max_texture_side: usize,
|
max_texture_side: usize,
|
||||||
window: &winit::window::Window,
|
window: &winit::window::Window,
|
||||||
storage: Option<Box<dyn epi::Storage>>,
|
storage: Option<Box<dyn epi::Storage>>,
|
||||||
#[cfg(feature = "glow")] gl: Option<std::rc::Rc<glow::Context>>,
|
#[cfg(feature = "glow")] gl: Option<std::sync::Arc<glow::Context>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let egui_ctx = egui::Context::default();
|
let egui_ctx = egui::Context::default();
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub fn run_glow(
|
||||||
let window_builder =
|
let window_builder =
|
||||||
epi_integration::window_builder(native_options, &window_settings).with_title(app_name);
|
epi_integration::window_builder(native_options, &window_settings).with_title(app_name);
|
||||||
let (gl_window, gl) = create_display(native_options, window_builder, &event_loop);
|
let (gl_window, gl) = create_display(native_options, window_builder, &event_loop);
|
||||||
let gl = std::rc::Rc::new(gl);
|
let gl = std::sync::Arc::new(gl);
|
||||||
|
|
||||||
let mut painter = egui_glow::Painter::new(gl.clone(), None, "")
|
let mut painter = egui_glow::Painter::new(gl.clone(), None, "")
|
||||||
.unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error));
|
.unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error));
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl WrappedGlowPainter {
|
||||||
let canvas = super::canvas_element_or_die(canvas_id);
|
let canvas = super::canvas_element_or_die(canvas_id);
|
||||||
|
|
||||||
let (gl, shader_prefix) = init_glow_context_from_canvas(&canvas)?;
|
let (gl, shader_prefix) = init_glow_context_from_canvas(&canvas)?;
|
||||||
let gl = std::rc::Rc::new(gl);
|
let gl = std::sync::Arc::new(gl);
|
||||||
|
|
||||||
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, Some(dimension), shader_prefix)
|
let painter = egui_glow::Painter::new(gl, Some(dimension), shader_prefix)
|
||||||
|
@ -32,7 +32,7 @@ impl WrappedGlowPainter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WrappedGlowPainter {
|
impl WrappedGlowPainter {
|
||||||
pub fn gl(&self) -> &std::rc::Rc<glow::Context> {
|
pub fn gl(&self) -> &std::sync::Arc<glow::Context> {
|
||||||
self.painter.gl()
|
self.painter.gl()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ fn main() {
|
||||||
|
|
||||||
let event_loop = glutin::event_loop::EventLoop::with_user_event();
|
let event_loop = glutin::event_loop::EventLoop::with_user_event();
|
||||||
let (gl_window, gl) = create_display(&event_loop);
|
let (gl_window, gl) = create_display(&event_loop);
|
||||||
let gl = std::rc::Rc::new(gl);
|
let gl = std::sync::Arc::new(gl);
|
||||||
|
|
||||||
let mut egui_glow = egui_glow::EguiGlow::new(gl_window.window(), gl.clone());
|
let mut egui_glow = egui_glow::EguiGlow::new(gl_window.window(), gl.clone());
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use std::{collections::HashMap, rc::Rc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use egui::{
|
use egui::{
|
||||||
emath::Rect,
|
emath::Rect,
|
||||||
|
@ -42,7 +42,7 @@ impl TextureFilterExt for TextureFilter {
|
||||||
/// This struct must be destroyed with [`Painter::destroy`] before dropping, to ensure OpenGL
|
/// This struct must be destroyed with [`Painter::destroy`] before dropping, to ensure OpenGL
|
||||||
/// objects have been properly deleted and are not leaked.
|
/// objects have been properly deleted and are not leaked.
|
||||||
pub struct Painter {
|
pub struct Painter {
|
||||||
gl: Rc<glow::Context>,
|
gl: Arc<glow::Context>,
|
||||||
|
|
||||||
max_texture_side: usize,
|
max_texture_side: usize,
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ impl Painter {
|
||||||
/// * 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(
|
pub fn new(
|
||||||
gl: Rc<glow::Context>,
|
gl: Arc<glow::Context>,
|
||||||
pp_fb_extent: Option<[i32; 2]>,
|
pp_fb_extent: Option<[i32; 2]>,
|
||||||
shader_prefix: &str,
|
shader_prefix: &str,
|
||||||
) -> Result<Painter, String> {
|
) -> Result<Painter, String> {
|
||||||
|
@ -219,7 +219,7 @@ impl Painter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the shared glow context.
|
/// Access the shared glow context.
|
||||||
pub fn gl(&self) -> &std::rc::Rc<glow::Context> {
|
pub fn gl(&self) -> &Arc<glow::Context> {
|
||||||
&self.gl
|
&self.gl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use glow::HasContext as _;
|
||||||
/// Uses a framebuffer to render everything in linear color space and convert it back to `sRGB`
|
/// Uses a framebuffer to render everything in linear color space and convert it back to `sRGB`
|
||||||
/// in a separate "post processing" step
|
/// in a separate "post processing" step
|
||||||
pub(crate) struct PostProcess {
|
pub(crate) struct PostProcess {
|
||||||
gl: std::rc::Rc<glow::Context>,
|
gl: std::sync::Arc<glow::Context>,
|
||||||
pos_buffer: glow::Buffer,
|
pos_buffer: glow::Buffer,
|
||||||
index_buffer: glow::Buffer,
|
index_buffer: glow::Buffer,
|
||||||
vao: crate::vao::VertexArrayObject,
|
vao: crate::vao::VertexArrayObject,
|
||||||
|
@ -21,7 +21,7 @@ pub(crate) struct PostProcess {
|
||||||
|
|
||||||
impl PostProcess {
|
impl PostProcess {
|
||||||
pub(crate) unsafe fn new(
|
pub(crate) unsafe fn new(
|
||||||
gl: std::rc::Rc<glow::Context>,
|
gl: std::sync::Arc<glow::Context>,
|
||||||
shader_prefix: &str,
|
shader_prefix: &str,
|
||||||
is_webgl_1: bool,
|
is_webgl_1: bool,
|
||||||
[width, height]: [i32; 2],
|
[width, height]: [i32; 2],
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub struct EguiGlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EguiGlow {
|
impl EguiGlow {
|
||||||
pub fn new(window: &winit::window::Window, gl: std::rc::Rc<glow::Context>) -> Self {
|
pub fn new(window: &winit::window::Window, gl: std::sync::Arc<glow::Context>) -> Self {
|
||||||
let painter = crate::Painter::new(gl, None, "")
|
let painter = crate::Painter::new(gl, None, "")
|
||||||
.map_err(|error| {
|
.map_err(|error| {
|
||||||
tracing::error!("error occurred in initializing painter:\n{}", error);
|
tracing::error!("error occurred in initializing painter:\n{}", error);
|
||||||
|
|
|
@ -12,4 +12,4 @@ publish = false
|
||||||
eframe = { path = "../../eframe", features = ["glow"] }
|
eframe = { path = "../../eframe", features = ["glow"] }
|
||||||
egui_glow = { path = "../../egui_glow" }
|
egui_glow = { path = "../../egui_glow" }
|
||||||
glow = "0.11"
|
glow = "0.11"
|
||||||
three-d = { version = "0.11", default-features = false }
|
three-d = { version = "0.12", default-features = false }
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl MyApp {
|
||||||
/// to the [`egui::PaintCallback`] because [`three_d::Context`] isn't `Send+Sync`, which
|
/// to the [`egui::PaintCallback`] because [`three_d::Context`] isn't `Send+Sync`, which
|
||||||
/// [`egui::PaintCallback`] is.
|
/// [`egui::PaintCallback`] is.
|
||||||
fn with_three_d_context<R>(
|
fn with_three_d_context<R>(
|
||||||
gl: &std::rc::Rc<glow::Context>,
|
gl: &std::sync::Arc<glow::Context>,
|
||||||
f: impl FnOnce(&three_d::Context) -> R,
|
f: impl FnOnce(&three_d::Context) -> R,
|
||||||
) -> R {
|
) -> R {
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -111,15 +111,12 @@ fn paint_with_three_d(three_d: &three_d::Context, info: &egui::PaintCallbackInfo
|
||||||
|
|
||||||
// Respect the egui clip region (e.g. if we are inside an `egui::ScrollArea`).
|
// Respect the egui clip region (e.g. if we are inside an `egui::ScrollArea`).
|
||||||
let clip_rect = info.clip_rect_in_pixels();
|
let clip_rect = info.clip_rect_in_pixels();
|
||||||
let render_states = RenderStates {
|
three_d.set_scissor(ScissorBox {
|
||||||
clip: Clip::Enabled {
|
x: clip_rect.left_px.round() as _,
|
||||||
x: clip_rect.left_px.round() as _,
|
y: clip_rect.from_bottom_px.round() as _,
|
||||||
y: clip_rect.from_bottom_px.round() as _,
|
width: clip_rect.width_px.round() as _,
|
||||||
width: clip_rect.width_px.round() as _,
|
height: clip_rect.height_px.round() as _,
|
||||||
height: clip_rect.height_px.round() as _,
|
});
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let camera = Camera::new_perspective(
|
let camera = Camera::new_perspective(
|
||||||
three_d,
|
three_d,
|
||||||
|
@ -150,11 +147,7 @@ fn paint_with_three_d(three_d: &three_d::Context, info: &egui::PaintCallbackInfo
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let material = ColorMaterial {
|
let mut model = Model::new(three_d, &cpu_mesh).unwrap();
|
||||||
render_states,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let mut model = Model::new_with_material(three_d, &cpu_mesh, material).unwrap();
|
|
||||||
|
|
||||||
// Set the current transformation of the triangle
|
// Set the current transformation of the triangle
|
||||||
model.set_transformation(Mat4::from_angle_y(radians(angle)));
|
model.set_transformation(Mat4::from_angle_y(radians(angle)));
|
||||||
|
|
Loading…
Reference in a new issue