// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. use super::WebGpuResult; use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; use serde::Deserialize; use std::borrow::Cow; use std::rc::Rc; use wgpu_types::SurfaceStatus; deno_core::extension!( deno_webgpu_surface, deps = [deno_webidl, deno_web, deno_webgpu], ops = [ op_webgpu_surface_configure, op_webgpu_surface_get_current_texture, op_webgpu_surface_present, ], esm = ["02_surface.js"], ); pub struct WebGpuSurface(pub crate::Instance, pub wgpu_core::id::SurfaceId); impl Resource for WebGpuSurface { fn name(&self) -> Cow { "webGPUSurface".into() } fn close(self: Rc) { self.0.surface_drop(self.1); } } #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct SurfaceConfigureArgs { surface_rid: ResourceId, device_rid: ResourceId, format: wgpu_types::TextureFormat, usage: u32, width: u32, height: u32, present_mode: Option, alpha_mode: wgpu_types::CompositeAlphaMode, view_formats: Vec, } #[op2] #[serde] pub fn op_webgpu_surface_configure( state: &mut OpState, #[serde] args: SurfaceConfigureArgs, ) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table .get::(args.device_rid)?; let device = device_resource.1; let surface_resource = state .resource_table .get::(args.surface_rid)?; let surface = surface_resource.1; let conf = wgpu_types::SurfaceConfiguration::> { usage: wgpu_types::TextureUsages::from_bits_truncate(args.usage), format: args.format, width: args.width, height: args.height, present_mode: args.present_mode.unwrap_or_default(), alpha_mode: args.alpha_mode, view_formats: args.view_formats, }; let err = gfx_select!(device => instance.surface_configure(surface, device, &conf)); Ok(WebGpuResult::maybe_err(err)) } #[op2] #[serde] pub fn op_webgpu_surface_get_current_texture( state: &mut OpState, #[smi] device_rid: ResourceId, #[smi] surface_rid: ResourceId, ) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table .get::(device_rid)?; let device = device_resource.1; let surface_resource = state.resource_table.get::(surface_rid)?; let surface = surface_resource.1; let output = gfx_select!(device => instance.surface_get_current_texture(surface, ()))?; match output.status { SurfaceStatus::Good | SurfaceStatus::Suboptimal => { let id = output.texture_id.unwrap(); let rid = state.resource_table.add(crate::texture::WebGpuTexture { instance: instance.clone(), id, owned: false, }); Ok(WebGpuResult::rid(rid)) } _ => Err(AnyError::msg("Invalid Surface Status")), } } #[op2(fast)] pub fn op_webgpu_surface_present( state: &mut OpState, #[smi] device_rid: ResourceId, #[smi] surface_rid: ResourceId, ) -> Result<(), AnyError> { let instance = state.borrow::(); let device_resource = state .resource_table .get::(device_rid)?; let device = device_resource.1; let surface_resource = state.resource_table.get::(surface_rid)?; let surface = surface_resource.1; let _ = gfx_select!(device => instance.surface_present(surface))?; Ok(()) }