SkColorFilter.cpp revision ff723af8b6bc7179132052fbab7d77ec2a20eba2
1b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com/* 2b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com * Copyright 2006 The Android Open Source Project 3b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com * 4b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com * Use of this source code is governed by a BSD-style license that can be 5b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com * found in the LICENSE file. 6b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com */ 7b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com 8b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#include "SkColorFilter.h" 94c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkReadBuffer.h" 1046596ae50559e89a0a2462573ac9448cf309cf56Mike Reed#include "SkRefCnt.h" 11b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#include "SkString.h" 12e8f3062a36d3682f4019309a32b5b84dc9eddf8creed#include "SkTDArray.h" 134c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkUnPreMultiply.h" 1446596ae50559e89a0a2462573ac9448cf309cf56Mike Reed#include "SkWriteBuffer.h" 154c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkPM4f.h" 164c21dc5ddf3b482293ed34eead876d8d61a662c3reed#include "SkNx.h" 179ce9d6772df650ceb0511f275e1a83dffa78ff72reed 18b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#if SK_SUPPORT_GPU 19b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#include "GrFragmentProcessor.h" 20b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#endif 21cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com 22e8f3062a36d3682f4019309a32b5b84dc9eddf8creedbool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const { 234c21dc5ddf3b482293ed34eead876d8d61a662c3reed return false; 24d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com} 25b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com 26b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.combool SkColorFilter::asColorMatrix(SkScalar matrix[20]) const { 27b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com return false; 28d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com} 29b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com 30d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.combool SkColorFilter::asComponentTable(SkBitmap*) const { 31b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com return false; 32b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com} 33d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 34b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#if SK_SUPPORT_GPU 354c21dc5ddf3b482293ed34eead876d8d61a662c3reedsk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*) const { 36b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com return nullptr; 37b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com} 384c21dc5ddf3b482293ed34eead876d8d61a662c3reed#endif 39b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com 40b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.comvoid SkColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const { 414c21dc5ddf3b482293ed34eead876d8d61a662c3reed const int N = 128; 424c21dc5ddf3b482293ed34eead876d8d61a662c3reed SkPMColor tmp[N]; 439ce9d6772df650ceb0511f275e1a83dffa78ff72reed while (count > 0) { 44b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com int n = SkTMin(count, N); 45b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com for (int i = 0; i < n; ++i) { 464c21dc5ddf3b482293ed34eead876d8d61a662c3reed SkNx_cast<uint8_t>(Sk4f::Load(src[i].fVec) * Sk4f(255) + Sk4f(0.5f)).store(&tmp[i]); 474c21dc5ddf3b482293ed34eead876d8d61a662c3reed } 484c21dc5ddf3b482293ed34eead876d8d61a662c3reed this->filterSpan(tmp, n, tmp); 494c21dc5ddf3b482293ed34eead876d8d61a662c3reed for (int i = 0; i < n; ++i) { 504c21dc5ddf3b482293ed34eead876d8d61a662c3reed result[i] = SkPM4f::FromPMColor(tmp[i]); 51d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 524c21dc5ddf3b482293ed34eead876d8d61a662c3reed src += n; 53b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com result += n; 549ce9d6772df650ceb0511f275e1a83dffa78ff72reed count -= n; 559ce9d6772df650ceb0511f275e1a83dffa78ff72reed } 569ce9d6772df650ceb0511f275e1a83dffa78ff72reed} 57b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com 58d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comSkColor SkColorFilter::filterColor(SkColor c) const { 59b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com SkPMColor dst, src = SkPreMultiplyColor(c); 60b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com this->filterSpan(&src, 1, &dst); 614c21dc5ddf3b482293ed34eead876d8d61a662c3reed return SkUnPreMultiply::PMColorToColor(dst); 62b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com} 63b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com 64b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.comSkColor4f SkColorFilter::filterColor4f(const SkColor4f& c) const { 654c21dc5ddf3b482293ed34eead876d8d61a662c3reed SkPM4f dst, src = c.premul(); 6633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt this->filterSpan4f(&src, 1, &dst); 67b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com return dst.unpremul(); 68b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com} 694c21dc5ddf3b482293ed34eead876d8d61a662c3reed 7096fcdcc219d2a0d3579719b84b28bede76efba64halcanary/////////////////////////////////////////////////////////////////////////////////////////////////// 719ce9d6772df650ceb0511f275e1a83dffa78ff72reed 729ce9d6772df650ceb0511f275e1a83dffa78ff72reed/* 734c21dc5ddf3b482293ed34eead876d8d61a662c3reed * Since colorfilters may be used on the GPU backend, and in that case we may string together 74d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com * many GrFragmentProcessors, we might exceed some internal instruction/resource limit. 75b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com * 764c21dc5ddf3b482293ed34eead876d8d61a662c3reed * Since we don't yet know *what* those limits might be when we construct the final shader, 77d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com * we just set an arbitrary limit during construction. If later we find smarter ways to know what 78fafe135349bd34961a12bfd8185733709cd0e45eHal Canary * the limnits are, we can change this constant (or remove it). 79b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com */ 80b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#define SK_MAX_COMPOSE_COLORFILTER_COUNT 4 81b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com 82b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.comclass SkComposeColorFilter : public SkColorFilter { 83b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.compublic: 84d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com uint32_t getFlags() const override { 8596fcdcc219d2a0d3579719b84b28bede76efba64halcanary // Can only claim alphaunchanged and SkPM4f support if both our proxys do. 86d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return fOuter->getFlags() & fInner->getFlags(); 87b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com } 88b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com 89d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override { 90b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com fInner->filterSpan(shader, count, result); 9133a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt fOuter->filterSpan(result, count, result); 9233a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt } 9333a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt 9433a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt void filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const override { 9533a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt fInner->filterSpan4f(shader, count, result); 9633a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt fOuter->filterSpan4f(result, count, result); 9733a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt } 9833a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt 9933a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt#ifndef SK_IGNORE_TO_STRING 1009ce9d6772df650ceb0511f275e1a83dffa78ff72reed void toString(SkString* str) const override { 10133a5fce6126dc5d3927a71fdc6c35af6f5893fd5joshualitt SkString outerS, innerS; 102b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com fOuter->toString(&outerS); 103b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com fInner->toString(&innerS); 104b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com str->appendf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(), innerS.c_str()); 105d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 106b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#endif 1074c21dc5ddf3b482293ed34eead876d8d61a662c3reed 108b67052596f8abebbbc6399c682b20a7dffeeecefreed@google.com#if SK_SUPPORT_GPU 1094c21dc5ddf3b482293ed34eead876d8d61a662c3reed sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context) const override { 110 sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context)); 111 sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context)); 112 if (!innerFP || !outerFP) { 113 return nullptr; 114 } 115 sk_sp<GrFragmentProcessor> series[] = { std::move(innerFP), std::move(outerFP) }; 116 return GrFragmentProcessor::RunInSeries(series, 2); 117 } 118#endif 119 120 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter) 121 122protected: 123 void flatten(SkWriteBuffer& buffer) const override { 124 buffer.writeFlattenable(fOuter.get()); 125 buffer.writeFlattenable(fInner.get()); 126 } 127 128private: 129 SkComposeColorFilter(sk_sp<SkColorFilter> outer, sk_sp<SkColorFilter> inner, 130 int composedFilterCount) 131 : fOuter(std::move(outer)) 132 , fInner(std::move(inner)) 133 , fComposedFilterCount(composedFilterCount) 134 { 135 SkASSERT(composedFilterCount >= 2); 136 SkASSERT(composedFilterCount <= SK_MAX_COMPOSE_COLORFILTER_COUNT); 137 } 138 139 int privateComposedFilterCount() const override { 140 return fComposedFilterCount; 141 } 142 143 sk_sp<SkColorFilter> fOuter; 144 sk_sp<SkColorFilter> fInner; 145 const int fComposedFilterCount; 146 147 friend class SkColorFilter; 148 149 typedef SkColorFilter INHERITED; 150}; 151 152sk_sp<SkFlattenable> SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) { 153 sk_sp<SkColorFilter> outer(buffer.readColorFilter()); 154 sk_sp<SkColorFilter> inner(buffer.readColorFilter()); 155 return MakeComposeFilter(std::move(outer), std::move(inner)); 156} 157 158/////////////////////////////////////////////////////////////////////////////////////////////////// 159 160sk_sp<SkColorFilter> SkColorFilter::MakeComposeFilter(sk_sp<SkColorFilter> outer, 161 sk_sp<SkColorFilter> inner) { 162 if (!outer) { 163 return inner; 164 } 165 if (!inner) { 166 return outer; 167 } 168 169 // Give the subclass a shot at a more optimal composition... 170 auto composition = outer->makeComposed(inner); 171 if (composition) { 172 return composition; 173 } 174 175 int count = inner->privateComposedFilterCount() + outer->privateComposedFilterCount(); 176 if (count > SK_MAX_COMPOSE_COLORFILTER_COUNT) { 177 return nullptr; 178 } 179 return sk_sp<SkColorFilter>(new SkComposeColorFilter(std::move(outer), std::move(inner),count)); 180} 181 182#include "SkModeColorFilter.h" 183 184SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter) 185SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter) 186SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter) 187SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 188