18ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org/*
28ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org * Copyright 2014 Google Inc.
38ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org *
48ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
58ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org * found in the LICENSE file.
68ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org */
78ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
88ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org#include "GrPictureUtils.h"
9d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
100205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org#include "SkPaintPriv.h"
11d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips#include "SkRecord.h"
12d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips#include "SkRecords.h"
130205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org
146617d509ab0b056c57952bb1ee04b4c94904284brobertphillipsSkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() {
150205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org    static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();
160205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org
170205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org    return gGPUID;
180205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org}
198ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
20d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips// SkRecord visitor to gather saveLayer/restore information.
21d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillipsclass CollectLayers {
228ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.orgpublic:
23d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    CollectLayers(const SkPicture* pict, GrAccelData* accelData)
24d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        : fPictureID(pict->uniqueID())
25d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        , fCTM(&SkMatrix::I())
26d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        , fSaveLayersInStack(0)
27d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        , fAccelData(accelData) {
28d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
29a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips        pict->cullRect().roundOut(&fCurrentClipBounds);
30a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips
31d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        if (NULL == pict->fRecord.get()) {
32d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            return;
33d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
348ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
35d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        for (fCurrentOp = 0; fCurrentOp < pict->fRecord->count(); ++fCurrentOp) {
36d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            pict->fRecord->visit<void>(fCurrentOp, *this);
37d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
388ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
39d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        while (!fSaveStack.isEmpty()) {
40d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            this->popSaveBlock();
41d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
428ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    }
438ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
44d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    template <typename T> void operator()(const T& op) {
45d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        this->updateCTM(op);
46d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        this->updateClipBounds(op);
47d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        this->trackSaveLayers(op);
488ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    }
498ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
50d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillipsprivate:
518ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
52d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    class SaveInfo {
53d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    public:
54d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        SaveInfo() { }
55d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        SaveInfo(int opIndex, bool isSaveLayer, const SkPaint* paint, const SkIRect& bounds)
56d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            : fStartIndex(opIndex)
57d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            , fIsSaveLayer(isSaveLayer)
58d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            , fHasNestedSaveLayer(false)
59d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            , fPaint(paint)
60d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            , fBounds(bounds) {
610205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org
62d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
630205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org
64d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        int            fStartIndex;
65d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        bool           fIsSaveLayer;
66d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        bool           fHasNestedSaveLayer;
67d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        const SkPaint* fPaint;
68d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        SkIRect        fBounds;
69d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    };
70d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
71d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    uint32_t            fPictureID;
72d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    unsigned int        fCurrentOp;
73d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    const SkMatrix*     fCTM;
74d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    SkIRect             fCurrentClipBounds;
75d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    int                 fSaveLayersInStack;
76d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    SkTDArray<SaveInfo> fSaveStack;
77d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    GrAccelData*        fAccelData;
78d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
79d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    template <typename T> void updateCTM(const T&) { /* most ops don't change the CTM */ }
80d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void updateCTM(const SkRecords::Restore& op)   { fCTM = &op.matrix; }
81d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void updateCTM(const SkRecords::SetMatrix& op) { fCTM = &op.matrix; }
82d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
83d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    template <typename T> void updateClipBounds(const T&) { /* most ops don't change the clip */ }
84d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    // Each of these devBounds fields is the state of the device bounds after the op.
85d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    // So Restore's devBounds are those bounds saved by its paired Save or SaveLayer.
86d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void updateClipBounds(const SkRecords::Restore& op)    { fCurrentClipBounds = op.devBounds; }
87d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void updateClipBounds(const SkRecords::ClipPath& op)   { fCurrentClipBounds = op.devBounds; }
88d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void updateClipBounds(const SkRecords::ClipRRect& op)  { fCurrentClipBounds = op.devBounds; }
89d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void updateClipBounds(const SkRecords::ClipRect& op)   { fCurrentClipBounds = op.devBounds; }
90d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void updateClipBounds(const SkRecords::ClipRegion& op) { fCurrentClipBounds = op.devBounds; }
91d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void updateClipBounds(const SkRecords::SaveLayer& op)  {
9249f085dddff10473b6ebf832a974288300224e60bsalomon        if (op.bounds) {
93d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            fCurrentClipBounds.intersect(this->adjustAndMap(*op.bounds, op.paint));
940205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org        }
95d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    }
960205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org
97d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    template <typename T> void trackSaveLayers(const T& op) {
98d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        /* most ops aren't involved in saveLayers */
998ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    }
100d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void trackSaveLayers(const SkRecords::Save& s) { this->pushSaveBlock(); }
101d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void trackSaveLayers(const SkRecords::SaveLayer& sl) { this->pushSaveLayerBlock(sl.paint); }
102d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void trackSaveLayers(const SkRecords::Restore& r) { this->popSaveBlock(); }
103d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void trackSaveLayers(const SkRecords::DrawPicture& dp) {
104d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        // For sub-pictures, we wrap their layer information within the parent
105d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        // picture's rendering hierarchy
106d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        const GrAccelData* childData = GPUOptimize(dp.picture);
107d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
108d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        for (int i = 0; i < childData->numSaveLayers(); ++i) {
109d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            const GrAccelData::SaveLayerInfo& src = childData->saveLayerInfo(i);
110d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
111d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            this->updateStackForSaveLayer();
112d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
113d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            // TODO: need to store an SkRect in GrAccelData::SaveLayerInfo?
114d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            SkRect srcRect = SkRect::MakeXYWH(SkIntToScalar(src.fOffset.fX),
115d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                                              SkIntToScalar(src.fOffset.fY),
116d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                                              SkIntToScalar(src.fSize.width()),
117d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                                              SkIntToScalar(src.fSize.height()));
118d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            SkIRect newClip(fCurrentClipBounds);
119d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            newClip.intersect(this->adjustAndMap(srcRect, dp.paint));
120d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
12130d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips            GrAccelData::SaveLayerInfo& dst = fAccelData->addSaveLayerInfo();
12230d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips
123d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            dst.fValid = true;
12430d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips            // If src.fPicture is NULL the layer is in dp.picture; otherwise
12530d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips            // it belongs to a sub-picture.
12630d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips            dst.fPicture = src.fPicture ? src.fPicture : static_cast<const SkPicture*>(dp.picture);
12730d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips            dst.fPicture->ref();
128d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            dst.fSize = SkISize::Make(newClip.width(), newClip.height());
129d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            dst.fOffset = SkIPoint::Make(newClip.fLeft, newClip.fTop);
130d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            dst.fOriginXform = *fCTM;
131d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            dst.fOriginXform.postConcat(src.fOriginXform);
13230d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips            if (src.fPaint) {
133d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                dst.fPaint = SkNEW_ARGS(SkPaint, (*src.fPaint));
134d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            }
135d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            dst.fSaveLayerOpID = src.fSaveLayerOpID;
136d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            dst.fRestoreOpID = src.fRestoreOpID;
137d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            dst.fHasNestedLayers = src.fHasNestedLayers;
138d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            dst.fIsNested = fSaveLayersInStack > 0 || src.fIsNested;
139d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
1408ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    }
141d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
142d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void pushSaveBlock() {
143d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        fSaveStack.push(SaveInfo(fCurrentOp, false, NULL, SkIRect::MakeEmpty()));
1448ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    }
145d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
146d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    // Inform all the saveLayers already on the stack that they now have a
147d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    // nested saveLayer inside them
148d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void updateStackForSaveLayer() {
149d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        for (int index = fSaveStack.count() - 1; index >= 0; --index) {
150d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            if (fSaveStack[index].fHasNestedSaveLayer) {
151d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                break;
152d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            }
153d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            fSaveStack[index].fHasNestedSaveLayer = true;
154d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            if (fSaveStack[index].fIsSaveLayer) {
155d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                break;
156d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            }
157d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
1588ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    }
1598ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
160d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void pushSaveLayerBlock(const SkPaint* paint) {
161d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        this->updateStackForSaveLayer();
1628ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
163d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        fSaveStack.push(SaveInfo(fCurrentOp, true, paint, fCurrentClipBounds));
164d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        ++fSaveLayersInStack;
165d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    }
1668ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
167d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    void popSaveBlock() {
168d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        if (fSaveStack.count() <= 0) {
169d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            SkASSERT(false);
170d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            return;
171d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
1728ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
173d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        SaveInfo si;
174d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        fSaveStack.pop(&si);
1758ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
176d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        if (!si.fIsSaveLayer) {
177d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            return;
178d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
1798ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
180d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        --fSaveLayersInStack;
1810205aba7d5e8802d2a3ef55d999f5aa41db3adc9commit-bot@chromium.org
18230d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips        GrAccelData::SaveLayerInfo& slInfo = fAccelData->addSaveLayerInfo();
1838ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
184d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        slInfo.fValid = true;
18530d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips        SkASSERT(NULL == slInfo.fPicture);  // This layer is in the top-most picture
186d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        slInfo.fSize = SkISize::Make(si.fBounds.width(), si.fBounds.height());
187d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        slInfo.fOffset = SkIPoint::Make(si.fBounds.fLeft, si.fBounds.fTop);
188d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        slInfo.fOriginXform = *fCTM;
18930d2cc6ff47cb7f981d83e9a536971beec920f61robertphillips        if (si.fPaint) {
190d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            slInfo.fPaint = SkNEW_ARGS(SkPaint, (*si.fPaint));
191d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
192d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        slInfo.fSaveLayerOpID = si.fStartIndex;
193d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        slInfo.fRestoreOpID = fCurrentOp;
194d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        slInfo.fHasNestedLayers = si.fHasNestedSaveLayer;
195d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        slInfo.fIsNested = fSaveLayersInStack > 0;
1968ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    }
1978ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
198d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    // Returns true if rect was meaningfully adjusted for the effects of paint,
199d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    // false if the paint could affect the rect in unknown ways.
200d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) {
201d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        if (paint) {
202d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            if (paint->canComputeFastBounds()) {
203d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                *rect = paint->computeFastBounds(*rect, rect);
204d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                return true;
205d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            }
206d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            return false;
207d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
208d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        return true;
209d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    }
2108ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
211d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    // Adjust rect for all paints that may affect its geometry, then map it to device space.
212d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    SkIRect adjustAndMap(SkRect rect, const SkPaint* paint) const {
213d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        // Inverted rectangles really confuse our BBHs.
214d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        rect.sort();
2158ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
216d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        // Adjust the rect for its own paint.
217d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        if (!AdjustForPaint(paint, &rect)) {
218d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            // The paint could do anything to our bounds.  The only safe answer is the current clip.
219d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            return fCurrentClipBounds;
220d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
2218ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
222d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        // Adjust rect for all the paints from the SaveLayers we're inside.
223d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        for (int i = fSaveStack.count() - 1; i >= 0; i--) {
224d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            if (!AdjustForPaint(fSaveStack[i].fPaint, &rect)) {
225d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                // Same deal as above.
226d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                return fCurrentClipBounds;
227d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips            }
228d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        }
2298ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
230d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        // Map the rect back to device space.
231d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        fCTM->mapRect(&rect);
232d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        SkIRect devRect;
233d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        rect.roundOut(&devRect);
2348ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
235d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        // Nothing can draw outside the current clip.
236d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        // (Only bounded ops call into this method, so oddballs like Clear don't matter here.)
237d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        devRect.intersect(fCurrentClipBounds);
238d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        return devRect;
2399b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    }
2408ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org};
2418ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
242d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
243d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips// GPUOptimize is only intended to be called within the context of SkGpuDevice's
2442c48ee83c824964fbcb3dc4733055da0e75e154fskia.committer@gmail.com// EXPERIMENTAL_optimize method.
245d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillipsconst GrAccelData* GPUOptimize(const SkPicture* pict) {
246a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips    if (NULL == pict || pict->cullRect().isEmpty()) {
247d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        return NULL;
2488ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org    }
2498ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
250d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
251d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
252d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    const GrAccelData* existing =
253d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips                            static_cast<const GrAccelData*>(pict->EXPERIMENTAL_getAccelData(key));
25449f085dddff10473b6ebf832a974288300224e60bsalomon    if (existing) {
255d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips        return existing;
256d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    }
257d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
258d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    SkAutoTUnref<GrAccelData> data(SkNEW_ARGS(GrAccelData, (key)));
259d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips
260d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    pict->EXPERIMENTAL_addAccelData(data);
261ce4dd3de38cd7c29bf5b9d8a8efb55c08ec9be47robertphillips
262d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    CollectLayers collector(pict, data);
2638ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org
264d62833079fc36e28e65692f9a0c7dbdb124519c6robertphillips    return data;
2658ddc26b68c4e41199c06961da3bff2ce72afff14commit-bot@chromium.org}
266