1c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org/*
2c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org * Copyright 2014 Google Inc.
3c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org *
4c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
5c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org * found in the LICENSE file.
6c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org */
7c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
8c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "SkPictureShader.h"
9c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
10c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "SkBitmap.h"
11c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "SkBitmapProcShader.h"
12c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "SkCanvas.h"
13c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "SkMatrixUtils.h"
14c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "SkPicture.h"
15c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "SkReadBuffer.h"
1623df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita#include "SkResourceCache.h"
17c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
18c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#if SK_SUPPORT_GPU
19c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#include "GrContext.h"
20c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#endif
21c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
22171e5b73a862418f4acd61faf8cecfbc8f58694cfmalitanamespace {
23171e5b73a862418f4acd61faf8cecfbc8f58694cfmalitastatic unsigned gBitmapSkaderKeyNamespaceLabel;
24171e5b73a862418f4acd61faf8cecfbc8f58694cfmalita
2523df2d693304824a2ce7ac3d988b0e48fec1c49dfmalitastruct BitmapShaderKey : public SkResourceCache::Key {
2623df2d693304824a2ce7ac3d988b0e48fec1c49dfmalitapublic:
2723df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    BitmapShaderKey(uint32_t pictureID,
2823df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                    const SkRect& tile,
2923df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                    SkShader::TileMode tmx,
3023df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                    SkShader::TileMode tmy,
3123df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                    const SkSize& scale,
3223df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                    const SkMatrix& localMatrix)
3323df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        : fPictureID(pictureID)
3423df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        , fTile(tile)
3523df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        , fTmx(tmx)
3623df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        , fTmy(tmy)
3704b49c31789201fbef969f5598a286187920dd56fmalita        , fScale(scale) {
3804b49c31789201fbef969f5598a286187920dd56fmalita
3904b49c31789201fbef969f5598a286187920dd56fmalita        for (int i = 0; i < 9; ++i) {
4004b49c31789201fbef969f5598a286187920dd56fmalita            fLocalMatrixStorage[i] = localMatrix[i];
4104b49c31789201fbef969f5598a286187920dd56fmalita        }
4223df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
4323df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        static const size_t keySize = sizeof(fPictureID) +
4423df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                                      sizeof(fTile) +
4523df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                                      sizeof(fTmx) + sizeof(fTmy) +
4623df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                                      sizeof(fScale) +
4704b49c31789201fbef969f5598a286187920dd56fmalita                                      sizeof(fLocalMatrixStorage);
4823df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        // This better be packed.
4923df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        SkASSERT(sizeof(uint32_t) * (&fEndOfStruct - &fPictureID) == keySize);
507eeba2587760a0802fd2b90765b4fd0e5e895375reed        this->init(&gBitmapSkaderKeyNamespaceLabel, 0, keySize);
5123df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    }
5223df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
5323df2d693304824a2ce7ac3d988b0e48fec1c49dfmalitaprivate:
5423df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    uint32_t           fPictureID;
5523df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    SkRect             fTile;
5623df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    SkShader::TileMode fTmx, fTmy;
5723df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    SkSize             fScale;
5804b49c31789201fbef969f5598a286187920dd56fmalita    SkScalar           fLocalMatrixStorage[9];
5923df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
6023df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    SkDEBUGCODE(uint32_t fEndOfStruct;)
6123df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita};
6223df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
6323df2d693304824a2ce7ac3d988b0e48fec1c49dfmalitastruct BitmapShaderRec : public SkResourceCache::Rec {
6423df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    BitmapShaderRec(const BitmapShaderKey& key, SkShader* tileShader, size_t bitmapBytes)
6523df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        : fKey(key)
6623df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        , fShader(SkRef(tileShader))
6723df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        , fBitmapBytes(bitmapBytes) {}
6823df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
6923df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    BitmapShaderKey        fKey;
7023df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    SkAutoTUnref<SkShader> fShader;
7123df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    size_t                 fBitmapBytes;
7223df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
7336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const Key& getKey() const override { return fKey; }
7436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    size_t bytesUsed() const override {
7523df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        return sizeof(fKey) + sizeof(SkShader) + fBitmapBytes;
7623df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    }
7723df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
7823df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextShader) {
7923df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        const BitmapShaderRec& rec = static_cast<const BitmapShaderRec&>(baseRec);
8023df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        SkAutoTUnref<SkShader>* result = reinterpret_cast<SkAutoTUnref<SkShader>*>(contextShader);
8123df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
8223df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        result->reset(SkRef(rec.fShader.get()));
83387a01a6357b4ba6ff87ac57626de1cb6a3b31bffmalita
84f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        SkBitmap tile;
85f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        rec.fShader.get()->asABitmap(&tile, NULL, NULL);
86f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        // FIXME: this doesn't protect the pixels from being discarded as soon as we unlock.
87f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        // Should be handled via a pixel ref generator instead
88f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        // (https://code.google.com/p/skia/issues/detail?id=3220).
89f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        SkAutoLockPixels alp(tile, true);
90f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        return tile.getPixels() != NULL;
9123df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    }
9223df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita};
9323df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
94f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalitastatic bool cache_try_alloc_pixels(SkBitmap* bitmap) {
95f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita    SkBitmap::Allocator* allocator = SkResourceCache::GetAllocator();
96f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita
97f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita    return NULL != allocator
98f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        ? allocator->allocPixelRef(bitmap, NULL)
99f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        : bitmap->tryAllocPixels();
100f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita}
101f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita
102171e5b73a862418f4acd61faf8cecfbc8f58694cfmalita} // namespace
103171e5b73a862418f4acd61faf8cecfbc8f58694cfmalita
104e8464994bbcc797b47a5ee24aa513530d2bade3brobertphillipsSkPictureShader::SkPictureShader(const SkPicture* picture, TileMode tmx, TileMode tmy,
105b5f7826c51af2862aebcabe61e1ba684f925e488fmalita                                 const SkMatrix* localMatrix, const SkRect* tile)
1065aacfe9ffcf1849727dca6761b4a221bd4315f26commit-bot@chromium.org    : INHERITED(localMatrix)
1075aacfe9ffcf1849727dca6761b4a221bd4315f26commit-bot@chromium.org    , fPicture(SkRef(picture))
10849f085dddff10473b6ebf832a974288300224e60bsalomon    , fTile(tile ? *tile : picture->cullRect())
109c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    , fTmx(tmx)
110b5f7826c51af2862aebcabe61e1ba684f925e488fmalita    , fTmy(tmy) {
111b5f7826c51af2862aebcabe61e1ba684f925e488fmalita}
112c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
113f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalitaSkPictureShader::~SkPictureShader() {
114f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita    fPicture->unref();
115f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita}
116f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita
117e8464994bbcc797b47a5ee24aa513530d2bade3brobertphillipsSkPictureShader* SkPictureShader::Create(const SkPicture* picture, TileMode tmx, TileMode tmy,
118b5f7826c51af2862aebcabe61e1ba684f925e488fmalita                                         const SkMatrix* localMatrix, const SkRect* tile) {
11949f085dddff10473b6ebf832a974288300224e60bsalomon    if (!picture || picture->cullRect().isEmpty() || (tile && tile->isEmpty())) {
120855e88edfafe4b3892e99f932c38fa7433b2fcbecommit-bot@chromium.org        return NULL;
121855e88edfafe4b3892e99f932c38fa7433b2fcbecommit-bot@chromium.org    }
122b5f7826c51af2862aebcabe61e1ba684f925e488fmalita    return SkNEW_ARGS(SkPictureShader, (picture, tmx, tmy, localMatrix, tile));
123c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
124c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
1259fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkPictureShader::CreateProc(SkReadBuffer& buffer) {
1269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkMatrix lm;
1279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.readMatrix(&lm);
1289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    TileMode mx = (TileMode)buffer.read32();
1299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    TileMode my = (TileMode)buffer.read32();
1309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkRect tile;
1319fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.readRect(&tile);
1329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkPicture> picture(SkPicture::CreateFromBuffer(buffer));
1339fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkPictureShader::Create(picture, mx, my, &lm, &tile);
1349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
135c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
1369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedvoid SkPictureShader::flatten(SkWriteBuffer& buffer) const {
1379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.writeMatrix(this->getLocalMatrix());
138c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    buffer.write32(fTmx);
139c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    buffer.write32(fTmy);
140b5f7826c51af2862aebcabe61e1ba684f925e488fmalita    buffer.writeRect(fTile);
141855e88edfafe4b3892e99f932c38fa7433b2fcbecommit-bot@chromium.org    fPicture->flatten(buffer);
142c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
143c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
144b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kimSkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix, const SkMatrix* localM,
145b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim                                            const int maxTextureSize) const {
146a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    SkASSERT(fPicture && !fPicture->cullRect().isEmpty());
147c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
148c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    SkMatrix m;
1495970f625e96cdc007c563ae72f343ae0d71719a1commit-bot@chromium.org    m.setConcat(matrix, this->getLocalMatrix());
15080116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org    if (localM) {
15180116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org        m.preConcat(*localM);
15280116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org    }
153c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
154c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    // Use a rotation-invariant scale
155c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    SkPoint scale;
156adf9990cb56ca389f37f02ac637496083b3c3cfcreed    //
157adf9990cb56ca389f37f02ac637496083b3c3cfcreed    // TODO: replace this with decomposeScale() -- but beware LayoutTest rebaselines!
158adf9990cb56ca389f37f02ac637496083b3c3cfcreed    //
159c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    if (!SkDecomposeUpper2x2(m, NULL, &scale, NULL)) {
160c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org        // Decomposition failed, use an approximation.
161c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org        scale.set(SkScalarSqrt(m.getScaleX() * m.getScaleX() + m.getSkewX() * m.getSkewX()),
162c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org                  SkScalarSqrt(m.getScaleY() * m.getScaleY() + m.getSkewY() * m.getSkewY()));
163c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    }
164b0878797b45f93b3bfe6084094c74affd10207dffmalita    SkSize scaledSize = SkSize::Make(SkScalarAbs(scale.x() * fTile.width()),
165b0878797b45f93b3bfe6084094c74affd10207dffmalita                                     SkScalarAbs(scale.y() * fTile.height()));
166c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
167511005b2ccf060bd8ca5f078f2c0c7c7da5cc084fmalita    // Clamp the tile size to about 4M pixels
168511005b2ccf060bd8ca5f078f2c0c7c7da5cc084fmalita    static const SkScalar kMaxTileArea = 2048 * 2048;
169bb204f4917aff10fcb65d29a2d96e53a9611c559fmalita    SkScalar tileArea = SkScalarMul(scaledSize.width(), scaledSize.height());
170bb204f4917aff10fcb65d29a2d96e53a9611c559fmalita    if (tileArea > kMaxTileArea) {
17180ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed        SkScalar clampScale = SkScalarSqrt(kMaxTileArea / tileArea);
172bb204f4917aff10fcb65d29a2d96e53a9611c559fmalita        scaledSize.set(SkScalarMul(scaledSize.width(), clampScale),
173bb204f4917aff10fcb65d29a2d96e53a9611c559fmalita                       SkScalarMul(scaledSize.height(), clampScale));
174bb204f4917aff10fcb65d29a2d96e53a9611c559fmalita    }
175b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim#if SK_SUPPORT_GPU
176b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim    // Scale down the tile size if larger than maxTextureSize for GPU Path or it should fail on create texture
177b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim    if (maxTextureSize) {
178b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim        if (scaledSize.width() > maxTextureSize || scaledSize.height() > maxTextureSize) {
17980ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed            SkScalar downScale = maxTextureSize / SkMax32(scaledSize.width(), scaledSize.height());
18088f12dbe926df806cfb5b0641f613a2e256a713bgen.kim            scaledSize.set(SkScalarFloorToScalar(SkScalarMul(scaledSize.width(), downScale)),
18188f12dbe926df806cfb5b0641f613a2e256a713bgen.kim                           SkScalarFloorToScalar(SkScalarMul(scaledSize.height(), downScale)));
182b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim        }
183b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim    }
184b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim#endif
185bb204f4917aff10fcb65d29a2d96e53a9611c559fmalita
186c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    SkISize tileSize = scaledSize.toRound();
187c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    if (tileSize.isEmpty()) {
18887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        return NULL;
189c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    }
190c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
191bb204f4917aff10fcb65d29a2d96e53a9611c559fmalita    // The actual scale, compensating for rounding & clamping.
192b5f7826c51af2862aebcabe61e1ba684f925e488fmalita    SkSize tileScale = SkSize::Make(SkIntToScalar(tileSize.width()) / fTile.width(),
193b5f7826c51af2862aebcabe61e1ba684f925e488fmalita                                    SkIntToScalar(tileSize.height()) / fTile.height());
194c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
19523df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    SkAutoTUnref<SkShader> tileShader;
19623df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    BitmapShaderKey key(fPicture->uniqueID(),
19723df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                        fTile,
19823df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                        fTmx,
19923df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                        fTmy,
20023df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                        tileScale,
20123df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita                        this->getLocalMatrix());
20287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
203171e5b73a862418f4acd61faf8cecfbc8f58694cfmalita    if (!SkResourceCache::Find(key, BitmapShaderRec::Visitor, &tileShader)) {
204c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org        SkBitmap bm;
205f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        bm.setInfo(SkImageInfo::MakeN32Premul(tileSize));
206f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        if (!cache_try_alloc_pixels(&bm)) {
20787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            return NULL;
208c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org        }
209f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        bm.eraseColor(SK_ColorTRANSPARENT);
210f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita
211f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        // Always disable LCD text, since we can't assume our image will be opaque.
212f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        SkCanvas canvas(bm, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
213f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita
214f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        canvas.scale(tileScale.width(), tileScale.height());
215f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        canvas.translate(-fTile.x(), -fTile.y());
216f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita        canvas.drawPicture(fPicture);
217c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
21887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkMatrix shaderMatrix = this->getLocalMatrix();
21987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
22023df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita        tileShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix));
22123df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita
222171e5b73a862418f4acd61faf8cecfbc8f58694cfmalita        SkResourceCache::Add(SkNEW_ARGS(BitmapShaderRec, (key, tileShader.get(), bm.getSize())));
22387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    }
2246e5671d8c9b2d9885e351b631b1dfbb4ed403789commit-bot@chromium.org
22523df2d693304824a2ce7ac3d988b0e48fec1c49dfmalita    return tileShader.detach();
22653783b026a00683c1fb504127c3398dabb61ea73commit-bot@chromium.org}
227c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
228ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgsize_t SkPictureShader::contextSize() const {
229ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    return sizeof(PictureShaderContext);
230ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org}
23168ea91a49311562347311448450199a957590c1ccommit-bot@chromium.org
232ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkPictureShader::onCreateContext(const ContextRec& rec, void* storage) const {
23380116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org    SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix));
234ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    if (NULL == bitmapShader.get()) {
23587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        return NULL;
236c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    }
237f03f9ff295298ff58acdeb4d7142e9736121d362commit-bot@chromium.org    return PictureShaderContext::Create(storage, *this, rec, bitmapShader);
23887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
23987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
240ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////////////////
24187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
242ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgSkShader::Context* SkPictureShader::PictureShaderContext::Create(void* storage,
243ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org                   const SkPictureShader& shader, const ContextRec& rec, SkShader* bitmapShader) {
244ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    PictureShaderContext* ctx = SkNEW_PLACEMENT_ARGS(storage, PictureShaderContext,
245ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org                                                     (shader, rec, bitmapShader));
246ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    if (NULL == ctx->fBitmapShaderContext) {
247ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org        ctx->~PictureShaderContext();
248ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org        ctx = NULL;
249c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    }
250ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    return ctx;
251c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
252c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
25387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkPictureShader::PictureShaderContext::PictureShaderContext(
254e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org        const SkPictureShader& shader, const ContextRec& rec, SkShader* bitmapShader)
255e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org    : INHERITED(shader, rec)
256ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    , fBitmapShader(SkRef(bitmapShader))
25787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org{
258ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    fBitmapShaderContextStorage = sk_malloc_throw(bitmapShader->contextSize());
259ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    fBitmapShaderContext = bitmapShader->createContext(rec, fBitmapShaderContextStorage);
260ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    //if fBitmapShaderContext is null, we are invalid
26187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
262001f4ed2fb62ecdc98ce2884d925de11b7516d23commit-bot@chromium.org
26387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkPictureShader::PictureShaderContext::~PictureShaderContext() {
264ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    if (fBitmapShaderContext) {
265ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org        fBitmapShaderContext->~Context();
266ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    }
26787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    sk_free(fBitmapShaderContextStorage);
268001f4ed2fb62ecdc98ce2884d925de11b7516d23commit-bot@chromium.org}
269001f4ed2fb62ecdc98ce2884d925de11b7516d23commit-bot@chromium.org
27087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orguint32_t SkPictureShader::PictureShaderContext::getFlags() const {
271ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    SkASSERT(fBitmapShaderContext);
27287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    return fBitmapShaderContext->getFlags();
273001f4ed2fb62ecdc98ce2884d925de11b7516d23commit-bot@chromium.org}
274001f4ed2fb62ecdc98ce2884d925de11b7516d23commit-bot@chromium.org
27587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkShader::Context::ShadeProc SkPictureShader::PictureShaderContext::asAShadeProc(void** ctx) {
276ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    SkASSERT(fBitmapShaderContext);
27787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    return fBitmapShaderContext->asAShadeProc(ctx);
278c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
279c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
28087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkPictureShader::PictureShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
28187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkASSERT(fBitmapShaderContext);
28287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fBitmapShaderContext->shadeSpan(x, y, dstC, count);
283c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
284c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
28587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkPictureShader::PictureShaderContext::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
28687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkASSERT(fBitmapShaderContext);
28787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fBitmapShaderContext->shadeSpan16(x, y, dstC, count);
288c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
289c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
290c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
291c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.orgvoid SkPictureShader::toString(SkString* str) const {
292c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    static const char* gTileModeName[SkShader::kTileModeCount] = {
293c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org        "clamp", "repeat", "mirror"
294c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    };
295c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
296a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    str->appendf("PictureShader: [%f:%f:%f:%f] ",
297f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita                 fPicture ? fPicture->cullRect().fLeft : 0,
298f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita                 fPicture ? fPicture->cullRect().fTop : 0,
299f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita                 fPicture ? fPicture->cullRect().fRight : 0,
300f47e70712b964b5360a3fec9e5e84bb594fc1f02fmalita                 fPicture ? fPicture->cullRect().fBottom : 0);
301c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
302c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    str->appendf("(%s, %s)", gTileModeName[fTmx], gTileModeName[fTmy]);
303c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
304c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    this->INHERITED::toString(str);
305c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
306c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#endif
307c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org
308c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#if SK_SUPPORT_GPU
309b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkPictureShader::asFragmentProcessor(GrContext* context, const SkPaint& paint,
3105531d51ce7426bdae7563547326fcf0bf926a083joshualitt                                          const SkMatrix& viewM, const SkMatrix* localMatrix,
3115531d51ce7426bdae7563547326fcf0bf926a083joshualitt                                          GrColor* paintColor,
312b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                          GrFragmentProcessor** fp) const {
313b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim    int maxTextureSize = 0;
314b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim    if (context) {
315b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim        maxTextureSize = context->getMaxTextureSize();
316b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim    }
317b9ed8845783ec3c59b2b185d26801f251adbf68dgen.kim    SkAutoTUnref<SkShader> bitmapShader(this->refBitmapShader(viewM, localMatrix, maxTextureSize));
31887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    if (!bitmapShader) {
3199de5b514d38c5b36066bcdc14fba2f7e5196d372dandov        return false;
320c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org    }
3215531d51ce7426bdae7563547326fcf0bf926a083joshualitt    return bitmapShader->asFragmentProcessor(context, paint, viewM, NULL, paintColor, fp);
3229de5b514d38c5b36066bcdc14fba2f7e5196d372dandov}
3239de5b514d38c5b36066bcdc14fba2f7e5196d372dandov#else
3245531d51ce7426bdae7563547326fcf0bf926a083joshualittbool SkPictureShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix&,
3255531d51ce7426bdae7563547326fcf0bf926a083joshualitt                                          const SkMatrix*, GrColor*,
326b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                          GrFragmentProcessor**) const {
3279de5b514d38c5b36066bcdc14fba2f7e5196d372dandov    SkDEBUGFAIL("Should not call in GPU-less build");
3289de5b514d38c5b36066bcdc14fba2f7e5196d372dandov    return false;
329c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org}
330c5d9bb0f677069f62ec76373b9730e70e7352455commit-bot@chromium.org#endif
331