1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
//! Texture backend interface.
//!
//! This interface defines the low-level API textures must implement to be usable.
//!
//! In order to add support for textures, you have to implement two traits:
//!
//! - [`TextureBase`], which is a _type family_ providing the backend representation of a texture. This is needed so
//! that other part of the crate don’t have to rely on a too abstraction.
//! - The rest of the abstraction, bigger, is [`Texture`].
//!
//! You will have to implement both traits to be able to use textures.
use crate::{
pixel::Pixel,
texture::{Dimensionable, Sampler, TexelUpload, TextureError},
};
/// Type family giving the backend representation type.
///
/// This type family is type-erased: it doesn’t know whether the texture is a 2D texture or a 3D one or a cubemap.
pub unsafe trait TextureBase {
/// Backend representation of a texture.
type TextureRepr;
}
/// Texture interface.
///
/// Implementing this trait requires implementing [`TextureBase`].
///
/// `D` is the _dimension_ of the texture, and must then implement [`Dimensionable`]. `P` is the format of the carried
/// pixels and must then implement [`Pixel`].
pub unsafe trait Texture<D, P>: TextureBase
where
D: Dimensionable,
P: Pixel,
{
/// Create a new texture.
unsafe fn new_texture(
&mut self,
size: D::Size,
sampler: Sampler,
texels: TexelUpload<[P::Encoding]>,
) -> Result<Self::TextureRepr, TextureError>;
/// Create a new texture from raw texels.
unsafe fn new_texture_raw(
&mut self,
size: D::Size,
sampler: Sampler,
texels: TexelUpload<[P::RawEncoding]>,
) -> Result<Self::TextureRepr, TextureError>;
/// Get the number of mimaps associated with the texture.
unsafe fn mipmaps(texture: &Self::TextureRepr) -> usize;
/// Upload texels to a part of a texture.
///
/// This method will use the input texels and will copy them everywhere in the part formed with `offset` and `size`. For
/// instance, for 2D textures, `offset` and `size` form a rectangle: that rectangle of pixels will be filled with the
/// provided input texels.
unsafe fn upload_part(
texture: &mut Self::TextureRepr,
offset: D::Offset,
size: D::Size,
texels: TexelUpload<[P::Encoding]>,
) -> Result<(), TextureError>;
/// Upload texels to a whole texture.
///
/// This method is similar to [`Texture::upload_part`] but instead of uploading a part of it, it will upload to the
/// whole texture at once. The size will match the size of the texture so you do not have to cache it and simply can use
/// the input `size` value.
unsafe fn upload(
texture: &mut Self::TextureRepr,
size: D::Size,
texels: TexelUpload<[P::Encoding]>,
) -> Result<(), TextureError>;
/// Upload texels to a part of a texture.
///
/// This method will use the input texels and will copy them everywhere in the part formed with `offset` and `size`. For
/// instance, for 2D textures, `offset` and `size` form a rectangle: that rectangle of pixels will be filled with the
/// provided input texels.
///
/// > This is very similar to [`Texture::upload_part_raw`], but the key difference is that this method works with the
/// > _raw encoding_ of the texels, which is often the case with crates that provide you with a contiguous array of raw
/// > data instead of rich texels.
unsafe fn upload_part_raw(
texture: &mut Self::TextureRepr,
offset: D::Offset,
size: D::Size,
texels: TexelUpload<[P::RawEncoding]>,
) -> Result<(), TextureError>;
/// Upload texels to a whole texture.
///
/// This method is similar to [`Texture::upload_part`] but instead of uploading a part of it, it will upload to the
/// whole texture at once. The size will match the size of the texture so you do not have to cache it and simply can use
/// the input `size` value.
///
/// > This is very similar to [`Texture::upload`], but the key difference is that this method works with the _raw
/// > encoding_ of the texels, which is often the case with crates that provide you with a contiguous array of raw
/// > data instead of rich texels.
unsafe fn upload_raw(
texture: &mut Self::TextureRepr,
size: D::Size,
texels: TexelUpload<[P::RawEncoding]>,
) -> Result<(), TextureError>;
/// Get a copy of the raw texels stored in the texture.
///
/// `size` will match the actual size of the texture, you do not need to cache it.
unsafe fn get_raw_texels(
texture: &Self::TextureRepr,
size: D::Size,
) -> Result<Vec<P::RawEncoding>, TextureError>
where
P::RawEncoding: Copy + Default;
/// Resize the texture.
///
/// Once the texture is resized, pixels are left in an unknown state. Depending on the implementation of the backend,
/// it is likely that texels will either be old ones, or completely random data.
unsafe fn resize(
texture: &mut Self::TextureRepr,
size: D::Size,
texel: TexelUpload<[P::Encoding]>,
) -> Result<(), TextureError>;
/// Resize the texture with raw texels.
///
/// Once the texture is resized, pixels are left in an unknown state. Depending on the implementation of the backend,
/// it is likely that texels will either be old ones, or completely random data.
unsafe fn resize_raw(
texture: &mut Self::TextureRepr,
size: D::Size,
texel: TexelUpload<[P::RawEncoding]>,
) -> Result<(), TextureError>;
}