Home | History | Annotate | Download | only in gpu
      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 GrPathRange_DEFINED
      9 #define GrPathRange_DEFINED
     10 
     11 #include "GrGpuResource.h"
     12 #include "SkPath.h"
     13 #include "SkRefCnt.h"
     14 #include "SkTArray.h"
     15 
     16 class SkDescriptor;
     17 
     18 /**
     19  * Represents a contiguous range of GPU path objects.
     20  * This object is immutable with the exception that individual paths may be
     21  * initialized lazily.
     22  */
     23 
     24 class GrPathRange : public GrGpuResource {
     25 public:
     26 
     27 
     28     enum PathIndexType {
     29         kU8_PathIndexType,   //!< uint8_t
     30         kU16_PathIndexType,  //!< uint16_t
     31         kU32_PathIndexType,  //!< uint32_t
     32 
     33         kLast_PathIndexType = kU32_PathIndexType
     34     };
     35 
     36     static inline int PathIndexSizeInBytes(PathIndexType type) {
     37         GR_STATIC_ASSERT(0 == kU8_PathIndexType);
     38         GR_STATIC_ASSERT(1 == kU16_PathIndexType);
     39         GR_STATIC_ASSERT(2 == kU32_PathIndexType);
     40         GR_STATIC_ASSERT(kU32_PathIndexType == kLast_PathIndexType);
     41 
     42         return 1 << type;
     43     }
     44 
     45     /**
     46      * Class that generates the paths for a specific range.
     47      */
     48     class PathGenerator : public SkRefCnt {
     49     public:
     50         virtual int getNumPaths() = 0;
     51         virtual void generatePath(int index, SkPath* out) = 0;
     52 #ifdef SK_DEBUG
     53         virtual bool isEqualTo(const SkDescriptor&) const { return false; }
     54 #endif
     55         virtual ~PathGenerator() {}
     56     };
     57 
     58     /**
     59      * Initialize a lazy-loaded path range. This class will generate an SkPath and call
     60      * onInitPath() for each path within the range before it is drawn for the first time.
     61      */
     62     GrPathRange(GrGpu*, PathGenerator*);
     63 
     64     /**
     65      * Initialize an eager-loaded path range. The subclass is responsible for ensuring all
     66      * the paths are initialized up front.
     67      */
     68     GrPathRange(GrGpu*, int numPaths);
     69 
     70     int getNumPaths() const { return fNumPaths; }
     71     const PathGenerator* getPathGenerator() const { return fPathGenerator.get(); }
     72 
     73     void loadPathsIfNeeded(const void* indices, PathIndexType, int count) const;
     74 
     75     template<typename IndexType> void loadPathsIfNeeded(const IndexType* indices, int count) const {
     76         if (!fPathGenerator) {
     77             return;
     78         }
     79 
     80         bool didLoadPaths = false;
     81 
     82         for (int i = 0; i < count; ++i) {
     83             SkASSERT(indices[i] < static_cast<uint32_t>(fNumPaths));
     84 
     85             const int groupIndex = indices[i] / kPathsPerGroup;
     86             const int groupByte = groupIndex / 8;
     87             const uint8_t groupBit = 1 << (groupIndex % 8);
     88 
     89             const bool hasPath = SkToBool(fGeneratedPaths[groupByte] & groupBit);
     90             if (!hasPath) {
     91                 // We track which paths are loaded in groups of kPathsPerGroup. To
     92                 // mark a path as loaded we need to load the entire group.
     93                 const int groupFirstPath = groupIndex * kPathsPerGroup;
     94                 const int groupLastPath = SkTMin(groupFirstPath + kPathsPerGroup, fNumPaths) - 1;
     95 
     96                 SkPath path;
     97                 for (int pathIdx = groupFirstPath; pathIdx <= groupLastPath; ++pathIdx) {
     98                     fPathGenerator->generatePath(pathIdx, &path);
     99                     this->onInitPath(pathIdx, path);
    100                 }
    101 
    102                 fGeneratedPaths[groupByte] |= groupBit;
    103                 didLoadPaths = true;
    104             }
    105         }
    106 
    107         if (didLoadPaths) {
    108             this->didChangeGpuMemorySize();
    109         }
    110     }
    111 
    112 #ifdef SK_DEBUG
    113     void assertPathsLoaded(const void* indices, PathIndexType, int count) const;
    114 
    115     template<typename IndexType> void assertPathsLoaded(const IndexType* indices, int count) const {
    116         if (!fPathGenerator) {
    117             return;
    118         }
    119 
    120         for (int i = 0; i < count; ++i) {
    121             SkASSERT(indices[i] < static_cast<uint32_t>(fNumPaths));
    122 
    123             const int groupIndex = indices[i] / kPathsPerGroup;
    124             const int groupByte = groupIndex / 8;
    125             const uint8_t groupBit = 1 << (groupIndex % 8);
    126 
    127             SkASSERT(fGeneratedPaths[groupByte] & groupBit);
    128         }
    129     }
    130 
    131     virtual bool isEqualTo(const SkDescriptor& desc) const {
    132         return nullptr != fPathGenerator.get() && fPathGenerator->isEqualTo(desc);
    133     }
    134 #endif
    135 protected:
    136     // Initialize a path in the range before drawing. This is only called when
    137     // fPathGenerator is non-null. The child class need not call didChangeGpuMemorySize(),
    138     // GrPathRange will take care of that after the call is complete.
    139     virtual void onInitPath(int index, const SkPath&) const = 0;
    140 
    141 private:
    142     enum {
    143         kPathsPerGroup = 16 // Paths get tracked in groups of 16 for lazy loading.
    144     };
    145 
    146     mutable sk_sp<PathGenerator> fPathGenerator;
    147     mutable SkTArray<uint8_t, true /*MEM_COPY*/> fGeneratedPaths;
    148     const int fNumPaths;
    149 
    150     typedef GrGpuResource INHERITED;
    151 };
    152 
    153 #endif
    154