maplibre/render/resource/
texture.rs

1//! Utility for a texture view which can either be created by a [`TextureView`](wgpu::TextureView)
2//! or [`SurfaceTexture`](wgpu::SurfaceTexture)
3
4use std::ops::Deref;
5
6use crate::render::{eventually::HasChanged, settings::Msaa};
7
8/// Describes a [`TextureView`].
9///
10/// May be converted from a [`TextureView`](wgpu::TextureView) or [`SurfaceTexture`](wgpu::SurfaceTexture)
11/// or dereferences to a wgpu [`TextureView`](wgpu::TextureView).
12#[derive(Debug)]
13pub enum TextureView {
14    /// The value is an actual wgpu [`TextureView`](wgpu::TextureView).
15    TextureView(wgpu::TextureView),
16
17    /// The value is a wgpu [`SurfaceTexture`](wgpu::SurfaceTexture), but dereferences to
18    /// a [`TextureView`](wgpu::TextureView).
19    SurfaceTexture {
20        // NOTE: The order of these fields is important because the view must be dropped before the
21        // frame is dropped
22        view: wgpu::TextureView,
23        texture: wgpu::SurfaceTexture,
24    },
25}
26
27impl TextureView {
28    /// Returns the [`SurfaceTexture`](wgpu::SurfaceTexture) of the texture view if it is of that type.
29    #[inline]
30    pub fn take_surface_texture(self) -> Option<wgpu::SurfaceTexture> {
31        match self {
32            TextureView::TextureView(_) => None,
33            TextureView::SurfaceTexture { texture, .. } => Some(texture),
34        }
35    }
36}
37
38impl From<wgpu::TextureView> for TextureView {
39    fn from(value: wgpu::TextureView) -> Self {
40        TextureView::TextureView(value)
41    }
42}
43
44impl From<wgpu::SurfaceTexture> for TextureView {
45    fn from(surface_texture: wgpu::SurfaceTexture) -> Self {
46        let view = surface_texture.texture.create_view(&Default::default());
47
48        TextureView::SurfaceTexture {
49            texture: surface_texture,
50            view,
51        }
52    }
53}
54
55impl Deref for TextureView {
56    type Target = wgpu::TextureView;
57
58    #[inline]
59    fn deref(&self) -> &Self::Target {
60        match &self {
61            TextureView::TextureView(value) => value,
62            TextureView::SurfaceTexture { view, .. } => view,
63        }
64    }
65}
66
67pub struct Texture {
68    pub size: wgpu::Extent3d,
69    pub texture: wgpu::Texture,
70    pub view: TextureView,
71}
72
73impl Texture {
74    pub fn new(
75        label: wgpu::Label,
76        device: &wgpu::Device,
77        format: wgpu::TextureFormat,
78        width: u32,
79        height: u32,
80        msaa: Msaa,
81        usage: wgpu::TextureUsages,
82    ) -> Texture {
83        let size = wgpu::Extent3d {
84            width,
85            height,
86            depth_or_array_layers: 1,
87        };
88
89        let texture = device.create_texture(&wgpu::TextureDescriptor {
90            label,
91            size,
92            mip_level_count: 1,
93            sample_count: msaa.samples,
94            dimension: wgpu::TextureDimension::D2,
95            format,
96            usage,
97            view_formats: &[format],
98        });
99        let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
100        Self {
101            size,
102            texture,
103            view: TextureView::TextureView(view),
104        }
105    }
106}
107
108impl HasChanged for Texture {
109    type Criteria = (u32, u32);
110
111    fn has_changed(&self, criteria: &Self::Criteria) -> bool {
112        let size = (self.size.width, self.size.height);
113        !size.eq(criteria)
114    }
115}