1d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips/*
2d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips * Copyright 2014 Google Inc.
3d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips *
4d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips * Use of this source code is governed by a BSD-style license that can be
5d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips * found in the LICENSE file.
6d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips */
7d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
8e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips#include "GrContext.h"
9e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips#include "GrLayerCache.h"
10d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips#include "GrRecordReplaceDraw.h"
1168cd2aa797f707a9847f8eba0758787cafd43e43robertphillips#include "SkCanvasPriv.h"
12e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips#include "SkGrPixelRef.h"
13d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips#include "SkImage.h"
14d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips#include "SkRecordDraw.h"
1568cd2aa797f707a9847f8eba0758787cafd43e43robertphillips#include "SkRecords.h"
1668cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
17e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillipsstatic inline void wrap_texture(GrTexture* texture, int width, int height, SkBitmap* result) {
18e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
19e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips    result->setInfo(info);
20e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips    result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
21d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips}
22d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
23e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillipsstatic inline void draw_replacement_bitmap(GrCachedLayer* layer, SkCanvas* canvas) {
24d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
2595145a9d3e0be24769c4c4e3810058e08b06fd3brobertphillips    // Some image filter can totally filter away a layer (e.g., SkPictureImageFilter's with
2695145a9d3e0be24769c4c4e3810058e08b06fd3brobertphillips    // no picture).
2795145a9d3e0be24769c4c4e3810058e08b06fd3brobertphillips    if (!layer->texture()) {
2895145a9d3e0be24769c4c4e3810058e08b06fd3brobertphillips        return;
2995145a9d3e0be24769c4c4e3810058e08b06fd3brobertphillips    }
3095145a9d3e0be24769c4c4e3810058e08b06fd3brobertphillips
31e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips    SkBitmap bm;
32e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips    wrap_texture(layer->texture(),
33e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                 !layer->isAtlased() ? layer->rect().width()  : layer->texture()->width(),
34e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                 !layer->isAtlased() ? layer->rect().height() : layer->texture()->height(),
35e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                 &bm);
3646625e06e23b65c05013fc686a8223d6d5b49050robertphillips
37478dd723362fefc2023aee03e11216d913eeac03robertphillips    if (layer->isAtlased()) {
38478dd723362fefc2023aee03e11216d913eeac03robertphillips        const SkRect src = SkRect::Make(layer->rect());
39478dd723362fefc2023aee03e11216d913eeac03robertphillips        const SkRect dst = SkRect::Make(layer->srcIR());
40478dd723362fefc2023aee03e11216d913eeac03robertphillips
41478dd723362fefc2023aee03e11216d913eeac03robertphillips        SkASSERT(layer->offset().isZero());
42478dd723362fefc2023aee03e11216d913eeac03robertphillips
43478dd723362fefc2023aee03e11216d913eeac03robertphillips        canvas->save();
44478dd723362fefc2023aee03e11216d913eeac03robertphillips        canvas->setMatrix(SkMatrix::I());
45478dd723362fefc2023aee03e11216d913eeac03robertphillips        canvas->drawBitmapRectToRect(bm, &src, dst, layer->paint());
46478dd723362fefc2023aee03e11216d913eeac03robertphillips        canvas->restore();
47478dd723362fefc2023aee03e11216d913eeac03robertphillips    } else {
48478dd723362fefc2023aee03e11216d913eeac03robertphillips        canvas->drawSprite(bm,
49478dd723362fefc2023aee03e11216d913eeac03robertphillips                           layer->srcIR().fLeft + layer->offset().fX,
50478dd723362fefc2023aee03e11216d913eeac03robertphillips                           layer->srcIR().fTop + layer->offset().fY,
51478dd723362fefc2023aee03e11216d913eeac03robertphillips                           layer->paint());
52478dd723362fefc2023aee03e11216d913eeac03robertphillips    }
53d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips}
54d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
5568cd2aa797f707a9847f8eba0758787cafd43e43robertphillips// Used by GrRecordReplaceDraw. It intercepts nested drawPicture calls and
5668cd2aa797f707a9847f8eba0758787cafd43e43robertphillips// also draws them with replaced layers.
5768cd2aa797f707a9847f8eba0758787cafd43e43robertphillipsclass ReplaceDraw : public SkRecords::Draw {
5868cd2aa797f707a9847f8eba0758787cafd43e43robertphillipspublic:
59e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips    ReplaceDraw(SkCanvas* canvas, GrLayerCache* layerCache,
606be2aa9a251bf6022570a03140f956655b3ef1dareed                SkPicture const* const drawablePicts[], int drawableCount,
6101d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips                const SkPicture* topLevelPicture,
6268cd2aa797f707a9847f8eba0758787cafd43e43robertphillips                const SkPicture* picture,
6368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips                const SkMatrix& initialMatrix,
64783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips                SkPicture::AbortCallback* callback,
65e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                const unsigned* opIndices, int numIndices)
661bdfd3f4f09e47364f76d3f08177b1ce844ac786reed        : INHERITED(canvas, drawablePicts, NULL, drawableCount)
6768cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        , fCanvas(canvas)
68e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips        , fLayerCache(layerCache)
6901d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        , fTopLevelPicture(topLevelPicture)
7068cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        , fPicture(picture)
7168cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        , fInitialMatrix(initialMatrix)
7268cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        , fCallback(callback)
730882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips        , fIndex(0)
740882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips        , fNumReplaced(0) {
7501d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        fOpIndexStack.append(numIndices, opIndices);
76ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    }
77ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips
780882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips    int draw() {
7968cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        const SkBBoxHierarchy* bbh = fPicture->fBBH.get();
8068cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        const SkRecord* record = fPicture->fRecord.get();
8168cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        if (NULL == record) {
820882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips            return 0;
8368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        }
8468cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
850882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips        fNumReplaced = 0;
860882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips
8768cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        fOps.rewind();
8868cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
8968cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        if (bbh) {
9068cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            // Draw only ops that affect pixels in the canvas's current clip.
9168cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            // The SkRecord and BBH were recorded in identity space.  This canvas
9268cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            // is not necessarily in that same space.  getClipBounds() returns us
9368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            // this canvas' clip bounds transformed back into identity space, which
9468cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            // lets us query the BBH.
9568cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            SkRect query = { 0, 0, 0, 0 };
9668cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            (void)fCanvas->getClipBounds(&query);
9768cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
9868cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            bbh->search(query, &fOps);
9968cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
10068cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            for (fIndex = 0; fIndex < fOps.count(); ++fIndex) {
101783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips                if (fCallback && fCallback->abort()) {
1020882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips                    return fNumReplaced;
10368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips                }
10468cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
1056bd41969a0f2283a7a7320bb0025551353c241ecmtklein                record->visit<void>(fOps[fIndex], *this);
106d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips            }
107d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
10868cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        } else {
10968cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            for (fIndex = 0; fIndex < (int) record->count(); ++fIndex) {
110783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips                if (fCallback && fCallback->abort()) {
1110882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips                    return fNumReplaced;
112d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips                }
11368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
11468cd2aa797f707a9847f8eba0758787cafd43e43robertphillips                record->visit<void>(fIndex, *this);
115d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips            }
11668cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        }
1170882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips
1180882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips        return fNumReplaced;
11968cd2aa797f707a9847f8eba0758787cafd43e43robertphillips    }
12068cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
12168cd2aa797f707a9847f8eba0758787cafd43e43robertphillips    // Same as Draw for all ops except DrawPicture and SaveLayer.
12268cd2aa797f707a9847f8eba0758787cafd43e43robertphillips    template <typename T> void operator()(const T& r) {
12368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        this->INHERITED::operator()(r);
12468cd2aa797f707a9847f8eba0758787cafd43e43robertphillips    }
12568cd2aa797f707a9847f8eba0758787cafd43e43robertphillips    void operator()(const SkRecords::DrawPicture& dp) {
12601d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips
12701d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        int drawPictureOffset;
12801d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        if (fOps.count()) {
12901d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips            drawPictureOffset = fOps[fIndex];
13001d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        } else {
13101d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips            drawPictureOffset = fIndex;
13201d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        }
13301d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips
13401d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        fOpIndexStack.push(drawPictureOffset);
13501d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips
136af57903f330a0afd0c10244d4a66f64fdbef5d1emtklein        SkAutoCanvasMatrixPaint acmp(fCanvas, &dp.matrix, dp.paint, dp.picture->cullRect());
137d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
13868cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        // Draw sub-pictures with the same replacement list but a different picture
139e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips        ReplaceDraw draw(fCanvas, fLayerCache,
140e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                         this->drawablePicts(), this->drawableCount(),
141e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                         fTopLevelPicture, dp.picture, fInitialMatrix, fCallback,
14201d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips                         fOpIndexStack.begin(), fOpIndexStack.count());
14368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
1440882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips        fNumReplaced += draw.draw();
14501d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips
14601d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        fOpIndexStack.pop();
14768cd2aa797f707a9847f8eba0758787cafd43e43robertphillips    }
14868cd2aa797f707a9847f8eba0758787cafd43e43robertphillips    void operator()(const SkRecords::SaveLayer& sl) {
1496bd41969a0f2283a7a7320bb0025551353c241ecmtklein
15068cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        // For a saveLayer command, check if it can be replaced by a drawBitmap
15168cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        // call and, if so, draw it and then update the current op index accordingly.
15230d7841f906116c3945ec8125a816a5c5462fed0robertphillips        unsigned startOffset;
15368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        if (fOps.count()) {
1546bd41969a0f2283a7a7320bb0025551353c241ecmtklein            startOffset = fOps[fIndex];
15568cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        } else {
15668cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            startOffset = fIndex;
157d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips        }
158d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
15901d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        fOpIndexStack.push(startOffset);
16001d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips
161e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips        GrCachedLayer* layer = fLayerCache->findLayer(fTopLevelPicture->uniqueID(),
162e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                                                      fInitialMatrix,
163e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                                                      fOpIndexStack.begin(),
164e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                                                      fOpIndexStack.count());
16568cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
166e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips        if (layer) {
1670882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips            fNumReplaced++;
168e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips
169e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips            draw_replacement_bitmap(layer, fCanvas);
17068cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
17168cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            if (fPicture->fBBH.get()) {
172e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                while (fOps[fIndex] < layer->stop()) {
17368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips                    ++fIndex;
17468cd2aa797f707a9847f8eba0758787cafd43e43robertphillips                }
175e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                SkASSERT(fOps[fIndex] == layer->stop());
17668cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            } else {
177e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                fIndex = layer->stop();
17868cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            }
17901d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips            fOpIndexStack.pop();
18068cd2aa797f707a9847f8eba0758787cafd43e43robertphillips            return;
181d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips        }
18268cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
18368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        // This is a fail for layer hoisting
18468cd2aa797f707a9847f8eba0758787cafd43e43robertphillips        this->INHERITED::operator()(sl);
18501d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips
18601d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips        fOpIndexStack.pop();
187d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    }
18868cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
18968cd2aa797f707a9847f8eba0758787cafd43e43robertphillipsprivate:
190783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    SkCanvas*                 fCanvas;
191783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    GrLayerCache*             fLayerCache;
192783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    const SkPicture*          fTopLevelPicture;
193783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    const SkPicture*          fPicture;
194783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    const SkMatrix            fInitialMatrix;
195783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    SkPicture::AbortCallback* fCallback;
19668cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
197783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    SkTDArray<unsigned>       fOps;
198783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    int                       fIndex;
199783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    int                       fNumReplaced;
20068cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
20101d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips    // The op code indices of all the enclosing drawPicture and saveLayer calls
202783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips    SkTDArray<unsigned>       fOpIndexStack;
20301d6e5f462d1d52203ee1a6660415877e4cf2dderobertphillips
20468cd2aa797f707a9847f8eba0758787cafd43e43robertphillips    typedef Draw INHERITED;
20568cd2aa797f707a9847f8eba0758787cafd43e43robertphillips};
20668cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
2070882fdcc15f81bbaf66421dc7934c2893726a3darobertphillipsint GrRecordReplaceDraw(const SkPicture* picture,
2080882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips                        SkCanvas* canvas,
209e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                        GrLayerCache* layerCache,
2100882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips                        const SkMatrix& initialMatrix,
211783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillips                        SkPicture::AbortCallback* callback) {
21268cd2aa797f707a9847f8eba0758787cafd43e43robertphillips    SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
21368cd2aa797f707a9847f8eba0758787cafd43e43robertphillips
2146be2aa9a251bf6022570a03140f956655b3ef1dareed    // TODO: drawablePicts?
215e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips    ReplaceDraw draw(canvas, layerCache, NULL, 0,
216af57903f330a0afd0c10244d4a66f64fdbef5d1emtklein                     picture, picture,
217e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips                     initialMatrix, callback, NULL, 0);
2180882fdcc15f81bbaf66421dc7934c2893726a3darobertphillips    return draw.draw();
219d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips}
220