use dom_struct::dom_struct;
use js::context::{JSContext, NoGC};
use script_bindings::cell::DomRefCell;
use script_bindings::codegen::GenericBindings::WebGPUBinding::{GPUDeviceMethods, GPUQueryType};
use script_bindings::error::{Error, Fallible};
use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
use script_bindings::root::DomRoot;
use webgpu_traits::{WebGPU, WebGPUQuerySet, WebGPURequest};
use crate::conversions::Convert;
use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{
GPUQuerySetDescriptor, GPUQuerySetMethods,
};
use crate::dom::bindings::reflector::DomGlobal as _;
use crate::dom::bindings::str::USVString;
use crate::dom::types::{GPUDevice, GlobalScope};
#[derive(JSTraceable, MallocSizeOf)]
struct DroppableGPUQuerySet {
#[no_trace]
channel: WebGPU,
#[no_trace]
query_set: WebGPUQuerySet,
}
impl Drop for DroppableGPUQuerySet {
fn drop(&mut self) {
if let Err(error) = self
.channel
.0
.send(WebGPURequest::DropQuerySet(self.query_set.0))
{
warn!(
"Failed to send WebGPURequest::DropQuerySet({:?}) ({error})",
self.query_set.0
);
}
}
}
#[dom_struct]
pub(crate) struct GPUQuerySet {
reflector_: Reflector,
droppable: DroppableGPUQuerySet,
label: DomRefCell<USVString>,
r#type: GPUQueryType,
count: u32,
}
impl GPUQuerySet {
pub(crate) fn new_inherited(
label: USVString,
channel: WebGPU,
query_set: WebGPUQuerySet,
r#type: GPUQueryType,
count: u32,
) -> Self {
GPUQuerySet {
reflector_: Reflector::new(),
label: DomRefCell::new(label),
droppable: DroppableGPUQuerySet { channel, query_set },
r#type,
count,
}
}
pub(crate) fn new(
cx: &mut JSContext,
global: &GlobalScope,
label: USVString,
channel: WebGPU,
query_set: WebGPUQuerySet,
r#type: GPUQueryType,
count: u32,
) -> DomRoot<Self> {
reflect_dom_object_with_cx(
Box::new(GPUQuerySet::new_inherited(
label, channel, query_set, r#type, count,
)),
global,
cx,
)
}
pub(crate) fn create(
cx: &mut JSContext,
device: &GPUDevice,
descriptor: &GPUQuerySetDescriptor,
) -> Fallible<DomRoot<Self>> {
if descriptor.type_ == GPUQueryType::Timestamp &&
!device
.Features()
.wgpu_features()
.contains(wgpu_types::Features::TIMESTAMP_QUERY)
{
return Err(Error::Type(
c"The device does not support timestamp queries".to_owned(),
));
}
let query_set_id = device.global().wgpu_id_hub().create_query_set_id();
let channel = device.channel();
if let Err(error) = channel.0.send(WebGPURequest::CreateQuerySet {
device_id: device.id().0,
query_set_id,
descriptor: descriptor.convert(),
}) {
warn!("Failed to send WebGPURequest::CreateQuerySet: {error}");
}
Ok(Self::new(
cx,
&device.global(),
descriptor.parent.label.clone(),
channel,
WebGPUQuerySet(query_set_id),
descriptor.type_,
descriptor.count,
))
}
pub(crate) fn id(&self) -> WebGPUQuerySet {
self.droppable.query_set
}
}
impl GPUQuerySetMethods<crate::DomTypeHolder> for GPUQuerySet {
fn Destroy(&self) {
}
fn Label(&self) -> USVString {
self.label.borrow().clone()
}
fn SetLabel(&self, no_gc: &NoGC, value: USVString) {
*self.label.safe_borrow_mut(no_gc) = value;
}
fn Type(&self) -> GPUQueryType {
self.r#type
}
fn Count(&self) -> u32 {
self.count
}
}