blob: df3dec9dc1ef20c55e7ef0da899b511894dfb6cc [file] [log] [blame]
Brian Osman10b6ad12017-07-25 09:59:24 -04001/*
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
Brian Osman10b6ad12017-07-25 09:59:24 -04008#include "SkColorSpace_Base.h"
Mike Klein92db5a32017-07-25 10:51:41 -04009#include "SkPM4fPriv.h"
Brian Osman10b6ad12017-07-25 09:59:24 -040010#include "SkRasterPipeline.h"
11#include "SkString.h"
Mike Klein92db5a32017-07-25 10:51:41 -040012#include "SkToSRGBColorFilter.h"
Brian Osman10b6ad12017-07-25 09:59:24 -040013
14#if SK_SUPPORT_GPU
Mike Klein92db5a32017-07-25 10:51:41 -040015 #include "effects/GrNonlinearColorSpaceXformEffect.h"
Brian Osman10b6ad12017-07-25 09:59:24 -040016#endif
17
18void SkToSRGBColorFilter::onAppendStages(SkRasterPipeline* p,
Mike Klein92db5a32017-07-25 10:51:41 -040019 SkColorSpace* /*dst color space*/,
20 SkArenaAlloc* alloc,
Brian Osman10b6ad12017-07-25 09:59:24 -040021 bool shaderIsOpaque) const {
Mike Klein92db5a32017-07-25 10:51:41 -040022 if (fSrcColorSpace->isSRGB()) {
23 // That was easy.
24 return;
25 }
26
27 // Step 1: Linearize by undoing the src transfer function.
28 // Linear and sRGB will return true to isNumericalTransferFn(), so we check them first.
29 SkColorSpaceTransferFn srcFn;
30 if (fSrcColorSpace->gammaIsLinear()) {
31 // Nothing to do.
32 } else if (fSrcColorSpace->gammaCloseToSRGB()) {
33 p->append_from_srgb(shaderIsOpaque ? kOpaque_SkAlphaType
34 : kPremul_SkAlphaType);
35 } else if (fSrcColorSpace->isNumericalTransferFn(&srcFn)) {
36 p->append(SkRasterPipeline::parametric_r, &srcFn);
37 p->append(SkRasterPipeline::parametric_g, &srcFn);
38 p->append(SkRasterPipeline::parametric_b, &srcFn);
39 } else {
40 SkDEBUGFAIL("Looks like we got a table transfer function here, quite unexpectedly.");
41 // TODO: If we really need to handle this, we can, but I don't think Ganesh does.
42 }
43
44 // Step 2: Transform to sRGB gamut, without clamping.
45 (void)append_gamut_transform_noclamp(p,
46 alloc->makeArrayDefault<float>(12),
47 fSrcColorSpace.get(),
48 SkColorSpace::MakeSRGB().get());
49
50 // Step 3: Back to sRGB encoding.
51 p->append(SkRasterPipeline::to_srgb);
Brian Osman10b6ad12017-07-25 09:59:24 -040052}
53
54sk_sp<SkColorFilter> SkToSRGBColorFilter::Make(sk_sp<SkColorSpace> srcColorSpace) {
Brian Osmanfa3ed032017-07-25 10:48:19 -040055 if (srcColorSpace->isSRGB()) {
56 return nullptr;
57 } else {
58 return sk_sp<SkColorFilter>(new SkToSRGBColorFilter(std::move(srcColorSpace)));
59 }
Brian Osman10b6ad12017-07-25 09:59:24 -040060}
61
62SkToSRGBColorFilter::SkToSRGBColorFilter(sk_sp<SkColorSpace> srcColorSpace)
63 : fSrcColorSpace(std::move(srcColorSpace)) {}
64
65sk_sp<SkFlattenable> SkToSRGBColorFilter::CreateProc(SkReadBuffer&) {
66 // TODO
67 return nullptr;
68}
69
70void SkToSRGBColorFilter::flatten(SkWriteBuffer&) const {
71 // TODO
72}
73
74#ifndef SK_IGNORE_TO_STRING
75void SkToSRGBColorFilter::toString(SkString* str) const {
76 // TODO
77 str->append("SkToSRGBColorFilter ");
78}
79#endif
80
81#if SK_SUPPORT_GPU
82sk_sp<GrFragmentProcessor> SkToSRGBColorFilter::asFragmentProcessor(GrContext*,
83 SkColorSpace*) const {
84 return GrNonlinearColorSpaceXformEffect::Make(fSrcColorSpace.get(),
85 SkColorSpace::MakeSRGB().get());
86}
87#endif