script/dom/webgl/
webglsync.rs1use std::cell::Cell;
6
7use canvas_traits::webgl::{WebGLCommand, WebGLSyncId, webgl_channel};
8use dom_struct::dom_struct;
9
10use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants;
11use crate::dom::bindings::inheritance::Castable;
12use crate::dom::bindings::refcounted::Trusted;
13use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
14use crate::dom::bindings::root::DomRoot;
15use crate::dom::webgl::webglobject::WebGLObject;
16use crate::dom::webgl::webglrenderingcontext::{Operation, WebGLRenderingContext};
17use crate::script_runtime::CanGc;
18
19#[dom_struct]
20pub(crate) struct WebGLSync {
21 webgl_object: WebGLObject,
22 #[no_trace]
23 sync_id: WebGLSyncId,
24 marked_for_deletion: Cell<bool>,
25 client_wait_status: Cell<Option<u32>>,
26 sync_status: Cell<Option<u32>>,
27}
28
29impl WebGLSync {
30 fn new_inherited(context: &WebGLRenderingContext, sync_id: WebGLSyncId) -> Self {
31 Self {
32 webgl_object: WebGLObject::new_inherited(context),
33 sync_id,
34 marked_for_deletion: Cell::new(false),
35 client_wait_status: Cell::new(None),
36 sync_status: Cell::new(None),
37 }
38 }
39
40 pub(crate) fn new(context: &WebGLRenderingContext, can_gc: CanGc) -> DomRoot<Self> {
41 let (sender, receiver) = webgl_channel().unwrap();
42 context.send_command(WebGLCommand::FenceSync(sender));
43 let sync_id = receiver.recv().unwrap();
44
45 reflect_dom_object(
46 Box::new(WebGLSync::new_inherited(context, sync_id)),
47 &*context.global(),
48 can_gc,
49 )
50 }
51}
52
53impl WebGLSync {
54 pub(crate) fn context(&self) -> &WebGLRenderingContext {
55 self.upcast::<WebGLObject>().context()
56 }
57
58 pub(crate) fn client_wait_sync(
59 &self,
60 context: &WebGLRenderingContext,
61 flags: u32,
62 timeout: u64,
63 ) -> Option<u32> {
64 match self.client_wait_status.get() {
65 Some(constants::TIMEOUT_EXPIRED) | Some(constants::WAIT_FAILED) | None => {
66 let this = Trusted::new(self);
67 let context = Trusted::new(context);
68 let task = task!(request_client_wait_status: move || {
69 let this = this.root();
70 let context = context.root();
71 let (sender, receiver) = webgl_channel().unwrap();
72 context.send_command(WebGLCommand::ClientWaitSync(
73 this.sync_id,
74 flags,
75 timeout,
76 sender,
77 ));
78 this.client_wait_status.set(Some(receiver.recv().unwrap()));
79 });
80 self.global()
81 .task_manager()
82 .dom_manipulation_task_source()
83 .queue(task);
84 },
85 _ => {},
86 }
87 self.client_wait_status.get()
88 }
89
90 pub(crate) fn delete(&self, operation_fallibility: Operation) {
91 if self.is_valid() {
92 self.marked_for_deletion.set(true);
93 let context = self.upcast::<WebGLObject>().context();
94 let cmd = WebGLCommand::DeleteSync(self.sync_id);
95 match operation_fallibility {
96 Operation::Fallible => context.send_command_ignored(cmd),
97 Operation::Infallible => context.send_command(cmd),
98 }
99 }
100 }
101
102 pub(crate) fn get_sync_status(
103 &self,
104 pname: u32,
105 context: &WebGLRenderingContext,
106 ) -> Option<u32> {
107 match self.sync_status.get() {
108 Some(constants::UNSIGNALED) | None => {
109 let this = Trusted::new(self);
110 let context = Trusted::new(context);
111 let task = task!(request_sync_status: move || {
112 let this = this.root();
113 let context = context.root();
114 let (sender, receiver) = webgl_channel().unwrap();
115 context.send_command(WebGLCommand::GetSyncParameter(this.sync_id, pname, sender));
116 this.sync_status.set(Some(receiver.recv().unwrap()));
117 });
118 self.global()
119 .task_manager()
120 .dom_manipulation_task_source()
121 .queue(task);
122 },
123 _ => {},
124 }
125 self.sync_status.get()
126 }
127
128 pub(crate) fn is_valid(&self) -> bool {
129 !self.marked_for_deletion.get()
130 }
131
132 pub(crate) fn id(&self) -> WebGLSyncId {
133 self.sync_id
134 }
135}
136
137impl Drop for WebGLSync {
138 fn drop(&mut self) {
139 self.delete(Operation::Fallible);
140 }
141}