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 "SkRecordPattern.h" | 10 #include "SkRecordPattern.h" |
11 #include "SkRecords.h" | 11 #include "SkRecords.h" |
12 #include "SkTDArray.h" | 12 #include "SkTDArray.h" |
13 | 13 |
14 using namespace SkRecords; | 14 using namespace SkRecords; |
15 | 15 |
16 void SkRecordOptimize(SkRecord* record) { | 16 void SkRecordOptimize(SkRecord* record) { |
17 // This might be useful as a first pass in the future if we want to weed | 17 // This might be useful as a first pass in the future if we want to weed |
18 // out junk for other optimization passes. Right now, nothing needs it, | 18 // out junk for other optimization passes. Right now, nothing needs it, |
19 // and the bounding box hierarchy will do the work of skipping no-op | 19 // and the bounding box hierarchy will do the work of skipping no-op |
20 // Save-NoDraw-Restore sequences better than we can here. | 20 // Save-NoDraw-Restore sequences better than we can here. |
21 //SkRecordNoopSaveRestores(record); | 21 //SkRecordNoopSaveRestores(record); |
22 | 22 |
23 SkRecordNoopSaveLayerDrawRestores(record); | 23 SkRecordNoopSaveLayerDrawRestores(record); |
24 SkRecordMergeSvgOpacityAndFilterLayers(record); | 24 SkRecordMergeSvgOpacityAndFilterLayers(record); |
25 } | 25 } |
26 | 26 |
27 // Most of the optimizations in this file are pattern-based. These are all defi
ned as structs with: | 27 // Most of the optimizations in this file are pattern-based. These are all defi
ned as structs with: |
28 // - a Pattern typedef | 28 // - a Pattern typedef |
29 // - a bool onMatch(SkRceord*, Pattern*, unsigned begin, unsigned end) method, | 29 // - a bool onMatch(SkRceord*, Pattern*, int begin, int end) method, |
30 // which returns true if it made changes and false if not. | 30 // which returns true if it made changes and false if not. |
31 | 31 |
32 // Run a pattern-based optimization once across the SkRecord, returning true if
it made any changes. | 32 // Run a pattern-based optimization once across the SkRecord, returning true if
it made any changes. |
33 // It looks for spans which match Pass::Pattern, and when found calls onMatch()
with the pattern, | 33 // It looks for spans which match Pass::Pattern, and when found calls onMatch()
with the pattern, |
34 // record, and [begin,end) span of the commands that matched. | 34 // record, and [begin,end) span of the commands that matched. |
35 template <typename Pass> | 35 template <typename Pass> |
36 static bool apply(Pass* pass, SkRecord* record) { | 36 static bool apply(Pass* pass, SkRecord* record) { |
37 typename Pass::Pattern pattern; | 37 typename Pass::Pattern pattern; |
38 bool changed = false; | 38 bool changed = false; |
39 unsigned begin, end = 0; | 39 int begin, end = 0; |
40 | 40 |
41 while (pattern.search(record, &begin, &end)) { | 41 while (pattern.search(record, &begin, &end)) { |
42 changed |= pass->onMatch(record, &pattern, begin, end); | 42 changed |= pass->onMatch(record, &pattern, begin, end); |
43 } | 43 } |
44 return changed; | 44 return changed; |
45 } | 45 } |
46 | 46 |
47 // Turns the logical NoOp Save and Restore in Save-Draw*-Restore patterns into a
ctual NoOps. | 47 // Turns the logical NoOp Save and Restore in Save-Draw*-Restore patterns into a
ctual NoOps. |
48 struct SaveOnlyDrawsRestoreNooper { | 48 struct SaveOnlyDrawsRestoreNooper { |
49 typedef Pattern3<Is<Save>, | 49 typedef Pattern3<Is<Save>, |
50 Star<Or<Is<NoOp>, IsDraw> >, | 50 Star<Or<Is<NoOp>, IsDraw> >, |
51 Is<Restore> > | 51 Is<Restore> > |
52 Pattern; | 52 Pattern; |
53 | 53 |
54 bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned en
d) { | 54 bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) { |
55 record->replace<NoOp>(begin); // Save | 55 record->replace<NoOp>(begin); // Save |
56 record->replace<NoOp>(end-1); // Restore | 56 record->replace<NoOp>(end-1); // Restore |
57 return true; | 57 return true; |
58 } | 58 } |
59 }; | 59 }; |
60 | 60 |
61 static bool fold_opacity_layer_color_to_paint(const SkPaint& layerPaint, | 61 static bool fold_opacity_layer_color_to_paint(const SkPaint& layerPaint, |
62 bool isSaveLayer, | 62 bool isSaveLayer, |
63 SkPaint* paint) { | 63 SkPaint* paint) { |
64 // We assume layerPaint is always from a saveLayer. If isSaveLayer is | 64 // We assume layerPaint is always from a saveLayer. If isSaveLayer is |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 // Star matches greedily, so we also have to exclude Save and Restore. | 120 // Star matches greedily, so we also have to exclude Save and Restore. |
121 // Nested SaveLayers need to be excluded, or we'll match their Restore! | 121 // Nested SaveLayers need to be excluded, or we'll match their Restore! |
122 typedef Pattern3<Is<Save>, | 122 typedef Pattern3<Is<Save>, |
123 Star<Not<Or4<Is<Save>, | 123 Star<Not<Or4<Is<Save>, |
124 Is<SaveLayer>, | 124 Is<SaveLayer>, |
125 Is<Restore>, | 125 Is<Restore>, |
126 IsDraw> > >, | 126 IsDraw> > >, |
127 Is<Restore> > | 127 Is<Restore> > |
128 Pattern; | 128 Pattern; |
129 | 129 |
130 bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned en
d) { | 130 bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) { |
131 // The entire span between Save and Restore (inclusively) does nothing. | 131 // The entire span between Save and Restore (inclusively) does nothing. |
132 for (unsigned i = begin; i < end; i++) { | 132 for (int i = begin; i < end; i++) { |
133 record->replace<NoOp>(i); | 133 record->replace<NoOp>(i); |
134 } | 134 } |
135 return true; | 135 return true; |
136 } | 136 } |
137 }; | 137 }; |
138 void SkRecordNoopSaveRestores(SkRecord* record) { | 138 void SkRecordNoopSaveRestores(SkRecord* record) { |
139 SaveOnlyDrawsRestoreNooper onlyDraws; | 139 SaveOnlyDrawsRestoreNooper onlyDraws; |
140 SaveNoDrawsRestoreNooper noDraws; | 140 SaveNoDrawsRestoreNooper noDraws; |
141 | 141 |
142 // Run until they stop changing things. | 142 // Run until they stop changing things. |
143 while (apply(&onlyDraws, record) || apply(&noDraws, record)); | 143 while (apply(&onlyDraws, record) || apply(&noDraws, record)); |
144 } | 144 } |
145 | 145 |
146 // For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's
alpha into the | 146 // For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's
alpha into the |
147 // draw, and no-op the SaveLayer and Restore. | 147 // draw, and no-op the SaveLayer and Restore. |
148 struct SaveLayerDrawRestoreNooper { | 148 struct SaveLayerDrawRestoreNooper { |
149 typedef Pattern3<Is<SaveLayer>, IsDraw, Is<Restore> > Pattern; | 149 typedef Pattern3<Is<SaveLayer>, IsDraw, Is<Restore> > Pattern; |
150 | 150 |
151 bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned en
d) { | 151 bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) { |
152 // A SaveLayer's bounds field is just a hint, so we should be free to ig
nore it. | 152 // A SaveLayer's bounds field is just a hint, so we should be free to ig
nore it. |
153 SkPaint* layerPaint = pattern->first<SaveLayer>()->paint; | 153 SkPaint* layerPaint = pattern->first<SaveLayer>()->paint; |
154 if (NULL == layerPaint) { | 154 if (NULL == layerPaint) { |
155 // There wasn't really any point to this SaveLayer at all. | 155 // There wasn't really any point to this SaveLayer at all. |
156 return KillSaveLayerAndRestore(record, begin); | 156 return KillSaveLayerAndRestore(record, begin); |
157 } | 157 } |
158 | 158 |
159 SkPaint* drawPaint = pattern->second<SkPaint>(); | 159 SkPaint* drawPaint = pattern->second<SkPaint>(); |
160 if (drawPaint == NULL) { | 160 if (drawPaint == NULL) { |
161 // We can just give the draw the SaveLayer's paint. | 161 // We can just give the draw the SaveLayer's paint. |
162 // TODO(mtklein): figure out how to do this clearly | 162 // TODO(mtklein): figure out how to do this clearly |
163 return false; | 163 return false; |
164 } | 164 } |
165 | 165 |
166 if (!fold_opacity_layer_color_to_paint(*layerPaint, false /*isSaveLayer*
/, drawPaint)) { | 166 if (!fold_opacity_layer_color_to_paint(*layerPaint, false /*isSaveLayer*
/, drawPaint)) { |
167 return false; | 167 return false; |
168 } | 168 } |
169 | 169 |
170 return KillSaveLayerAndRestore(record, begin); | 170 return KillSaveLayerAndRestore(record, begin); |
171 } | 171 } |
172 | 172 |
173 static bool KillSaveLayerAndRestore(SkRecord* record, unsigned saveLayerInde
x) { | 173 static bool KillSaveLayerAndRestore(SkRecord* record, int saveLayerIndex) { |
174 record->replace<NoOp>(saveLayerIndex); // SaveLayer | 174 record->replace<NoOp>(saveLayerIndex); // SaveLayer |
175 record->replace<NoOp>(saveLayerIndex+2); // Restore | 175 record->replace<NoOp>(saveLayerIndex+2); // Restore |
176 return true; | 176 return true; |
177 } | 177 } |
178 }; | 178 }; |
179 void SkRecordNoopSaveLayerDrawRestores(SkRecord* record) { | 179 void SkRecordNoopSaveLayerDrawRestores(SkRecord* record) { |
180 SaveLayerDrawRestoreNooper pass; | 180 SaveLayerDrawRestoreNooper pass; |
181 apply(&pass, record); | 181 apply(&pass, record); |
182 } | 182 } |
183 | 183 |
184 | 184 |
185 /* For SVG generated: | 185 /* For SVG generated: |
186 SaveLayer (non-opaque, typically for CSS opacity) | 186 SaveLayer (non-opaque, typically for CSS opacity) |
187 Save | 187 Save |
188 ClipRect | 188 ClipRect |
189 SaveLayer (typically for SVG filter) | 189 SaveLayer (typically for SVG filter) |
190 Restore | 190 Restore |
191 Restore | 191 Restore |
192 Restore | 192 Restore |
193 */ | 193 */ |
194 struct SvgOpacityAndFilterLayerMergePass { | 194 struct SvgOpacityAndFilterLayerMergePass { |
195 typedef Pattern7<Is<SaveLayer>, Is<Save>, Is<ClipRect>, Is<SaveLayer>, | 195 typedef Pattern7<Is<SaveLayer>, Is<Save>, Is<ClipRect>, Is<SaveLayer>, |
196 Is<Restore>, Is<Restore>, Is<Restore> > Pattern; | 196 Is<Restore>, Is<Restore>, Is<Restore> > Pattern; |
197 | 197 |
198 bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned en
d) { | 198 bool onMatch(SkRecord* record, Pattern* pattern, int begin, int end) { |
199 SkPaint* opacityPaint = pattern->first<SaveLayer>()->paint; | 199 SkPaint* opacityPaint = pattern->first<SaveLayer>()->paint; |
200 if (NULL == opacityPaint) { | 200 if (NULL == opacityPaint) { |
201 // There wasn't really any point to this SaveLayer at all. | 201 // There wasn't really any point to this SaveLayer at all. |
202 return KillSaveLayerAndRestore(record, begin); | 202 return KillSaveLayerAndRestore(record, begin); |
203 } | 203 } |
204 | 204 |
205 // This layer typically contains a filter, but this should work for laye
rs with for other | 205 // This layer typically contains a filter, but this should work for laye
rs with for other |
206 // purposes too. | 206 // purposes too. |
207 SkPaint* filterLayerPaint = pattern->fourth<SaveLayer>()->paint; | 207 SkPaint* filterLayerPaint = pattern->fourth<SaveLayer>()->paint; |
208 if (filterLayerPaint == NULL) { | 208 if (filterLayerPaint == NULL) { |
209 // We can just give the inner SaveLayer the paint of the outer SaveL
ayer. | 209 // We can just give the inner SaveLayer the paint of the outer SaveL
ayer. |
210 // TODO(mtklein): figure out how to do this clearly | 210 // TODO(mtklein): figure out how to do this clearly |
211 return false; | 211 return false; |
212 } | 212 } |
213 | 213 |
214 if (!fold_opacity_layer_color_to_paint(*opacityPaint, true /*isSaveLayer
*/, | 214 if (!fold_opacity_layer_color_to_paint(*opacityPaint, true /*isSaveLayer
*/, |
215 filterLayerPaint)) { | 215 filterLayerPaint)) { |
216 return false; | 216 return false; |
217 } | 217 } |
218 | 218 |
219 return KillSaveLayerAndRestore(record, begin); | 219 return KillSaveLayerAndRestore(record, begin); |
220 } | 220 } |
221 | 221 |
222 static bool KillSaveLayerAndRestore(SkRecord* record, unsigned saveLayerInde
x) { | 222 static bool KillSaveLayerAndRestore(SkRecord* record, int saveLayerIndex) { |
223 record->replace<NoOp>(saveLayerIndex); // SaveLayer | 223 record->replace<NoOp>(saveLayerIndex); // SaveLayer |
224 record->replace<NoOp>(saveLayerIndex + 6); // Restore | 224 record->replace<NoOp>(saveLayerIndex + 6); // Restore |
225 return true; | 225 return true; |
226 } | 226 } |
227 }; | 227 }; |
228 | 228 |
229 void SkRecordMergeSvgOpacityAndFilterLayers(SkRecord* record) { | 229 void SkRecordMergeSvgOpacityAndFilterLayers(SkRecord* record) { |
230 SvgOpacityAndFilterLayerMergePass pass; | 230 SvgOpacityAndFilterLayerMergePass pass; |
231 apply(&pass, record); | 231 apply(&pass, record); |
232 } | 232 } |
OLD | NEW |