fyrox_graphics/
gpu_texture.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Texture is an image that used to fill faces to add details to them. It could also be used as a
22//! generic and mostly unlimited capacity storage for arbitrary data.
23
24#![warn(missing_docs)]
25
26use crate::{
27    core::{color::Color, Downcast},
28    define_shared_wrapper,
29    error::FrameworkError,
30};
31use bytemuck::Pod;
32
33/// A kind of GPU texture.
34#[derive(Copy, Clone)]
35pub enum GpuTextureKind {
36    /// 1D texture.
37    Line {
38        /// Length of the texture.
39        length: usize,
40    },
41    /// 2D texture.
42    Rectangle {
43        /// Width of the texture.
44        width: usize,
45        /// Height of the texture.
46        height: usize,
47    },
48    /// Six 2D textures forming a cube.
49    Cube {
50        /// Width of the texture.
51        width: usize,
52        /// Height of the texture.
53        height: usize,
54    },
55    /// Volumetric texture that consists of `depth` textures with `width x height` size.
56    Volume {
57        /// Width of the texture.
58        width: usize,
59        /// Height of the texture.
60        height: usize,
61        /// Depth of the texture.
62        depth: usize,
63    },
64}
65
66/// Pixel kind of GPU texture.
67#[derive(Copy, Clone, Debug, PartialEq)]
68pub enum PixelKind {
69    /// Floating point 32-bit pixel.
70    R32F,
71    /// Unsigned integer 32-bit pixel.
72    R32UI,
73    /// Floating point 16-bit pixel.
74    R16F,
75    /// Floating point 32-bit depth pixel.
76    D32F,
77    /// Integer 16-bit depth pixel.
78    D16,
79    /// Integer 24-bit depth pixel + 8-bit stencil.
80    D24S8,
81    /// Red, Green, Blue, Alpha; all by 8-bit.
82    RGBA8,
83    /// Red, Green, Blue, Alpha in sRGB color space; all by 8-bit.
84    SRGBA8,
85    /// Red, Green, Blue; all by 8-bit.
86    RGB8,
87    /// Red, Green, Blue in sRGB color space; all by 8-bit.
88    SRGB8,
89    /// Blue, Green, Red, Alpha; all by 8-bit.
90    BGRA8,
91    /// Blue, Green, Red; all by 8-bit.
92    BGR8,
93    /// Red, Green; all by 8-bit.
94    RG8,
95    /// Luminance, Alpha; all by 8-bit.
96    LA8,
97    /// Luminance, Alpha; all by 16-bit.
98    LA16,
99    /// Red, Green; all by 16-bit.
100    RG16,
101    /// Red, Green; 16-bit.
102    R8,
103    /// Luminance; 8-bit.
104    L8,
105    /// Luminance; 16-bit.
106    L16,
107    /// Red, unsigned integer; 8-bit.
108    R8UI,
109    /// Red, signed integer; 16-bit.
110    R16,
111    /// Red, Green, Blue; all by 16-bit.
112    RGB16,
113    /// Red, Green, Blue, Alpha; all by 8-bit.
114    RGBA16,
115    /// Compressed S3TC DXT1 RGB.
116    DXT1RGB,
117    /// Compressed S3TC DXT1 RGBA.
118    DXT1RGBA,
119    /// Compressed S3TC DXT3 RGBA.
120    DXT3RGBA,
121    /// Compressed S3TC DXT5 RGBA.
122    DXT5RGBA,
123    /// Floating-point RGB texture with 32-bit depth.
124    RGB32F,
125    /// Floating-point RGBA texture with 32-bit depth.
126    RGBA32F,
127    /// Floating-point RGB texture with 16-bit depth.
128    RGB16F,
129    /// Floating-point RGBA texture with 16-bit depth.
130    RGBA16F,
131    /// Compressed R8 texture (RGTC).
132    R8RGTC,
133    /// Compressed RG8 texture (RGTC).
134    RG8RGTC,
135    /// Floating-point RGB texture with 11-bit for Red and Green channels, 10-bit for Blue channel.
136    R11G11B10F,
137    /// Red, Green, Blue (8-bit) + Alpha (2-bit).
138    RGB10A2,
139}
140
141/// Element kind of pixel.
142pub enum PixelElementKind {
143    /// Floating-point pixel.
144    Float,
145    /// Normalized unsigned integer.
146    NormalizedUnsignedInteger,
147    /// Integer.
148    Integer,
149    /// Unsigned integer.
150    UnsignedInteger,
151}
152
153impl PixelKind {
154    pub(crate) fn unpack_alignment(self) -> Option<i32> {
155        match self {
156            Self::RGBA16
157            | Self::RGBA16F
158            | Self::RGB16
159            | Self::RGB16F
160            | Self::RGBA32F
161            | Self::RGB32F
162            | Self::RGBA8
163            | Self::SRGBA8
164            | Self::BGRA8
165            | Self::RG16
166            | Self::LA16
167            | Self::D24S8
168            | Self::D32F
169            | Self::R32F
170            | Self::R32UI
171            | Self::RGB10A2 => Some(4),
172            Self::RG8 | Self::LA8 | Self::D16 | Self::R16F | Self::L16 | Self::R16 => Some(2),
173            Self::R8
174            | Self::L8
175            | Self::R8UI
176            | Self::SRGB8
177            | Self::RGB8
178            | Self::BGR8
179            | Self::R11G11B10F => Some(1),
180            Self::DXT1RGB
181            | Self::DXT1RGBA
182            | Self::DXT3RGBA
183            | Self::DXT5RGBA
184            | Self::R8RGTC
185            | Self::RG8RGTC => None,
186        }
187    }
188
189    /// Returns `true` if the pixel kind is compressed, `false` - otherwise.
190    pub fn is_compressed(self) -> bool {
191        match self {
192            Self::DXT1RGB
193            | Self::DXT1RGBA
194            | Self::DXT3RGBA
195            | Self::DXT5RGBA
196            | Self::R8RGTC
197            | Self::RG8RGTC => true,
198            // Explicit match for rest of formats instead of _ will help to not forget
199            // to add new entry here.
200            Self::RGBA16
201            | Self::RGBA16F
202            | Self::RGB16
203            | Self::RGB16F
204            | Self::RGBA8
205            | Self::SRGBA8
206            | Self::RGB8
207            | Self::SRGB8
208            | Self::BGRA8
209            | Self::BGR8
210            | Self::RG16
211            | Self::R16
212            | Self::D24S8
213            | Self::D32F
214            | Self::R32F
215            | Self::R32UI
216            | Self::RG8
217            | Self::D16
218            | Self::R16F
219            | Self::R8
220            | Self::R8UI
221            | Self::RGB32F
222            | Self::RGBA32F
223            | Self::R11G11B10F
224            | Self::RGB10A2
225            | Self::L8
226            | Self::LA8
227            | Self::L16
228            | Self::LA16 => false,
229        }
230    }
231
232    /// Returns element kind of the pixel.
233    pub fn element_kind(self) -> PixelElementKind {
234        match self {
235            Self::R32F
236            | Self::R16F
237            | Self::RGB32F
238            | Self::RGBA32F
239            | Self::RGBA16F
240            | Self::RGB16F
241            | Self::D32F
242            | Self::R11G11B10F => PixelElementKind::Float,
243            Self::D16
244            | Self::D24S8
245            | Self::RGBA8
246            | Self::SRGBA8
247            | Self::RGB8
248            | Self::SRGB8
249            | Self::BGRA8
250            | Self::BGR8
251            | Self::RG8
252            | Self::RG16
253            | Self::R8
254            | Self::R16
255            | Self::RGB16
256            | Self::RGBA16
257            | Self::DXT1RGB
258            | Self::DXT1RGBA
259            | Self::DXT3RGBA
260            | Self::DXT5RGBA
261            | Self::R8RGTC
262            | Self::RG8RGTC
263            | Self::RGB10A2
264            | Self::LA8
265            | Self::L8
266            | Self::LA16
267            | Self::L16 => PixelElementKind::NormalizedUnsignedInteger,
268            Self::R8UI | Self::R32UI => PixelElementKind::UnsignedInteger,
269        }
270    }
271}
272
273fn ceil_div_4(x: usize) -> usize {
274    (x + 3) / 4
275}
276
277/// Calculates size in bytes of a volume texture using the given size of the texture and its pixel
278/// kind.
279pub fn image_3d_size_bytes(
280    pixel_kind: PixelKind,
281    width: usize,
282    height: usize,
283    depth: usize,
284) -> usize {
285    let pixel_count = width * height * depth;
286    match pixel_kind {
287        PixelKind::RGBA32F => 16 * pixel_count,
288        PixelKind::RGB32F => 12 * pixel_count,
289        PixelKind::RGBA16 | PixelKind::RGBA16F => 8 * pixel_count,
290        PixelKind::RGB16 | PixelKind::RGB16F => 6 * pixel_count,
291        PixelKind::RGBA8
292        | PixelKind::SRGBA8
293        | PixelKind::BGRA8
294        | PixelKind::RG16
295        | PixelKind::LA16
296        | PixelKind::D24S8
297        | PixelKind::D32F
298        | PixelKind::R32F
299        | PixelKind::R32UI
300        | PixelKind::R11G11B10F
301        | PixelKind::RGB10A2 => 4 * pixel_count,
302        PixelKind::RGB8 | PixelKind::SRGB8 | PixelKind::BGR8 => 3 * pixel_count,
303        PixelKind::RG8
304        | PixelKind::LA8
305        | PixelKind::R16
306        | PixelKind::L16
307        | PixelKind::D16
308        | PixelKind::R16F => 2 * pixel_count,
309        PixelKind::R8 | PixelKind::L8 | PixelKind::R8UI => pixel_count,
310        PixelKind::DXT1RGB | PixelKind::DXT1RGBA | PixelKind::R8RGTC => {
311            let block_size = 8;
312            ceil_div_4(width) * ceil_div_4(height) * ceil_div_4(depth) * block_size
313        }
314        PixelKind::DXT3RGBA | PixelKind::DXT5RGBA | PixelKind::RG8RGTC => {
315            let block_size = 16;
316            ceil_div_4(width) * ceil_div_4(height) * ceil_div_4(depth) * block_size
317        }
318    }
319}
320
321/// Calculates size in bytes of a rectangular texture using the given size of the texture and its pixel
322/// kind.
323pub fn image_2d_size_bytes(pixel_kind: PixelKind, width: usize, height: usize) -> usize {
324    let pixel_count = width * height;
325    match pixel_kind {
326        PixelKind::RGBA32F => 16 * pixel_count,
327        PixelKind::RGB32F => 12 * pixel_count,
328        PixelKind::RGBA16 | PixelKind::RGBA16F => 8 * pixel_count,
329        PixelKind::RGB16 | PixelKind::RGB16F => 6 * pixel_count,
330        PixelKind::RGBA8
331        | PixelKind::SRGBA8
332        | PixelKind::BGRA8
333        | PixelKind::RG16
334        | PixelKind::LA16
335        | PixelKind::D24S8
336        | PixelKind::D32F
337        | PixelKind::R32F
338        | PixelKind::R32UI
339        | PixelKind::R11G11B10F
340        | PixelKind::RGB10A2 => 4 * pixel_count,
341        PixelKind::RGB8 | PixelKind::SRGB8 | PixelKind::BGR8 => 3 * pixel_count,
342        PixelKind::RG8
343        | PixelKind::LA8
344        | PixelKind::R16
345        | PixelKind::L16
346        | PixelKind::D16
347        | PixelKind::R16F => 2 * pixel_count,
348        PixelKind::R8 | PixelKind::L8 | PixelKind::R8UI => pixel_count,
349        PixelKind::DXT1RGB | PixelKind::DXT1RGBA | PixelKind::R8RGTC => {
350            let block_size = 8;
351            ceil_div_4(width) * ceil_div_4(height) * block_size
352        }
353        PixelKind::DXT3RGBA | PixelKind::DXT5RGBA | PixelKind::RG8RGTC => {
354            let block_size = 16;
355            ceil_div_4(width) * ceil_div_4(height) * block_size
356        }
357    }
358}
359
360/// Calculates size in bytes of a linear texture using the given size of the texture and its pixel
361/// kind.
362pub fn image_1d_size_bytes(pixel_kind: PixelKind, length: usize) -> usize {
363    match pixel_kind {
364        PixelKind::RGBA32F => 16 * length,
365        PixelKind::RGB32F => 12 * length,
366        PixelKind::RGBA16 | PixelKind::RGBA16F => 8 * length,
367        PixelKind::RGB16 | PixelKind::RGB16F => 6 * length,
368        PixelKind::RGBA8
369        | PixelKind::SRGBA8
370        | PixelKind::BGRA8
371        | PixelKind::RG16
372        | PixelKind::LA16
373        | PixelKind::D24S8
374        | PixelKind::D32F
375        | PixelKind::R32F
376        | PixelKind::R32UI
377        | PixelKind::R11G11B10F
378        | PixelKind::RGB10A2 => 4 * length,
379        PixelKind::RGB8 | PixelKind::SRGB8 | PixelKind::BGR8 => 3 * length,
380        PixelKind::RG8
381        | PixelKind::LA8
382        | PixelKind::L16
383        | PixelKind::R16
384        | PixelKind::D16
385        | PixelKind::R16F => 2 * length,
386        PixelKind::R8 | PixelKind::L8 | PixelKind::R8UI => length,
387        PixelKind::DXT1RGB | PixelKind::DXT1RGBA | PixelKind::R8RGTC => {
388            let block_size = 8;
389            ceil_div_4(length) * block_size
390        }
391        PixelKind::DXT3RGBA | PixelKind::DXT5RGBA | PixelKind::RG8RGTC => {
392            let block_size = 16;
393            ceil_div_4(length) * block_size
394        }
395    }
396}
397
398/// The texture magnification function is used when the pixel being textured maps to an area
399/// less than or equal to one texture element.
400#[derive(Default, Copy, Clone, PartialOrd, PartialEq, Eq, Hash, Debug)]
401#[repr(u32)]
402pub enum MagnificationFilter {
403    /// Returns the value of the texture element that is nearest to the center of the pixel
404    /// being textured.
405    Nearest,
406    /// Returns the weighted average of the four texture elements that are closest to the
407    /// center of the pixel being textured.
408    #[default]
409    Linear,
410}
411
412/// The texture minifying function is used whenever the pixel being textured maps to an area
413/// greater than one texture element.
414#[derive(Default, Copy, Clone, PartialOrd, PartialEq, Eq, Hash, Debug)]
415pub enum MinificationFilter {
416    /// Returns the value of the texture element that is nearest to the center of the pixel
417    /// being textured.
418    Nearest,
419    /// Chooses the mipmap that most closely matches the size of the pixel being textured and
420    /// uses the Nearest criterion (the texture element nearest to the center of the pixel)
421    /// to produce a texture value.
422    NearestMipMapNearest,
423    /// Chooses the two mipmaps that most closely match the size of the pixel being textured
424    /// and uses the Nearest criterion (the texture element nearest to the center of the pixel)
425    /// to produce a texture value from each mipmap. The final texture value is a weighted average
426    /// of those two values.
427    NearestMipMapLinear,
428    /// Returns the weighted average of the four texture elements that are closest to the
429    /// center of the pixel being textured.
430    #[default]
431    Linear,
432    /// Chooses the mipmap that most closely matches the size of the pixel being textured and
433    /// uses the Linear criterion (a weighted average of the four texture elements that are
434    /// closest to the center of the pixel) to produce a texture value.
435    LinearMipMapNearest,
436    /// Chooses the two mipmaps that most closely match the size of the pixel being textured
437    /// and uses the Linear criterion (a weighted average of the four texture elements that
438    /// are closest to the center of the pixel) to produce a texture value from each mipmap.
439    /// The final texture value is a weighted average of those two values.
440    LinearMipMapLinear,
441}
442
443/// Defines a law of texture coordinate modification.
444#[derive(Default, Copy, Clone, Eq, PartialEq, Debug)]
445pub enum WrapMode {
446    /// Causes the integer part of a coordinate to be ignored; GPU uses only the fractional part,
447    /// thereby creating a repeating pattern.
448    #[default]
449    Repeat,
450    /// Causes a coordinates to be clamped to the range, where N is the size of the texture
451    /// in the direction of clamping
452    ClampToEdge,
453    /// Evaluates a coordinates in a similar manner to ClampToEdge. However, in cases where clamping
454    /// would have occurred in ClampToEdge mode, the fetched texel data is substituted with the values
455    /// specified by border color.
456    ClampToBorder,
457    /// Causes the coordinate to be set to the fractional part of the texture coordinate if the integer
458    /// part of coordinate is even; if the integer part of coordinate is odd, then the coordinate texture
459    /// coordinate is set to 1-frac, where frac represents the fractional part of coordinate.
460    MirroredRepeat,
461    /// Causes a coordinate to be repeated as for MirroredRepeat for one repetition of the texture, at
462    /// which point the coordinate to be clamped as in ClampToEdge.
463    MirrorClampToEdge,
464}
465
466/// Texture coordinate.
467#[derive(Copy, Clone, Eq, PartialEq, Debug)]
468pub enum Coordinate {
469    /// S coordinate, similar to X axis.
470    S,
471    /// T coordinate, similar to Y axis.
472    T,
473    /// R coordinate, similar to Z axis.
474    R,
475}
476
477/// Face of a cube map.
478#[derive(Copy, Clone, Eq, PartialEq, Debug)]
479pub enum CubeMapFace {
480    /// +X face.
481    PositiveX,
482    /// -X face.
483    NegativeX,
484    /// +Y face.
485    PositiveY,
486    /// -Y face.
487    NegativeY,
488    /// +Z face.
489    PositiveZ,
490    /// -Z face.
491    NegativeZ,
492}
493
494/// Descriptor of a texture that is used to request textures from a graphics server.
495pub struct GpuTextureDescriptor<'a> {
496    /// Kind of the texture. See [`GpuTextureKind`] docs for more info.
497    pub kind: GpuTextureKind,
498    /// Pixel kind of the texture. See [`PixelKind`] docs for more info.
499    pub pixel_kind: PixelKind,
500    /// Minification filter of the texture. See [`MinificationFilter`] docs for more info.
501    pub min_filter: MinificationFilter,
502    /// Magnification filter of the texture. See [`MagnificationFilter`] docs for more info.
503    pub mag_filter: MagnificationFilter,
504    /// Total number of mips in the texture. Texture data must contain at least this number of
505    /// mips.
506    pub mip_count: usize,
507    /// S coordinate wrap mode. See [`WrapMode`] docs for more info.
508    pub s_wrap_mode: WrapMode,
509    /// T coordinate wrap mode. See [`WrapMode`] docs for more info.
510    pub t_wrap_mode: WrapMode,
511    /// R coordinate wrap mode. See [`WrapMode`] docs for more info.
512    pub r_wrap_mode: WrapMode,
513    /// Anisotropy level of the texture. Default is 1.0. Max number is usually depends on the
514    /// GPU, but the cap is 16.0 on pretty much any platform. This number should be a power of two.
515    pub anisotropy: f32,
516    /// Optional data of the texture. If present, then the total number of bytes must match the
517    /// required number of bytes defined by the texture kind, pixel kind, mip count.
518    pub data: Option<&'a [u8]>,
519    /// Specifies the index of the lowest defined mipmap level. Keep in mind, that the texture data
520    /// should provide the actual mip map level defined by the provided value, otherwise the
521    /// rendering will be incorrect (probably just black on majority of implementations) and glitchy.
522    pub base_level: usize,
523    /// Sets the index of the highest defined mipmap level. Keep in mind, that the texture data
524    /// should provide the actual mip map level defined by the provided value, otherwise the
525    /// rendering will be incorrect (probably just black on majority of implementations) and glitchy.
526    pub max_level: usize,
527    /// Sets the minimum level-of-detail parameter. This floating-point value limits the selection
528    /// of highest resolution mipmap (lowest mipmap level). The initial value is -1000.0.
529    pub min_lod: f32,
530    /// Sets the maximum level-of-detail parameter. This floating-point value limits the selection
531    /// of the lowest resolution mipmap (highest mipmap level). The initial value is 1000.0.
532    pub max_lod: f32,
533    /// Specifies a fixed bias value that is to be added to the level-of-detail parameter for the
534    /// texture before texture sampling. The specified value is added to the shader-supplied bias
535    /// value (if any) and subsequently clamped into the implementation-defined range
536    /// `−bias_max..bias_max`, where `bias_max` is the value that can be fetched from the current
537    /// graphics server. The initial value is 0.0.
538    pub lod_bias: f32,
539}
540
541impl Default for GpuTextureDescriptor<'_> {
542    // WARNING: Do NOT change these default values. This will affect a lot of places in the engine
543    // and may potentially lead to weird behavior!
544    fn default() -> Self {
545        Self {
546            kind: GpuTextureKind::Rectangle {
547                width: 1,
548                height: 1,
549            },
550            pixel_kind: PixelKind::RGBA8,
551            min_filter: Default::default(),
552            mag_filter: Default::default(),
553            mip_count: 1,
554            s_wrap_mode: Default::default(),
555            t_wrap_mode: Default::default(),
556            r_wrap_mode: Default::default(),
557            anisotropy: 1.0,
558            data: None,
559            base_level: 0,
560            max_level: 1000,
561            min_lod: -1000.0,
562            max_lod: 1000.0,
563            lod_bias: 0.0,
564        }
565    }
566}
567
568/// Texture is an image that used to fill faces to add details to them. It could also be used as a
569/// generic and mostly unlimited capacity storage for arbitrary data.
570///
571/// In most cases textures are just 2D images, however there are some exclusions to that - for example
572/// cube maps, that may be used for environment mapping. Fyrox supports 1D, 2D, 3D and Cube textures.
573///
574/// ## Example
575///
576/// ```rust
577/// use fyrox_graphics::{
578///     error::FrameworkError,
579///     gpu_texture::{
580///         GpuTexture, GpuTextureDescriptor, GpuTextureKind, MagnificationFilter,
581///         MinificationFilter, PixelKind, WrapMode,
582///     },
583///     server::GraphicsServer,
584/// };
585/// use std::{cell::RefCell, rc::Rc};
586///
587/// fn create_texture(
588///     server: &dyn GraphicsServer,
589/// ) -> Result<GpuTexture, FrameworkError> {
590///     server.create_texture(GpuTextureDescriptor {
591///         kind: GpuTextureKind::Rectangle {
592///             width: 1,
593///             height: 1,
594///         },
595///         pixel_kind: PixelKind::RGBA8,
596///         min_filter: MinificationFilter::Nearest,
597///         mag_filter: MagnificationFilter::Nearest,
598///         mip_count: 1,
599///         s_wrap_mode: WrapMode::Repeat,
600///         t_wrap_mode: WrapMode::Repeat,
601///         r_wrap_mode: WrapMode::Repeat,
602///         anisotropy: 1.0,
603///         // Opaque red pixel.
604///         data: Some(&[255, 0, 0, 255]),
605///         // Take the defaults for the rest of parameters.
606///         ..Default::default()
607///     })
608/// }
609/// ```
610pub trait GpuTextureTrait: Downcast {
611    /// Max samples for anisotropic filtering. Default value is 16.0 (max). However, real value passed
612    /// to GPU will be clamped to maximum supported by current GPU. To disable anisotropic filtering
613    /// set this to 1.0. Typical values are 2.0, 4.0, 8.0, 16.0.
614    fn set_anisotropy(&self, anisotropy: f32);
615
616    /// Returns current anisotropy level.
617    fn anisotropy(&self) -> f32;
618
619    /// Sets new minification filter. It is used when texture becomes smaller. See [`MinificationFilter`]
620    /// docs for more info.
621    fn set_minification_filter(&self, min_filter: MinificationFilter);
622
623    /// Returns current minification filter.
624    fn minification_filter(&self) -> MinificationFilter;
625
626    /// Sets new magnification filter. It is used when texture is "stretching". See [`MagnificationFilter`]
627    /// docs for more info.
628    fn set_magnification_filter(&self, mag_filter: MagnificationFilter);
629
630    /// Returns current magnification filter.
631    fn magnification_filter(&self) -> MagnificationFilter;
632
633    /// Sets new wrap mode for the given coordinate. See [`WrapMode`] for more info.
634    fn set_wrap(&self, coordinate: Coordinate, wrap: WrapMode);
635
636    /// Returns current wrap mode for the given coordinate.
637    fn wrap_mode(&self, coordinate: Coordinate) -> WrapMode;
638
639    /// Sets border color of the texture. Works together with [`WrapMode::ClampToBorder`] and
640    /// essentially forces the GPU to use the given color when it tries to read outside the texture
641    /// bounds.
642    fn set_border_color(&self, color: Color);
643
644    /// Sets the new data of the texture. This method is also able to change the kind of the texture
645    /// and its pixel kind.
646    fn set_data(
647        &self,
648        kind: GpuTextureKind,
649        pixel_kind: PixelKind,
650        mip_count: usize,
651        data: Option<&[u8]>,
652    ) -> Result<(), FrameworkError>;
653
654    /// Reads the texture data at the given mip level. This method could block current thread until
655    /// the data comes from GPU to CPU side.
656    fn get_image(&self, level: usize) -> Vec<u8>;
657
658    /// Reads texture pixels.
659    fn read_pixels(&self) -> Vec<u8>;
660
661    /// Returns kind of the texture.
662    fn kind(&self) -> GpuTextureKind;
663
664    /// Returns pixel kind of the texture.
665    fn pixel_kind(&self) -> PixelKind;
666
667    /// Specifies the index of the lowest defined mipmap level. Keep in mind, that the texture data
668    /// should provide the actual mip map level defined by the provided value, otherwise the
669    /// rendering will be incorrect (probably just black on majority of implementations) and glitchy.
670    fn set_base_level(&self, level: usize);
671
672    /// Returns the index of the lowest defined mipmap level.
673    fn base_level(&self) -> usize;
674
675    /// Sets the index of the highest defined mipmap level. Keep in mind, that the texture data
676    /// should provide the actual mip map level defined by the provided value, otherwise the
677    /// rendering will be incorrect (probably just black on majority of implementations) and glitchy.
678    fn set_max_level(&self, level: usize);
679
680    /// Returns the index of the highest defined mipmap level.
681    fn max_level(&self) -> usize;
682
683    /// Sets the minimum level-of-detail parameter. This floating-point value limits the selection
684    /// of highest resolution mipmap (lowest mipmap level). The initial value is -1000.0.
685    fn set_min_lod(&self, min_lod: f32);
686
687    /// Returns the minimum level-of-detail parameter. See [`Self::set_min_lod`] for more info.
688    fn min_lod(&self) -> f32;
689
690    /// Sets the maximum level-of-detail parameter. This floating-point value limits the selection
691    /// of the lowest resolution mipmap (highest mipmap level). The initial value is 1000.
692    fn set_max_lod(&self, max_lod: f32);
693
694    /// Returns the maximum level-of-detail parameter. See [`Self::set_max_lod`] for more info.
695    fn max_lod(&self) -> f32;
696
697    /// Specifies a fixed bias value that is to be added to the level-of-detail parameter for the
698    /// texture before texture sampling. The specified value is added to the shader-supplied bias
699    /// value (if any) and subsequently clamped into the implementation-defined range
700    /// `−bias_max..bias_max`, where `bias_max` is the value that can be fetched from the current
701    /// graphics server. The initial value is 0.0.
702    fn set_lod_bias(&self, bias: f32);
703
704    /// Returns a fixed bias value that is to be added to the level-of-detail parameter for the
705    /// texture before texture sampling. See [`Self::set_lod_bias`] for more info.
706    fn lod_bias(&self) -> f32;
707}
708
709impl dyn GpuTextureTrait {
710    /// Reads the pixels at the given mip level and reinterprets them using the given type.
711    pub fn get_image_of_type<T: Pod>(&self, level: usize) -> Vec<T> {
712        let mut bytes = self.get_image(level);
713
714        let typed = unsafe {
715            Vec::<T>::from_raw_parts(
716                bytes.as_mut_ptr() as *mut T,
717                bytes.len() / size_of::<T>(),
718                bytes.capacity() / size_of::<T>(),
719            )
720        };
721
722        std::mem::forget(bytes);
723
724        typed
725    }
726
727    /// Reads the pixels and reinterprets them using the given type.
728    pub fn read_pixels_of_type<T>(&self) -> Vec<T>
729    where
730        T: Pod,
731    {
732        let mut bytes = self.read_pixels();
733        let typed = unsafe {
734            Vec::<T>::from_raw_parts(
735                bytes.as_mut_ptr() as *mut T,
736                bytes.len() / size_of::<T>(),
737                bytes.capacity() / size_of::<T>(),
738            )
739        };
740        std::mem::forget(bytes);
741        typed
742    }
743}
744
745define_shared_wrapper!(GpuTexture<dyn GpuTextureTrait>);