| 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 |