blob: 3ab9098136bf8543b13a8426c8f1033b03d12f98 [file] [log] [blame]
reed3061af42016-01-07 15:47:29 -08001/*
2 * Copyright 2013 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkShader.h"
9#include "include/core/SkString.h"
Ben Wagner729a23f2019-05-17 16:29:34 -040010#include "src/core/SkArenaAlloc.h"
Mike Klein96bce8f2019-10-23 11:26:46 -050011#include "src/core/SkRasterPipeline.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/core/SkReadBuffer.h"
13#include "src/core/SkWriteBuffer.h"
14#include "src/shaders/SkColorFilterShader.h"
reed3061af42016-01-07 15:47:29 -080015
16#if SK_SUPPORT_GPU
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/gpu/GrFragmentProcessor.h"
reed3061af42016-01-07 15:47:29 -080018#endif
19
Mike Klein96bce8f2019-10-23 11:26:46 -050020SkColorFilterShader::SkColorFilterShader(sk_sp<SkShader> shader,
21 float alpha,
22 sk_sp<SkColorFilter> filter)
reedd053ce92016-03-22 10:17:23 -070023 : fShader(std::move(shader))
24 , fFilter(std::move(filter))
Mike Klein96bce8f2019-10-23 11:26:46 -050025 , fAlpha (alpha)
reed3061af42016-01-07 15:47:29 -080026{
reedd053ce92016-03-22 10:17:23 -070027 SkASSERT(fShader);
28 SkASSERT(fFilter);
reed3061af42016-01-07 15:47:29 -080029}
30
reed60c9b582016-04-03 09:11:13 -070031sk_sp<SkFlattenable> SkColorFilterShader::CreateProc(SkReadBuffer& buffer) {
reed8a21c9f2016-03-08 18:50:00 -080032 auto shader = buffer.readShader();
reedd053ce92016-03-22 10:17:23 -070033 auto filter = buffer.readColorFilter();
34 if (!shader || !filter) {
reed3061af42016-01-07 15:47:29 -080035 return nullptr;
36 }
Mike Klein96bce8f2019-10-23 11:26:46 -050037 return sk_make_sp<SkColorFilterShader>(shader, 1.0f, filter);
reed3061af42016-01-07 15:47:29 -080038}
39
Mike Klein96b61502019-11-05 10:18:05 -060040bool SkColorFilterShader::isOpaque() const {
41 return fShader->isOpaque()
42 && fAlpha == 1.0f
43 && (fFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) != 0;
44}
45
reed3061af42016-01-07 15:47:29 -080046void SkColorFilterShader::flatten(SkWriteBuffer& buffer) const {
reedd053ce92016-03-22 10:17:23 -070047 buffer.writeFlattenable(fShader.get());
Mike Klein96bce8f2019-10-23 11:26:46 -050048 SkASSERT(fAlpha == 1.0f); // Not exposed in public API SkShader::makeWithColorFilter().
reedd053ce92016-03-22 10:17:23 -070049 buffer.writeFlattenable(fFilter.get());
reed3061af42016-01-07 15:47:29 -080050}
51
Mike Reed1386b2d2019-03-13 21:15:05 -040052bool SkColorFilterShader::onAppendStages(const SkStageRec& rec) const {
Mike Reed1d8c42e2017-08-29 14:58:19 -040053 if (!as_SB(fShader)->appendStages(rec)) {
Mike Reed2aab8022017-05-31 12:14:56 -040054 return false;
55 }
Mike Klein96bce8f2019-10-23 11:26:46 -050056 if (fAlpha != 1.0f) {
57 rec.fPipeline->append(SkRasterPipeline::scale_1_float, rec.fAlloc->make<float>(fAlpha));
58 }
Mike Reed1386b2d2019-03-13 21:15:05 -040059 fFilter->appendStages(rec, fShader->isOpaque());
Mike Reed2aab8022017-05-31 12:14:56 -040060 return true;
61}
62
Mike Klein746acf12019-11-05 09:54:55 -060063bool SkColorFilterShader::onProgram(skvm::Builder* p,
64 SkColorSpace* dstCS,
Mike Klein1cc60672019-11-05 14:19:58 -060065 skvm::Uniforms* uniforms,
Mike Klein746acf12019-11-05 09:54:55 -060066 skvm::F32 x, skvm::F32 y,
Mike Kleinb9f20882019-11-08 12:14:15 -060067 skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
Mike Klein746acf12019-11-05 09:54:55 -060068 // Run the shader.
Mike Klein1cc60672019-11-05 14:19:58 -060069 if (!as_SB(fShader)->program(p, dstCS, uniforms, x,y, r,g,b,a)) {
Mike Klein746acf12019-11-05 09:54:55 -060070 return false;
71 }
Mike Klein746acf12019-11-05 09:54:55 -060072
73 // Scale that by alpha.
74 if (fAlpha != 1.0f) {
Mike Kleinb9f20882019-11-08 12:14:15 -060075 skvm::F32 A = p->uniformF(uniforms->pushF(fAlpha));
76 *r = p->mul(*r, A);
77 *g = p->mul(*g, A);
78 *b = p->mul(*b, A);
79 *a = p->mul(*a, A);
Mike Klein746acf12019-11-05 09:54:55 -060080 }
81
82 // Finally run that through the color filter.
Mike Klein1cc60672019-11-05 14:19:58 -060083 if (!fFilter->program(p, dstCS, uniforms, r,g,b,a)) {
Mike Klein746acf12019-11-05 09:54:55 -060084 return false;
85 }
86
87 return true;
88}
89
reed3061af42016-01-07 15:47:29 -080090#if SK_SUPPORT_GPU
91/////////////////////////////////////////////////////////////////////
92
Mike Kleinc0bd9f92019-04-23 12:05:21 -050093#include "include/gpu/GrContext.h"
Robert Phillips1efecea2019-02-15 16:58:40 -050094
Brian Salomonaff329b2017-08-11 09:40:37 -040095std::unique_ptr<GrFragmentProcessor> SkColorFilterShader::asFragmentProcessor(
Mike Reede3429e62018-01-19 11:43:34 -050096 const GrFPArgs& args) const {
Brian Salomonaff329b2017-08-11 09:40:37 -040097 auto fp1 = as_SB(fShader)->asFragmentProcessor(args);
bungeman06ca8ec2016-06-09 08:01:03 -070098 if (!fp1) {
reed3061af42016-01-07 15:47:29 -080099 return nullptr;
100 }
101
Mike Klein96bce8f2019-10-23 11:26:46 -0500102 // TODO I guess, but it shouldn't come up as used today.
103 SkASSERT(fAlpha == 1.0f);
104
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400105 auto fp2 = fFilter->asFragmentProcessor(args.fContext, *args.fDstColorInfo);
bungeman06ca8ec2016-06-09 08:01:03 -0700106 if (!fp2) {
107 return fp1;
reed3061af42016-01-07 15:47:29 -0800108 }
109
Brian Salomonaff329b2017-08-11 09:40:37 -0400110 std::unique_ptr<GrFragmentProcessor> fpSeries[] = { std::move(fp1), std::move(fp2) };
reed3061af42016-01-07 15:47:29 -0800111 return GrFragmentProcessor::RunInSeries(fpSeries, 2);
112}
113#endif
114
reed3061af42016-01-07 15:47:29 -0800115///////////////////////////////////////////////////////////////////////////////////////////////////
116
reedd053ce92016-03-22 10:17:23 -0700117sk_sp<SkShader> SkShader::makeWithColorFilter(sk_sp<SkColorFilter> filter) const {
reed3061af42016-01-07 15:47:29 -0800118 SkShader* base = const_cast<SkShader*>(this);
119 if (!filter) {
reed150835e2016-03-10 06:36:49 -0800120 return sk_ref_sp(base);
reed3061af42016-01-07 15:47:29 -0800121 }
Mike Klein96bce8f2019-10-23 11:26:46 -0500122 return sk_make_sp<SkColorFilterShader>(sk_ref_sp(base), 1.0f, filter);
reed3061af42016-01-07 15:47:29 -0800123}