Skip to main content

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