Implemented paint worklet properties.

This commit is contained in:
Alan Jeffrey 2017-06-14 18:14:54 -05:00
parent de331c6bc8
commit ef033b8362
29 changed files with 353 additions and 118 deletions

View file

@ -10,8 +10,6 @@
//! thread pool implementation, which only performs GC or code loading on
//! a backup thread, not on the primary worklet thread.
use app_units::Au;
use canvas_traits::CanvasData;
use dom::bindings::codegen::Bindings::RequestBinding::RequestCredentials;
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use dom::bindings::codegen::Bindings::WorkletBinding::WorkletMethods;
@ -29,7 +27,6 @@ use dom::bindings::str::USVString;
use dom::bindings::trace::JSTraceable;
use dom::bindings::trace::RootedTraceableBox;
use dom::globalscope::GlobalScope;
use dom::paintworkletglobalscope::PaintWorkletTask;
use dom::promise::Promise;
use dom::testworkletglobalscope::TestWorkletTask;
use dom::window::Window;
@ -38,8 +35,6 @@ use dom::workletglobalscope::WorkletGlobalScopeInit;
use dom::workletglobalscope::WorkletGlobalScopeType;
use dom::workletglobalscope::WorkletTask;
use dom_struct::dom_struct;
use euclid::Size2D;
use ipc_channel::ipc::IpcSender;
use js::jsapi::JSGCParamKey;
use js::jsapi::JSTracer;
use js::jsapi::JS_GC;
@ -59,8 +54,6 @@ use script_runtime::new_rt_and_cx;
use script_thread::MainThreadScriptMsg;
use script_thread::Runnable;
use script_thread::ScriptThread;
use script_traits::PaintWorkletExecutor;
use servo_atoms::Atom;
use servo_rand;
use servo_url::ImmutableOrigin;
use servo_url::ServoUrl;
@ -69,7 +62,6 @@ use std::collections::HashMap;
use std::collections::hash_map;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::atomic::AtomicIsize;
use std::sync::atomic::Ordering;
use std::sync::mpsc;
@ -117,13 +109,6 @@ impl Worklet {
pub fn worklet_global_scope_type(&self) -> WorkletGlobalScopeType {
self.global_type
}
pub fn executor(&self) -> WorkletExecutor {
WorkletExecutor {
worklet_id: self.worklet_id,
primary_sender: Mutex::new(ScriptThread::worklet_thread_pool().primary_sender.clone()),
}
}
}
impl WorkletMethods for Worklet {
@ -268,7 +253,7 @@ impl Drop for WorkletThreadPool {
impl WorkletThreadPool {
/// Create a new thread pool and spawn the threads.
/// When the thread pool is dropped, the threads will be asked to quit.
pub fn spawn(script_sender: Sender<MainThreadScriptMsg>, global_init: WorkletGlobalScopeInit) -> WorkletThreadPool {
pub fn spawn(global_init: WorkletGlobalScopeInit) -> WorkletThreadPool {
let primary_role = WorkletThreadRole::new(false, false);
let hot_backup_role = WorkletThreadRole::new(true, false);
let cold_backup_role = WorkletThreadRole::new(false, true);
@ -276,9 +261,9 @@ impl WorkletThreadPool {
let hot_backup_sender = hot_backup_role.sender.clone();
let cold_backup_sender = cold_backup_role.sender.clone();
let init = WorkletThreadInit {
primary_sender: primary_sender.clone(),
hot_backup_sender: hot_backup_sender.clone(),
cold_backup_sender: cold_backup_sender.clone(),
script_sender: script_sender.clone(),
global_init: global_init,
};
WorkletThreadPool {
@ -388,9 +373,9 @@ impl WorkletThreadRole {
#[derive(Clone)]
struct WorkletThreadInit {
/// Senders
primary_sender: Sender<WorkletData>,
hot_backup_sender: Sender<WorkletData>,
cold_backup_sender: Sender<WorkletData>,
script_sender: Sender<MainThreadScriptMsg>,
/// Data for initializing new worklet global scopes
global_init: WorkletGlobalScopeInit,
@ -406,9 +391,9 @@ struct WorkletThread {
control_receiver: Receiver<WorkletControl>,
/// Senders
primary_sender: Sender<WorkletData>,
hot_backup_sender: Sender<WorkletData>,
cold_backup_sender: Sender<WorkletData>,
script_sender: Sender<MainThreadScriptMsg>,
/// Data for initializing new worklet global scopes
global_init: WorkletGlobalScopeInit,
@ -451,9 +436,9 @@ impl WorkletThread {
let mut thread = RootedTraceableBox::new(WorkletThread {
role: role,
control_receiver: control_receiver,
primary_sender: init.primary_sender,
hot_backup_sender: init.hot_backup_sender,
cold_backup_sender: init.cold_backup_sender,
script_sender: init.script_sender,
global_init: init.global_init,
global_scopes: HashMap::new(),
control_buffer: None,
@ -562,7 +547,8 @@ impl WorkletThread {
hash_map::Entry::Occupied(entry) => Root::from_ref(entry.get()),
hash_map::Entry::Vacant(entry) => {
debug!("Creating new worklet global scope.");
let result = global_type.new(&self.runtime, pipeline_id, base_url, &self.global_init);
let executor = WorkletExecutor::new(worklet_id, self.primary_sender.clone());
let result = global_type.new(&self.runtime, pipeline_id, base_url, executor, &self.global_init);
entry.insert(JS::from_ref(&*result));
result
},
@ -626,7 +612,7 @@ impl WorkletThread {
if old_counter == 1 {
debug!("Resolving promise.");
let msg = MainThreadScriptMsg::WorkletLoaded(pipeline_id);
self.script_sender.send(msg).expect("Worklet thread outlived script thread.");
self.global_init.script_sender.send(msg).expect("Worklet thread outlived script thread.");
self.run_in_script_thread(promise.resolve_runnable(()));
}
}
@ -668,35 +654,28 @@ impl WorkletThread {
{
let msg = CommonScriptMsg::RunnableMsg(ScriptThreadEventCategory::WorkletEvent, box runnable);
let msg = MainThreadScriptMsg::Common(msg);
self.script_sender.send(msg).expect("Worklet thread outlived script thread.");
self.global_init.script_sender.send(msg).expect("Worklet thread outlived script thread.");
}
}
/// An executor of worklet tasks
#[derive(Clone, JSTraceable, HeapSizeOf)]
pub struct WorkletExecutor {
worklet_id: WorkletId,
// Rather annoyingly, we have to use a mutex here because
// layout threads share their context rather than cloning it.
primary_sender: Mutex<Sender<WorkletData>>,
#[ignore_heap_size_of = "channels are hard"]
primary_sender: Sender<WorkletData>,
}
impl WorkletExecutor {
/// Schedule a worklet task to be peformed by the worklet thread pool.
fn schedule_a_worklet_task(&self, task: WorkletTask) {
let _ = self.primary_sender.lock()
.expect("Locking the worklet channel.")
.send(WorkletData::Task(self.worklet_id, task));
fn new(worklet_id: WorkletId, primary_sender: Sender<WorkletData>) -> WorkletExecutor {
WorkletExecutor {
worklet_id: worklet_id,
primary_sender: primary_sender,
}
}
}
impl PaintWorkletExecutor for WorkletExecutor {
/// https://drafts.css-houdini.org/css-paint-api/#draw-a-paint-image
fn draw_a_paint_image(&self,
name: Atom,
concrete_object_size: Size2D<Au>,
sender: IpcSender<CanvasData>)
{
let task = WorkletTask::Paint(PaintWorkletTask::DrawAPaintImage(name, concrete_object_size, sender));
self.schedule_a_worklet_task(task);
/// Schedule a worklet task to be peformed by the worklet thread pool.
pub fn schedule_a_worklet_task(&self, task: WorkletTask) {
let _ = self.primary_sender.send(WorkletData::Task(self.worklet_id, task));
}
}