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
//a Imports
use std::cell::{Ref, RefCell};

use crate::{BufferElementType, Renderable};

//a Texture
//tp Texture
/// A texture is managed by the library as a byte slice which has up
/// to three dimensions - minimally a width, with a 2D texture having
/// a non-zero height, and a 3D texture with a non-zero depth
///
/// The 'elements' that make up each entry of the texture can be
/// multiples of 1 to 4 of a fundamental element type (int or float,
/// of 8, 16 or 32 bits as permitted)
///
/// After the texture has been created, it may be instantiated within
/// the client, when a texture client handle is created by the client;
/// this must be easily Cloned, particuarly if the texture is used in
/// more than one instantiable object
pub struct Texture<'texture, R: Renderable + ?Sized> {
    /// The underlying data for the texture
    pub data: &'texture [u8],
    /// Width, height, and depth of the texture - width must be
    /// non-zero
    ///
    /// If height is zero then the texture is 1D, and depth must be 0
    ///
    /// If height is non-zero and depth is zero then the texture is 2D
    pub dims: (usize, usize, usize),
    /// Number of elements per texture entry (1,2,3 or 4)
    ///
    /// An RGB texture would be 3; an RGBA texture 4.
    pub elements_per_data: u32,
    /// The type of each element
    ///
    /// For most image textures this is Int8
    pub ele_type: BufferElementType,
    /// Client handle/value
    rc_client: RefCell<R::Texture>,
}

//ip Debug for Texture
impl<'texture, R: Renderable> std::fmt::Debug for Texture<'texture, R>
where
    R: Renderable,
{
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        writeln!(
            fmt,
            "Texture {{dims:{:?}, {:?}*{}, client:{:?}}}",
            self.dims, self.ele_type, self.elements_per_data, self.rc_client
        )?;
        Ok(())
    }
}

//ip Display for Texture
impl<'texture, R: Renderable> std::fmt::Display for Texture<'texture, R>
where
    R: Renderable,
{
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        writeln!(fmt, "Texture:")?;
        writeln!(fmt, "  dims: {:?}", self.dims)?;
        Ok(())
    }
}

///ip Texture
impl<'texture, R: Renderable> Texture<'texture, R> {
    //cp new
    /// Create a new [Texture] object with no additional attributes
    pub fn new(
        data: &'texture [u8],
        dims: (usize, usize, usize),
        ele_type: BufferElementType,
        elements_per_data: u32,
    ) -> Self {
        let rc_client = Default::default();
        Self {
            data,
            dims,
            ele_type,
            elements_per_data,
            rc_client,
        }
    }

    //ap dims
    /// Get the dimensions of the texture
    pub fn dims(&self) -> &(usize, usize, usize) {
        &self.dims
    }

    //ap data
    /// Get the data slice for the texture
    pub fn data(&self) -> &[u8] {
        self.data
    }

    //ap data_type
    /// Get the data slice for the texture
    pub fn data_type(&self) -> (u32, BufferElementType) {
        (self.elements_per_data, self.ele_type)
    }

    //mp create_client
    /// Create the client texture
    pub fn create_client(&self, renderer: &mut R) {
        *(self.rc_client.borrow_mut()) = renderer.create_texture_client(self);
    }

    //ap borrow_client
    /// Borrow the client
    pub fn borrow_client(&self) -> Ref<R::Texture> {
        self.rc_client.borrow()
    }
}