Skip to main content

agpu/
surface.rs

1//! GPU surface — the swapchain / presentation target wrapping the
2//! platform window surface.
3
4use crate::context::GpuContext;
5use crate::resource::GpuTextureView;
6use crate::types::*;
7use std::sync::atomic::{AtomicU64, Ordering};
8
9#[allow(dead_code)]
10static NEXT_SURFACE_ID: AtomicU64 = AtomicU64::new(1);
11
12/// A GPU surface — the render target presented to a window.
13pub struct GpuSurface {
14    inner: wgpu::Surface<'static>,
15    id: u64,
16    config: wgpu::SurfaceConfiguration,
17}
18
19impl GpuSurface {
20    /// Wrap an existing wgpu surface with its configuration.
21    #[allow(dead_code)]
22    pub(crate) fn from_raw(
23        inner: wgpu::Surface<'static>,
24        config: wgpu::SurfaceConfiguration,
25    ) -> Self {
26        Self {
27            inner,
28            id: NEXT_SURFACE_ID.fetch_add(1, Ordering::Relaxed),
29            config,
30        }
31    }
32
33    pub fn id(&self) -> u64 {
34        self.id
35    }
36
37    /// Current texture format.
38    pub fn format(&self) -> TextureFormat {
39        self.config.format
40    }
41
42    /// Current present mode.
43    pub fn present_mode(&self) -> PresentMode {
44        self.config.present_mode
45    }
46
47    /// Current width.
48    pub fn width(&self) -> u32 {
49        self.config.width
50    }
51
52    /// Current height.
53    pub fn height(&self) -> u32 {
54        self.config.height
55    }
56
57    /// Reconfigure the surface (e.g. after a resize).
58    pub fn configure(&mut self, gpu: &GpuContext) {
59        self.inner.configure(gpu.device(), &self.config);
60    }
61
62    /// Update dimensions and reconfigure.
63    pub fn resize(&mut self, gpu: &GpuContext, width: u32, height: u32) {
64        if width > 0 && height > 0 {
65            self.config.width = width;
66            self.config.height = height;
67            self.configure(gpu);
68        }
69    }
70
71    /// Update present mode and reconfigure.
72    pub fn set_present_mode(&mut self, gpu: &GpuContext, mode: PresentMode) {
73        self.config.present_mode = mode;
74        self.configure(gpu);
75    }
76
77    /// Get the next frame to render into.
78    pub fn get_current_texture(&self) -> Result<GpuSurfaceTexture, SurfaceError> {
79        let frame = self.inner.get_current_texture()?;
80        Ok(GpuSurfaceTexture { inner: frame })
81    }
82
83    /// Access the underlying wgpu surface.
84    pub fn raw(&self) -> &wgpu::Surface<'static> {
85        &self.inner
86    }
87
88    /// Access the surface configuration.
89    pub fn config(&self) -> &wgpu::SurfaceConfiguration {
90        &self.config
91    }
92
93    /// Get surface capabilities for an adapter.
94    pub fn get_capabilities(&self, adapter: &wgpu::Adapter) -> wgpu::SurfaceCapabilities {
95        self.inner.get_capabilities(adapter)
96    }
97}
98
99/// A surface texture frame — the current backbuffer to render into.
100pub struct GpuSurfaceTexture {
101    inner: wgpu::SurfaceTexture,
102}
103
104impl GpuSurfaceTexture {
105    /// Create a default view of this frame.
106    pub fn create_view(&self, format: TextureFormat) -> GpuTextureView {
107        let view = self
108            .inner
109            .texture
110            .create_view(&wgpu::TextureViewDescriptor::default());
111        GpuTextureView::from_surface(view, format)
112    }
113
114    /// Present the frame to the screen.
115    pub fn present(self) {
116        self.inner.present();
117    }
118
119    /// Access the underlying wgpu surface texture.
120    pub fn raw(&self) -> &wgpu::SurfaceTexture {
121        &self.inner
122    }
123}