Chromium Code Reviews| Index: src/core/SkRecordOpts.cpp |
| diff --git a/src/core/SkRecordOpts.cpp b/src/core/SkRecordOpts.cpp |
| index 17595c01c55b5cef09a6509163346f2ebb0996a2..bdb15cbd15b0eb0efef622e0b11206af78e90d2d 100644 |
| --- a/src/core/SkRecordOpts.cpp |
| +++ b/src/core/SkRecordOpts.cpp |
| @@ -12,6 +12,7 @@ |
| #include "SkTDArray.h" |
| using namespace SkRecords; |
| +static void SkRecordNoopSaveLayerSaveLayerRestores(SkRecord* record); |
|
mtklein
2015/01/21 16:20:29
This is a sign we need unit tests. :) You'll want
Kimmo Kinnunen
2015/01/22 13:55:01
Done.
|
| void SkRecordOptimize(SkRecord* record) { |
| // This might be useful as a first pass in the future if we want to weed |
| @@ -21,6 +22,7 @@ void SkRecordOptimize(SkRecord* record) { |
| //SkRecordNoopSaveRestores(record); |
| SkRecordNoopSaveLayerDrawRestores(record); |
| + SkRecordNoopSaveLayerSaveLayerRestores(record); |
|
mtklein
2015/01/21 16:20:30
Can you see any SKPs where these optimizations fee
Kimmo Kinnunen
2015/01/22 13:55:01
No, they are not related. They can not generate ne
|
| } |
| // Most of the optimizations in this file are pattern-based. These are all defined as structs with: |
| @@ -56,6 +58,27 @@ struct SaveOnlyDrawsRestoreNooper { |
| return true; |
| } |
| }; |
| + |
| +static bool has_any_effect(const SkPaint& paint) { |
| + return paint.getPathEffect() || |
| + paint.getShader() || |
| + paint.getXfermode() || |
| + paint.getMaskFilter() || |
| + paint.getColorFilter() || |
| + paint.getRasterizer() || |
| + paint.getLooper() || |
| + paint.getImageFilter(); |
| +} |
| + |
| +static bool is_only_alpha(SkColor color) { |
| + return SK_ColorTRANSPARENT == SkColorSetA(color, SK_AlphaTRANSPARENT); |
| +} |
| + |
| +static SkColor blend_opacity_layer_color(SkColor baseColor, SkColor opacityLayerColor) { |
| + return SkColorSetA(baseColor, SkFloatToIntRound(SkColorGetA(baseColor) * |
| + SkColorGetA(opacityLayerColor) / 255.0f)); |
| +} |
| + |
| // Turns logical no-op Save-[non-drawing command]*-Restore patterns into actual no-ops. |
| struct SaveNoDrawsRestoreNooper { |
| // Star matches greedily, so we also have to exclude Save and Restore. |
| @@ -111,34 +134,15 @@ struct SaveLayerDrawRestoreNooper { |
| const uint32_t layerColor = layerPaint->getColor(); |
| const uint32_t drawColor = drawPaint->getColor(); |
| - if (!IsOnlyAlpha(layerColor) || HasAnyEffect(*layerPaint) || CantFoldAlpha(*drawPaint)) { |
| + if (!is_only_alpha(layerColor) || has_any_effect(*layerPaint) || CantFoldAlpha(*drawPaint)) { |
| // Too fancy for us. |
| return false; |
| } |
| - drawPaint->setColor(SkColorSetA(drawColor, |
| - SkFloatToIntRound(SkColorGetA(drawColor) * |
| - SkColorGetA(layerColor) / 255.0f))); |
| + drawPaint->setColor(blend_opacity_layer_color(drawColor, layerColor)); |
| return KillSaveLayerAndRestore(record, begin); |
| } |
| - static bool KillSaveLayerAndRestore(SkRecord* record, unsigned saveLayerIndex) { |
| - record->replace<NoOp>(saveLayerIndex); // SaveLayer |
| - record->replace<NoOp>(saveLayerIndex+2); // Restore |
| - return true; |
| - } |
| - |
| - static bool HasAnyEffect(const SkPaint& paint) { |
| - return paint.getPathEffect() || |
| - paint.getShader() || |
| - paint.getXfermode() || |
| - paint.getMaskFilter() || |
| - paint.getColorFilter() || |
| - paint.getRasterizer() || |
| - paint.getLooper() || |
| - paint.getImageFilter(); |
| - } |
| - |
| // The alpha folding can proceed if the single draw's paint has a shader, |
| // path effect, mask filter and/or rasterizer. |
| // TODO: most likely the looper and only some xfer modes are the hard |
| @@ -150,8 +154,10 @@ struct SaveLayerDrawRestoreNooper { |
| paint.getImageFilter(); |
| } |
| - static bool IsOnlyAlpha(SkColor color) { |
| - return SK_ColorTRANSPARENT == SkColorSetA(color, SK_AlphaTRANSPARENT); |
| + static bool KillSaveLayerAndRestore(SkRecord* record, unsigned saveLayerIndex) { |
| + record->replace<NoOp>(saveLayerIndex); // SaveLayer |
| + record->replace<NoOp>(saveLayerIndex+2); // Restore |
| + return true; |
| } |
| }; |
| void SkRecordNoopSaveLayerDrawRestores(SkRecord* record) { |
| @@ -159,3 +165,59 @@ void SkRecordNoopSaveLayerDrawRestores(SkRecord* record) { |
| apply(&pass, record); |
| } |
| + |
| +/* For SVG generated: |
| + SaveLayer (non-opaque) |
|
mtklein
2015/01/13 21:12:20
This pattern seems very specific. This makes me w
Kimmo Kinnunen
2015/01/22 13:55:01
Acknowledged.
|
| + Save |
| + Clip Rect |
| + Save Layer |
| + Restore |
| + Restore |
| + Restore |
| +*/ |
| +struct SaveLayerSaveLayerRestoreNooper { |
|
mtklein
2015/01/21 16:20:29
Might be I've set a bad naming precedent here. Ma
Kimmo Kinnunen
2015/01/22 13:55:01
Done.
|
| + typedef Pattern7<Is<SaveLayer>, Is<Save>, Is<ClipRect>, Is<SaveLayer>, |
| + Is<Restore>, Is<Restore>, Is<Restore> > Pattern; |
| + |
| + bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned end) { |
| + SaveLayer* opacityLayer = pattern->first<SaveLayer>(); |
| + if (opacityLayer->bounds != NULL) { |
| + // SaveLayer with bounds is too tricky for us. |
|
mtklein
2015/01/21 16:20:29
I removed this check in the other pattern. I thin
Kimmo Kinnunen
2015/01/22 13:55:01
Done.
|
| + return false; |
| + } |
| + |
| + SkPaint* opacityPaint = opacityLayer->paint; |
| + if (NULL == opacityPaint) { |
| + // There wasn't really any point to this SaveLayer at all. |
| + return KillSaveLayerAndRestore(record, begin); |
| + } |
| + |
| + SkPaint* secondLayerPaint = pattern->fourth<SaveLayer>()->paint; |
| + if (secondLayerPaint == NULL) { |
| + // We can just give the draw the SaveLayer's paint. |
|
mtklein
2015/01/21 16:20:29
// We can just give the inner SaveLayer the outer
Kimmo Kinnunen
2015/01/22 13:55:01
Done.
|
| + // TODO(mtklein): figure out how to do this clearly |
| + return false; |
| + } |
| + |
| + const uint32_t opacityColor = opacityPaint->getColor(); |
| + const uint32_t secondLayerColor = secondLayerPaint->getColor(); |
| + if (!is_only_alpha(opacityColor) || has_any_effect(*opacityPaint)) { |
|
mtklein
2015/01/21 16:20:29
We're not doing a CantFoldAlpha check here, and I'
Kimmo Kinnunen
2015/01/22 13:55:01
Done.
|
| + // Too fancy for us. |
| + return false; |
| + } |
| + |
| + secondLayerPaint->setColor(blend_opacity_layer_color(secondLayerColor, opacityColor)); |
| + return KillSaveLayerAndRestore(record, begin); |
| + } |
| + |
| + static bool KillSaveLayerAndRestore(SkRecord* record, unsigned saveLayerIndex) { |
| + record->replace<NoOp>(saveLayerIndex); // SaveLayer |
| + record->replace<NoOp>(saveLayerIndex + 6); // Restore |
| + return true; |
| + } |
| +}; |
| + |
| +static void SkRecordNoopSaveLayerSaveLayerRestores(SkRecord* record) { |
| + SaveLayerSaveLayerRestoreNooper pass; |
| + apply(&pass, record); |
| +} |