1use alloc::rc::Rc;
17use core::cell::Cell;
18
19use crate::web_dev::{call, Device, Handle, CALL_CONTEXT, CALL_CURRENT, CALL_RESERVE, CALL_RESIZE, CALL_RGBA};
20use crate::*;
21
22pub(crate) struct SurfInner {
23 canvas: Handle,
24 window: i32,
25}
26
27#[derive(Clone)]
29pub struct Surface(pub(crate) Rc<SurfInner>);
30
31impl Surface {
32 pub fn track_size(&self) {}
34
35 pub fn new(instance: &Instance, window: i32) -> Result<Surface> {
37 let nw = plat::win_gpu_child(window).ok_or(GpuError::NotReady)?;
38 Surface::native(instance, nw, window)
39 }
40
41 pub fn native(_instance: &Instance, nw: plat::NativeWindow, window: i32) -> Result<Surface> {
43 Ok(Surface(Rc::new(SurfInner { canvas: Handle { h: nw.take(), destroy: false }, window })))
44 }
45}
46
47pub struct Frame {
49 size: (u32, u32),
50}
51
52#[must_use]
54pub enum TryAcquire {
55 Frame(Frame),
56 NotReady,
58 Stale,
60 NoArea,
62}
63
64impl Frame {
65 pub fn index(&self) -> u32 {
67 0
68 }
69 pub fn size(&self) -> (u32, u32) {
70 self.size
71 }
72}
73
74pub struct Swapchain {
76 dev: Device,
77 surf: Surface,
78 ctx: Handle,
79 size: Cell<(u32, u32)>,
80 format: Format,
81 texture: Texture,
82 view: TextureView,
83 stale: Cell<bool>,
84}
85
86impl Device {
87 pub fn create_swapchain(&self, surface: &Surface, desc: &SwapchainDesc) -> Result<Swapchain> {
88 self.d.check()?;
89 let (w, h) = plat::win_size(surface.0.window);
90 let (w, h) = (w.max(0) as u32, h.max(0) as u32);
91 if w == 0 || h == 0 {
92 return Err(GpuError::NotReady);
93 }
94 let ctx = call(CALL_CONTEXT, &[self.d.h, surface.0.canvas.h, w, h, desc.copy_src as u32, desc.srgb as u32]);
95 if ctx == 0 {
96 return Err(GpuError::SurfaceLost);
97 }
98 let rgba = call(CALL_RGBA, &[]) != 0;
99 let format = match (rgba, desc.srgb) {
100 (false, false) => Format::Bgra8Unorm,
101 (false, true) => Format::Bgra8Srgb,
102 (true, false) => Format::Rgba8Unorm,
103 (true, true) => Format::Rgba8Srgb,
104 };
105 let usage = TextureUsage::COLOR_TARGET | if desc.copy_src { TextureUsage::COPY_SRC } else { TextureUsage::NONE };
106 let view = TextureView::for_frame(call(CALL_RESERVE, &[]), format, w, h);
107 let texture = Texture::for_frame(call(CALL_RESERVE, &[]), view.clone(), format, w, h, usage);
108 Ok(Swapchain { dev: self.clone(), surf: surface.clone(), ctx: Handle { h: ctx, destroy: false }, size: Cell::new((w, h)), format, texture, view, stale: Cell::new(false) })
109 }
110}
111
112impl Swapchain {
113 pub fn rebuild(&mut self) -> Result<()> {
115 let (w, h) = plat::win_size(self.surf.0.window);
116 let (w, h) = (w.max(0) as u32, h.max(0) as u32);
117 if w != 0 && h != 0 {
118 call(CALL_RESIZE, &[self.ctx.h, w, h]);
119 let usage = self.texture.usage();
120 let view = TextureView::for_frame(call(CALL_RESERVE, &[]), self.format, w, h);
121 self.texture = Texture::for_frame(call(CALL_RESERVE, &[]), view.clone(), self.format, w, h, usage);
122 self.view = view;
123 }
124 self.size.set((w, h));
125 self.stale.set(false);
126 Ok(())
127 }
128
129 pub fn try_acquire(&mut self) -> Result<TryAcquire> {
131 self.dev.d.check()?;
132 let (w, h) = plat::win_size(self.surf.0.window);
133 if w <= 0 || h <= 0 {
134 return Ok(TryAcquire::NoArea);
135 }
136 if self.stale.get() || self.size.get() != (w as u32, h as u32) {
137 return Ok(TryAcquire::Stale);
138 }
139 match call(CALL_CURRENT, &[self.ctx.h, self.texture.handle(), self.view.handle()]) {
140 0 => Err(GpuError::SurfaceLost),
141 _ => Ok(TryAcquire::Frame(Frame { size: self.size.get() })),
142 }
143 }
144
145 pub fn acquire(&mut self) -> Result<Option<Frame>> {
147 match self.try_acquire()? {
148 TryAcquire::Frame(f) => Ok(Some(f)),
149 TryAcquire::Stale => {
150 self.rebuild()?;
151 match self.try_acquire()? {
152 TryAcquire::Frame(f) => Ok(Some(f)),
153 _ => Ok(None),
154 }
155 }
156 _ => Ok(None),
157 }
158 }
159
160 pub fn view(&self, _frame: &Frame) -> &TextureView {
162 &self.view
163 }
164
165 pub fn texture(&self, _frame: &Frame) -> &Texture {
167 &self.texture
168 }
169
170 pub fn present<'a, I: IntoIterator<Item = CommandBuffer<'a>>>(&self, _frame: Frame, cmds: I) -> Result<SubmitId> {
172 self.dev.queue().submit(cmds)
173 }
174
175 pub fn prepare(&mut self) -> Result<bool> {
177 Ok(true)
178 }
179 pub fn flush(&self) -> Result<bool> {
181 Ok(true)
182 }
183 pub fn busy(&self) -> bool {
185 false
186 }
187 pub fn next_look(&self, retry: u64) -> u64 {
189 retry
190 }
191 pub fn damage(&self, _rects: Option<&[[i32; 4]]>) {}
193 pub fn resize(&mut self) {
195 self.stale.set(true);
196 }
197 pub fn set_present_mode(&mut self, _m: PresentMode) {}
199 pub fn present_mode(&self) -> PresentMode {
200 PresentMode::Mailbox
201 }
202 pub fn format(&self) -> Format {
203 self.format
204 }
205 pub fn size(&self) -> (u32, u32) {
207 self.size.get()
208 }
209 pub fn image_count(&self) -> usize {
210 1
211 }
212}