Observed AE layer parenting semantics:
* layers are flagged as either 2D or 3D
* camera applies to 3D layers, but not to 2D layers
* parented 3D layers treat their ancestor transform chain as 3D (SkMatrix44)
* parented 2D layers treat their ancestor transform chain as 2D (SkMatrix, ignoring 3D components)
This means that for a given layer, we may need to build two distinct transform chains - depending
on the type of descendant layer being considered.
Furthermore, transforms are animatable and their animators are scoped to a layer controller. Since
we're potentially building two version of the transform node, we need to ensure all animators for
both of them are transferred to controller object (we still want to only instantiate a single layer
controller and render tree to avoid duplication). IOW, all dependent layer transforms need to be
considered before "sealing off" a given layer controller.
In order to avoid a layer dependency/topological sort, we can split off the transform tree
construction into a separate pass. High-level changes:
-- replace existing LayerAttachContext with CompositionBuilder
(holds LayerBuilders and other Composition-wide state)
-- replace LayerRec with LayerBuilder
(holds Layer-wide state and also caches transform nodes)
-- pass 1: for each LayerBuilder, transitively build and cache a transform chain
of a type (2d/3d) determined by the leaf (entry point) layer
-- pass 2: for each LayerBuilder, build the actual layer content render tree
and instantiate the layer controller objects
Bug: skia:8914
Change-Id: I9f7efcf4819424282fd3dda98f5621ba12fd001b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/251001
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Add a new seek method which takes a frame index. This provides more accurate
control when rendering of exact frames is needed.
Also surface the animation frame rate, and convert skottie_tool to use this
new mechanism (now defaulting to native animation frame rate).
Change-Id: Id870629e1747a9f70cbf4d3e770366df1299a519
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/249799
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Reed <reed@google.com>
When 3D layers are present, we need a camera view even when no explicit
camera is present.
TBR=
Bug: skia:8914
Change-Id: I408986d516e03bc4f80c7c09103e09821704ff2f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/249420
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Currently, the camera view transform is attached to the render tree as a
TransformEffect. This means it gets "flattened" to an SkMatrix in isolation,
and does not compose with other layer transforms in 4x4 format.
Refactor the implementation to
- build the camera transform upfront
- compose (chain) all layer transforms from this camera transform
This ensures that transform composition happens in SkMatrix44.
E.g. render tree topology change (TE == TransformEffect)
Before:
[root]
|
[TE]<---[CameraT]
|
------------------------------------
| |
| |
[TE]<--[Layer1T] [Layer2T]-->[TE]
| |
[Layer1] [Layer2]
| |
After:
[root]
|
|
------------------------------------
| |
| [CameraT] |
| / \ |
[TE]<--[Layer1T]<-- --->[Layer2T]-->[TE]
| |
[Layer1] [Layer2]
| |
TBR=
Bug: skia:8914
Change-Id: Idd407712f75c48623b5299a4284ddb17b98c155f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/249217
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Instead of rendering all .mp4 frames then encoding, we can kick off
rendering and have the encoder consume frames in order as they become
available.
This uses std::promise / std::future pairs to make the handoff: frame
producers fulfill thieir promise by moving their image into set_value(),
and the encoder (main thread) consumes them by moving those images out
of the paired std::future(). It may not be obvious, but the line
sk_sp<SkImage> img = frame.get_future().get();
does move the image into `img`... gMP4Frames does not hold a ref once
.get_future().get() has returned. (Though depending on when you look,
the surface still might.)
This lets us get going on encoding as soon as the first frame is ready,
and hypothetically means encoding should finish shortly after the last
frame draws. But, different frames cost different time to draw, and we
can't control the order they'll return. We _do_ have control over the
order they're started, and we're doing that exactly wrong using a LIFO
thread pool. I've added .mp4 encoding starvation stats to show this...
when I run in LIFO order it looks typically something like
starved min 0ms, med 0ms, avg 4.12333ms, max 2115ms, sum 2474ms
frame time min 12ms, med 292ms, avg 307.208ms, max 711ms, sum 184325ms
106.68user 57.27system 0:04.55elapsed 3601%CPU (0avgtext+0avgdata 3159748maxresident)k
0inputs+1528outputs (0major+772790minor)pagefaults 0swaps
Mirroring the batch order with (i = frame_count - 1 - i) results in less
starvation, less memory usage, better scaling, and a quicker wall time.
starved min 0ms, med 0ms, avg 0.896667ms, max 382ms, sum 538ms
frame time min 13ms, med 374ms, avg 344.365ms, max 918ms, sum 206619ms
111.64user 52.56system 0:03.62elapsed 4529%CPU (0avgtext+0avgdata 2660912maxresident)k
0inputs+1528outputs (0major+649031minor)pagefaults 0swaps
Change-Id: Ic60e8eac856af238ef32e3383d86f6c24e5c7851
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/247674
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
Change-Id: If57514c9e7e8d0a417eb9388873bbb348fc49076
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/247384
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This runs way faster than skottie2movie, even with Mike's patch.
We could probably ditch skottie2movie with this CL and one adding --gpu?
Change-Id: I41376c2cd636eb75a3a6d2aaa75bef48211a1021
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/247377
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Klein <mtklein@google.com>
Currently we only constrain vertically, assuming shaped lines don't
overflow horizontally. This is not true for very long words.
Update kVisualResizeToFit and kVisualDownscaleToFit to constrain in
both dimensions.
Also drop the early exit condition because
a) it makes less sense when checking in 2 dimensions (there are
multiple answers which fit snugly in one dimension, but we're
ultimately selecting for the largest font size)
b) it probably doesn't trigger much in practice
Existing tests cover the change in behavior.
Bug: skia:9471
Change-Id: I4e53a51500b02ba7db26dad249458bcf491b088a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/246305
Reviewed-by: Avinash Parchuri <aparchur@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
For motion blur we're sampling within some window around a given t.
If t is close to the layer in/out point, things get murky: for samples
which fall outside the layer lifespan, we skip drawing => fewer samples
are accumulated => the opacity of the result drops => visual glitches.
The solution is to modulate the frame alpha based on the number of
*visible* samples, and skip rendering when no samples are visible.
Bug: skia:9486
Change-Id: I8d9692ae1589b43d9e6f728d7b7ac2fbf39153fe
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245363
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Limit the optional/top layer size to the dest area.
Change-Id: Ic3825ff3c12d87b01f18f52ea60bfc31710e2272
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/244885
Commit-Queue: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
Auto-Submit: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Reed <reed@google.com>
Pre-compute the scale matrix based on the main thread animation size,
to avoid touching thread-local animations before null-checking.
Change-Id: Ib2b91d9db7d60a1bd31b21972de136fd838b8377
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/244836
Commit-Queue: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Klein <mtklein@google.com>
Auto-Submit: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@google.com>
Useful for excluding encoder/IO from scaling tests.
Change-Id: Ib76cc07a54d3cd3e00b4a3b3c9ea6f049440b7f8
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/244396
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@google.com>
Change-Id: I9d02ff9f6bcc86cdc10e01a4e3379014557172e9
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/244507
Commit-Queue: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Klein <mtklein@google.com>
Auto-Submit: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@google.com>
I think this is largely free win if done once at process startup:
$ time out/skottie_tool -i ~/Downloads/mb/data.json -w before
166.59user 29.42system 0:06.13elapsed 3195%CPU (0avgtext+0avgdata 1994888maxresident)k
$ time out/skottie_tool -i ~/Downloads/mb/data.json -w after
93.36user 34.96system 0:04.76elapsed 2690%CPU (0avgtext+0avgdata 1968568maxresident)k
$ idiff before after
1333 files are identical.
Change-Id: I5454aed5e64bf78d61dfdc22ea1ce629714bd70c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/244120
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
$ time out/skottie_tool -i ~/Downloads/mb/data.json -w after
Animation loaded with 2 errors, 0 warnings.
!! Could not create typeface for Google Sans|Bold.
!! Could not create typeface for Google Sans|Medium.
frame time min 28ms, med 286ms, avg 441.18ms, max 1982ms, sum 264708ms
93.74user 33.03system 0:04.70elapsed 2694%CPU (0avgtext+0avgdata 1976980maxresident)k
Things are looking pretty reasonable scaling-wise when we take ~5
seconds to run and some frames take up to ~2 seconds.
Change-Id: I0bfd955afcd9b8ac18e6614e1b5aa6889a06059a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/244121
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
There's an implicit +1 to the SkTaskGroup worker count, as the
main/scheduling thread also participates in the queue.
This is quite confusing.
Adjust the --threads parameter such that 1 means single threaded,
2 means rendering on two threads, etc.
Change-Id: Ib55c4b0a29cb342c7d18a15384e1c511614ee7af
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243740
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Parallelize frame rendering and encoding:
- introduce a caching/pre-decoding resource manager.
- dispatch individual frames to a task group
- use per-thread animation instances and sinks
Change-Id: I91549ed20e3346c445defa0d8734648f8a89f8df
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243659
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Mike Klein <mtklein@google.com>
MotionBlurEffect makes use of many abilities some consider to be
unnatural. Notably, it mutates the state of its subtree at render time
(gasp) to sample various time points.
Mutation triggers scene graph invalidation, which bubbles up the
ancestor chain. While we immediately revalidate the subtree, we
cannot do the same for ancestors (no full scene knowledge). This means
post-rendering, we leave some SG nodes dirty - which triggers various
debug asserts).
The easiest fix is to temporarily suppress invalidation bubbling at the
MotionBlurEffect node level (this is safe, because we always revalidate
the subtree).
Also add a post-render assert for tighter state validation.
Change-Id: I376b7a8880f71d85e595c419334b42bc4720ac65
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243420
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
CQ_INCLUDE_TRYBOTS=skia.primary:Build-Win-MSVC-arm64-Debug,Build-Win-MSVC-x86_64-Debug
Change-Id: I381da9c2b2e9b98bc50e8d80ead10ad048e50fce
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243036
Commit-Queue: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
The gist here is to use saveLayer() to create a buffer to draw each
subframe into, but not actually use it to draw anything at restore()
time, hence, canvas->clear(0). (SkCanvas sniffs out cleverer approaches
like 0 alpha or SkBlendMode::kDst.)
Instead, we accessTopLayerPixels() and slurp the subframe out into a
16-bit accumulator, then when all subframes have drawn and accumulated
there, one more saveLayer() and accessTopLayerPixels() lets us put them
back, shifting back down to 8-bit.
The hot parts of the profile are drawing the frames themselves, then the
accumulate / repack code in renderToRaster8888Pow2Samples().
$ time out/skottie_tool -i ~/Downloads/mb/data.json -w bar
Before: 28.39user 1.14system 0:29.54elapsed
After: 22.08user 1.12system 0:23.21elapsed
I'm not proud of it.
...
...
...
I am a bit!
Now using one layer.
Change-Id: I241529fad4c5b55c6abc55793f2d9c9693a03c18
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/242853
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
This trades a bit of file size for CPU time spent encoding,
making Skia dominate the profile. Most of our other tools
use these same settings for the same reason.
Before:
$ time out/skottie_tool -i resources/skottie/skottie-text-animator-4.json -w bar; du -sh bar
1.53user 0.82system 0:02.35elapsed
1.3M bar
After:
$ time out/skottie_tool -i resources/skottie/skottie-text-animator-4.json -w bar; du -sh bar
0.49user 0.81system 0:01.31elapsed
1.7M bar
Change-Id: If00ca43d49e3f12d2e34e1a2b8e15158e6a76034
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/242498
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
Only call into SkShaper when the text value changes.
Change-Id: I4c44a20fd48be932f9ffe23af5ebcc12b67956ee
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/241077
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
The main motivation for this change is getting *all* shape generators to
run the ramp through a cubic mapper - this will allow adding
ease-in/ease-out support in a follow up CL.
As a bonus, the new implementation is more straightforward and concise
(at the expense of dropping some likely-premature optimizations).
Change-Id: Ia2bc53525ae529c35300be124220b4d61e4fc474
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/238061
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
<ostream> is one of the more expensive headers to include
and that's amplified by SkRefCnt.h's popularity.
We've been including <ostream> for sk_sp's operator<<. That's only
used by Chromium and while we could just sprinkle in a bunch of .get()
calls and remove operator<<, when I started going through and actually
doing that I got the feeling I was making things pointlessly harder to
read and write, and wanted to find a way to make it actually work.
My next instinct was to template it without mentioning ostreams,
template <typename OS, typename T>
auto operator<<(OS& os, const sk_sp<T>& sp) -> decltype(os << sp.get()) {
return os << sp.get();
}
but that makes this operator<< ambiguous with some other templated operator<<
in GTest. They got in first, so they win...
So ultimately, switch <ostream> to <iosfwd>. Anyone using our
operator<<() presumably has <ostream> included already, and the #include
cost for <iosfwd> is small enough that I don't think we'll mind keeping
this around indefinitely.
To repro, look at before/after of -ftime-trace:
~/chromium/src/third_party/llvm-build/Release+Asserts/bin/clang++ -I. -Os -c src/core/SkCanvas.cpp -ftime-trace
I have tested locally that Chromium builds with this change.
Change-Id: I9decc2e65b5cc8fd07d8106a5eff81901aedd7d5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/237190
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
1) don't attempt to attach the effect when the layer is null
2) sksg::onRender can receive a null context - handle it gracefully
TBR=
Change-Id: I4fae08b15d448849c7c99b17df6811ad31f190c8
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/237276
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Introduce a new hybrid valign extension, kVisualDownscaleToFit (sk_vj: 4):
- when the text shaped at the requested size fits within the box,
center vertically (same as kVisualCenter)
- otherwise, scale down until it fits (same as kVisualResizeToFit)
Change-Id: I8e096a49e2b87582e1bd42161657ec4ef561ebdf
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/235601
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Change-Id: I127c979670c3dc7dac2e35908a795afbdefca8f6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/234902
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This is a reland of 2a558f5675
Original change's description:
> [skottie] Add onTextProperty support into PropertyObserver.
>
> This effectively allows observing/modifying properties at the text document level. By default
> Bodymovin exports even static TextDocuments as a single keyframe, so the unit-tests have been
> updated to store the property handles for verification.
>
> Change-Id: Iab8bcb29cdc5626d1abc34593ee9967b543428eb
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/231681
> Commit-Queue: Florin Malita <fmalita@chromium.org>
> Reviewed-by: Florin Malita <fmalita@chromium.org>
Change-Id: I3231607e469dcc321fa5900500a21f0f101c299c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/232628
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Ben Wagner <bungeman@google.com>
This reverts commit 2a558f5675.
Reason for revert: breaking Test-Win7-Clang-Golo-CPU-AVX-x86_64-Debug-All-NativeFonts_GDI bot
Original change's description:
> [skottie] Add onTextProperty support into PropertyObserver.
>
> This effectively allows observing/modifying properties at the text document level. By default
> Bodymovin exports even static TextDocuments as a single keyframe, so the unit-tests have been
> updated to store the property handles for verification.
>
> Change-Id: Iab8bcb29cdc5626d1abc34593ee9967b543428eb
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/231681
> Commit-Queue: Florin Malita <fmalita@chromium.org>
> Reviewed-by: Florin Malita <fmalita@chromium.org>
TBR=fmalita@chromium.org,aparchur@google.com,isabelren@google.com
Change-Id: I5298bb45cd12b86fb921aaf835b2340205fed1b5
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/232582
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This effectively allows observing/modifying properties at the text document level. By default
Bodymovin exports even static TextDocuments as a single keyframe, so the unit-tests have been
updated to store the property handles for verification.
Change-Id: Iab8bcb29cdc5626d1abc34593ee9967b543428eb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/231681
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Due to limitations in BodyMovin/AE JSX, full effect data is not
available (specifically the "channel range" property).
We only support static master hue, static master saturation and
static master lightness at this point.
This CL also introduces a new animation builder pattern:
DiscardableAdapterBase and attachDiscardableAdapter().
The former is a base class for adapters with full animator ownership.
This enables a) capturing raw adapter pointers in animator lambdas and
b) syncing to SG only once, after all local animators are updated).
The latter is a helper for managing adapter creation and optional
destruction (when all adapter properties are static we can discard it).
Change-Id: Iecc4b78830e5464e7958cb12cdfd75a61010aa25
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/231956
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
For text animators without associated range selectors, BodyMovin still
exports a selector entry with invalid (0) domain/shape props.
Suppress warnings for these, as they are expected with BM.
TBR=
Change-Id: I7ec3737ebc2a33f4ba6955975c50ea7bf116b003
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/231481
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
This allows TextValues to be manipulated via the skottie::PropertyObserver API in a future change.
Change-Id: I96b22771d8ee9a90c8d41869ece814b0bfa4dc74
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/230917
Commit-Queue: Florin Malita <fmalita@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>