New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented the plumbing for paint worklets #17150
Implemented the plumbing for paint worklets #17150
Conversation
Heads up! This PR modifies the following files:
|
@@ -98,6 +99,9 @@ impl Parse for Image { | |||
if let Ok(gradient) = input.try(|i| Gradient::parse(context, i)) { | |||
return Ok(GenericImage::Gradient(gradient)); | |||
} | |||
if let Ok(paint_worklet) = input.try(|i| PaintWorklet::parse(context, i)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're going to remove this path for Gecko, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Err, that sounded quite inquisitive, I meant "You're going to need to remove" :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -673,6 +677,18 @@ impl Parse for ColorStop { | |||
} | |||
} | |||
|
|||
impl Parse for PaintWorklet { | |||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { | |||
input.try(|i| i.expect_function_matching("paint"))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No input.try
needed here, afaict.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
let task = WorkletTask::Paint(PaintWorkletTask::DrawAPaintImage(name, concrete_object_size, sender)); | ||
let timeout = Duration::from_millis(PAINT_TIMEOUT_MILLISECONDS); | ||
self.schedule_a_worklet_task(task); | ||
receiver.recv_timeout(timeout)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heh, glad recv_timeout
was useful after all!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed!
} | ||
} | ||
|
||
pub fn draw_a_paint_image(&self, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably no need to be pub
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
components/script/dom/window.rs
Outdated
@@ -371,6 +374,14 @@ impl Window { | |||
self.webvr_thread.clone() | |||
} | |||
|
|||
pub fn new_paint_worklet(&self) -> Root<Worklet> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for pub here either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
components/layout_thread/lib.rs
Outdated
@@ -689,6 +695,10 @@ impl LayoutThread { | |||
Msg::SetFinalUrl(final_url) => { | |||
self.url = final_url; | |||
}, | |||
Msg::SetPaintWorkletExecutor(executor) => { | |||
debug!("Setting the paint worklet executor"); | |||
self.paint_worklet_executor = Some(executor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug_assert!(self.paint_worklet_executor.is_none())
? This would need to be refactored if/when we fix #14885
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick review!
components/layout_thread/lib.rs
Outdated
@@ -689,6 +695,10 @@ impl LayoutThread { | |||
Msg::SetFinalUrl(final_url) => { | |||
self.url = final_url; | |||
}, | |||
Msg::SetPaintWorkletExecutor(executor) => { | |||
debug!("Setting the paint worklet executor"); | |||
self.paint_worklet_executor = Some(executor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
} | ||
} | ||
|
||
pub fn draw_a_paint_image(&self, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
components/script/dom/window.rs
Outdated
@@ -371,6 +374,14 @@ impl Window { | |||
self.webvr_thread.clone() | |||
} | |||
|
|||
pub fn new_paint_worklet(&self) -> Root<Worklet> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
let task = WorkletTask::Paint(PaintWorkletTask::DrawAPaintImage(name, concrete_object_size, sender)); | ||
let timeout = Duration::from_millis(PAINT_TIMEOUT_MILLISECONDS); | ||
self.schedule_a_worklet_task(task); | ||
receiver.recv_timeout(timeout)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed!
@@ -98,6 +99,9 @@ impl Parse for Image { | |||
if let Ok(gradient) = input.try(|i| Gradient::parse(context, i)) { | |||
return Ok(GenericImage::Gradient(gradient)); | |||
} | |||
if let Ok(paint_worklet) = input.try(|i| PaintWorklet::parse(context, i)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -673,6 +677,18 @@ impl Parse for ColorStop { | |||
} | |||
} | |||
|
|||
impl Parse for PaintWorklet { | |||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { | |||
input.try(|i| i.expect_function_matching("paint"))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CSS and display list building bits look fine to me with the nits, assuming build_display_list_for_webrender_image
is just moved code.
The dom bits look harmless, but I haven't been following along enough the worklet stuff to consider myself confident enough to stamp it, so better if you get @jdm to do that.
Also, as you've already pointed out, a test would be quite nice :)
fn draw_a_paint_image(&self, | ||
name: Atom, | ||
concrete_object_size: Size2D<Au>, | ||
sender: Sender<Result<Image, PaintWorkletError>>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: indentation :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done,
components/script/dom/worklet.rs
Outdated
@@ -561,7 +578,9 @@ impl WorkletThread { | |||
// TODO: Caching. | |||
// TODO: Avoid re-parsing the origin as a URL. | |||
let resource_fetcher = self.global_init.resource_threads.sender(); | |||
let origin_url = ServoUrl::parse(&*origin.unicode_serialization()).expect("Failed to parse origin as URL."); | |||
let origin_url = ServoUrl::parse(&*origin.unicode_serialization()) | |||
.or_else(|_| ServoUrl::parse("about:blank")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: unwrap_or_else
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
impl ToCss for PaintWorklet { | ||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { | ||
dest.write_str("paint(")?; | ||
dest.write_str(&*self.name)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs to use serialize_identifier
to handle escaping properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
fn draw_a_paint_image(&self, | ||
name: Atom, | ||
concrete_object_size: Size2D<Au>, | ||
sender: Sender<Result<Image, PaintWorkletError>>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done,
components/script/dom/worklet.rs
Outdated
@@ -561,7 +578,9 @@ impl WorkletThread { | |||
// TODO: Caching. | |||
// TODO: Avoid re-parsing the origin as a URL. | |||
let resource_fetcher = self.global_init.resource_threads.sender(); | |||
let origin_url = ServoUrl::parse(&*origin.unicode_serialization()).expect("Failed to parse origin as URL."); | |||
let origin_url = ServoUrl::parse(&*origin.unicode_serialization()) | |||
.or_else(|_| ServoUrl::parse("about:blank")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
impl ToCss for PaintWorklet { | ||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { | ||
dest.write_str("paint(")?; | ||
dest.write_str(&*self.name)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
r? @jdm do you want to have a look at the script/worklet side of things? |
pub struct PaintWorkletGlobalScope { | ||
// The worklet global for this object | ||
worklet_global: WorkletGlobalScope, | ||
// A buffer to draw into |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make these ///?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
debug!("Creating paint worklet global scope for pipeline {}.", pipeline_id); | ||
let global = box PaintWorkletGlobalScope { | ||
worklet_global: WorkletGlobalScope::new_inherited(pipeline_id, base_url, init), | ||
buffer: DOMRefCell::new(Vec::new()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default::default()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
name: Atom, | ||
concrete_object_size: Size2D<Au>, | ||
sender: Sender<Result<Image, PaintWorkletError>>) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: { on the previous line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, though I prefer the brace-on-its-own-line style when the fn defn ended up being multi-line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made changes.
pub struct PaintWorkletGlobalScope { | ||
// The worklet global for this object | ||
worklet_global: WorkletGlobalScope, | ||
// A buffer to draw into |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
debug!("Creating paint worklet global scope for pipeline {}.", pipeline_id); | ||
let global = box PaintWorkletGlobalScope { | ||
worklet_global: WorkletGlobalScope::new_inherited(pipeline_id, base_url, init), | ||
buffer: DOMRefCell::new(Vec::new()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
name: Atom, | ||
concrete_object_size: Size2D<Au>, | ||
sender: Sender<Result<Image, PaintWorkletError>>) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, though I prefer the brace-on-its-own-line style when the fn defn ended up being multi-line.
Looks good. Just needs squashing and a test. |
And this:
|
bc84493
to
e8db3ea
Compare
2e133b0
to
fd17dcd
Compare
@bors-servo r=jdm |
📌 Commit fd17dcd has been approved by |
Implemented the plumbing for paint worklets <!-- Please describe your changes on the following line: --> This PR implements the plumbing for paint worklets: * Adding CSS values for paint worklets. * Implementing a skeleton for the `PaintWorkletGlobalScope` webidl. * Implementing an executor for paint worklet tasks, and passing it from script to layout. * Building the display list items for paint worklet images. This PR does not implement registering or calling paint worklets in JS. Before it merges, this PR needs a reftest added for basic paint worklet functionality. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] There are tests for these changes <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17150) <!-- Reviewable:end -->
☀️ Test successful - android, arm32, arm64, linux-dev, linux-rel-css, linux-rel-wpt, mac-dev-unit, mac-rel-css1, mac-rel-css2, mac-rel-wpt1, mac-rel-wpt2, mac-rel-wpt3, mac-rel-wpt4, windows-msvc-dev |
This PR implements the plumbing for paint worklets:
PaintWorkletGlobalScope
webidl.This PR does not implement registering or calling paint worklets in JS.
Before it merges, this PR needs a reftest added for basic paint worklet functionality.
./mach build -d
does not report any errors./mach test-tidy
does not report any errorsThis change is