cogl/auto/onscreen.rs
1use crate::{
2 Context, FrameClosure, FrameEvent, FrameInfo, Framebuffer, Object, OnscreenDirtyClosure,
3 OnscreenDirtyInfo, OnscreenResizeClosure,
4};
5
6use glib::translate::*;
7use std::boxed::Box as Box_;
8use std::fmt;
9
10glib_wrapper! {
11 pub struct Onscreen(Object<ffi::CoglOnscreen, OnscreenClass>) @extends Object, @implements Framebuffer;
12
13 match fn {
14 get_type => || ffi::cogl_onscreen_get_gtype(),
15 }
16}
17
18impl Onscreen {
19 /// Instantiates an "unallocated" `Onscreen` framebuffer that may be
20 /// configured before later being allocated, either implicitly when
21 /// it is first used or explicitly via `Framebuffer::allocate`.
22 /// ## `context`
23 /// A `Context`
24 /// ## `width`
25 /// The desired framebuffer width
26 /// ## `height`
27 /// The desired framebuffer height
28 ///
29 /// # Returns
30 ///
31 /// A newly instantiated `Onscreen` framebuffer
32 pub fn new(context: &Context, width: i32, height: i32) -> Onscreen {
33 unsafe {
34 from_glib_full(ffi::cogl_onscreen_new(
35 context.to_glib_none().0,
36 width,
37 height,
38 ))
39 }
40 }
41
42 /// Installs a `callback` function that will be called whenever the
43 /// window system has lost the contents of a region of the onscreen
44 /// buffer and the application should redraw it to repair the buffer.
45 /// For example this may happen in a window system without a compositor
46 /// if a window that was previously covering up the onscreen window has
47 /// been moved causing a region of the onscreen to be exposed.
48 ///
49 /// The `callback` will be passed a `OnscreenDirtyInfo` struct which
50 /// decribes a rectangle containing the newly dirtied region. Note that
51 /// this may be called multiple times to describe a non-rectangular
52 /// region composed of multiple smaller rectangles.
53 ///
54 /// The dirty events are separate from `FrameEvent::Sync` events so
55 /// the application should also listen for this event before rendering
56 /// the dirty region to ensure that the framebuffer is actually ready
57 /// for rendering.
58 /// ## `callback`
59 /// A callback function to call for dirty events
60 /// ## `user_data`
61 /// A private pointer to be passed to `callback`
62 ///
63 /// # Returns
64 ///
65 /// a `OnscreenDirtyClosure` pointer that can be used to
66 /// remove the callback and associated `user_data` later.
67 pub fn add_dirty_callback<P: Fn(&Onscreen, &OnscreenDirtyInfo) + 'static>(
68 &self,
69 callback: P,
70 ) -> Option<OnscreenDirtyClosure> {
71 let callback_data: Box_<P> = Box_::new(callback);
72 unsafe extern "C" fn callback_func<P: Fn(&Onscreen, &OnscreenDirtyInfo) + 'static>(
73 onscreen: *mut ffi::CoglOnscreen,
74 info: *const ffi::CoglOnscreenDirtyInfo,
75 user_data: glib_sys::gpointer,
76 ) {
77 let onscreen = from_glib_borrow(onscreen);
78 let info = from_glib_borrow(info);
79 let callback: &P = &*(user_data as *mut _);
80 (*callback)(&onscreen, &info);
81 }
82 let callback = Some(callback_func::<P> as _);
83 let super_callback0: Box_<P> = callback_data;
84 unsafe {
85 from_glib_full(ffi::cogl_onscreen_add_dirty_callback(
86 self.to_glib_none().0,
87 callback,
88 Box_::into_raw(super_callback0) as *mut _,
89 None,
90 ))
91 }
92 }
93
94 /// Installs a `callback` function that will be called for significant
95 /// events relating to the given `self` framebuffer.
96 ///
97 /// The `callback` will be used to notify when the system compositor is
98 /// ready for this application to render a new frame. In this case
99 /// `FrameEvent::Sync` will be passed as the event argument to the
100 /// given `callback` in addition to the `FrameInfo` corresponding to
101 /// the frame beeing acknowledged by the compositor.
102 ///
103 /// The `callback` will also be called to notify when the frame has
104 /// ended. In this case `FrameEvent::Complete` will be passed as
105 /// the event argument to the given `callback` in addition to the
106 /// `FrameInfo` corresponding to the newly presented frame. The
107 /// meaning of "ended" here simply means that no more timing
108 /// information will be collected within the corresponding
109 /// `FrameInfo` and so this is a good opportunity to analyse the
110 /// given info. It does not necessarily mean that the GPU has finished
111 /// rendering the corresponding frame.
112 ///
113 /// We highly recommend throttling your application according to
114 /// `FrameEvent::Sync` events so that your application can avoid
115 /// wasting resources, drawing more frames than your system compositor
116 /// can display.
117 /// ## `callback`
118 /// A callback function to call for frame events
119 /// ## `user_data`
120 /// A private pointer to be passed to `callback`
121 ///
122 /// # Returns
123 ///
124 /// a `FrameClosure` pointer that can be used to
125 /// remove the callback and associated `user_data` later.
126 pub fn add_frame_callback<P: Fn(&Onscreen, &FrameEvent, &FrameInfo) + 'static>(
127 &self,
128 callback: P,
129 ) -> Option<FrameClosure> {
130 let callback_data: Box_<P> = Box_::new(callback);
131 unsafe extern "C" fn callback_func<P: Fn(&Onscreen, &FrameEvent, &FrameInfo) + 'static>(
132 onscreen: *mut ffi::CoglOnscreen,
133 event: ffi::CoglFrameEvent,
134 info: *mut ffi::CoglFrameInfo,
135 user_data: glib_sys::gpointer,
136 ) {
137 let onscreen = from_glib_borrow(onscreen);
138 let event = from_glib(event);
139 let info = from_glib_borrow(info);
140 let callback: &P = &*(user_data as *mut _);
141 (*callback)(&onscreen, &event, &info);
142 }
143 let callback = Some(callback_func::<P> as _);
144 let super_callback0: Box_<P> = callback_data;
145 unsafe {
146 from_glib_full(ffi::cogl_onscreen_add_frame_callback(
147 self.to_glib_none().0,
148 callback,
149 Box_::into_raw(super_callback0) as *mut _,
150 None,
151 ))
152 }
153 }
154
155 /// Registers a `callback` with `self` that will be called whenever
156 /// the `self` framebuffer changes size.
157 ///
158 /// The `callback` can be removed using
159 /// `Onscreen::remove_resize_callback` passing the returned closure
160 /// pointer.
161 ///
162 /// `<note>`Since Cogl automatically updates the viewport of an `self`
163 /// framebuffer that is resized, a resize callback can also be used to
164 /// track when the viewport has been changed automatically by Cogl in
165 /// case your application needs more specialized control over the
166 /// viewport.`</note>`
167 ///
168 /// `<note>`A resize callback will only ever be called while dispatching
169 /// Cogl events from the system mainloop; so for example during
170 /// `cogl_poll_renderer_dispatch`. This is so that callbacks shouldn't
171 /// occur while an application might have arbitrary locks held for
172 /// example.`</note>`
173 ///
174 /// ## `callback`
175 /// A `CoglOnscreenResizeCallback` to call when
176 /// the `self` changes size.
177 /// ## `user_data`
178 /// Private data to be passed to `callback`.
179 /// ## `destroy`
180 ///
181 /// # Returns
182 ///
183 /// a `OnscreenResizeClosure` pointer that can be used to
184 /// remove the callback and associated `user_data` later.
185 pub fn add_resize_callback<P: Fn(&Onscreen, i32, i32) + 'static>(
186 &self,
187 callback: P,
188 ) -> Option<OnscreenResizeClosure> {
189 let callback_data: Box_<P> = Box_::new(callback);
190 unsafe extern "C" fn callback_func<P: Fn(&Onscreen, i32, i32) + 'static>(
191 onscreen: *mut ffi::CoglOnscreen,
192 width: libc::c_int,
193 height: libc::c_int,
194 user_data: glib_sys::gpointer,
195 ) {
196 let onscreen = from_glib_borrow(onscreen);
197 let callback: &P = &*(user_data as *mut _);
198 (*callback)(&onscreen, width, height);
199 }
200 let callback = Some(callback_func::<P> as _);
201 let super_callback0: Box_<P> = callback_data;
202 unsafe {
203 from_glib_full(ffi::cogl_onscreen_add_resize_callback(
204 self.to_glib_none().0,
205 callback,
206 Box_::into_raw(super_callback0) as *mut _,
207 None,
208 ))
209 }
210 }
211
212 /// Gets the current age of the buffer contents.
213 ///
214 /// This function allows applications to query the age of the current
215 /// back buffer contents for a `Onscreen` as the number of frames
216 /// elapsed since the contents were most recently defined.
217 ///
218 /// These age values exposes enough information to applications about
219 /// how Cogl internally manages back buffers to allow applications to
220 /// re-use the contents of old frames and minimize how much must be
221 /// redrawn for the next frame.
222 ///
223 /// The back buffer contents can either be reported as invalid (has an
224 /// age of 0) or it may be reported to be the same contents as from n
225 /// frames prior to the current frame.
226 ///
227 /// The queried value remains valid until the next buffer swap.
228 ///
229 /// `<note>`One caveat is that under X11 the buffer age does not reflect
230 /// changes to buffer contents caused by the window systems. X11
231 /// applications must track Expose events to determine what buffer
232 /// regions need to additionally be repaired each frame.`</note>`
233 ///
234 /// The recommended way to take advantage of this buffer age api is to
235 /// build up a circular buffer of length 3 for tracking damage regions
236 /// over the last 3 frames and when starting a new frame look at the
237 /// age of the buffer and combine the damage regions for the current
238 /// frame with the damage regions of previous `age` frames so you know
239 /// everything that must be redrawn to update the old contents for the
240 /// new frame.
241 ///
242 /// `<note>`If the system doesn't not support being able to track the age
243 /// of back buffers then this function will always return 0 which
244 /// implies that the contents are undefined.`</note>`
245 ///
246 /// `<note>`The `FeatureID::OglFeatureIdBufferAge` feature can optionally be
247 /// explicitly checked to determine if Cogl is currently tracking the
248 /// age of `Onscreen` back buffer contents. If this feature is
249 /// missing then this function will always return 0.`</note>`
250 ///
251 /// # Returns
252 ///
253 /// The age of the buffer contents or 0 when the buffer
254 /// contents are undefined.
255 pub fn get_buffer_age(&self) -> i32 {
256 unsafe { ffi::cogl_onscreen_get_buffer_age(self.to_glib_none().0) }
257 }
258
259 /// Gets the value of the framebuffers frame counter. This is
260 /// a counter that increases by one each time
261 /// `Onscreen::swap_buffers` or `Onscreen::swap_region`
262 /// is called.
263 ///
264 /// # Returns
265 ///
266 /// the current frame counter value
267 pub fn get_frame_counter(&self) -> i64 {
268 unsafe { ffi::cogl_onscreen_get_frame_counter(self.to_glib_none().0) }
269 }
270
271 /// Lets you query whether `self` has been marked as resizable via
272 /// the `Onscreen::set_resizable` api.
273 ///
274 /// By default, if possible, a `self` will be created by Cogl
275 /// as non resizable, but it is not guaranteed that this is always
276 /// possible for all window systems.
277 ///
278 /// `<note>`If cogl_onscreen_set_resizable(`self`, `true`) has been
279 /// previously called then this function will return `true`, but it's
280 /// possible that the current windowing system being used does not
281 /// support window resizing (consider fullscreen windows on a phone or
282 /// a TV). This function is not aware of whether resizing is truly
283 /// meaningful with your window system, only whether the `self` has
284 /// been marked as resizable.`</note>`
285 ///
286 ///
287 /// # Returns
288 ///
289 /// Returns whether `self` has been marked as
290 /// resizable or not.
291 pub fn get_resizable(&self) -> bool {
292 unsafe {
293 let ret = ffi::cogl_onscreen_get_resizable(self.to_glib_none().0);
294 ret == crate::TRUE
295 }
296 }
297
298 /// This requests to make `self` invisible to the user.
299 ///
300 /// Actually the precise semantics of this function depend on the
301 /// window system currently in use, and if you don't have a
302 /// multi-windowining system this function may in-fact do nothing.
303 ///
304 /// This function does not implicitly allocate the given `self`
305 /// framebuffer before hiding it.
306 ///
307 /// `<note>`Since Cogl doesn't explicitly track the visibility status of
308 /// onscreen framebuffers it wont try to avoid redundant window system
309 /// requests e.g. to show an already visible window. This also means
310 /// that it's acceptable to alternatively use native APIs to show and
311 /// hide windows without confusing Cogl.`</note>`
312 ///
313 pub fn hide(&self) {
314 unsafe {
315 ffi::cogl_onscreen_hide(self.to_glib_none().0);
316 }
317 }
318
319 /// Removes a callback and associated user data that were previously
320 /// registered using `Onscreen::add_dirty_callback`.
321 ///
322 /// If a destroy callback was passed to
323 /// `Onscreen::add_dirty_callback` to destroy the user data then
324 /// this will also get called.
325 /// ## `closure`
326 /// A `OnscreenDirtyClosure` returned from
327 /// `Onscreen::add_dirty_callback`
328 pub fn remove_dirty_callback(&self, closure: &mut OnscreenDirtyClosure) {
329 unsafe {
330 ffi::cogl_onscreen_remove_dirty_callback(
331 self.to_glib_none().0,
332 closure.to_glib_none_mut().0,
333 );
334 }
335 }
336
337 /// Removes a callback and associated user data that were previously
338 /// registered using `Onscreen::add_frame_callback`.
339 ///
340 /// If a destroy callback was passed to
341 /// `Onscreen::add_frame_callback` to destroy the user data then
342 /// this will get called.
343 /// ## `closure`
344 /// A `FrameClosure` returned from
345 /// `Onscreen::add_frame_callback`
346 pub fn remove_frame_callback(&self, closure: &mut FrameClosure) {
347 unsafe {
348 ffi::cogl_onscreen_remove_frame_callback(
349 self.to_glib_none().0,
350 closure.to_glib_none_mut().0,
351 );
352 }
353 }
354
355 /// Removes a resize `callback` and `user_data` pair that were previously
356 /// associated with `self` via `Onscreen::add_resize_callback`.
357 ///
358 /// ## `closure`
359 /// An identifier returned from `Onscreen::add_resize_callback`
360 pub fn remove_resize_callback(&self, closure: &mut OnscreenResizeClosure) {
361 unsafe {
362 ffi::cogl_onscreen_remove_resize_callback(
363 self.to_glib_none().0,
364 closure.to_glib_none_mut().0,
365 );
366 }
367 }
368
369 /// Lets you request Cogl to mark an `self` framebuffer as
370 /// resizable or not.
371 ///
372 /// By default, if possible, a `self` will be created by Cogl
373 /// as non resizable, but it is not guaranteed that this is always
374 /// possible for all window systems.
375 ///
376 /// `<note>`Cogl does not know whether marking the `self` framebuffer
377 /// is truly meaningful for your current window system (consider
378 /// applications being run fullscreen on a phone or TV) so this
379 /// function may not have any useful effect. If you are running on a
380 /// multi windowing system such as X11 or Win32 or OSX then Cogl will
381 /// request to the window system that users be allowed to resize the
382 /// `self`, although it's still possible that some other window
383 /// management policy will block this possibility.`</note>`
384 ///
385 /// `<note>`Whenever an `self` framebuffer is resized the viewport
386 /// will be automatically updated to match the new size of the
387 /// framebuffer with an origin of (0,0). If your application needs more
388 /// specialized control of the viewport it will need to register a
389 /// resize handler using `Onscreen::add_resize_callback` so that it
390 /// can track when the viewport has been changed automatically.`</note>`
391 ///
392 pub fn set_resizable(&self, resizable: bool) {
393 unsafe {
394 ffi::cogl_onscreen_set_resizable(self.to_glib_none().0, resizable as i32);
395 }
396 }
397
398 /// Requests that the given `self` framebuffer should have swap buffer
399 /// requests (made using `Onscreen::swap_buffers`) throttled either by a
400 /// displays vblank period or perhaps some other mechanism in a composited
401 /// environment.
402 /// ## `throttled`
403 /// Whether swap throttling is wanted or not.
404 pub fn set_swap_throttled(&self, throttled: bool) {
405 unsafe {
406 ffi::cogl_onscreen_set_swap_throttled(self.to_glib_none().0, throttled as i32);
407 }
408 }
409
410 /// This requests to make `self` visible to the user.
411 ///
412 /// Actually the precise semantics of this function depend on the
413 /// window system currently in use, and if you don't have a
414 /// multi-windowining system this function may in-fact do nothing.
415 ///
416 /// This function will implicitly allocate the given `self`
417 /// framebuffer before showing it if it hasn't already been allocated.
418 ///
419 /// When using the Wayland winsys calling this will set the surface to
420 /// a toplevel type which will make it appear. If the application wants
421 /// to set a different type for the surface, it can avoid calling
422 /// `Onscreen::show` and set its own type directly with the Wayland
423 /// client API via `cogl_wayland_onscreen_get_surface`.
424 ///
425 /// `<note>`Since Cogl doesn't explicitly track the visibility status of
426 /// onscreen framebuffers it wont try to avoid redundant window system
427 /// requests e.g. to show an already visible window. This also means
428 /// that it's acceptable to alternatively use native APIs to show and
429 /// hide windows without confusing Cogl.`</note>`
430 ///
431 pub fn show(&self) {
432 unsafe {
433 ffi::cogl_onscreen_show(self.to_glib_none().0);
434 }
435 }
436
437 /// Swaps the current back buffer being rendered too, to the front for display.
438 ///
439 /// This function also implicitly discards the contents of the color, depth and
440 /// stencil buffers as if `Framebuffer::discard_buffers` were used. The
441 /// significance of the discard is that you should not expect to be able to
442 /// start a new frame that incrementally builds on the contents of the previous
443 /// frame.
444 ///
445 /// `<note>`It is highly recommended that applications use
446 /// `Onscreen::swap_buffers_with_damage` instead whenever possible
447 /// and also use the `Onscreen::get_buffer_age` api so they can
448 /// perform incremental updates to older buffers instead of having to
449 /// render a full buffer for every frame.`</note>`
450 pub fn swap_buffers(&self) {
451 unsafe {
452 ffi::cogl_onscreen_swap_buffers(self.to_glib_none().0);
453 }
454 }
455
456 /// Swaps the current back buffer being rendered too, to the front for
457 /// display and provides information to any system compositor about
458 /// what regions of the buffer have changed (damage) with respect to
459 /// the last swapped buffer.
460 ///
461 /// This function has the same semantics as
462 /// `cogl_framebuffer_swap_buffers` except that it additionally allows
463 /// applications to pass a list of damaged rectangles which may be
464 /// passed on to a compositor so that it can minimize how much of the
465 /// screen is redrawn in response to this applications newly swapped
466 /// front buffer.
467 ///
468 /// For example if your application is only animating a small object in
469 /// the corner of the screen and everything else is remaining static
470 /// then it can help the compositor to know that only the bottom right
471 /// corner of your newly swapped buffer has really changed with respect
472 /// to your previously swapped front buffer.
473 ///
474 /// If `n_rectangles` is 0 then the whole buffer will implicitly be
475 /// reported as damaged as if `Onscreen::swap_buffers` had been
476 /// called.
477 ///
478 /// This function also implicitly discards the contents of the color,
479 /// depth and stencil buffers as if `Framebuffer::discard_buffers`
480 /// were used. The significance of the discard is that you should not
481 /// expect to be able to start a new frame that incrementally builds on
482 /// the contents of the previous frame. If you want to perform
483 /// incremental updates to older back buffers then please refer to the
484 /// `Onscreen::get_buffer_age` api.
485 ///
486 /// Whenever possible it is recommended that applications use this
487 /// function instead of `Onscreen::swap_buffers` to improve
488 /// performance when running under a compositor.
489 ///
490 /// `<note>`It is highly recommended to use this API in conjunction with
491 /// the `Onscreen::get_buffer_age` api so that your application can
492 /// perform incremental rendering based on old back buffers.`</note>`
493 /// ## `rectangles`
494 /// An array of integer 4-tuples representing damaged
495 /// rectangles as (x, y, width, height) tuples.
496 /// ## `n_rectangles`
497 /// The number of 4-tuples to be read from `rectangles`
498 pub fn swap_buffers_with_damage(&self, rectangles: &[i32], n_rectangles: i32) {
499 unsafe {
500 ffi::cogl_onscreen_swap_buffers_with_damage(
501 self.to_glib_none().0,
502 rectangles.as_ptr(),
503 n_rectangles,
504 );
505 }
506 }
507
508 /// Swaps a region of the back buffer being rendered too, to the front for
509 /// display. `rectangles` represents the region as array of `n_rectangles` each
510 /// defined by 4 sequential (x, y, width, height) integers.
511 ///
512 /// This function also implicitly discards the contents of the color, depth and
513 /// stencil buffers as if `Framebuffer::discard_buffers` were used. The
514 /// significance of the discard is that you should not expect to be able to
515 /// start a new frame that incrementally builds on the contents of the previous
516 /// frame.
517 /// ## `rectangles`
518 /// An array of integer 4-tuples representing rectangles as
519 /// (x, y, width, height) tuples.
520 /// ## `n_rectangles`
521 /// The number of 4-tuples to be read from `rectangles`
522 pub fn swap_region(&self, rectangles: &[i32], n_rectangles: i32) {
523 unsafe {
524 ffi::cogl_onscreen_swap_region(
525 self.to_glib_none().0,
526 rectangles.as_ptr(),
527 n_rectangles,
528 );
529 }
530 }
531}
532
533impl fmt::Display for Onscreen {
534 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
535 write!(f, "Onscreen")
536 }
537}