Line data Source code
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 0 : 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 0 : 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 0 : virtual bool isEqualTo(const SkDescriptor&) const { return false; }
54 : #endif
55 0 : 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 0 : 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 0 : template<typename IndexType> void loadPathsIfNeeded(const IndexType* indices, int count) const {
76 0 : if (!fPathGenerator) {
77 0 : return;
78 : }
79 :
80 0 : bool didLoadPaths = false;
81 :
82 0 : for (int i = 0; i < count; ++i) {
83 0 : SkASSERT(indices[i] < static_cast<uint32_t>(fNumPaths));
84 :
85 0 : const int groupIndex = indices[i] / kPathsPerGroup;
86 0 : const int groupByte = groupIndex / 8;
87 0 : const uint8_t groupBit = 1 << (groupIndex % 8);
88 :
89 0 : const bool hasPath = SkToBool(fGeneratedPaths[groupByte] & groupBit);
90 0 : 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 0 : const int groupFirstPath = groupIndex * kPathsPerGroup;
94 0 : const int groupLastPath = SkTMin(groupFirstPath + kPathsPerGroup, fNumPaths) - 1;
95 :
96 0 : SkPath path;
97 0 : for (int pathIdx = groupFirstPath; pathIdx <= groupLastPath; ++pathIdx) {
98 0 : fPathGenerator->generatePath(pathIdx, &path);
99 0 : this->onInitPath(pathIdx, path);
100 : }
101 :
102 0 : fGeneratedPaths[groupByte] |= groupBit;
103 0 : didLoadPaths = true;
104 : }
105 : }
106 :
107 0 : if (didLoadPaths) {
108 0 : this->didChangeGpuMemorySize();
109 : }
110 : }
111 :
112 : #ifdef SK_DEBUG
113 : void assertPathsLoaded(const void* indices, PathIndexType, int count) const;
114 :
115 0 : template<typename IndexType> void assertPathsLoaded(const IndexType* indices, int count) const {
116 0 : if (!fPathGenerator) {
117 0 : return;
118 : }
119 :
120 0 : for (int i = 0; i < count; ++i) {
121 0 : SkASSERT(indices[i] < static_cast<uint32_t>(fNumPaths));
122 :
123 0 : const int groupIndex = indices[i] / kPathsPerGroup;
124 0 : const int groupByte = groupIndex / 8;
125 0 : const uint8_t groupBit = 1 << (groupIndex % 8);
126 :
127 0 : SkASSERT(fGeneratedPaths[groupByte] & groupBit);
128 : }
129 : }
130 :
131 0 : virtual bool isEqualTo(const SkDescriptor& desc) const {
132 0 : 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
|