gdk4/
dmabuf_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, Display, DmabufTextureBuilder, Texture};
8
9impl DmabufTextureBuilder {
10    /// Sets the color state for the texture.
11    ///
12    /// By default, the colorstate is `NULL`. In that case, GTK will choose the
13    /// correct colorstate based on the format.
14    /// If you don't know what colorstates are, this is probably the right thing.
15    /// ## `color_state`
16    /// a [`ColorState`][crate::ColorState] or `NULL` to unset the colorstate.
17    #[cfg(feature = "v4_16")]
18    #[cfg_attr(docsrs, doc(cfg(feature = "v4_16")))]
19    #[doc(alias = "gdk_dmabuf_texture_builder_set_color_state")]
20    #[doc(alias = "color-state")]
21    pub fn set_color_state(self, color_state: Option<&ColorState>) -> Self {
22        unsafe {
23            ffi::gdk_dmabuf_texture_builder_set_color_state(
24                self.to_glib_none().0,
25                color_state.to_glib_none().0,
26            );
27        }
28
29        self
30    }
31
32    /// Sets the display that this texture builder is
33    /// associated with.
34    ///
35    /// The display is used to determine the supported
36    /// dma-buf formats.
37    /// ## `display`
38    /// the display
39    #[doc(alias = "gdk_dmabuf_texture_builder_set_display")]
40    #[doc(alias = "display")]
41    pub fn set_display(self, display: &impl IsA<Display>) -> Self {
42        unsafe {
43            ffi::gdk_dmabuf_texture_builder_set_display(
44                self.to_glib_none().0,
45                display.as_ref().to_glib_none().0,
46            );
47        }
48
49        self
50    }
51
52    // rustdoc-stripper-ignore-next
53    /// # Safety
54    ///
55    /// The caller must ensure that `fd` says valid for at least as long as the texture, e.g. by
56    /// using `build_with_release_func()` to get notified when `fd` is not used anymore.
57    // rustdoc-stripper-ignore-next-stop
58    /// Sets the file descriptor for a plane.
59    /// ## `plane`
60    /// the plane to set the fd for
61    /// ## `fd`
62    /// the file descriptor
63    #[doc(alias = "gdk_dmabuf_texture_builder_set_fd")]
64    pub unsafe fn set_fd(self, plane: u32, fd: std::os::fd::RawFd) -> Self {
65        unsafe {
66            ffi::gdk_dmabuf_texture_builder_set_fd(self.to_glib_none().0, plane, fd);
67        }
68
69        self
70    }
71
72    /// Gets the file descriptor for a plane.
73    /// ## `plane`
74    /// the plane to get the fd for
75    ///
76    /// # Returns
77    ///
78    /// the file descriptor
79    #[doc(alias = "gdk_dmabuf_texture_builder_get_fd")]
80    #[doc(alias = "get_fd")]
81    pub fn fd(&self, plane: u32) -> Option<std::os::fd::BorrowedFd<'_>> {
82        unsafe {
83            let fd = ffi::gdk_dmabuf_texture_builder_get_fd(self.to_glib_none().0, plane);
84
85            if fd == -1 {
86                None
87            } else {
88                Some(std::os::fd::BorrowedFd::borrow_raw(fd))
89            }
90        }
91    }
92
93    /// Sets the format of the texture.
94    ///
95    /// The format is specified as a fourcc code.
96    ///
97    /// The format must be set before calling [`build()`][Self::build()].
98    /// ## `fourcc`
99    /// the texture's format or 0 to unset
100    #[doc(alias = "gdk_dmabuf_texture_builder_set_fourcc")]
101    #[doc(alias = "fourcc")]
102    pub fn set_fourcc(self, fourcc: u32) -> Self {
103        unsafe {
104            ffi::gdk_dmabuf_texture_builder_set_fourcc(self.to_glib_none().0, fourcc);
105        }
106
107        self
108    }
109
110    /// Sets the height of the texture.
111    ///
112    /// The height must be set before calling [`build()`][Self::build()].
113    /// ## `height`
114    /// the texture's height or 0 to unset
115    #[doc(alias = "gdk_dmabuf_texture_builder_set_height")]
116    #[doc(alias = "height")]
117    pub fn set_height(self, height: u32) -> Self {
118        unsafe {
119            ffi::gdk_dmabuf_texture_builder_set_height(self.to_glib_none().0, height);
120        }
121
122        self
123    }
124
125    /// Sets the modifier.
126    /// ## `modifier`
127    /// the modifier value
128    #[doc(alias = "gdk_dmabuf_texture_builder_set_modifier")]
129    #[doc(alias = "modifier")]
130    pub fn set_modifier(self, modifier: u64) -> Self {
131        unsafe {
132            ffi::gdk_dmabuf_texture_builder_set_modifier(self.to_glib_none().0, modifier);
133        }
134
135        self
136    }
137
138    /// Sets the number of planes of the texture.
139    /// ## `n_planes`
140    /// the number of planes
141    #[doc(alias = "gdk_dmabuf_texture_builder_set_n_planes")]
142    #[doc(alias = "n-planes")]
143    pub fn set_n_planes(self, n_planes: u32) -> Self {
144        unsafe {
145            ffi::gdk_dmabuf_texture_builder_set_n_planes(self.to_glib_none().0, n_planes);
146        }
147
148        self
149    }
150
151    /// Sets the offset for a plane.
152    /// ## `plane`
153    /// the plane to set the offset for
154    /// ## `offset`
155    /// the offset value
156    #[doc(alias = "gdk_dmabuf_texture_builder_set_offset")]
157    pub fn set_offset(self, plane: u32, offset: u32) -> Self {
158        unsafe {
159            ffi::gdk_dmabuf_texture_builder_set_offset(self.to_glib_none().0, plane, offset);
160        }
161
162        self
163    }
164
165    /// Sets whether the data is premultiplied.
166    ///
167    /// Unless otherwise specified, all formats including alpha channels are assumed
168    /// to be premultiplied.
169    /// ## `premultiplied`
170    /// whether the data is premultiplied
171    #[doc(alias = "gdk_dmabuf_texture_builder_set_premultiplied")]
172    #[doc(alias = "premultiplied")]
173    pub fn set_premultiplied(self, premultiplied: bool) -> Self {
174        unsafe {
175            ffi::gdk_dmabuf_texture_builder_set_premultiplied(
176                self.to_glib_none().0,
177                premultiplied.into_glib(),
178            );
179        }
180
181        self
182    }
183
184    /// Sets the stride for a plane.
185    ///
186    /// The stride must be set for all planes before calling [`build()`][Self::build()].
187    /// ## `plane`
188    /// the plane to set the stride for
189    /// ## `stride`
190    /// the stride value
191    #[doc(alias = "gdk_dmabuf_texture_builder_set_stride")]
192    pub fn set_stride(self, plane: u32, stride: u32) -> Self {
193        unsafe {
194            ffi::gdk_dmabuf_texture_builder_set_stride(self.to_glib_none().0, plane, stride);
195        }
196
197        self
198    }
199
200    /// Sets the region to be updated by this texture. Together with
201    /// [`update-texture`][struct@crate::DmabufTextureBuilder#update-texture] this describes an
202    /// update of a previous texture.
203    ///
204    /// When rendering animations of large textures, it is possible that
205    /// consecutive textures are only updating contents in parts of the texture.
206    /// It is then possible to describe this update via these two properties,
207    /// so that GTK can avoid rerendering parts that did not change.
208    ///
209    /// An example would be a screen recording where only the mouse pointer moves.
210    /// ## `region`
211    /// the region to update
212    #[doc(alias = "gdk_dmabuf_texture_builder_set_update_region")]
213    #[doc(alias = "update-region")]
214    pub fn set_update_region(self, region: Option<&cairo::Region>) -> Self {
215        unsafe {
216            ffi::gdk_dmabuf_texture_builder_set_update_region(
217                self.to_glib_none().0,
218                mut_override(region.to_glib_none().0),
219            );
220        }
221
222        self
223    }
224
225    /// Sets the texture to be updated by this texture. See
226    /// [`set_update_region()`][Self::set_update_region()] for an explanation.
227    /// ## `texture`
228    /// the texture to update
229    #[doc(alias = "gdk_dmabuf_texture_builder_set_update_texture")]
230    #[doc(alias = "update-texture")]
231    pub fn set_update_texture(self, texture: Option<&impl IsA<Texture>>) -> Self {
232        unsafe {
233            ffi::gdk_dmabuf_texture_builder_set_update_texture(
234                self.to_glib_none().0,
235                texture.map(|p| p.as_ref()).to_glib_none().0,
236            );
237        }
238
239        self
240    }
241
242    /// Sets the width of the texture.
243    ///
244    /// The width must be set before calling [`build()`][Self::build()].
245    /// ## `width`
246    /// The texture's width or 0 to unset
247    #[doc(alias = "gdk_dmabuf_texture_builder_set_width")]
248    #[doc(alias = "width")]
249    pub fn set_width(self, width: u32) -> Self {
250        unsafe {
251            ffi::gdk_dmabuf_texture_builder_set_width(self.to_glib_none().0, width);
252        }
253
254        self
255    }
256
257    /// Builds a new [`Texture`][crate::Texture] with the values set up in the builder.
258    ///
259    /// It is a programming error to call this function if any mandatory property has not been set.
260    ///
261    /// Not all formats defined in the `drm_fourcc.h` header are supported. You can use
262    /// [`DisplayExt::dmabuf_formats()`][crate::prelude::DisplayExt::dmabuf_formats()] to get a list of supported formats. If the
263    /// format is not supported by GTK, [`None`] will be returned and @error will be set.
264    ///
265    /// The `destroy` function gets called when the returned texture gets released.
266    ///
267    /// It is the responsibility of the caller to keep the file descriptors for the planes
268    /// open until the created texture is no longer used, and close them afterwards (possibly
269    /// using the @destroy notify).
270    ///
271    /// It is possible to call this function multiple times to create multiple textures,
272    /// possibly with changing properties in between.
273    ///
274    /// # Returns
275    ///
276    /// a newly built [`Texture`][crate::Texture] or `NULL`
277    ///   if the format is not supported
278    #[doc(alias = "gdk_dmabuf_texture_builder_build")]
279    #[must_use = "The builder must be built to be used"]
280    #[allow(clippy::missing_safety_doc)]
281    pub unsafe fn build(self) -> Result<Texture, glib::Error> {
282        let mut error = std::ptr::null_mut();
283
284        let result = ffi::gdk_dmabuf_texture_builder_build(
285            self.to_glib_none().0,
286            None,
287            std::ptr::null_mut(),
288            &mut error,
289        );
290        if error.is_null() {
291            if result.is_null() {
292                Err(glib::Error::new(
293                    crate::DmabufError::UnsupportedFormat,
294                    "Unsupported format",
295                ))
296            } else {
297                Ok(from_glib_full(result))
298            }
299        } else {
300            Err(from_glib_full(error))
301        }
302    }
303
304    #[doc(alias = "gdk_dmabuf_texture_builder_build")]
305    #[must_use = "The builder must be built to be used"]
306    #[allow(clippy::missing_safety_doc)]
307    pub unsafe fn build_with_release_func<F: FnOnce() + Send + 'static>(
308        self,
309        release_func: F,
310    ) -> Result<Texture, glib::Error> {
311        let mut error = std::ptr::null_mut();
312        unsafe extern "C" fn destroy_closure<F: FnOnce() + Send + 'static>(
313            func: glib::ffi::gpointer,
314        ) {
315            let released_func = Box::<F>::from_raw(func as *mut _);
316            released_func();
317        }
318        let released_func = Box::new(release_func);
319        let result = ffi::gdk_dmabuf_texture_builder_build(
320            self.to_glib_none().0,
321            Some(destroy_closure::<F>),
322            Box::into_raw(released_func) as glib::ffi::gpointer,
323            &mut error,
324        );
325        if error.is_null() {
326            if result.is_null() {
327                Err(glib::Error::new(
328                    crate::DmabufError::UnsupportedFormat,
329                    "Unsupported format",
330                ))
331            } else {
332                Ok(from_glib_full(result))
333            }
334        } else {
335            Err(from_glib_full(error))
336        }
337    }
338}