New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 801768 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Jan 2018
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Android , Windows , Chrome , Mac
Pri: 2
Type: Bug



Sign in to add a comment

SkLayerDrawLooper serialization/deserialization mismatch.

Project Member Reported by vmp...@chromium.org, Jan 13 2018

Issue description

When serializing SkLayerDrawLooper, it seems like filters like SkBlurMaskFilter don't survive past serialization/deserialization.

Is this an expected result? If so, we'd have to create a PaintDrawLooper or something along those lines. I'm hoping that it's just some small change on the Skia side though. 

mtklein@, could you triage/take a look?

This is what I'm doing:

  SkLayerDrawLooper::Builder builder;
  auto* paint = builder.addLayer(SkLayerDrawLooper::LayerInfo());
  paint->setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 3.3f));

  auto looper = builder.detach();
  sk_sp<SkData> data(SkValidatingSerializeFlattenable(looper.get()));

  sk_sp<SkDrawLooper> result(
      static_cast<SkDrawLooper*>(SkValidatingDeserializeFlattenable(
          data->data(), data->size(), SkDrawLooper::GetFlattenableType())));

  /* print looper and result */

The printing gets the initial looper (truncated):
SkLayerDrawLooper (1): 0: paintBits: (None) mode: kDst offset: (0, 0) postTranslate: false
SkPaint:
...
TextSkewX:
0
MaskFilter:
SkBlurMaskFilterImpl: (sigma: 3.3 style: normal flags: (None))
Color:
0xFF000000
...

And the result (truncated):
SkLayerDrawLooper (1): 0: paintBits: (None) mode: kDst offset: (0, 0) postTranslate: false
SkPaint:
...
TextSkewX:
0
Color:
0xFF000000
...

Note that the SkBlurMaskFilterImpl is missing.


 

Comment 2 by reed@google.com, Jan 16 2018

Owner: reed@google.com
The test (in the bug) is building a "default" Info, which signals that we should ignore all paint-overrides in the layer, and just use the caller's paint (the one passed to the 'draw' call). There is no problem in the serial/deserial code.

If you want to have the looper specify a maskfilter for a given layer, then you must set that bit on the Info's fPaintBits field.

Here is a modified code snippet that draws the blur:

    SkLayerDrawLooper::LayerInfo info;
    info.fPaintBits = SkLayerDrawLooper::kMaskFilter_Bit;
    SkLayerDrawLooper::Builder builder;
    auto* paint = builder.addLayer(info);
    paint->setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 3.3f));

    p.setLooper(builder.detach());
    canvas->drawCircle(50, 50, 40, p);

    sk_sp<SkData> data(p.getLooper()->serialize());
    sk_sp<SkDrawLooper> result = SkDrawLooper::Deserialize(data->data(), data->size());

    p.setLooper(result);
    canvas->drawCircle(150, 50, 40, p);

If you comment out the 2nd line where we assign to fPaintBits, both drawings will not show the blur.

Comment 3 by reed@google.com, Jan 16 2018

... oops, need to declare 'p' to be a paint at the beginning.

SkPaint p;
...

Comment 4 by vmp...@chromium.org, Jan 16 2018

Hmm, setting the fPaintBits yields the same result for me. If I use the same code as in the original post, but set the MaskFilter bit, then the only difference in outputs is that the paintBits are set, but the blur filter is still missing:

SkLayerDrawLooper (1): 0: paintBits: (MaskFilter) mode: kDst offset: (0, 0) postTranslate: false
SkPaint:
TextSize:
12
TextScaleX:
1
TextSkewX:
0
Color:
0xFF000000
Stroke Width:
0
Stroke Miter:
4
Flags:
(None)
FilterLevel:
None
TextAlign:
Left
CapType:
Butt
JoinType:
Miter
Style:
Fill
TextEncoding:
UTF8
Hinting:
Normal

My reduced case possibly reduced too much, but in Chrome, we do set the bits properly and the looper is missing filters.

I'm using this:
<!doctype HTML>

<style>
div {
  width: 100px;
  height: 100px;
  background-color: lightblue;
  box-shadow: 10px 10px 10px cyan;
}
</style>

<div></div>

FWIW, I'm just doing toString on the loopers to see the difference, but I also ran this on Chrome with --force-gpu-rasterization and --enable-oop-rasterization. The result is that the looper is there since the drop shadow is drawn, but it's drawn as black and without a blur. When I dug into what's happening, that's when I spotted that the filters associated with the looper are missing.

For completeness, that code path serializes the draw looper here:
https://cs.chromium.org/chromium/src/cc/paint/paint_op_writer.cc?sq=package:chromium&dr=CSs&l=140
and deserializes it here:
https://cs.chromium.org/chromium/src/cc/paint/paint_op_reader.cc?sq=package:chromium&dr=CSs&l=240

Comment 5 by reed@google.com, Jan 16 2018

Cc: fmalita@chromium.org
I haven't had time to dig into it, but as a quick test I grabbed an SKP from the c#4 example (chrome.gpuBenchmarking.printToSkPicture), and it seems to render fine.  So I'm guessing the problem is external to Skia, but will have verify.
layer_0.skp
584 bytes Download

Comment 7 by reed@google.com, Jan 16 2018

Pictures "help" by serializing effects and paints separately. Just calling the raw methods 'from scratch' shows the problem. I think I have a fix here: 

https://skia-review.googlesource.com/c/skia/+/94761

Comment 8 by vmp...@chromium.org, Jan 16 2018

I verified locally that the patch fixes this. Thanks!
Project Member

Comment 9 by bugdroid1@chromium.org, Jan 16 2018

The following revision refers to this bug:
  https://skia.googlesource.com/skia/+/c183d1642055fb9a6304f2ae9d3e75656fd82b7b

commit c183d1642055fb9a6304f2ae9d3e75656fd82b7b
Author: Mike Reed <reed@google.com>
Date: Tue Jan 16 20:46:18 2018

it is not an error to have no flattenable

Bug:801768
Change-Id: Ib6a0a27a1e6828819879c4b5eef9fe0fd319b225
Reviewed-on: https://skia-review.googlesource.com/94761
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>

[modify] https://crrev.com/c183d1642055fb9a6304f2ae9d3e75656fd82b7b/src/core/SkReadBuffer.cpp

Status: Fixed (was: Assigned)

Sign in to add a comment