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}