Viewer's nonlinear blend mode uses SkColorSpaceXformCanvas
Also avoid asserting when untagged images are being transformed.
BUG=skia:
Change-Id: If712f39b5f588b2bc3dc318a5b782badb7662ccf
Reviewed-on: https://skia-review.googlesource.com/9695
Reviewed-by: Matt Sarett <msarett@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 2513e84..2a83eaf 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -318,7 +318,7 @@
return nullptr;
}
- if (SkColorSpace::Equals(this->colorSpace(), target.get())) {
+ if (!this->colorSpace() || SkColorSpace::Equals(this->colorSpace(), target.get())) {
return sk_ref_sp(const_cast<SkImage_Base*>(this));
}
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 0cc6486..e190acd 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -17,6 +17,7 @@
#include "SkATrace.h"
#include "SkCanvas.h"
#include "SkColorSpace_Base.h"
+#include "SkColorSpaceXformCanvas.h"
#include "SkCommandLineFlags.h"
#include "SkCommonFlagsPathRenderer.h"
#include "SkDashPathEffect.h"
@@ -714,10 +715,11 @@
fColorMode = colorMode;
// When we're in color managed mode, we tag our window surface as sRGB. If we've switched into
- // or out of legacy mode, we need to update our window configuration.
+ // or out of legacy/nonlinear mode, we need to update our window configuration.
DisplayParams params = fWindow->getRequestedDisplayParams();
bool wasInLegacy = !SkToBool(params.fColorSpace);
- bool wantLegacy = (ColorMode::kLegacy == fColorMode);
+ bool wantLegacy = (ColorMode::kLegacy == fColorMode) ||
+ (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode);
if (wasInLegacy != wantLegacy) {
params.fColorSpace = wantLegacy ? nullptr : SkColorSpace::MakeSRGB();
fWindow->setRequestedDisplayParams(params);
@@ -740,32 +742,42 @@
SkCanvas* slideCanvas = canvas;
fLastImage.reset();
- // If we're in F16 or nonlinear blending mode, or the gamut isn't sRGB, or we're zooming,
+ // If we're in any of the color managed modes, construct the color space we're going to use
+ sk_sp<SkColorSpace> cs = nullptr;
+ if (ColorMode::kLegacy != fColorMode) {
+ auto transferFn = (ColorMode::kColorManagedLinearF16 == fColorMode)
+ ? SkColorSpace::kLinear_RenderTargetGamma : SkColorSpace::kSRGB_RenderTargetGamma;
+ SkMatrix44 toXYZ;
+ SkAssertResult(fColorSpacePrimaries.toXYZD50(&toXYZ));
+ cs = SkColorSpace::MakeRGB(transferFn, toXYZ);
+ }
+
+ // If we're in F16, or we're zooming, or we're in color correct 8888 and the gamut isn't sRGB,
// we need to render offscreen
- bool colorManaged = (ColorMode::kLegacy != fColorMode);
sk_sp<SkSurface> offscreenSurface = nullptr;
if (ColorMode::kColorManagedLinearF16 == fColorMode ||
- ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode ||
fShowZoomWindow ||
- (colorManaged && !primaries_equal(fColorSpacePrimaries, gSrgbPrimaries))) {
- sk_sp<SkColorSpace> cs = nullptr;
- if (colorManaged) {
- auto transferFn = (ColorMode::kColorManagedLinearF16 == fColorMode)
- ? SkColorSpace::kLinear_RenderTargetGamma : SkColorSpace::kSRGB_RenderTargetGamma;
- SkMatrix44 toXYZ;
- SkAssertResult(fColorSpacePrimaries.toXYZD50(&toXYZ));
- uint32_t flags = (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode)
- ? SkColorSpace::kNonLinearBlending_ColorSpaceFlag : 0;
- cs = SkColorSpace::MakeRGB(transferFn, toXYZ, flags);
- }
+ (ColorMode::kColorManagedSRGB8888 == fColorMode &&
+ !primaries_equal(fColorSpacePrimaries, gSrgbPrimaries))) {
+
SkColorType colorType = (ColorMode::kColorManagedLinearF16 == fColorMode)
? kRGBA_F16_SkColorType : kN32_SkColorType;
+ // In nonlinear blending mode, we actually use a legacy off-screen canvas, and wrap it
+ // with a special canvas (below) that has the color space attached
+ sk_sp<SkColorSpace> offscreenColorSpace =
+ (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) ? nullptr : cs;
SkImageInfo info = SkImageInfo::Make(fWindow->width(), fWindow->height(), colorType,
- kPremul_SkAlphaType, std::move(cs));
+ kPremul_SkAlphaType, std::move(offscreenColorSpace));
offscreenSurface = canvas->makeSurface(info);
slideCanvas = offscreenSurface->getCanvas();
}
+ std::unique_ptr<SkCanvas> xformCanvas = nullptr;
+ if (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) {
+ xformCanvas = SkCreateColorSpaceXformCanvas(slideCanvas, cs);
+ slideCanvas = xformCanvas.get();
+ }
+
int count = slideCanvas->save();
slideCanvas->clear(SK_ColorWHITE);
slideCanvas->concat(fDefaultMatrix);
@@ -786,9 +798,9 @@
fLastImage = offscreenSurface->makeImageSnapshot();
// Tag the image with the sRGB gamut, so no further color space conversion happens
- sk_sp<SkColorSpace> cs = (ColorMode::kColorManagedLinearF16 == fColorMode)
+ sk_sp<SkColorSpace> srgb = (ColorMode::kColorManagedLinearF16 == fColorMode)
? SkColorSpace::MakeSRGBLinear() : SkColorSpace::MakeSRGB();
- auto retaggedImage = SkImageMakeRasterCopyAndAssignColorSpace(fLastImage.get(), cs.get());
+ auto retaggedImage = SkImageMakeRasterCopyAndAssignColorSpace(fLastImage.get(), srgb.get());
SkPaint paint;
paint.setBlendMode(SkBlendMode::kSrc);
canvas->drawImage(retaggedImage, 0, 0, &paint);