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}