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 #include "SkXfermode.h" |
13 | 14 |
14 using namespace SkRecords; | 15 using namespace SkRecords; |
15 | 16 |
16 // Most of the optimizations in this file are pattern-based. These are all defi
ned as structs with: | 17 // Most of the optimizations in this file are pattern-based. These are all defi
ned as structs with: |
17 // - a Match typedef | 18 // - a Match typedef |
18 // - a bool onMatch(SkRceord*, Match*, int begin, int end) method, | 19 // - a bool onMatch(SkRceord*, Match*, int begin, int end) method, |
19 // which returns true if it made changes and false if not. | 20 // which returns true if it made changes and false if not. |
20 | 21 |
21 // Run a pattern-based optimization once across the SkRecord, returning true if
it made any changes. | 22 // Run a pattern-based optimization once across the SkRecord, returning true if
it made any changes. |
22 // It looks for spans which match Pass::Match, and when found calls onMatch() wi
th that pattern, | 23 // It looks for spans which match Pass::Match, and when found calls onMatch() wi
th that pattern, |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 } | 165 } |
165 }; | 166 }; |
166 void SkRecordNoopSaveRestores(SkRecord* record) { | 167 void SkRecordNoopSaveRestores(SkRecord* record) { |
167 SaveOnlyDrawsRestoreNooper onlyDraws; | 168 SaveOnlyDrawsRestoreNooper onlyDraws; |
168 SaveNoDrawsRestoreNooper noDraws; | 169 SaveNoDrawsRestoreNooper noDraws; |
169 | 170 |
170 // Run until they stop changing things. | 171 // Run until they stop changing things. |
171 while (apply(&onlyDraws, record) || apply(&noDraws, record)); | 172 while (apply(&onlyDraws, record) || apply(&noDraws, record)); |
172 } | 173 } |
173 | 174 |
| 175 static bool effectively_srcover(const SkPaint* paint) { |
| 176 if (!paint) { |
| 177 return true; |
| 178 } |
| 179 SkXfermode* mode = paint->getXfermode(); |
| 180 if (SkXfermode::IsMode(mode, SkXfermode::kSrcOver_Mode)) { |
| 181 return true; |
| 182 } |
| 183 // src-mode with opaque and no effects (which might change opaqueness) is ok
too. |
| 184 return !paint->getShader() && !paint->getColorFilter() && !paint->getImageFi
lter() && |
| 185 0xFF == paint->getAlpha() && SkXfermode::IsMode(mode, SkXfermode::kSr
c_Mode); |
| 186 } |
| 187 |
174 // For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's
alpha into the | 188 // For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's
alpha into the |
175 // draw, and no-op the SaveLayer and Restore. | 189 // draw, and no-op the SaveLayer and Restore. |
176 struct SaveLayerDrawRestoreNooper { | 190 struct SaveLayerDrawRestoreNooper { |
177 typedef Pattern<Is<SaveLayer>, IsDraw, Is<Restore>> Match; | 191 typedef Pattern<Is<SaveLayer>, IsDraw, Is<Restore>> Match; |
178 | 192 |
179 bool onMatch(SkRecord* record, Match* match, int begin, int end) { | 193 bool onMatch(SkRecord* record, Match* match, int begin, int end) { |
180 if (match->first<SaveLayer>()->backdrop) { | 194 if (match->first<SaveLayer>()->backdrop) { |
181 // can't throw away the layer if we have a backdrop | 195 // can't throw away the layer if we have a backdrop |
182 return false; | 196 return false; |
183 } | 197 } |
184 | 198 |
185 // A SaveLayer's bounds field is just a hint, so we should be free to ig
nore it. | 199 // A SaveLayer's bounds field is just a hint, so we should be free to ig
nore it. |
186 SkPaint* layerPaint = match->first<SaveLayer>()->paint; | 200 SkPaint* layerPaint = match->first<SaveLayer>()->paint; |
187 if (nullptr == layerPaint) { | 201 SkPaint* drawPaint = match->second<SkPaint>(); |
| 202 |
| 203 if (nullptr == layerPaint && effectively_srcover(drawPaint)) { |
188 // There wasn't really any point to this SaveLayer at all. | 204 // There wasn't really any point to this SaveLayer at all. |
189 return KillSaveLayerAndRestore(record, begin); | 205 return KillSaveLayerAndRestore(record, begin); |
190 } | 206 } |
191 | 207 |
192 SkPaint* drawPaint = match->second<SkPaint>(); | |
193 if (drawPaint == nullptr) { | 208 if (drawPaint == nullptr) { |
194 // We can just give the draw the SaveLayer's paint. | 209 // We can just give the draw the SaveLayer's paint. |
195 // TODO(mtklein): figure out how to do this clearly | 210 // TODO(mtklein): figure out how to do this clearly |
196 return false; | 211 return false; |
197 } | 212 } |
198 | 213 |
199 if (!fold_opacity_layer_color_to_paint(*layerPaint, false /*isSaveLayer*
/, drawPaint)) { | 214 if (!fold_opacity_layer_color_to_paint(*layerPaint, false /*isSaveLayer*
/, drawPaint)) { |
200 return false; | 215 return false; |
201 } | 216 } |
202 | 217 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 } | 303 } |
289 | 304 |
290 void SkRecordOptimize2(SkRecord* record) { | 305 void SkRecordOptimize2(SkRecord* record) { |
291 multiple_set_matrices(record); | 306 multiple_set_matrices(record); |
292 SkRecordNoopSaveRestores(record); | 307 SkRecordNoopSaveRestores(record); |
293 SkRecordNoopSaveLayerDrawRestores(record); | 308 SkRecordNoopSaveLayerDrawRestores(record); |
294 SkRecordMergeSvgOpacityAndFilterLayers(record); | 309 SkRecordMergeSvgOpacityAndFilterLayers(record); |
295 | 310 |
296 record->defrag(); | 311 record->defrag(); |
297 } | 312 } |
OLD | NEW |