SkToSRGBColorFilter.cpp revision 4cbb6e6d551e8bea2c040b1aa9dce253cffb9af0
110b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman/*
210b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman * Copyright 2017 Google Inc.
310b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman *
410b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman * Use of this source code is governed by a BSD-style license that can be
510b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman * found in the LICENSE file.
610b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman */
710b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman
810b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman#include "SkColorSpace_Base.h"
992db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein#include "SkPM4fPriv.h"
1010b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman#include "SkRasterPipeline.h"
11205c69d4895ac115c2e456707169321b257dc6aeMike Reed#include "SkReadBuffer.h"
1210b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman#include "SkString.h"
1392db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein#include "SkToSRGBColorFilter.h"
14205c69d4895ac115c2e456707169321b257dc6aeMike Reed#include "SkWriteBuffer.h"
1510b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman
1610b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman#if SK_SUPPORT_GPU
1792db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    #include "effects/GrNonlinearColorSpaceXformEffect.h"
1810b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman#endif
1910b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman
2010b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osmanvoid SkToSRGBColorFilter::onAppendStages(SkRasterPipeline* p,
2192db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein                                         SkColorSpace* /*dst color space*/,
2292db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein                                         SkArenaAlloc* alloc,
2310b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman                                         bool shaderIsOpaque) const {
2492db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    // Step 1: Linearize by undoing the src transfer function.
2592db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    // Linear and sRGB will return true to isNumericalTransferFn(), so we check them first.
2692db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    SkColorSpaceTransferFn srcFn;
2792db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    if (fSrcColorSpace->gammaIsLinear()) {
2892db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein        // Nothing to do.
2992db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    } else if (fSrcColorSpace->gammaCloseToSRGB()) {
3092db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein        p->append_from_srgb(shaderIsOpaque ? kOpaque_SkAlphaType
3192db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein                                           : kPremul_SkAlphaType);
3292db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    } else if (fSrcColorSpace->isNumericalTransferFn(&srcFn)) {
3392db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein        p->append(SkRasterPipeline::parametric_r, &srcFn);
3492db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein        p->append(SkRasterPipeline::parametric_g, &srcFn);
3592db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein        p->append(SkRasterPipeline::parametric_b, &srcFn);
3692db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    } else {
3792db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein        SkDEBUGFAIL("Looks like we got a table transfer function here, quite unexpectedly.");
3892db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein        // TODO: If we really need to handle this, we can, but I don't think Ganesh does.
3992db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    }
4092db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein
4192db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    // Step 2: Transform to sRGB gamut, without clamping.
42159db0a6a1001b220b42fcae46ed324e0986b14aMike Klein    float* gamut_transform = alloc->makeArrayDefault<float>(12);
4392db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    (void)append_gamut_transform_noclamp(p,
44159db0a6a1001b220b42fcae46ed324e0986b14aMike Klein                                         gamut_transform,
4592db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein                                         fSrcColorSpace.get(),
4692db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein                                         SkColorSpace::MakeSRGB().get());
4792db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein
48159db0a6a1001b220b42fcae46ed324e0986b14aMike Klein    bool needs_clamp_0, needs_clamp_1;
49159db0a6a1001b220b42fcae46ed324e0986b14aMike Klein    analyze_3x4_matrix(gamut_transform, &needs_clamp_0, &needs_clamp_1);
50159db0a6a1001b220b42fcae46ed324e0986b14aMike Klein    if (needs_clamp_0 || needs_clamp_1) {
51159db0a6a1001b220b42fcae46ed324e0986b14aMike Klein        p->set_clamped(false);
52159db0a6a1001b220b42fcae46ed324e0986b14aMike Klein    }
53159db0a6a1001b220b42fcae46ed324e0986b14aMike Klein
5492db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    // Step 3: Back to sRGB encoding.
5592db5a39d4f810dbef96b2b966e4615f7af0ce51Mike Klein    p->append(SkRasterPipeline::to_srgb);
5610b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman}
5710b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman
5810b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osmansk_sp<SkColorFilter> SkToSRGBColorFilter::Make(sk_sp<SkColorSpace> srcColorSpace) {
59fa78ece52e8e30f522eea77df7ab67edcd17bddcMike Reed    if (srcColorSpace->isSRGB()) {
60fa78ece52e8e30f522eea77df7ab67edcd17bddcMike Reed        return nullptr;
61fa78ece52e8e30f522eea77df7ab67edcd17bddcMike Reed    } else {
62fa78ece52e8e30f522eea77df7ab67edcd17bddcMike Reed        return sk_sp<SkColorFilter>(new SkToSRGBColorFilter(std::move(srcColorSpace)));
63fa78ece52e8e30f522eea77df7ab67edcd17bddcMike Reed    }
6410b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman}
6510b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman
6610b6ad13f996d2f522bc057d17acea58e43a7f0bBrian OsmanSkToSRGBColorFilter::SkToSRGBColorFilter(sk_sp<SkColorSpace> srcColorSpace)
6710b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman        : fSrcColorSpace(std::move(srcColorSpace)) {}
6810b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman
69205c69d4895ac115c2e456707169321b257dc6aeMike Reedsk_sp<SkFlattenable> SkToSRGBColorFilter::CreateProc(SkReadBuffer& buffer) {
70205c69d4895ac115c2e456707169321b257dc6aeMike Reed    auto data = buffer.readByteArrayAsData();
71205c69d4895ac115c2e456707169321b257dc6aeMike Reed    if (data) {
72205c69d4895ac115c2e456707169321b257dc6aeMike Reed        return Make(SkColorSpace::Deserialize(data->data(), data->size()));
73205c69d4895ac115c2e456707169321b257dc6aeMike Reed    }
7410b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman    return nullptr;
7510b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman}
7610b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman
77205c69d4895ac115c2e456707169321b257dc6aeMike Reedvoid SkToSRGBColorFilter::flatten(SkWriteBuffer& buffer) const {
78205c69d4895ac115c2e456707169321b257dc6aeMike Reed    buffer.writeDataAsByteArray(fSrcColorSpace->serialize().get());
7910b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman}
8010b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman
8110b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman#ifndef SK_IGNORE_TO_STRING
8210b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osmanvoid SkToSRGBColorFilter::toString(SkString* str) const {
8310b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman    // TODO
8410b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman    str->append("SkToSRGBColorFilter ");
8510b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman}
8610b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman#endif
8710b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman
8810b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman#if SK_SUPPORT_GPU
894cbb6e6d551e8bea2c040b1aa9dce253cffb9af0Brian Salomonstd::unique_ptr<GrFragmentProcessor> SkToSRGBColorFilter::asFragmentProcessor(
904cbb6e6d551e8bea2c040b1aa9dce253cffb9af0Brian Salomon        GrContext*, const GrColorSpaceInfo&) const {
9110b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman    return GrNonlinearColorSpaceXformEffect::Make(fSrcColorSpace.get(),
9210b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman                                                  SkColorSpace::MakeSRGB().get());
9310b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman}
9410b6ad13f996d2f522bc057d17acea58e43a7f0bBrian Osman#endif
95