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}