Revert "Use colorFilters when rendering to an sRGB bitmap."
This reverts commit b851b197497783f894b72edcaed8f93d035ddea0.
Change-Id: I5bb8fe9bf9f5d411674e289c467b3f569f7bb068
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 02c0e19..9683d06 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -25,6 +25,7 @@
#include <SkCanvasStateUtils.h>
#include <SkColorFilter.h>
+// TODO remove me!
#include <SkColorSpaceXformCanvas.h>
#include <SkDrawable.h>
#include <SkDeque.h>
@@ -47,28 +48,25 @@
return new SkiaCanvas(bitmap);
}
-Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) {
- return new SkiaCanvas(skiaCanvas);
+Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas, XformToSRGB xformToSRGB) {
+ return new SkiaCanvas(skiaCanvas, xformToSRGB);
}
SkiaCanvas::SkiaCanvas() {}
-SkiaCanvas::SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {}
+SkiaCanvas::SkiaCanvas(SkCanvas* canvas, XformToSRGB xformToSRGB)
+ : mCanvas(canvas)
+{
+ LOG_ALWAYS_FATAL_IF(XformToSRGB::kImmediate == xformToSRGB);
+}
SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
mCanvasOwned =
std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
- if (cs.get() == nullptr || cs->isSRGB()) {
- mCanvas = mCanvasOwned.get();
- } else {
- /** The wrapper is needed if we are drawing into a non-sRGB destination, since
- * we need to transform all colors (not just bitmaps via filters) into the
- * destination's colorspace.
- */
- mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), std::move(cs));
- mCanvas = mCanvasWrapper.get();
- }
+ mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(),
+ cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
+ mCanvas = mCanvasWrapper.get();
}
SkiaCanvas::~SkiaCanvas() {}
@@ -77,7 +75,6 @@
if (mCanvas != skiaCanvas) {
mCanvas = skiaCanvas;
mCanvasOwned.reset();
- mCanvasWrapper.reset();
}
mSaveStack.reset(nullptr);
mHighContrastText = false;
@@ -91,15 +88,13 @@
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
std::unique_ptr<SkCanvas> newCanvas =
std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
- std::unique_ptr<SkCanvas> newCanvasWrapper;
- if (cs.get() != nullptr && !cs->isSRGB()) {
- newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), std::move(cs));
- }
+ std::unique_ptr<SkCanvas> newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(),
+ cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
// deletes the previously owned canvas (if any)
mCanvasOwned = std::move(newCanvas);
mCanvasWrapper = std::move(newCanvasWrapper);
- mCanvas = mCanvasWrapper ? mCanvasWrapper.get() : mCanvasOwned.get();
+ mCanvas = mCanvasWrapper.get();
// clean up the old save stack
mSaveStack.reset(nullptr);
@@ -536,27 +531,13 @@
// Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------
-const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
- sk_sp<SkColorFilter> colorSpaceFilter) {
- /* We don't apply the colorSpace filter if this canvas is already wrapped with
- * a SkColorSpaceXformCanvas since it already takes care of converting the
- * contents of the bitmap into the appropriate colorspace. The mCanvasWrapper
- * should only be used if this canvas is backed by a surface/bitmap that is known
- * to have a non-sRGB colorspace.
- */
- if (!mCanvasWrapper && colorSpaceFilter) {
+inline static const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
+ sk_sp<SkColorFilter> colorFilter) {
+ if (colorFilter) {
if (origPaint) {
*tmpPaint = *origPaint;
}
-
- if (tmpPaint->getColorFilter()) {
- tmpPaint->setColorFilter(SkColorFilter::MakeComposeFilter(
- tmpPaint->refColorFilter(), colorSpaceFilter));
- LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
- } else {
- tmpPaint->setColorFilter(colorSpaceFilter);
- }
-
+ tmpPaint->setColorFilter(colorFilter);
return tmpPaint;
} else {
return origPaint;
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 6a01f96..af2c23e 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -37,8 +37,12 @@
* @param canvas SkCanvas to handle calls made to this SkiaCanvas. Must
* not be NULL. This constructor does not take ownership, so the caller
* must guarantee that it remains valid while the SkiaCanvas is valid.
+ * @param xformToSRGB Indicates if bitmaps should be xformed to the sRGB
+ * color space before drawing. This makes sense for software rendering.
+ * For the picture case, it may make more sense to leave bitmaps as is,
+ * and handle the xform when replaying the picture.
*/
- explicit SkiaCanvas(SkCanvas* canvas);
+ explicit SkiaCanvas(SkCanvas* canvas, XformToSRGB xformToSRGB);
virtual ~SkiaCanvas();
@@ -178,9 +182,6 @@
void drawPoints(const float* points, int count, const SkPaint& paint,
SkCanvas::PointMode mode);
- const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
- sk_sp<SkColorFilter> colorSpaceFilter);
-
class Clip;
std::unique_ptr<SkCanvas> mCanvasWrapper; // might own a wrapper on the canvas
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 90d98f2..ac8a081 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -98,6 +98,15 @@
static WARN_UNUSED_RESULT Canvas* create_recording_canvas(int width, int height,
uirenderer::RenderNode* renderNode = nullptr);
+ enum class XformToSRGB {
+ // Transform any Bitmaps to the sRGB color space before drawing.
+ kImmediate,
+
+ // Draw the Bitmap as is. This likely means that we are recording and that the
+ // transform can be handled at playback time.
+ kDefer,
+ };
+
/**
* Create a new Canvas object which delegates to an SkCanvas.
*
@@ -105,10 +114,12 @@
* delegated to this object. This function will call ref() on the
* SkCanvas, and the returned Canvas will unref() it upon
* destruction.
+ * @param xformToSRGB Indicates if bitmaps should be xformed to the sRGB
+ * color space before drawing.
* @return new non-null Canvas Object. The type of DisplayList produced by this canvas is
* determined based on Properties::getRenderPipelineType().
*/
- static Canvas* create_canvas(SkCanvas* skiaCanvas);
+ static Canvas* create_canvas(SkCanvas* skiaCanvas, XformToSRGB xformToSRGB);
/**
* Provides a Skia SkCanvas interface that acts as a proxy to this Canvas.
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 4c1d673..bb41607 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -150,17 +150,8 @@
if (origPaint) {
*tmpPaint = *origPaint;
}
-
- sk_sp<SkColorFilter> filter;
- if (colorFilter && tmpPaint->getColorFilter()) {
- filter = SkColorFilter::MakeComposeFilter(tmpPaint->refColorFilter(), colorFilter);
- LOG_ALWAYS_FATAL_IF(!filter);
- } else {
- filter = colorFilter;
- }
-
tmpPaint->setAntiAlias(false);
- tmpPaint->setColorFilter(filter);
+ tmpPaint->setColorFilter(colorFilter);
return tmpPaint;
} else {
return origPaint;
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index d84b83d..c048dda 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -45,7 +45,8 @@
// record the same text draw into a SkPicture and replay it into a Recording canvas
SkPictureRecorder recorder;
SkCanvas* skCanvas = recorder.beginRecording(200, 200, NULL, 0);
- std::unique_ptr<Canvas> pictCanvas(Canvas::create_canvas(skCanvas));
+ std::unique_ptr<Canvas> pictCanvas(Canvas::create_canvas(skCanvas,
+ Canvas::XformToSRGB::kDefer));
TestUtils::drawUtf8ToCanvas(pictCanvas.get(), text, paint, 25, 25);
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
@@ -64,7 +65,7 @@
TEST(SkiaCanvas, drawShadowLayer) {
auto surface = SkSurface::MakeRasterN32Premul(10, 10);
- SkiaCanvas canvas(surface->getCanvas());
+ SkiaCanvas canvas(surface->getCanvas(), Canvas::XformToSRGB::kDefer);
// clear to white
canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrc);
@@ -107,14 +108,27 @@
// The result should be less than fully red, since we convert to Adobe RGB at draw time.
ASSERT_EQ(0xFF0000DC, *adobeSkBitmap.getAddr32(0, 0));
- // Test picture recording.
+ // Now try in kDefer mode. This is a little strange given that, in practice, all software
+ // canvases are kImmediate.
+ SkCanvas skCanvas(skBitmap);
+ SkiaCanvas deferCanvas(&skCanvas, Canvas::XformToSRGB::kDefer);
+ deferCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
+ // The result should be as before, since we deferred the conversion to sRGB.
+ ASSERT_EQ(0xFF0000DC, *skBitmap.getAddr32(0, 0));
+
+ // Test picture recording. We will kDefer the xform at recording time, but handle it when
+ // we playback to the software canvas.
SkPictureRecorder recorder;
SkCanvas* skPicCanvas = recorder.beginRecording(1, 1, NULL, 0);
- SkiaCanvas picCanvas(skPicCanvas);
+ SkiaCanvas picCanvas(skPicCanvas, Canvas::XformToSRGB::kDefer);
picCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
- // Playback to an software canvas. The result should be fully red.
+ // Playback to a deferred canvas. The result should be as before.
+ deferCanvas.asSkCanvas()->drawPicture(picture);
+ ASSERT_EQ(0xFF0000DC, *skBitmap.getAddr32(0, 0));
+
+ // Playback to an immediate canvas. The result should be fully red.
canvas.asSkCanvas()->drawPicture(picture);
ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
}
@@ -141,7 +155,7 @@
// Create a picture canvas.
SkPictureRecorder recorder;
SkCanvas* skPicCanvas = recorder.beginRecording(1, 1, NULL, 0);
- SkiaCanvas picCanvas(skPicCanvas);
+ SkiaCanvas picCanvas(skPicCanvas, Canvas::XformToSRGB::kDefer);
state = picCanvas.captureCanvasState();
// Verify that we cannot get the CanvasState.