wgpu/api/surface_texture.rs
1use std::{error, fmt, thread};
2
3use crate::context::DynContext;
4use crate::*;
5
6/// Surface texture that can be rendered to.
7/// Result of a successful call to [`Surface::get_current_texture`].
8///
9/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
10/// the [`GPUCanvasContext`](https://gpuweb.github.io/gpuweb/#canvas-context) provides
11/// a texture without any additional information.
12#[derive(Debug)]
13pub struct SurfaceTexture {
14 /// Accessible view of the frame.
15 pub texture: Texture,
16 /// `true` if the acquired buffer can still be used for rendering,
17 /// but should be recreated for maximum performance.
18 pub suboptimal: bool,
19 pub(crate) presented: bool,
20 pub(crate) detail: Box<dyn AnyWasmNotSendSync>,
21}
22#[cfg(send_sync)]
23static_assertions::assert_impl_all!(SurfaceTexture: Send, Sync);
24
25impl SurfaceTexture {
26 /// Schedule this texture to be presented on the owning surface.
27 ///
28 /// Needs to be called after any work on the texture is scheduled via [`Queue::submit`].
29 ///
30 /// # Platform dependent behavior
31 ///
32 /// On Wayland, `present` will attach a `wl_buffer` to the underlying `wl_surface` and commit the new surface
33 /// state. If it is desired to do things such as request a frame callback, scale the surface using the viewporter
34 /// or synchronize other double buffered state, then these operations should be done before the call to `present`.
35 pub fn present(mut self) {
36 self.presented = true;
37 DynContext::surface_present(
38 &*self.texture.context,
39 // This call to as_ref is essential because we want the DynContext implementation to see the inner
40 // value of the Box (T::SurfaceOutputDetail), not the Box itself.
41 self.detail.as_ref(),
42 );
43 }
44}
45
46impl Drop for SurfaceTexture {
47 fn drop(&mut self) {
48 if !self.presented && !thread::panicking() {
49 DynContext::surface_texture_discard(
50 &*self.texture.context,
51 // This call to as_ref is essential because we want the DynContext implementation to see the inner
52 // value of the Box (T::SurfaceOutputDetail), not the Box itself.
53 self.detail.as_ref(),
54 );
55 }
56 }
57}
58
59/// Result of an unsuccessful call to [`Surface::get_current_texture`].
60#[derive(Clone, PartialEq, Eq, Debug)]
61pub enum SurfaceError {
62 /// A timeout was encountered while trying to acquire the next frame.
63 Timeout,
64 /// The underlying surface has changed, and therefore the swap chain must be updated.
65 Outdated,
66 /// The swap chain has been lost and needs to be recreated.
67 Lost,
68 /// There is no more memory left to allocate a new frame.
69 OutOfMemory,
70}
71static_assertions::assert_impl_all!(SurfaceError: Send, Sync);
72
73impl fmt::Display for SurfaceError {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(f, "{}", match self {
76 Self::Timeout => "A timeout was encountered while trying to acquire the next frame",
77 Self::Outdated => "The underlying surface has changed, and therefore the swap chain must be updated",
78 Self::Lost => "The swap chain has been lost and needs to be recreated",
79 Self::OutOfMemory => "There is no more memory left to allocate a new frame",
80 })
81 }
82}
83
84impl error::Error for SurfaceError {}