OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkRecordOpts.h" | 8 #include "SkRecordOpts.h" |
9 | 9 |
10 #include "SkRecords.h" | 10 #include "SkRecords.h" |
11 #include "SkTDArray.h" | 11 #include "SkTDArray.h" |
12 | 12 |
13 void SkRecordOptimize(SkRecord* record) { | 13 void SkRecordOptimize(SkRecord* record) { |
14 // TODO(mtklein): fuse independent optimizations to reduce number of passes? | 14 // TODO(mtklein): fuse independent optimizations to reduce number of passes? |
15 SkRecordNoopSaveRestores(record); | 15 SkRecordNoopSaveRestores(record); |
16 SkRecordAnnotateCullingPairs(record); | 16 SkRecordAnnotateCullingPairs(record); |
17 SkRecordReduceDrawPosTextStrength(record); // Helpful to run this before Bo
undDrawPosTextH. | 17 SkRecordReduceDrawPosTextStrength(record); // Helpful to run this before Bo
undDrawPosTextH. |
18 SkRecordBoundDrawPosTextH(record); | 18 SkRecordBoundDrawPosTextH(record); |
19 } | 19 } |
20 | 20 |
21 // Streamline replacing one command with another. | |
22 #define REPLACE(record, index, T, ...) \ | |
23 SkNEW_PLACEMENT_ARGS(record->replace<SkRecords::T>(index), SkRecords::T, (__
VA_ARGS__)) | |
24 | |
25 namespace { | 21 namespace { |
26 | 22 |
27 // Convenience base class to share some common implementation code. | 23 // Convenience base class to share some common implementation code. |
28 class Common : SkNoncopyable { | 24 class Common : SkNoncopyable { |
29 public: | 25 public: |
30 explicit Common(SkRecord* record) : fRecord(record), fIndex(0) {} | 26 explicit Common(SkRecord* record) : fRecord(record), fIndex(0) {} |
31 | 27 |
32 unsigned index() const { return fIndex; } | 28 unsigned index() const { return fIndex; } |
33 void next() { ++fIndex; } | 29 void next() { ++fIndex; } |
34 | 30 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 template <> | 70 template <> |
75 void SaveRestoreNooper::operator()(SkRecords::Save* r) { | 71 void SaveRestoreNooper::operator()(SkRecords::Save* r) { |
76 fSave = SkCanvas::kMatrixClip_SaveFlag == r->flags ? this->index() : kInacti
ve; | 72 fSave = SkCanvas::kMatrixClip_SaveFlag == r->flags ? this->index() : kInacti
ve; |
77 } | 73 } |
78 | 74 |
79 template <> | 75 template <> |
80 void SaveRestoreNooper::operator()(SkRecords::Restore* r) { | 76 void SaveRestoreNooper::operator()(SkRecords::Restore* r) { |
81 if (fSave != kInactive) { | 77 if (fSave != kInactive) { |
82 // Remove everything between the save and restore, inclusive on both sid
es. | 78 // Remove everything between the save and restore, inclusive on both sid
es. |
83 fChanged = true; | 79 fChanged = true; |
84 SkRecord::Destroyer destroyer; | |
85 for (unsigned i = fSave; i <= this->index(); i++) { | 80 for (unsigned i = fSave; i <= this->index(); i++) { |
86 fRecord->mutate(i, destroyer); | 81 fRecord->replace<SkRecords::NoOp>(i); |
87 REPLACE(fRecord, i, NoOp); | |
88 } | 82 } |
89 fSave = kInactive; | 83 fSave = kInactive; |
90 } | 84 } |
91 } | 85 } |
92 | 86 |
93 | 87 |
94 // Tries to replace PushCull with PairedPushCull, which lets us skip to the pair
ed PopCull | 88 // Tries to replace PushCull with PairedPushCull, which lets us skip to the pair
ed PopCull |
95 // when the canvas can quickReject the cull rect. | 89 // when the canvas can quickReject the cull rect. |
96 class CullAnnotator : public Common { | 90 class CullAnnotator : public Common { |
97 public: | 91 public: |
(...skipping 19 matching lines...) Expand all Loading... |
117 } | 111 } |
118 | 112 |
119 template <> | 113 template <> |
120 void CullAnnotator::operator()(SkRecords::PopCull* pop) { | 114 void CullAnnotator::operator()(SkRecords::PopCull* pop) { |
121 Pair push = fPushStack.top(); | 115 Pair push = fPushStack.top(); |
122 fPushStack.pop(); | 116 fPushStack.pop(); |
123 | 117 |
124 SkASSERT(this->index() > push.index); | 118 SkASSERT(this->index() > push.index); |
125 unsigned skip = this->index() - push.index; | 119 unsigned skip = this->index() - push.index; |
126 | 120 |
127 // PairedPushCull adopts push.command. | 121 SkRecords::Adopted<SkRecords::PushCull> adopted(push.command); |
128 REPLACE(fRecord, push.index, PairedPushCull, push.command, skip); | 122 SkNEW_PLACEMENT_ARGS(fRecord->replace<SkRecords::PairedPushCull>(push.index,
adopted), |
| 123 SkRecords::PairedPushCull, (&adopted, skip)); |
129 } | 124 } |
130 | 125 |
131 // Replaces DrawPosText with DrawPosTextH when all Y coordinates are equal. | 126 // Replaces DrawPosText with DrawPosTextH when all Y coordinates are equal. |
132 class StrengthReducer : public Common { | 127 class StrengthReducer : public Common { |
133 public: | 128 public: |
134 explicit StrengthReducer(SkRecord* record) : Common(record) {} | 129 explicit StrengthReducer(SkRecord* record) : Common(record) {} |
135 | 130 |
136 // Do nothing to most ops. | 131 // Do nothing to most ops. |
137 template <typename T> | 132 template <typename T> |
138 void operator()(T*) {} | 133 void operator()(T*) {} |
(...skipping 18 matching lines...) Expand all Loading... |
157 | 152 |
158 // r->pos is points SkPoints, [(x,y),(x,y),(x,y),(x,y), ... ]. | 153 // r->pos is points SkPoints, [(x,y),(x,y),(x,y),(x,y), ... ]. |
159 // We're going to squint and look at that as 2*points SkScalars, [x,y,x,y,x,
y,x,y, ...]. | 154 // We're going to squint and look at that as 2*points SkScalars, [x,y,x,y,x,
y,x,y, ...]. |
160 // Then we'll rearrange things so all the xs are in order up front, clobberi
ng the ys. | 155 // Then we'll rearrange things so all the xs are in order up front, clobberi
ng the ys. |
161 SK_COMPILE_ASSERT(sizeof(SkPoint) == 2 * sizeof(SkScalar), SquintingIsNotSaf
e); | 156 SK_COMPILE_ASSERT(sizeof(SkPoint) == 2 * sizeof(SkScalar), SquintingIsNotSaf
e); |
162 SkScalar* scalars = &r->pos[0].fX; | 157 SkScalar* scalars = &r->pos[0].fX; |
163 for (unsigned i = 0; i < 2*points; i += 2) { | 158 for (unsigned i = 0; i < 2*points; i += 2) { |
164 scalars[i/2] = scalars[i]; | 159 scalars[i/2] = scalars[i]; |
165 } | 160 } |
166 | 161 |
167 SkRecord::Destroyer destroyer; | 162 // Extend lifetime of r to the end of the method so we can copy its parts. |
168 fRecord->mutate(this->index(), destroyer); | 163 SkRecords::Adopted<SkRecords::DrawPosText> adopted(r); |
169 REPLACE(fRecord, this->index(), | 164 SkNEW_PLACEMENT_ARGS(fRecord->replace<SkRecords::DrawPosTextH>(this->index()
, adopted), |
170 DrawPosTextH, (char*)r->text, r->byteLength, scalars, firstY, r->pai
nt); | 165 SkRecords::DrawPosTextH, |
| 166 (r->text, r->byteLength, scalars, firstY, r->paint)); |
171 } | 167 } |
172 | 168 |
173 | 169 |
174 // Tries to replace DrawPosTextH with BoundedDrawPosTextH, which knows conservat
ive upper and lower | 170 // Tries to replace DrawPosTextH with BoundedDrawPosTextH, which knows conservat
ive upper and lower |
175 // bounds to use with SkCanvas::quickRejectY. | 171 // bounds to use with SkCanvas::quickRejectY. |
176 class TextBounder : public Common { | 172 class TextBounder : public Common { |
177 public: | 173 public: |
178 explicit TextBounder(SkRecord* record) : Common(record) {} | 174 explicit TextBounder(SkRecord* record) : Common(record) {} |
179 | 175 |
180 // Do nothing to most ops. | 176 // Do nothing to most ops. |
(...skipping 16 matching lines...) Expand all Loading... |
197 SkDEBUGCODE(r->paint.getFontMetrics(&metrics);) | 193 SkDEBUGCODE(r->paint.getFontMetrics(&metrics);) |
198 SkASSERT(-buffer <= metrics.fTop); | 194 SkASSERT(-buffer <= metrics.fTop); |
199 SkASSERT(+buffer >= metrics.fBottom); | 195 SkASSERT(+buffer >= metrics.fBottom); |
200 | 196 |
201 // Let the paint adjust the text bounds. We don't care about left and right
here, so we use | 197 // Let the paint adjust the text bounds. We don't care about left and right
here, so we use |
202 // 0 and 1 respectively just so the bounds rectangle isn't empty. | 198 // 0 and 1 respectively just so the bounds rectangle isn't empty. |
203 SkRect bounds; | 199 SkRect bounds; |
204 bounds.set(0, r->y - buffer, SK_Scalar1, r->y + buffer); | 200 bounds.set(0, r->y - buffer, SK_Scalar1, r->y + buffer); |
205 SkRect adjusted = r->paint.computeFastBounds(bounds, &bounds); | 201 SkRect adjusted = r->paint.computeFastBounds(bounds, &bounds); |
206 | 202 |
207 // BoundedDrawPosTextH adopts r. | 203 SkRecords::Adopted<SkRecords::DrawPosTextH> adopted(r); |
208 REPLACE(fRecord, this->index(), BoundedDrawPosTextH, r, adjusted.fTop, adjus
ted.fBottom); | 204 SkNEW_PLACEMENT_ARGS(fRecord->replace<SkRecords::BoundedDrawPosTextH>(this->
index(), adopted), |
| 205 SkRecords::BoundedDrawPosTextH, |
| 206 (&adopted, adjusted.fTop, adjusted.fBottom)); |
209 } | 207 } |
210 | 208 |
211 template <typename Pass> | 209 template <typename Pass> |
212 static void run_pass(Pass& pass, SkRecord* record) { | 210 static void run_pass(Pass& pass, SkRecord* record) { |
213 for (; pass.index() < record->count(); pass.next()) { | 211 for (; pass.index() < record->count(); pass.next()) { |
214 record->mutate(pass.index(), pass); | 212 record->mutate(pass.index(), pass); |
215 } | 213 } |
216 } | 214 } |
217 | 215 |
218 } // namespace | 216 } // namespace |
(...skipping 16 matching lines...) Expand all Loading... |
235 | 233 |
236 void SkRecordReduceDrawPosTextStrength(SkRecord* record) { | 234 void SkRecordReduceDrawPosTextStrength(SkRecord* record) { |
237 StrengthReducer reducer(record); | 235 StrengthReducer reducer(record); |
238 run_pass(reducer, record); | 236 run_pass(reducer, record); |
239 } | 237 } |
240 | 238 |
241 void SkRecordBoundDrawPosTextH(SkRecord* record) { | 239 void SkRecordBoundDrawPosTextH(SkRecord* record) { |
242 TextBounder bounder(record); | 240 TextBounder bounder(record); |
243 run_pass(bounder, record); | 241 run_pass(bounder, record); |
244 } | 242 } |
245 | |
246 #undef REPLACE | |
OLD | NEW |