reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 1 | /* |
| 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 Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 8 | #include "include/core/SkShader.h" |
| 9 | #include "include/core/SkString.h" |
Ben Wagner | 729a23f | 2019-05-17 16:29:34 -0400 | [diff] [blame] | 10 | #include "src/core/SkArenaAlloc.h" |
Mike Klein | 96bce8f | 2019-10-23 11:26:46 -0500 | [diff] [blame] | 11 | #include "src/core/SkRasterPipeline.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 12 | #include "src/core/SkReadBuffer.h" |
| 13 | #include "src/core/SkWriteBuffer.h" |
| 14 | #include "src/shaders/SkColorFilterShader.h" |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 15 | |
| 16 | #if SK_SUPPORT_GPU |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 17 | #include "src/gpu/GrFragmentProcessor.h" |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 18 | #endif |
| 19 | |
Mike Klein | 96bce8f | 2019-10-23 11:26:46 -0500 | [diff] [blame] | 20 | SkColorFilterShader::SkColorFilterShader(sk_sp<SkShader> shader, |
| 21 | float alpha, |
| 22 | sk_sp<SkColorFilter> filter) |
reed | d053ce9 | 2016-03-22 10:17:23 -0700 | [diff] [blame] | 23 | : fShader(std::move(shader)) |
| 24 | , fFilter(std::move(filter)) |
Mike Klein | 96bce8f | 2019-10-23 11:26:46 -0500 | [diff] [blame] | 25 | , fAlpha (alpha) |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 26 | { |
reed | d053ce9 | 2016-03-22 10:17:23 -0700 | [diff] [blame] | 27 | SkASSERT(fShader); |
| 28 | SkASSERT(fFilter); |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 29 | } |
| 30 | |
reed | 60c9b58 | 2016-04-03 09:11:13 -0700 | [diff] [blame] | 31 | sk_sp<SkFlattenable> SkColorFilterShader::CreateProc(SkReadBuffer& buffer) { |
reed | 8a21c9f | 2016-03-08 18:50:00 -0800 | [diff] [blame] | 32 | auto shader = buffer.readShader(); |
reed | d053ce9 | 2016-03-22 10:17:23 -0700 | [diff] [blame] | 33 | auto filter = buffer.readColorFilter(); |
| 34 | if (!shader || !filter) { |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 35 | return nullptr; |
| 36 | } |
Mike Klein | 96bce8f | 2019-10-23 11:26:46 -0500 | [diff] [blame] | 37 | return sk_make_sp<SkColorFilterShader>(shader, 1.0f, filter); |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 38 | } |
| 39 | |
Mike Klein | 96b6150 | 2019-11-05 10:18:05 -0600 | [diff] [blame] | 40 | bool SkColorFilterShader::isOpaque() const { |
| 41 | return fShader->isOpaque() |
| 42 | && fAlpha == 1.0f |
| 43 | && (fFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) != 0; |
| 44 | } |
| 45 | |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 46 | void SkColorFilterShader::flatten(SkWriteBuffer& buffer) const { |
reed | d053ce9 | 2016-03-22 10:17:23 -0700 | [diff] [blame] | 47 | buffer.writeFlattenable(fShader.get()); |
Mike Klein | 96bce8f | 2019-10-23 11:26:46 -0500 | [diff] [blame] | 48 | SkASSERT(fAlpha == 1.0f); // Not exposed in public API SkShader::makeWithColorFilter(). |
reed | d053ce9 | 2016-03-22 10:17:23 -0700 | [diff] [blame] | 49 | buffer.writeFlattenable(fFilter.get()); |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 50 | } |
| 51 | |
Mike Reed | 1386b2d | 2019-03-13 21:15:05 -0400 | [diff] [blame] | 52 | bool SkColorFilterShader::onAppendStages(const SkStageRec& rec) const { |
Mike Reed | 1d8c42e | 2017-08-29 14:58:19 -0400 | [diff] [blame] | 53 | if (!as_SB(fShader)->appendStages(rec)) { |
Mike Reed | 2aab802 | 2017-05-31 12:14:56 -0400 | [diff] [blame] | 54 | return false; |
| 55 | } |
Mike Klein | 96bce8f | 2019-10-23 11:26:46 -0500 | [diff] [blame] | 56 | if (fAlpha != 1.0f) { |
| 57 | rec.fPipeline->append(SkRasterPipeline::scale_1_float, rec.fAlloc->make<float>(fAlpha)); |
| 58 | } |
Mike Reed | 1386b2d | 2019-03-13 21:15:05 -0400 | [diff] [blame] | 59 | fFilter->appendStages(rec, fShader->isOpaque()); |
Mike Reed | 2aab802 | 2017-05-31 12:14:56 -0400 | [diff] [blame] | 60 | return true; |
| 61 | } |
| 62 | |
Mike Klein | 746acf1 | 2019-11-05 09:54:55 -0600 | [diff] [blame] | 63 | bool SkColorFilterShader::onProgram(skvm::Builder* p, |
| 64 | SkColorSpace* dstCS, |
Mike Klein | 1cc6067 | 2019-11-05 14:19:58 -0600 | [diff] [blame] | 65 | skvm::Uniforms* uniforms, |
Mike Klein | 746acf1 | 2019-11-05 09:54:55 -0600 | [diff] [blame] | 66 | skvm::F32 x, skvm::F32 y, |
Mike Klein | b9f2088 | 2019-11-08 12:14:15 -0600 | [diff] [blame] | 67 | skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const { |
Mike Klein | 746acf1 | 2019-11-05 09:54:55 -0600 | [diff] [blame] | 68 | // Run the shader. |
Mike Klein | 1cc6067 | 2019-11-05 14:19:58 -0600 | [diff] [blame] | 69 | if (!as_SB(fShader)->program(p, dstCS, uniforms, x,y, r,g,b,a)) { |
Mike Klein | 746acf1 | 2019-11-05 09:54:55 -0600 | [diff] [blame] | 70 | return false; |
| 71 | } |
Mike Klein | 746acf1 | 2019-11-05 09:54:55 -0600 | [diff] [blame] | 72 | |
| 73 | // Scale that by alpha. |
| 74 | if (fAlpha != 1.0f) { |
Mike Klein | b9f2088 | 2019-11-08 12:14:15 -0600 | [diff] [blame] | 75 | 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 Klein | 746acf1 | 2019-11-05 09:54:55 -0600 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | // Finally run that through the color filter. |
Mike Klein | 1cc6067 | 2019-11-05 14:19:58 -0600 | [diff] [blame] | 83 | if (!fFilter->program(p, dstCS, uniforms, r,g,b,a)) { |
Mike Klein | 746acf1 | 2019-11-05 09:54:55 -0600 | [diff] [blame] | 84 | return false; |
| 85 | } |
| 86 | |
| 87 | return true; |
| 88 | } |
| 89 | |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 90 | #if SK_SUPPORT_GPU |
| 91 | ///////////////////////////////////////////////////////////////////// |
| 92 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 93 | #include "include/gpu/GrContext.h" |
Robert Phillips | 1efecea | 2019-02-15 16:58:40 -0500 | [diff] [blame] | 94 | |
Brian Salomon | aff329b | 2017-08-11 09:40:37 -0400 | [diff] [blame] | 95 | std::unique_ptr<GrFragmentProcessor> SkColorFilterShader::asFragmentProcessor( |
Mike Reed | e3429e6 | 2018-01-19 11:43:34 -0500 | [diff] [blame] | 96 | const GrFPArgs& args) const { |
Brian Salomon | aff329b | 2017-08-11 09:40:37 -0400 | [diff] [blame] | 97 | auto fp1 = as_SB(fShader)->asFragmentProcessor(args); |
bungeman | 06ca8ec | 2016-06-09 08:01:03 -0700 | [diff] [blame] | 98 | if (!fp1) { |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 99 | return nullptr; |
| 100 | } |
| 101 | |
Mike Klein | 96bce8f | 2019-10-23 11:26:46 -0500 | [diff] [blame] | 102 | // TODO I guess, but it shouldn't come up as used today. |
| 103 | SkASSERT(fAlpha == 1.0f); |
| 104 | |
Brian Salomon | 4bc0c1f | 2019-09-30 15:12:27 -0400 | [diff] [blame] | 105 | auto fp2 = fFilter->asFragmentProcessor(args.fContext, *args.fDstColorInfo); |
bungeman | 06ca8ec | 2016-06-09 08:01:03 -0700 | [diff] [blame] | 106 | if (!fp2) { |
| 107 | return fp1; |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 108 | } |
| 109 | |
Brian Salomon | aff329b | 2017-08-11 09:40:37 -0400 | [diff] [blame] | 110 | std::unique_ptr<GrFragmentProcessor> fpSeries[] = { std::move(fp1), std::move(fp2) }; |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 111 | return GrFragmentProcessor::RunInSeries(fpSeries, 2); |
| 112 | } |
| 113 | #endif |
| 114 | |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 115 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 116 | |
reed | d053ce9 | 2016-03-22 10:17:23 -0700 | [diff] [blame] | 117 | sk_sp<SkShader> SkShader::makeWithColorFilter(sk_sp<SkColorFilter> filter) const { |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 118 | SkShader* base = const_cast<SkShader*>(this); |
| 119 | if (!filter) { |
reed | 150835e | 2016-03-10 06:36:49 -0800 | [diff] [blame] | 120 | return sk_ref_sp(base); |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 121 | } |
Mike Klein | 96bce8f | 2019-10-23 11:26:46 -0500 | [diff] [blame] | 122 | return sk_make_sp<SkColorFilterShader>(sk_ref_sp(base), 1.0f, filter); |
reed | 3061af4 | 2016-01-07 15:47:29 -0800 | [diff] [blame] | 123 | } |