cogl/auto/
texture.rs

1#![allow(
2    clippy::too_many_arguments,
3    clippy::let_and_return,
4    clippy::from_over_into
5)]
6
7use crate::{Bitmap, Object, PixelFormat, TextureComponents};
8
9use glib::object::IsA;
10use glib::translate::*;
11use std::{fmt, mem, ptr};
12
13glib_wrapper! {
14    pub struct Texture(Interface<ffi::CoglTexture>) @requires Object;
15
16    match fn {
17        get_type => || ffi::cogl_texture_get_gtype(),
18    }
19}
20
21pub const NONE_TEXTURE: Option<&Texture> = None;
22
23/// Trait containing all `Texture` methods.
24///
25/// # Implementors
26///
27/// [`Texture2DSliced`](struct.Texture2DSliced.html), [`Texture2D`](struct.Texture2D.html), [`Texture3D`](struct.Texture3D.html), [`TextureRectangle`](struct.TextureRectangle.html), [`Texture`](struct.Texture.html)
28pub trait TextureExt: 'static {
29    /// Explicitly allocates the storage for the given `self` which
30    /// allows you to be sure that there is enough memory for the
31    /// texture and if not then the error can be handled gracefully.
32    ///
33    /// `<note>`Normally applications don't need to use this api directly
34    /// since the texture will be implicitly allocated when data is set on
35    /// the texture, or if the texture is attached to a `CoglOffscreen`
36    /// framebuffer and rendered too.`</note>`
37    ///
38    /// # Returns
39    ///
40    /// `true` if the texture was successfully allocated,
41    ///  otherwise `false` and `error` will be updated if it
42    ///  wasn't `None`.
43    fn allocate(&self) -> Result<bool, glib::Error>;
44
45    /// Queries what components the given `self` stores internally as set
46    /// via `Texture::set_components`.
47    ///
48    /// For textures created by the ‘_with_size’ constructors the default
49    /// is `TextureComponents::Rgba`. The other constructors which take
50    /// a `Bitmap` or a data pointer default to the same components as
51    /// the pixel format of the data.
52    fn get_components(&self) -> TextureComponents;
53
54    /// Copies the pixel data from a cogl texture to system memory.
55    ///
56    /// `<note>`Don't pass the value of `cogl_texture_get_rowstride` as the
57    /// `rowstride` argument, the rowstride should be the rowstride you
58    /// want for the destination `data` buffer not the rowstride of the
59    /// source texture`</note>`
60    /// ## `format`
61    /// the `PixelFormat` to store the texture as.
62    /// ## `rowstride`
63    /// the rowstride of `data` in bytes or pass 0 to calculate
64    ///  from the bytes-per-pixel of `format` multiplied by the
65    ///  `self` width.
66    /// ## `data`
67    /// memory location to write the `self`'s contents, or `None`
68    /// to only query the data size through the return value.
69    ///
70    /// # Returns
71    ///
72    /// the size of the texture data in bytes
73    fn get_data(&self, format: PixelFormat, rowstride: u32, data: &[u8]) -> i32;
74
75    /// Queries the GL handles for a GPU side texture through its `Texture`.
76    ///
77    /// If the texture is spliced the data for the first sub texture will be
78    /// queried.
79    /// ## `out_gl_handle`
80    /// pointer to return location for the
81    ///  textures GL handle, or `None`.
82    /// ## `out_gl_target`
83    /// pointer to return location for the
84    ///  GL target type, or `None`.
85    ///
86    /// # Returns
87    ///
88    /// `true` if the handle was successfully retrieved, `false`
89    ///  if the handle was invalid
90    fn get_gl_texture(&self) -> (bool, u32, u32);
91
92    /// Queries the height of a cogl texture.
93    ///
94    /// # Returns
95    ///
96    /// the height of the GPU side texture in pixels
97    fn get_height(&self) -> u32;
98
99    /// Queries the maximum wasted (unused) pixels in one dimension of a GPU side
100    /// texture.
101    ///
102    /// # Returns
103    ///
104    /// the maximum waste
105    fn get_max_waste(&self) -> i32;
106
107    /// Queries the pre-multiplied alpha status for internally stored red,
108    /// green and blue components for the given `self` as set by
109    /// `Texture::set_premultiplied`.
110    ///
111    /// By default the pre-multipled state is `true`.
112    ///
113    /// # Returns
114    ///
115    /// `true` if red, green and blue components are
116    ///  internally stored pre-multiplied by the alpha
117    ///  value or `false` if not.
118    fn get_premultiplied(&self) -> bool;
119
120    /// Queries the width of a cogl texture.
121    ///
122    /// # Returns
123    ///
124    /// the width of the GPU side texture in pixels
125    fn get_width(&self) -> u32;
126
127    /// Queries if a texture is sliced (stored as multiple GPU side tecture
128    /// objects).
129    ///
130    /// # Returns
131    ///
132    /// `true` if the texture is sliced, `false` if the texture
133    ///  is stored as a single GPU texture
134    fn is_sliced(&self) -> bool;
135
136    /// Affects the internal storage format for this texture by specifying
137    /// what components will be required for sampling later.
138    ///
139    /// This api affects how data is uploaded to the GPU since unused
140    /// components can potentially be discarded from source data.
141    ///
142    /// For textures created by the ‘_with_size’ constructors the default
143    /// is `TextureComponents::Rgba`. The other constructors which take
144    /// a `Bitmap` or a data pointer default to the same components as
145    /// the pixel format of the data.
146    ///
147    /// Note that the `TextureComponents::Rg` format is not available
148    /// on all drivers. The availability can be determined by checking for
149    /// the `FeatureID::OglFeatureIdTextureRg` feature. If this format is used on
150    /// a driver where it is not available then `TextureError::Format`
151    /// will be raised when the texture is allocated. Even if the feature
152    /// is not available then `PixelFormat::Rg88` can still be used as
153    /// an image format as long as `TextureComponents::Rg` isn't used
154    /// as the texture's components.
155    fn set_components(&self, components: TextureComponents);
156
157    /// `self` a `Texture`.
158    /// Sets all the pixels for a given mipmap `level` by copying the pixel
159    /// data pointed to by the `data` argument into the given `self`.
160    ///
161    /// `data` should point to the first pixel to copy corresponding
162    /// to the top left of the mipmap `level` being set.
163    ///
164    /// If `rowstride` equals 0 then it will be automatically calculated
165    /// from the width of the mipmap level and the bytes-per-pixel for the
166    /// given `format`.
167    ///
168    /// A mipmap `level` of 0 corresponds to the largest, base image of a
169    /// texture and `level` 1 is half the width and height of level 0. If
170    /// dividing any dimension of the previous level by two results in a
171    /// fraction then round the number down (`floor`), but clamp to 1
172    /// something like this:
173    ///
174    ///
175    /// ```text
176    ///  next_width = MAX (1, floor (prev_width));
177    /// ```
178    ///
179    /// You can determine the number of mipmap levels for a given texture
180    /// like this:
181    ///
182    ///
183    /// ```text
184    ///  n_levels = 1 + floor (log2 (max_dimension));
185    /// ```
186    ///
187    /// Where `max_dimension` is the larger of `Texture::get_width` and
188    /// `Texture::get_height`.
189    ///
190    /// It is an error to pass a `level` number >= the number of levels that
191    /// `self` can have according to the above calculation.
192    ///
193    /// `<note>`Since the storage for a `Texture` is allocated lazily then
194    /// if the given `self` has not previously been allocated then this
195    /// api can return `false` and throw an exceptional `error` if there is
196    /// not enough memory to allocate storage for `self`.`</note>`
197    /// ## `format`
198    /// the `PixelFormat` used in the source `data` buffer.
199    /// ## `rowstride`
200    /// rowstride of the source `data` buffer (computed from
201    ///  the texture width and `format` if it equals 0)
202    /// ## `data`
203    /// the source data, pointing to the first top-left pixel to set
204    /// ## `level`
205    /// The mipmap level to update (Normally 0 for the largest,
206    ///  base texture)
207    ///
208    /// # Returns
209    ///
210    /// `true` if the data upload was successful, and
211    ///  `false` otherwise
212    fn set_data(
213        &self,
214        format: PixelFormat,
215        rowstride: i32,
216        data: &[u8],
217        level: i32,
218    ) -> Result<bool, glib::Error>;
219
220    /// Affects the internal storage format for this texture by specifying
221    /// whether red, green and blue color components should be stored as
222    /// pre-multiplied alpha values.
223    ///
224    /// This api affects how data is uploaded to the GPU since Cogl will
225    /// convert source data to have premultiplied or unpremultiplied
226    /// components according to this state.
227    ///
228    /// For example if you create a texture via
229    /// `Texture2D::new_with_size` and then upload data via
230    /// `Texture::set_data` passing a source format of
231    /// `PixelFormat::Rgba8888` then Cogl will internally multiply the
232    /// red, green and blue components of the source data by the alpha
233    /// component, for each pixel so that the internally stored data has
234    /// pre-multiplied alpha components. If you instead upload data that
235    /// already has pre-multiplied components by passing
236    /// `PixelFormat::Rgba8888Pre` as the source format to
237    /// `Texture::set_data` then the data can be uploaded without being
238    /// converted.
239    ///
240    /// By default the `premultipled` state is `true`.
241    /// ## `premultiplied`
242    /// Whether any internally stored red, green or blue
243    ///  components are pre-multiplied by an alpha
244    ///  component.
245    fn set_premultiplied(&self, premultiplied: bool);
246
247    /// Sets the pixels in a rectangular subregion of `self` from an in-memory
248    /// buffer containing pixel data.
249    ///
250    /// `<note>`The region set can't be larger than the source `data``</note>`
251    /// ## `src_x`
252    /// upper left coordinate to use from source data.
253    /// ## `src_y`
254    /// upper left coordinate to use from source data.
255    /// ## `dst_x`
256    /// upper left destination horizontal coordinate.
257    /// ## `dst_y`
258    /// upper left destination vertical coordinate.
259    /// ## `dst_width`
260    /// width of destination region to write. (Must be less
261    ///  than or equal to `width`)
262    /// ## `dst_height`
263    /// height of destination region to write. (Must be less
264    ///  than or equal to `height`)
265    /// ## `width`
266    /// width of source data buffer.
267    /// ## `height`
268    /// height of source data buffer.
269    /// ## `format`
270    /// the `PixelFormat` used in the source buffer.
271    /// ## `rowstride`
272    /// rowstride of source buffer (computed from width if none
273    /// specified)
274    /// ## `data`
275    /// the actual pixel data.
276    ///
277    /// # Returns
278    ///
279    /// `true` if the subregion upload was successful, and
280    ///  `false` otherwise
281    fn set_region(
282        &self,
283        src_x: i32,
284        src_y: i32,
285        dst_x: i32,
286        dst_y: i32,
287        dst_width: u32,
288        dst_height: u32,
289        width: i32,
290        height: i32,
291        format: PixelFormat,
292        rowstride: u32,
293        data: &[u8],
294    ) -> bool;
295
296    /// Copies a specified source region from `bitmap` to the position
297    /// (`src_x`, `src_y`) of the given destination texture `handle`.
298    ///
299    /// `<note>`The region updated can't be larger than the source
300    /// bitmap`</note>`
301    /// ## `src_x`
302    /// upper left coordinate to use from the source bitmap.
303    /// ## `src_y`
304    /// upper left coordinate to use from the source bitmap
305    /// ## `dst_x`
306    /// upper left destination horizontal coordinate.
307    /// ## `dst_y`
308    /// upper left destination vertical coordinate.
309    /// ## `dst_width`
310    /// width of destination region to write. (Must be less
311    ///  than or equal to the bitmap width)
312    /// ## `dst_height`
313    /// height of destination region to write. (Must be less
314    ///  than or equal to the bitmap height)
315    /// ## `bitmap`
316    /// The source bitmap to read from
317    ///
318    /// # Returns
319    ///
320    /// `true` if the subregion upload was successful, and
321    ///  `false` otherwise
322    fn set_region_from_bitmap(
323        &self,
324        src_x: i32,
325        src_y: i32,
326        dst_x: i32,
327        dst_y: i32,
328        dst_width: u32,
329        dst_height: u32,
330        bitmap: &Bitmap,
331    ) -> bool;
332}
333
334impl<O: IsA<Texture>> TextureExt for O {
335    fn allocate(&self) -> Result<bool, glib::Error> {
336        unsafe {
337            let mut error = ptr::null_mut();
338            let ret = ffi::cogl_texture_allocate(self.as_ref().to_glib_none().0, &mut error);
339            if error.is_null() {
340                Ok(ret == crate::TRUE)
341            } else {
342                Err(from_glib_full(error))
343            }
344        }
345    }
346
347    fn get_components(&self) -> TextureComponents {
348        unsafe {
349            from_glib(ffi::cogl_texture_get_components(
350                self.as_ref().to_glib_none().0,
351            ))
352        }
353    }
354
355    fn get_data(&self, format: PixelFormat, rowstride: u32, data: &[u8]) -> i32 {
356        unsafe {
357            ffi::cogl_texture_get_data(
358                self.as_ref().to_glib_none().0,
359                format.to_glib(),
360                rowstride,
361                data.to_glib_none().0,
362            )
363        }
364    }
365
366    fn get_gl_texture(&self) -> (bool, u32, u32) {
367        unsafe {
368            let mut out_gl_handle = mem::MaybeUninit::uninit();
369            let mut out_gl_target = mem::MaybeUninit::uninit();
370            let ret = ffi::cogl_texture_get_gl_texture(
371                self.as_ref().to_glib_none().0,
372                out_gl_handle.as_mut_ptr(),
373                out_gl_target.as_mut_ptr(),
374            );
375            let out_gl_handle = out_gl_handle.assume_init();
376            let out_gl_target = out_gl_target.assume_init();
377            (ret == crate::TRUE, out_gl_handle, out_gl_target)
378        }
379    }
380
381    fn get_height(&self) -> u32 {
382        unsafe { ffi::cogl_texture_get_height(self.as_ref().to_glib_none().0) }
383    }
384
385    fn get_max_waste(&self) -> i32 {
386        unsafe { ffi::cogl_texture_get_max_waste(self.as_ref().to_glib_none().0) }
387    }
388
389    fn get_premultiplied(&self) -> bool {
390        unsafe {
391            ffi::cogl_texture_get_premultiplied(self.as_ref().to_glib_none().0) == crate::TRUE
392        }
393    }
394
395    fn get_width(&self) -> u32 {
396        unsafe { ffi::cogl_texture_get_width(self.as_ref().to_glib_none().0) }
397    }
398
399    fn is_sliced(&self) -> bool {
400        unsafe { ffi::cogl_texture_is_sliced(self.as_ref().to_glib_none().0) == crate::TRUE }
401    }
402
403    fn set_components(&self, components: TextureComponents) {
404        unsafe {
405            ffi::cogl_texture_set_components(self.as_ref().to_glib_none().0, components.to_glib());
406        }
407    }
408
409    fn set_data(
410        &self,
411        format: PixelFormat,
412        rowstride: i32,
413        data: &[u8],
414        level: i32,
415    ) -> Result<bool, glib::Error> {
416        unsafe {
417            let mut error = ptr::null_mut();
418            let ret = ffi::cogl_texture_set_data(
419                self.as_ref().to_glib_none().0,
420                format.to_glib(),
421                rowstride,
422                data.to_glib_none().0,
423                level,
424                &mut error,
425            );
426            if error.is_null() {
427                Ok(ret == crate::TRUE)
428            } else {
429                Err(from_glib_full(error))
430            }
431        }
432    }
433
434    fn set_premultiplied(&self, premultiplied: bool) {
435        unsafe {
436            ffi::cogl_texture_set_premultiplied(
437                self.as_ref().to_glib_none().0,
438                premultiplied as i32,
439            );
440        }
441    }
442
443    fn set_region(
444        &self,
445        src_x: i32,
446        src_y: i32,
447        dst_x: i32,
448        dst_y: i32,
449        dst_width: u32,
450        dst_height: u32,
451        width: i32,
452        height: i32,
453        format: PixelFormat,
454        rowstride: u32,
455        data: &[u8],
456    ) -> bool {
457        unsafe {
458            ffi::cogl_texture_set_region(
459                self.as_ref().to_glib_none().0,
460                src_x,
461                src_y,
462                dst_x,
463                dst_y,
464                dst_width,
465                dst_height,
466                width,
467                height,
468                format.to_glib(),
469                rowstride,
470                data.as_ptr(),
471            ) == crate::TRUE
472        }
473    }
474
475    fn set_region_from_bitmap(
476        &self,
477        src_x: i32,
478        src_y: i32,
479        dst_x: i32,
480        dst_y: i32,
481        dst_width: u32,
482        dst_height: u32,
483        bitmap: &Bitmap,
484    ) -> bool {
485        unsafe {
486            ffi::cogl_texture_set_region_from_bitmap(
487                self.as_ref().to_glib_none().0,
488                src_x,
489                src_y,
490                dst_x,
491                dst_y,
492                dst_width,
493                dst_height,
494                bitmap.to_glib_none().0,
495            ) == crate::TRUE
496        }
497    }
498}
499
500impl fmt::Display for Texture {
501    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
502        write!(f, "Texture")
503    }
504}