aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-06-08 09:37:01 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-08 19:07:54 +0000
commitdc792701012a99d3b7499952df1e55031fa4b795 (patch)
tree06b40f93c7c3274d792d2790b9f319b54e47413c
parent81c83a7db4e524b19d33bf7c8a9b537b9d606c93 (diff)
Draw time color xform API for Android
Will do a lazy color xform to the dst color space at GPU upload time. I've included the capability to control the gen id of the output image. This will allow us to reuse images in the Ganesh cache. This should only be temporary. When Android is able to cache the actual SkImage object, we won't need to expose this anymore. Bug: b/62347704 Change-Id: I93b950ef680f6bbdd7eb6a2ec6f50195dbb78311 Reviewed-on: https://skia-review.googlesource.com/16440 Reviewed-by: Mike Reed <reed@google.com> Reviewed-by: Yuqian Li <liyuqian@google.com> Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Matt Sarett <msarett@google.com>
-rw-r--r--src/core/SkColorSpaceXformImageGenerator.cpp13
-rw-r--r--src/core/SkColorSpaceXformImageGenerator.h7
-rw-r--r--src/core/SkImagePriv.h13
-rw-r--r--src/image/SkImage_Raster.cpp23
-rw-r--r--tests/ImageGeneratorTest.cpp37
5 files changed, 86 insertions, 7 deletions
diff --git a/src/core/SkColorSpaceXformImageGenerator.cpp b/src/core/SkColorSpaceXformImageGenerator.cpp
index f5777cccc4..5d97a024bc 100644
--- a/src/core/SkColorSpaceXformImageGenerator.cpp
+++ b/src/core/SkColorSpaceXformImageGenerator.cpp
@@ -9,6 +9,11 @@
std::unique_ptr<SkImageGenerator> SkColorSpaceXformImageGenerator::Make(
const SkBitmap& src, sk_sp<SkColorSpace> dst, SkCopyPixelsMode mode) {
+ return SkColorSpaceXformImageGenerator::Make(src, dst, mode, kNeedNewImageUniqueID);
+}
+
+std::unique_ptr<SkImageGenerator> SkColorSpaceXformImageGenerator::Make(
+ const SkBitmap& src, sk_sp<SkColorSpace> dst, SkCopyPixelsMode mode, uint32_t id) {
if (!dst) {
return nullptr;
}
@@ -26,14 +31,14 @@ std::unique_ptr<SkImageGenerator> SkColorSpaceXformImageGenerator::Make(
srcPtr = &copy;
}
-
return std::unique_ptr<SkImageGenerator>(
- new SkColorSpaceXformImageGenerator(*srcPtr, std::move(dst)));
+ new SkColorSpaceXformImageGenerator(*srcPtr, std::move(dst), id));
}
SkColorSpaceXformImageGenerator::SkColorSpaceXformImageGenerator(const SkBitmap& src,
- sk_sp<SkColorSpace> dst)
- : INHERITED(src.info().makeColorSpace(dst), kNeedNewImageUniqueID)
+ sk_sp<SkColorSpace> dst,
+ uint32_t id)
+ : INHERITED(src.info().makeColorSpace(dst), id)
, fSrc(src)
, fDst(std::move(dst))
{}
diff --git a/src/core/SkColorSpaceXformImageGenerator.h b/src/core/SkColorSpaceXformImageGenerator.h
index 29bf85bff9..953a1db925 100644
--- a/src/core/SkColorSpaceXformImageGenerator.h
+++ b/src/core/SkColorSpaceXformImageGenerator.h
@@ -30,10 +30,11 @@ private:
SkBitmap fSrc;
sk_sp<SkColorSpace> fDst;
- SkColorSpaceXformImageGenerator(const SkBitmap& src, sk_sp<SkColorSpace> dst);
-
- friend class SkImageGenerator;
+ static std::unique_ptr<SkImageGenerator> Make(
+ const SkBitmap& src, sk_sp<SkColorSpace> dst, SkCopyPixelsMode, uint32_t id);
+ SkColorSpaceXformImageGenerator(const SkBitmap& src, sk_sp<SkColorSpace> dst, uint32_t id);
+ friend sk_sp<SkImage> SkMakeImageInColorSpace(const SkBitmap&, sk_sp<SkColorSpace>, uint32_t);
typedef SkImageGenerator INHERITED;
};
diff --git a/src/core/SkImagePriv.h b/src/core/SkImagePriv.h
index 2e800195d7..d4785c69dd 100644
--- a/src/core/SkImagePriv.h
+++ b/src/core/SkImagePriv.h
@@ -45,6 +45,19 @@ sk_sp<SkShader> SkMakeBitmapShader(const SkBitmap& src, SkShader::TileMode, SkSh
*/
extern sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap&, SkCopyPixelsMode);
+/**
+ * Similar to SkMakeImageFromRasterBitmap, this wraps a |src| bitmap in an image.
+ * This always operates in kNever_SkCopyPixelsMode.
+ *
+ * It also promises to transform the bitmap into the |dst| color space before it
+ * is drawn. The transform will happen lazily.
+ *
+ * If |id| is non-zero, the output image will use that as its unique id. Otherwise,
+ * it will generate a new id.
+ */
+extern sk_sp<SkImage> SkMakeImageInColorSpace(const SkBitmap& src, sk_sp<SkColorSpace> dst,
+ uint32_t id);
+
// Given an image created from SkNewImageFromBitmap, return its pixelref. This
// may be called to see if the surface and the image share the same pixelref,
// in which case the surface may need to perform a copy-on-write.
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 5b55c44685..ce0957901b 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -10,6 +10,7 @@
#include "SkBitmapProcShader.h"
#include "SkCanvas.h"
#include "SkColorSpaceXform_Base.h"
+#include "SkColorSpaceXformImageGenerator.h"
#include "SkColorSpaceXformPriv.h"
#include "SkColorTable.h"
#include "SkData.h"
@@ -321,6 +322,28 @@ sk_sp<SkImage> SkMakeImageFromRasterBitmap(const SkBitmap& bm, SkCopyPixelsMode
return SkMakeImageFromRasterBitmapPriv(bm, cpm);
}
+sk_sp<SkImage> SkMakeImageInColorSpace(const SkBitmap& bm, sk_sp<SkColorSpace> dstCS, uint32_t id) {
+ if (!SkImageInfoIsValidAllowNumericalCS(bm.info()) || !bm.getPixels() ||
+ bm.rowBytes() < bm.info().minRowBytes() || !dstCS) {
+ return nullptr;
+ }
+
+ sk_sp<SkColorSpace> srcCS = bm.info().refColorSpace();
+ if (!srcCS) {
+ // Treat nullptr as sRGB.
+ srcCS = SkColorSpace::MakeSRGB();
+ }
+
+ // For the Android use case, this is very likely to be true.
+ if (SkColorSpace::Equals(srcCS.get(), dstCS.get())) {
+ SkASSERT(0 == id || bm.getGenerationID() == id);
+ return SkMakeImageFromRasterBitmapPriv(bm, kNever_SkCopyPixelsMode);
+ }
+
+ return SkImage::MakeFromGenerator(SkColorSpaceXformImageGenerator::Make(
+ bm, dstCS, kNever_SkCopyPixelsMode, id));
+}
+
const SkPixelRef* SkBitmapImageGetPixelRef(const SkImage* image) {
return ((const SkImage_Raster*)image)->getPixelRef();
}
diff --git a/tests/ImageGeneratorTest.cpp b/tests/ImageGeneratorTest.cpp
index 3d82534717..bc9dca4b18 100644
--- a/tests/ImageGeneratorTest.cpp
+++ b/tests/ImageGeneratorTest.cpp
@@ -109,3 +109,40 @@ DEF_TEST(PictureImageGenerator, reporter) {
REPORTER_ASSERT(reporter, success == rec.fExpectSuccess);
}
}
+
+#include "SkImagePriv.h"
+
+DEF_TEST(ColorXformGenerator, r) {
+ SkBitmap a, b, c, d;
+ SkImageInfo info = SkImageInfo::MakeS32(1, 1, kPremul_SkAlphaType);
+ a.allocPixels(info);
+ b.allocPixels(info.makeColorSpace(nullptr));
+ c.allocPixels(info.makeColorSpace(SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kRec2020_Gamut)));
+ d.allocPixels(info.makeColorSpace(SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kAdobeRGB_Gamut)));
+ a.eraseColor(0);
+ b.eraseColor(1);
+ c.eraseColor(2);
+ d.eraseColor(3);
+
+ sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
+ sk_sp<SkImage> ia = SkMakeImageInColorSpace(a, srgb, 0);
+ sk_sp<SkImage> ib = SkMakeImageInColorSpace(b, srgb, b.getGenerationID());
+ sk_sp<SkImage> ic = SkMakeImageInColorSpace(c, srgb, c.getGenerationID());
+ sk_sp<SkImage> id = SkMakeImageInColorSpace(d, srgb, 0);
+
+ // Equal because sRGB->sRGB is a no-op.
+ REPORTER_ASSERT(r, ia->uniqueID() == a.getGenerationID());
+
+ // Equal because nullptr->sRGB is a no-op (nullptr is treated as sRGB), and because
+ // we pass the explicit id that we want. In the no-op case, the implementation
+ // actually asserts that if we pass an id, it must match the id on the bitmap.
+ REPORTER_ASSERT(r, ib->uniqueID() == b.getGenerationID());
+
+ // Equal because we pass in an explicit id.
+ REPORTER_ASSERT(r, ic->uniqueID() == c.getGenerationID());
+
+ // Not equal because sRGB->Adobe is not a no-op and we do not pass an explicit id.
+ REPORTER_ASSERT(r, id->uniqueID() != d.getGenerationID());
+}