cogl/auto/
renderer.rs

1#![allow(
2    clippy::too_many_arguments,
3    clippy::let_and_return,
4    clippy::from_over_into
5)]
6
7use crate::{Driver, Object, OnscreenTemplate, Output, RendererConstraint, WinsysID};
8
9use glib::translate::*;
10use std::{fmt, ptr};
11
12glib_wrapper! {
13    pub struct Renderer(Object<ffi::CoglRenderer, RendererClass>) @extends Object;
14
15    match fn {
16        get_type => || ffi::cogl_renderer_get_gtype(),
17    }
18}
19
20impl Renderer {
21    /// Instantiates a new (unconnected) `Renderer` object. A
22    /// `Renderer` represents a means to render. It encapsulates the
23    /// selection of an underlying driver, such as OpenGL or OpenGL-ES and
24    /// a selection of a window system binding API such as GLX, or EGL or
25    /// WGL.
26    ///
27    /// While the renderer is unconnected it can be configured so that
28    /// applications may specify backend constraints, such as "must use
29    /// x11" for example via `Renderer::add_constraint`.
30    ///
31    /// There are also some platform specific configuration apis such
32    /// as `cogl_xlib_renderer_set_foreign_display` that may also be
33    /// used while the renderer is unconnected.
34    ///
35    /// Once the renderer has been configured, then it may (optionally) be
36    /// explicitly connected using `Renderer::connect` which allows
37    /// errors to be handled gracefully and potentially fallback
38    /// configurations can be tried out if there are initial failures.
39    ///
40    /// If a renderer is not explicitly connected then `Display::new`
41    /// will automatically connect the renderer for you. If you don't
42    /// have any code to deal with error/fallback situations then its fine
43    /// to just let Cogl do the connection for you.
44    ///
45    /// Once you have setup your renderer then the next step is to create a
46    /// `Display` using `Display::new`.
47    ///
48    /// `<note>`Many applications don't need to explicitly use
49    /// `Renderer::new` or `Display::new` and can just jump
50    /// straight to `Context::new` and pass a `None` display argument
51    /// so Cogl will automatically connect and setup a renderer and
52    /// display.`</note>`
53    ///
54    /// # Returns
55    ///
56    /// A newly created `Renderer`.
57    pub fn new() -> Renderer {
58        unsafe { from_glib_full(ffi::cogl_renderer_new()) }
59    }
60
61    /// This adds a renderer selection `constraint`.
62    ///
63    /// Applications should ideally minimize how many of these constraints they
64    /// depend on to ensure maximum portability.
65    /// ## `constraint`
66    /// A `RendererConstraint` to add
67    pub fn add_constraint(&self, constraint: RendererConstraint) {
68        unsafe {
69            ffi::cogl_renderer_add_constraint(self.to_glib_none().0, constraint.to_glib());
70        }
71    }
72
73    /// Tests if a given `onscreen_template` can be supported with the given
74    /// `self`.
75    /// ## `onscreen_template`
76    /// A `OnscreenTemplate`
77    ///
78    /// # Returns
79    ///
80    /// `true` if the `onscreen_template` can be supported,
81    ///  else `false`.
82    pub fn check_onscreen_template(
83        &self,
84        onscreen_template: &OnscreenTemplate,
85    ) -> Result<bool, glib::Error> {
86        unsafe {
87            let mut error = ptr::null_mut();
88            let ret = ffi::cogl_renderer_check_onscreen_template(
89                self.to_glib_none().0,
90                onscreen_template.to_glib_none().0,
91                &mut error,
92            );
93            if error.is_null() {
94                Ok(ret == crate::TRUE)
95            } else {
96                Err(from_glib_full(error))
97            }
98        }
99    }
100
101    /// Connects the configured `self`. Renderer connection isn't a
102    /// very active process, it basically just means validating that
103    /// any given constraint criteria can be satisfied and that a
104    /// usable driver and window system backend can be found.
105    ///
106    /// # Returns
107    ///
108    /// `true` if there was no error while connecting the
109    ///  given `self`. `false` if there was an error.
110    pub fn connect(&self) -> Result<bool, glib::Error> {
111        unsafe {
112            let mut error = ptr::null_mut();
113            let ret = ffi::cogl_renderer_connect(self.to_glib_none().0, &mut error);
114            if error.is_null() {
115                Ok(ret == crate::TRUE)
116            } else {
117                Err(from_glib_full(error))
118            }
119        }
120    }
121
122    /// Iterates all known display outputs for the given `self` and
123    /// passes a corresponding `Output` pointer to the given `callback`
124    /// for each one, along with the given `user_data`.
125    /// ## `callback`
126    /// A `CoglOutputCallback` to be called for
127    ///  each display output
128    /// ## `user_data`
129    /// A user pointer to be passed to `callback`
130    pub fn foreach_output<P: FnMut(&Output)>(&self, callback: P) {
131        let callback_data: P = callback;
132        unsafe extern "C" fn callback_func<P: FnMut(&Output)>(
133            output: *mut ffi::CoglOutput,
134            user_data: glib_sys::gpointer,
135        ) {
136            let output = from_glib_borrow(output);
137            let callback: *mut P = user_data as *const _ as usize as *mut P;
138            (*callback)(&output);
139        }
140        let callback = Some(callback_func::<P> as _);
141        let super_callback0: &P = &callback_data;
142        unsafe {
143            ffi::cogl_renderer_foreach_output(
144                self.to_glib_none().0,
145                callback,
146                super_callback0 as *const _ as usize as *mut _,
147            );
148        }
149    }
150
151    /// Queries what underlying driver is being used by Cogl.
152    ///
153    /// This may only be called on a connected `Renderer`.
154    pub fn get_driver(&self) -> Driver {
155        unsafe { from_glib(ffi::cogl_renderer_get_driver(self.to_glib_none().0)) }
156    }
157
158    /// Queries how many texture units can be used from fragment programs
159    ///
160    /// # Returns
161    ///
162    /// the number of texture image units.
163    pub fn get_n_fragment_texture_units(&self) -> i32 {
164        unsafe { ffi::cogl_renderer_get_n_fragment_texture_units(self.to_glib_none().0) }
165    }
166
167    /// Queries which window system backend Cogl has chosen to use.
168    ///
169    /// This may only be called on a connected `Renderer`.
170    ///
171    /// # Returns
172    ///
173    /// The `WinsysID` corresponding to the chosen window
174    ///  system backend.
175    pub fn get_winsys_id(&self) -> WinsysID {
176        unsafe { from_glib(ffi::cogl_renderer_get_winsys_id(self.to_glib_none().0)) }
177    }
178
179    /// This removes a renderer selection `constraint`.
180    ///
181    /// Applications should ideally minimize how many of these constraints they
182    /// depend on to ensure maximum portability.
183    /// ## `constraint`
184    /// A `RendererConstraint` to remove
185    pub fn remove_constraint(&self, constraint: RendererConstraint) {
186        unsafe {
187            ffi::cogl_renderer_remove_constraint(self.to_glib_none().0, constraint.to_glib());
188        }
189    }
190
191    /// Requests that Cogl should try to use a specific underlying driver
192    /// for rendering.
193    ///
194    /// If you select an unsupported driver then `Renderer::connect`
195    /// will fail and report an error. Most applications should not
196    /// explicitly select a driver and should rely on Cogl automatically
197    /// choosing the driver.
198    ///
199    /// This may only be called on an un-connected `Renderer`.
200    pub fn set_driver(&self, driver: Driver) {
201        unsafe {
202            ffi::cogl_renderer_set_driver(self.to_glib_none().0, driver.to_glib());
203        }
204    }
205
206    /// This allows you to explicitly select a winsys backend to use instead
207    /// of letting Cogl automatically select a backend.
208    ///
209    /// if you select an unsupported backend then `Renderer::connect`
210    /// will fail and report an error.
211    ///
212    /// This may only be called on an un-connected `Renderer`.
213    /// ## `winsys_id`
214    /// An ID of the winsys you explicitly want to use.
215    pub fn set_winsys_id(&self, winsys_id: WinsysID) {
216        unsafe {
217            ffi::cogl_renderer_set_winsys_id(self.to_glib_none().0, winsys_id.to_glib());
218        }
219    }
220}
221
222impl Default for Renderer {
223    fn default() -> Self {
224        Self::new()
225    }
226}
227
228impl fmt::Display for Renderer {
229    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
230        write!(f, "Renderer")
231    }
232}