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}