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