1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkPM4fPriv.h" 9 #include "SkRasterPipeline.h" 10 #include "SkReadBuffer.h" 11 #include "SkString.h" 12 #include "SkToSRGBColorFilter.h" 13 #include "SkWriteBuffer.h" 14 15 #if SK_SUPPORT_GPU 16 #include "effects/GrNonlinearColorSpaceXformEffect.h" 17 #endif 18 19 void SkToSRGBColorFilter::onAppendStages(SkRasterPipeline* p, 20 SkColorSpace* /*dst color space*/, 21 SkArenaAlloc* alloc, 22 bool shaderIsOpaque) const { 23 // Step 1: Linearize by undoing the src transfer function. 24 // Linear and sRGB will return true to isNumericalTransferFn(), so we check them first. 25 SkColorSpaceTransferFn srcFn; 26 if (fSrcColorSpace->gammaIsLinear()) { 27 // Nothing to do. 28 } else if (fSrcColorSpace->gammaCloseToSRGB()) { 29 p->append(SkRasterPipeline::from_srgb); 30 } else if (fSrcColorSpace->isNumericalTransferFn(&srcFn)) { 31 auto copy = alloc->make<SkColorSpaceTransferFn>(srcFn); 32 p->append(SkRasterPipeline::parametric_r, copy); 33 p->append(SkRasterPipeline::parametric_g, copy); 34 p->append(SkRasterPipeline::parametric_b, copy); 35 } else { 36 SkDEBUGFAIL("Looks like we got a table transfer function here, quite unexpectedly."); 37 // TODO: If we really need to handle this, we can, but I don't think Ganesh does. 38 } 39 40 // Step 2: Transform to sRGB gamut, without clamping. 41 // TODO: because... 42 float* gamut_transform = alloc->makeArrayDefault<float>(12); 43 (void)append_gamut_transform_noclamp(p, 44 gamut_transform, 45 fSrcColorSpace.get(), 46 SkColorSpace::MakeSRGB().get()); 47 48 // Step 3: Back to sRGB encoding. 49 p->append(SkRasterPipeline::to_srgb); 50 } 51 52 sk_sp<SkColorFilter> SkToSRGBColorFilter::Make(sk_sp<SkColorSpace> srcColorSpace) { 53 if (!srcColorSpace || srcColorSpace->isSRGB()) { 54 return nullptr; 55 } else { 56 return sk_sp<SkColorFilter>(new SkToSRGBColorFilter(std::move(srcColorSpace))); 57 } 58 } 59 60 SkToSRGBColorFilter::SkToSRGBColorFilter(sk_sp<SkColorSpace> srcColorSpace) 61 : fSrcColorSpace(std::move(srcColorSpace)) { 62 SkASSERT(fSrcColorSpace); 63 } 64 65 sk_sp<SkFlattenable> SkToSRGBColorFilter::CreateProc(SkReadBuffer& buffer) { 66 auto data = buffer.readByteArrayAsData(); 67 if (data) { 68 return Make(SkColorSpace::Deserialize(data->data(), data->size())); 69 } 70 return nullptr; 71 } 72 73 void SkToSRGBColorFilter::flatten(SkWriteBuffer& buffer) const { 74 buffer.writeDataAsByteArray(fSrcColorSpace->serialize().get()); 75 } 76 77 #ifndef SK_IGNORE_TO_STRING 78 void SkToSRGBColorFilter::toString(SkString* str) const { 79 // TODO 80 str->append("SkToSRGBColorFilter "); 81 } 82 #endif 83 84 #if SK_SUPPORT_GPU 85 std::unique_ptr<GrFragmentProcessor> SkToSRGBColorFilter::asFragmentProcessor( 86 GrContext*, const GrColorSpaceInfo&) const { 87 return GrNonlinearColorSpaceXformEffect::Make(fSrcColorSpace.get(), 88 SkColorSpace::MakeSRGB().get()); 89 } 90 #endif 91