wgpu/api/surface_texture.rs
1use crate::*;
2
3/// Surface texture that can be rendered to.
4/// Result of a successful call to [`Surface::get_current_texture`].
5///
6/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
7/// the [`GPUCanvasContext`](https://gpuweb.github.io/gpuweb/#canvas-context) provides
8/// a texture without any additional information.
9#[derive(Debug, Clone)]
10pub struct SurfaceTexture {
11 /// Accessible view of the frame.
12 pub texture: Texture,
13 pub(crate) presented: bool,
14 pub(crate) detail: dispatch::DispatchSurfaceOutputDetail,
15}
16#[cfg(send_sync)]
17static_assertions::assert_impl_all!(SurfaceTexture: Send, Sync);
18
19crate::cmp::impl_eq_ord_hash_proxy!(SurfaceTexture => .texture.inner);
20
21impl SurfaceTexture {
22 /// Schedule this texture to be presented on the owning surface.
23 ///
24 /// Needs to be called after any work on the texture is scheduled via [`Queue::submit`].
25 ///
26 /// # Platform dependent behavior
27 ///
28 /// On Wayland, `present` will attach a `wl_buffer` to the underlying `wl_surface` and commit the new surface
29 /// state. If it is desired to do things such as request a frame callback, scale the surface using the viewporter
30 /// or synchronize other double buffered state, then these operations should be done before the call to `present`.
31 pub fn present(mut self) {
32 self.presented = true;
33 self.detail.present();
34 }
35
36 #[cfg(custom)]
37 /// Returns custom implementation of SurfaceTexture (if custom backend and is internally T)
38 pub fn as_custom<T: crate::custom::SurfaceOutputDetailInterface>(&self) -> Option<&T> {
39 self.detail.as_custom()
40 }
41}
42
43impl Drop for SurfaceTexture {
44 fn drop(&mut self) {
45 if !self.presented && !thread_panicking() {
46 self.detail.texture_discard();
47 }
48 }
49}
50
51/// Result of a call to [`Surface::get_current_texture`].
52///
53/// See variant documentation for how to handle each case.
54#[derive(Debug)]
55pub enum CurrentSurfaceTexture {
56 /// Successfully acquired a surface texture with no issues.
57 Success(SurfaceTexture),
58 /// Successfully acquired a surface texture, but texture no longer matches the properties of the underlying surface.
59 /// It's highly recommended to call [`Surface::configure`] again for optimal performance.
60 Suboptimal(SurfaceTexture),
61 /// A timeout was encountered while trying to acquire the next frame.
62 ///
63 /// Applications should skip the current frame and try again later.
64 Timeout,
65 /// The window is occluded (e.g. minimized or behind another window).
66 ///
67 /// Applications should skip the current frame and try again once the window
68 /// is no longer occluded.
69 Occluded,
70 /// The underlying surface has changed, and therefore the surface configuration is outdated.
71 ///
72 /// Call [`Surface::configure()`] and try again.
73 Outdated,
74 /// The surface has been lost and needs to be recreated.
75 ///
76 /// If the device as a whole is lost (see [`set_device_lost_callback()`][crate::Device::set_device_lost_callback]), then
77 /// you need to recreate the device and all resources.
78 /// Otherwise, call [`Instance::create_surface()`] to recreate the surface,
79 /// then [`Surface::configure()`], and try again.
80 Lost,
81 /// A validation error inside [`Surface::get_current_texture()`] was raised
82 /// and caught by an [error scope](crate::Device::push_error_scope) or
83 /// [`on_uncaptured_error()`][crate::Device::on_uncaptured_error].
84 ///
85 /// Applications should attend to the validation error and try again.
86 Validation,
87}
88
89fn thread_panicking() -> bool {
90 cfg_if::cfg_if! {
91 if #[cfg(std)] {
92 std::thread::panicking()
93 } else if #[cfg(panic = "abort")] {
94 // If `panic = "abort"` then a thread _cannot_ be observably panicking by definition.
95 false
96 } else {
97 // TODO: This is potentially overly pessimistic; it may be appropriate to instead allow a
98 // texture to not be discarded.
99 // Alternatively, this could _also_ be a `panic!`, since we only care if the thread is panicking
100 // when the surface has not been presented.
101 compile_error!(
102 "cannot determine if a thread is panicking without either `panic = \"abort\"` or `std`"
103 );
104 }
105 }
106}