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

Add support for color animated properties #2149

Closed
wants to merge 3 commits into from

Conversation

@nc4rrillo
Copy link
Contributor

nc4rrillo commented Dec 1, 2017

Fixes: #2118

Hi,
This is a patch to add support for animated color properties in WebRender.

Some things to note:

  • I modified the animations sample to show off the color animations. I hope my change is okay :).
  • There is an assertion that popped up as a result of me calling gpu_cache.invalidate() in prepare_prim_for_render.

STR for the assertion is:

  • Open animations sample
  • Hit ',' or ',.' to rotate the rects until they go off screen.

Things to do before merging:

  • Fix assertion in gpu_cache.rs line 612
  • Decide on default value for color bindings
  • Investigate border glitch
  • Rebase
  • Measure serialization/deserialization impact
  • Bump WR API version

This change is Reviewable

@nc4rrillo nc4rrillo force-pushed the nc4rrillo:color-animated branch 3 times, most recently from 0112536 to 2539749 Dec 1, 2017
@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 1, 2017

backtrace of the assertion mentioned in the PR description:

thread 'WRRenderBackend#0' panicked at 'assertion failed: `(left == right)`
  left: `Epoch(16)`,
 right: `Epoch(15)`', src/gpu_cache.rs:612:8
stack backtrace:
   0:     0x560cf93306d3 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::h5ffdc97e68d73ef0
                               at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1:     0x560cf932cb80 - std::sys_common::backtrace::_print::h5927dee13340444c
                               at /checkout/src/libstd/sys_common/backtrace.rs:69
   2:     0x560cf93328e3 - std::panicking::default_hook::{{closure}}::h3522a43e516ec509
                               at /checkout/src/libstd/sys_common/backtrace.rs:58
                               at /checkout/src/libstd/panicking.rs:381
   3:     0x560cf9332655 - std::panicking::default_hook::hab587947abeefc97
                               at /checkout/src/libstd/panicking.rs:397
   4:     0x560cf9332d77 - std::panicking::rust_panic_with_hook::hd4c05252aed3c4fa
                               at /checkout/src/libstd/panicking.rs:577
   5:     0x560cf9332bec - std::panicking::begin_panic::h1363ae4ae483138a
                               at /checkout/src/libstd/panicking.rs:538
   6:     0x560cf9332b69 - std::panicking::begin_panic_fmt::h7a41a337a38e2164
                               at /checkout/src/libstd/panicking.rs:522
   7:     0x560cf8bc4ce4 - webrender::gpu_cache::GpuCache::get_address::h51d51a0e1440fd7a
                               at src/gpu_cache.rs:612
   8:     0x560cf8bc6388 - webrender::tiling::add_to_batch::he357d026bffe0069
                               at src/tiling.rs:395
   9:     0x560cf8d1f407 - webrender::tiling::<impl webrender::prim_store::PrimitiveRun>::add_to_batch::h449f3025c24bb52e
                               at src/tiling.rs:72
  10:     0x560cf8b1b590 - webrender::tiling::<impl webrender::picture::PicturePrimitive>::add_to_batch::h7646a9dc3b5c1458
                               at src/tiling.rs:957
  11:     0x560cf8bc7957 - webrender::tiling::add_to_batch::he357d026bffe0069
                               at src/tiling.rs:804
  12:     0x560cf8d1f407 - webrender::tiling::<impl webrender::prim_store::PrimitiveRun>::add_to_batch::h449f3025c24bb52e
                               at src/tiling.rs:72
  13:     0x560cf8b1b590 - webrender::tiling::<impl webrender::picture::PicturePrimitive>::add_to_batch::h7646a9dc3b5c1458
                               at src/tiling.rs:957
  14:     0x560cf8bc7957 - webrender::tiling::add_to_batch::he357d026bffe0069
                               at src/tiling.rs:804
  15:     0x560cf8d1f407 - webrender::tiling::<impl webrender::prim_store::PrimitiveRun>::add_to_batch::h449f3025c24bb52e
                               at src/tiling.rs:72
  16:     0x560cf8b1b590 - webrender::tiling::<impl webrender::picture::PicturePrimitive>::add_to_batch::h7646a9dc3b5c1458
                               at src/tiling.rs:957
  17:     0x560cf8bc7957 - webrender::tiling::add_to_batch::he357d026bffe0069
                               at src/tiling.rs:804
  18:     0x560cf8d1f407 - webrender::tiling::<impl webrender::prim_store::PrimitiveRun>::add_to_batch::h449f3025c24bb52e
                               at src/tiling.rs:72
  19:     0x560cf8b1b590 - webrender::tiling::<impl webrender::picture::PicturePrimitive>::add_to_batch::h7646a9dc3b5c1458
                               at src/tiling.rs:957
  20:     0x560cf8bc7957 - webrender::tiling::add_to_batch::he357d026bffe0069
                               at src/tiling.rs:804
  21:     0x560cf8d1f407 - webrender::tiling::<impl webrender::prim_store::PrimitiveRun>::add_to_batch::h449f3025c24bb52e
                               at src/tiling.rs:72
  22:     0x560cf8b1b590 - webrender::tiling::<impl webrender::picture::PicturePrimitive>::add_to_batch::h7646a9dc3b5c1458
                               at src/tiling.rs:957
  23:     0x560cf8bc7957 - webrender::tiling::add_to_batch::he357d026bffe0069
                               at src/tiling.rs:804
  24:     0x560cf8d1f407 - webrender::tiling::<impl webrender::prim_store::PrimitiveRun>::add_to_batch::h449f3025c24bb52e
                               at src/tiling.rs:72
  25:     0x560cf8b1b590 - webrender::tiling::<impl webrender::picture::PicturePrimitive>::add_to_batch::h7646a9dc3b5c1458
                               at src/tiling.rs:957
  26:     0x560cf8bca16b - webrender::tiling::AlphaBatcher::build::h1fc443cd6ca0ea84
                               at src/tiling.rs:1036
  27:     0x560cf8bcc2a4 - <webrender::tiling::ColorRenderTarget as webrender::tiling::RenderTarget>::build::hdf096be533dadd43
                               at src/tiling.rs:1407
  28:     0x560cf8bce31a - webrender::tiling::RenderPass::build::h17db9bc27270c8dd
                               at src/tiling.rs:1805
  29:     0x560cf8c37cba - webrender::frame_builder::FrameBuilder::build::h63c1c07d28020cc2
                               at src/frame_builder.rs:1790
  30:     0x560cf8cdd00a - webrender::frame::FrameContext::build_rendered_document::hb60abb554f1ea2a5
                               at src/frame.rs:1185
  31:     0x560cf8b10487 - webrender::render_backend::Document::render::hdd3603e1a2065eba
                               at src/render_backend.rs:117
  32:     0x560cf8b11f48 - webrender::render_backend::RenderBackend::process_document::h01d60d63fd9491f6
                               at src/render_backend.rs:419
  33:     0x560cf8b12a1d - webrender::render_backend::RenderBackend::run::h0fd1753afa3b1576
                               at src/render_backend.rs:491
  34:     0x560cf8d64fe8 - webrender::renderer::Renderer::new::{{closure}}::hc85f574d1c07b4d4
                               at src/renderer.rs:1988
  35:     0x560cf8d69184 - std::sys_common::backtrace::__rust_begin_short_backtrace::h904e1df1c5a4e253
                               at /checkout/src/libstd/sys_common/backtrace.rs:134
  36:     0x560cf8c15b0b - std::thread::Builder::spawn::{{closure}}::{{closure}}::hb24e4516680d4ee3
                               at /checkout/src/libstd/thread/mod.rs:402
  37:     0x560cf8ce0574 - <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::h77ee506dc5a53b74
                               at /checkout/src/libstd/panic.rs:296
  38:     0x560cf8ce4c94 - std::panicking::try::do_call::h213fb5694738b52d
                               at /checkout/src/libstd/panicking.rs:480
  39:     0x560cf933b5be - __rust_maybe_catch_panic
                               at /checkout/src/libpanic_unwind/lib.rs:99
  40:     0x560cf8ce470c - std::panicking::try::h74dffcfbd24d1b09
                               at /checkout/src/libstd/panicking.rs:459
  41:     0x560cf8ce3d9c - std::panic::catch_unwind::hd3998450aacf89fd
                               at /checkout/src/libstd/panic.rs:361
  42:     0x560cf8c1595d - std::thread::Builder::spawn::{{closure}}::he3d1d5e244f17f2f
                               at /checkout/src/libstd/thread/mod.rs:401
  43:     0x560cf8c1cd95 - <F as alloc::boxed::FnBox<A>>::call_box::hf6386e2f3b2a3639
                               at /checkout/src/liballoc/boxed.rs:762
  44:     0x560cf9331d5b - std::sys::imp::thread::Thread::new::thread_start::h783d2fade112e868
                               at /checkout/src/liballoc/boxed.rs:772
                               at /checkout/src/libstd/sys_common/thread.rs:24
                               at /checkout/src/libstd/sys/unix/thread.rs:90
  45:     0x7fdd453b36d9 - start_thread
  46:     0x7fdd44ed6d7e - __clone
  47:                0x0 - <unknown>
@glennw
Copy link
Member

glennw commented Dec 4, 2017

Wow, this is amazing work. Apologies I haven't gotten to it yet - will run through this tomorrow.

Not sure if relevant, but I think it's completely fine to do this incrementally (e.g. merge support for just animated color on rects, then follow up with other primitives etc), if that makes things easier.

@bors-servo
Copy link
Contributor

bors-servo commented Dec 4, 2017

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

@glennw
Copy link
Member

glennw commented Dec 5, 2017

Reviewed 23 of 23 files at r1.
Review status: all files reviewed at latest revision, 5 unresolved discussions, some commit checks failed.


webrender/examples/animation.rs, line 296 at r1 (raw file):

                y += 200.;
            }
            

nit: extra spaces


webrender/src/frame_builder.rs, line 844 at r1 (raw file):

            &PropertyBinding::Value(value) => PropertyBinding::Value(value.premultiplied()),
            &PropertyBinding::Binding(binding) => {
                let property_binding_key : PropertyBindingKey<PremultipliedColorF> = unsafe { mem::transmute(binding.key) };

If we were storing the value outside the property, then that would probably make this a lot simpler and remove the transmute nastiness you mentioned?


webrender/src/prim_store.rs, line 1434 at r1 (raw file):

                PrimitiveKind::Rectangle => {
                    let mut rect = &mut self.cpu_rectangles[metadata.cpu_prim_index.0];
                    

nit: extra spaces


wrench/src/rawtest.rs, line 201 at r1 (raw file):

            builder.push_clip_id(clip);
            builder.push_rect(&PrimitiveInfo::new(rect(100., 100., 100., 100.)),
                              ColorF::new(0.0, 0.0, 1.0, 1.0).into());

Perhaps we could instead have the interface be something like:

fn push_rect<P>(&mut self, color: P) where P: Into<PropertyBinding<ColorF>>

So that you can push a color directly in the common case?


wrench/src/yaml_frame_writer.rs, line 739 at r1 (raw file):

                    println!("TODO YAML YuvImage");
                }
                Border(mut item) => {

Having to use all the mutability on stored items is why I originally had the resolved value stored outside the property binding. There's pros and cons to each.


Comments from Reviewable

@glennw
Copy link
Member

glennw commented Dec 5, 2017

This generally looks good to me! My main questions are whether (a) storing the resolved value outside the binding would remove a lot of the extra mutability here and also fix the transmute in the PR, and (b) if we should use the Into trick mentioned above to simplify the case for callers that are just providing colors without a binding.

@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 5, 2017

@glennw that Into trait is a good idea. I agree with moving the resolved value out of PropertyBinding. I'll make that change as well.

I'm also going to revert my changes to add this animated color support to borders and save that for a follow up.

@jrmuizel
Copy link
Contributor

jrmuizel commented Dec 5, 2017

I'm a little worried about the additional serialization/deserialization and display list size cost this might add. Should we measure it?

@glennw
Copy link
Member

glennw commented Dec 5, 2017

@jrmuizel Yea, I'll do some measurements before merging anything.

@nc4rrillo nc4rrillo force-pushed the nc4rrillo:color-animated branch 3 times, most recently from bf2707f to a82bb27 Dec 5, 2017
@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 5, 2017

I've rebased this again and implemented the changes you suggested.

The Into<PropertyBinding<ColorF>> is very good in that very little places need an API change.
AFAICT it should only be places that use GradientStops since create_gradient takes a Vec<GradientStop> directly.

I also reverted my change to PropertyBinding<T> to remove some of the mutability in my earlier changes. This resulted in me having to pass SceneProperties around to some of the FrameBuilder methods which I hope is alright.

For now only rects, box shadows, and gradients have color animation support.

Besides the assertion, another open question I have is about what good behavior for an initial value for color bindings would be. Should the client be expected to GenerateFrame with the initial value? Or should I try to do something similar to what FilterOp does with opacity?

cc: @glennw

(None, true, true)
},
PrimitiveKind::AlignedGradient | PrimitiveKind::AngleGradient | PrimitiveKind::RadialGradient => {
gpu_cache.invalidate(&metadata.gpu_location);

This comment has been minimized.

@nc4rrillo

nc4rrillo Dec 5, 2017

Author Contributor

I don't like that I unconditionally invalidate here.

PrimitiveKind::Brush => {
let brush = &mut self.cpu_brushes[metadata.cpu_prim_index.0];
if let BrushKind::Solid { ref mut color, ref binding } = brush.kind {
*color = scene_properties.resolve_color(&binding);

This comment has been minimized.

@nc4rrillo

nc4rrillo Dec 5, 2017

Author Contributor

Maybe I should add an if let &PropertyBinding::Binding(_) = binding here so I'm not trying to resolve PropertyBinding::Value properties?

@nc4rrillo nc4rrillo force-pushed the nc4rrillo:color-animated branch from a82bb27 to 8088180 Dec 5, 2017
@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 5, 2017

Review status: 0 of 14 files reviewed at latest revision, 7 unresolved discussions.


webrender/examples/animation.rs, line 296 at r1 (raw file):

Previously, glennw (Glenn Watson) wrote…

nit: extra spaces

Done.


webrender/src/frame_builder.rs, line 844 at r1 (raw file):

Previously, glennw (Glenn Watson) wrote…

If we were storing the value outside the property, then that would probably make this a lot simpler and remove the transmute nastiness you mentioned?

Done.


webrender/src/prim_store.rs, line 1434 at r1 (raw file):

Previously, glennw (Glenn Watson) wrote…

nit: extra spaces

Done.


wrench/src/yaml_frame_writer.rs, line 739 at r1 (raw file):

Previously, glennw (Glenn Watson) wrote…

Having to use all the mutability on stored items is why I originally had the resolved value stored outside the property binding. There's pros and cons to each.

Done. Reverted my change to PropertyBinding.


wrench/src/rawtest.rs, line 201 at r1 (raw file):

Previously, glennw (Glenn Watson) wrote…

Perhaps we could instead have the interface be something like:

fn push_rect<P>(&mut self, color: P) where P: Into<PropertyBinding<ColorF>>

So that you can push a color directly in the common case?

Done.


Comments from Reviewable

@nc4rrillo nc4rrillo closed this Dec 5, 2017
@nc4rrillo nc4rrillo reopened this Dec 5, 2017
@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 5, 2017

Accidentally closed. Reopening.

@nc4rrillo nc4rrillo force-pushed the nc4rrillo:color-animated branch 2 times, most recently from b76b8d8 to b42f4ae Dec 5, 2017
@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 5, 2017

@glennw so I managed to also add support for borders (including complex ones) by moving the GPU block building out of the border code and into the primitive code.

I did however run into the following issue while putting together the sample app where some of the borders are glitched:

It only happens with Dashed/Dotted borders of a non zero radius.
I'm investigating if it has anything to do with my changes or if it existed previously

@nc4rrillo nc4rrillo force-pushed the nc4rrillo:color-animated branch from b42f4ae to d7763f1 Dec 5, 2017
@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 5, 2017

So the glitch above isn't related to my change, I'm trying to track down exactly what caused it but I'm pretty far back in the commit history and not having any luck so far. It seems to be affected by the allocation patterns of the render targets, as different changes (for example box shadow caching) have impacted where I see it show up.

@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 5, 2017

it gets weirder 🥇

@nc4rrillo nc4rrillo force-pushed the nc4rrillo:color-animated branch from d7763f1 to df76cf6 Dec 6, 2017
@glennw
Copy link
Member

glennw commented Dec 7, 2017

@nc4rrillo Interesting glitches! But if unrelated to this PR, it doesn't need to block this. Is this ready for re-review again, or is it still in progress?

@nc4rrillo nc4rrillo force-pushed the nc4rrillo:color-animated branch from df76cf6 to 64e1ddf Dec 7, 2017
@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 7, 2017

@glennw This is ready for review now. For default values, I hang it off of PropertyBinding::Binding, the only place where its mutated is in picture.rs where it works much like how FilterOp did.

@nc4rrillo nc4rrillo force-pushed the nc4rrillo:color-animated branch 2 times, most recently from 7d9980b to 00920e9 Dec 7, 2017
@nc4rrillo nc4rrillo force-pushed the nc4rrillo:color-animated branch from 00920e9 to 3097ea2 Dec 7, 2017
@nc4rrillo nc4rrillo changed the title WIP: Add support for color animated properties Add support for color animated properties Dec 7, 2017
@bors-servo
Copy link
Contributor

bors-servo commented Dec 7, 2017

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

@bors-servo
Copy link
Contributor

bors-servo commented Dec 8, 2017

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

@glennw
Copy link
Member

glennw commented Dec 8, 2017

Could you remove the merge commits and rebase it onto master instead? I'll run through this again today or tomorrow, and try to do some measurements of the DL deserialization time differences. I don't expect anything major, but I'll check just in case.

@glennw
Copy link
Member

glennw commented Dec 9, 2017

Reviewed 4 of 23 files at r2, 5 of 15 files at r3, 5 of 8 files at r4, 6 of 6 files at r5.
Review status: all files reviewed at latest revision, 15 unresolved discussions.


webrender/src/border.rs, line 111 at r5 (raw file):

    fn get_corner(
        &self,
        scene_properties: &SceneProperties,

I think we might need to leave doing borders to a follow up PR. In this code here, we determine how we are going to render the border during the scene construction. If the colors then change by an animation property, we would need to re-run this code to determine the most efficient path to render the border.


webrender/src/box_shadow.rs, line 64 at r5 (raw file):

        clip_mode: BoxShadowClipMode,
    ) {
        let color = scene_properties.resolve_color(&binding);

Same issue here, that we resolve during scene construction. If we remove the box shadow, and then it gets animated to a valid color, it won't appear.


webrender/src/frame_builder.rs, line 764 at r5 (raw file):

        aa_mode: BrushAntiAliasMode,
    ) {
        let color = scene_properties.resolve_color(&binding);

Same issue here, unfortunately. We can't discard rectangles based on the scene properties, since they will then be removed if the initial resolved color is invalid.


webrender/src/picture.rs, line 142 at r5 (raw file):

                            &mut FilterOp::Opacity(ref mut binding) => {
                                let value = properties.resolve_float(binding);
                                match binding {

I don't quite follow why we need this code here?


webrender/src/prim_store.rs, line 509 at r5 (raw file):

        request.push([self.widths.left,  self.widths.top, 
                      self.widths.right, self.widths.bottom]);
        

nit: extra spaces


webrender/src/scene.rs, line 33 at r5 (raw file):

        self.float_properties.clear();
        self.color_properties.clear();
        

nit: extra spaces


webrender/src/scene.rs, line 217 at r5 (raw file):

                    PropertyBinding::Binding(_, value) => value
                };
                

nit: extra spaces


webrender/src/tiling.rs, line 808 at r5 (raw file):

                                                FilterOp::Brightness(amount) => (7, amount),
                                                FilterOp::Opacity(binding) => {
                                                    let amount = match binding {

Perhaps we should have a method to return the current value, to avoid duplication.


Comments from Reviewable

@glennw
Copy link
Member

glennw commented Dec 9, 2017

Ugh, I'm so sorry this has turned out to be way more complex than I thought it would. It hadn't occurred to me that we will need to change a lot of how we early reject primitives based on invalid color etc (which are what most of the substantive comments in the last review are in relation to).

I'll be traveling most of next week - but I'll try to follow up on this again. I wonder if it's worth trying to land this with initial support for just the API changes and rectangles only (with the fixes to early discard of the primitives mentioned above)? That might let us get the initial support landed, and then work incrementally on each other primitive. Thoughts?

@glennw
Copy link
Member

glennw commented Dec 9, 2017

PS: I removed the easy tag from the bug this references :)

@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Dec 9, 2017

@glennw That sounds good to me. I'll rework this to support only rectangles for now.

@glennw
Copy link
Member

glennw commented Dec 9, 2017

@nc4rrillo Thanks, and again, apologies for how tricky this has turned out to be.

@bors-servo
Copy link
Contributor

bors-servo commented Dec 9, 2017

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

@glennw
Copy link
Member

glennw commented Jan 29, 2018

@nc4rrillo Should we close this for now?

@nc4rrillo
Copy link
Contributor Author

nc4rrillo commented Jan 29, 2018

Yes I will reopen a PR once I have more time to work on this 🙂

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

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