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}