aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrBatchFontCache.h
blob: 6300fbe212f1260308a8203fb5fbca9497eb7ea2 (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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrBatchFontCache_DEFINED
#define GrBatchFontCache_DEFINED

#include "GrBatchAtlas.h"
#include "GrDrawTarget.h"
#include "GrFontScaler.h"
#include "GrGlyph.h"
#include "SkTDynamicHash.h"
#include "SkVarAlloc.h"

class GrBatchFontCache;
class GrBatchTarget;
class GrGpu;

/**
 *  The GrBatchTextStrike manages a pool of CPU backing memory for Glyph Masks.  This backing memory
 *  is abstracted by GrGlyph, and indexed by a PackedID and GrFontScaler.  The GrFontScaler is what
 *  actually creates the mask.
 */
class GrBatchTextStrike {
public:
    GrBatchTextStrike(GrBatchFontCache*, const GrFontDescKey* fontScalerKey);
    ~GrBatchTextStrike();

    const GrFontDescKey* getFontScalerKey() const { return fFontScalerKey; }
    GrBatchFontCache* getBatchFontCache() const { return fBatchFontCache; }

    inline GrGlyph* getGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler) {
        GrGlyph* glyph = fCache.find(packed);
        if (NULL == glyph) {
            glyph = this->generateGlyph(packed, scaler);
        }
        return glyph;
    }

    // returns true if glyph (or glyph+padding for distance field)
    // is too large to ever fit in texture atlas subregions (GrPlots)
    bool glyphTooLargeForAtlas(GrGlyph*);
    // returns true if glyph successfully added to texture atlas, false otherwise
    bool addGlyphToAtlas(GrBatchTarget*, GrGlyph*, GrFontScaler*);

    // testing
    int countGlyphs() const { return fCache.count(); }

    // remove any references to this plot
    void removeID(GrBatchAtlas::AtlasID);

    static const GrFontDescKey& GetKey(const GrBatchTextStrike& ts) {
        return *(ts.fFontScalerKey);
    }
    static uint32_t Hash(const GrFontDescKey& key) {
        return key.getHash();
    }

private:
    SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache;
    SkAutoTUnref<const GrFontDescKey> fFontScalerKey;
    SkVarAlloc fPool;

    GrBatchFontCache* fBatchFontCache;
    int fAtlasedGlyphs;

    GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler);

    friend class GrBatchFontCache;
};

/*
 * GrBatchFontCache manages strikes which are indexed by a GrFontScaler.  These strikes can then be
 * used to individual Glyph Masks.  The GrBatchFontCache also manages GrBatchAtlases, though this is
 * more or less transparent to the client(aside from atlasGeneration, described below)
 */
class GrBatchFontCache {
public:
    GrBatchFontCache();
    ~GrBatchFontCache();

    // Initializes the GrBatchFontCache on the owning GrContext
    void init(GrContext*);

    inline GrBatchTextStrike* getStrike(GrFontScaler* scaler) {

        GrBatchTextStrike* strike = fCache.find(*(scaler->getKey()));
        if (NULL == strike) {
            strike = this->generateStrike(scaler);
        }
        return strike;
    }

    bool hasGlyph(GrGlyph* glyph);

    // To ensure the GrBatchAtlas does not evict the Glyph Mask from its texture backing store,
    // the client must pass in the currentToken from the GrBatchTarget along with the GrGlyph
    void setGlyphRefToken(GrGlyph*, GrBatchAtlas::BatchToken);

    // add to texture atlas that matches this format
    bool addToAtlas(GrBatchTextStrike*, GrBatchAtlas::AtlasID*, GrBatchTarget*,
                    GrMaskFormat, int width, int height, const void* image,
                    SkIPoint16* loc);

    // Some clients may wish to verify the integrity of the texture backing store of the
    // GrBatchAtlas.  The atlasGeneration returned below is a monitonically increasing number which
    // changes everytime something is removed from the texture backing store.
    uint64_t atlasGeneration(GrMaskFormat) const;

    void freeAll();

    GrTexture* getTexture(GrMaskFormat);
    GrPixelConfig getPixelConfig(GrMaskFormat) const;

    void dump() const;

private:
    // There is a 1:1 mapping between GrMaskFormats and atlas indices
    static int MaskFormatToAtlasIndex(GrMaskFormat);
    static GrMaskFormat AtlasIndexToMaskFormat(int atlasIndex);

    GrBatchTextStrike* generateStrike(GrFontScaler*);

    inline GrBatchAtlas* getAtlas(GrMaskFormat) const;

    static void HandleEviction(GrBatchAtlas::AtlasID, void*);

    SkTDynamicHash<GrBatchTextStrike, GrFontDescKey> fCache;

    GrBatchAtlas* fAtlases[kMaskFormatCount];
    GrBatchTextStrike* fPreserveStrike;
};

#endif