1845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com */ 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkBlitRow.h" 9e902f8dc7e111ede8b22cbd9bb74f326b0ce36fbMike Klein#include "SkBlendModePriv.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 12ac04fef619ad3939a25e66bdaef6f6b1e7f5ca50Herb Derby#include "SkArenaAlloc.h" 13db873d8677a2d4ecfe38a794a5d868301bdeeabereed#include "SkModeColorFilter.h" 14744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein#include "SkPM4fPriv.h" 1596b333a9a1b6a367d6c542118638e3108d8ed23bMike Klein#include "SkRasterPipeline.h" 168b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 178b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 196f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#include "SkRandom.h" 201202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com#include "SkString.h" 21c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h" 22dd9ffea9ce051a49dbc6544e6aa3cb68fe987f47reed#include "SkPM4f.h" 2331b3044af4e97c662076147d119ba233a163b769reed@google.com 24c7141eb8fba41f1e098499ef17d0bc79641d54c5reed////////////////////////////////////////////////////////////////////////////////////////////////// 25c7141eb8fba41f1e098499ef17d0bc79641d54c5reed 26c7141eb8fba41f1e098499ef17d0bc79641d54c5reed#ifndef SK_IGNORE_TO_STRING 27c7141eb8fba41f1e098499ef17d0bc79641d54c5reedvoid SkModeColorFilter::toString(SkString* str) const { 28c7141eb8fba41f1e098499ef17d0bc79641d54c5reed str->append("SkModeColorFilter: color: 0x"); 29c7141eb8fba41f1e098499ef17d0bc79641d54c5reed str->appendHex(fColor); 30c7141eb8fba41f1e098499ef17d0bc79641d54c5reed str->append(" mode: "); 31c7141eb8fba41f1e098499ef17d0bc79641d54c5reed str->append(SkXfermode::ModeName(fMode)); 32c7141eb8fba41f1e098499ef17d0bc79641d54c5reed} 33c7141eb8fba41f1e098499ef17d0bc79641d54c5reed#endif 34c7141eb8fba41f1e098499ef17d0bc79641d54c5reed 35faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reedbool SkModeColorFilter::asColorMode(SkColor* color, SkBlendMode* mode) const { 36db873d8677a2d4ecfe38a794a5d868301bdeeabereed if (color) { 37db873d8677a2d4ecfe38a794a5d868301bdeeabereed *color = fColor; 388b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com } 39db873d8677a2d4ecfe38a794a5d868301bdeeabereed if (mode) { 40faba3715b8ddfaa0ce4df79bc8006e9bc7694e5bMike Reed *mode = fMode; 411202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com } 42db873d8677a2d4ecfe38a794a5d868301bdeeabereed return true; 43db873d8677a2d4ecfe38a794a5d868301bdeeabereed} 441202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com 45db873d8677a2d4ecfe38a794a5d868301bdeeabereeduint32_t SkModeColorFilter::getFlags() const { 46c5b1228141bd26d4573552a00ebeb0b85a4768dfreed uint32_t flags = 0; 4762a320c8d444cd04e4f2952c269ea4cbd58dee64reed switch (fMode) { 487d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed case SkBlendMode::kDst: //!< [Da, Dc] 497d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed case SkBlendMode::kSrcATop: //!< [Da, Sc * Da + (1 - Sa) * Dc] 503125565804054691b110b4731bc5a32070fab780reed flags |= kAlphaUnchanged_Flag; 5162a320c8d444cd04e4f2952c269ea4cbd58dee64reed default: 5262a320c8d444cd04e4f2952c269ea4cbd58dee64reed break; 5362a320c8d444cd04e4f2952c269ea4cbd58dee64reed } 543125565804054691b110b4731bc5a32070fab780reed return flags; 55db873d8677a2d4ecfe38a794a5d868301bdeeabereed} 5643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com 57db873d8677a2d4ecfe38a794a5d868301bdeeabereedvoid SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const { 58db873d8677a2d4ecfe38a794a5d868301bdeeabereed SkPMColor color = fPMColor; 59db873d8677a2d4ecfe38a794a5d868301bdeeabereed SkXfermodeProc proc = fProc; 609d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary 613125565804054691b110b4731bc5a32070fab780reed for (int i = 0; i < count; i++) { 623125565804054691b110b4731bc5a32070fab780reed result[i] = proc(color, shader[i]); 633125565804054691b110b4731bc5a32070fab780reed } 643125565804054691b110b4731bc5a32070fab780reed} 6595cc012ccaea20f372893ae277ea0a8a6339d094mtklein 663125565804054691b110b4731bc5a32070fab780reedvoid SkModeColorFilter::filterSpan4f(const SkPM4f shader[], int count, SkPM4f result[]) const { 676a01554e9e8687c56e6b6707e0c6a02062a1824eMike Reed SkXfermodeProc4f proc = SkXfermode::GetProc4f(fMode); 68744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein auto pm4f = SkColor4f::FromColor(fColor).premul(); 69db873d8677a2d4ecfe38a794a5d868301bdeeabereed for (int i = 0; i < count; i++) { 70744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein result[i] = proc(pm4f, shader[i]); 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 72db873d8677a2d4ecfe38a794a5d868301bdeeabereed} 731447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com 74db873d8677a2d4ecfe38a794a5d868301bdeeabereedvoid SkModeColorFilter::flatten(SkWriteBuffer& buffer) const { 75db873d8677a2d4ecfe38a794a5d868301bdeeabereed buffer.writeColor(fColor); 767d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed buffer.writeUInt((int)fMode); 77db873d8677a2d4ecfe38a794a5d868301bdeeabereed} 78fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 79db873d8677a2d4ecfe38a794a5d868301bdeeabereedvoid SkModeColorFilter::updateCache() { 80db873d8677a2d4ecfe38a794a5d868301bdeeabereed fPMColor = SkPreMultiplyColor(fColor); 816a01554e9e8687c56e6b6707e0c6a02062a1824eMike Reed fProc = SkXfermode::GetProc(fMode); 82db873d8677a2d4ecfe38a794a5d868301bdeeabereed} 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8460c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkModeColorFilter::CreateProc(SkReadBuffer& buffer) { 859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkColor color = buffer.readColor(); 867d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode mode = (SkBlendMode)buffer.readUInt(); 8760c9b58b3214b0154c931656e91e39b230e987d8reed return SkColorFilter::MakeModeFilter(color, mode); 889fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 899fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 90744908e5e81f81f34288a1b5547aa4ea990ad13dMike Kleinbool SkModeColorFilter::onAppendStages(SkRasterPipeline* p, 91744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein SkColorSpace* dst, 92ac04fef619ad3939a25e66bdaef6f6b1e7f5ca50Herb Derby SkArenaAlloc* scratch, 93744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein bool shaderIsOpaque) const { 94526525a37c2550ab4292a02a179ed5d5fe291919Mike Klein auto color = scratch->make<SkPM4f>(SkPM4f_from_SkColor(fColor, dst)); 95744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein 96c5093411071222c752334dc6e38887020e986cc3Mike Klein p->append(SkRasterPipeline::move_src_dst); 97744908e5e81f81f34288a1b5547aa4ea990ad13dMike Klein p->append(SkRasterPipeline::constant_color, color); 98130863ef51a2a94e5bdf87f344c0e892b2403985Mike Klein auto mode = (SkBlendMode)fMode; 99130863ef51a2a94e5bdf87f344c0e892b2403985Mike Klein if (!SkBlendMode_AppendStages(mode, p)) { 100130863ef51a2a94e5bdf87f344c0e892b2403985Mike Klein return false; 101130863ef51a2a94e5bdf87f344c0e892b2403985Mike Klein } 102eea7c16d59a163bd5b858891bc916c49063ed8acMike Klein if (SkBlendMode_CanOverflow(mode)) { p->append(SkRasterPipeline::clamp_a); } 103130863ef51a2a94e5bdf87f344c0e892b2403985Mike Klein return true; 10496b333a9a1b6a367d6c542118638e3108d8ed23bMike Klein} 10596b333a9a1b6a367d6c542118638e3108d8ed23bMike Klein 106a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 107a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#if SK_SUPPORT_GPU 108a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#include "GrBlend.h" 109ae4738f677c70f4ec7687422e1510ee3d80d810ebsalomon#include "effects/GrXfermodeFragmentProcessor.h" 110ae4738f677c70f4ec7687422e1510ee3d80d810ebsalomon#include "effects/GrConstColorProcessor.h" 111eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "SkGr.h" 112a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org 113618d304eb394d64779be0ecdc5eff898242faa8fBrian Osmansk_sp<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor( 114618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman GrContext*, SkColorSpace* dstColorSpace) const { 1157d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if (SkBlendMode::kDst == fMode) { 116e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon return nullptr; 117e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon } 118e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon 11906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman sk_sp<GrFragmentProcessor> constFP( 120618d304eb394d64779be0ecdc5eff898242faa8fBrian Osman GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpace), 12106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman GrConstColorProcessor::kIgnore_InputMode)); 12206ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman sk_sp<GrFragmentProcessor> fp( 12306ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode)); 124e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon if (!fp) { 125e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon return nullptr; 126e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon } 127ae4738f677c70f4ec7687422e1510ee3d80d810ebsalomon#ifdef SK_DEBUG 128e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon // With a solid color input this should always be able to compute the blended color 129e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon // (at least for coeff modes) 1307d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if ((unsigned)fMode <= (unsigned)SkBlendMode::kLastCoeffMode) { 131cb30bb2cb727e276792812c6390547dba474c831Brian Salomon SkASSERT(fp->hasConstantOutputForConstantInput()); 132a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org } 133e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon#endif 134e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon return fp; 135a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org} 136a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org 137a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org#endif 138a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org 139a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 140a34995e18b1f0a7d8c9f23451718bb30ff0105b0commit-bot@chromium.org 141c7141eb8fba41f1e098499ef17d0bc79641d54c5reedclass Src_SkModeColorFilter final : public SkModeColorFilter { 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1437d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkBlendMode::kSrc) {} 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override { 1468b0d0f6a9c01f45cd5bacf7aea2a32306fb16684reed@google.com sk_memset32(result, this->getPMColor(), count); 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1491447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate: 15043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com typedef SkModeColorFilter INHERITED; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 153c7141eb8fba41f1e098499ef17d0bc79641d54c5reedclass SrcOver_SkModeColorFilter final : public SkModeColorFilter { 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1557d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SrcOver_SkModeColorFilter(SkColor color) : INHERITED(color, SkBlendMode::kSrcOver) { } 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override { 15895cc012ccaea20f372893ae277ea0a8a6339d094mtklein SkBlitRow::Color32(result, shader, count, this->getPMColor()); 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 16243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com typedef SkModeColorFilter INHERITED; 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com/////////////////////////////////////////////////////////////////////////////// 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1677d954ad797176afedb9262fdea4507d0fc60eb9dMike Reedsk_sp<SkColorFilter> SkColorFilter::MakeModeFilter(SkColor color, SkBlendMode mode) { 1689fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (!SkIsValidMode(mode)) { 16996fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 1709fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 1719fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned alpha = SkColorGetA(color); 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // first collaps some modes if possible 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1767d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if (SkBlendMode::kClear == mode) { 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com color = 0; 1787d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed mode = SkBlendMode::kSrc; 1797d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed } else if (SkBlendMode::kSrcOver == mode) { 180845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (0 == alpha) { 1817d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed mode = SkBlendMode::kDst; 182845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com } else if (255 == alpha) { 1837d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed mode = SkBlendMode::kSrc; 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // else just stay srcover 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // weed out combinations that are noops, and just return null 1897d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed if (SkBlendMode::kDst == mode || 1907d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed (0 == alpha && (SkBlendMode::kSrcOver == mode || 1917d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode::kDstOver == mode || 1927d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode::kDstOut == mode || 1937d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode::kSrcATop == mode || 1947d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode::kXor == mode || 1957d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode::kDarken == mode)) || 1967d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed (0xFF == alpha && SkBlendMode::kDstIn == mode)) { 19796fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1991447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 2017d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed case SkBlendMode::kSrc: 202d053ce9c54d4e5937a142278359e5a4cde18095ereed return sk_make_sp<Src_SkModeColorFilter>(color); 2037d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed case SkBlendMode::kSrcOver: 204d053ce9c54d4e5937a142278359e5a4cde18095ereed return sk_make_sp<SrcOver_SkModeColorFilter>(color); 20543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com default: 206d053ce9c54d4e5937a142278359e5a4cde18095ereed return SkModeColorFilter::Make(color, mode); 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 209