anvil: Properly free textures
This commit is contained in:
parent
85bef5fec6
commit
0661ebebb8
|
@ -1,5 +1,5 @@
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc, sync::mpsc::Sender};
|
||||||
|
|
||||||
#[cfg(feature = "udev")]
|
#[cfg(feature = "udev")]
|
||||||
use smithay::backend::renderer::{Renderer, Texture};
|
use smithay::backend::renderer::{Renderer, Texture};
|
||||||
|
@ -86,6 +86,7 @@ impl BufferUtils {
|
||||||
Ok(BufferTextures {
|
Ok(BufferTextures {
|
||||||
buffer,
|
buffer,
|
||||||
textures: HashMap::new(),
|
textures: HashMap::new(),
|
||||||
|
callbacks: HashMap::new(),
|
||||||
egl: egl_buffer, // I guess we need to keep this alive ?
|
egl: egl_buffer, // I guess we need to keep this alive ?
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -103,6 +104,7 @@ impl BufferUtils {
|
||||||
pub struct BufferTextures<T> {
|
pub struct BufferTextures<T> {
|
||||||
buffer: WlBuffer,
|
buffer: WlBuffer,
|
||||||
pub textures: HashMap<dev_t, T>,
|
pub textures: HashMap<dev_t, T>,
|
||||||
|
callbacks: HashMap<dev_t, Sender<T>>,
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
egl: Option<EGLBuffer>,
|
egl: Option<EGLBuffer>,
|
||||||
}
|
}
|
||||||
|
@ -110,10 +112,11 @@ pub struct BufferTextures<T> {
|
||||||
#[cfg(feature = "udev")]
|
#[cfg(feature = "udev")]
|
||||||
impl<T: Texture> BufferTextures<T> {
|
impl<T: Texture> BufferTextures<T> {
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
pub fn load_texture<'a, R: Renderer<Texture=T>>(
|
pub fn load_texture<'a, R: Renderer<TextureId=T>>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
id: u64,
|
id: u64,
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
|
texture_destruction_callback: &Sender<T>,
|
||||||
) -> Result<&'a T, R::Error> {
|
) -> Result<&'a T, R::Error> {
|
||||||
if self.textures.contains_key(&id) {
|
if self.textures.contains_key(&id) {
|
||||||
return Ok(&self.textures[&id]);
|
return Ok(&self.textures[&id]);
|
||||||
|
@ -122,10 +125,13 @@ impl<T: Texture> BufferTextures<T> {
|
||||||
if let Some(buffer) = self.egl.as_ref() {
|
if let Some(buffer) = self.egl.as_ref() {
|
||||||
//EGL buffer
|
//EGL buffer
|
||||||
let texture = renderer.import_egl(&buffer)?;
|
let texture = renderer.import_egl(&buffer)?;
|
||||||
self.textures.insert(id, texture);
|
if let Some(old_texture) = self.textures.insert(id, texture) {
|
||||||
|
let _ = renderer.destroy_texture(old_texture);
|
||||||
|
}
|
||||||
|
self.callbacks.insert(id, texture_destruction_callback.clone());
|
||||||
Ok(&self.textures[&id])
|
Ok(&self.textures[&id])
|
||||||
} else {
|
} else {
|
||||||
self.load_shm_texture(id, renderer)
|
self.load_shm_texture(id, renderer, texture_destruction_callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,22 +140,27 @@ impl<T: Texture> BufferTextures<T> {
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
id: u64,
|
id: u64,
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
|
texture_destruction_callback: &Sender<T>,
|
||||||
) -> Result<&'a T, R::Error> {
|
) -> Result<&'a T, R::Error> {
|
||||||
if self.textures.contains_key(&id) {
|
if self.textures.contains_key(&id) {
|
||||||
return Ok(&self.textures[&id]);
|
return Ok(&self.textures[&id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.load_shm_texture(id, renderer)
|
self.load_shm_texture(id, renderer, texture_destruction_callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_shm_texture<'a, R: Renderer<Texture=T>>(
|
fn load_shm_texture<'a, R: Renderer<TextureId=T>>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
id: u64,
|
id: u64,
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
|
texture_destruction_callback: &Sender<T>,
|
||||||
) -> Result<&'a T, R::Error> {
|
) -> Result<&'a T, R::Error> {
|
||||||
let texture = renderer.import_shm(&self.buffer)?;
|
let texture = renderer.import_shm(&self.buffer)?;
|
||||||
|
|
||||||
self.textures.insert(id, texture);
|
if let Some(old_texture) = self.textures.insert(id, texture) {
|
||||||
|
let _ = renderer.destroy_texture(old_texture)?;
|
||||||
|
}
|
||||||
|
self.callbacks.insert(id, texture_destruction_callback.clone());
|
||||||
Ok(&self.textures[&id])
|
Ok(&self.textures[&id])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +168,9 @@ impl<T: Texture> BufferTextures<T> {
|
||||||
#[cfg(feature = "udev")]
|
#[cfg(feature = "udev")]
|
||||||
impl<T> Drop for BufferTextures<T> {
|
impl<T> Drop for BufferTextures<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.buffer.release()
|
self.buffer.release();
|
||||||
|
for (id, texture) in self.textures.drain() {
|
||||||
|
self.callbacks.get(&id).unwrap().send(texture).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
sync::mpsc::Sender,
|
||||||
};
|
};
|
||||||
|
|
||||||
use slog::Logger;
|
use slog::Logger;
|
||||||
|
@ -25,6 +26,7 @@ use crate::buffer_utils::{BufferUtils, BufferTextures};
|
||||||
pub fn draw_cursor<R, E, T>(
|
pub fn draw_cursor<R, E, T>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
renderer_id: u64,
|
renderer_id: u64,
|
||||||
|
texture_destruction_callback: &Sender<T>,
|
||||||
buffer_utils: &BufferUtils,
|
buffer_utils: &BufferUtils,
|
||||||
surface: &wl_surface::WlSurface,
|
surface: &wl_surface::WlSurface,
|
||||||
(x, y): (i32, i32),
|
(x, y): (i32, i32),
|
||||||
|
@ -32,7 +34,7 @@ pub fn draw_cursor<R, E, T>(
|
||||||
log: &Logger,
|
log: &Logger,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
R: Renderer<Error=E, Texture=T>,
|
R: Renderer<Error=E, TextureId=T>,
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
T: Texture + 'static,
|
T: Texture + 'static,
|
||||||
{
|
{
|
||||||
|
@ -46,12 +48,13 @@ pub fn draw_cursor<R, E, T>(
|
||||||
(0, 0)
|
(0, 0)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
draw_surface_tree(renderer, renderer_id, buffer_utils, surface, (x - dx, y - dy), token, log);
|
draw_surface_tree(renderer, renderer_id, texture_destruction_callback, buffer_utils, surface, (x - dx, y - dy), token, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_surface_tree<R, E, T>(
|
fn draw_surface_tree<R, E, T>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
renderer_id: u64,
|
renderer_id: u64,
|
||||||
|
texture_destruction_callback: &Sender<T>,
|
||||||
buffer_utils: &BufferUtils,
|
buffer_utils: &BufferUtils,
|
||||||
root: &wl_surface::WlSurface,
|
root: &wl_surface::WlSurface,
|
||||||
location: (i32, i32),
|
location: (i32, i32),
|
||||||
|
@ -59,7 +62,7 @@ fn draw_surface_tree<R, E, T>(
|
||||||
log: &Logger,
|
log: &Logger,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
R: Renderer<Error=E, Texture=T>,
|
R: Renderer<Error=E, TextureId=T>,
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
T: Texture + 'static,
|
T: Texture + 'static,
|
||||||
{
|
{
|
||||||
|
@ -72,7 +75,7 @@ fn draw_surface_tree<R, E, T>(
|
||||||
let mut data = data.borrow_mut();
|
let mut data = data.borrow_mut();
|
||||||
if data.texture.is_none() {
|
if data.texture.is_none() {
|
||||||
if let Some(buffer) = data.current_state.buffer.take() {
|
if let Some(buffer) = data.current_state.buffer.take() {
|
||||||
match buffer_utils.load_buffer::<R::Texture>(buffer) {
|
match buffer_utils.load_buffer::<R::TextureId>(buffer) {
|
||||||
Ok(m) => data.texture = Some(Box::new(m) as Box<dyn std::any::Any + 'static>),
|
Ok(m) => data.texture = Some(Box::new(m) as Box<dyn std::any::Any + 'static>),
|
||||||
// there was an error reading the buffer, release it, we
|
// there was an error reading the buffer, release it, we
|
||||||
// already logged the error
|
// already logged the error
|
||||||
|
@ -133,7 +136,7 @@ fn draw_surface_tree<R, E, T>(
|
||||||
x += sub_x;
|
x += sub_x;
|
||||||
y += sub_y;
|
y += sub_y;
|
||||||
}
|
}
|
||||||
let texture = buffer_textures.load_texture(renderer_id, renderer).unwrap();
|
let texture = buffer_textures.load_texture(renderer_id, renderer, texture_destruction_callback).unwrap();
|
||||||
renderer.render_texture_at(texture, (x, y), Transform::Normal /* TODO */, 1.0);
|
renderer.render_texture_at(texture, (x, y), Transform::Normal /* TODO */, 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,6 +148,7 @@ fn draw_surface_tree<R, E, T>(
|
||||||
pub fn draw_windows<R, E, T>(
|
pub fn draw_windows<R, E, T>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
renderer_id: u64,
|
renderer_id: u64,
|
||||||
|
texture_destruction_callback: &Sender<T>,
|
||||||
buffer_utils: &BufferUtils,
|
buffer_utils: &BufferUtils,
|
||||||
window_map: &MyWindowMap,
|
window_map: &MyWindowMap,
|
||||||
output_rect: Option<Rectangle>,
|
output_rect: Option<Rectangle>,
|
||||||
|
@ -152,7 +156,7 @@ pub fn draw_windows<R, E, T>(
|
||||||
log: &::slog::Logger,
|
log: &::slog::Logger,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
R: Renderer<Error=E, Texture=T>,
|
R: Renderer<Error=E, TextureId=T>,
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
T: Texture + 'static,
|
T: Texture + 'static,
|
||||||
{
|
{
|
||||||
|
@ -172,6 +176,7 @@ pub fn draw_windows<R, E, T>(
|
||||||
draw_surface_tree(
|
draw_surface_tree(
|
||||||
renderer,
|
renderer,
|
||||||
renderer_id,
|
renderer_id,
|
||||||
|
texture_destruction_callback,
|
||||||
buffer_utils,
|
buffer_utils,
|
||||||
&wl_surface,
|
&wl_surface,
|
||||||
initial_place,
|
initial_place,
|
||||||
|
@ -187,6 +192,7 @@ pub fn draw_windows<R, E, T>(
|
||||||
pub fn draw_dnd_icon<R, E, T>(
|
pub fn draw_dnd_icon<R, E, T>(
|
||||||
renderer: &mut R,
|
renderer: &mut R,
|
||||||
renderer_id: u64,
|
renderer_id: u64,
|
||||||
|
texture_destruction_callback: &Sender<T>,
|
||||||
buffer_utils: &BufferUtils,
|
buffer_utils: &BufferUtils,
|
||||||
surface: &wl_surface::WlSurface,
|
surface: &wl_surface::WlSurface,
|
||||||
(x, y): (i32, i32),
|
(x, y): (i32, i32),
|
||||||
|
@ -194,7 +200,7 @@ pub fn draw_dnd_icon<R, E, T>(
|
||||||
log: &::slog::Logger,
|
log: &::slog::Logger,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
R: Renderer<Error=E, Texture=T>,
|
R: Renderer<Error=E, TextureId=T>,
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
T: Texture + 'static,
|
T: Texture + 'static,
|
||||||
{
|
{
|
||||||
|
@ -204,7 +210,7 @@ pub fn draw_dnd_icon<R, E, T>(
|
||||||
"Trying to display as a dnd icon a surface that does not have the DndIcon role."
|
"Trying to display as a dnd icon a surface that does not have the DndIcon role."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
draw_surface_tree(renderer, renderer_id, buffer_utils, surface, (x, y), token, log);
|
draw_surface_tree(renderer, renderer_id, texture_destruction_callback, buffer_utils, surface, (x, y), token, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn schedule_initial_render<R: Renderer + 'static, Data: 'static>(
|
pub fn schedule_initial_render<R: Renderer + 'static, Data: 'static>(
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
||||||
os::unix::io::{AsRawFd, RawFd},
|
os::unix::io::{AsRawFd, RawFd},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::{atomic::Ordering, Arc, Mutex},
|
sync::{atomic::Ordering, Arc, Mutex, mpsc},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -494,6 +494,8 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
||||||
&self.logger,
|
&self.logger,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
// we leak this texture (we would need to call `destroy_texture` on Drop of DrmRenderer),
|
||||||
|
// but only on shutdown anyway, because we do not support hot-pluggin, so it does not really matter.
|
||||||
let pointer_image = {
|
let pointer_image = {
|
||||||
let context = EGLContext::new_shared(&egl, &context, self.logger.clone()).unwrap();
|
let context = EGLContext::new_shared(&egl, &context, self.logger.clone()).unwrap();
|
||||||
let mut renderer = unsafe { Gles2Renderer::new(context, self.logger.clone()).unwrap() };
|
let mut renderer = unsafe { Gles2Renderer::new(context, self.logger.clone()).unwrap() };
|
||||||
|
@ -508,6 +510,7 @@ impl<Data: 'static> UdevHandlerImpl<Data> {
|
||||||
buffer_utils: self.buffer_utils.clone(),
|
buffer_utils: self.buffer_utils.clone(),
|
||||||
compositor_token: self.compositor_token,
|
compositor_token: self.compositor_token,
|
||||||
backends: backends.clone(),
|
backends: backends.clone(),
|
||||||
|
texture_destruction_callback: mpsc::channel(),
|
||||||
window_map: self.window_map.clone(),
|
window_map: self.window_map.clone(),
|
||||||
output_map: self.output_map.clone(),
|
output_map: self.output_map.clone(),
|
||||||
pointer_location: self.pointer_location.clone(),
|
pointer_location: self.pointer_location.clone(),
|
||||||
|
@ -647,6 +650,7 @@ pub struct DrmRenderer {
|
||||||
buffer_utils: BufferUtils,
|
buffer_utils: BufferUtils,
|
||||||
compositor_token: CompositorToken<Roles>,
|
compositor_token: CompositorToken<Roles>,
|
||||||
backends: Rc<RefCell<HashMap<crtc::Handle, Rc<RefCell<RenderSurface>>>>>,
|
backends: Rc<RefCell<HashMap<crtc::Handle, Rc<RefCell<RenderSurface>>>>>,
|
||||||
|
texture_destruction_callback: (mpsc::Sender<Gles2Texture>, mpsc::Receiver<Gles2Texture>),
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
output_map: Rc<RefCell<Vec<MyOutput>>>,
|
output_map: Rc<RefCell<Vec<MyOutput>>>,
|
||||||
pointer_location: Rc<RefCell<(f64, f64)>>,
|
pointer_location: Rc<RefCell<(f64, f64)>>,
|
||||||
|
@ -672,6 +676,7 @@ impl DrmRenderer {
|
||||||
if let Some(surface) = self.backends.borrow().get(&crtc) {
|
if let Some(surface) = self.backends.borrow().get(&crtc) {
|
||||||
let result = DrmRenderer::render_surface(
|
let result = DrmRenderer::render_surface(
|
||||||
&mut *surface.borrow_mut(),
|
&mut *surface.borrow_mut(),
|
||||||
|
&self.texture_destruction_callback.0,
|
||||||
&self.buffer_utils,
|
&self.buffer_utils,
|
||||||
self.device_id,
|
self.device_id,
|
||||||
crtc,
|
crtc,
|
||||||
|
@ -739,12 +744,17 @@ impl DrmRenderer {
|
||||||
self.window_map
|
self.window_map
|
||||||
.borrow()
|
.borrow()
|
||||||
.send_frames(self.start_time.elapsed().as_millis() as u32);
|
.send_frames(self.start_time.elapsed().as_millis() as u32);
|
||||||
|
|
||||||
|
while let Ok(texture) = self.texture_destruction_callback.1.try_recv() {
|
||||||
|
let _ = surface.borrow_mut().destroy_texture(texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_surface(
|
fn render_surface(
|
||||||
surface: &mut RenderSurface,
|
surface: &mut RenderSurface,
|
||||||
|
texture_destruction_callback: &mpsc::Sender<Gles2Texture>,
|
||||||
buffer_utils: &BufferUtils,
|
buffer_utils: &BufferUtils,
|
||||||
device_id: dev_t,
|
device_id: dev_t,
|
||||||
crtc: crtc::Handle,
|
crtc: crtc::Handle,
|
||||||
|
@ -777,6 +787,7 @@ impl DrmRenderer {
|
||||||
draw_windows(
|
draw_windows(
|
||||||
surface,
|
surface,
|
||||||
device_id,
|
device_id,
|
||||||
|
texture_destruction_callback,
|
||||||
buffer_utils,
|
buffer_utils,
|
||||||
window_map,
|
window_map,
|
||||||
Some(Rectangle {
|
Some(Rectangle {
|
||||||
|
@ -800,7 +811,7 @@ impl DrmRenderer {
|
||||||
{
|
{
|
||||||
if let Some(ref wl_surface) = dnd_icon.as_ref() {
|
if let Some(ref wl_surface) = dnd_icon.as_ref() {
|
||||||
if wl_surface.as_ref().is_alive() {
|
if wl_surface.as_ref().is_alive() {
|
||||||
draw_dnd_icon(surface, device_id, buffer_utils, wl_surface, (ptr_x, ptr_y), compositor_token.clone(), logger);
|
draw_dnd_icon(surface, device_id, texture_destruction_callback, buffer_utils, wl_surface, (ptr_x, ptr_y), compositor_token.clone(), logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -819,6 +830,7 @@ impl DrmRenderer {
|
||||||
draw_cursor(
|
draw_cursor(
|
||||||
surface,
|
surface,
|
||||||
device_id,
|
device_id,
|
||||||
|
texture_destruction_callback,
|
||||||
buffer_utils,
|
buffer_utils,
|
||||||
wl_surface,
|
wl_surface,
|
||||||
(ptr_x, ptr_y),
|
(ptr_x, ptr_y),
|
||||||
|
|
|
@ -91,6 +91,7 @@ pub fn run_winit(
|
||||||
|
|
||||||
info!(log, "Initialization completed, starting the main loop.");
|
info!(log, "Initialization completed, starting the main loop.");
|
||||||
|
|
||||||
|
let (texture_send, texture_receive) = std::sync::mpsc::channel();
|
||||||
while state.running.load(Ordering::SeqCst) {
|
while state.running.load(Ordering::SeqCst) {
|
||||||
if input
|
if input
|
||||||
.dispatch_new_events(|event, _| state.process_input_event(event))
|
.dispatch_new_events(|event, _| state.process_input_event(event))
|
||||||
|
@ -113,7 +114,7 @@ pub fn run_winit(
|
||||||
renderer.clear([0.8, 0.8, 0.9, 1.0]).expect("Failed to clear frame");
|
renderer.clear([0.8, 0.8, 0.9, 1.0]).expect("Failed to clear frame");
|
||||||
|
|
||||||
// draw the windows
|
// draw the windows
|
||||||
draw_windows(&mut renderer, 0, &buffer_utils, &*state.window_map.borrow(), None, state.ctoken, &log);
|
draw_windows(&mut renderer, 0, &texture_send, &buffer_utils, &*state.window_map.borrow(), None, state.ctoken, &log);
|
||||||
|
|
||||||
let (x, y) = *state.pointer_location.borrow();
|
let (x, y) = *state.pointer_location.borrow();
|
||||||
// draw the dnd icon if any
|
// draw the dnd icon if any
|
||||||
|
@ -121,7 +122,7 @@ pub fn run_winit(
|
||||||
let guard = state.dnd_icon.lock().unwrap();
|
let guard = state.dnd_icon.lock().unwrap();
|
||||||
if let Some(ref surface) = *guard {
|
if let Some(ref surface) = *guard {
|
||||||
if surface.as_ref().is_alive() {
|
if surface.as_ref().is_alive() {
|
||||||
draw_dnd_icon(&mut renderer, 0, &buffer_utils, surface, (x as i32, y as i32), state.ctoken, &log);
|
draw_dnd_icon(&mut renderer, 0, &texture_send, &buffer_utils, surface, (x as i32, y as i32), state.ctoken, &log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +141,7 @@ pub fn run_winit(
|
||||||
// draw as relevant
|
// draw as relevant
|
||||||
if let CursorImageStatus::Image(ref surface) = *guard {
|
if let CursorImageStatus::Image(ref surface) = *guard {
|
||||||
renderer.window().set_cursor_visible(false);
|
renderer.window().set_cursor_visible(false);
|
||||||
draw_cursor(&mut renderer, 0, &buffer_utils, surface, (x as i32, y as i32), state.ctoken, &log);
|
draw_cursor(&mut renderer, 0, &texture_send, &buffer_utils, surface, (x as i32, y as i32), state.ctoken, &log);
|
||||||
} else {
|
} else {
|
||||||
renderer.window().set_cursor_visible(true);
|
renderer.window().set_cursor_visible(true);
|
||||||
}
|
}
|
||||||
|
@ -162,6 +163,10 @@ pub fn run_winit(
|
||||||
display.borrow_mut().flush_clients(&mut state);
|
display.borrow_mut().flush_clients(&mut state);
|
||||||
state.window_map.borrow_mut().refresh();
|
state.window_map.borrow_mut().refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while let Ok(texture) = texture_receive.try_recv() {
|
||||||
|
let _ = renderer.destroy_texture(texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup stuff
|
// Cleanup stuff
|
||||||
|
|
Loading…
Reference in New Issue