-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
native_texture.rs
139 lines (115 loc) · 5.14 KB
/
native_texture.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
use glium::glutin;
fn main() {
let event_loop = glutin::event_loop::EventLoopBuilder::with_user_event().build();
let display = create_display(&event_loop);
let mut egui_glium = egui_glium::EguiGlium::new(&display, &event_loop);
let png_data = include_bytes!("../../../examples/retained_image/src/rust-logo-256x256.png");
let image = load_glium_image(png_data);
let image_size = egui::vec2(image.width as f32, image.height as f32);
// Load to gpu memory
let glium_texture = glium::texture::SrgbTexture2d::new(&display, image).unwrap();
// Allow us to share the texture with egui:
let glium_texture = std::rc::Rc::new(glium_texture);
// Allocate egui's texture id for GL texture
let texture_id = egui_glium
.painter
.register_native_texture(glium_texture, Default::default());
// Setup button image size for reasonable image size for button container.
let button_image_size = egui::vec2(32_f32, 32_f32);
event_loop.run(move |event, _, control_flow| {
let mut redraw = || {
let mut quit = false;
let repaint_after = egui_glium.run(&display, |egui_ctx| {
egui::SidePanel::left("my_side_panel").show(egui_ctx, |ui| {
if ui
.add(egui::Button::image_and_text(
texture_id,
button_image_size,
"Quit",
))
.clicked()
{
quit = true;
}
});
egui::Window::new("NativeTextureDisplay").show(egui_ctx, |ui| {
ui.image(texture_id, image_size);
});
});
*control_flow = if quit {
glutin::event_loop::ControlFlow::Exit
} else if repaint_after.is_zero() {
display.gl_window().window().request_redraw();
glutin::event_loop::ControlFlow::Poll
} else if let Some(repaint_after_instant) =
std::time::Instant::now().checked_add(repaint_after)
{
glutin::event_loop::ControlFlow::WaitUntil(repaint_after_instant)
} else {
glutin::event_loop::ControlFlow::Wait
};
{
use glium::Surface as _;
let mut target = display.draw();
let color = egui::Rgba::from_rgb(0.1, 0.3, 0.2);
target.clear_color(color[0], color[1], color[2], color[3]);
// draw things behind egui here
egui_glium.paint(&display, &mut target);
// 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, .. } => {
use glutin::event::WindowEvent;
if matches!(event, WindowEvent::CloseRequested | WindowEvent::Destroyed) {
*control_flow = glutin::event_loop::ControlFlow::Exit;
}
let event_response = egui_glium.on_event(&event);
if event_response.repaint {
display.gl_window().window().request_redraw();
}
}
glutin::event::Event::NewEvents(glutin::event::StartCause::ResumeTimeReached {
..
}) => {
display.gl_window().window().request_redraw();
}
_ => (),
}
});
}
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_stencil_buffer(0)
.with_vsync(true);
glium::Display::new(window_builder, context_builder, event_loop).unwrap()
}
fn load_glium_image(png_data: &[u8]) -> glium::texture::RawImage2d<'_, u8> {
// Load image using the image crate:
let image = image::load_from_memory(png_data).unwrap().to_rgba8();
let image_dimensions = image.dimensions();
// Premultiply alpha:
let pixels: Vec<_> = image
.into_vec()
.chunks_exact(4)
.map(|p| egui::Color32::from_rgba_unmultiplied(p[0], p[1], p[2], p[3]))
.flat_map(|color| color.to_array())
.collect();
// Convert to glium image:
glium::texture::RawImage2d::from_raw_rgba(pixels, image_dimensions)
}