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}