aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrRecordReplaceDraw.h
blob: 9110ac82f9e09884b355cf7a2ba2b0d472fa61d4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrRecordReplaceDraw_DEFINED
#define GrRecordReplaceDraw_DEFINED

#include "SkChecksum.h"
#include "SkDrawPictureCallback.h"
#include "SkImage.h"
#include "SkRect.h"
#include "SkTDynamicHash.h"

class SkBBoxHierarchy;
class SkBitmap;
class SkCanvas;
class SkImage;
class SkMatrix;
class SkPaint;
class SkPicture;
class SkRecord;

// GrReplacements collects op ranges that can be replaced with
// a single drawBitmap call (using a precomputed bitmap).
class GrReplacements {
public:
    // All the operations between fStart and fStop (inclusive) will be replaced with
    // a single drawBitmap call using fPos, fImage and fPaint.
    class ReplacementInfo {
    public:
        struct Key {
            Key(uint32_t pictureID, unsigned int start, const SkMatrix& ctm)
            : fPictureID(pictureID)
            , fStart(start)
            , fCTM(ctm) {
                fCTM.getType(); // force initialization of type so hashes match

                // Key needs to be tightly packed.
                GR_STATIC_ASSERT(sizeof(Key) == sizeof(uint32_t) +      // picture ID
                                                sizeof(int) +           // start
                                                9 * sizeof(SkScalar)    // 3x3 from CTM
                                                +sizeof(uint32_t));     // matrix's type
            }

            bool operator==(const Key& other) const { 
                return fPictureID == other.fPictureID &&
                       fStart == other.fStart &&
                       fCTM.cheapEqualTo(other.fCTM); // TODO: should be fuzzy
            }

            uint32_t     pictureID() const { return fPictureID; }
            unsigned int start() const { return fStart; }

        private:
            const uint32_t     fPictureID;
            const unsigned int fStart;
            const SkMatrix     fCTM;
        };

        static const Key& GetKey(const ReplacementInfo& layer) { return layer.fKey; }
        static uint32_t Hash(const Key& key) {
            return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&key), sizeof(Key));
        }

        ReplacementInfo(uint32_t pictureID, unsigned int start, const SkMatrix& ctm)
            : fKey(pictureID, start, ctm)
            , fImage(NULL)
            , fPaint(NULL) {
        }
        ~ReplacementInfo() { fImage->unref(); SkDELETE(fPaint); }

        unsigned int start() const { return fKey.start(); }

        const Key       fKey;
        unsigned        fStop;
        SkIPoint        fPos;
        SkImage*        fImage;  // Owns a ref
        const SkPaint*  fPaint;  // Owned by this object

        SkIRect         fSrcRect;
    };

    ~GrReplacements() { this->freeAll(); }

    // Add a new replacement range.
    ReplacementInfo* newReplacement(uint32_t pictureID, unsigned int start, const SkMatrix& ctm);

    // look up a replacement range by its pictureID, start offset and the CTM
    // TODO: also need to add clip to lookup
    const ReplacementInfo* lookupByStart(uint32_t pictureID, size_t start, 
                                         const SkMatrix& ctm) const;

private:
    SkTDynamicHash<ReplacementInfo, ReplacementInfo::Key> fReplacementHash;

    void freeAll();
};

// Draw an SkPicture into an SkCanvas replacing saveLayer/restore blocks with
// drawBitmap calls.  A convenience wrapper around SkRecords::Draw.
// It returns the number of saveLayer/restore blocks replaced with drawBitmap calls.
int GrRecordReplaceDraw(const SkPicture*,
                        SkCanvas*,
                        const GrReplacements*,
                        const SkMatrix& initialMatrix,
                        SkDrawPictureCallback*);

#endif // GrRecordReplaceDraw_DEFINED