1use glow::{Context, HasContext};
2use std::rc::Rc;
3use crate::access::{AccessLock, UnitAccessLock};
4use std::num::NonZeroU32;
5
6#[derive(Debug)]
8pub(crate) struct InnerTexture {
9 pub(crate) context: Rc<Context>,
11 pub(crate) texture: <Context as HasContext>::Texture,
13 pub(crate) access: UnitAccessLock,
15 pub(crate) format: TextureFormat,
17 pub(crate) extent: TextureExtent,
19}
20impl Drop for InnerTexture {
21 fn drop(&mut self) {
22 unsafe {
23 let _atom = self.access.acquire_write_guarded();
24 self.context.delete_texture(self.texture)
25 }
26 }
27}
28impl AccessLock for InnerTexture {
29 fn write_locks(&self) -> usize {
30 self.access.write_locks()
31 }
32 fn read_locks(&self) -> usize {
33 self.access.read_locks()
34 }
35 fn acquire_write(&self) {
36 self.access.acquire_write();
37 }
38 fn release_write(&self) {
39 self.access.release_write();
40 }
41 fn acquire_read(&self) {
42 self.access.acquire_read();
43 }
44 fn release_read(&self) {
45 self.access.release_read();
46 }
47}
48
49#[derive(Debug)]
50pub struct Texture {
51 pub(crate) inner: Rc<InnerTexture>
53}
54impl Texture {
55 pub fn format(&self) -> TextureFormat {
57 self.inner.format
58 }
59 pub unsafe fn as_raw_handle(&self) -> <Context as HasContext>::Texture {
61 self.inner.texture
62 }
63}
64impl AccessLock for Texture {
65 fn write_locks(&self) -> usize {
66 self.inner.access.write_locks()
67 }
68 fn read_locks(&self) -> usize {
69 self.inner.access.read_locks()
70 }
71 fn acquire_write(&self) {
72 self.inner.access.acquire_write()
73 }
74 fn release_write(&self) {
75 self.inner.access.release_write()
76 }
77 fn acquire_read(&self) {
78 self.inner.access.acquire_read()
79 }
80 fn release_read(&self) {
81 self.inner.access.release_read()
82 }
83}
84
85#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
87pub enum TextureFormat {
88 Rgba32Float,
90 Rgba8Unorm,
92 Depth24Stencil8
94}
95
96
97#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
104pub enum TextureFilter {
105 Nearest,
107 Linear
109}
110impl TextureFilter {
111 pub(crate) fn as_opengl(&self, min: bool) -> u32 {
113 match self {
114 Self::Nearest => if min { glow::NEAREST_MIPMAP_NEAREST } else { glow::NEAREST },
115 Self::Linear => if min { glow::LINEAR_MIPMAP_LINEAR } else { glow::LINEAR },
116 }
117 }
118}
119
120#[derive(Debug, Copy, Clone)]
122pub struct TextureDescriptor {
123 pub extent: TextureExtent,
125 pub format: TextureFormat,
127 pub mip: Mipmap,
129}
130
131#[derive(Debug, Copy, Clone)]
133pub enum Mipmap {
134 None,
136 Manual {
139 levels: NonZeroU32,
141 },
142 #[cfg(feature = "mipmap-generation")]
149 Automatic {
150 filter: FilterType
153 },
154}
155
156#[cfg(feature = "mipmap-generation")]
157pub use image::imageops::FilterType;
158
159#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
161pub enum TextureExtent {
162 D1 {
164 length: u32,
165 },
166 D2 {
168 width: u32,
169 height: u32,
170 },
171 D2Array {
173 width: u32,
174 height: u32,
175 layers: u32,
176 },
177 D3 {
179 width: u32,
180 height: u32,
181 depth: u32
182 }
183}
184
185#[derive(Debug, thiserror::Error)]
186pub enum TextureError {
187 #[error("failed to create a new texture: {what}")]
188 CreationError {
189 what: String
190 },
191 #[error("the bounds given to the texture are invalid")]
192 InvalidBounds {
193 what: String
194 }
195}