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.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ab_glyph"
|
name = "ab_glyph"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
|
@ -829,6 +831,7 @@ dependencies = [
|
||||||
"egui",
|
"egui",
|
||||||
"epi",
|
"epi",
|
||||||
"glium",
|
"glium",
|
||||||
|
"image",
|
||||||
"ron",
|
"ron",
|
||||||
"serde",
|
"serde",
|
||||||
"tts",
|
"tts",
|
||||||
|
|
|
@ -5,7 +5,8 @@ All notable changes to the `egui_glium` integration will be noted in this file.
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
* Remove "http" feature (use https://github.com/emilk/ehttp instead!).
|
* 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
|
## 0.14.0 - 2021-08-24
|
||||||
* Fix native file dialogs hanging (eg. when using [`rfd`](https://github.com/PolyMeilex/rfd)).
|
* 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"
|
# feature "time"
|
||||||
chrono = { version = "0.4", optional = true }
|
chrono = { version = "0.4", optional = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
image = { version = "0.23", default-features = false, features = ["png"] }
|
||||||
[features]
|
[features]
|
||||||
default = ["default_fonts"]
|
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},
|
std::hash::{Hash, Hasher},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use copypasta::ClipboardContext; // TODO: remove
|
pub use copypasta::ClipboardContext;
|
||||||
|
use std::borrow::BorrowMut; // TODO: remove
|
||||||
|
|
||||||
pub struct GliumInputState {
|
pub struct GliumInputState {
|
||||||
pub pointer_pos_in_points: Option<Pos2>,
|
pub pointer_pos_in_points: Option<Pos2>,
|
||||||
|
@ -644,4 +645,8 @@ impl EguiGlium {
|
||||||
&self.egui_ctx.texture(),
|
&self.egui_ctx.texture(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn painter_mut(&mut self) -> &mut Painter {
|
||||||
|
self.painter.borrow_mut()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,8 +241,7 @@ impl Painter {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
/// register glium texture as egui texture
|
#[deprecated = "Use: `NativeTexture::register_native_texture` instead"]
|
||||||
/// Usable for render to image rectangle
|
|
||||||
pub fn register_glium_texture(
|
pub fn register_glium_texture(
|
||||||
&mut self,
|
&mut self,
|
||||||
texture: glium::texture::SrgbTexture2d,
|
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
|
## 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
|
## 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 {
|
pub fn register_webgl_texture(&mut self, texture: WebGlTexture) -> egui::TextureId {
|
||||||
let id = self.alloc_user_texture_index();
|
let id = self.alloc_user_texture_index();
|
||||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id) {
|
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 {
|
impl crate::Painter for WebGlPainter {
|
||||||
fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator {
|
fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator {
|
||||||
self
|
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 {
|
pub fn register_webgl_texture(&mut self, texture: WebGlTexture) -> egui::TextureId {
|
||||||
let id = self.alloc_user_texture_index();
|
let id = self.alloc_user_texture_index();
|
||||||
if let Some(Some(user_texture)) = self.user_textures.get_mut(id) {
|
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 {
|
impl crate::Painter for WebGl2Painter {
|
||||||
fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator {
|
fn as_tex_allocator(&mut self) -> &mut dyn epi::TextureAllocator {
|
||||||
self
|
self
|
||||||
|
|
|
@ -304,6 +304,18 @@ pub trait TextureAllocator {
|
||||||
fn free(&mut self, id: egui::TextureId);
|
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.
|
/// How to signal the [`egui`] integration that a repaint is required.
|
||||||
pub trait RepaintSignal: Send + Sync {
|
pub trait RepaintSignal: Send + Sync {
|
||||||
/// This signals the [`egui`] integration that a repaint is required.
|
/// This signals the [`egui`] integration that a repaint is required.
|
||||||
|
|
Loading…
Reference in a new issue