Chromium Code Reviews| Index: third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp |
| diff --git a/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp b/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp |
| index 78dea66626650db17f55dd143817340770044d42..fabe263e66328b49a1163dc543710b66ab633993 100644 |
| --- a/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp |
| +++ b/third_party/WebKit/Source/platform/graphics/DecodingImageGenerator.cpp |
| @@ -70,34 +70,89 @@ SkData* DecodingImageGenerator::onRefEncodedData(GrContext* ctx) { |
| return m_data->getAsSkData().release(); |
| } |
| -bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info, |
| - void* pixels, |
| - size_t rowBytes, |
| - SkPMColor table[], |
| - int* tableCount) { |
| +bool DecodingImageGenerator::onGetPixels(const SkImageInfo& dstInfo, |
| + void* dstPixels, |
| + size_t dstRowBytes, |
| + SkPMColor*, |
| + int*) { |
| TRACE_EVENT1("blink", "DecodingImageGenerator::getPixels", "frame index", |
| static_cast<int>(m_frameIndex)); |
| // Implementation doesn't support scaling yet, so make sure we're not given a |
| // different size. |
| - if (info.width() != getInfo().width() || info.height() != getInfo().height()) |
| + if (dstInfo.width() != getInfo().width() || |
| + dstInfo.height() != getInfo().height()) { |
| return false; |
| + } |
| - if (info.colorType() != getInfo().colorType()) { |
| - // blink::ImageFrame may have changed the owning SkBitmap to |
| - // kOpaque_SkAlphaType after fully decoding the image frame, so if we see a |
| - // request for opaque, that is ok even if our initial alpha type was not |
| - // opaque. |
| - return false; |
| + sk_sp<SkColorSpace> decodeColorSpace = getInfo().refColorSpace(); |
| + switch (dstInfo.colorType()) { |
| + case kN32_SkColorType: |
| + break; |
| + case kRGBA_F16_SkColorType: |
| + if (!decodeColorSpace || !dstInfo.colorSpace() || |
| + !dstInfo.colorSpace()->gammaIsLinear()) { |
| + return false; |
| + } |
| + break; |
| + default: |
| + return false; |
| } |
| + // Skip the check for alphaType. blink::ImageFrame may have changed the |
| + // owning SkBitmap to kOpaque_SkAlphaType after fully decoding the image |
| + // frame, so if we see a request for opaque, that is ok even if our initial |
| + // alpha type was not opaque. |
| + |
| + void* decodePixels = dstPixels; |
| + size_t decodeRowBytes = dstRowBytes; |
| + std::unique_ptr<uint32_t[]> tmp = nullptr; |
| + if (kRGBA_F16_SkColorType == dstInfo.colorType()) { |
| + // Since the decoder does not support F16, we'll need to decode into a |
| + // temporary buffer, then convert that to F16. |
| + tmp.reset(new uint32_t[dstInfo.width() * dstInfo.height()]); |
| + decodePixels = tmp.get(); |
| + decodeRowBytes = sizeof(uint32_t) * dstInfo.width(); |
| + } |
| + |
| + // Might as well pass kN32 and decodeColorSpace to the decoder. That's what |
| + // the output is always going to be anyway. |
| + SkImageInfo decodeInfo = |
| + dstInfo.makeColorType(kN32_SkColorType).makeColorSpace(decodeColorSpace); |
| PlatformInstrumentation::willDecodeLazyPixelRef(uniqueID()); |
| bool decoded = m_frameGenerator->decodeAndScale( |
| - m_data.get(), m_allDataReceived, m_frameIndex, getInfo(), pixels, |
| - rowBytes); |
| + m_data.get(), m_allDataReceived, m_frameIndex, decodeInfo, decodePixels, |
| + decodeRowBytes); |
| PlatformInstrumentation::didDecodeLazyPixelRef(); |
| - return decoded; |
| + if (!decoded) { |
| + return false; |
| + } |
| + |
| + if (kRGBA_F16_SkColorType == dstInfo.colorType() || |
| + (decodeColorSpace && dstInfo.colorSpace() && |
| + !SkColorSpace::Equals(decodeColorSpace.get(), dstInfo.colorSpace()))) { |
|
f(malita)
2017/03/31 19:52:07
It reads a bit strange for this conditional to be
msarett1
2017/03/31 21:47:30
Yeah I can see how this is confusing. I'm droppin
|
| + // FIXME: |
|
f(malita)
2017/03/31 19:52:07
Nit: Chromium style is // TODO(msarett): ...
msarett1
2017/03/31 21:47:30
Done.
|
| + // Why can't we take this out of the "if" condition and just assert it? |
| + // DCHECK(dstInfo.colorSpace()); |
| + |
| + SkPixmap dst(dstInfo, dstPixels, dstRowBytes); |
| + SkPixmap src(decodeInfo, decodePixels, decodeRowBytes); |
| + |
| + // FIXME: |
|
f(malita)
2017/03/31 19:52:07
Nit: ditto
msarett1
2017/03/31 21:47:30
Done.
|
| + // In the case of images with alpha, the decoder will premultiply them in |
| + // the |src| color space. In order to do this xform correctly, we will need |
| + // to unpremultiply in |src| color space, and then premultiply again in the |
| + // |dst| color space. The Skia API for this conversion (non-linear |
|
msarett1
2017/03/31 19:05:28
I'll see if I can make this public.
Regardless, t
ccameron
2017/03/31 19:46:08
Doing (2) may be possible ... I'm looking to see a
msarett1
2017/03/31 19:59:10
I looked at (2) first, then got scared and backed
scroggo_chromium
2017/04/04 20:52:45
FWIW, kUnpremul in ImageDecoder is already support
msarett1
2017/04/04 23:02:36
Thanks for the unpremul tip, not sure how I missed
|
| + // premultiplies and unpremultiplies) is not public. In the use case where |
| + // we want linear blending (which means linear premultiplies), this works |
| + // correctly as is. Of course, it will assume that the premultiply |
| + // performed by the image decoder was linear (which it was not). |
| + bool xformed = src.readPixels(dst); |
| + DCHECK(xformed); |
|
ccameron
2017/03/31 19:46:08
This DCHECK fires for the test image attached at
h
f(malita)
2017/03/31 19:52:07
Nit: return xformed?
msarett1
2017/03/31 19:59:10
SkPixmap::readPixels() has some restrictions on tr
msarett1
2017/03/31 21:47:30
I still like the DCHECK, but yeah I think so.
|
| + } |
| + |
| + return true; |
| } |
| bool DecodingImageGenerator::onQueryYUV8(SkYUVSizeInfo* sizeInfo, |