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