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