blob: fc99118e424ed087e6240b1744114d916ac567a3 [file] [log] [blame]
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +00001/*
2 * Copyright 2014 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 Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/shaders/SkPictureShader.h"
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +00009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkBitmap.h"
11#include "include/core/SkCanvas.h"
12#include "include/core/SkImage.h"
Ben Wagner729a23f2019-05-17 16:29:34 -040013#include "src/core/SkArenaAlloc.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/core/SkMatrixUtils.h"
15#include "src/core/SkPicturePriv.h"
16#include "src/core/SkReadBuffer.h"
17#include "src/core/SkResourceCache.h"
18#include "src/shaders/SkBitmapProcShader.h"
19#include "src/shaders/SkImageShader.h"
Mike Klein0ec1c572018-12-04 11:52:51 -050020#include <atomic>
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +000021
22#if SK_SUPPORT_GPU
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "include/private/GrRecordingContext.h"
24#include "src/gpu/GrCaps.h"
Brian Salomon4bc0c1f2019-09-30 15:12:27 -040025#include "src/gpu/GrColorInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/gpu/GrFragmentProcessor.h"
27#include "src/gpu/GrRecordingContextPriv.h"
28#include "src/gpu/SkGr.h"
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +000029#endif
30
Mike Reede25b4472019-04-02 17:49:12 -040031sk_sp<SkShader> SkPicture::makeShader(SkTileMode tmx, SkTileMode tmy, const SkMatrix* localMatrix,
32 const SkRect* tile) const {
33 if (localMatrix && !localMatrix->invert(nullptr)) {
34 return nullptr;
35 }
36 return SkPictureShader::Make(sk_ref_sp(this), tmx, tmy, localMatrix, tile);
37}
38
39sk_sp<SkShader> SkPicture::makeShader(SkTileMode tmx, SkTileMode tmy,
40 const SkMatrix* localMatrix) const {
41 return this->makeShader(tmx, tmy, localMatrix, nullptr);
42}
43
fmalita171e5b72014-10-22 11:20:40 -070044namespace {
Brian Osmane1552a52018-10-18 10:40:37 -040045static unsigned gBitmapShaderKeyNamespaceLabel;
fmalita171e5b72014-10-22 11:20:40 -070046
fmalita23df2d62014-10-22 07:39:08 -070047struct BitmapShaderKey : public SkResourceCache::Key {
48public:
Brian Osmane1552a52018-10-18 10:40:37 -040049 BitmapShaderKey(SkColorSpace* colorSpace,
Brian Osman2e8f48e2018-10-19 13:50:48 -040050 SkImage::BitDepth bitDepth,
Florin Malitab00a3602017-07-13 22:34:04 -040051 uint32_t shaderID,
Brian Osmane1552a52018-10-18 10:40:37 -040052 const SkSize& scale)
53 : fColorSpaceXYZHash(colorSpace->toXYZD50Hash())
54 , fColorSpaceTransferFnHash(colorSpace->transferFnHash())
Brian Osman2e8f48e2018-10-19 13:50:48 -040055 , fBitDepth(bitDepth)
Brian Osmane1552a52018-10-18 10:40:37 -040056 , fScale(scale) {
fmalita04b49c32014-12-10 13:01:43 -080057
Brian Osmane1552a52018-10-18 10:40:37 -040058 static const size_t keySize = sizeof(fColorSpaceXYZHash) +
59 sizeof(fColorSpaceTransferFnHash) +
Brian Osman2e8f48e2018-10-19 13:50:48 -040060 sizeof(fBitDepth) +
Brian Osmane1552a52018-10-18 10:40:37 -040061 sizeof(fScale);
fmalita23df2d62014-10-22 07:39:08 -070062 // This better be packed.
Brian Osmane1552a52018-10-18 10:40:37 -040063 SkASSERT(sizeof(uint32_t) * (&fEndOfStruct - &fColorSpaceXYZHash) == keySize);
64 this->init(&gBitmapShaderKeyNamespaceLabel, MakeSharedID(shaderID), keySize);
Florin Malitab00a3602017-07-13 22:34:04 -040065 }
66
67 static uint64_t MakeSharedID(uint32_t shaderID) {
68 uint64_t sharedID = SkSetFourByteTag('p', 's', 'd', 'r');
69 return (sharedID << 32) | shaderID;
fmalita23df2d62014-10-22 07:39:08 -070070 }
71
72private:
Brian Osmane1552a52018-10-18 10:40:37 -040073 uint32_t fColorSpaceXYZHash;
74 uint32_t fColorSpaceTransferFnHash;
Brian Osman2e8f48e2018-10-19 13:50:48 -040075 SkImage::BitDepth fBitDepth;
Matt Sarett28a7ad22017-04-21 15:12:34 -040076 SkSize fScale;
fmalita23df2d62014-10-22 07:39:08 -070077
78 SkDEBUGCODE(uint32_t fEndOfStruct;)
79};
80
81struct BitmapShaderRec : public SkResourceCache::Rec {
fmalitac9a9ca92016-10-12 13:43:43 -070082 BitmapShaderRec(const BitmapShaderKey& key, SkShader* tileShader)
fmalita23df2d62014-10-22 07:39:08 -070083 : fKey(key)
fmalitac9a9ca92016-10-12 13:43:43 -070084 , fShader(SkRef(tileShader)) {}
fmalita23df2d62014-10-22 07:39:08 -070085
Hal Canary704cd322016-11-07 14:13:52 -050086 BitmapShaderKey fKey;
87 sk_sp<SkShader> fShader;
fmalita23df2d62014-10-22 07:39:08 -070088
mtklein36352bf2015-03-25 18:17:31 -070089 const Key& getKey() const override { return fKey; }
90 size_t bytesUsed() const override {
Brian Osmanbd659552018-09-11 10:03:19 -040091 // Just the record overhead -- the actual pixels are accounted by SkImage_Lazy.
fmalitac9a9ca92016-10-12 13:43:43 -070092 return sizeof(fKey) + sizeof(SkImageShader);
fmalita23df2d62014-10-22 07:39:08 -070093 }
reed216b6432015-08-19 12:25:40 -070094 const char* getCategory() const override { return "bitmap-shader"; }
95 SkDiscardableMemory* diagnostic_only_getDiscardable() const override { return nullptr; }
fmalita23df2d62014-10-22 07:39:08 -070096
97 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextShader) {
98 const BitmapShaderRec& rec = static_cast<const BitmapShaderRec&>(baseRec);
Hal Canary704cd322016-11-07 14:13:52 -050099 sk_sp<SkShader>* result = reinterpret_cast<sk_sp<SkShader>*>(contextShader);
fmalita23df2d62014-10-22 07:39:08 -0700100
Hal Canary704cd322016-11-07 14:13:52 -0500101 *result = rec.fShader;
fmalita387a01a2014-12-10 12:17:58 -0800102
fmalitaddc4b462015-08-31 19:54:03 -0700103 // The bitmap shader is backed by an image generator, thus it can always re-generate its
104 // pixels if discarded.
105 return true;
fmalita23df2d62014-10-22 07:39:08 -0700106 }
107};
108
Florin Malitab00a3602017-07-13 22:34:04 -0400109uint32_t next_id() {
Mike Klein0ec1c572018-12-04 11:52:51 -0500110 static std::atomic<uint32_t> nextID{1};
111
112 uint32_t id;
Florin Malitab00a3602017-07-13 22:34:04 -0400113 do {
Mike Klein0ec1c572018-12-04 11:52:51 -0500114 id = nextID++;
Florin Malitab00a3602017-07-13 22:34:04 -0400115 } while (id == SK_InvalidGenID);
Mike Klein0ec1c572018-12-04 11:52:51 -0500116 return id;
Florin Malitab00a3602017-07-13 22:34:04 -0400117}
118
fmalita171e5b72014-10-22 11:20:40 -0700119} // namespace
120
Mike Reedfae8fce2019-04-03 10:27:45 -0400121SkPictureShader::SkPictureShader(sk_sp<SkPicture> picture, SkTileMode tmx, SkTileMode tmy,
Brian Osmanf9666f52019-03-21 12:35:02 -0400122 const SkMatrix* localMatrix, const SkRect* tile)
commit-bot@chromium.org5aacfe92014-05-02 21:23:52 +0000123 : INHERITED(localMatrix)
reed8a21c9f2016-03-08 18:50:00 -0800124 , fPicture(std::move(picture))
125 , fTile(tile ? *tile : fPicture->cullRect())
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000126 , fTmx(tmx)
Matt Sarett28a7ad22017-04-21 15:12:34 -0400127 , fTmy(tmy)
Florin Malitab00a3602017-07-13 22:34:04 -0400128 , fUniqueID(next_id())
129 , fAddedToCache(false) {}
130
131SkPictureShader::~SkPictureShader() {
132 if (fAddedToCache.load()) {
133 SkResourceCache::PostPurgeSharedID(BitmapShaderKey::MakeSharedID(fUniqueID));
134 }
135}
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000136
Mike Reede25b4472019-04-02 17:49:12 -0400137sk_sp<SkShader> SkPictureShader::Make(sk_sp<SkPicture> picture, SkTileMode tmx, SkTileMode tmy,
reed8a21c9f2016-03-08 18:50:00 -0800138 const SkMatrix* localMatrix, const SkRect* tile) {
Robert Phillips54be5c92017-02-11 01:19:30 +0000139 if (!picture || picture->cullRect().isEmpty() || (tile && tile->isEmpty())) {
Mike Reedc8bea7d2019-04-09 13:55:36 -0400140 return SkShaders::Empty();
commit-bot@chromium.org855e88e2014-04-21 19:33:12 +0000141 }
Mike Reedfae8fce2019-04-03 10:27:45 -0400142 return sk_sp<SkShader>(new SkPictureShader(std::move(picture), tmx, tmy, localMatrix, tile));
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000143}
144
Hal Canary8a64fa62019-05-30 10:29:40 -0400145SkPicture* SkPictureShader::isAPicture(SkMatrix* matrix,
146 SkTileMode tileModes[2],
147 SkRect* tile) const {
148 if (matrix) {
149 *matrix = this->getLocalMatrix();
150 }
151 if (tileModes) {
152 tileModes[0] = fTmx;
153 tileModes[1] = fTmy;
154 }
155 if (tile) {
156 *tile = fTile;
157 }
158 return fPicture.get();
159}
160
reed60c9b582016-04-03 09:11:13 -0700161sk_sp<SkFlattenable> SkPictureShader::CreateProc(SkReadBuffer& buffer) {
reed9fa60da2014-08-21 07:59:51 -0700162 SkMatrix lm;
163 buffer.readMatrix(&lm);
Mike Reede25b4472019-04-02 17:49:12 -0400164 auto tmx = buffer.read32LE(SkTileMode::kLastTileMode);
165 auto tmy = buffer.read32LE(SkTileMode::kLastTileMode);
reed9fa60da2014-08-21 07:59:51 -0700166 SkRect tile;
167 buffer.readRect(&tile);
mtklein76be9c82015-05-20 12:05:15 -0700168
reed8a21c9f2016-03-08 18:50:00 -0800169 sk_sp<SkPicture> picture;
hendrikw446ee672015-06-16 09:28:37 -0700170
Mike Reed5a0f3452018-01-19 08:25:11 -0500171 bool didSerialize = buffer.readBool();
172 if (didSerialize) {
Cary Clarkefd99cc2018-06-11 16:25:43 -0400173 picture = SkPicturePriv::MakeFromBuffer(buffer);
mtklein76be9c82015-05-20 12:05:15 -0700174 }
Mike Reede25b4472019-04-02 17:49:12 -0400175 return SkPictureShader::Make(picture, tmx, tmy, &lm, &tile);
reed9fa60da2014-08-21 07:59:51 -0700176}
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000177
reed9fa60da2014-08-21 07:59:51 -0700178void SkPictureShader::flatten(SkWriteBuffer& buffer) const {
179 buffer.writeMatrix(this->getLocalMatrix());
Mike Reedfae8fce2019-04-03 10:27:45 -0400180 buffer.write32((unsigned)fTmx);
181 buffer.write32((unsigned)fTmy);
fmalitab5f78262014-08-06 13:07:15 -0700182 buffer.writeRect(fTile);
mtklein76be9c82015-05-20 12:05:15 -0700183
Mike Reed5a0f3452018-01-19 08:25:11 -0500184 buffer.writeBool(true);
Cary Clarkefd99cc2018-06-11 16:25:43 -0400185 SkPicturePriv::Flatten(fPicture, buffer);
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000186}
187
Florin Malita8f88d892018-04-19 21:07:19 -0400188// Returns a cached image shader, which wraps a single picture tile at the given
189// CTM/local matrix. Also adjusts the local matrix for tile scaling.
Florin Malita18f7e0a2018-02-06 16:49:40 -0500190sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix,
Florin Malita8f88d892018-04-19 21:07:19 -0400191 SkTCopyOnFirstWrite<SkMatrix>* localMatrix,
Brian Osman2e8f48e2018-10-19 13:50:48 -0400192 SkColorType dstColorType,
Brian Osman138ea972016-12-16 11:55:18 -0500193 SkColorSpace* dstColorSpace,
reed8a21c9f2016-03-08 18:50:00 -0800194 const int maxTextureSize) const {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700195 SkASSERT(fPicture && !fPicture->cullRect().isEmpty());
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000196
Florin Malita8f88d892018-04-19 21:07:19 -0400197 const SkMatrix m = SkMatrix::Concat(viewMatrix, **localMatrix);
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000198
199 // Use a rotation-invariant scale
200 SkPoint scale;
reedadf99902015-03-19 16:10:54 -0700201 //
202 // TODO: replace this with decomposeScale() -- but beware LayoutTest rebaselines!
203 //
halcanary96fcdcc2015-08-27 07:41:13 -0700204 if (!SkDecomposeUpper2x2(m, nullptr, &scale, nullptr)) {
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000205 // Decomposition failed, use an approximation.
206 scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m.getSkewX()),
207 SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m.getSkewY()));
208 }
fmalitab0878792015-01-15 10:45:56 -0800209 SkSize scaledSize = SkSize::Make(SkScalarAbs(scale.x() * fTile.width()),
210 SkScalarAbs(scale.y() * fTile.height()));
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000211
fmalita511005b2015-03-13 06:50:44 -0700212 // Clamp the tile size to about 4M pixels
213 static const SkScalar kMaxTileArea = 2048 * 2048;
Mike Reeda99b6ce2017-02-04 11:04:26 -0500214 SkScalar tileArea = scaledSize.width() * scaledSize.height();
fmalitabb204f42014-08-07 08:39:24 -0700215 if (tileArea > kMaxTileArea) {
reed80ea19c2015-05-12 10:37:34 -0700216 SkScalar clampScale = SkScalarSqrt(kMaxTileArea / tileArea);
Mike Reeda99b6ce2017-02-04 11:04:26 -0500217 scaledSize.set(scaledSize.width() * clampScale,
218 scaledSize.height() * clampScale);
fmalitabb204f42014-08-07 08:39:24 -0700219 }
gen.kimb9ed8842015-05-03 22:36:30 -0700220#if SK_SUPPORT_GPU
221 // Scale down the tile size if larger than maxTextureSize for GPU Path or it should fail on create texture
222 if (maxTextureSize) {
223 if (scaledSize.width() > maxTextureSize || scaledSize.height() > maxTextureSize) {
ericrkf469fc02015-10-14 17:33:29 -0700224 SkScalar downScale = maxTextureSize / SkMaxScalar(scaledSize.width(), scaledSize.height());
Mike Reeda99b6ce2017-02-04 11:04:26 -0500225 scaledSize.set(SkScalarFloorToScalar(scaledSize.width() * downScale),
226 SkScalarFloorToScalar(scaledSize.height() * downScale));
gen.kimb9ed8842015-05-03 22:36:30 -0700227 }
228 }
229#endif
fmalitabb204f42014-08-07 08:39:24 -0700230
fmalita85c6f982016-02-29 09:18:31 -0800231 const SkISize tileSize = scaledSize.toCeil();
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000232 if (tileSize.isEmpty()) {
Mike Reedc8bea7d2019-04-09 13:55:36 -0400233 return SkShaders::Empty();
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000234 }
235
fmalitabb204f42014-08-07 08:39:24 -0700236 // The actual scale, compensating for rounding & clamping.
fmalita85c6f982016-02-29 09:18:31 -0800237 const SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fTile.width(),
238 SkIntToScalar(tileSize.height()) / fTile.height());
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000239
Matt Sarett28a7ad22017-04-21 15:12:34 -0400240
Brian Osmanf9666f52019-03-21 12:35:02 -0400241 sk_sp<SkColorSpace> imgCS = dstColorSpace ? sk_ref_sp(dstColorSpace): SkColorSpace::MakeSRGB();
Brian Osman2e8f48e2018-10-19 13:50:48 -0400242 SkImage::BitDepth bitDepth =
Brian Osmandfddf342019-03-07 13:33:45 -0500243 dstColorType >= kRGBA_F16Norm_SkColorType
Brian Osman2e8f48e2018-10-19 13:50:48 -0400244 ? SkImage::BitDepth::kF16 : SkImage::BitDepth::kU8;
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000245
Brian Osman2e8f48e2018-10-19 13:50:48 -0400246 BitmapShaderKey key(imgCS.get(), bitDepth, fUniqueID, tileScale);
247
248 sk_sp<SkShader> tileShader;
fmalita171e5b72014-10-22 11:20:40 -0700249 if (!SkResourceCache::Find(key, BitmapShaderRec::Visitor, &tileShader)) {
robertphillips25a5b0d2015-09-28 09:32:50 -0700250 SkMatrix tileMatrix;
251 tileMatrix.setRectToRect(fTile, SkRect::MakeIWH(tileSize.width(), tileSize.height()),
fmalita1b46a572016-02-01 02:34:03 -0800252 SkMatrix::kFill_ScaleToFit);
253
Brian Osmane1552a52018-10-18 10:40:37 -0400254 sk_sp<SkImage> tileImage = SkImage::MakeFromPicture(fPicture, tileSize, &tileMatrix,
Brian Osman2e8f48e2018-10-19 13:50:48 -0400255 nullptr, bitDepth, std::move(imgCS));
fmalita1b46a572016-02-01 02:34:03 -0800256 if (!tileImage) {
fmalitaddc4b462015-08-31 19:54:03 -0700257 return nullptr;
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000258 }
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000259
Florin Malita18f7e0a2018-02-06 16:49:40 -0500260 tileShader = tileImage->makeShader(fTmx, fTmy);
fmalita23df2d62014-10-22 07:39:08 -0700261
fmalitac9a9ca92016-10-12 13:43:43 -0700262 SkResourceCache::Add(new BitmapShaderRec(key, tileShader.get()));
Florin Malitab00a3602017-07-13 22:34:04 -0400263 fAddedToCache.store(true);
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000264 }
265
Florin Malita8f88d892018-04-19 21:07:19 -0400266 if (tileScale.width() != 1 || tileScale.height() != 1) {
267 localMatrix->writable()->preScale(1 / tileScale.width(), 1 / tileScale.height());
268 }
Florin Malita18f7e0a2018-02-06 16:49:40 -0500269
reed8a21c9f2016-03-08 18:50:00 -0800270 return tileShader;
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000271}
272
Mike Reed1386b2d2019-03-13 21:15:05 -0400273bool SkPictureShader::onAppendStages(const SkStageRec& rec) const {
Florin Malitac6c5ead2018-04-11 15:33:40 -0400274 auto lm = this->totalLocalMatrix(rec.fLocalM);
Florin Malitac6c5ead2018-04-11 15:33:40 -0400275
Yuqian Li8d2fb472017-01-30 11:33:46 -0500276 // Keep bitmapShader alive by using alloc instead of stack memory
Mike Reed1d8c42e2017-08-29 14:58:19 -0400277 auto& bitmapShader = *rec.fAlloc->make<sk_sp<SkShader>>();
Brian Osman2e8f48e2018-10-19 13:50:48 -0400278 bitmapShader = this->refBitmapShader(rec.fCTM, &lm, rec.fDstColorType, rec.fDstCS);
Florin Malitac6c5ead2018-04-11 15:33:40 -0400279
280 if (!bitmapShader) {
281 return false;
282 }
283
Mike Reed1386b2d2019-03-13 21:15:05 -0400284 SkStageRec localRec = rec;
Florin Malitac6c5ead2018-04-11 15:33:40 -0400285 localRec.fLocalM = lm->isIdentity() ? nullptr : lm.get();
Florin Malita18f7e0a2018-02-06 16:49:40 -0500286
Florin Malitac6c5ead2018-04-11 15:33:40 -0400287 return as_SB(bitmapShader)->appendStages(localRec);
Yuqian Li8d2fb472017-01-30 11:33:46 -0500288}
289
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000290/////////////////////////////////////////////////////////////////////////////////////////
Mike Reede92aae62018-10-17 10:21:51 -0400291
292#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
Florin Malita4aed1382017-05-25 10:38:07 -0400293SkShaderBase::Context* SkPictureShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc)
Herb Derby83e939b2017-02-07 14:25:11 -0500294const {
Florin Malitac6c5ead2018-04-11 15:33:40 -0400295 auto lm = this->totalLocalMatrix(rec.fLocalMatrix);
Brian Osman2e8f48e2018-10-19 13:50:48 -0400296 sk_sp<SkShader> bitmapShader = this->refBitmapShader(*rec.fMatrix, &lm, rec.fDstColorType,
297 rec.fDstColorSpace);
Herb Derby83e939b2017-02-07 14:25:11 -0500298 if (!bitmapShader) {
299 return nullptr;
300 }
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000301
Florin Malita18f7e0a2018-02-06 16:49:40 -0500302 ContextRec localRec = rec;
Florin Malitac6c5ead2018-04-11 15:33:40 -0400303 localRec.fLocalMatrix = lm->isIdentity() ? nullptr : lm.get();
Florin Malita18f7e0a2018-02-06 16:49:40 -0500304
Herb Derby83e939b2017-02-07 14:25:11 -0500305 PictureShaderContext* ctx =
Florin Malita18f7e0a2018-02-06 16:49:40 -0500306 alloc->make<PictureShaderContext>(*this, localRec, std::move(bitmapShader), alloc);
halcanary96fcdcc2015-08-27 07:41:13 -0700307 if (nullptr == ctx->fBitmapShaderContext) {
halcanary96fcdcc2015-08-27 07:41:13 -0700308 ctx = nullptr;
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000309 }
310 return ctx;
311}
Mike Reede92aae62018-10-17 10:21:51 -0400312#endif
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000313
Herb Derby83e939b2017-02-07 14:25:11 -0500314/////////////////////////////////////////////////////////////////////////////////////////
315
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000316SkPictureShader::PictureShaderContext::PictureShaderContext(
Herb Derby83e939b2017-02-07 14:25:11 -0500317 const SkPictureShader& shader, const ContextRec& rec, sk_sp<SkShader> bitmapShader,
318 SkArenaAlloc* alloc)
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000319 : INHERITED(shader, rec)
reed8a21c9f2016-03-08 18:50:00 -0800320 , fBitmapShader(std::move(bitmapShader))
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000321{
Florin Malita4aed1382017-05-25 10:38:07 -0400322 fBitmapShaderContext = as_SB(fBitmapShader)->makeContext(rec, alloc);
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000323 //if fBitmapShaderContext is null, we are invalid
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000324}
325
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000326uint32_t SkPictureShader::PictureShaderContext::getFlags() const {
commit-bot@chromium.orgce56d962014-05-05 18:39:18 +0000327 SkASSERT(fBitmapShaderContext);
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000328 return fBitmapShaderContext->getFlags();
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000329}
330
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000331void SkPictureShader::PictureShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
332 SkASSERT(fBitmapShaderContext);
333 fBitmapShaderContext->shadeSpan(x, y, dstC, count);
334}
335
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000336#if SK_SUPPORT_GPU
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500337#include "include/gpu/GrContext.h"
338#include "src/gpu/GrContextPriv.h"
Robert Phillips1efecea2019-02-15 16:58:40 -0500339
Brian Salomonaff329b2017-08-11 09:40:37 -0400340std::unique_ptr<GrFragmentProcessor> SkPictureShader::asFragmentProcessor(
Mike Reede3429e62018-01-19 11:43:34 -0500341 const GrFPArgs& args) const {
gen.kimb9ed8842015-05-03 22:36:30 -0700342 int maxTextureSize = 0;
brianosman839345d2016-07-22 11:04:53 -0700343 if (args.fContext) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500344 maxTextureSize = args.fContext->priv().caps()->maxTextureSize();
gen.kimb9ed8842015-05-03 22:36:30 -0700345 }
Florin Malitac6c5ead2018-04-11 15:33:40 -0400346
347 auto lm = this->totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix);
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400348 SkColorType dstColorType = GrColorTypeToSkColorType(args.fDstColorInfo->colorType());
Brian Salomonbd3d8d32019-07-02 09:16:28 -0400349 if (dstColorType == kUnknown_SkColorType) {
350 dstColorType = kRGBA_8888_SkColorType;
351 }
Brian Osman2e8f48e2018-10-19 13:50:48 -0400352 sk_sp<SkShader> bitmapShader(this->refBitmapShader(*args.fViewMatrix, &lm, dstColorType,
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400353 args.fDstColorInfo->colorSpace(),
Florin Malita8f88d892018-04-19 21:07:19 -0400354 maxTextureSize));
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000355 if (!bitmapShader) {
bsalomonc21b09e2015-08-28 18:46:56 -0700356 return nullptr;
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000357 }
Florin Malita18f7e0a2018-02-06 16:49:40 -0500358
Florin Malitac6c5ead2018-04-11 15:33:40 -0400359 // We want to *reset* args.fPreLocalMatrix, not compose it.
Brian Salomon4bc0c1f2019-09-30 15:12:27 -0400360 GrFPArgs newArgs(args.fContext, args.fViewMatrix, args.fFilterQuality, args.fDstColorInfo);
Florin Malitac6c5ead2018-04-11 15:33:40 -0400361 newArgs.fPreLocalMatrix = lm.get();
362
363 return as_SB(bitmapShader)->asFragmentProcessor(newArgs);
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000364}
365#endif