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>);