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
use glfw::*;
use glow::HasContext as _;
use impellers::*;
pub fn main() {
let mut gtx = init(fail_on_errors).unwrap();
gtx.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
gtx.window_hint(WindowHint::ContextVersionMajor(4));
gtx.window_hint(WindowHint::SRgbCapable(true));
gtx.window_hint(WindowHint::ScaleToMonitor(true));
let (mut window, ev_receiver) = gtx
.create_window(800, 600, "rust-glfw-impeller demo", WindowMode::Windowed)
.expect("failed to create window");
window.set_all_polling(true);
window.make_current();
// initialize impeller context using opengl fn pointers
let mut itx = unsafe {
impellers::Context::new_opengl_es(|s| {
window
.get_proc_address(s)
.map(|f| f as _)
.unwrap_or(std::ptr::null_mut())
})
}
.unwrap();
let glow_ctx: glow::Context = unsafe {
glow::Context::from_loader_function(|s| {
window
.get_proc_address(s)
.map(|f| f as _)
.unwrap_or(std::ptr::null_mut())
})
};
// enter event loop
while !window.should_close() {
// check events
gtx.poll_events();
for (_, event) in flush_messages(&ev_receiver) {
match event {
WindowEvent::Close => {
window.set_should_close(true);
}
WindowEvent::FramebufferSize(_, _) => {
// glViewPort here
}
_ => {}
}
}
let (width, height) = window.get_framebuffer_size();
let mut surface = unsafe {
itx.wrap_fbo(
0,
PixelFormat::RGBA8888,
ISize::new(width.into(), height.into()),
)
}
.expect("failed to wrap window's framebuffer");
// create a display list
let clear_display_list = {
// create a display list builder
let mut builder = DisplayListBuilder::new(None);
// paint controls the properties of draw commands
let mut paint = Paint::default();
// eg: lets set the color to black. So, any drawing command with this paint will use that color.
paint.set_color(Color::BLACKBERRY);
// fill the bounds with a color (^^that we set above)
builder.draw_paint(&paint);
let current_time = gtx.get_time(); // time in seconds since start of the program
// lets set the color to a color that changes with time.
// sin/cos/tan will always be in the range of -1 to 1, so lets use abs to keep it in between 0 and 1.
paint.set_color(Color::new_srgb(
current_time.sin().abs() as _,
current_time.cos().abs() as _,
current_time.tan().abs() as _,
));
builder.draw_rect(&Rect::from_size(Size::new(200.0, 200.0)), &paint);
// finish recording the drawing commands. This is only a "list" and we haven't drawn anything yet.
builder.build().expect("failed to build a display_list")
};
let animating_dl = {
// create a display list builder
let mut builder = DisplayListBuilder::new(None);
// paint controls the properties of draw commands
let mut paint = Paint::default();
let current_time = gtx.get_time(); // time in seconds since start of the program
// lets set the color to a color that changes with time.
// sin/cos/tan will always be in the range of -1 to 1, so lets use abs to keep it in between 0 and 1.
paint.set_color(Color::new_srgb(
current_time.sin().abs() as _,
current_time.cos().abs() as _,
current_time.tan().abs() as _,
));
builder.draw_rect(&Rect::from_size(Size::new(200.0, 200.0)), &paint);
// finish recording the drawing commands. This is only a "list" and we haven't drawn anything yet.
builder.build().expect("failed to build a display_list")
};
let oval_dl = {
// create a display list builder
let mut builder = DisplayListBuilder::new(None);
// paint controls the properties of draw commands
let mut paint = Paint::default();
// eg: lets set the color to black. So, any drawing command with this paint will use that color.
paint.set_color(Color::GRANNY_APPLE);
builder.draw_oval(&Rect::from_size(Size::new(200.0, 200.0)), &paint);
// finish recording the drawing commands. This is only a "list" and we haven't drawn anything yet.
builder.build().expect("failed to build a display_list")
};
let main_display_list = {
let mut builder = DisplayListBuilder::new(None);
builder.draw_display_list(&clear_display_list, 1.0);
builder.draw_display_list(&animating_dl, 1.0);
builder.draw_display_list(&oval_dl, 1.0);
// finish recording the drawing commands. This is only a "list" and we haven't drawn anything yet.
builder.build().expect("failed to build a display_list")
};
// Now, draw the display_list on the surface. All the commands we recorded in the display_list will be drawn.
// you can redraw the display_list multiple times to animate it on any number of surfaces.
unsafe {
glow_ctx.clear_color(1.0, 0.0, 0.0, 1.0);
glow_ctx.clear(glow::COLOR_BUFFER_BIT);
}
surface
.draw_display_list(&main_display_list)
.expect("failed to draw on surface");
// submit frame and wait for vsync
window.swap_buffers();
}
// drop the window/sdl or whatever
}