1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrLayerCache_DEFINED
9#define GrLayerCache_DEFINED
10
11#include "GrAllocPool.h"
12#include "GrTHashTable.h"
13#include "GrPictureUtils.h"
14#include "GrRect.h"
15
16class GrAtlasMgr;
17class GrGpu;
18class GrPlot;
19class SkPicture;
20
21// GrAtlasLocation captures an atlased item's position in the atlas. This
22// means the plot in which it resides and its bounds inside the plot.
23// TODO: Make GrGlyph use one of these?
24class GrAtlasLocation {
25public:
26    GrAtlasLocation() : fPlot(NULL) {}
27
28    void set(GrPlot* plot, const GrIRect16& bounds) {
29        fPlot = plot;
30        fBounds = bounds;
31    }
32
33    const GrPlot* plot() const {
34        return fPlot;
35    }
36
37    const GrIRect16& bounds() const {
38        return fBounds;
39    }
40
41private:
42    GrPlot*   fPlot;
43    GrIRect16 fBounds;  // only valid is fPlot != NULL
44};
45
46// GrCachedLayer encapsulates the caching information for a single saveLayer.
47//
48// Atlased layers get a ref to their atlas GrTexture and their GrAtlasLocation
49// is filled in.
50// In this case GrCachedLayer is roughly equivalent to a GrGlyph in the font
51// caching system.
52//
53// Non-atlased layers get a ref to the GrTexture in which they reside.
54// TODO: can we easily reuse the empty space in the non-atlased GrTexture's?
55struct GrCachedLayer {
56public:
57    uint32_t pictureID() const { return fPictureID; }
58    int layerID() const { return fLayerID; }
59
60    void init(uint32_t pictureID, int layerID) {
61        fPictureID = pictureID;
62        fLayerID   = layerID;
63        fTexture   = NULL;
64        fLocation.set(NULL, GrIRect16::MakeEmpty());
65    }
66
67    // This call takes over the caller's ref
68    void setTexture(GrTexture* texture) {
69        if (NULL != fTexture) {
70            fTexture->unref();
71        }
72
73        fTexture = texture; // just take over caller's ref
74    }
75    GrTexture* getTexture() { return fTexture; }
76
77private:
78    uint32_t        fPictureID;
79    // fLayerID is only valid when fPicture != kInvalidGenID in which case it
80    // is the index of this layer in the picture (one of 0 .. #layers).
81    int             fLayerID;
82
83    // fTexture is a ref on the atlasing texture for atlased layers and a
84    // ref on a GrTexture for non-atlased textures. In both cases, if this is
85    // non-NULL, that means that the texture is locked in the texture cache.
86    GrTexture*      fTexture;
87
88    GrAtlasLocation fLocation;       // only valid if the layer is atlased
89};
90
91// The GrLayerCache caches pre-computed saveLayers for later rendering.
92// Non-atlased layers are stored in their own GrTexture while the atlased
93// layers share a single GrTexture.
94// Unlike the GrFontCache, the GrTexture atlas only has one GrAtlasMgr (for 8888)
95// and one GrPlot (for the entire atlas). As such, the GrLayerCache
96// roughly combines the functionality of the GrFontCache and GrTextStrike
97// classes.
98class GrLayerCache {
99public:
100    GrLayerCache(GrGpu*);
101    ~GrLayerCache();
102
103    void freeAll();
104
105    GrCachedLayer* findLayerOrCreate(const SkPicture* picture, int id);
106
107private:
108    SkAutoTUnref<GrGpu>       fGpu;
109    SkAutoTDelete<GrAtlasMgr> fAtlasMgr; // TODO: could lazily allocate
110
111    class PictureLayerKey;
112    GrTHashTable<GrCachedLayer, PictureLayerKey, 7> fLayerHash;
113    GrTAllocPool<GrCachedLayer> fLayerPool;
114
115    void init();
116    GrCachedLayer* createLayer(const SkPicture* picture, int id);
117
118};
119
120#endif
121