aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2015-11-03 07:04:47 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-03 07:04:48 -0800
commite51fa4ac31716863b80633419370e7e4174ead61 (patch)
tree558f259a11992ceecf0961f2b2df58bb0440765c
parentf27f08b76d3c99bbca8b56a38faddbb58239c94c (diff)
Clean up GrAtlas and rename it GrLayerAtlas
-rw-r--r--gyp/gpu.gypi4
-rw-r--r--src/gpu/GrAtlas.cpp229
-rw-r--r--src/gpu/GrAtlas.h137
-rw-r--r--src/gpu/GrLayerAtlas.cpp145
-rw-r--r--src/gpu/GrLayerAtlas.h145
-rw-r--r--src/gpu/GrLayerCache.cpp34
-rw-r--r--src/gpu/GrLayerCache.h24
7 files changed, 323 insertions, 395 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index f0c610831e..b3e89ffba1 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -57,8 +57,6 @@
'<(skia_src_path)/gpu/GrAutoLocaleSetter.h',
'<(skia_src_path)/gpu/GrAllocator.h',
- '<(skia_src_path)/gpu/GrAtlas.cpp',
- '<(skia_src_path)/gpu/GrAtlas.h',
'<(skia_src_path)/gpu/GrAtlasTextBlob.cpp',
'<(skia_src_path)/gpu/GrAtlasTextBlob.h',
'<(skia_src_path)/gpu/GrAtlasTextContext.cpp',
@@ -104,6 +102,8 @@
'<(skia_src_path)/gpu/GrGpuFactory.h',
'<(skia_src_path)/gpu/GrIndexBuffer.h',
'<(skia_src_path)/gpu/GrInvariantOutput.cpp',
+ '<(skia_src_path)/gpu/GrLayerAtlas.cpp',
+ '<(skia_src_path)/gpu/GrLayerAtlas.h',
'<(skia_src_path)/gpu/GrLayerCache.cpp',
'<(skia_src_path)/gpu/GrLayerCache.h',
'<(skia_src_path)/gpu/GrLayerHoister.cpp',
diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp
deleted file mode 100644
index 3eb74f074b..0000000000
--- a/src/gpu/GrAtlas.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrAtlas.h"
-#include "GrContext.h"
-#include "GrGpu.h"
-#include "GrRectanizer.h"
-#include "GrTracing.h"
-
-///////////////////////////////////////////////////////////////////////////////
-
-// for testing
-#define FONT_CACHE_STATS 0
-#if FONT_CACHE_STATS
-static int g_UploadCount = 0;
-#endif
-
-GrPlot::GrPlot()
- : fID(-1)
- , fTexture(nullptr)
- , fRects(nullptr)
- , fAtlas(nullptr)
- , fBytesPerPixel(1)
- , fDirty(false)
- , fBatchUploads(false)
-{
- fOffset.set(0, 0);
-}
-
-GrPlot::~GrPlot() {
- delete[] fPlotData;
- fPlotData = nullptr;
- delete fRects;
-}
-
-void GrPlot::init(GrAtlas* atlas, int id, int offX, int offY, int width, int height, size_t bpp,
- bool batchUploads) {
- fID = id;
- fRects = GrRectanizer::Factory(width, height);
- fAtlas = atlas;
- fOffset.set(offX * width, offY * height);
- fBytesPerPixel = bpp;
- fPlotData = nullptr;
- fDirtyRect.setEmpty();
- fDirty = false;
- fBatchUploads = batchUploads;
-}
-
-static inline void adjust_for_offset(SkIPoint16* loc, const SkIPoint16& offset) {
- loc->fX += offset.fX;
- loc->fY += offset.fY;
-}
-
-bool GrPlot::addSubImage(int width, int height, const void* image, SkIPoint16* loc) {
- float percentFull = fRects->percentFull();
- if (!fRects->addRect(width, height, loc)) {
- return false;
- }
-
- // if batching uploads, create backing memory on first use
- // once the plot is nearly full we will revert to uploading each subimage individually
- int plotWidth = fRects->width();
- int plotHeight = fRects->height();
- if (fBatchUploads && nullptr == fPlotData && 0.0f == percentFull) {
- fPlotData = new unsigned char[fBytesPerPixel * plotWidth * plotHeight];
- memset(fPlotData, 0, fBytesPerPixel*plotWidth*plotHeight);
- }
-
- // if we have backing memory, copy to the memory and set for future upload
- if (fPlotData) {
- const unsigned char* imagePtr = (const unsigned char*) image;
- // point ourselves at the right starting spot
- unsigned char* dataPtr = fPlotData;
- dataPtr += fBytesPerPixel*plotWidth*loc->fY;
- dataPtr += fBytesPerPixel*loc->fX;
- // copy into the data buffer
- for (int i = 0; i < height; ++i) {
- memcpy(dataPtr, imagePtr, fBytesPerPixel*width);
- dataPtr += fBytesPerPixel*plotWidth;
- imagePtr += fBytesPerPixel*width;
- }
-
- fDirtyRect.join(loc->fX, loc->fY, loc->fX + width, loc->fY + height);
- adjust_for_offset(loc, fOffset);
- fDirty = true;
- // otherwise, just upload the image directly
- } else if (image) {
- adjust_for_offset(loc, fOffset);
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "GrPlot::uploadToTexture");
- fTexture->writePixels(loc->fX, loc->fY, width, height, fTexture->config(), image, 0,
- GrContext::kDontFlush_PixelOpsFlag);
- } else {
- adjust_for_offset(loc, fOffset);
- }
-
-#if FONT_CACHE_STATS
- ++g_UploadCount;
-#endif
-
- return true;
-}
-
-void GrPlot::resetRects() {
- SkASSERT(fRects);
- fRects->reset();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-GrAtlas::GrAtlas(GrGpu* gpu, GrPixelConfig config, GrSurfaceFlags flags,
- const SkISize& backingTextureSize,
- int numPlotsX, int numPlotsY, bool batchUploads) {
- fGpu = SkRef(gpu);
- fPixelConfig = config;
- fFlags = flags;
- fBackingTextureSize = backingTextureSize;
- fNumPlotsX = numPlotsX;
- fNumPlotsY = numPlotsY;
- fBatchUploads = batchUploads;
- fTexture = nullptr;
-
- int textureWidth = fBackingTextureSize.width();
- int textureHeight = fBackingTextureSize.height();
-
- int plotWidth = textureWidth / fNumPlotsX;
- int plotHeight = textureHeight / fNumPlotsY;
-
- SkASSERT(plotWidth * fNumPlotsX == textureWidth);
- SkASSERT(plotHeight * fNumPlotsY == textureHeight);
-
- // We currently do not support compressed atlases...
- SkASSERT(!GrPixelConfigIsCompressed(config));
-
- // set up allocated plots
- size_t bpp = GrBytesPerPixel(fPixelConfig);
- fPlotArray = new GrPlot[(fNumPlotsX * fNumPlotsY)];
-
- GrPlot* currPlot = fPlotArray;
- for (int y = numPlotsY-1; y >= 0; --y) {
- for (int x = numPlotsX-1; x >= 0; --x) {
- currPlot->init(this, y*numPlotsX+x, x, y, plotWidth, plotHeight, bpp, batchUploads);
-
- // build LRU list
- fPlotList.addToHead(currPlot);
- ++currPlot;
- }
- }
-}
-
-GrAtlas::~GrAtlas() {
- SkSafeUnref(fTexture);
- delete[] fPlotArray;
-
- fGpu->unref();
-#if FONT_CACHE_STATS
- SkDebugf("Num uploads: %d\n", g_UploadCount);
-#endif
-}
-
-void GrAtlas::makeMRU(GrPlot* plot) {
- if (fPlotList.head() == plot) {
- return;
- }
-
- fPlotList.remove(plot);
- fPlotList.addToHead(plot);
-};
-
-GrPlot* GrAtlas::addToAtlas(ClientPlotUsage* usage,
- int width, int height, const void* image,
- SkIPoint16* loc) {
- // iterate through entire plot list for this atlas, see if we can find a hole
- // last one was most recently added and probably most empty
- for (int i = usage->fPlots.count()-1; i >= 0; --i) {
- GrPlot* plot = usage->fPlots[i];
- // client may have plots from more than one atlas, must check for ours before adding
- if (this == plot->fAtlas && plot->addSubImage(width, height, image, loc)) {
- this->makeMRU(plot);
- return plot;
- }
- }
-
- // before we get a new plot, make sure we have a backing texture
- if (nullptr == fTexture) {
- // TODO: Update this to use the cache rather than directly creating a texture.
- GrSurfaceDesc desc;
- desc.fFlags = fFlags;
- desc.fWidth = fBackingTextureSize.width();
- desc.fHeight = fBackingTextureSize.height();
- desc.fConfig = fPixelConfig;
-
- fTexture = fGpu->createTexture(desc, true, nullptr, 0);
- if (nullptr == fTexture) {
- return nullptr;
- }
- }
-
- // now look through all allocated plots for one we can share, in MRU order
- GrPlotList::Iter plotIter;
- plotIter.init(fPlotList, GrPlotList::Iter::kHead_IterStart);
- GrPlot* plot;
- while ((plot = plotIter.get())) {
- // make sure texture is set for quick lookup
- plot->fTexture = fTexture;
- if (plot->addSubImage(width, height, image, loc)) {
- this->makeMRU(plot);
- // new plot for atlas, put at end of array
- SkASSERT(!usage->fPlots.contains(plot));
- *(usage->fPlots.append()) = plot;
- return plot;
- }
- plotIter.next();
- }
-
- // If the above fails, then the current plot list has no room
- return nullptr;
-}
-
-void GrAtlas::RemovePlot(ClientPlotUsage* usage, const GrPlot* plot) {
- int index = usage->fPlots.find(const_cast<GrPlot*>(plot));
- if (index >= 0) {
- usage->fPlots.remove(index);
- }
-}
diff --git a/src/gpu/GrAtlas.h b/src/gpu/GrAtlas.h
deleted file mode 100644
index aaec0b02d9..0000000000
--- a/src/gpu/GrAtlas.h
+++ /dev/null
@@ -1,137 +0,0 @@
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrAtlas_DEFINED
-#define GrAtlas_DEFINED
-
-
-#include "SkTDArray.h"
-#include "GrTexture.h"
-#include "SkPoint.h"
-#include "SkTInternalLList.h"
-
-class GrGpu;
-class GrRectanizer;
-class GrAtlas;
-
-// The backing GrTexture for a set of GrAtlases is broken into a spatial grid of GrPlots. When
-// a GrAtlas needs space on the texture, it requests a GrPlot. Each GrAtlas can claim one
-// or more GrPlots. The GrPlots keep track of subimage placement via their GrRectanizer. Once a
-// GrPlot is "full" (i.e. there is no room for the new subimage according to the GrRectanizer), the
-// GrAtlas can request a new GrPlot via GrAtlas::addToAtlas().
-//
-// If all GrPlots are allocated, the replacement strategy is up to the client. The drawToken is
-// available to ensure that all draw calls are finished for that particular GrPlot.
-// GrAtlas::removeUnusedPlots() will free up any finished plots for a given GrAtlas.
-
-class GrPlot {
-public:
- SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrPlot);
-
- // This returns a plot ID unique to each plot in a given GrAtlas. They are
- // consecutive and start at 0.
- int id() const { return fID; }
-
- GrTexture* texture() const { return fTexture; }
-
- bool addSubImage(int width, int height, const void*, SkIPoint16*);
-
- void resetRects();
-
-private:
- GrPlot();
- ~GrPlot(); // does not try to delete the fNext field
- void init(GrAtlas* atlas, int id, int offX, int offY, int width, int height, size_t bpp,
- bool batchUploads);
-
- int fID;
- unsigned char* fPlotData;
- GrTexture* fTexture;
- GrRectanizer* fRects;
- GrAtlas* fAtlas;
- SkIPoint16 fOffset; // the offset of the plot in the backing texture
- size_t fBytesPerPixel;
- SkIRect fDirtyRect;
- bool fDirty;
- bool fBatchUploads;
-
- friend class GrAtlas;
-};
-
-typedef SkTInternalLList<GrPlot> GrPlotList;
-
-class GrAtlas {
-public:
- // This class allows each client to independently track the GrPlots in
- // which its data is stored.
- class ClientPlotUsage {
- public:
- bool isEmpty() const { return 0 == fPlots.count(); }
-
-#ifdef SK_DEBUG
- bool contains(const GrPlot* plot) const {
- return fPlots.contains(const_cast<GrPlot*>(plot));
- }
-#endif
-
- private:
- SkTDArray<GrPlot*> fPlots;
-
- friend class GrAtlas;
- };
-
- GrAtlas(GrGpu*, GrPixelConfig, GrSurfaceFlags flags,
- const SkISize& backingTextureSize,
- int numPlotsX, int numPlotsY, bool batchUploads);
- ~GrAtlas();
-
- // Adds a width x height subimage to the atlas. Upon success it returns
- // the containing GrPlot and absolute location in the backing texture.
- // nullptr is returned if the subimage cannot fit in the atlas.
- // If provided, the image data will either be immediately uploaded or
- // written to the CPU-side backing bitmap.
- GrPlot* addToAtlas(ClientPlotUsage*, int width, int height, const void* image, SkIPoint16* loc);
-
- // remove reference to this plot
- static void RemovePlot(ClientPlotUsage* usage, const GrPlot* plot);
-
- GrTexture* getTexture() const {
- return fTexture;
- }
-
- enum IterOrder {
- kLRUFirst_IterOrder,
- kMRUFirst_IterOrder
- };
-
- typedef GrPlotList::Iter PlotIter;
- GrPlot* iterInit(PlotIter* iter, IterOrder order) {
- return iter->init(fPlotList, kLRUFirst_IterOrder == order
- ? GrPlotList::Iter::kTail_IterStart
- : GrPlotList::Iter::kHead_IterStart);
- }
-
-private:
- void makeMRU(GrPlot* plot);
-
- GrGpu* fGpu;
- GrPixelConfig fPixelConfig;
- GrSurfaceFlags fFlags;
- GrTexture* fTexture;
- SkISize fBackingTextureSize;
- int fNumPlotsX;
- int fNumPlotsY;
- bool fBatchUploads;
-
- // allocated array of GrPlots
- GrPlot* fPlotArray;
- // LRU list of GrPlots (MRU at head - LRU at tail)
- GrPlotList fPlotList;
-};
-
-#endif
diff --git a/src/gpu/GrLayerAtlas.cpp b/src/gpu/GrLayerAtlas.cpp
new file mode 100644
index 0000000000..3b30607c8c
--- /dev/null
+++ b/src/gpu/GrLayerAtlas.cpp
@@ -0,0 +1,145 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrLayerAtlas.h"
+#include "GrRectanizer.h"
+#include "GrTextureProvider.h"
+
+///////////////////////////////////////////////////////////////////////////////
+GrLayerAtlas::Plot::Plot()
+ : fID(-1)
+ , fRects(nullptr) {
+ fOffset.set(0, 0);
+}
+
+GrLayerAtlas::Plot::~Plot() {
+ delete fRects;
+}
+
+void GrLayerAtlas::Plot::init(int id, int offX, int offY, int width, int height) {
+ fID = id;
+ fRects = GrRectanizer::Factory(width, height);
+ fOffset.set(offX * width, offY * height);
+}
+
+bool GrLayerAtlas::Plot::allocateRect(int width, int height, SkIPoint16* loc) {
+ if (!fRects->addRect(width, height, loc)) {
+ return false;
+ }
+
+ loc->fX += fOffset.fX;
+ loc->fY += fOffset.fY;
+ return true;
+}
+
+void GrLayerAtlas::Plot::reset() {
+ SkASSERT(fRects);
+ fRects->reset();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GrLayerAtlas::GrLayerAtlas(GrTextureProvider* texProvider, GrPixelConfig config,
+ GrSurfaceFlags flags,
+ const SkISize& backingTextureSize,
+ int numPlotsX, int numPlotsY) {
+ fTexProvider = texProvider;
+ fPixelConfig = config;
+ fFlags = flags;
+ fBackingTextureSize = backingTextureSize;
+ fTexture = nullptr;
+
+ int textureWidth = fBackingTextureSize.width();
+ int textureHeight = fBackingTextureSize.height();
+
+ int plotWidth = textureWidth / numPlotsX;
+ int plotHeight = textureHeight / numPlotsY;
+
+ SkASSERT(plotWidth * numPlotsX == textureWidth);
+ SkASSERT(plotHeight * numPlotsY == textureHeight);
+
+ // We currently do not support compressed atlases...
+ SkASSERT(!GrPixelConfigIsCompressed(config));
+
+ // set up allocated plots
+ fPlotArray = new Plot[numPlotsX * numPlotsY];
+
+ Plot* currPlot = fPlotArray;
+ for (int y = numPlotsY-1; y >= 0; --y) {
+ for (int x = numPlotsX-1; x >= 0; --x) {
+ currPlot->init(y*numPlotsX+x, x, y, plotWidth, plotHeight);
+
+ // build LRU list
+ fPlotList.addToHead(currPlot);
+ ++currPlot;
+ }
+ }
+}
+
+GrLayerAtlas::~GrLayerAtlas() {
+ SkSafeUnref(fTexture);
+ delete[] fPlotArray;
+}
+
+void GrLayerAtlas::makeMRU(Plot* plot) {
+ if (fPlotList.head() == plot) {
+ return;
+ }
+
+ fPlotList.remove(plot);
+ fPlotList.addToHead(plot);
+};
+
+GrLayerAtlas::Plot* GrLayerAtlas::addToAtlas(ClientPlotUsage* usage,
+ int width, int height, SkIPoint16* loc) {
+ // Iterate through the plots currently being used by this client and see if we can find a hole.
+ // The last one was most recently added and probably most empty.
+ // We want to consolidate the uses from individual clients to the same plot(s) so that
+ // when a specific client goes away they are more likely to completely empty a plot.
+ for (int i = usage->numPlots()-1; i >= 0; --i) {
+ Plot* plot = usage->plot(i);
+ if (plot->allocateRect(width, height, loc)) {
+ this->makeMRU(plot);
+ return plot;
+ }
+ }
+
+ // before we get a new plot, make sure we have a backing texture
+ if (nullptr == fTexture) {
+ // TODO: Update this to use the cache rather than directly creating a texture.
+ GrSurfaceDesc desc;
+ desc.fFlags = fFlags;
+ desc.fWidth = fBackingTextureSize.width();
+ desc.fHeight = fBackingTextureSize.height();
+ desc.fConfig = fPixelConfig;
+
+ fTexture = fTexProvider->createTexture(desc, true, nullptr, 0);
+ if (nullptr == fTexture) {
+ return nullptr;
+ }
+ }
+
+ // Now look through all allocated plots for one we can share, in MRU order
+ // TODO: its seems like traversing from emptiest to fullest would make more sense
+ PlotList::Iter plotIter;
+ plotIter.init(fPlotList, PlotList::Iter::kHead_IterStart);
+ Plot* plot;
+ while ((plot = plotIter.get())) {
+ if (plot->allocateRect(width, height, loc)) {
+ this->makeMRU(plot);
+ // new plot for atlas, put at end of array
+ usage->appendPlot(plot);
+ return plot;
+ }
+ plotIter.next();
+ }
+
+ // If the above fails, then the current plot list has no room
+ return nullptr;
+}
+
diff --git a/src/gpu/GrLayerAtlas.h b/src/gpu/GrLayerAtlas.h
new file mode 100644
index 0000000000..ae08e4527b
--- /dev/null
+++ b/src/gpu/GrLayerAtlas.h
@@ -0,0 +1,145 @@
+
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrLayerAtlas_DEFINED
+#define GrLayerAtlas_DEFINED
+
+#include "GrTypes.h"
+
+#include "SkPoint.h"
+#include "SkSize.h"
+#include "SkTDArray.h"
+#include "SkTInternalLList.h"
+
+class GrLayerAtlas;
+class GrTexture;
+class GrTextureProvider;
+class GrRectanizer;
+
+// The backing GrTexture for a GrLayerAtlas is broken into a spatial grid of Plots. When
+// the atlas needs space on the texture (i.e., in response to an addToAtlas call), it
+// iterates through the plots in use by the requesting client looking for space and,
+// if no space is found, opens up a new Plot for that client. The Plots keep track of
+// subimage placement via their GrRectanizer.
+//
+// If all Plots are full, the replacement strategy is up to the client. The Plot::reset
+// call will remove a Plot's knowledge of any allocated rects - freeing its space for reuse.
+
+class GrLayerAtlas {
+public:
+ class Plot {
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(Plot); // In an MRU llist
+
+ public:
+ // This returns a plot ID unique to each plot in the atlas. They are
+ // consecutive and start at 0.
+ int id() const { return fID; }
+
+ void reset();
+
+ private:
+ friend class GrLayerAtlas;
+
+ Plot();
+ ~Plot(); // does not try to delete the fNext field
+
+ void init(int id, int offX, int offY, int width, int height);
+
+ bool allocateRect(int width, int height, SkIPoint16*);
+
+ int fID;
+ GrRectanizer* fRects;
+ SkIPoint16 fOffset; // the offset of the plot in the backing texture
+ };
+
+ // This class allows each client to independently track the Plots in
+ // which its data is stored.
+ // For example, multiple pictures may simultaneously store their layers in the
+ // layer atlas. When a picture goes away it can use the ClientPlotUsage to remove itself
+ // from those plots.
+ class ClientPlotUsage {
+ public:
+ ClientPlotUsage(int maxPlots)
+ SkDEBUGCODE(: fMaxPlots(maxPlots)) {
+ fPlots.setReserve(maxPlots);
+ }
+
+ bool isEmpty() const { return 0 == fPlots.count(); }
+
+ int numPlots() const { return fPlots.count(); }
+ Plot* plot(int index) { return fPlots[index]; }
+
+ void appendPlot(Plot* plot) {
+ SkASSERT(fPlots.count() <= fMaxPlots);
+ SkASSERT(!fPlots.contains(plot));
+ *fPlots.append() = plot;
+ }
+
+ // remove reference to 'plot'
+ void removePlot(const Plot* plot) {
+ int index = fPlots.find(const_cast<Plot*>(plot));
+ if (index >= 0) {
+ fPlots.remove(index);
+ }
+ }
+
+#ifdef SK_DEBUG
+ bool contains(const Plot* plot) const {
+ return fPlots.contains(const_cast<Plot*>(plot));
+ }
+#endif
+
+ private:
+ SkTDArray<Plot*> fPlots;
+ SkDEBUGCODE(int fMaxPlots;)
+ };
+
+ GrLayerAtlas(GrTextureProvider*, GrPixelConfig, GrSurfaceFlags flags,
+ const SkISize& backingTextureSize,
+ int numPlotsX, int numPlotsY);
+ ~GrLayerAtlas();
+
+ // Requests a width x height block in the atlas. Upon success it returns
+ // the containing Plot and absolute location in the backing texture.
+ // nullptr is returned if there is no more space in the atlas.
+ Plot* addToAtlas(ClientPlotUsage*, int width, int height, SkIPoint16* loc);
+
+ GrTexture* getTexture() const {
+ return fTexture;
+ }
+
+ enum IterOrder {
+ kLRUFirst_IterOrder,
+ kMRUFirst_IterOrder
+ };
+
+ typedef SkTInternalLList<Plot> PlotList;
+ typedef PlotList::Iter PlotIter;
+ Plot* iterInit(PlotIter* iter, IterOrder order) {
+ return iter->init(fPlotList, kLRUFirst_IterOrder == order
+ ? PlotList::Iter::kTail_IterStart
+ : PlotList::Iter::kHead_IterStart);
+ }
+
+private:
+ void makeMRU(Plot* plot);
+
+ GrTextureProvider* fTexProvider;
+ GrPixelConfig fPixelConfig;
+ GrSurfaceFlags fFlags;
+ GrTexture* fTexture;
+
+ SkISize fBackingTextureSize;
+
+ // allocated array of Plots
+ Plot* fPlotArray;
+ // LRU list of Plots (MRU at head - LRU at tail)
+ PlotList fPlotList;
+};
+
+#endif
diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp
index b2d4c4ed76..9af89a3466 100644
--- a/src/gpu/GrLayerCache.cpp
+++ b/src/gpu/GrLayerCache.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "GrAtlas.h"
+#include "GrLayerAtlas.h"
#include "GrContext.h"
#include "GrDrawContext.h"
#include "GrGpu.h"
@@ -104,9 +104,9 @@ void GrLayerCache::initAtlas() {
GR_STATIC_ASSERT(kNumPlotsX*kNumPlotsX == GrPictureInfo::kNumPlots);
SkISize textureSize = SkISize::Make(kAtlasTextureWidth, kAtlasTextureHeight);
- fAtlas.reset(new GrAtlas(fContext->getGpu(), kSkia8888_GrPixelConfig,
- kRenderTarget_GrSurfaceFlag, textureSize, kNumPlotsX, kNumPlotsY,
- false));
+ fAtlas.reset(new GrLayerAtlas(fContext->textureProvider(), kSkia8888_GrPixelConfig,
+ kRenderTarget_GrSurfaceFlag, textureSize,
+ kNumPlotsX, kNumPlotsY));
}
void GrLayerCache::freeAll() {
@@ -205,9 +205,9 @@ bool GrLayerCache::tryToAtlas(GrCachedLayer* layer,
SkIPoint16 loc;
for (int i = 0; i < 2; ++i) { // extra pass in case we fail to add but are able to purge
- GrPlot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage,
- desc.fWidth, desc.fHeight,
- nullptr, &loc);
+ GrLayerAtlas::Plot* plot = fAtlas->addToAtlas(&pictInfo->fPlotUsage,
+ desc.fWidth, desc.fHeight,
+ &loc);
// addToAtlas can allocate the backing texture
SkDEBUGCODE(avl.setBackingTexture(fAtlas->getTexture()));
if (plot) {
@@ -290,7 +290,7 @@ void GrLayerCache::unlock(GrCachedLayer* layer) {
pictInfo->decPlotUsage(plotID);
if (0 == pictInfo->plotUsage(plotID)) {
- GrAtlas::RemovePlot(&pictInfo->fPlotUsage, layer->plot());
+ pictInfo->fPlotUsage.removePlot(layer->plot());
if (pictInfo->fPlotUsage.isEmpty()) {
fPictureHash.remove(pictInfo->fPictureID);
@@ -393,9 +393,9 @@ bool GrLayerCache::purgePlot() {
SkDEBUGCODE(GrAutoValidateCache avc(this);)
SkASSERT(fAtlas);
- GrAtlas::PlotIter iter;
- GrPlot* plot;
- for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder);
+ GrLayerAtlas::PlotIter iter;
+ GrLayerAtlas::Plot* plot;
+ for (plot = fAtlas->iterInit(&iter, GrLayerAtlas::kLRUFirst_IterOrder);
plot;
plot = iter.prev()) {
if (fPlotLocks[plot->id()] > 0) {
@@ -409,7 +409,7 @@ bool GrLayerCache::purgePlot() {
return false;
}
-void GrLayerCache::purgePlot(GrPlot* plot) {
+void GrLayerCache::purgePlot(GrLayerAtlas::Plot* plot) {
SkASSERT(0 == fPlotLocks[plot->id()]);
// We need to find all the layers in 'plot' and remove them.
@@ -437,7 +437,7 @@ void GrLayerCache::purgePlot(GrPlot* plot) {
#if !GR_CACHE_HOISTED_LAYERS
SkASSERT(0 == pictInfo->plotUsage(plot->id()));
#endif
- GrAtlas::RemovePlot(&pictInfo->fPlotUsage, plot);
+ pictInfo->fPlotUsage.removePlot(plot);
if (pictInfo->fPlotUsage.isEmpty()) {
fPictureHash.remove(pictInfo->fPictureID);
@@ -446,7 +446,7 @@ void GrLayerCache::purgePlot(GrPlot* plot) {
}
}
- plot->resetRects();
+ plot->reset();
}
#if !GR_CACHE_HOISTED_LAYERS
@@ -455,9 +455,9 @@ void GrLayerCache::purgeAll() {
return;
}
- GrAtlas::PlotIter iter;
- GrPlot* plot;
- for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder);
+ GrLayerAtlas::PlotIter iter;
+ GrLayerAtlas::Plot* plot;
+ for (plot = fAtlas->iterInit(&iter, GrLayerAtlas::kLRUFirst_IterOrder);
plot;
plot = iter.prev()) {
SkASSERT(0 == fPlotLocks[plot->id()]);
diff --git a/src/gpu/GrLayerCache.h b/src/gpu/GrLayerCache.h
index 0fb23f2298..914d0d5a58 100644
--- a/src/gpu/GrLayerCache.h
+++ b/src/gpu/GrLayerCache.h
@@ -8,7 +8,9 @@
#ifndef GrLayerCache_DEFINED
#define GrLayerCache_DEFINED
-#include "GrAtlas.h"
+
+#include "GrLayerAtlas.h"
+#include "GrTexture.h"
#include "GrRect.h"
#include "SkChecksum.h"
@@ -31,7 +33,9 @@ public:
static uint32_t Hash(const uint32_t& key) { return SkChecksum::Mix(key); }
// GrPictureInfo proper
- GrPictureInfo(uint32_t pictureID) : fPictureID(pictureID) {
+ GrPictureInfo(uint32_t pictureID)
+ : fPictureID(pictureID)
+ , fPlotUsage(kNumPlots) {
#if !GR_CACHE_HOISTED_LAYERS
memset(fPlotUses, 0, sizeof(fPlotUses));
#endif
@@ -56,7 +60,7 @@ public:
#endif
const uint32_t fPictureID;
- GrAtlas::ClientPlotUsage fPlotUsage;
+ GrLayerAtlas::ClientPlotUsage fPlotUsage;
#if !GR_CACHE_HOISTED_LAYERS
private:
@@ -206,18 +210,18 @@ public:
void setOffset(const SkIPoint& offset) { fOffset = offset; }
const SkIPoint& offset() const { return fOffset; }
- void setPlot(GrPlot* plot) {
+ void setPlot(GrLayerAtlas::Plot* plot) {
SkASSERT(nullptr == plot || nullptr == fPlot);
fPlot = plot;
}
- GrPlot* plot() { return fPlot; }
+ GrLayerAtlas::Plot* plot() { return fPlot; }
bool isAtlased() const { return SkToBool(fPlot); }
void setLocked(bool locked) { fLocked = locked; }
bool locked() const { return fLocked; }
- SkDEBUGCODE(const GrPlot* plot() const { return fPlot; })
+ SkDEBUGCODE(const GrLayerAtlas::Plot* plot() const { return fPlot; })
SkDEBUGCODE(void validate(const GrTexture* backingTexture) const;)
private:
@@ -255,7 +259,7 @@ private:
// For atlased layers, fPlot stores the atlas plot in which the layer rests.
// It is always nullptr for non-atlased layers.
- GrPlot* fPlot;
+ GrLayerAtlas::Plot* fPlot;
// The number of actively hoisted layers using this cached image (e.g.,
// extant GrHoistedLayers pointing at this object). This object will
@@ -356,8 +360,8 @@ private:
static const int kPlotWidth = kAtlasTextureWidth / kNumPlotsX;
static const int kPlotHeight = kAtlasTextureHeight / kNumPlotsY;
- GrContext* fContext; // pointer back to owning context
- SkAutoTDelete<GrAtlas> fAtlas; // TODO: could lazily allocate
+ GrContext* fContext; // pointer back to owning context
+ SkAutoTDelete<GrLayerAtlas> fAtlas; // TODO: could lazily allocate
// We cache this information here (rather then, say, on the owning picture)
// because we want to be able to clean it up as needed (e.g., if a picture
@@ -391,7 +395,7 @@ private:
// Remove all the layers (and unlock any resources) associated with 'pictureID'
void purge(uint32_t pictureID);
- void purgePlot(GrPlot* plot);
+ void purgePlot(GrLayerAtlas::Plot* plot);
// Try to find a purgeable plot and clear it out. Return true if a plot
// was purged; false otherwise.