Add api for accessing backend texture via epi (#695)
* Define NativeTexture trait for offscreen rendering add demo for NativeTexture trait * write changelog * add comment for native texture example * formatting * add license of Rust logo * NativeTexture trait method rename remove duplicate function with native texture remove rust logo * deprecated notice for register_glium_texture,register_webgl_texture * collect deprecated notice
This commit is contained in:
parent
acf9d0114d
commit
203d571c8b
10 changed files with 227 additions and 5 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -1,5 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ab_glyph"
|
||||
version = "0.2.11"
|
||||
|
@ -829,6 +831,7 @@ dependencies = [
|
|||
"egui",
|
||||
"epi",
|
||||
"glium",
|
||||
"image",
|
||||
"ron",
|
||||
"serde",
|
||||
"tts",
|
||||
|
|
|
@ -5,7 +5,8 @@ All notable changes to the `egui_glium` integration will be noted in this file.
|
|||
|
||||
## Unreleased
|
||||
* Remove "http" feature (use https://github.com/emilk/ehttp instead!).
|
||||
|
||||
* Add `epi::NativeTexture` trait for glium painter
|
||||
* Deprecate 'Painter::register_glium_texture'
|
||||
|
||||
## 0.14.0 - 2021-08-24
|
||||
* Fix native file dialogs hanging (eg. when using [`rfd`](https://github.com/PolyMeilex/rfd)).
|
||||
|
|
|
@ -39,6 +39,8 @@ tts = { version = "0.17", optional = true }
|
|||
# feature "time"
|
||||
chrono = { version = "0.4", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
image = { version = "0.23", default-features = false, features = ["png"] }
|
||||
[features]
|
||||
default = ["default_fonts"]
|
||||
|
||||
|
|
111
egui_glium/examples/native_texture.rs
Normal file
111
egui_glium/examples/native_texture.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
//! Example how to use [epi::NativeTexture] with glium.
|
||||
use epi::NativeTexture;
|
||||
use glium::glutin;
|
||||
use std::io::Cursor;
|
||||
|
||||
fn create_display(event_loop: &glutin::event_loop::EventLoop<()>) -> glium::Display {
|
||||
let window_builder = glutin::window::WindowBuilder::new()
|
||||
.with_resizable(true)
|
||||
.with_inner_size(glutin::dpi::LogicalSize {
|
||||
width: 800.0,
|
||||
height: 600.0,
|
||||
})
|
||||
.with_title("egui_glium example");
|
||||
|
||||
let context_builder = glutin::ContextBuilder::new()
|
||||
.with_depth_buffer(0)
|
||||
.with_srgb(true)
|
||||
.with_stencil_buffer(0)
|
||||
.with_vsync(true);
|
||||
|
||||
glium::Display::new(window_builder, context_builder, event_loop).unwrap()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let event_loop = glutin::event_loop::EventLoop::with_user_event();
|
||||
let display = create_display(&event_loop);
|
||||
|
||||
let mut egui = egui_glium::EguiGlium::new(&display);
|
||||
//load image by image crate
|
||||
let image = image::load(
|
||||
Cursor::new(&include_bytes!("../../eframe/examples/rust-logo-512x512.png")[..]),
|
||||
image::ImageFormat::Png,
|
||||
)
|
||||
.unwrap()
|
||||
.to_rgba8();
|
||||
let image_dimensions = image.dimensions();
|
||||
//mark as image
|
||||
let image = glium::texture::RawImage2d::from_raw_rgba(image.into_raw(), image_dimensions);
|
||||
//load to gpu memory
|
||||
let native_texture = glium::texture::SrgbTexture2d::new(&display, image).unwrap();
|
||||
//allocate egui's texture id for GL texture
|
||||
let texture_id = egui.painter_mut().register_native_texture(native_texture);
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
let mut redraw = || {
|
||||
egui.begin_frame(&display);
|
||||
|
||||
let mut quit = false;
|
||||
|
||||
egui::SidePanel::left("my_side_panel").show(egui.ctx(), |ui| {
|
||||
ui.heading("");
|
||||
if ui.button("Quit").clicked() {
|
||||
quit = true;
|
||||
}
|
||||
});
|
||||
egui::Window::new("NativeTextureDisplay").show(egui.ctx(), |ui| {
|
||||
ui.image(texture_id, egui::Vec2::new(128.0, 128.0));
|
||||
});
|
||||
let (needs_repaint, shapes) = egui.end_frame(&display);
|
||||
|
||||
*control_flow = if quit {
|
||||
glutin::event_loop::ControlFlow::Exit
|
||||
} else if needs_repaint {
|
||||
display.gl_window().window().request_redraw();
|
||||
glutin::event_loop::ControlFlow::Poll
|
||||
} else {
|
||||
glutin::event_loop::ControlFlow::Wait
|
||||
};
|
||||
|
||||
{
|
||||
use glium::Surface as _;
|
||||
let mut target = display.draw();
|
||||
|
||||
let clear_color = egui::Rgba::from_rgb(0.1, 0.3, 0.2);
|
||||
target.clear_color(
|
||||
clear_color[0],
|
||||
clear_color[1],
|
||||
clear_color[2],
|
||||
clear_color[3],
|
||||
);
|
||||
|
||||
// draw things behind egui here
|
||||
|
||||
egui.paint(&display, &mut target, shapes);
|
||||
|
||||
// draw things on top of egui here
|
||||
|
||||
target.finish().unwrap();
|
||||
}
|
||||
};
|
||||
|
||||
match event {
|
||||
// Platform-dependent event handlers to workaround a winit bug
|
||||
// See: https://github.com/rust-windowing/winit/issues/987
|
||||
// See: https://github.com/rust-windowing/winit/issues/1619
|
||||
glutin::event::Event::RedrawEventsCleared if cfg!(windows) => redraw(),
|
||||
glutin::event::Event::RedrawRequested(_) if !cfg!(windows) => redraw(),
|
||||
|
||||
glutin::event::Event::WindowEvent { event, .. } => {
|
||||
if egui.is_quit_event(&event) {
|
||||
*control_flow = glium::glutin::event_loop::ControlFlow::Exit;
|
||||
}
|
||||
|
||||
egui.on_event(&event);
|
||||
|
||||
display.gl_window().window().request_redraw(); // TODO: ask egui if the events warrants a repaint instead
|
||||
}
|
||||
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
}
|
|
@ -40,7 +40,8 @@ use {
|
|||
std::hash::{Hash, Hasher},
|
||||
};
|
||||
|
||||
pub use copypasta::ClipboardContext; // TODO: remove
|
||||
pub use copypasta::ClipboardContext;
|
||||
use std::borrow::BorrowMut; // TODO: remove
|
||||
|
||||
pub struct GliumInputState {
|
||||
pub pointer_pos_in_points: Option<Pos2>,
|
||||
|
@ -644,4 +645,8 @@ impl EguiGlium {
|
|||
&self.egui_ctx.texture(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn painter_mut(&mut self) -> &mut Painter {
|
||||
self.painter.borrow_mut()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,8 +241,7 @@ impl Painter {
|
|||
id
|
||||
}
|
||||
|
||||
/// register glium texture as egui texture
|
||||
/// Usable for render to image rectangle
|
||||
#[deprecated = "Use: `NativeTexture::register_native_texture` instead"]
|
||||
pub fn register_glium_texture(
|
||||
&mut self,
|
||||
texture: glium::texture::SrgbTexture2d,
|
||||
|
@ -319,3 +318,31 @@ impl Painter {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl epi::NativeTexture for Painter {
|
||||
type Texture = glium::texture::srgb_texture2d::SrgbTexture2d;
|
||||
|
||||
fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId {
|
||||
let id = self.alloc_user_texture();
|
||||
if let egui::TextureId::User(id) = id {
|
||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) {
|
||||
*user_texture = UserTexture {
|
||||
pixels: vec![],
|
||||
gl_texture: Some(native),
|
||||
}
|
||||
}
|
||||
}
|
||||
id
|
||||
}
|
||||
|
||||
fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) {
|
||||
if let egui::TextureId::User(id) = id {
|
||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) {
|
||||
*user_texture = UserTexture {
|
||||
pixels: vec![],
|
||||
gl_texture: Some(replacing),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,11 @@ All notable changes to the `egui_web` integration will be noted in this file.
|
|||
|
||||
|
||||
## Unreleased
|
||||
* Remove "http" feature (use https://github.com/emilk/ehttp instead!).
|
||||
|
||||
### Added
|
||||
* Remove "http" feature (use https://github.com/emilk/ehttp instead!).
|
||||
* `epi::NativeTexture` trait for webgl1 webgl2 painter
|
||||
* Deprecate `Painter::register_webgl_texture`
|
||||
|
||||
## 0.14.1 - 2021-08-28
|
||||
|
||||
|
|
|
@ -223,6 +223,7 @@ impl WebGlPainter {
|
|||
}
|
||||
}
|
||||
|
||||
#[deprecated = "Use: `NativeTexture::register_native_texture` instead"]
|
||||
pub fn register_webgl_texture(&mut self, texture: WebGlTexture) -> egui::TextureId {
|
||||
let id = self.alloc_user_texture_index();
|
||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id) {
|
||||
|
@ -370,6 +371,34 @@ impl epi::TextureAllocator for WebGlPainter {
|
|||
}
|
||||
}
|
||||
|
||||
impl epi::NativeTexture for WebGlPainter {
|
||||
type Texture = WebGlTexture;
|
||||
|
||||
fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId {
|
||||
let id = self.alloc_user_texture_index();
|
||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id) {
|
||||
*user_texture = UserTexture {
|
||||
size: (0, 0),
|
||||
pixels: vec![],
|
||||
gl_texture: Some(native),
|
||||
}
|
||||
}
|
||||
egui::TextureId::User(id as u64)
|
||||
}
|
||||
|
||||
fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) {
|
||||
if let egui::TextureId::User(id) = id {
|
||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) {
|
||||
*user_texture = UserTexture {
|
||||
size: (0, 0),
|
||||
pixels: vec![],
|
||||
gl_texture: Some(replacing),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::Painter for WebGlPainter {
|
||||
fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator {
|
||||
self
|
||||
|
|
|
@ -202,6 +202,7 @@ impl WebGl2Painter {
|
|||
}
|
||||
}
|
||||
|
||||
#[deprecated = "Use: `NativeTexture::register_native_texture` instead"]
|
||||
pub fn register_webgl_texture(&mut self, texture: WebGlTexture) -> egui::TextureId {
|
||||
let id = self.alloc_user_texture_index();
|
||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id) {
|
||||
|
@ -349,6 +350,34 @@ impl epi::TextureAllocator for WebGl2Painter {
|
|||
}
|
||||
}
|
||||
|
||||
impl epi::NativeTexture for WebGl2Painter {
|
||||
type Texture = WebGlTexture;
|
||||
|
||||
fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId {
|
||||
let id = self.alloc_user_texture_index();
|
||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id) {
|
||||
*user_texture = UserTexture {
|
||||
size: (0, 0),
|
||||
pixels: vec![],
|
||||
gl_texture: Some(native),
|
||||
}
|
||||
}
|
||||
egui::TextureId::User(id as u64)
|
||||
}
|
||||
|
||||
fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture) {
|
||||
if let egui::TextureId::User(id) = id {
|
||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id as usize) {
|
||||
*user_texture = UserTexture {
|
||||
size: (0, 0),
|
||||
pixels: vec![],
|
||||
gl_texture: Some(replacing),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::Painter for WebGl2Painter {
|
||||
fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator {
|
||||
self
|
||||
|
|
|
@ -304,6 +304,18 @@ pub trait TextureAllocator {
|
|||
fn free(&mut self, id: egui::TextureId);
|
||||
}
|
||||
|
||||
/// Abstraction for platform dependent texture reference
|
||||
pub trait NativeTexture {
|
||||
type Texture;
|
||||
|
||||
/// Bind native texture to egui texture
|
||||
fn register_native_texture(&mut self, native: Self::Texture) -> egui::TextureId;
|
||||
|
||||
/// Change id's actual pointing texture
|
||||
/// only for user texture
|
||||
fn replace_native_texture(&mut self, id: egui::TextureId, replacing: Self::Texture);
|
||||
}
|
||||
|
||||
/// How to signal the [`egui`] integration that a repaint is required.
|
||||
pub trait RepaintSignal: Send + Sync {
|
||||
/// This signals the [`egui`] integration that a repaint is required.
|
||||
|
|
Loading…
Reference in a new issue