|
|
DescriptionAdd SkWebpCodec, for decoding .webp images.
Based on SkImageDecoder_libwebp.
TODO:
Support YUV? (Longer term - may influence our API for SkImageGenerator)
BUG=skia:3257
Committed: https://skia.googlesource.com/skia/+/6f5e619b877b0dc1a42910637a6ffe37add98001
Patch Set 1 #Patch Set 2 : peek, handle rewind, add tests #Patch Set 3 : Remove large stack allocation. #Patch Set 4 : Call newer version of peek. #Patch Set 5 : Support BGRA and ARGB for real. #Patch Set 6 : rebase #
Total comments: 22
Patch Set 7 : Respond to jzern's comments. #Patch Set 8 : Add a FIXME regarding incomplete input. #
Total comments: 10
Patch Set 9 : Allow DM to test decoding webp files. #Patch Set 10 : Rebase #Patch Set 11 : Fix conversion from float to int. #
Messages
Total messages: 36 (11 generated)
scroggo@google.com changed reviewers: + halcanary@google.com
scroggo@google.com changed reviewers: + jzern@chromium.org, msarett@google.com
jzern@, can you take a look at this and see if our use of webp makes sense? This code is based on SkImageDecoder_libwebp, which I believe was written by the webp team (possibly you?). https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:88: // FIXME: Do we want to support 565? The plan is to not downscale to 565, but if the data were natively 565, we could return it. Is that ever the case?
On 2015/04/02 21:31:55, scroggo wrote: > jzern@, can you take a look at this and see if our use of webp makes sense? Looks all right, just some small comments. > This > code is based on SkImageDecoder_libwebp, which I believe was written by the webp > team (possibly you?). > Probably Vikas, no matter.
Just a few questions. https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:168: config.output.u.RGBA.rgba = (uint8_t*) dst; Does this mean we always convert to RGBA? It looks like we indicate that we also support BGRA? Is the reason that it is important to specify because we are not using the skia swizzler which handles both as kN32? https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:183: return kInvalidInput; // Or incomplete? I'm not familiar with webp format, but in this type of situation, I've been filling the remainder of the image with some default value and then returning kIncompleteInput.
On 2015/04/02 22:56:27, jzern wrote: > On 2015/04/02 21:31:55, scroggo wrote: > > jzern@, can you take a look at this and see if our use of webp makes sense? > > Looks all right, just some small comments. Do you have some unpublished draft comments? (Unfortunately, clicking reply down at the bottom does not publish your draft comments if you made any...) https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:168: config.output.u.RGBA.rgba = (uint8_t*) dst; On 2015/04/03 12:28:13, msarett wrote: > Does this mean we always convert to RGBA? jzern@ can confirm, but if I understand correctly, this is used whether you choose BGRA or RGBA. The only other option (looking at the header we have in third_party) is YUVA. > It looks like we indicate that we also support BGRA? That is correct. > Is the reason that it is important to specify because we are not using the skia > swizzler which handles both as kN32? We are not using the SkSwizzler because libwebp appears to be able to handle the swizzling for us. The SkSwizzler *should* handle both versions, but that code has not been written yet. https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:183: return kInvalidInput; // Or incomplete? On 2015/04/03 12:28:13, msarett wrote: > I'm not familiar with webp format, but in this type of situation, I've been > filling the remainder of the image with some default value and then returning > kIncompleteInput. Yeah, I'm a little torn about what to do in this situation in general. If we're missing the last couple of lines, for example, I think we should return kIncompleteInput. If we failed initially, maybe that should be a straight failure? In order to treat those situations differently, we'd need to know how far we are into the image. We also need to know that so we can know how many lines we need to fill. jzern@, is there a way to know what lines were decoded successfully? On the other hand, maybe it's up to the caller to decide whether we decoded enough for them? Unfortunately we do not provide a way for them to know how much of the image was decoded. With kIncompleteInput they can just decide to take what we give them or treat it as a failure.
On 2015/04/03 14:14:12, scroggo wrote: > On 2015/04/02 22:56:27, jzern wrote: > > On 2015/04/02 21:31:55, scroggo wrote: > > > jzern@, can you take a look at this and see if our use of webp makes sense? > > > > Looks all right, just some small comments. > > Do you have some unpublished draft comments? (Unfortunately, clicking reply down > at the bottom does not publish your draft comments if you made any...) > Sorry about that, I wasn't paying attention...
https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:15: // http://www.webmproject.org/code/#libwebp_webp_image_decoder_library #libwebp-webp-image-library https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:16: // http://review.webmproject.org/gitweb?p=libwebp.git long dead. review is on gerrit.chromium, but https://chromium.googlesource.com/webm/libwebp will work https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:18: extern "C" { I don't think this was ever necessary with the public headers, they should have this within them. https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:37: static const size_t WEBP_VP8_HEADER_SIZE = 64; note we use 30 in blink to ensure a partial demux will succeed. that's large enough for a VP8X chunk + header to allow width / height info to be returned https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:54: // sanity check for image size that's about to be decoded. this is OK, we have lib protection for this too https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:88: // FIXME: Do we want to support 565? On 2015/04/02 21:31:55, scroggo wrote: > The plan is to not downscale to 565, but if the data were natively 565, we could > return it. Is that ever the case? No. The format is natively yuv420 for lossy or 32-bit rgba for lossless. 565 can be imported but it's converted before processing, so that information is lost. https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:117: return premultiply ? MODE_bgrA : MODE_BGRA; note this is memory layout and isn't affected by endianness, not sure if that's true for skia or whether you'd like to treat this as a uint32 https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:151: // Wait, this seems like an error in the decoder? would indicate an abi mismatch https://codereview.chromium.org/1044433002/diff/100001/tests/CodexTest.cpp File tests/CodexTest.cpp (right): https://codereview.chromium.org/1044433002/diff/100001/tests/CodexTest.cpp#ne... tests/CodexTest.cpp:90: check(r, "yellow_rose.webp", SkISize::Make(400, 301), false); should be OK if you aren't concerned here about full lossless/(no)alpha coverage here
https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:183: return kInvalidInput; // Or incomplete? On 2015/04/03 14:14:12, scroggo wrote: > [...] > jzern@, is there a way to know what lines were decoded > successfully? > yes this is how we handle incremental decoding in blink for instance. you can use WebPIDecGetRGB / WebPIDecGetYUVA to retrieve the line count. it seems we're missing a concrete example in the decode guide [1], but the function is simple enough: WEBP_EXTERN(uint8_t*) WebPIDecGetRGB( const WebPIDecoder* idec, int* last_y, int* width, int* height, int* stride); [1] https://developers.google.com/speed/webp/docs/api#advanced_decoding_api
On 2015/04/03 19:15:30, jzern wrote: > Sorry about that, I wasn't paying attention... NP, it happens fairly regularly. Thanks for the input! https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:15: // http://www.webmproject.org/code/#libwebp_webp_image_decoder_library On 2015/04/03 19:15:48, jzern wrote: > #libwebp-webp-image-library Done. https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:16: // http://review.webmproject.org/gitweb?p=libwebp.git On 2015/04/03 19:15:49, jzern wrote: > long dead. review is on gerrit.chromium, but > https://chromium.googlesource.com/webm/libwebp > will work Done. https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:18: extern "C" { On 2015/04/03 19:15:49, jzern wrote: > I don't think this was ever necessary with the public headers, they should have > this within them. Done. https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:37: static const size_t WEBP_VP8_HEADER_SIZE = 64; On 2015/04/03 19:15:48, jzern wrote: > note we use 30 in blink to ensure a partial demux will succeed. that's large > enough for a VP8X chunk + header to allow width / height info to be returned Done. https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:88: // FIXME: Do we want to support 565? On 2015/04/03 19:15:48, jzern wrote: > On 2015/04/02 21:31:55, scroggo wrote: > > The plan is to not downscale to 565, but if the data were natively 565, we > could > > return it. Is that ever the case? > > No. The format is natively yuv420 for lossy or 32-bit rgba for lossless. 565 can > be imported but it's converted before processing, so that information is lost. Good to know. Thanks! https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:117: return premultiply ? MODE_bgrA : MODE_BGRA; On 2015/04/03 19:15:48, jzern wrote: > note this is memory layout and isn't affected by endianness, not sure if that's > true for skia or whether you'd like to treat this as a uint32 The difference between kBGRA_8888_SkColorType and kRGBA_888_SkColorType is endianness (unless configured otherwise by someone building Skia using a different #define for SK_PMCOLOR_BYTE_ORDER). I think this is what we want. (The old code, in SkImageDecoder_libwebp.cpp: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/skia/s... , chooses MODE_BGRA or MODE_RGBA (or their premultiplied counterparts) based on SK_PMCOLOR_BYTE_ORDER, which is the same check we use to determine which SkColorType kN32 (used in the old code) maps to.) https://codereview.chromium.org/1044433002/diff/100001/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:151: // Wait, this seems like an error in the decoder? On 2015/04/03 19:15:49, jzern wrote: > would indicate an abi mismatch Acknowledged.
lgtm
scroggo@google.com changed reviewers: + djsollen@google.com
Derek and/or Matt, can you take a look? I think I need a Skia member to approve, and I understand Hal is busy. Thanks
https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:67: // best type, when Skia currently cannot draw unpremul (and raster is faster if we are going to draw this multiple times won't it be better to pay the premul cost only once? https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:107: dim.fHeight *= desiredScale; I think I remember vikas saying that while they supported arbitrary scaling in webp the algorithms for doing it wouldn't be any better than us doing it. https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:161: config.options.scaled_height = dimensions.height(); I think I remember vikas saying that while they supported arbitrary scaling in webp the algorithms for doing it wouldn't be any better than us doing it (and possibly worse if we have neonized code).
https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:67: // best type, when Skia currently cannot draw unpremul (and raster is faster On 2015/04/06 14:36:28, djsollen wrote: > if we are going to draw this multiple times won't it be better to pay the premul > cost only once? Yes, when drawing to software. My understanding is that hardware backends can theoretically accept unpremul input without any real cost, meaning it is actually slower to do the premultiplication here at all. I say theoretically because as I understand it, neither Ganesh nor HWUI is ready to take unpremul input. I was thinking that by default, BitmapDecoder would return an unpremul Bitmap. That of course depends on all of our backends supporting unpremul. It does *not* mean that SkCodec needs to report unpremul, though it does seem intuitive for the two to align. The larger question is, what does this info mean? I was thinking it meant "this is the most natural approximation of the data in Skia." As such, other SkCodecs also default to kUnpremul_SkAlphaType when the colors are stored unpremultiplied. (jzern@, it sounds like webp stores its colors as unpremultiplied. Is that correct?) You could certainly argue that "most natural" means something we can (*currently*) draw, even if it does not represent the data. In that case, I think we should change *all* SkCodecs to use premul rather than unpremul (rather than changing this one here). This also is better for users of SkImageGenerators that just use the default info (e.g. SkDiscardablePixelRef or SkCachingPixelRef). https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:107: dim.fHeight *= desiredScale; On 2015/04/06 14:36:28, djsollen wrote: > I think I remember vikas saying that while they supported arbitrary scaling in > webp the algorithms for doing it wouldn't be any better than us doing it. Oh, yeah, maybe. jzern@, does that sound correct? That said, for us to do the arbitrary scaling, we'll need to be able to decode individual scanlines (or sets of 16, as vikas suggested, since he said the decoder works in groups of 16 scanlines). Maybe we should leave this in with a FIXME until we can get scanlines from libwebp (unless there is a way already that we do not know about, jzern@?). https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:161: config.options.scaled_height = dimensions.height(); On 2015/04/06 14:36:28, djsollen wrote: > I think I remember vikas saying that while they supported arbitrary scaling in > webp the algorithms for doing it wouldn't be any better than us doing it (and > possibly worse if we have neonized code). See comment in onGetScaledDimensions.
https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:67: // best type, when Skia currently cannot draw unpremul (and raster is faster On 2015/04/06 16:34:43, scroggo wrote: > On 2015/04/06 14:36:28, djsollen wrote: > > if we are going to draw this multiple times won't it be better to pay the > premul > > cost only once? > > Yes, when drawing to software. My understanding is that hardware backends can > theoretically accept unpremul input without any real cost, meaning it is > actually slower to do the premultiplication here at all. I say theoretically > because as I understand it, neither Ganesh nor HWUI is ready to take unpremul > input. > > I was thinking that by default, BitmapDecoder would return an unpremul Bitmap. > That of course depends on all of our backends supporting unpremul. It does *not* > mean that SkCodec needs to report unpremul, though it does seem intuitive for > the two to align. > > The larger question is, what does this info mean? I was thinking it meant "this > is the most natural approximation of the data in Skia." As such, other SkCodecs > also default to kUnpremul_SkAlphaType when the colors are stored > unpremultiplied. (jzern@, it sounds like webp stores its colors as > unpremultiplied. Is that correct?) > Correct. > You could certainly argue that "most natural" means something we can > (*currently*) draw, even if it does not represent the data. In that case, I > think we should change *all* SkCodecs to use premul rather than unpremul (rather > than changing this one here). This also is better for users of SkImageGenerators > that just use the default info (e.g. SkDiscardablePixelRef or > SkCachingPixelRef). https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:107: dim.fHeight *= desiredScale; On 2015/04/06 16:34:43, scroggo wrote: > On 2015/04/06 14:36:28, djsollen wrote: > > I think I remember vikas saying that while they supported arbitrary scaling in > > webp the algorithms for doing it wouldn't be any better than us doing it. > > Oh, yeah, maybe. jzern@, does that sound correct? > The primary motivation of the rescaler is to reduce memory use since it's done per-row not on a final frame. It'd be better used on downscale (upscale is bilinear). There's only C-code now (and some mips), but everything is in place to allow for other platform optimizations. > That said, for us to do the arbitrary scaling, we'll need to be able to decode > individual scanlines (or sets of 16, as vikas suggested, since he said the > decoder works in groups of 16 scanlines). > > Maybe we should leave this in with a FIXME until we can get scanlines from > libwebp (unless there is a way already that we do not know about, jzern@?). Not directly, though you could mimic it with the incremental decoder + WebPIDecGetRGB.
https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:107: dim.fHeight *= desiredScale; On 2015/04/06 21:30:34, jzern wrote: > On 2015/04/06 16:34:43, scroggo wrote: > > On 2015/04/06 14:36:28, djsollen wrote: > > > I think I remember vikas saying that while they supported arbitrary scaling > in > > > webp the algorithms for doing it wouldn't be any better than us doing it. > > > > Oh, yeah, maybe. jzern@, does that sound correct? > > > > The primary motivation of the rescaler is to reduce memory use since it's done > per-row not on a final frame. It'd be better used on downscale (upscale is > bilinear). > There's only C-code now (and some mips), but everything is in place to allow for > other platform optimizations. That is good to know. Saving memory by doing the scaling row by row on a downscale is the main motivation behind us wanting to see individual rows at a time. Using libwebp's use_scaling does limit our options for how to do the scaling, though. (It also means we cannot use our existing platform optimizations.) > > > That said, for us to do the arbitrary scaling, we'll need to be able to decode > > individual scanlines (or sets of 16, as vikas suggested, since he said the > > decoder works in groups of 16 scanlines). > > > > Maybe we should leave this in with a FIXME until we can get scanlines from > > libwebp (unless there is a way already that we do not know about, jzern@?). > > Not directly, though you could mimic it with the incremental decoder + > WebPIDecGetRGB. I was actually thinking about an approach like this. I'm not sure it gets us what we want, though. The goal is to only have a couple of lines of the output buffer allocated, so we'd need to make sure we only provide enough info to the incremental decoder to not go beyond the rows we want. I'm also guessing that we can only set the external memory for the whole image, not for a couple of lines?
https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.cpp File src/codec/SkWebpCodec.cpp (right): https://codereview.chromium.org/1044433002/diff/130006/src/codec/SkWebpCodec.... src/codec/SkWebpCodec.cpp:107: dim.fHeight *= desiredScale; On 2015/04/07 18:46:10, scroggo wrote: > On 2015/04/06 21:30:34, jzern wrote: > > On 2015/04/06 16:34:43, scroggo wrote: > > > On 2015/04/06 14:36:28, djsollen wrote: > > > > I think I remember vikas saying that while they supported arbitrary > scaling > > in > > > > webp the algorithms for doing it wouldn't be any better than us doing it. > > > > > > Oh, yeah, maybe. jzern@, does that sound correct? > > > > > > > The primary motivation of the rescaler is to reduce memory use since it's done > > per-row not on a final frame. It'd be better used on downscale (upscale is > > bilinear). > > There's only C-code now (and some mips), but everything is in place to allow > for > > other platform optimizations. > > That is good to know. Saving memory by doing the scaling row by row on a > downscale is the main motivation behind us wanting to see individual rows at a > time. Using libwebp's use_scaling does limit our options for how to do the > scaling, though. (It also means we cannot use our existing platform > optimizations.) > > > > > > That said, for us to do the arbitrary scaling, we'll need to be able to > decode > > > individual scanlines (or sets of 16, as vikas suggested, since he said the > > > decoder works in groups of 16 scanlines). > > > > > > Maybe we should leave this in with a FIXME until we can get scanlines from > > > libwebp (unless there is a way already that we do not know about, jzern@?). > > > > Not directly, though you could mimic it with the incremental decoder + > > WebPIDecGetRGB. > > I was actually thinking about an approach like this. I'm not sure it gets us > what we want, though. The goal is to only have a couple of lines of the output > buffer allocated, so we'd need to make sure we only provide enough info to the > incremental decoder to not go beyond the rows we want. I'm also guessing that we > can only set the external memory for the whole image, not for a couple of lines? You can change the external memory between calls of append/update and it should return suspended if the memory is exhausted, but I'd have to double check the behavior for a case like this.
The CQ bit was checked by scroggo@google.com to run a CQ dry run
The patchset sent to the CQ was uploaded after l-g-t-m from jzern@chromium.org Link to the patchset: https://codereview.chromium.org/1044433002/#ps170001 (title: "Rebase")
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1044433002/170001
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: Build-Win-MSVC-x86_64-Debug-Trybot on client.skia.compile (JOB_FAILED, http://build.chromium.org/p/client.skia.compile/builders/Build-Win-MSVC-x86_6...)
The CQ bit was checked by scroggo@google.com to run a CQ dry run
The patchset sent to the CQ was uploaded after l-g-t-m from jzern@chromium.org Link to the patchset: https://codereview.chromium.org/1044433002/#ps190001 (title: "Fix conversion from float to int.")
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1044433002/190001
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
The CQ bit was checked by scroggo@google.com
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1044433002/190001
Note for Reviewers: The CQ is waiting for an approval. If you believe that the CL is not ready yet, or if you would like to L-G-T-M with comments then please uncheck the CQ checkbox. Waiting for LGTM from valid reviewer(s) till 2015-06-19 01:22 UTC
scroggo@google.com changed reviewers: + emmaleer@google.com - halcanary@google.com
Can I get a Skia lgtm? With this, and some more code to do subsets for webp, we can replace SkImageDecoder::decodeSubset on Android.
lgtm
Message was sent while issue was closed.
Committed patchset #11 (id:190001) as https://skia.googlesource.com/skia/+/6f5e619b877b0dc1a42910637a6ffe37add98001 |