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
use ffi::gl;
use geom::{Transform, Vector};
use graphics::{Image, PixelFormat, Window, View};
use std::rc::Rc;
#[derive(Debug)]
struct SurfaceData {
framebuffer: u32
}
impl Drop for SurfaceData {
fn drop(&mut self) {
unsafe { gl::DeleteFramebuffer(self.framebuffer) };
}
}
#[derive(Clone, Debug)]
pub struct Surface {
image: Image,
data: Rc<SurfaceData>,
}
impl Surface {
pub fn new(width: u32, height: u32) -> Surface {
let image = Image::new_null(width, height, PixelFormat::RGBA);
let surface = SurfaceData {
framebuffer: unsafe { gl::GenFramebuffer() }
};
unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, surface.framebuffer);
gl::FramebufferTexture(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, image.get_id(), 0);
gl::DrawBuffer(gl::COLOR_ATTACHMENT0);
}
Surface {
image,
data: Rc::new(surface)
}
}
pub fn render_to<F>(&self, window: &mut Window, func: F) where F: FnOnce(&mut Window) {
let viewport = &mut [0, 0, 0, 0];
let view = window.view();
unsafe {
gl::GetViewport(viewport.as_mut_ptr());
gl::BindFramebuffer(gl::FRAMEBUFFER, self.data.framebuffer);
gl::Viewport(0, 0, self.image.source_width() as i32, self.image.source_height() as i32);
window.flush();
window.set_view(View::new_transformed(self.image.area(), Transform::scale(Vector::new(1, -1))));
}
func(window);
window.set_view(view);
unsafe {
window.flush();
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
gl::Viewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
}
pub fn image(&self) -> &Image {
&self.image
}
}