Skip to content
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 paint worklets invoking worklet scripts. #17239

Conversation

@asajeffrey
Copy link
Member

asajeffrey commented Jun 8, 2017

Implemented the "invoke a paint callback" functionality of paint worklets (https://drafts.css-houdini.org/css-paint-api/#invoke-a-paint-callback).

This PR does not implement the 2D rendering context, and just generates a placeholder image.


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • These changes do not require tests because we can't write reftests until we have 2D rendering contexts implemented.

This change is Reviewable

@highfive
Copy link

highfive commented Jun 8, 2017

Heads up! This PR modifies the following files:

  • @fitzgen: components/script/dom/paintrenderingcontext2d.rs, components/script/dom/webidls/PaintWorkletGlobalScope.webidl, components/script/dom/webidls/PaintRenderingContext2D.webidl, components/script/dom/bindings/conversions.rs, components/script/dom/mod.rs and 4 more
  • @KiChjang: components/script/dom/paintrenderingcontext2d.rs, components/script/dom/webidls/PaintWorkletGlobalScope.webidl, components/script/dom/webidls/PaintRenderingContext2D.webidl, components/script/dom/bindings/conversions.rs, components/script/dom/mod.rs and 4 more
@highfive
Copy link

highfive commented Jun 8, 2017

warning Warning warning

  • These commits modify unsafe code. Please review it carefully!
  • These commits modify script code, but no tests are modified. Please consider adding a test!
@asajeffrey
Copy link
Member Author

asajeffrey commented Jun 8, 2017

debug!("Got {:?}.", alpha);

// Step 14
if unsafe { !IsConstructor(paint_obj.get()) } {

This comment has been minimized.

@cbrewster

cbrewster Jun 9, 2017

Member

Is paint_ctor allowed to be an arrow function? If not, you may need to unwrap paint_obj first before using IsConstructor.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 9, 2017

Author Member

Step 14 of https://drafts.css-houdini.org/css-paint-api/#dom-paintworkletglobalscope-registerpaint implies no, since IsConstructor of an arrow function is false?

This comment has been minimized.

@cbrewster

cbrewster Jun 9, 2017

Member

@asajeffrey IsConstructor returns true for any wrapper that is callable which includes wrapped arrow functions. If you use UnwrapObject and then use IsConstructor, it will return false for the arrow function.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 12, 2017

Author Member

I tried it, and ran:

registerPaint("foo", (x => "arrow fn"));

and got:

$ ./mach run -d ~/tmp/test.html
ERROR:script::dom::bindings::error: Error at :5:1 Not a constructor.
ERROR:script::dom::bindings::error: Error at :5:1 Not a constructor.
ERROR:script::dom::bindings::error: Error at :5:1 Not a constructor.
...

So it looks like it's doing the right thing? (Which reminds me, this needs some test cases...)

This comment has been minimized.

@cbrewster

cbrewster Jun 12, 2017

Member

Looks like the right thing, quite odd since IsConstructor always returned true for an arrow fn unless I unwrapped it. Maybe it has to do with Function vs VoidFunction

This comment has been minimized.

@asajeffrey

asajeffrey Jun 12, 2017

Author Member

Could be.

@asajeffrey asajeffrey mentioned this pull request Jun 14, 2017
3 of 3 tasks complete
@asajeffrey
Copy link
Member Author

asajeffrey commented Jun 14, 2017

r? @jdm

@highfive highfive assigned jdm and unassigned glennw Jun 14, 2017
Copy link
Member

jdm left a comment

Generally straightforward implementation of the spec. Unfortunately our unsafe SpiderMonkey bindings keep getting in the way.

/// https://drafts.css-houdini.org/css-paint-api/#paint-definitions
paint_definitions: DOMRefCell<HashMap<Atom, PaintDefinition>>,
/// https://drafts.css-houdini.org/css-paint-api/#paint-class-instances
paint_class_instances: DOMRefCell<HashMap<Atom, Heap<JSVal>>>,

This comment has been minimized.

@jdm

jdm Jun 16, 2017

Member

We will need Box<Heap<JSVal>> here.

/// A paint definition
/// https://drafts.css-houdini.org/css-paint-api/#paint-definition
#[derive(Clone, JSTraceable, HeapSizeOf)]
struct PaintDefinition {

This comment has been minimized.

@jdm

jdm Jun 16, 2017

Member

Mark this as #[must_root].

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Done.

class_constructor: Heap<JSVal>,
paint_function: Heap<JSVal>,
#[ignore_heap_size_of = "Rc"]
constructor_valid_flag: Rc<Cell<bool>>,

This comment has been minimized.

@jdm

jdm Jun 16, 2017

Member

It's not clear to me why this is inside an Rc.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

It was because I was cloning the definition. I'm not now, so the Rc is gone.

debug!("Getting alpha.");
let alpha: bool =
unsafe { get_property(cx, paint_obj.handle(), "alpha", ()) }?
.unwrap_or_default();

This comment has been minimized.

@jdm

jdm Jun 16, 2017

Member

This looks like alpha will be false if the alpha property is undefined.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Good point. Fixed.

// Step 19.
let definition = PaintDefinition {
class_constructor: Heap::new(ObjectValue(paint_obj.get())),
paint_function: Heap::new(paint_function),

This comment has been minimized.

@jdm

jdm Jun 16, 2017

Member

Heap::new is dangerous. Please use Heap::default and box the heap values.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Fixed.

// TODO: Steps 1-2.1.
// Step 3.
let definition = match self.paint_definitions.borrow().get(&name) {
Some(defn) => defn.clone(),

This comment has been minimized.

@jdm

jdm Jun 16, 2017

Member

This is scary when a PaintDefinition contains Heap values. We need to find something else to do here.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

OK, I rewrote this to copy out the values needed (into rooted locations) rather than clone the paint definition.

return;
}
// Step 5.4
entry.insert(Heap::new(paint_instance.get()));

This comment has been minimized.

@jdm

jdm Jun 16, 2017

Member

We'll need Heap::default.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Done.

// TODO: Step 10
// Steps 11-12
debug!("Invoking paint function {}.", name);
let args = unsafe { HandleValueArray::from_rooted_slice(&[

This comment has been minimized.

@jdm

jdm Jun 16, 2017

Member

Unfortunately from_rooted_slice is easy to misuse. Please create a RootedVec (rooted_vec!) containing these values and pass its slice as the argument here.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Well I tried, but I hit:

   --> /home/ajeffrey/github/asajeffrey/servo/components/script/dom/macros.rs:549:25
    |
549 |         let mut $name = $crate::dom::bindings::trace::RootedVec::new(&mut root);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `dom::bindings::trace::JSTraceable` is not implemented for `js::jsapi::Value`
    | 
   ::: /home/ajeffrey/github/asajeffrey/servo/components/script/dom/paintworkletglobalscope.rs
    |
171 |         rooted_vec!(let mut args);
    |         -------------------------- in this macro invocation
    |
    = note: required by `<dom::bindings::trace::RootedVec<'a, T>>::new`

The problem being that I need to construct a RootedVec<JSVal>.

There's a similar type error with rooted!(in(cx) let args = ....):

error[E0277]: the trait bound `js::jsapi::HandleValueArray: js::rust::RootKind` is not satisfied
   --> /home/ajeffrey/github/asajeffrey/servo/components/script/dom/paintworkletglobalscope.rs:171:9
    |
171 | /         rooted!(in(cx) let args = unsafe { HandleValueArray::from_rooted_slice(&[
172 | |             ObjectValue(rendering_context.reflector().get_jsobject().get()),
173 | |             ObjectValue(paint_size.reflector().get_jsobject().get()),
174 | |         ]) });
    | |______________^ the trait `js::rust::RootKind` is not implemented for `js::jsapi::HandleValueArray`
    |
    = note: required by `<js::rust::RootedGuard<'a, T>>::new`
    = note: this error originates in a macro outside of the current crate

I'm not sure this is needed anyway, all the objects in the array are already rooted, the only thing is the array itself, but I believe Call manages the lifetime of the arguments object?

This comment has been minimized.

@jdm

jdm Jun 20, 2017

Member

HandleValueArray is a type meaning "this is a pointer to an array of values that are rooted." This is literally storing a pointer to an array that goes out of scope immediately after returning.

This comment has been minimized.

@jdm

jdm Jun 29, 2017

Member

I am ok with the current code as long as we store the slice in a binding that outlives the call to from_rooted_slice, otherwise we are storing a pointer to a temporary stack value that could be overwritten before we actually reach Call.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 29, 2017

Author Member

Cool.

@asajeffrey asajeffrey mentioned this pull request Jun 16, 2017
4 of 4 tasks complete
Copy link
Member Author

asajeffrey left a comment

OK, I fought the JS bindings, and I think it's in better shape now!

/// https://drafts.css-houdini.org/css-paint-api/#paint-definitions
paint_definitions: DOMRefCell<HashMap<Atom, PaintDefinition>>,
/// https://drafts.css-houdini.org/css-paint-api/#paint-class-instances
paint_class_instances: DOMRefCell<HashMap<Atom, Heap<JSVal>>>,

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Done.

// TODO: Steps 1-2.1.
// Step 3.
let definition = match self.paint_definitions.borrow().get(&name) {
Some(defn) => defn.clone(),

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

OK, I rewrote this to copy out the values needed (into rooted locations) rather than clone the paint definition.

return;
}
// Step 5.4
entry.insert(Heap::new(paint_instance.get()));

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Done.

// TODO: Step 10
// Steps 11-12
debug!("Invoking paint function {}.", name);
let args = unsafe { HandleValueArray::from_rooted_slice(&[

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Well I tried, but I hit:

   --> /home/ajeffrey/github/asajeffrey/servo/components/script/dom/macros.rs:549:25
    |
549 |         let mut $name = $crate::dom::bindings::trace::RootedVec::new(&mut root);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `dom::bindings::trace::JSTraceable` is not implemented for `js::jsapi::Value`
    | 
   ::: /home/ajeffrey/github/asajeffrey/servo/components/script/dom/paintworkletglobalscope.rs
    |
171 |         rooted_vec!(let mut args);
    |         -------------------------- in this macro invocation
    |
    = note: required by `<dom::bindings::trace::RootedVec<'a, T>>::new`

The problem being that I need to construct a RootedVec<JSVal>.

There's a similar type error with rooted!(in(cx) let args = ....):

error[E0277]: the trait bound `js::jsapi::HandleValueArray: js::rust::RootKind` is not satisfied
   --> /home/ajeffrey/github/asajeffrey/servo/components/script/dom/paintworkletglobalscope.rs:171:9
    |
171 | /         rooted!(in(cx) let args = unsafe { HandleValueArray::from_rooted_slice(&[
172 | |             ObjectValue(rendering_context.reflector().get_jsobject().get()),
173 | |             ObjectValue(paint_size.reflector().get_jsobject().get()),
174 | |         ]) });
    | |______________^ the trait `js::rust::RootKind` is not implemented for `js::jsapi::HandleValueArray`
    |
    = note: required by `<js::rust::RootedGuard<'a, T>>::new`
    = note: this error originates in a macro outside of the current crate

I'm not sure this is needed anyway, all the objects in the array are already rooted, the only thing is the array itself, but I believe Call manages the lifetime of the arguments object?

debug!("Getting alpha.");
let alpha: bool =
unsafe { get_property(cx, paint_obj.handle(), "alpha", ()) }?
.unwrap_or_default();

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Good point. Fixed.

// Step 19.
let definition = PaintDefinition {
class_constructor: Heap::new(ObjectValue(paint_obj.get())),
paint_function: Heap::new(paint_function),

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Fixed.

/// A paint definition
/// https://drafts.css-houdini.org/css-paint-api/#paint-definition
#[derive(Clone, JSTraceable, HeapSizeOf)]
struct PaintDefinition {

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

Done.

class_constructor: Heap<JSVal>,
paint_function: Heap<JSVal>,
#[ignore_heap_size_of = "Rc"]
constructor_valid_flag: Rc<Cell<bool>>,

This comment has been minimized.

@asajeffrey

asajeffrey Jun 16, 2017

Author Member

It was because I was cloning the definition. I'm not now, so the Rc is gone.

Entry::Vacant(entry) => {
Some(definition) => {
class_constructor.set(definition.class_constructor.get());
paint_function.set(definition.paint_function.get());

This comment has been minimized.

@jdm

jdm Jun 20, 2017

Member

Move these after the code for 5.1.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 21, 2017

Author Member

Done.

@@ -208,6 +215,7 @@ impl PaintWorkletGlobalScopeMethods for PaintWorkletGlobalScope {
let name = Atom::from(name);
let cx = self.worklet_global.get_cx();
rooted!(in(cx) let paint_obj = paint_ctor.callback_holder().get());
let paint_val = ObjectValue(paint_obj.get());

This comment has been minimized.

@jdm

jdm Jun 20, 2017

Member

Unrooted values are scary.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 21, 2017

Author Member

OK, I rooted it, somewhat unnecessarily because the line above roots it too, but better safe than sorry.


impl PaintDefinition {
fn new(class_constructor: JSVal,
paint_function: JSVal,

This comment has been minimized.

@jdm

jdm Jun 20, 2017

Member

Let's take HandleValue arguments instead.

This comment has been minimized.

@asajeffrey

asajeffrey Jun 21, 2017

Author Member

Done.

paint_function: JSVal,
input_properties: Vec<DOMString>,
alpha: bool)
-> Box<PaintDefinition>

This comment has been minimized.

@jdm

jdm Jun 20, 2017

Member

I am actually quite unnerved that this does not trigger our must_root compiler check :(

This comment has been minimized.

@asajeffrey

asajeffrey Jun 21, 2017

Author Member

Indeed.

registerPaint("propertiesThrows", class {
static get inputProperties() { throw new TypeError(); }
paint(ctx, size) { }
});

This comment has been minimized.

@jdm

jdm Jun 20, 2017

Member

These tests may not be needed if #17416 merges first.

// TODO: Step 10
// Steps 11-12
debug!("Invoking paint function {}.", name);
let args = unsafe { HandleValueArray::from_rooted_slice(&[

This comment has been minimized.

@jdm

jdm Jun 20, 2017

Member

HandleValueArray is a type meaning "this is a pointer to an array of values that are rooted." This is literally storing a pointer to an array that goes out of scope immediately after returning.

Copy link
Member Author

asajeffrey left a comment

Some more fighting with GC rooting.

Entry::Vacant(entry) => {
Some(definition) => {
class_constructor.set(definition.class_constructor.get());
paint_function.set(definition.paint_function.get());

This comment has been minimized.

@asajeffrey

asajeffrey Jun 21, 2017

Author Member

Done.

@@ -208,6 +215,7 @@ impl PaintWorkletGlobalScopeMethods for PaintWorkletGlobalScope {
let name = Atom::from(name);
let cx = self.worklet_global.get_cx();
rooted!(in(cx) let paint_obj = paint_ctor.callback_holder().get());
let paint_val = ObjectValue(paint_obj.get());

This comment has been minimized.

@asajeffrey

asajeffrey Jun 21, 2017

Author Member

OK, I rooted it, somewhat unnecessarily because the line above roots it too, but better safe than sorry.


impl PaintDefinition {
fn new(class_constructor: JSVal,
paint_function: JSVal,

This comment has been minimized.

@asajeffrey

asajeffrey Jun 21, 2017

Author Member

Done.

paint_function: JSVal,
input_properties: Vec<DOMString>,
alpha: bool)
-> Box<PaintDefinition>

This comment has been minimized.

@asajeffrey

asajeffrey Jun 21, 2017

Author Member

Indeed.

@bors-servo
Copy link
Contributor

bors-servo commented Jun 22, 2017

The latest upstream changes (presumably #17456) made this pull request unmergeable. Please resolve the merge conflicts.

@asajeffrey asajeffrey force-pushed the asajeffrey:script-paint-worklets-invoke-worklet-scripts branch from db5165a to d89851c Jun 22, 2017
asajeffrey added a commit to asajeffrey/servo that referenced this pull request Jun 23, 2017
asajeffrey added a commit to asajeffrey/servo that referenced this pull request Jun 28, 2017
Copy link
Member Author

asajeffrey left a comment

Can I r=you?

// TODO: Step 10
// Steps 11-12
debug!("Invoking paint function {}.", name);
let args = unsafe { HandleValueArray::from_rooted_slice(&[

This comment has been minimized.

@asajeffrey

asajeffrey Jun 29, 2017

Author Member

Cool.

@asajeffrey asajeffrey force-pushed the asajeffrey:script-paint-worklets-invoke-worklet-scripts branch from 9c9fb82 to 3db4761 Jun 29, 2017
@asajeffrey
Copy link
Member Author

asajeffrey commented Jun 29, 2017

Squashed. @bors-servo r=jdm IRL.

@bors-servo
Copy link
Contributor

bors-servo commented Jun 29, 2017

📌 Commit 3db4761 has been approved by jdm

@bors-servo
Copy link
Contributor

bors-servo commented Jun 29, 2017

🌲 The tree is currently closed for pull requests below priority 9000, this pull request will be tested once the tree is reopened

@jdm
Copy link
Member

jdm commented Jun 30, 2017

@bors-servo: treeclosed-

@bors-servo
Copy link
Contributor

bors-servo commented Jun 30, 2017

Testing commit 3db4761 with merge 39da6d4...

bors-servo added a commit that referenced this pull request Jun 30, 2017
…t-scripts, r=jdm

Implemented paint worklets invoking worklet scripts.

<!-- Please describe your changes on the following line: -->

Implemented the "invoke a paint callback" functionality of paint worklets (https://drafts.css-houdini.org/css-paint-api/#invoke-a-paint-callback).

This PR does not implement the 2D rendering context, and just generates a placeholder image.

---
<!-- 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
- [X] These changes do not require tests because we can't write reftests until we have 2D rendering contexts implemented.

<!-- 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/17239)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Jun 30, 2017

@bors-servo bors-servo merged commit 3db4761 into servo:master Jun 30, 2017
3 checks passed
3 checks passed
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
@bors-servo bors-servo mentioned this pull request Jun 30, 2017
4 of 4 tasks complete
bors-servo added a commit that referenced this pull request Jul 11, 2017
…=jdm

Implement paint worklet properties

<!-- Please describe your changes on the following line: -->

This is the final PR to get basic paint worklet support. It adds support for paint worklet properties (https://drafts.css-houdini.org/css-paint-api/#paint-definition-input-properties). When a paint worklet is registered, it specifies a list of CSS properties, and is provided with their computed values when it is invoked.

This is a dependent PR:
* "Implemented paint worklets invoking worklet scripts" is #17239.
* "Implemented paint worklets rendering contexts" is #17326.

There should be tests added for this, hopefully the existing wpt houdini tests.

---
<!-- 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
- [X] These changes fix #16839
- [x] 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/17364)
<!-- Reviewable:end -->
bors-servo added a commit that referenced this pull request Jul 11, 2017
…=jdm

Implement paint worklet properties

<!-- Please describe your changes on the following line: -->

This is the final PR to get basic paint worklet support. It adds support for paint worklet properties (https://drafts.css-houdini.org/css-paint-api/#paint-definition-input-properties). When a paint worklet is registered, it specifies a list of CSS properties, and is provided with their computed values when it is invoked.

This is a dependent PR:
* "Implemented paint worklets invoking worklet scripts" is #17239.
* "Implemented paint worklets rendering contexts" is #17326.

There should be tests added for this, hopefully the existing wpt houdini tests.

---
<!-- 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
- [X] These changes fix #16839
- [x] 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/17364)
<!-- Reviewable:end -->
bors-servo added a commit that referenced this pull request Jul 20, 2017
Fixed scaling artefacts in paint worklets caused by zoom and hidpi

<!-- Please describe your changes on the following line: -->

This PR renders paint worklet canvases at the device pixel resolution, rather than the CSS pixel resolution.

It's a dependent PR, building on #17239, #17326 and #17364.

---
<!-- 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
- [X] These changes fix #17454
- [X] These changes do not require tests because we don't run reftests with zoom enabled

<!-- 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/17499)
<!-- Reviewable:end -->
bors-servo added a commit that referenced this pull request Jul 21, 2017
Fixed scaling artefacts in paint worklets caused by zoom and hidpi

<!-- Please describe your changes on the following line: -->

This PR renders paint worklet canvases at the device pixel resolution, rather than the CSS pixel resolution.

It's a dependent PR, building on #17239, #17326 and #17364.

---
<!-- 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
- [X] These changes fix #17454
- [X] These changes do not require tests because we don't run reftests with zoom enabled

<!-- 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/17499)
<!-- Reviewable:end -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

6 participants
You can’t perform that action at this time.