| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ |
| |
| use std::rc::Rc; |
| |
| use constellation_traits::ScriptToConstellationMessage; |
| use dom_struct::dom_struct; |
| use js::jsapi::HandleObject; |
| use webgpu_traits::WebGPUAdapterResponse; |
| use wgpu_types::PowerPreference; |
| |
| use super::wgsllanguagefeatures::WGSLLanguageFeatures; |
| use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ |
| GPUMethods, GPUPowerPreference, GPURequestAdapterOptions, GPUTextureFormat, |
| }; |
| use crate::dom::bindings::error::Error; |
| use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; |
| use crate::dom::bindings::root::{DomRoot, MutNullableDom}; |
| use crate::dom::bindings::str::DOMString; |
| use crate::dom::globalscope::GlobalScope; |
| use crate::dom::promise::Promise; |
| use crate::dom::webgpu::gpuadapter::GPUAdapter; |
| use crate::realms::InRealm; |
| use crate::routed_promise::{RoutedPromiseListener, route_promise}; |
| use crate::script_runtime::CanGc; |
| |
| #[dom_struct] |
| #[allow(clippy::upper_case_acronyms)] |
| pub(crate) struct GPU { |
| reflector_: Reflector, |
| /// Same object for <https://www.w3.org/TR/webgpu/#dom-gpu-wgsllanguagefeatures> |
| wgsl_language_features: MutNullableDom<WGSLLanguageFeatures>, |
| } |
| |
| impl GPU { |
| pub(crate) fn new_inherited() -> GPU { |
| GPU { |
| reflector_: Reflector::new(), |
| wgsl_language_features: MutNullableDom::default(), |
| } |
| } |
| |
| pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<GPU> { |
| reflect_dom_object(Box::new(GPU::new_inherited()), global, can_gc) |
| } |
| } |
| |
| impl GPUMethods<crate::DomTypeHolder> for GPU { |
| // https://gpuweb.github.io/gpuweb/#dom-gpu-requestadapter |
| fn RequestAdapter( |
| &self, |
| options: &GPURequestAdapterOptions, |
| comp: InRealm, |
| can_gc: CanGc, |
| ) -> Rc<Promise> { |
| let global = &self.global(); |
| let promise = Promise::new_in_current_realm(comp, can_gc); |
| let task_source = global.task_manager().dom_manipulation_task_source(); |
| let sender = route_promise(&promise, self, task_source); |
| |
| let power_preference = match options.powerPreference { |
| Some(GPUPowerPreference::Low_power) => PowerPreference::LowPower, |
| Some(GPUPowerPreference::High_performance) => PowerPreference::HighPerformance, |
| None => PowerPreference::default(), |
| }; |
| let ids = global.wgpu_id_hub().create_adapter_id(); |
| |
| let script_to_constellation_chan = global.script_to_constellation_chan(); |
| if script_to_constellation_chan |
| .send(ScriptToConstellationMessage::RequestAdapter( |
| sender, |
| wgpu_core::instance::RequestAdapterOptions { |
| power_preference, |
| compatible_surface: None, |
| force_fallback_adapter: options.forceFallbackAdapter, |
| }, |
| ids, |
| )) |
| .is_err() |
| { |
| promise.reject_error(Error::Operation, can_gc); |
| } |
| promise |
| } |
| |
| /// <https://gpuweb.github.io/gpuweb/#dom-gpu-getpreferredcanvasformat> |
| fn GetPreferredCanvasFormat(&self) -> GPUTextureFormat { |
| // From https://github.com/mozilla-firefox/firefox/blob/24d49101ce17b78c3ba1217d00297fe2891be6b3/dom/webgpu/Instance.h#L68 |
| if cfg!(target_os = "android") { |
| GPUTextureFormat::Rgba8unorm |
| } else { |
| GPUTextureFormat::Bgra8unorm |
| } |
| } |
| |
| /// <https://www.w3.org/TR/webgpu/#dom-gpu-wgsllanguagefeatures> |
| fn WgslLanguageFeatures(&self, can_gc: CanGc) -> DomRoot<WGSLLanguageFeatures> { |
| self.wgsl_language_features |
| .or_init(|| WGSLLanguageFeatures::new(&self.global(), None, can_gc)) |
| } |
| } |
| |
| impl RoutedPromiseListener<WebGPUAdapterResponse> for GPU { |
| fn handle_response( |
| &self, |
| response: WebGPUAdapterResponse, |
| promise: &Rc<Promise>, |
| can_gc: CanGc, |
| ) { |
| match response { |
| Some(Ok(adapter)) => { |
| let adapter = GPUAdapter::new( |
| &self.global(), |
| adapter.channel, |
| DOMString::from(format!( |
| "{} ({:?})", |
| adapter.adapter_info.name, adapter.adapter_id.0 |
| )), |
| HandleObject::null(), |
| adapter.features, |
| adapter.limits, |
| adapter.adapter_info, |
| adapter.adapter_id, |
| can_gc, |
| ); |
| promise.resolve_native(&adapter, can_gc); |
| }, |
| Some(Err(e)) => { |
| warn!("Could not get GPUAdapter ({:?})", e); |
| promise.resolve_native(&None::<GPUAdapter>, can_gc); |
| }, |
| None => { |
| warn!("Couldn't get a response, because WebGPU is disabled"); |
| promise.resolve_native(&None::<GPUAdapter>, can_gc); |
| }, |
| } |
| } |
| } |