use crate::gpu::{
CompareOp, Device, Filter, SampleCount, SamplerAddressMode, SamplerMipmapMode, TextureFormat,
TextureType, TextureUsage, TransferBuffer, WeakDevice,
};
use std::{marker::PhantomData, sync::Arc};
use sys::gpu::{
SDL_GPUCompareOp, SDL_GPUFilter, SDL_GPUSampleCount, SDL_GPUSampler, SDL_GPUSamplerAddressMode,
SDL_GPUSamplerCreateInfo, SDL_GPUSamplerMipmapMode, SDL_GPUTexture, SDL_GPUTextureCreateInfo,
SDL_GPUTextureFormat, SDL_GPUTextureRegion, SDL_GPUTextureSamplerBinding,
SDL_GPUTextureTransferInfo, SDL_GPUTextureType, SDL_ReleaseGPUSampler, SDL_ReleaseGPUTexture,
};
#[derive(Default)]
pub struct TextureTransferInfo {
pub(super) inner: SDL_GPUTextureTransferInfo,
}
impl TextureTransferInfo {
pub fn new() -> Self {
Default::default()
}
pub fn with_transfer_buffer(mut self, buffer: &TransferBuffer) -> Self {
self.inner.transfer_buffer = buffer.raw();
self
}
pub fn with_offset(mut self, offset: u32) -> Self {
self.inner.offset = offset;
self
}
pub fn with_pixels_per_row(mut self, value: u32) -> Self {
self.inner.pixels_per_row = value;
self
}
pub fn with_rows_per_layer(mut self, value: u32) -> Self {
self.inner.rows_per_layer = value;
self
}
}
#[derive(Default)]
pub struct TextureRegion {
pub(super) inner: SDL_GPUTextureRegion,
}
impl TextureRegion {
pub fn new() -> Self {
Default::default()
}
pub fn with_texture(mut self, texture: &Texture) -> Self {
self.inner.texture = texture.raw();
self
}
pub fn with_mip_level(mut self, mip_level: u32) -> Self {
self.inner.mip_level = mip_level;
self
}
pub fn with_layer(mut self, layer: u32) -> Self {
self.inner.layer = layer;
self
}
pub fn with_x(mut self, x: u32) -> Self {
self.inner.x = x;
self
}
pub fn with_y(mut self, y: u32) -> Self {
self.inner.y = y;
self
}
pub fn with_z(mut self, z: u32) -> Self {
self.inner.z = z;
self
}
pub fn with_width(mut self, width: u32) -> Self {
self.inner.w = width;
self
}
pub fn with_height(mut self, height: u32) -> Self {
self.inner.h = height;
self
}
pub fn with_depth(mut self, depth: u32) -> Self {
self.inner.d = depth;
self
}
}
#[derive(Default)]
pub struct SamplerCreateInfo {
pub(super) inner: SDL_GPUSamplerCreateInfo,
}
impl SamplerCreateInfo {
pub fn new() -> Self {
Default::default()
}
pub fn with_min_filter(mut self, filter: Filter) -> Self {
self.inner.min_filter = SDL_GPUFilter(filter as i32);
self
}
pub fn with_mag_filter(mut self, filter: Filter) -> Self {
self.inner.mag_filter = SDL_GPUFilter(filter as i32);
self
}
pub fn with_mipmap_mode(mut self, mode: SamplerMipmapMode) -> Self {
self.inner.mipmap_mode = SDL_GPUSamplerMipmapMode(mode as i32);
self
}
pub fn with_address_mode_u(mut self, mode: SamplerAddressMode) -> Self {
self.inner.address_mode_u = SDL_GPUSamplerAddressMode(mode as i32);
self
}
pub fn with_address_mode_v(mut self, mode: SamplerAddressMode) -> Self {
self.inner.address_mode_v = SDL_GPUSamplerAddressMode(mode as i32);
self
}
pub fn with_address_mode_w(mut self, mode: SamplerAddressMode) -> Self {
self.inner.address_mode_w = SDL_GPUSamplerAddressMode(mode as i32);
self
}
pub fn with_mip_lod_bias(mut self, value: f32) -> Self {
self.inner.mip_lod_bias = value;
self
}
pub fn with_max_anisotropy(mut self, value: f32) -> Self {
self.inner.max_anisotropy = value;
self
}
pub fn with_compare_op(mut self, value: CompareOp) -> Self {
self.inner.compare_op = SDL_GPUCompareOp(value as i32);
self
}
pub fn with_min_lod(mut self, value: f32) -> Self {
self.inner.min_lod = value;
self
}
pub fn with_max_lod(mut self, value: f32) -> Self {
self.inner.max_lod = value;
self
}
pub fn with_enable_anisotropy(mut self, enable: bool) -> Self {
self.inner.enable_anisotropy = enable;
self
}
pub fn with_enable_compare(mut self, enable: bool) -> Self {
self.inner.enable_compare = enable;
self
}
}
struct SamplerContainer {
raw: *mut SDL_GPUSampler,
device: WeakDevice,
}
impl Drop for SamplerContainer {
fn drop(&mut self) {
if let Some(device) = self.device.upgrade() {
unsafe { SDL_ReleaseGPUSampler(device.raw(), self.raw) }
}
}
}
#[derive(Clone)]
pub struct Sampler {
inner: Arc<SamplerContainer>,
}
impl Sampler {
pub(super) fn new(device: &Device, raw_sampler: *mut SDL_GPUSampler) -> Self {
Self {
inner: Arc::new(SamplerContainer {
raw: raw_sampler,
device: device.weak(),
}),
}
}
#[inline]
fn raw(&self) -> *mut SDL_GPUSampler {
self.inner.raw
}
}
#[repr(C)]
#[derive(Default)]
pub struct TextureSamplerBinding {
inner: SDL_GPUTextureSamplerBinding,
}
impl TextureSamplerBinding {
pub fn new() -> Self {
Default::default()
}
pub fn with_texture(mut self, texture: &Texture<'static>) -> Self {
self.inner.texture = texture.raw();
self
}
pub fn with_sampler(mut self, sampler: &Sampler) -> Self {
self.inner.sampler = sampler.raw();
self
}
}
enum TextureContainer {
UserManaged {
raw: *mut SDL_GPUTexture,
device: WeakDevice,
},
SdlManaged { raw: *mut SDL_GPUTexture },
}
impl TextureContainer {
fn raw(&self) -> *mut SDL_GPUTexture {
match self {
Self::UserManaged { raw, .. } => *raw,
Self::SdlManaged { raw } => *raw,
}
}
}
impl Drop for TextureContainer {
#[doc(alias = "SDL_ReleaseGPUTexture")]
fn drop(&mut self) {
match self {
Self::UserManaged { raw, device } => {
if let Some(device) = device.upgrade() {
unsafe { SDL_ReleaseGPUTexture(device.raw(), *raw) };
}
}
_ => {}
}
}
}
#[derive(Clone)]
pub struct Texture<'a> {
inner: Arc<TextureContainer>,
width: u32,
height: u32,
_phantom: PhantomData<&'a ()>,
}
impl<'a> Texture<'a> {
pub(super) fn new(
device: &Device,
raw: *mut SDL_GPUTexture,
width: u32,
height: u32,
) -> Texture<'a> {
Texture {
inner: Arc::new(TextureContainer::UserManaged {
raw,
device: device.weak(),
}),
width,
height,
_phantom: Default::default(),
}
}
pub(super) fn new_sdl_managed(
raw: *mut SDL_GPUTexture,
width: u32,
height: u32,
) -> Texture<'a> {
Texture {
inner: Arc::new(TextureContainer::SdlManaged { raw }),
width,
height,
_phantom: Default::default(),
}
}
#[inline]
pub fn raw(&self) -> *mut SDL_GPUTexture {
self.inner.raw()
}
pub fn width(&self) -> u32 {
self.width
}
pub fn height(&self) -> u32 {
self.height
}
}
#[derive(Default)]
pub struct TextureCreateInfo {
pub(super) inner: SDL_GPUTextureCreateInfo,
}
impl TextureCreateInfo {
pub fn new() -> Self {
Default::default()
}
pub fn with_type(mut self, value: TextureType) -> Self {
self.inner.r#type = SDL_GPUTextureType(value as i32);
self
}
pub fn with_format(mut self, format: TextureFormat) -> Self {
self.inner.format = SDL_GPUTextureFormat(format as i32);
self
}
pub fn with_usage(mut self, value: TextureUsage) -> Self {
self.inner.usage = value as u32;
self
}
pub fn with_width(mut self, value: u32) -> Self {
self.inner.width = value;
self
}
pub fn with_height(mut self, value: u32) -> Self {
self.inner.height = value;
self
}
pub fn with_layer_count_or_depth(mut self, value: u32) -> Self {
self.inner.layer_count_or_depth = value;
self
}
pub fn with_num_levels(mut self, value: u32) -> Self {
self.inner.num_levels = value;
self
}
pub fn with_sample_count(mut self, value: SampleCount) -> Self {
self.inner.sample_count = SDL_GPUSampleCount(value as i32);
self
}
}