gdk4/
gl_texture_builder.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::{prelude::*, translate::*};
4
5#[cfg(feature = "v4_16")]
6use crate::ColorState;
7use crate::{ffi, GLContext, GLTextureBuilder, MemoryFormat, Texture};
8
9#[cfg(not(feature = "gl"))]
10pub type GLsync = *const libc::c_void;
11
12#[cfg(feature = "gl")]
13pub use gl::types::GLsync;
14
15impl GLTextureBuilder {
16    /// Builds a new [`Texture`][crate::Texture] with the values set up in the builder.
17    ///
18    /// The `destroy` function gets called when the returned texture gets released;
19    /// either when the texture is finalized or by an explicit call to
20    /// [`GLTexture::release()`][crate::GLTexture::release()]. It should release all GL resources associated
21    /// with the texture, such as the [`id`][struct@crate::GLTextureBuilder#id] and the
22    /// [`sync`][struct@crate::GLTextureBuilder#sync].
23    ///
24    /// Note that it is a programming error to call this function if any mandatory
25    /// property has not been set.
26    ///
27    /// It is possible to call this function multiple times to create multiple textures,
28    /// possibly with changing properties in between.
29    ///
30    /// # Returns
31    ///
32    /// a newly built [`Texture`][crate::Texture]
33    #[doc(alias = "gdk_gl_texture_builder_build")]
34    #[must_use = "The builder must be built to be used"]
35    #[allow(clippy::missing_safety_doc)]
36    pub unsafe fn build(self) -> Texture {
37        from_glib_full(ffi::gdk_gl_texture_builder_build(
38            self.to_glib_none().0,
39            None,
40            std::ptr::null_mut(),
41        ))
42    }
43
44    #[doc(alias = "gdk_gl_texture_builder_build")]
45    #[must_use = "The builder must be built to be used"]
46    #[allow(clippy::missing_safety_doc)]
47    pub unsafe fn build_with_release_func<F: FnOnce() + Send + 'static>(
48        self,
49        release_func: F,
50    ) -> Texture {
51        unsafe extern "C" fn destroy_closure<F: FnOnce() + Send + 'static>(
52            func: glib::ffi::gpointer,
53        ) {
54            let released_func = Box::<F>::from_raw(func as *mut _);
55            released_func();
56        }
57        let released_func = Box::new(release_func);
58        from_glib_full(ffi::gdk_gl_texture_builder_build(
59            self.to_glib_none().0,
60            Some(destroy_closure::<F>),
61            Box::into_raw(released_func) as glib::ffi::gpointer,
62        ))
63    }
64
65    /// Sets the color state for the texture.
66    ///
67    /// By default, the sRGB colorstate is used. If you don't know what
68    /// colorstates are, this is probably the right thing.
69    /// ## `color_state`
70    /// a [`ColorState`][crate::ColorState]
71    #[cfg(feature = "v4_16")]
72    #[cfg_attr(docsrs, doc(cfg(feature = "v4_16")))]
73    #[doc(alias = "gdk_gl_texture_builder_set_color_state")]
74    #[doc(alias = "color-state")]
75    pub fn set_color_state(self, color_state: &ColorState) -> Self {
76        unsafe {
77            ffi::gdk_gl_texture_builder_set_color_state(
78                self.to_glib_none().0,
79                color_state.to_glib_none().0,
80            );
81        }
82
83        self
84    }
85
86    /// Sets the context to be used for the texture. This is the context that owns
87    /// the texture.
88    ///
89    /// The context must be set before calling [`build()`][Self::build()].
90    /// ## `context`
91    /// The context the texture belongs to or [`None`] to unset
92    #[doc(alias = "gdk_gl_texture_builder_set_context")]
93    pub fn set_context(self, context: Option<&impl IsA<GLContext>>) -> Self {
94        unsafe {
95            ffi::gdk_gl_texture_builder_set_context(
96                self.to_glib_none().0,
97                context.map(|p| p.as_ref()).to_glib_none().0,
98            );
99        }
100
101        self
102    }
103
104    /// Sets the format of the texture. The default is `GDK_MEMORY_R8G8B8A8_PREMULTIPLIED`.
105    ///
106    /// The format is the preferred format the texture data should be downloaded to. The
107    /// format must be supported by the GL version of [`context`][struct@crate::GLTextureBuilder#context].
108    ///
109    /// GDK's texture download code assumes that the format corresponds to the storage
110    /// parameters of the GL texture in an obvious way. For example, a format of
111    /// `GDK_MEMORY_R16G16B16A16_PREMULTIPLIED` is expected to be stored as `GL_RGBA16`
112    /// texture, and `GDK_MEMORY_G8A8` is expected to be stored as `GL_RG8` texture.
113    ///
114    /// Setting the right format is particularly useful when using high bit depth textures
115    /// to preserve the bit depth, to set the correct value for unpremultiplied textures
116    /// and to make sure opaque textures are treated as such.
117    ///
118    /// Non-RGBA textures need to have swizzling parameters set up properly to be usable
119    /// in GSK's shaders.
120    /// ## `format`
121    /// The texture's format
122    #[doc(alias = "gdk_gl_texture_builder_set_format")]
123    pub fn set_format(self, format: MemoryFormat) -> Self {
124        unsafe {
125            ffi::gdk_gl_texture_builder_set_format(self.to_glib_none().0, format.into_glib());
126        }
127
128        self
129    }
130
131    /// Sets whether the texture has a mipmap. This allows the renderer and other users of the
132    /// generated texture to use a higher quality downscaling.
133    ///
134    /// Typically, the `glGenerateMipmap` function is used to generate a mimap.
135    /// ## `has_mipmap`
136    /// Whether the texture has a mipmap
137    #[doc(alias = "gdk_gl_texture_builder_set_has_mipmap")]
138    pub fn set_has_mipmap(self, has_mipmap: bool) -> Self {
139        unsafe {
140            ffi::gdk_gl_texture_builder_set_has_mipmap(
141                self.to_glib_none().0,
142                has_mipmap.into_glib(),
143            );
144        }
145
146        self
147    }
148
149    /// Sets the height of the texture.
150    ///
151    /// The height must be set before calling [`build()`][Self::build()].
152    /// ## `height`
153    /// The texture's height or 0 to unset
154    #[doc(alias = "gdk_gl_texture_builder_set_height")]
155    pub fn set_height(self, height: i32) -> Self {
156        unsafe {
157            ffi::gdk_gl_texture_builder_set_height(self.to_glib_none().0, height);
158        }
159
160        self
161    }
162
163    /// Sets the texture id of the texture. The texture id must remain unmodified
164    /// until the texture was finalized. See [`build()`][Self::build()]
165    /// for a longer discussion.
166    ///
167    /// The id must be set before calling [`build()`][Self::build()].
168    /// ## `id`
169    /// The texture id to be used for creating the texture
170    #[doc(alias = "gdk_gl_texture_builder_set_id")]
171    pub fn set_id(self, id: u32) -> Self {
172        unsafe {
173            ffi::gdk_gl_texture_builder_set_id(self.to_glib_none().0, id);
174        }
175
176        self
177    }
178
179    /// Sets the region to be updated by this texture. Together with
180    /// [`update-texture`][struct@crate::GLTextureBuilder#update-texture] this describes an
181    /// update of a previous texture.
182    ///
183    /// When rendering animations of large textures, it is possible that
184    /// consecutive textures are only updating contents in parts of the texture.
185    /// It is then possible to describe this update via these two properties,
186    /// so that GTK can avoid rerendering parts that did not change.
187    ///
188    /// An example would be a screen recording where only the mouse pointer moves.
189    /// ## `region`
190    /// the region to update
191    #[doc(alias = "gdk_gl_texture_builder_set_update_region")]
192    pub fn set_update_region(self, region: Option<&cairo::Region>) -> Self {
193        unsafe {
194            ffi::gdk_gl_texture_builder_set_update_region(
195                self.to_glib_none().0,
196                mut_override(region.to_glib_none().0),
197            );
198        }
199
200        self
201    }
202
203    /// Sets the texture to be updated by this texture. See
204    /// [`set_update_region()`][Self::set_update_region()] for an explanation.
205    /// ## `texture`
206    /// the texture to update
207    #[doc(alias = "gdk_gl_texture_builder_set_update_texture")]
208    pub fn set_update_texture(self, texture: Option<&impl IsA<Texture>>) -> Self {
209        unsafe {
210            ffi::gdk_gl_texture_builder_set_update_texture(
211                self.to_glib_none().0,
212                texture.map(|p| p.as_ref()).to_glib_none().0,
213            );
214        }
215
216        self
217    }
218
219    /// Sets the width of the texture.
220    ///
221    /// The width must be set before calling [`build()`][Self::build()].
222    /// ## `width`
223    /// The texture's width or 0 to unset
224    #[doc(alias = "gdk_gl_texture_builder_set_width")]
225    pub fn set_width(self, width: i32) -> Self {
226        unsafe {
227            ffi::gdk_gl_texture_builder_set_width(self.to_glib_none().0, width);
228        }
229
230        self
231    }
232
233    /// Gets the `GLsync` previously set via gdk_gl_texture_builder_set_sync().
234    ///
235    /// # Returns
236    ///
237    /// the `GLSync`
238    #[doc(alias = "gdk_gl_texture_builder_get_sync")]
239    #[doc(alias = "get_sync")]
240    pub fn sync(&self) -> Option<GLsync> {
241        let ptr = unsafe { ffi::gdk_gl_texture_builder_get_sync(self.to_glib_none().0) };
242        if ptr.is_null() {
243            None
244        } else {
245            Some(ptr as _)
246        }
247    }
248
249    /// Sets the GLSync object to use for the texture.
250    ///
251    /// GTK will wait on this object before using the created [`Texture`][crate::Texture].
252    ///
253    /// The `destroy` function that is passed to [`build()`][Self::build()]
254    /// is responsible for freeing the sync object when it is no longer needed.
255    /// The texture builder does not destroy it and it is the callers
256    /// responsibility to make sure it doesn't leak.
257    /// ## `sync`
258    /// the GLSync object
259    #[doc(alias = "gdk_gl_texture_builder_set_sync")]
260    pub fn set_sync(self, sync: Option<GLsync>) -> Self {
261        let ptr = sync.unwrap_or(std::ptr::null());
262        unsafe {
263            ffi::gdk_gl_texture_builder_set_sync(self.to_glib_none().0, ptr as _);
264        }
265
266        self
267    }
268}