• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 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 GrCCAtlas_DEFINED
9 #define GrCCAtlas_DEFINED
10 
11 #include "GrAllocator.h"
12 #include "GrNonAtomicRef.h"
13 #include "GrResourceKey.h"
14 #include "GrTexture.h"
15 #include "SkRefCnt.h"
16 #include "SkSize.h"
17 
18 class GrCCCachedAtlas;
19 class GrOnFlushResourceProvider;
20 class GrRenderTargetContext;
21 class GrTextureProxy;
22 struct SkIPoint16;
23 struct SkIRect;
24 
25 /**
26  * This class implements a dynamic size GrRectanizer that grows until it reaches the implementation-
27  * dependent max texture size. When finalized, it also creates and stores a GrTextureProxy for the
28  * underlying atlas.
29  */
30 class GrCCAtlas {
31 public:
32     // As long as GrSurfaceOrigin exists, we just have to decide on one for the atlas texture.
33     static constexpr GrSurfaceOrigin kTextureOrigin = kTopLeft_GrSurfaceOrigin;
34     static constexpr int kPadding = 1;  // Amount of padding below and to the right of each path.
35 
36     // This struct encapsulates the minimum and desired requirements for an atlas, as well as an
37     // approximate number of pixels to help select a good initial size.
38     struct Specs {
39         int fMaxPreferredTextureSize = 0;
40         int fMinTextureSize = 0;
41         int fMinWidth = 0;  // If there are 100 20x10 paths, this should be 20.
42         int fMinHeight = 0;  // If there are 100 20x10 paths, this should be 10.
43         int fApproxNumPixels = 0;
44 
45         // Add space for a rect in the desired atlas specs.
46         void accountForSpace(int width, int height);
47     };
48 
49     enum class CoverageType : bool {
50         kFP16_CoverageCount,
51         kA8_LiteralCoverage
52     };
53 
54     GrCCAtlas(CoverageType, const Specs&, const GrCaps&);
55     ~GrCCAtlas();
56 
textureProxy()57     GrTextureProxy* textureProxy() const { return fTextureProxy.get(); }
currentWidth()58     int currentWidth() const { return fWidth; }
currentHeight()59     int currentHeight() const { return fHeight; }
60 
61     // Attempts to add a rect to the atlas. If successful, returns the integer offset from
62     // device-space pixels where the path will be drawn, to atlas pixels where its mask resides.
63     bool addRect(const SkIRect& devIBounds, SkIVector* atlasOffset);
drawBounds()64     const SkISize& drawBounds() { return fDrawBounds; }
65 
66     // This is an optional space for the caller to jot down which user-defined batches to use when
67     // they render the content of this atlas.
68     void setFillBatchID(int id);
getFillBatchID()69     int getFillBatchID() const { return fFillBatchID; }
70     void setStrokeBatchID(int id);
getStrokeBatchID()71     int getStrokeBatchID() const { return fStrokeBatchID; }
72 
73     sk_sp<GrCCCachedAtlas> refOrMakeCachedAtlas(GrOnFlushResourceProvider*);
74 
75     // Instantiates our texture proxy for the atlas and returns a pre-cleared GrRenderTargetContext
76     // that the caller may use to render the content. After this call, it is no longer valid to call
77     // addRect(), setUserBatchID(), or this method again.
78     //
79     // 'backingTexture', if provided, is a renderable texture with which to instantiate our proxy.
80     // If null then we will create a texture using the resource provider. The purpose of this param
81     // is to provide a guaranteed way to recycle a stashed atlas texture from a previous flush.
82     sk_sp<GrRenderTargetContext> makeRenderTargetContext(GrOnFlushResourceProvider*,
83                                                          sk_sp<GrTexture> backingTexture = nullptr);
84 
85 private:
86     class Node;
87 
88     bool internalPlaceRect(int w, int h, SkIPoint16* loc);
89 
90     const CoverageType fCoverageType;
91     const int fMaxTextureSize;
92     int fWidth, fHeight;
93     std::unique_ptr<Node> fTopNode;
94     SkISize fDrawBounds = {0, 0};
95 
96     int fFillBatchID;
97     int fStrokeBatchID;
98 
99     sk_sp<GrCCCachedAtlas> fCachedAtlas;
100     sk_sp<GrTextureProxy> fTextureProxy;
101     sk_sp<GrTexture> fBackingTexture;
102 };
103 
104 /**
105  * This class implements an unbounded stack of atlases. When the current atlas reaches the
106  * implementation-dependent max texture size, a new one is pushed to the back and we continue on.
107  */
108 class GrCCAtlasStack {
109 public:
110     using CoverageType = GrCCAtlas::CoverageType;
111 
GrCCAtlasStack(CoverageType coverageType,const GrCCAtlas::Specs & specs,const GrCaps * caps)112     GrCCAtlasStack(CoverageType coverageType, const GrCCAtlas::Specs& specs, const GrCaps* caps)
113             : fCoverageType(coverageType), fSpecs(specs), fCaps(caps) {}
114 
empty()115     bool empty() const { return fAtlases.empty(); }
front()116     const GrCCAtlas& front() const { SkASSERT(!this->empty()); return fAtlases.front(); }
front()117     GrCCAtlas& front() { SkASSERT(!this->empty()); return fAtlases.front(); }
current()118     GrCCAtlas& current() { SkASSERT(!this->empty()); return fAtlases.back(); }
119 
120     class Iter {
121     public:
Iter(GrCCAtlasStack & stack)122         Iter(GrCCAtlasStack& stack) : fImpl(&stack.fAtlases) {}
next()123         bool next() { return fImpl.next(); }
124         GrCCAtlas* operator->() const { return fImpl.get(); }
125     private:
126         typename GrTAllocator<GrCCAtlas>::Iter fImpl;
127     };
128 
129     // Adds a rect to the current atlas and returns the offset from device space to atlas space.
130     // Call current() to get the atlas it was added to.
131     //
132     // If the return value is non-null, it means the given rect did not fit in the then-current
133     // atlas, so it was retired and a new one was added to the stack. The return value is the
134     // newly-retired atlas. The caller should call setUserBatchID() on the retired atlas before
135     // moving on.
136     GrCCAtlas* addRect(const SkIRect& devIBounds, SkIVector* devToAtlasOffset);
137 
138 private:
139     const CoverageType fCoverageType;
140     const GrCCAtlas::Specs fSpecs;
141     const GrCaps* const fCaps;
142     GrSTAllocator<4, GrCCAtlas> fAtlases;
143 };
144 
accountForSpace(int width,int height)145 inline void GrCCAtlas::Specs::accountForSpace(int width, int height) {
146     fMinWidth = SkTMax(width, fMinWidth);
147     fMinHeight = SkTMax(height, fMinHeight);
148     fApproxNumPixels += (width + kPadding) * (height + kPadding);
149 }
150 
151 #endif
152