use glow::{Context, HasContext};
use std::rc::Rc;
use crate::access::{AccessLock, UnitAccessLock};
use std::num::NonZeroU32;
#[derive(Debug)]
pub(crate) struct InnerTexture {
pub(crate) context: Rc<Context>,
pub(crate) texture: <Context as HasContext>::Texture,
pub(crate) access: UnitAccessLock,
pub(crate) format: TextureFormat,
pub(crate) extent: TextureExtent,
}
impl Drop for InnerTexture {
fn drop(&mut self) {
unsafe {
let _atom = self.access.acquire_write_guarded();
self.context.delete_texture(self.texture)
}
}
}
impl AccessLock for InnerTexture {
fn write_locks(&self) -> usize {
self.access.write_locks()
}
fn read_locks(&self) -> usize {
self.access.read_locks()
}
fn acquire_write(&self) {
self.access.acquire_write();
}
fn release_write(&self) {
self.access.release_write();
}
fn acquire_read(&self) {
self.access.acquire_read();
}
fn release_read(&self) {
self.access.release_read();
}
}
#[derive(Debug)]
pub struct Texture {
pub(crate) inner: Rc<InnerTexture>
}
impl Texture {
pub fn format(&self) -> TextureFormat {
self.inner.format
}
pub unsafe fn as_raw_handle(&self) -> <Context as HasContext>::Texture {
self.inner.texture
}
}
impl AccessLock for Texture {
fn write_locks(&self) -> usize {
self.inner.access.write_locks()
}
fn read_locks(&self) -> usize {
self.inner.access.read_locks()
}
fn acquire_write(&self) {
self.inner.access.acquire_write()
}
fn release_write(&self) {
self.inner.access.release_write()
}
fn acquire_read(&self) {
self.inner.access.acquire_read()
}
fn release_read(&self) {
self.inner.access.release_read()
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum TextureFormat {
Rgba32Float,
Rgba8Unorm,
Depth24Stencil8
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum TextureFilter {
Nearest,
Linear
}
impl TextureFilter {
pub(crate) fn as_opengl(&self, min: bool) -> u32 {
match self {
Self::Nearest => if min { glow::NEAREST_MIPMAP_NEAREST } else { glow::NEAREST },
Self::Linear => if min { glow::LINEAR_MIPMAP_LINEAR } else { glow::LINEAR },
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct TextureDescriptor {
pub extent: TextureExtent,
pub format: TextureFormat,
pub mip: Mipmap,
}
#[derive(Debug, Copy, Clone)]
pub enum Mipmap {
None,
Manual {
levels: NonZeroU32,
},
#[cfg(feature = "mipmap-generation")]
Automatic {
filter: FilterType
},
}
#[cfg(feature = "mipmap-generation")]
pub use image::imageops::FilterType;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum TextureExtent {
D1 {
length: u32,
},
D2 {
width: u32,
height: u32,
},
D2Array {
width: u32,
height: u32,
layers: u32,
},
D3 {
width: u32,
height: u32,
depth: u32
}
}
#[derive(Debug, thiserror::Error)]
pub enum TextureError {
#[error("failed to create a new texture: {what}")]
CreationError {
what: String
},
#[error("the bounds given to the texture are invalid")]
InvalidBounds {
what: String
}
}