15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2010 Google Inc.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file.
79ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch */
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifndef GrAtlas_DEFINED
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GrAtlas_DEFINED
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrTexture.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrDrawTarget.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "SkPoint.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "SkTInternalLList.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class GrGpu;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GrRectanizer;
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class GrAtlas;
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// The backing GrTexture for a set of GrAtlases is broken into a spatial grid of GrPlots. When
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// a GrAtlas needs space on the texture, it requests a GrPlot. Each GrAtlas can claim one
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or more GrPlots. The GrPlots keep track of subimage placement via their GrRectanizer. Once a
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GrPlot is "full" (i.e. there is no room for the new subimage according to the GrRectanizer), the
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GrAtlas can request a new GrPlot via GrAtlas::addToAtlas().
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If all GrPlots are allocated, the replacement strategy is up to the client. The drawToken is
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// available to ensure that all draw calls are finished for that particular GrPlot.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// GrAtlas::removeUnusedPlots() will free up any finished plots for a given GrAtlas.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GrPlot {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrPlot);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This returns a plot ID unique to each plot in a given GrAtlas. They are
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // consecutive and start at 0.
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int id() const { return fID; }
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrTexture* texture() const { return fTexture; }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool addSubImage(int width, int height, const void*, SkIPoint16*);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrDrawTarget::DrawToken drawToken() const { return fDrawToken; }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void setDrawToken(GrDrawTarget::DrawToken draw) { fDrawToken = draw; }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void uploadToTexture();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void resetRects();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)private:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrPlot();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~GrPlot(); // does not try to delete the fNext field
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void init(GrAtlas* atlas, int id, int offX, int offY, int width, int height, size_t bpp,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              bool batchUploads);
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for recycling
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrDrawTarget::DrawToken fDrawToken;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int                     fID;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char*          fPlotData;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrTexture*              fTexture;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrRectanizer*           fRects;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrAtlas*                fAtlas;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkIPoint16              fOffset;        // the offset of the plot in the backing texture
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t                  fBytesPerPixel;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkIRect                 fDirtyRect;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool                    fDirty;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool                    fBatchUploads;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend class GrAtlas;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SkTInternalLList<GrPlot> GrPlotList;
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class GrAtlas {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This class allows each client to independently track the GrPlots in
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which its data is stored.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    class ClientPlotUsage {
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    public:
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        bool isEmpty() const { return 0 == fPlots.count(); }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SK_DEBUG
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool contains(const GrPlot* plot) const {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return fPlots.contains(const_cast<GrPlot*>(plot));
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private:
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SkTDArray<GrPlot*> fPlots;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        friend class GrAtlas;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    };
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    GrAtlas(GrGpu*, GrPixelConfig, GrTextureFlags flags,
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            const SkISize& backingTextureSize,
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            int numPlotsX, int numPlotsY, bool batchUploads);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~GrAtlas();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Adds a width x height subimage to the atlas. Upon success it returns
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // the containing GrPlot and absolute location in the backing texture.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NULL is returned if the subimage cannot fit in the atlas.
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // If provided, the image data will either be immediately uploaded or
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // written to the CPU-side backing bitmap.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrPlot* addToAtlas(ClientPlotUsage*, int width, int height, const void* image, SkIPoint16* loc);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // remove reference to this plot
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static void RemovePlot(ClientPlotUsage* usage, const GrPlot* plot);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // get a plot that's not being used by the current draw
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this allows us to overwrite this plot without flushing
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    GrPlot* getUnusedPlot();
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GrTexture* getTexture() const {
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return fTexture;
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    void uploadPlotsToTexture();
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum IterOrder {
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        kLRUFirst_IterOrder,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kMRUFirst_IterOrder
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    typedef GrPlotList::Iter PlotIter;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrPlot* iterInit(PlotIter* iter, IterOrder order) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return iter->init(fPlotList, kLRUFirst_IterOrder == order
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                       ? GrPlotList::Iter::kTail_IterStart
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       : GrPlotList::Iter::kHead_IterStart);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void makeMRU(GrPlot* plot);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    GrGpu*         fGpu;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrPixelConfig  fPixelConfig;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrTextureFlags fFlags;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GrTexture*     fTexture;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkISize        fBackingTextureSize;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int            fNumPlotsX;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int            fNumPlotsY;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool           fBatchUploads;
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // allocated array of GrPlots
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GrPlot*       fPlotArray;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // LRU list of GrPlots (MRU at head - LRU at tail)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GrPlotList    fPlotList;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)