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
use ash::vk::Handle;
use glfw::*;
use impellers::*;
pub fn main() {
let mut gtx = init(fail_on_errors).unwrap();
gtx.window_hint(WindowHint::ClientApi(ClientApiHint::NoApi));
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);
// initialize impeller context by loading vulkan fn pointers
let itx = unsafe {
assert!(gtx.vulkan_supported());
// create context using callback
impellers::Context::new_vulkan(false, |vk_instance, vk_proc_name| {
let proc_name = std::ffi::CStr::from_ptr(vk_proc_name).to_str().unwrap();
gtx.get_instance_proc_address_raw(vk_instance as _, proc_name)
.map(|f| f as _)
.unwrap_or(std::ptr::null_mut())
})
}
.expect("failed to create impeller context");
// lets see what's in here
let vk_info = itx.get_vulkan_info().expect("failed to get vulkan info");
dbg!(vk_info);
assert!(
!vk_info.vk_instance.is_null(),
"instance pointer from vulkan info is null"
);
let mut vulkan_surface_khr: ash::vk::SurfaceKHR = ash::vk::SurfaceKHR::null();
let result = unsafe {
window.create_window_surface(
vk_info.vk_instance as _,
std::ptr::null(),
&raw mut vulkan_surface_khr as _,
)
};
if result != 0 {
panic!("failed to create vk surface khr");
}
assert!(!vulkan_surface_khr.is_null(), "surface pointer is null");
let mut vk_swapchain =
unsafe { itx.create_new_vulkan_swapchain(vulkan_surface_khr.as_raw() as _) }
.expect("failed to create vk swapchain");
// enter event loop
while !window.should_close() {
// check events
gtx.poll_events();
for (_, event) in flush_messages(&ev_receiver) {
if event == WindowEvent::Close {
window.set_should_close(true);
}
}
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);
builder.build().expect("failed to build a display_list")
};
let mut surface = vk_swapchain.acquire_next_surface_new().unwrap();
// 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.
surface
.draw_display_list(&main_display_list)
.expect("failed to draw on surface");
// submit frame and wait for vsync
surface.present().unwrap();
}
// drop the window/sdl or whatever
}