Clean up GrAtlas and rename it GrLayerAtlas
authorrobertphillips <robertphillips@google.com>
Tue, 3 Nov 2015 15:04:47 +0000 (07:04 -0800)
committerCommit bot <commit-bot@chromium.org>
Tue, 3 Nov 2015 15:04:48 +0000 (07:04 -0800)
Review URL: https://codereview.chromium.org/1412243013

gyp/gpu.gypi
src/gpu/GrAtlas.cpp [deleted file]
src/gpu/GrAtlas.h [deleted file]
src/gpu/GrLayerAtlas.cpp [new file with mode: 0644]
src/gpu/GrLayerAtlas.h [new file with mode: 0644]
src/gpu/GrLayerCache.cpp
src/gpu/GrLayerCache.h

index f0c6108..b3e89ff 100644 (file)
@@ -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',
       '<(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 (file)
index 3eb74f0..0000000
+++ /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 (file)
index aaec0b0..0000000
+++ /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 (file)
index 0000000..3b30607
--- /dev/null
@@ -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 (file)
index 0000000..ae08e45
--- /dev/null
@@ -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
index b2d4c4e..9af89a3 100644 (file)
@@ -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()]);
index 0fb23f2..914d0d5 100644 (file)
@@ -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.