Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: src/gpu/GrLayerCache.h

Issue 1950523002: Remove GrLayerHoister (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Forgot to remove some files Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrLayerAtlas.cpp ('k') | src/gpu/GrLayerCache.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
12 #include "GrLayerAtlas.h"
13 #include "GrTexture.h"
14 #include "GrRect.h"
15
16 #include "SkChecksum.h"
17 #include "SkImageFilter.h"
18 #include "SkMessageBus.h"
19 #include "SkPaint.h"
20 #include "SkPicture.h"
21 #include "SkTDynamicHash.h"
22
23 // Set to 0 to disable caching of hoisted layers
24 #define GR_CACHE_HOISTED_LAYERS 0
25
26 // GrPictureInfo stores the atlas plots used by a single picture. A single
27 // plot may be used to store layers from multiple pictures.
28 struct GrPictureInfo {
29 public:
30 static const int kNumPlots = 4;
31
32 // for SkTDynamicHash - just use the pictureID as the hash key
33 static const uint32_t& GetKey(const GrPictureInfo& pictInfo) { return pictIn fo.fPictureID; }
34 static uint32_t Hash(const uint32_t& key) { return SkChecksum::Mix(key); }
35
36 // GrPictureInfo proper
37 GrPictureInfo(uint32_t pictureID)
38 : fPictureID(pictureID)
39 , fPlotUsage(kNumPlots) {
40 #if !GR_CACHE_HOISTED_LAYERS
41 memset(fPlotUses, 0, sizeof(fPlotUses));
42 #endif
43 }
44
45 #if !GR_CACHE_HOISTED_LAYERS
46 void incPlotUsage(int plotID) {
47 SkASSERT(plotID < kNumPlots);
48 fPlotUses[plotID]++;
49 }
50
51 void decPlotUsage(int plotID) {
52 SkASSERT(plotID < kNumPlots);
53 SkASSERT(fPlotUses[plotID] > 0);
54 fPlotUses[plotID]--;
55 }
56
57 int plotUsage(int plotID) const {
58 SkASSERT(plotID < kNumPlots);
59 return fPlotUses[plotID];
60 }
61 #endif
62
63 const uint32_t fPictureID;
64 GrLayerAtlas::ClientPlotUsage fPlotUsage;
65
66 #if !GR_CACHE_HOISTED_LAYERS
67 private:
68 int fPlotUses[kNumPlots];
69 #endif
70 };
71
72 // GrCachedLayer encapsulates the caching information for a single saveLayer.
73 //
74 // Atlased layers get a ref to the backing GrTexture while non-atlased layers
75 // get a ref to the GrTexture in which they reside. In both cases 'fRect'
76 // contains the layer's extent in its texture.
77 // Atlased layers also get a pointer to the plot in which they reside.
78 // For non-atlased layers, the lock field just corresponds to locking in
79 // the resource cache. For atlased layers, it implements an additional level
80 // of locking to allow atlased layers to be reused multiple times.
81 struct GrCachedLayer {
82 public:
83 // For SkTDynamicHash
84 struct Key {
85 Key(uint32_t pictureID, const SkMatrix& initialMat,
86 const int* key, int keySize, bool copyKey = false)
87 : fKeySize(keySize)
88 , fFreeKey(copyKey) {
89 fIDMatrix.fPictureID = pictureID;
90 fIDMatrix.fInitialMat = initialMat;
91 fIDMatrix.fInitialMat.getType(); // force initialization of type so hashes match
92
93 if (copyKey) {
94 int* tempKey = new int[keySize];
95 memcpy(tempKey, key, keySize*sizeof(int));
96 fKey = tempKey;
97 } else {
98 fKey = key;
99 }
100
101 // The pictureID/matrix portion needs to be tightly packed.
102 GR_STATIC_ASSERT(sizeof(IDMatrix) == sizeof(uint32_t)+ // pictureID
103 9 * sizeof(SkScalar) + sizeof(uint3 2_t)); // matrix
104 }
105
106 ~Key() {
107 if (fFreeKey) {
108 delete[] fKey;
109 }
110 }
111
112 bool operator==(const Key& other) const {
113 if (fKeySize != other.fKeySize) {
114 return false;
115 }
116 return fIDMatrix.fPictureID == other.fIDMatrix.fPictureID &&
117 fIDMatrix.fInitialMat.cheapEqualTo(other.fIDMatrix.fInitialMa t) &&
118 !memcmp(fKey, other.fKey, fKeySize * sizeof(int));
119 }
120
121 uint32_t pictureID() const { return fIDMatrix.fPictureID; }
122
123 // TODO: remove these when GrCachedLayer & ReplacementInfo fuse
124 const int* key() const { SkASSERT(fFreeKey); return fKey; }
125 int keySize() const { SkASSERT(fFreeKey); return fKeySize; }
126
127 uint32_t hash() const {
128 uint32_t hash = SkChecksum::Murmur3(reinterpret_cast<const uint32_t* >(fKey),
129 fKeySize * sizeof(int));
130 return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(&fIDMat rix),
131 sizeof(IDMatrix), hash);
132 }
133
134 private:
135 struct IDMatrix {
136 // ID of the picture of which this layer is a part
137 uint32_t fPictureID;
138 // The initial matrix passed into drawPicture
139 SkMatrix fInitialMat;
140 } fIDMatrix;
141
142 const int* fKey;
143 const int fKeySize;
144 bool fFreeKey;
145 };
146
147 static const Key& GetKey(const GrCachedLayer& layer) { return layer.fKey; }
148 static uint32_t Hash(const Key& key) { return key.hash(); }
149
150 // GrCachedLayer proper
151 GrCachedLayer(uint32_t pictureID,
152 int start,
153 int stop,
154 const SkIRect& srcIR,
155 const SkIRect& dstIR,
156 const SkMatrix& ctm,
157 const int* key,
158 int keySize,
159 const SkPaint* paint)
160 : fKey(pictureID, ctm, key, keySize, true)
161 , fStart(start)
162 , fStop(stop)
163 , fSrcIR(srcIR)
164 , fDstIR(dstIR)
165 , fOffset(SkIPoint::Make(0, 0))
166 , fPaint(paint ? new SkPaint(*paint) : nullptr)
167 , fFilter(nullptr)
168 , fTexture(nullptr)
169 , fAtlased(false)
170 , fRect(SkIRect::MakeEmpty())
171 , fPlot(nullptr)
172 , fUses(0)
173 , fLocked(false) {
174 SkASSERT(SK_InvalidGenID != pictureID);
175
176 if (fPaint) {
177 if (fPaint->getImageFilter()) {
178 fFilter = SkSafeRef(fPaint->getImageFilter());
179 fPaint->setImageFilter(nullptr);
180 }
181 }
182 }
183
184 ~GrCachedLayer() {
185 if (!fAtlased) {
186 SkSafeUnref(fTexture);
187 }
188 SkSafeUnref(fFilter);
189 delete fPaint;
190 }
191
192 uint32_t pictureID() const { return fKey.pictureID(); }
193 // TODO: remove these when GrCachedLayer & ReplacementInfo fuse
194 const int* key() const { return fKey.key(); }
195 int keySize() const { return fKey.keySize(); }
196
197 int start() const { return fStart; }
198 // TODO: make bound debug only
199 const SkIRect& srcIR() const { return fSrcIR; }
200 const SkIRect& dstIR() const { return fDstIR; }
201 int stop() const { return fStop; }
202 void setTexture(GrTexture* texture, const SkIRect& rect, bool atlased) {
203 if (texture && !atlased) {
204 texture->ref(); // non-atlased textures carry a ref
205 }
206 if (fTexture && !fAtlased) {
207 fTexture->unref(); // non-atlased textures carry a ref
208 }
209 fTexture = texture;
210 fAtlased = atlased;
211 fRect = rect;
212 if (!fTexture) {
213 fLocked = false;
214 }
215 }
216 GrTexture* texture() { return fTexture; }
217 const SkPaint* paint() const { return fPaint; }
218 const SkImageFilter* filter() const { return fFilter; }
219 const SkIRect& rect() const { return fRect; }
220
221 void setOffset(const SkIPoint& offset) { fOffset = offset; }
222 const SkIPoint& offset() const { return fOffset; }
223
224 void setPlot(GrLayerAtlas::Plot* plot) {
225 SkASSERT(nullptr == plot || nullptr == fPlot);
226 fPlot = plot;
227 }
228 GrLayerAtlas::Plot* plot() { return fPlot; }
229
230 bool isAtlased() const { SkASSERT(fAtlased == SkToBool(fPlot)); return fAtla sed; }
231
232 void setLocked(bool locked) { fLocked = locked; }
233 bool locked() const { return fLocked; }
234
235 SkDEBUGCODE(const GrLayerAtlas::Plot* plot() const { return fPlot; })
236 SkDEBUGCODE(void validate(const GrTexture* backingTexture) const;)
237
238 private:
239 const Key fKey;
240
241 // The "saveLayer" operation index of the cached layer
242 const int fStart;
243 // The final "restore" operation index of the cached layer
244 const int fStop;
245
246 // The layer's src rect (i.e., the portion of the source scene required
247 // for filtering).
248 const SkIRect fSrcIR;
249 // The layer's dest rect (i.e., where it will land in device space)
250 const SkIRect fDstIR;
251 // Offset sometimes required by image filters
252 SkIPoint fOffset;
253
254 // The paint used when dropping the layer down into the owning canvas.
255 // Can be nullptr. This class makes a copy for itself.
256 SkPaint* fPaint;
257
258 // The imagefilter that needs to be applied to the layer prior to it being
259 // composited with the rest of the scene.
260 const SkImageFilter* fFilter;
261
262 // fTexture is a ref on the atlasing texture for atlased layers and a
263 // ref on a GrTexture for non-atlased textures.
264 GrTexture* fTexture;
265
266 // true if this layer is in the atlas (and 'fTexture' doesn't carry a ref)
267 // and false if the layer is a free floater (and carries a ref).
268 bool fAtlased;
269
270 // For both atlased and non-atlased layers 'fRect' contains the bound of
271 // the layer in whichever texture it resides. It is empty when 'fTexture'
272 // is nullptr.
273 SkIRect fRect;
274
275 // For atlased layers, fPlot stores the atlas plot in which the layer rests.
276 // It is always nullptr for non-atlased layers.
277 GrLayerAtlas::Plot* fPlot;
278
279 // The number of actively hoisted layers using this cached image (e.g.,
280 // extant GrHoistedLayers pointing at this object). This object will
281 // be unlocked when the use count reaches 0.
282 int fUses;
283
284 // For non-atlased layers 'fLocked' should always match "fTexture".
285 // (i.e., if there is a texture it is locked).
286 // For atlased layers, 'fLocked' is true if the layer is in a plot and
287 // actively required for rendering. If the layer is in a plot but not
288 // actively required for rendering, then 'fLocked' is false. If the
289 // layer isn't in a plot then is can never be locked.
290 bool fLocked;
291
292 void addUse() { ++fUses; }
293 void removeUse() { SkASSERT(fUses > 0); --fUses; }
294 int uses() const { return fUses; }
295
296 friend class GrLayerCache; // for access to usage methods
297 friend class TestingAccess; // for testing
298 };
299
300 // The GrLayerCache caches pre-computed saveLayers for later rendering.
301 // Non-atlased layers are stored in their own GrTexture while the atlased
302 // layers share a single GrTexture.
303 // Unlike the GrFontCache, the GrLayerCache only has one atlas (for 8888).
304 // As such, the GrLayerCache roughly combines the functionality of the
305 // GrFontCache and GrTextStrike classes.
306 class GrLayerCache {
307 public:
308 GrLayerCache(GrContext*);
309 ~GrLayerCache();
310
311 // As a cache, the GrLayerCache can be ordered to free up all its cached
312 // elements by the GrContext
313 void freeAll();
314
315 GrCachedLayer* findLayer(uint32_t pictureID, const SkMatrix& ctm,
316 const int* key, int keySize);
317 GrCachedLayer* findLayerOrCreate(uint32_t pictureID,
318 int start, int stop,
319 const SkIRect& srcIR,
320 const SkIRect& dstIR,
321 const SkMatrix& initialMat,
322 const int* key, int keySize,
323 const SkPaint* paint);
324
325 // Attempt to place 'layer' in the atlas. Return true on success; false on f ailure.
326 // When true is returned, 'needsRendering' will indicate if the layer must b e (re)drawn.
327 // Additionally, the GPU resources will be locked.
328 bool tryToAtlas(GrCachedLayer* layer, const GrSurfaceDesc& desc, bool* needs Rendering);
329
330 // Attempt to lock the GPU resources required for a layer. Return true on su ccess;
331 // false on failure. When true is returned 'needsRendering' will indicate if the
332 // layer must be (re)drawn.
333 // Note that atlased layers should already have been locked and rendered so only
334 // free floating layers will have 'needsRendering' set.
335 // Currently, this path always uses a new scratch texture for non-Atlased la yers
336 // and (thus) doesn't cache anything. This can yield a lot of re-rendering.
337 // TODO: allow rediscovery of free-floating layers that are still in the res ource cache.
338 bool lock(GrCachedLayer* layer, const GrSurfaceDesc& desc, bool* needsRender ing);
339
340 // addUse is just here to keep the API symmetric
341 void addUse(GrCachedLayer* layer) { layer->addUse(); }
342 void removeUse(GrCachedLayer* layer) {
343 layer->removeUse();
344 if (layer->uses() == 0) {
345 // If no one cares about the layer allow it to be recycled.
346 this->unlock(layer);
347 }
348 }
349
350 // Cleanup after any SkPicture deletions
351 void processDeletedPictures();
352
353 SkDEBUGCODE(void validate() const;)
354
355 #ifdef SK_DEBUG
356 void writeLayersToDisk(const SkString& dirName);
357 #endif
358
359 static bool PlausiblyAtlasable(int width, int height) {
360 return width <= kPlotWidth && height <= kPlotHeight;
361 }
362
363 void begin();
364 void end();
365
366 #if !GR_CACHE_HOISTED_LAYERS
367 void purgeAll();
368 #endif
369
370 private:
371 static const int kAtlasTextureWidth = 1024;
372 static const int kAtlasTextureHeight = 1024;
373
374 static const int kNumPlotsX = 2;
375 static const int kNumPlotsY = 2;
376
377 static const int kPlotWidth = kAtlasTextureWidth / kNumPlotsX;
378 static const int kPlotHeight = kAtlasTextureHeight / kNumPlotsY;
379
380 GrContext* fContext; // pointer back to owning context
381 SkAutoTDelete<GrLayerAtlas> fAtlas; // lazily allocated
382
383 // We cache this information here (rather then, say, on the owning picture)
384 // because we want to be able to clean it up as needed (e.g., if a picture
385 // is leaked and never cleans itself up we still want to be able to
386 // remove the GrPictureInfo once its layers are purged from all the atlas
387 // plots).
388 SkTDynamicHash<GrPictureInfo, uint32_t> fPictureHash;
389
390 SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key> fLayerHash;
391
392 SkMessageBus<SkPicture::DeletionMessage>::Inbox fPictDeletionInbox;
393
394 // This implements a plot-centric locking mechanism (since the atlas
395 // backing texture is always locked). Each layer that is locked (i.e.,
396 // needed for the current rendering) in a plot increments the plot lock
397 // count for that plot. Similarly, once a rendering is complete all the
398 // layers used in it decrement the lock count for the used plots.
399 // Plots with a 0 lock count are open for recycling/purging.
400 int fPlotLocks[kNumPlotsX * kNumPlotsY];
401
402 // Inform the cache that layer's cached image is not currently required
403 void unlock(GrCachedLayer* layer);
404
405 void initAtlas();
406 GrCachedLayer* createLayer(uint32_t pictureID, int start, int stop,
407 const SkIRect& srcIR, const SkIRect& dstIR,
408 const SkMatrix& initialMat,
409 const int* key, int keySize,
410 const SkPaint* paint);
411
412 // Remove all the layers (and unlock any resources) associated with 'picture ID'
413 void purge(uint32_t pictureID);
414
415 void purgePlot(GrLayerAtlas::Plot* plot);
416
417 // Either purge all un-locked plots or just one. Return true if >= 1 plot
418 // was purged; false otherwise.
419 bool purgePlots(bool justOne);
420
421 void incPlotLock(int plotIdx) { ++fPlotLocks[plotIdx]; }
422 void decPlotLock(int plotIdx) {
423 SkASSERT(fPlotLocks[plotIdx] > 0);
424 --fPlotLocks[plotIdx];
425 }
426
427 // for testing
428 friend class TestingAccess;
429 int numLayers() const { return fLayerHash.count(); }
430 };
431
432 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrLayerAtlas.cpp ('k') | src/gpu/GrLayerCache.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698