blob: 682ccea953ce64e0e63506e30c812dda84312a7b [file] [log] [blame]
reed856e9d92015-09-30 12:21:45 -07001/*
2 * Copyright 2015 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
Herb Derbyac04fef2017-01-13 17:34:33 -05008#include "SkArenaAlloc.h"
Mike Kleinf447dee2016-11-29 16:37:12 -05009#include "SkBitmapController.h"
reed856e9d92015-09-30 12:21:45 -070010#include "SkBitmapProcShader.h"
11#include "SkBitmapProvider.h"
reed320a40d2016-08-02 06:12:06 -070012#include "SkColorTable.h"
13#include "SkEmptyShader.h"
reed856e9d92015-09-30 12:21:45 -070014#include "SkImage_Base.h"
15#include "SkImageShader.h"
Mike Klein06a65e22016-11-17 12:39:09 -050016#include "SkPM4fPriv.h"
reed856e9d92015-09-30 12:21:45 -070017#include "SkReadBuffer.h"
18#include "SkWriteBuffer.h"
Mike Klein0a904492017-04-12 12:52:48 -040019#include "../jumper/SkJumper.h"
reed856e9d92015-09-30 12:21:45 -070020
reed6b2d7ac2016-08-11 06:42:26 -070021SkImageShader::SkImageShader(sk_sp<SkImage> img, TileMode tmx, TileMode tmy, const SkMatrix* matrix)
reed856e9d92015-09-30 12:21:45 -070022 : INHERITED(matrix)
reed6b2d7ac2016-08-11 06:42:26 -070023 , fImage(std::move(img))
reed856e9d92015-09-30 12:21:45 -070024 , fTileModeX(tmx)
25 , fTileModeY(tmy)
26{}
27
reed60c9b582016-04-03 09:11:13 -070028sk_sp<SkFlattenable> SkImageShader::CreateProc(SkReadBuffer& buffer) {
reed856e9d92015-09-30 12:21:45 -070029 const TileMode tx = (TileMode)buffer.readUInt();
30 const TileMode ty = (TileMode)buffer.readUInt();
31 SkMatrix matrix;
32 buffer.readMatrix(&matrix);
reeda9ca05c2016-08-11 03:55:15 -070033 sk_sp<SkImage> img = buffer.readImage();
reed856e9d92015-09-30 12:21:45 -070034 if (!img) {
35 return nullptr;
36 }
reed6b2d7ac2016-08-11 06:42:26 -070037 return SkImageShader::Make(std::move(img), tx, ty, &matrix);
reed856e9d92015-09-30 12:21:45 -070038}
39
40void SkImageShader::flatten(SkWriteBuffer& buffer) const {
41 buffer.writeUInt(fTileModeX);
42 buffer.writeUInt(fTileModeY);
43 buffer.writeMatrix(this->getLocalMatrix());
reed6b2d7ac2016-08-11 06:42:26 -070044 buffer.writeImage(fImage.get());
reed856e9d92015-09-30 12:21:45 -070045}
46
47bool SkImageShader::isOpaque() const {
48 return fImage->isOpaque();
49}
50
Herb Derby83e939b2017-02-07 14:25:11 -050051SkShader::Context* SkImageShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
reed320a40d2016-08-02 06:12:06 -070052 return SkBitmapProcLegacyShader::MakeContext(*this, fTileModeX, fTileModeY,
Brian Osman61624f02016-12-09 14:51:59 -050053 SkBitmapProvider(fImage.get(), rec.fDstColorSpace),
Herb Derby83e939b2017-02-07 14:25:11 -050054 rec, alloc);
reed856e9d92015-09-30 12:21:45 -070055}
56
reedf1ac1822016-08-01 11:24:14 -070057SkImage* SkImageShader::onIsAImage(SkMatrix* texM, TileMode xy[]) const {
58 if (texM) {
59 *texM = this->getLocalMatrix();
60 }
61 if (xy) {
62 xy[0] = (TileMode)fTileModeX;
63 xy[1] = (TileMode)fTileModeY;
64 }
65 return const_cast<SkImage*>(fImage.get());
66}
67
Mike Reed627778d2016-09-28 17:13:38 -040068#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP
reedf1ac1822016-08-01 11:24:14 -070069bool SkImageShader::onIsABitmap(SkBitmap* texture, SkMatrix* texM, TileMode xy[]) const {
70 const SkBitmap* bm = as_IB(fImage)->onPeekBitmap();
71 if (!bm) {
72 return false;
73 }
74
75 if (texture) {
76 *texture = *bm;
77 }
78 if (texM) {
79 *texM = this->getLocalMatrix();
80 }
81 if (xy) {
82 xy[0] = (TileMode)fTileModeX;
83 xy[1] = (TileMode)fTileModeY;
84 }
85 return true;
86}
Mike Reed627778d2016-09-28 17:13:38 -040087#endif
reedf1ac1822016-08-01 11:24:14 -070088
reed320a40d2016-08-02 06:12:06 -070089static bool bitmap_is_too_big(int w, int h) {
90 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it
91 // communicates between its matrix-proc and its sampler-proc. Until we can
92 // widen that, we have to reject bitmaps that are larger.
93 //
94 static const int kMaxSize = 65535;
Mike Klein06a65e22016-11-17 12:39:09 -050095
reed320a40d2016-08-02 06:12:06 -070096 return w > kMaxSize || h > kMaxSize;
97}
98
reed6b2d7ac2016-08-11 06:42:26 -070099sk_sp<SkShader> SkImageShader::Make(sk_sp<SkImage> image, TileMode tx, TileMode ty,
Herb Derbybfdc87a2017-02-14 15:06:23 +0000100 const SkMatrix* localMatrix) {
Robert Phillips54be5c92017-02-11 01:19:30 +0000101 if (!image || bitmap_is_too_big(image->width(), image->height())) {
Herb Derbybfdc87a2017-02-14 15:06:23 +0000102 return sk_make_sp<SkEmptyShader>();
reed320a40d2016-08-02 06:12:06 -0700103 } else {
Herb Derbybfdc87a2017-02-14 15:06:23 +0000104 return sk_make_sp<SkImageShader>(image, tx, ty, localMatrix);
reed320a40d2016-08-02 06:12:06 -0700105 }
reed856e9d92015-09-30 12:21:45 -0700106}
107
108#ifndef SK_IGNORE_TO_STRING
109void SkImageShader::toString(SkString* str) const {
110 const char* gTileModeName[SkShader::kTileModeCount] = {
111 "clamp", "repeat", "mirror"
112 };
113
114 str->appendf("ImageShader: ((%s %s) ", gTileModeName[fTileModeX], gTileModeName[fTileModeY]);
115 fImage->toString(str);
116 this->INHERITED::toString(str);
117 str->append(")");
118}
119#endif
120
121///////////////////////////////////////////////////////////////////////////////////////////////////
122
123#if SK_SUPPORT_GPU
124
reed856e9d92015-09-30 12:21:45 -0700125#include "SkGr.h"
Robert Phillips296b1cc2017-03-15 10:42:12 -0400126#include "GrContext.h"
reed856e9d92015-09-30 12:21:45 -0700127#include "effects/GrSimpleTextureEffect.h"
128#include "effects/GrBicubicEffect.h"
129#include "effects/GrSimpleTextureEffect.h"
130
brianosman839345d2016-07-22 11:04:53 -0700131sk_sp<GrFragmentProcessor> SkImageShader::asFragmentProcessor(const AsFPArgs& args) const {
reed856e9d92015-09-30 12:21:45 -0700132
133 SkMatrix lmInverse;
134 if (!this->getLocalMatrix().invert(&lmInverse)) {
135 return nullptr;
136 }
brianosman839345d2016-07-22 11:04:53 -0700137 if (args.fLocalMatrix) {
reed856e9d92015-09-30 12:21:45 -0700138 SkMatrix inv;
brianosman839345d2016-07-22 11:04:53 -0700139 if (!args.fLocalMatrix->invert(&inv)) {
reed856e9d92015-09-30 12:21:45 -0700140 return nullptr;
141 }
142 lmInverse.postConcat(inv);
143 }
reed856e9d92015-09-30 12:21:45 -0700144
145 SkShader::TileMode tm[] = { fTileModeX, fTileModeY };
146
147 // Must set wrap and filter on the sampler before requesting a texture. In two places below
148 // we check the matrix scale factors to determine how to interpret the filter quality setting.
149 // This completely ignores the complexity of the drawVertices case where explicit local coords
150 // are provided by the caller.
151 bool doBicubic;
Brian Salomon514baff2016-11-17 15:17:07 -0500152 GrSamplerParams::FilterMode textureFilterMode =
brianosman839345d2016-07-22 11:04:53 -0700153 GrSkFilterQualityToGrFilterMode(args.fFilterQuality, *args.fViewMatrix, this->getLocalMatrix(),
154 &doBicubic);
Brian Salomon514baff2016-11-17 15:17:07 -0500155 GrSamplerParams params(tm, textureFilterMode);
Brian Osman7992da32016-11-18 11:28:24 -0500156 sk_sp<SkColorSpace> texColorSpace;
Robert Phillips67c18d62017-01-20 12:44:06 -0500157 SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
Robert Phillipsb726d582017-03-09 16:36:32 -0500158 sk_sp<GrTextureProxy> proxy(as_IB(fImage)->asTextureProxyRef(args.fContext, params,
159 args.fDstColorSpace,
160 &texColorSpace, scaleAdjust));
161 if (!proxy) {
reed856e9d92015-09-30 12:21:45 -0700162 return nullptr;
163 }
164
Robert Phillipsb726d582017-03-09 16:36:32 -0500165 bool isAlphaOnly = GrPixelConfigIsAlphaOnly(proxy->config());
166
Robert Phillips67c18d62017-01-20 12:44:06 -0500167 lmInverse.postScale(scaleAdjust[0], scaleAdjust[1]);
168
Brian Osman7992da32016-11-18 11:28:24 -0500169 sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(texColorSpace.get(),
brianosman51924752016-09-12 08:50:19 -0700170 args.fDstColorSpace);
bungeman06ca8ec2016-06-09 08:01:03 -0700171 sk_sp<GrFragmentProcessor> inner;
reed856e9d92015-09-30 12:21:45 -0700172 if (doBicubic) {
Robert Phillips296b1cc2017-03-15 10:42:12 -0400173 inner = GrBicubicEffect::Make(args.fContext->resourceProvider(), std::move(proxy),
174 std::move(colorSpaceXform), lmInverse, tm);
reed856e9d92015-09-30 12:21:45 -0700175 } else {
Robert Phillips296b1cc2017-03-15 10:42:12 -0400176 inner = GrSimpleTextureEffect::Make(args.fContext->resourceProvider(), std::move(proxy),
Robert Phillipsb726d582017-03-09 16:36:32 -0500177 std::move(colorSpaceXform), lmInverse, params);
reed856e9d92015-09-30 12:21:45 -0700178 }
179
Robert Phillipsb726d582017-03-09 16:36:32 -0500180 if (isAlphaOnly) {
bungeman06ca8ec2016-06-09 08:01:03 -0700181 return inner;
reed856e9d92015-09-30 12:21:45 -0700182 }
bungeman06ca8ec2016-06-09 08:01:03 -0700183 return sk_sp<GrFragmentProcessor>(GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)));
reed856e9d92015-09-30 12:21:45 -0700184}
185
186#endif
reed320a40d2016-08-02 06:12:06 -0700187
188///////////////////////////////////////////////////////////////////////////////////////////////////
189#include "SkImagePriv.h"
190
191sk_sp<SkShader> SkMakeBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
192 SkShader::TileMode tmy, const SkMatrix* localMatrix,
Herb Derbybfdc87a2017-02-14 15:06:23 +0000193 SkCopyPixelsMode cpm) {
194 return SkImageShader::Make(SkMakeImageFromRasterBitmap(src, cpm),
195 tmx, tmy, localMatrix);
reed320a40d2016-08-02 06:12:06 -0700196}
197
198static sk_sp<SkFlattenable> SkBitmapProcShader_CreateProc(SkReadBuffer& buffer) {
199 SkMatrix lm;
200 buffer.readMatrix(&lm);
reeda9ca05c2016-08-11 03:55:15 -0700201 sk_sp<SkImage> image = buffer.readBitmapAsImage();
reed320a40d2016-08-02 06:12:06 -0700202 SkShader::TileMode mx = (SkShader::TileMode)buffer.readUInt();
203 SkShader::TileMode my = (SkShader::TileMode)buffer.readUInt();
reeda9ca05c2016-08-11 03:55:15 -0700204 return image ? image->makeShader(mx, my, &lm) : nullptr;
reed320a40d2016-08-02 06:12:06 -0700205}
206
207SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShader)
208SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkImageShader)
209SkFlattenable::Register("SkBitmapProcShader", SkBitmapProcShader_CreateProc, kSkShader_Type);
210SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
211
Mike Klein06a65e22016-11-17 12:39:09 -0500212
Herb Derbyac04fef2017-01-13 17:34:33 -0500213bool SkImageShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* dst, SkArenaAlloc* scratch,
Florin Malita882ccaf2017-01-27 10:51:58 -0500214 const SkMatrix& ctm, const SkPaint& paint,
215 const SkMatrix* localM) const {
Mike Klein06a65e22016-11-17 12:39:09 -0500216 auto matrix = SkMatrix::Concat(ctm, this->getLocalMatrix());
Florin Malita882ccaf2017-01-27 10:51:58 -0500217 if (localM) {
218 matrix.preConcat(*localM);
219 }
220
Mike Klein06a65e22016-11-17 12:39:09 -0500221 if (!matrix.invert(&matrix)) {
222 return false;
223 }
Mike Klein7a14734d2016-11-29 15:33:39 -0500224 auto quality = paint.getFilterQuality();
Mike Klein06a65e22016-11-17 12:39:09 -0500225
Brian Osman61624f02016-12-09 14:51:59 -0500226 SkBitmapProvider provider(fImage.get(), dst);
Mike Kleinb0b17d12016-12-09 16:25:44 -0500227 SkDefaultBitmapController controller(SkDefaultBitmapController::CanShadeHQ::kYes);
Mike Kleinf447dee2016-11-29 16:37:12 -0500228 std::unique_ptr<SkBitmapController::State> state {
229 controller.requestBitmap(provider, matrix, quality)
230 };
231 if (!state) {
232 return false;
233 }
234
235 const SkPixmap& pm = state->pixmap();
236 matrix = state->invMatrix();
237 quality = state->quality();
238 auto info = pm.info();
239
Mike Klein77760292016-11-17 14:04:22 -0500240 // When the matrix is just an integer translate, bilerp == nearest neighbor.
Mike Kleinb0b17d12016-12-09 16:25:44 -0500241 if (quality == kLow_SkFilterQuality &&
242 matrix.getType() <= SkMatrix::kTranslate_Mask &&
Mike Klein77760292016-11-17 14:04:22 -0500243 matrix.getTranslateX() == (int)matrix.getTranslateX() &&
244 matrix.getTranslateY() == (int)matrix.getTranslateY()) {
245 quality = kNone_SkFilterQuality;
246 }
247
Mike Kleinbf178a72016-11-17 15:56:24 -0500248 // See skia:4649 and the GM image_scale_aligned.
Mike Klein06a65e22016-11-17 12:39:09 -0500249 if (quality == kNone_SkFilterQuality) {
250 if (matrix.getScaleX() >= 0) {
251 matrix.setTranslateX(nextafterf(matrix.getTranslateX(),
252 floorf(matrix.getTranslateX())));
253 }
254 if (matrix.getScaleY() >= 0) {
255 matrix.setTranslateY(nextafterf(matrix.getTranslateY(),
256 floorf(matrix.getTranslateY())));
257 }
258 }
259
Mike Klein0a904492017-04-12 12:52:48 -0400260
261 struct MiscCtx {
262 std::unique_ptr<SkBitmapController::State> state;
263 SkColor4f paint_color;
264 float width;
265 float height;
266 float matrix[9];
267 };
268 auto misc = scratch->make<MiscCtx>();
269 misc->state = std::move(state); // Extend lifetime to match the pipeline's.
270 misc->paint_color = SkColor4f_from_SkColor(paint.getColor(), dst);
271 misc->width = (float)pm.width();
272 misc->height = (float)pm.height();
273 if (matrix.asAffine(misc->matrix)) {
274 p->append(SkRasterPipeline::matrix_2x3, misc->matrix);
Mike Kleinc01e7df2016-11-17 16:27:10 -0500275 } else {
Mike Klein0a904492017-04-12 12:52:48 -0400276 matrix.get9(misc->matrix);
277 p->append(SkRasterPipeline::matrix_perspective, misc->matrix);
Mike Kleinc01e7df2016-11-17 16:27:10 -0500278 }
Mike Klein06a65e22016-11-17 12:39:09 -0500279
Mike Klein0a904492017-04-12 12:52:48 -0400280 auto gather = scratch->make<SkJumper_GatherCtx>();
281 gather->pixels = pm.addr();
282 gather->ctable = pm.ctable() ? pm.ctable()->readColors() : nullptr;
283 gather->stride = pm.rowBytesAsPixels();
284
Mike Kleinb04c3522016-11-28 11:55:58 -0500285 auto append_tiling_and_gather = [&] {
Mike Kleinf7f883b2016-11-21 15:09:45 -0500286 switch (fTileModeX) {
Mike Klein0a904492017-04-12 12:52:48 -0400287 case kClamp_TileMode: p->append(SkRasterPipeline::clamp_x, &misc->width); break;
288 case kMirror_TileMode: p->append(SkRasterPipeline::mirror_x, &misc->width); break;
289 case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_x, &misc->width); break;
Mike Kleinf7f883b2016-11-21 15:09:45 -0500290 }
291 switch (fTileModeY) {
Mike Klein0a904492017-04-12 12:52:48 -0400292 case kClamp_TileMode: p->append(SkRasterPipeline::clamp_y, &misc->height); break;
293 case kMirror_TileMode: p->append(SkRasterPipeline::mirror_y, &misc->height); break;
294 case kRepeat_TileMode: p->append(SkRasterPipeline::repeat_y, &misc->height); break;
Mike Kleinf7f883b2016-11-21 15:09:45 -0500295 }
Mike Kleinf7f883b2016-11-21 15:09:45 -0500296 switch (info.colorType()) {
Mike Klein0a904492017-04-12 12:52:48 -0400297 case kAlpha_8_SkColorType: p->append(SkRasterPipeline::gather_a8, gather); break;
298 case kIndex_8_SkColorType: p->append(SkRasterPipeline::gather_i8, gather); break;
299 case kGray_8_SkColorType: p->append(SkRasterPipeline::gather_g8, gather); break;
300 case kRGB_565_SkColorType: p->append(SkRasterPipeline::gather_565, gather); break;
301 case kARGB_4444_SkColorType: p->append(SkRasterPipeline::gather_4444, gather); break;
Mike Kleinf7f883b2016-11-21 15:09:45 -0500302 case kRGBA_8888_SkColorType:
Mike Klein0a904492017-04-12 12:52:48 -0400303 case kBGRA_8888_SkColorType: p->append(SkRasterPipeline::gather_8888, gather); break;
304 case kRGBA_F16_SkColorType: p->append(SkRasterPipeline::gather_f16, gather); break;
Mike Kleinb04c3522016-11-28 11:55:58 -0500305 default: SkASSERT(false);
306 }
307 if (info.gammaCloseToSRGB() && dst != nullptr) {
Mike Kleind37d5d92016-12-14 13:38:24 +0000308 p->append_from_srgb(info.alphaType());
Mike Kleinf7f883b2016-11-21 15:09:45 -0500309 }
310 };
311
Mike Klein0a904492017-04-12 12:52:48 -0400312 SkJumper_SamplerCtx* sampler = nullptr;
313 if (quality != kNone_SkFilterQuality) {
314 sampler = scratch->make<SkJumper_SamplerCtx>();
315 }
316
Mike Kleinb0b17d12016-12-09 16:25:44 -0500317 auto sample = [&](SkRasterPipeline::StockStage setup_x,
318 SkRasterPipeline::StockStage setup_y) {
Mike Klein0a904492017-04-12 12:52:48 -0400319 p->append(setup_x, sampler);
320 p->append(setup_y, sampler);
Mike Klein886cf532016-12-06 11:31:25 -0500321 append_tiling_and_gather();
Mike Klein0a904492017-04-12 12:52:48 -0400322 p->append(SkRasterPipeline::accumulate, sampler);
Mike Klein886cf532016-12-06 11:31:25 -0500323 };
324
Mike Kleinf7f883b2016-11-21 15:09:45 -0500325 if (quality == kNone_SkFilterQuality) {
Mike Kleinb04c3522016-11-28 11:55:58 -0500326 append_tiling_and_gather();
Mike Kleinb0b17d12016-12-09 16:25:44 -0500327 } else if (quality == kLow_SkFilterQuality) {
Mike Klein0a904492017-04-12 12:52:48 -0400328 p->append(SkRasterPipeline::save_xy, sampler);
Mike Kleinb0b17d12016-12-09 16:25:44 -0500329
330 sample(SkRasterPipeline::bilinear_nx, SkRasterPipeline::bilinear_ny);
331 sample(SkRasterPipeline::bilinear_px, SkRasterPipeline::bilinear_ny);
332 sample(SkRasterPipeline::bilinear_nx, SkRasterPipeline::bilinear_py);
333 sample(SkRasterPipeline::bilinear_px, SkRasterPipeline::bilinear_py);
334
335 p->append(SkRasterPipeline::move_dst_src);
Mike Klein46e66a22016-11-21 16:19:34 -0500336 } else {
Mike Klein0a904492017-04-12 12:52:48 -0400337 p->append(SkRasterPipeline::save_xy, sampler);
Mike Kleinb0b17d12016-12-09 16:25:44 -0500338
339 sample(SkRasterPipeline::bicubic_n3x, SkRasterPipeline::bicubic_n3y);
340 sample(SkRasterPipeline::bicubic_n1x, SkRasterPipeline::bicubic_n3y);
341 sample(SkRasterPipeline::bicubic_p1x, SkRasterPipeline::bicubic_n3y);
342 sample(SkRasterPipeline::bicubic_p3x, SkRasterPipeline::bicubic_n3y);
343
344 sample(SkRasterPipeline::bicubic_n3x, SkRasterPipeline::bicubic_n1y);
345 sample(SkRasterPipeline::bicubic_n1x, SkRasterPipeline::bicubic_n1y);
346 sample(SkRasterPipeline::bicubic_p1x, SkRasterPipeline::bicubic_n1y);
347 sample(SkRasterPipeline::bicubic_p3x, SkRasterPipeline::bicubic_n1y);
348
349 sample(SkRasterPipeline::bicubic_n3x, SkRasterPipeline::bicubic_p1y);
350 sample(SkRasterPipeline::bicubic_n1x, SkRasterPipeline::bicubic_p1y);
351 sample(SkRasterPipeline::bicubic_p1x, SkRasterPipeline::bicubic_p1y);
352 sample(SkRasterPipeline::bicubic_p3x, SkRasterPipeline::bicubic_p1y);
353
354 sample(SkRasterPipeline::bicubic_n3x, SkRasterPipeline::bicubic_p3y);
355 sample(SkRasterPipeline::bicubic_n1x, SkRasterPipeline::bicubic_p3y);
356 sample(SkRasterPipeline::bicubic_p1x, SkRasterPipeline::bicubic_p3y);
357 sample(SkRasterPipeline::bicubic_p3x, SkRasterPipeline::bicubic_p3y);
358
Mike Kleinb04c3522016-11-28 11:55:58 -0500359 p->append(SkRasterPipeline::move_dst_src);
Mike Klein06a65e22016-11-17 12:39:09 -0500360 }
361
Mike Kleinf7657e92016-11-29 12:57:22 -0500362 auto effective_color_type = [](SkColorType ct) {
363 return ct == kIndex_8_SkColorType ? kN32_SkColorType : ct;
364 };
365
366 if (effective_color_type(info.colorType()) == kBGRA_8888_SkColorType) {
Mike Klein06a65e22016-11-17 12:39:09 -0500367 p->append(SkRasterPipeline::swap_rb);
368 }
Mike Klein7a14734d2016-11-29 15:33:39 -0500369 if (info.colorType() == kAlpha_8_SkColorType) {
Mike Klein0a904492017-04-12 12:52:48 -0400370 p->append(SkRasterPipeline::set_rgb, &misc->paint_color);
Mike Klein7a14734d2016-11-29 15:33:39 -0500371 }
372 if (info.colorType() == kAlpha_8_SkColorType || info.alphaType() == kUnpremul_SkAlphaType) {
Mike Klein06a65e22016-11-17 12:39:09 -0500373 p->append(SkRasterPipeline::premul);
374 }
Mike Kleinb0b17d12016-12-09 16:25:44 -0500375 if (quality > kLow_SkFilterQuality) {
376 // Bicubic filtering naturally produces out of range values on both sides.
377 p->append(SkRasterPipeline::clamp_0);
378 p->append(SkRasterPipeline::clamp_a);
379 }
Mike Kleinee2d9df2017-05-08 21:56:55 -0400380 append_gamut_transform(p, scratch, info.colorSpace(), dst);
381 return true;
Mike Klein06a65e22016-11-17 12:39:09 -0500382}