From ea6d1c56d1c4b3b507deca24bcd9121a7e188a6c Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Tue, 20 Jan 2015 21:55:11 -0800 Subject: [PATCH] A feeble attempt to overcome flickering issues on window resize. It really seems insurmountable at this point. Not sure what SDL is doing that's causing this. But I'm leaving this code in, because it makes things a little cleaner and serves as a good example to myself for how to render to textures. --- src/font.rs | 3 +- src/gui/mod.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/font.rs b/src/font.rs index 7a019cc..7fefee2 100644 --- a/src/font.rs +++ b/src/font.rs @@ -7,12 +7,13 @@ use freetype; use sdl2; use sdl2::surface::Surface; +use sdl2::render::Texture; use sdl2::rect::Rect; use string_utils::{is_line_ending}; struct CachedGlyph { - texture: Option, + texture: Option, height: i32, width: i32, advance: i32, diff --git a/src/gui/mod.rs b/src/gui/mod.rs index 327c6b6..8c4db67 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -1,13 +1,19 @@ #![allow(dead_code)] +use std::cmp::min; + use sdl2; +use sdl2::event::WindowEventId; +use sdl2::render::{Renderer, Texture}; +use sdl2::rect::Rect; use font::Font; use editor::Editor; pub struct GUI { - renderer: sdl2::render::Renderer, + renderer: Renderer, + draw_buf: Texture, font: Font, editor: Editor, } @@ -19,12 +25,15 @@ impl GUI { // Get the window and renderer for sdl let window = sdl2::video::Window::new("Led Editor", sdl2::video::WindowPos::PosCentered, sdl2::video::WindowPos::PosCentered, 800, 600, sdl2::video::OPENGL | sdl2::video::RESIZABLE).unwrap(); let renderer = sdl2::render::Renderer::from_window(window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED).unwrap(); + let (w, h) = renderer.get_output_size().unwrap(); + let draw_buf = renderer.create_texture(sdl2::pixels::PixelFormatFlag::RGBA8888, sdl2::render::TextureAccess::Target, w, h).unwrap(); let mut editor = Editor::new(); editor.update_dim(renderer.get_output_size().unwrap().1 as usize, renderer.get_output_size().unwrap().0 as usize); GUI { renderer: renderer, + draw_buf: draw_buf, font: font, editor: editor, } @@ -37,12 +46,15 @@ impl GUI { // Get the window and renderer for sdl let window = sdl2::video::Window::new("Led Editor", sdl2::video::WindowPos::PosCentered, sdl2::video::WindowPos::PosCentered, 800, 600, sdl2::video::OPENGL | sdl2::video::RESIZABLE).unwrap(); let renderer = sdl2::render::Renderer::from_window(window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED).unwrap(); + let (w, h) = renderer.get_output_size().unwrap(); + let draw_buf = renderer.create_texture(sdl2::pixels::PixelFormatFlag::RGBA8888, sdl2::render::TextureAccess::Target, w, h).unwrap(); let mut editor = ed; editor.update_dim(renderer.get_output_size().unwrap().1 as usize, renderer.get_output_size().unwrap().0 as usize); GUI { renderer: renderer, + draw_buf: draw_buf, font: font, editor: editor, } @@ -55,16 +67,57 @@ impl GUI { sdl2::event::Event::Quit(_) => break, sdl2::event::Event::KeyDown(_, _, key, _, _, _) => { if key == sdl2::keycode::KeyCode::Escape { - break + break; } }, - sdl2::event::Event::Window(_, _, sdl2::event::WindowEventId::Exposed, _, _) => { - let _ = self.renderer.set_draw_color(sdl2::pixels::Color::RGB(240, 240, 240)); + + sdl2::event::Event::Window(_, _, WindowEventId::Exposed, _, _) => { + // Remove other Exposed events from the queue, to avoid + // clogging things up. + sdl2::event::filter_events(filter_window_expose); + + // Get renderer size + let (w, h) = self.renderer.get_output_size().unwrap(); + + // Display last rendered contents to fill things in quickly + match self.draw_buf.query() { + Ok(tq) => { + let wm = min(w, tq.width) as i32; + let hm = min(h, tq.height) as i32; + let _ = self.renderer.copy(&self.draw_buf, Some(Rect{x:0, y:0, h:hm, w:wm}), Some(Rect{x:0, y:0, h:hm, w:wm})); + self.renderer.present(); + }, + + _ => { + } + } + + + // Make sure the texture still matches the render size + match self.draw_buf.query() { + Ok(tq) => { + if tq.width != w || tq.height != h { + self.draw_buf = self.renderer.create_texture(sdl2::pixels::PixelFormatFlag::RGBA8888, sdl2::render::TextureAccess::Target, w, h).unwrap(); + } + }, + + _ => { + self.draw_buf = self.renderer.create_texture(sdl2::pixels::PixelFormatFlag::RGBA8888, sdl2::render::TextureAccess::Target, w, h).unwrap(); + } + } + + // Draw UI to texture + let _ = self.renderer.set_render_target(Some(&self.draw_buf)); + let _ = self.renderer.set_draw_color(sdl2::pixels::Color::RGB(80, 80, 80)); let _ = self.renderer.clear(); - //self.font.draw_text("Hi there! (How's it going???) { let b = 42; }", (0, 0, 0), 50, 50, &self.renderer); self.draw_editor_text((50, 50), (300, 300)); + + // Copy texture over + let _ = self.renderer.set_render_target(None); + let _ = self.renderer.copy(&self.draw_buf, Some(Rect{x:0, y:0, h:h as i32, w:w as i32}), Some(Rect{x:0, y:0, h:h as i32, w:w as i32})); self.renderer.present(); - } + }, + _ => {} } } @@ -79,11 +132,20 @@ impl GUI { for line in line_iter { for g in line.grapheme_iter() { - x += self.font.draw_text(g, (0, 0, 0), x as i32, y as i32, &self.renderer); + x += self.font.draw_text(g, (255, 255, 255), x as i32, y as i32, &self.renderer); } x = c1.1; y += self.font.line_height() >> 6; } } +} + + +// Used for removing WindowEventId::Exposed events from the queue +extern "C" fn filter_window_expose(e: sdl2::event::Event) -> bool { + match e { + sdl2::event::Event::Window(_, _, WindowEventId::Exposed, _, _) => false, + _ => true, + } } \ No newline at end of file