Reviewers: haraken, jbroman
CL:
https://codereview.chromium.org/2039983002/Message:
PTAL
Description:
Change code path for structured cloning ImageBitmap
This is how it works currently:
When an ImageBitmap is un-premultiplied, we read bitmap's pixel data in
premultiplied format. When de-serialize happens, we call
ImageBitmap::create(ImageData*) and in that create() function, we create
an SkImage that is in premultiplied format because the input data is
already premultiplied. This is causing the problem because the SkImage
should be in un-premultiplied format.
We change the implementation like this:
When we serialize the ImageBitmap into uint8_t*, we always read the pixel
data in un-premultiplied format, also we store the information whether
the bitmap is premultiplied or not. When de-serialize happens, we call
the ImageBitmap::create(ImageData*) function. If the bitmap is
premultiplied/un-premultiplied, we create a new ImageBitmap that is
premultiplied/un-premultiplied.
Notice that after this change, the layout tests
fast/canvas/webgl/texImage-imageBitmap-structured-clone.html
passes.
BUG=615172
Base URL:
https://chromium.googlesource.com/chromium/src.git@masterAffected files (+32, -27 lines):
M third_party/WebKit/LayoutTests/TestExpectations
M third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageBitmap-structured-clone.html
M third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
M third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
M third_party/WebKit/Source/core/frame/ImageBitmap.h
M third_party/WebKit/Source/core/frame/ImageBitmap.cpp
Index: third_party/WebKit/LayoutTests/TestExpectations
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 50d3866ae78a783055bdad6325058cfdbee2f6fa..5cfae12e01b88fc17a8fc687dfa66cc0e5564af1 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -59,10 +59,6 @@
crbug.com/593514 virtual/gpu/fast/canvas/OffscreenCanvas-2d-gradients-in-worker.
crbug.com/593514 virtual/gpu/fast/canvas/OffscreenCanvas-2d-drawImage-in-worker.html [ Failure ]
crbug.com/593514 virtual/gpu/fast/canvas/OffscreenCanvas-2d-drawImage.html [ Failure ]
-
crbug.com/615172 fast/canvas/webgl/texImage-imageBitmap-structured-clone.html [ Failure ]
-
crbug.com/615172 virtual/display_list_2d_canvas/fast/canvas/webgl/texImage-imageBitmap-structured-clone.html [ Failure ]
-
crbug.com/615172 virtual/gpu/fast/canvas/webgl/texImage-imageBitmap-structured-clone.html [ Failure ]
-
crbug.com/417782 [ Linux Win ] virtual/rootlayerscrolls/fast/scrolling/fractional-scroll-offset-fixed-position-non-composited.html [ Failure ]
crbug.com/492664 [ Linux ] imported/csswg-test/css-writing-modes-3/box-offsets-rel-pos-vlr-005.xht [ Failure ]
crbug.com/492664 [ Linux ] imported/csswg-test/css-writing-modes-3/box-offsets-rel-pos-vrl-004.xht [ Failure ]
Index: third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageBitmap-structured-clone.html
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageBitmap-structured-clone.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageBitmap-structured-clone.html
index 38c798b0cc81bed1e2bb836199412ae9b18788be..3b77b9da84ab66f631a1fef3225a7b3f08509f83 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageBitmap-structured-clone.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-ImageBitmap-structured-clone.html
@@ -38,14 +38,14 @@ function checkImageBitmap1() {
// multiplying and dividing by alpha during the round trip, but
// they should be close.
// The alpha channel should be exactly the same.
- compareImageData(newImage.data, image1.data);
+ compareImageData(newImage.data, imageData1);
}
function checkImageBitmap2() {
shouldBe("bitmapWidth", "imageWidth2");
shouldBe("bitmapHeight", "imageHeight2");
- compareImageData(newImage.data, image2.data);
+ compareImageData(newImage.data, imageData2);
}
function postToWorker(message, transferable) {
@@ -59,7 +59,7 @@ function postToWorker(message, transferable) {
});
}
-function getNewImageDataFromWorkerReply(newImageBitmap)
+function getNewImageDataFromImageBitmap(newImageBitmap)
{
bitmapWidth = newImageBitmap.width;
bitmapHeight = newImageBitmap.height;
@@ -77,6 +77,8 @@ var bitmapHeight;
var imageBitmap1;
var imageBitmap2;
var newImage;
+var imageData1;
+var imageData2;
var image1 = new ImageData(new Uint8ClampedArray(
[255, 0, 0, 255,
0, 255, 0, 255,
@@ -91,6 +93,11 @@ var context = document.getElementById("canvas").getContext("2d");
var p1 = createImageBitmap(image1).then(function(image) {imageBitmap1 = image});
var p2 = createImageBitmap(image2, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(image) {imageBitmap2 = image});
Promise.all([p1, p2]).then(function() {
+ getNewImageDataFromImageBitmap(imageBitmap1);
+ imageData1 = newImage.data;
+ getNewImageDataFromImageBitmap(imageBitmap2);
+ imageData2 = newImage.data;
+
bitmapWidth = imageBitmap1.width;
bitmapHeight = imageBitmap1.height;
shouldBe("bitmapWidth", "imageWidth1");
@@ -105,7 +112,7 @@ Promise.all([p1, p2]).then(function() {
shouldBe("bitmapHeight", "imageHeight1");
return replyPromise.then(reply => {
- getNewImageDataFromWorkerReply(reply);
+ getNewImageDataFromImageBitmap(reply);
checkImageBitmap1();
});
}).then(function() {
@@ -118,7 +125,7 @@ Promise.all([p1, p2]).then(function() {
shouldBe("bitmapHeight", "0");
return replyPromise.then(reply => {
- getNewImageDataFromWorkerReply(reply);
+ getNewImageDataFromImageBitmap(reply);
checkImageBitmap1();
});
}).then(function() {
@@ -131,7 +138,7 @@ Promise.all([p1, p2]).then(function() {
shouldBe("bitmapHeight", "imageHeight2");
return replyPromise.then(reply => {
- getNewImageDataFromWorkerReply(reply);
+ getNewImageDataFromImageBitmap(reply);
checkImageBitmap2();
});
}).then(finishJSTest, shouldNotBeCalled);
Index: third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
index f143d25720079fb6e9fbe46b92f409591d3cfd6e..0a76804c5c16a8c9852d0125fe012c9b7ab0f983 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
@@ -312,10 +312,11 @@ void SerializedScriptValueWriter::writeImageData(uint32_t width, uint32_t height
doWriteImageData(width, height, pixelData, pixelDataLength);
}
-void SerializedScriptValueWriter::writeImageBitmap(uint32_t width, uint32_t height, uint32_t isOriginClean, const uint8_t* pixelData, uint32_t pixelDataLength)
+void SerializedScriptValueWriter::writeImageBitmap(uint32_t width, uint32_t height, uint32_t isOriginClean, uint32_t isPremultiplied, const uint8_t* pixelData, uint32_t pixelDataLength)
{
append(ImageBitmapTag);
append(isOriginClean);
+ append(isPremultiplied);
doWriteImageData(width, height, pixelData, pixelDataLength);
}
@@ -1145,8 +1146,8 @@ ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyImageBitmap
m_writer.writeTransferredImageBitmap(index);
} else {
greyObject(object);
- std::unique_ptr<uint8_t[]> pixelData = imageBitmap->copyBitmapData(PremultiplyAlpha);
- m_writer.writeImageBitmap(imageBitmap->width(), imageBitmap->height(), static_cast<uint32_t>(imageBitmap->originClean()), pixelData.get(), imageBitmap->width() * imageBitmap->height() * 4);
+ std::unique_ptr<uint8_t[]> pixelData = imageBitmap->copyBitmapData(DontPremultiplyAlpha);
+ m_writer.writeImageBitmap(imageBitmap->width(), imageBitmap->height(), static_cast<uint32_t>(imageBitmap->originClean()), static_cast<uint32_t>(imageBitmap->isPremultiplied()), pixelData.get(), imageBitmap->width() * imageBitmap->height() * 4);
}
return nullptr;
}
@@ -1785,12 +1786,16 @@ bool SerializedScriptValueReader::readImageBitmap(v8::Local<v8::Value>* value)
uint32_t isOriginClean;
if (!doReadUint32(&isOriginClean))
return false;
+ uint32_t isPremultiplied;
+ if (!doReadUint32(&isPremultiplied))
+ return false;
ImageData* imageData = doReadImageData();
if (!imageData)
return false;
ImageBitmapOptions options;
- options.setPremultiplyAlpha("none");
- ImageBitmap* imageBitmap = ImageBitmap::create(imageData, IntRect(0, 0, imageData->width(), imageData->height()), options, true, isOriginClean);
+ if (!isPremultiplied)
+ options.setPremultiplyAlpha("none");
+ ImageBitmap* imageBitmap = ImageBitmap::create(imageData, IntRect(0, 0, imageData->width(), imageData->height()), options, isOriginClean);
if (!imageBitmap)
return false;
*value = toV8(imageBitmap, m_scriptState->context()->Global(), isolate());
Index: third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
index 15b23b9623ba313238597fb1125296fbac38168d..5efba487dbbd08aae70f5d783e6e43ee6e7036df 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.h
@@ -143,7 +143,7 @@ protected:
void writeArrayBufferView(const DOMArrayBufferView&);
void doWriteImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength);
void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelData, uint32_t pixelDataLength);
- void writeImageBitmap(uint32_t width, uint32_t height, uint32_t isOriginClean, const uint8_t* pixelData, uint32_t pixelDataLength);
+ void writeImageBitmap(uint32_t width, uint32_t height, uint32_t isOriginClean, uint32_t isPremultiplied, const uint8_t* pixelData, uint32_t pixelDataLength);
void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags);
void writeTransferredMessagePort(uint32_t index);
void writeTransferredArrayBuffer(uint32_t index);
Index: third_party/WebKit/Source/core/frame/ImageBitmap.cpp
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
index 7c0de1e9e10b593f496e058d70579b981bd201f8..30949c9a0f1006ae8070ca25a8b0c95b284e1563 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -258,8 +258,8 @@ ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, con
m_image->setPremultiplied(premultiplyAlpha);
}
-// The last two parameters are used for structure-cloning.
-ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBitmapOptions& options, const bool& isImageDataPremultiplied, const bool& isImageDataOriginClean)
+// The last parameter are used for structure-cloning.
+ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBitmapOptions& options, const bool& isImageDataOriginClean)
{
bool flipY;
bool premultiplyAlpha;
@@ -273,11 +273,7 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
int dstHeight = cropRect.height();
// TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a kRGBA color type.
// For now, we swap R and B channel and uses kBGRA color type.
- SkImageInfo info;
- if (!isImageDataPremultiplied)
- info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
- else
- info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
+ SkImageInfo info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType);
int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width();
int dstPixelBytesPerRow = info.bytesPerPixel() * cropRect.width();
if (cropRect == IntRect(IntPoint(), data->size())) {
@@ -340,6 +336,7 @@ ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBi
m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlpha));
else
m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown));
+ m_image->setOriginClean(isImageDataOriginClean);
}
ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const ImageBitmapOptions& options)
@@ -405,10 +402,10 @@ ImageBitmap* ImageBitmap::create(HTMLCanvasElement* canvas, const IntRect& cropR
return new ImageBitmap(canvas, normalizedCropRect, options);
}
-ImageBitmap* ImageBitmap::create(ImageData* data, const IntRect& cropRect, const ImageBitmapOptions& options, const bool& isImageDataPremultiplied, const bool& isImageDataOriginClean)
+ImageBitmap* ImageBitmap::create(ImageData* data, const IntRect& cropRect, const ImageBitmapOptions& options, const bool& isImageDataOriginClean)
{
IntRect normalizedCropRect = normalizeRect(cropRect);
- return new ImageBitmap(data, normalizedCropRect, options, isImageDataPremultiplied, isImageDataOriginClean);
+ return new ImageBitmap(data, normalizedCropRect, options, isImageDataOriginClean);
}
ImageBitmap* ImageBitmap::create(ImageBitmap* bitmap, const IntRect& cropRect, const ImageBitmapOptions& options)
Index: third_party/WebKit/Source/core/frame/ImageBitmap.h
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.h b/third_party/WebKit/Source/core/frame/ImageBitmap.h
index 1e6e3db9db56924decb8f44f2124148eb065a267..3b7f1a5b33149c7b4ecc88406ed19b91cff8f493 100644
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.h
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.h
@@ -37,7 +37,7 @@ public:
static ImageBitmap* create(HTMLImageElement*, const IntRect&, Document*, const ImageBitmapOptions& = ImageBitmapOptions());
static ImageBitmap* create(HTMLVideoElement*, const IntRect&, Document*, const ImageBitmapOptions& = ImageBitmapOptions());
static ImageBitmap* create(HTMLCanvasElement*, const IntRect&, const ImageBitmapOptions& = ImageBitmapOptions());
- static ImageBitmap* create(ImageData*, const IntRect&, const ImageBitmapOptions& = ImageBitmapOptions(), const bool& isImageDataPremultiplied = false, const bool& isImageDataOriginClean = true);
+ static ImageBitmap* create(ImageData*, const IntRect&, const ImageBitmapOptions& = ImageBitmapOptions(), const bool& isImageDataOriginClean = true);
static ImageBitmap* create(ImageBitmap*, const IntRect&, const ImageBitmapOptions& = ImageBitmapOptions());
static ImageBitmap* create(PassRefPtr<StaticBitmapImage>);
static ImageBitmap* create(PassRefPtr<StaticBitmapImage>, const IntRect&, const ImageBitmapOptions& = ImageBitmapOptions());
@@ -82,7 +82,7 @@ private:
ImageBitmap(HTMLImageElement*, const IntRect&, Document*, const ImageBitmapOptions&);
ImageBitmap(HTMLVideoElement*, const IntRect&, Document*, const ImageBitmapOptions&);
ImageBitmap(HTMLCanvasElement*, const IntRect&, const ImageBitmapOptions&);
- ImageBitmap(ImageData*, const IntRect&, const ImageBitmapOptions&, const bool&, const bool&);
+ ImageBitmap(ImageData*, const IntRect&, const ImageBitmapOptions&, const bool&);
ImageBitmap(ImageBitmap*, const IntRect&, const ImageBitmapOptions&);
ImageBitmap(PassRefPtr<StaticBitmapImage>);
ImageBitmap(PassRefPtr<StaticBitmapImage>, const IntRect&, const ImageBitmapOptions&);