Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: src/gpu/gl/GrGLNameAllocator.cpp

Issue 304403003: Generate path names on the client side (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1
2 /*
3 * Copyright 2014 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
bsalomon 2014/05/30 18:09:11 This file could really use some documentation.
7 */
8
9 #include "GrGLNameAllocator.h"
10
11 class GrGLNameAllocator::SparseNameRange {
12 public:
13 virtual ~SparseNameRange() {}
14
15 GrGLuint first() const { return fFirst; }
16 GrGLuint end() const { return fEnd; }
17 GrGLuint height() const { return fHeight; }
18
19 virtual SparseNameRange* SK_WARN_UNUSED_RESULT internalAllocate(GrGLuint* ou tName) = 0;
20 virtual SparseNameRange* SK_WARN_UNUSED_RESULT removeLeftmostContiguousRange (GrGLuint* removedCount) = 0;
21 virtual GrGLuint appendNames(GrGLuint count) = 0;
22
23 virtual SparseNameRange* SK_WARN_UNUSED_RESULT free(GrGLuint name) = 0;
24
25 // Implement ref/unref without atomics.
26 SparseNameRange* ref() {
bsalomon 2014/05/30 18:09:11 Are these really frequently ref'ed and unref'ed?
Chris Dalton 2014/05/30 21:39:41 In theory it could. In practice it might not. I ca
bsalomon 2014/06/02 15:14:43 I'd prefer that. If we're going to tackle non-atom
27 ++fRefCnt;
28 return this;
29 }
30 int unref() {
31 if (0 == --fRefCnt) {
32 SkDELETE(this);
33 return 0;
34 }
35 return fRefCnt;
36 }
37
38 protected:
39 SparseNameRange() : fRefCnt(1) {}
40
41 GrGLuint fFirst;
42 GrGLuint fEnd;
43 GrGLuint fHeight;
44
45 private:
46 int fRefCnt;
47 };
48
49 class GrGLNameAllocator::SparseNameTree : public SparseNameRange {
50 public:
51 SparseNameTree(SparseNameRange* left, SparseNameRange* right)
52 : fLeft(left),
53 fRight(right) {
54 SkASSERT(fLeft.get());
55 SkASSERT(fRight.get());
56 this->updateStats();
57 }
58
59 virtual SparseNameRange* SK_WARN_UNUSED_RESULT internalAllocate(GrGLuint* ou tName) SK_OVERRIDE {
60 // Try allocating the range inside fLeft's internal gaps.
61 fLeft.reset(fLeft->internalAllocate(outName));
62 if (0 != *outName) {
63 this->updateStats();
64 return this->rebalance();
65 }
66
67 if (fLeft->end() + 1 == fRight->first()) {
68 // It closed the gap between fLeft and fRight; merge.
69 GrGLuint removedCount;
70 fRight.reset(fRight->removeLeftmostContiguousRange(&removedCount));
71 *outName = fLeft->appendNames(1 + removedCount);
72 if (NULL == fRight.get()) {
73 return fLeft.detach();
74 }
75 this->updateStats();
76 return this->rebalance();
77 }
78
79 *outName = fLeft->appendNames(1);
80 return this->ref();
81 }
82
83 virtual SparseNameRange* SK_WARN_UNUSED_RESULT removeLeftmostContiguousRange (GrGLuint* removedCount) SK_OVERRIDE {
84 fLeft.reset(fLeft->removeLeftmostContiguousRange(removedCount));
85 if (NULL == fLeft) {
86 return fRight.detach();
87 }
88 this->updateStats();
89 return this->rebalance();
90 }
91
92 virtual GrGLuint SK_WARN_UNUSED_RESULT appendNames(GrGLuint count) SK_OVERRI DE {
93 SkASSERT(fEnd + count > fEnd); // Check for integer wrap.
94 GrGLuint name = fRight->appendNames(count);
95 SkASSERT(fRight->end() == fEnd + count);
96 this->updateStats();
97 return name;
98 }
99
100 virtual SparseNameRange* SK_WARN_UNUSED_RESULT free(GrGLuint name) SK_OVERRI DE {
101 if (name < fLeft->end()) {
102 fLeft.reset(fLeft->free(name));
103 if (NULL == fLeft) {
104 // fLeft became empty after the free.
105 return fRight.detach();
106 }
107 this->updateStats();
108 return this->rebalance();
109 } else {
110 SkASSERT(name >= fRight->first());
111 fRight.reset(fRight->free(name));
112 if (NULL == fRight) {
113 // fRight became empty after the free.
114 return fLeft.detach();
115 }
116 this->updateStats();
117 return this->rebalance();
118 }
119 }
120
121 protected:
122 typedef SkAutoTUnref<SparseNameRange> SparseNameTree::* ChildRange;
123
124 SparseNameRange* SK_WARN_UNUSED_RESULT rebalance() {
125 if (fLeft->height() > fRight->height() + 1) {
126 return this->rebalanceImpl<&SparseNameTree::fLeft, &SparseNameTree:: fRight>();
127 }
128 if (fRight->height() > fLeft->height() + 1) {
129 return this->rebalanceImpl<&SparseNameTree::fRight, &SparseNameTree: :fLeft>();
130 }
131 return this->ref();
132 }
133
134 template<ChildRange Tall, ChildRange Short>
135 SparseNameRange* SK_WARN_UNUSED_RESULT rebalanceImpl() {
136 // We should be calling rebalance() enough that the tree never gets more
137 // than one rotation off balance.
138 SkASSERT(2 == (this->*Tall)->height() - (this->*Short)->height());
139 SparseNameTree* tallChild = static_cast<SparseNameTree*>((this->*Tall).g et());
140 if ((tallChild->*Tall)->height() < (tallChild->*Short)->height()) {
141 (this->*Tall).reset(tallChild->rotate<Short, Tall>());
142 }
143 return this->rotate<Tall, Short>();
144 }
145
146 template<ChildRange Tall, ChildRange Short>
147 SparseNameRange* SK_WARN_UNUSED_RESULT rotate() {
148 SparseNameTree* newRoot = static_cast<SparseNameTree*>((this->*Tall).det ach());
149
150 (this->*Tall).reset((newRoot->*Short).detach());
151 this->updateStats();
152
153 (newRoot->*Short).reset(this->ref());
154 newRoot->updateStats();
155
156 return newRoot;
157 }
158
159 void updateStats() {
160 SkASSERT(fLeft->end() < fRight->first()); // There must be a gap between left and right.
161 fFirst = fLeft->first();
162 fEnd = fRight->end();
163 fHeight = 1 + SkMax32(fLeft->height(), fRight->height());
164 }
165
166 private:
167 SkAutoTUnref<SparseNameRange> fLeft;
168 SkAutoTUnref<SparseNameRange> fRight;
169 };
170
171 class GrGLNameAllocator::ContiguousNameRange : public SparseNameRange {
172 public:
173 ContiguousNameRange(GrGLuint first, GrGLuint end) {
174 SkASSERT(first < end);
175 fFirst = first;
176 fEnd = end;
177 fHeight = 0;
178 }
179
180 virtual SparseNameRange* SK_WARN_UNUSED_RESULT internalAllocate(GrGLuint* ou tName) SK_OVERRIDE {
181 *outName = 0; // No internal gaps, we are contiguous.
182 return this->ref();
183 }
184
185 virtual SparseNameRange* SK_WARN_UNUSED_RESULT removeLeftmostContiguousRange (GrGLuint* removedCount) SK_OVERRIDE {
186 *removedCount = fEnd - fFirst;
187 return NULL;
188 }
189
190 virtual GrGLuint SK_WARN_UNUSED_RESULT appendNames(GrGLuint count) SK_OVERRI DE {
191 SkASSERT(fEnd + count > fEnd); // Check for integer wrap.
192 GrGLuint name = fEnd;
193 fEnd += count;
194 return name;
195 }
196
197 virtual SparseNameRange* SK_WARN_UNUSED_RESULT free(GrGLuint name) SK_OVERRI DE {
198 SkASSERT(name >= fFirst);
199 SkASSERT(name < fEnd);
200
201 if (fFirst == name) {
202 ++fFirst;
203 return (fEnd == fFirst) ? NULL : this->ref();
204 }
205
206 if (fEnd == name + 1) {
207 --fEnd;
208 return this->ref();
209 }
210
211 SparseNameRange* left = SkNEW_ARGS(ContiguousNameRange, (fFirst, name));
212 SparseNameRange* right = this->ref();
213 fFirst = name + 1;
214 return SkNEW_ARGS(SparseNameTree, (left, right));
215 }
216 };
217
218 GrGLNameAllocator::GrGLNameAllocator(GrGLuint names, GrGLuint range)
219 : fNames(names),
220 fRange(range) {
221 SkASSERT(range > 0);
222 }
223
224 GrGLNameAllocator::~GrGLNameAllocator() {
225 }
226
227 GrGLuint GrGLNameAllocator::allocateName() {
228 if (NULL == fAllocatedNames.get()) {
229 fAllocatedNames.reset(SkNEW_ARGS(ContiguousNameRange, (fNames, fNames + 1)));
230 return fNames;
231 }
232
233 GrGLuint name;
234 fAllocatedNames.reset(fAllocatedNames->internalAllocate(&name));
235 if (0 != name) {
236 return name;
237 }
238
239 if (fAllocatedNames->end() >= fAllocatedNames->first() + fRange) {
240 // Out of names.
241 return 0;
242 }
243
244 return fAllocatedNames->appendNames(1);
245 }
246
247 void GrGLNameAllocator::freeName(GrGLuint name) {
248 SkASSERT(fAllocatedNames.get());
249 SkASSERT(name >= fAllocatedNames->first());
250 SkASSERT(name < fAllocatedNames->end()); // It is invalid to free not-alloca ted names.
251
252 fAllocatedNames.reset(fAllocatedNames->free(name));
253 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698