blob: d7637f2304e7420bc488014fc5e795233d6d4424 [file] [log] [blame]
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +00001/*
2 * Copyright 2013 The Android Open Source Project
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
8#include "SkXfermodeImageFilter.h"
Brian Salomon89cb8212017-01-09 10:48:23 -05009#include "SkArithmeticImageFilter.h"
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000010#include "SkCanvas.h"
Cary Clarka4083c92017-09-15 11:59:23 -040011#include "SkColorData.h"
Mike Reed6d9f4292017-07-06 12:32:55 -040012#include "SkColorSpaceXformer.h"
Cary Clark4dc5a452018-05-21 11:56:57 -040013#include "SkFlattenablePriv.h"
Cary Clark60aaeb22017-11-03 08:06:09 -040014#include "SkImageFilterPriv.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000015#include "SkReadBuffer.h"
robertphillipsf230c6d2016-04-15 12:47:42 -070016#include "SkSpecialImage.h"
17#include "SkSpecialSurface.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000018#include "SkWriteBuffer.h"
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000019#if SK_SUPPORT_GPU
Brian Salomonc65aec92017-03-09 09:03:58 -050020#include "GrClip.h"
Brian Osman1cb41712017-10-19 12:54:52 -040021#include "GrColorSpaceXform.h"
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000022#include "GrContext.h"
Brian Osman11052242016-10-27 14:47:55 -040023#include "GrRenderTargetContext.h"
Robert Phillips7f6cd902016-11-10 17:03:43 -050024#include "GrTextureProxy.h"
25
robertphillips4f037942016-02-09 05:09:27 -080026#include "effects/GrConstColorProcessor.h"
senorblancod762ca22015-04-07 12:16:55 -070027#include "effects/GrTextureDomain.h"
bsalomonae4738f2015-09-15 15:33:27 -070028#include "effects/GrSimpleTextureEffect.h"
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000029#include "SkGr.h"
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000030#endif
Mike Reedebfce6d2016-12-12 10:02:12 -050031#include "SkClipOpPriv.h"
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000032
Mike Reed403d1542016-09-26 18:51:24 -040033class SkXfermodeImageFilter_Base : public SkImageFilter {
Mike Reed667a0072016-09-23 11:43:54 -040034public:
reed374772b2016-10-05 17:33:02 -070035 SkXfermodeImageFilter_Base(SkBlendMode mode, sk_sp<SkImageFilter> inputs[2],
Mike Reed667a0072016-09-23 11:43:54 -040036 const CropRect* cropRect);
37
Mike Reed667a0072016-09-23 11:43:54 -040038 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkXfermodeImageFilter_Base)
39
40protected:
41 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
42 SkIPoint* offset) const override;
Matt Sarett6d72ed92017-04-10 16:35:33 -040043 sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
Mike Reed667a0072016-09-23 11:43:54 -040044
Robert Phillips12078432018-05-17 11:17:39 -040045 SkIRect onFilterBounds(const SkIRect&, const SkMatrix& ctm,
46 MapDirection, const SkIRect* inputRect) const override;
Xianzhu Wang0fa353c2017-08-25 16:27:04 -070047
Mike Reed667a0072016-09-23 11:43:54 -040048#if SK_SUPPORT_GPU
49 sk_sp<SkSpecialImage> filterImageGPU(SkSpecialImage* source,
50 sk_sp<SkSpecialImage> background,
51 const SkIPoint& backgroundOffset,
52 sk_sp<SkSpecialImage> foreground,
53 const SkIPoint& foregroundOffset,
54 const SkIRect& bounds,
55 const OutputProperties& outputProperties) const;
56#endif
57
58 void flatten(SkWriteBuffer&) const override;
59
Brian Salomon89cb8212017-01-09 10:48:23 -050060 void drawForeground(SkCanvas* canvas, SkSpecialImage*, const SkIRect&) const;
Mike Reed403d1542016-09-26 18:51:24 -040061#if SK_SUPPORT_GPU
Brian Salomonaff329b2017-08-11 09:40:37 -040062 std::unique_ptr<GrFragmentProcessor> makeFGFrag(
63 std::unique_ptr<GrFragmentProcessor> bgFP) const;
Mike Reed403d1542016-09-26 18:51:24 -040064#endif
Mike Reed667a0072016-09-23 11:43:54 -040065
66private:
Brian Salomon89cb8212017-01-09 10:48:23 -050067 static sk_sp<SkFlattenable> LegacyArithmeticCreateProc(SkReadBuffer& buffer);
68
reed374772b2016-10-05 17:33:02 -070069 SkBlendMode fMode;
Mike Reed667a0072016-09-23 11:43:54 -040070
71 friend class SkXfermodeImageFilter;
72
73 typedef SkImageFilter INHERITED;
74};
75
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000076///////////////////////////////////////////////////////////////////////////////
77
reed374772b2016-10-05 17:33:02 -070078sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(SkBlendMode mode,
robertphillips8c0326d2016-04-05 12:48:34 -070079 sk_sp<SkImageFilter> background,
80 sk_sp<SkImageFilter> foreground,
Mike Reed667a0072016-09-23 11:43:54 -040081 const SkImageFilter::CropRect* cropRect) {
robertphillips8c0326d2016-04-05 12:48:34 -070082 sk_sp<SkImageFilter> inputs[2] = { std::move(background), std::move(foreground) };
Mike Reed667a0072016-09-23 11:43:54 -040083 return sk_sp<SkImageFilter>(new SkXfermodeImageFilter_Base(mode, inputs, cropRect));
reedcfb6bdf2016-03-29 11:32:50 -070084}
85
reed374772b2016-10-05 17:33:02 -070086SkXfermodeImageFilter_Base::SkXfermodeImageFilter_Base(SkBlendMode mode,
87 sk_sp<SkImageFilter> inputs[2],
88 const CropRect* cropRect)
Mike Reed18342422016-10-04 10:06:20 -040089 : INHERITED(inputs, 2, cropRect)
reed374772b2016-10-05 17:33:02 -070090 , fMode(mode)
91{}
92
Mike Reed63544a42017-06-09 17:00:25 -040093static unsigned unflatten_blendmode(SkReadBuffer& buffer) {
94 unsigned mode = buffer.read32();
Mike Reed70bc94f2017-06-08 12:45:52 -040095 (void)buffer.validate(mode <= (unsigned)SkBlendMode::kLastMode);
96 return mode;
Mike Reed3ed485f2016-10-04 21:35:32 +000097}
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +000098
Mike Reed667a0072016-09-23 11:43:54 -040099sk_sp<SkFlattenable> SkXfermodeImageFilter_Base::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -0700100 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
Mike Reed63544a42017-06-09 17:00:25 -0400101 unsigned mode = unflatten_blendmode(buffer);
102 if (!buffer.isValid()) {
103 return nullptr;
reed374772b2016-10-05 17:33:02 -0700104 }
Mike Reed63544a42017-06-09 17:00:25 -0400105 return SkXfermodeImageFilter::Make((SkBlendMode)mode, common.getInput(0),
106 common.getInput(1), &common.cropRect());
reed9fa60da2014-08-21 07:59:51 -0700107}
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000108
Mike Reed667a0072016-09-23 11:43:54 -0400109void SkXfermodeImageFilter_Base::flatten(SkWriteBuffer& buffer) const {
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000110 this->INHERITED::flatten(buffer);
reed374772b2016-10-05 17:33:02 -0700111 buffer.write32((unsigned)fMode);
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000112}
113
Mike Reed667a0072016-09-23 11:43:54 -0400114sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* source,
Robert Phillipsc100d482018-07-10 10:11:01 -0400115 const Context& ctx,
116 SkIPoint* offset) const {
commit-bot@chromium.org7b320702013-07-10 21:22:18 +0000117 SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
robertphillipsf230c6d2016-04-15 12:47:42 -0700118 sk_sp<SkSpecialImage> background(this->filterInput(0, source, ctx, &backgroundOffset));
119
commit-bot@chromium.org7b320702013-07-10 21:22:18 +0000120 SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
robertphillipsf230c6d2016-04-15 12:47:42 -0700121 sk_sp<SkSpecialImage> foreground(this->filterInput(1, source, ctx, &foregroundOffset));
122
123 SkIRect foregroundBounds = SkIRect::EmptyIRect();
124 if (foreground) {
125 foregroundBounds = SkIRect::MakeXYWH(foregroundOffset.x(), foregroundOffset.y(),
126 foreground->width(), foreground->height());
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000127 }
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +0000128
robertphillipsf230c6d2016-04-15 12:47:42 -0700129 SkIRect srcBounds = SkIRect::EmptyIRect();
130 if (background) {
131 srcBounds = SkIRect::MakeXYWH(backgroundOffset.x(), backgroundOffset.y(),
Robert Phillipsc100d482018-07-10 10:11:01 -0400132 background->width(), background->height());
robertphillipsf230c6d2016-04-15 12:47:42 -0700133 }
Ben Wagner63fd7602017-10-09 15:45:33 -0400134
senorblanco9db04272016-03-31 08:24:29 -0700135 srcBounds.join(foregroundBounds);
robertphillipsf230c6d2016-04-15 12:47:42 -0700136 if (srcBounds.isEmpty()) {
137 return nullptr;
138 }
139
senorblanco9db04272016-03-31 08:24:29 -0700140 SkIRect bounds;
141 if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
robertphillipsf230c6d2016-04-15 12:47:42 -0700142 return nullptr;
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +0000143 }
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +0000144
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000145 offset->fX = bounds.left();
146 offset->fY = bounds.top();
robertphillipsf230c6d2016-04-15 12:47:42 -0700147
148#if SK_SUPPORT_GPU
149 if (source->isTextureBacked()) {
150 return this->filterImageGPU(source,
Ben Wagner63fd7602017-10-09 15:45:33 -0400151 background, backgroundOffset,
robertphillipsf230c6d2016-04-15 12:47:42 -0700152 foreground, foregroundOffset,
brianosman2a75e5d2016-09-22 07:15:37 -0700153 bounds, ctx.outputProperties());
robertphillipsf230c6d2016-04-15 12:47:42 -0700154 }
155#endif
156
brianosmaneed6b0e2016-09-23 13:04:05 -0700157 sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
robertphillipsf230c6d2016-04-15 12:47:42 -0700158 if (!surf) {
159 return nullptr;
160 }
161
162 SkCanvas* canvas = surf->getCanvas();
163 SkASSERT(canvas);
164
robertphillips3806b8f2016-05-12 10:46:39 -0700165 canvas->clear(0x0); // can't count on background to fully clear the background
robertphillipsf230c6d2016-04-15 12:47:42 -0700166 canvas->translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
167
robertphillipsf230c6d2016-04-15 12:47:42 -0700168 if (background) {
Mike Reed403d1542016-09-26 18:51:24 -0400169 SkPaint paint;
reed374772b2016-10-05 17:33:02 -0700170 paint.setBlendMode(SkBlendMode::kSrc);
robertphillipsf230c6d2016-04-15 12:47:42 -0700171 background->draw(canvas,
172 SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY),
173 &paint);
174 }
175
Mike Reed403d1542016-09-26 18:51:24 -0400176 this->drawForeground(canvas, foreground.get(), foregroundBounds);
Mike Reed10ff5bf2016-09-26 20:40:57 +0000177
178 return surf->makeImageSnapshot();
Mike Reed0530c882016-09-26 15:33:00 -0400179}
180
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700181SkIRect SkXfermodeImageFilter_Base::onFilterBounds(const SkIRect& src,
182 const SkMatrix& ctm,
Robert Phillips12078432018-05-17 11:17:39 -0400183 MapDirection dir,
184 const SkIRect* inputRect) const {
185 if (kReverse_MapDirection == dir) {
186 return SkImageFilter::onFilterBounds(src, ctm, dir, inputRect);
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700187 }
188
Robert Phillips12078432018-05-17 11:17:39 -0400189 SkASSERT(!inputRect);
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700190 SkASSERT(2 == this->countInputs());
191 auto getBackground = [&]() {
Robert Phillips12078432018-05-17 11:17:39 -0400192 return this->getInput(0) ? this->getInput(0)->filterBounds(src, ctm, dir, inputRect) : src;
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700193 };
194 auto getForeground = [&]() {
Robert Phillips12078432018-05-17 11:17:39 -0400195 return this->getInput(1) ? this->getInput(1)->filterBounds(src, ctm, dir, inputRect) : src;
Xianzhu Wang0fa353c2017-08-25 16:27:04 -0700196 };
197 switch (fMode) {
198 case SkBlendMode::kClear:
199 return SkIRect::MakeEmpty();
200
201 case SkBlendMode::kSrc:
202 case SkBlendMode::kDstATop:
203 return getForeground();
204
205 case SkBlendMode::kDst:
206 case SkBlendMode::kSrcATop:
207 return getBackground();
208
209 case SkBlendMode::kSrcIn:
210 case SkBlendMode::kDstIn: {
211 auto result = getBackground();
212 if (!result.intersect(getForeground())) {
213 return SkIRect::MakeEmpty();
214 }
215 return result;
216 }
217
218 default: {
219 auto result = getBackground();
220 result.join(getForeground());
221 return result;
222 }
223 }
224}
225
Matt Sarett6d72ed92017-04-10 16:35:33 -0400226sk_sp<SkImageFilter> SkXfermodeImageFilter_Base::onMakeColorSpace(SkColorSpaceXformer* xformer)
227const {
228 SkASSERT(2 == this->countInputs());
Mike Reed6d9f4292017-07-06 12:32:55 -0400229 auto background = xformer->apply(this->getInput(0));
230 auto foreground = xformer->apply(this->getInput(1));
231 if (background.get() != this->getInput(0) || foreground.get() != this->getInput(1)) {
232 return SkXfermodeImageFilter::Make(fMode, std::move(background), std::move(foreground),
233 this->getCropRectIfSet());
Matt Sarett6d72ed92017-04-10 16:35:33 -0400234 }
Mike Reed6d9f4292017-07-06 12:32:55 -0400235 return this->refMe();
Matt Sarett6d72ed92017-04-10 16:35:33 -0400236}
237
Mike Reed403d1542016-09-26 18:51:24 -0400238void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img,
239 const SkIRect& fgBounds) const {
240 SkPaint paint;
reed374772b2016-10-05 17:33:02 -0700241 paint.setBlendMode(fMode);
Mike Reed403d1542016-09-26 18:51:24 -0400242 if (img) {
243 img->draw(canvas, SkIntToScalar(fgBounds.fLeft), SkIntToScalar(fgBounds.fTop), &paint);
244 }
245
246 SkAutoCanvasRestore acr(canvas, true);
Mike Reedc1f77742016-12-09 09:00:50 -0500247 canvas->clipRect(SkRect::Make(fgBounds), kDifference_SkClipOp);
Mike Reed403d1542016-09-26 18:51:24 -0400248 paint.setColor(0);
249 canvas->drawPaint(paint);
250}
251
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000252#if SK_SUPPORT_GPU
253
Mike Reed2f07c282017-06-10 14:07:36 -0400254#include "effects/GrXfermodeFragmentProcessor.h"
robertphillips4f037942016-02-09 05:09:27 -0800255
Mike Reed667a0072016-09-23 11:43:54 -0400256sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU(
brianosman2a75e5d2016-09-22 07:15:37 -0700257 SkSpecialImage* source,
258 sk_sp<SkSpecialImage> background,
259 const SkIPoint& backgroundOffset,
260 sk_sp<SkSpecialImage> foreground,
261 const SkIPoint& foregroundOffset,
262 const SkIRect& bounds,
263 const OutputProperties& outputProperties) const {
robertphillipsf230c6d2016-04-15 12:47:42 -0700264 SkASSERT(source->isTextureBacked());
265
266 GrContext* context = source->getContext();
267
Robert Phillips8e1c4e62017-02-19 12:27:01 -0500268 sk_sp<GrTextureProxy> backgroundProxy, foregroundProxy;
269
robertphillipsf230c6d2016-04-15 12:47:42 -0700270 if (background) {
Robert Phillips8e1c4e62017-02-19 12:27:01 -0500271 backgroundProxy = background->asTextureProxyRef(context);
egdaniel38cd0552015-01-14 08:05:11 -0800272 }
273
robertphillipsf230c6d2016-04-15 12:47:42 -0700274 if (foreground) {
Robert Phillips8e1c4e62017-02-19 12:27:01 -0500275 foregroundProxy = foreground->asTextureProxyRef(context);
senorblanco06d54ad2016-01-13 13:48:54 -0800276 }
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000277
joshualittb2456052015-07-08 09:36:59 -0700278 GrPaint paint;
Brian Salomonaff329b2017-08-11 09:40:37 -0400279 std::unique_ptr<GrFragmentProcessor> bgFP;
robertphillips4f037942016-02-09 05:09:27 -0800280
Robert Phillips8e1c4e62017-02-19 12:27:01 -0500281 if (backgroundProxy) {
282 SkMatrix bgMatrix = SkMatrix::MakeTrans(-SkIntToScalar(backgroundOffset.fX),
283 -SkIntToScalar(backgroundOffset.fY));
Brian Osman2240be92017-10-18 13:15:13 -0400284 bgFP = GrTextureDomainEffect::Make(std::move(backgroundProxy), bgMatrix,
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400285 GrTextureDomain::MakeTexelDomain(background->subset()),
286 GrTextureDomain::kDecal_Mode,
287 GrSamplerState::Filter::kNearest);
Brian Osmanbd2c6532017-10-18 09:57:33 -0400288 bgFP = GrColorSpaceXformEffect::Make(std::move(bgFP), background->getColorSpace(),
Brian Osman21fc5ce2018-08-27 20:36:19 +0000289 background->alphaType(),
Brian Osman653f34d2018-06-14 11:44:02 -0400290 outputProperties.colorSpace());
robertphillips4f037942016-02-09 05:09:27 -0800291 } else {
Brian Osmanf28e55d2018-10-03 16:35:54 -0400292 bgFP = GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
Ethan Nicholase9d172a2017-11-20 12:12:24 -0500293 GrConstColorProcessor::InputMode::kIgnore);
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000294 }
295
Robert Phillips8e1c4e62017-02-19 12:27:01 -0500296 if (foregroundProxy) {
297 SkMatrix fgMatrix = SkMatrix::MakeTrans(-SkIntToScalar(foregroundOffset.fX),
298 -SkIntToScalar(foregroundOffset.fY));
Brian Salomonaff329b2017-08-11 09:40:37 -0400299 auto foregroundFP = GrTextureDomainEffect::Make(
Brian Osman2240be92017-10-18 13:15:13 -0400300 std::move(foregroundProxy), fgMatrix,
Brian Salomonaff329b2017-08-11 09:40:37 -0400301 GrTextureDomain::MakeTexelDomain(foreground->subset()),
Brian Salomon2bbdcc42017-09-07 12:36:34 -0400302 GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
Brian Osmanbd2c6532017-10-18 09:57:33 -0400303 foregroundFP = GrColorSpaceXformEffect::Make(std::move(foregroundFP),
Brian Osman653f34d2018-06-14 11:44:02 -0400304 foreground->getColorSpace(),
Brian Osman21fc5ce2018-08-27 20:36:19 +0000305 foreground->alphaType(),
Brian Osmanbd2c6532017-10-18 09:57:33 -0400306 outputProperties.colorSpace());
bungeman06ca8ec2016-06-09 08:01:03 -0700307 paint.addColorFragmentProcessor(std::move(foregroundFP));
robertphillips4f037942016-02-09 05:09:27 -0800308
Brian Salomonaff329b2017-08-11 09:40:37 -0400309 std::unique_ptr<GrFragmentProcessor> xferFP = this->makeFGFrag(std::move(bgFP));
robertphillips4f037942016-02-09 05:09:27 -0800310
311 // A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
312 if (xferFP) {
bungeman06ca8ec2016-06-09 08:01:03 -0700313 paint.addColorFragmentProcessor(std::move(xferFP));
robertphillips4f037942016-02-09 05:09:27 -0800314 }
315 } else {
bungeman06ca8ec2016-06-09 08:01:03 -0700316 paint.addColorFragmentProcessor(std::move(bgFP));
bsalomonae4738f2015-09-15 15:33:27 -0700317 }
robertphillips4f037942016-02-09 05:09:27 -0800318
reed374772b2016-10-05 17:33:02 -0700319 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
robertphillipsea461502015-05-26 11:38:03 -0700320
Robert Phillips0c4b7b12018-03-06 08:20:37 -0500321 sk_sp<GrRenderTargetContext> renderTargetContext(
322 context->contextPriv().makeDeferredRenderTargetContext(
Robert Phillips7f6cd902016-11-10 17:03:43 -0500323 SkBackingFit::kApprox, bounds.width(), bounds.height(),
Brian Osmana50205f2018-07-06 13:57:01 -0400324 SkColorType2GrPixelConfig(outputProperties.colorType()),
Robert Phillips7f6cd902016-11-10 17:03:43 -0500325 sk_ref_sp(outputProperties.colorSpace())));
Brian Osman11052242016-10-27 14:47:55 -0400326 if (!renderTargetContext) {
robertphillipsf230c6d2016-04-15 12:47:42 -0700327 return nullptr;
robertphillipsea461502015-05-26 11:38:03 -0700328 }
329
senorblanco06d54ad2016-01-13 13:48:54 -0800330 SkMatrix matrix;
331 matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
Brian Salomon82f44312017-01-11 13:42:54 -0500332 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix,
333 SkRect::Make(bounds));
senorblanco@chromium.orgee845ae2014-04-01 19:15:23 +0000334
Brian Salomonf3569f02017-10-24 12:52:33 -0400335 return SkSpecialImage::MakeDeferredFromGpu(
336 context,
337 SkIRect::MakeWH(bounds.width(), bounds.height()),
338 kNeedNewImageUniqueID_SpecialImage,
339 renderTargetContext->asTextureProxyRef(),
340 renderTargetContext->colorSpaceInfo().refColorSpace());
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000341}
342
Brian Salomonaff329b2017-08-11 09:40:37 -0400343std::unique_ptr<GrFragmentProcessor> SkXfermodeImageFilter_Base::makeFGFrag(
344 std::unique_ptr<GrFragmentProcessor> bgFP) const {
Mike Reed2f07c282017-06-10 14:07:36 -0400345 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(bgFP), fMode);
Mike Reed403d1542016-09-26 18:51:24 -0400346}
347
senorblanco@chromium.org86fc2662013-05-31 17:49:12 +0000348#endif
Mike Reed667a0072016-09-23 11:43:54 -0400349///////////////////////////////////////////////////////////////////////////////////////////////////
350
Brian Salomon89cb8212017-01-09 10:48:23 -0500351sk_sp<SkFlattenable> SkXfermodeImageFilter_Base::LegacyArithmeticCreateProc(SkReadBuffer& buffer) {
Mike Reed403d1542016-09-26 18:51:24 -0400352 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
Brian Salomon89cb8212017-01-09 10:48:23 -0500353 // skip the unused mode (srcover) field
Mike Reed63544a42017-06-09 17:00:25 -0400354 SkDEBUGCODE(unsigned mode =) unflatten_blendmode(buffer);
reed374772b2016-10-05 17:33:02 -0700355 if (!buffer.isValid()) {
356 return nullptr;
357 }
358 SkASSERT(SkBlendMode::kSrcOver == (SkBlendMode)mode);
Mike Reed403d1542016-09-26 18:51:24 -0400359 float k[4];
360 for (int i = 0; i < 4; ++i) {
361 k[i] = buffer.readScalar();
362 }
363 const bool enforcePMColor = buffer.readBool();
Kevin Lubickdaebae92018-05-17 11:29:10 -0400364 if (!buffer.isValid()) {
365 return nullptr;
366 }
Brian Salomon89cb8212017-01-09 10:48:23 -0500367 return SkArithmeticImageFilter::Make(k[0], k[1], k[2], k[3], enforcePMColor, common.getInput(0),
368 common.getInput(1), &common.cropRect());
Mike Reed403d1542016-09-26 18:51:24 -0400369}
370
371///////////////////////////////////////////////////////////////////////////////////////////////////
372
Mike Reed667a0072016-09-23 11:43:54 -0400373SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermodeImageFilter)
374 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkXfermodeImageFilter_Base)
375 // manually register the legacy serialized name "SkXfermodeImageFilter"
376 SkFlattenable::Register("SkXfermodeImageFilter", SkXfermodeImageFilter_Base::CreateProc,
377 SkFlattenable::kSkImageFilter_Type);
Brian Salomon89cb8212017-01-09 10:48:23 -0500378 // manually register the legacy serialized name "SkArithmeticImageFilter" from when that filter
379 // was implemented as a xfermode image filter.
380 SkFlattenable::Register("SkArithmeticImageFilter",
381 SkXfermodeImageFilter_Base::LegacyArithmeticCreateProc,
382 SkFlattenable::kSkImageFilter_Type);
Mike Reed667a0072016-09-23 11:43:54 -0400383SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END