1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tests/RecordTestUtils.h" 9cb93a386Sopenharmony_ci#include "tests/Test.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/core/SkColorFilter.h" 12cb93a386Sopenharmony_ci#include "include/core/SkPictureRecorder.h" 13cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 14cb93a386Sopenharmony_ci#include "include/effects/SkImageFilters.h" 15cb93a386Sopenharmony_ci#include "src/core/SkRecord.h" 16cb93a386Sopenharmony_ci#include "src/core/SkRecordOpts.h" 17cb93a386Sopenharmony_ci#include "src/core/SkRecorder.h" 18cb93a386Sopenharmony_ci#include "src/core/SkRecords.h" 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_cistatic const int W = 1920, H = 1080; 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ciDEF_TEST(RecordOpts_NoopDraw, r) { 23cb93a386Sopenharmony_ci SkRecord record; 24cb93a386Sopenharmony_ci SkRecorder recorder(&record, W, H); 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci recorder.drawRect(SkRect::MakeWH(200, 200), SkPaint()); 27cb93a386Sopenharmony_ci recorder.drawRect(SkRect::MakeWH(300, 300), SkPaint()); 28cb93a386Sopenharmony_ci recorder.drawRect(SkRect::MakeWH(100, 100), SkPaint()); 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci record.replace<SkRecords::NoOp>(1); // NoOps should be allowed. 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci SkRecordNoopSaveRestores(&record); 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 2 == count_instances_of_type<SkRecords::DrawRect>(record)); 35cb93a386Sopenharmony_ci} 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ciDEF_TEST(RecordOpts_SingleNoopSaveRestore, r) { 38cb93a386Sopenharmony_ci SkRecord record; 39cb93a386Sopenharmony_ci SkRecorder recorder(&record, W, H); 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci recorder.save(); 42cb93a386Sopenharmony_ci recorder.clipRect(SkRect::MakeWH(200, 200)); 43cb93a386Sopenharmony_ci recorder.restore(); 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci SkRecordNoopSaveRestores(&record); 46cb93a386Sopenharmony_ci for (int i = 0; i < 3; i++) { 47cb93a386Sopenharmony_ci assert_type<SkRecords::NoOp>(r, record, i); 48cb93a386Sopenharmony_ci } 49cb93a386Sopenharmony_ci} 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ciDEF_TEST(RecordOpts_NoopSaveRestores, r) { 52cb93a386Sopenharmony_ci SkRecord record; 53cb93a386Sopenharmony_ci SkRecorder recorder(&record, W, H); 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci // The second pass will clean up this pair after the first pass noops all the innards. 56cb93a386Sopenharmony_ci recorder.save(); 57cb93a386Sopenharmony_ci // A simple pointless pair of save/restore. 58cb93a386Sopenharmony_ci recorder.save(); 59cb93a386Sopenharmony_ci recorder.restore(); 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci // As long as we don't draw in there, everything is a noop. 62cb93a386Sopenharmony_ci recorder.save(); 63cb93a386Sopenharmony_ci recorder.clipRect(SkRect::MakeWH(200, 200)); 64cb93a386Sopenharmony_ci recorder.clipRect(SkRect::MakeWH(100, 100)); 65cb93a386Sopenharmony_ci recorder.restore(); 66cb93a386Sopenharmony_ci recorder.restore(); 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci SkRecordNoopSaveRestores(&record); 69cb93a386Sopenharmony_ci for (int index = 0; index < record.count(); index++) { 70cb93a386Sopenharmony_ci assert_type<SkRecords::NoOp>(r, record, index); 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci} 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ciDEF_TEST(RecordOpts_SaveSaveLayerRestoreRestore, r) { 75cb93a386Sopenharmony_ci SkRecord record; 76cb93a386Sopenharmony_ci SkRecorder recorder(&record, W, H); 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci // A previous bug NoOp'd away the first 3 commands. 79cb93a386Sopenharmony_ci recorder.save(); 80cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, nullptr); 81cb93a386Sopenharmony_ci recorder.restore(); 82cb93a386Sopenharmony_ci recorder.restore(); 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci SkRecordNoopSaveRestores(&record); 85cb93a386Sopenharmony_ci switch (record.count()) { 86cb93a386Sopenharmony_ci case 4: 87cb93a386Sopenharmony_ci assert_type<SkRecords::Save> (r, record, 0); 88cb93a386Sopenharmony_ci assert_type<SkRecords::SaveLayer>(r, record, 1); 89cb93a386Sopenharmony_ci assert_type<SkRecords::Restore> (r, record, 2); 90cb93a386Sopenharmony_ci assert_type<SkRecords::Restore> (r, record, 3); 91cb93a386Sopenharmony_ci break; 92cb93a386Sopenharmony_ci case 2: 93cb93a386Sopenharmony_ci assert_type<SkRecords::SaveLayer>(r, record, 0); 94cb93a386Sopenharmony_ci assert_type<SkRecords::Restore> (r, record, 1); 95cb93a386Sopenharmony_ci break; 96cb93a386Sopenharmony_ci case 0: 97cb93a386Sopenharmony_ci break; 98cb93a386Sopenharmony_ci default: 99cb93a386Sopenharmony_ci REPORTER_ASSERT(r, false); 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK 104cb93a386Sopenharmony_cistatic void assert_savelayer_restore(skiatest::Reporter* r, 105cb93a386Sopenharmony_ci SkRecord* record, 106cb93a386Sopenharmony_ci int i, 107cb93a386Sopenharmony_ci bool shouldBeNoOped) { 108cb93a386Sopenharmony_ci SkRecordNoopSaveLayerDrawRestores(record); 109cb93a386Sopenharmony_ci if (shouldBeNoOped) { 110cb93a386Sopenharmony_ci assert_type<SkRecords::NoOp>(r, *record, i); 111cb93a386Sopenharmony_ci assert_type<SkRecords::NoOp>(r, *record, i+1); 112cb93a386Sopenharmony_ci } else { 113cb93a386Sopenharmony_ci assert_type<SkRecords::SaveLayer>(r, *record, i); 114cb93a386Sopenharmony_ci assert_type<SkRecords::Restore>(r, *record, i+1); 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci} 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_cistatic void assert_savelayer_draw_restore(skiatest::Reporter* r, 119cb93a386Sopenharmony_ci SkRecord* record, 120cb93a386Sopenharmony_ci int i, 121cb93a386Sopenharmony_ci bool shouldBeNoOped) { 122cb93a386Sopenharmony_ci SkRecordNoopSaveLayerDrawRestores(record); 123cb93a386Sopenharmony_ci if (shouldBeNoOped) { 124cb93a386Sopenharmony_ci assert_type<SkRecords::NoOp>(r, *record, i); 125cb93a386Sopenharmony_ci assert_type<SkRecords::NoOp>(r, *record, i+2); 126cb93a386Sopenharmony_ci } else { 127cb93a386Sopenharmony_ci assert_type<SkRecords::SaveLayer>(r, *record, i); 128cb93a386Sopenharmony_ci assert_type<SkRecords::Restore>(r, *record, i+2); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci} 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ciDEF_TEST(RecordOpts_NoopSaveLayerDrawRestore, r) { 133cb93a386Sopenharmony_ci SkRecord record; 134cb93a386Sopenharmony_ci SkRecorder recorder(&record, W, H); 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci SkRect bounds = SkRect::MakeWH(100, 200); 137cb93a386Sopenharmony_ci SkRect draw = SkRect::MakeWH(50, 60); 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci SkPaint alphaOnlyLayerPaint, translucentLayerPaint, xfermodeLayerPaint; 140cb93a386Sopenharmony_ci alphaOnlyLayerPaint.setColor(0x03000000); // Only alpha. 141cb93a386Sopenharmony_ci translucentLayerPaint.setColor(0x03040506); // Not only alpha. 142cb93a386Sopenharmony_ci xfermodeLayerPaint.setBlendMode(SkBlendMode::kDstIn); // Any effect will do. 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci SkPaint opaqueDrawPaint, translucentDrawPaint; 145cb93a386Sopenharmony_ci opaqueDrawPaint.setColor(0xFF020202); // Opaque. 146cb93a386Sopenharmony_ci translucentDrawPaint.setColor(0x0F020202); // Not opaque. 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ci // SaveLayer/Restore removed: No paint = no point. 149cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, nullptr); 150cb93a386Sopenharmony_ci recorder.drawRect(draw, opaqueDrawPaint); 151cb93a386Sopenharmony_ci recorder.restore(); 152cb93a386Sopenharmony_ci assert_savelayer_draw_restore(r, &record, 0, true); 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ci // Bounds don't matter. 155cb93a386Sopenharmony_ci recorder.saveLayer(&bounds, nullptr); 156cb93a386Sopenharmony_ci recorder.drawRect(draw, opaqueDrawPaint); 157cb93a386Sopenharmony_ci recorder.restore(); 158cb93a386Sopenharmony_ci assert_savelayer_draw_restore(r, &record, 3, true); 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci // TODO(mtklein): test case with null draw paint 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci // No change: layer paint isn't alpha-only. 163cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, &translucentLayerPaint); 164cb93a386Sopenharmony_ci recorder.drawRect(draw, opaqueDrawPaint); 165cb93a386Sopenharmony_ci recorder.restore(); 166cb93a386Sopenharmony_ci assert_savelayer_draw_restore(r, &record, 6, false); 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci // No change: layer paint has an effect. 169cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, &xfermodeLayerPaint); 170cb93a386Sopenharmony_ci recorder.drawRect(draw, opaqueDrawPaint); 171cb93a386Sopenharmony_ci recorder.restore(); 172cb93a386Sopenharmony_ci assert_savelayer_draw_restore(r, &record, 9, false); 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci // SaveLayer/Restore removed: we can fold in the alpha! 175cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, &alphaOnlyLayerPaint); 176cb93a386Sopenharmony_ci recorder.drawRect(draw, translucentDrawPaint); 177cb93a386Sopenharmony_ci recorder.restore(); 178cb93a386Sopenharmony_ci assert_savelayer_draw_restore(r, &record, 12, true); 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci // SaveLayer/Restore removed: we can fold in the alpha! 181cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, &alphaOnlyLayerPaint); 182cb93a386Sopenharmony_ci recorder.drawRect(draw, opaqueDrawPaint); 183cb93a386Sopenharmony_ci recorder.restore(); 184cb93a386Sopenharmony_ci assert_savelayer_draw_restore(r, &record, 15, true); 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_ci const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, record, 16); 187cb93a386Sopenharmony_ci REPORTER_ASSERT(r, drawRect != nullptr); 188cb93a386Sopenharmony_ci REPORTER_ASSERT(r, drawRect->paint.getColor() == 0x03020202); 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_ci // saveLayer w/ backdrop should NOT go away 191cb93a386Sopenharmony_ci sk_sp<SkImageFilter> filter(SkImageFilters::Blur(3, 3, nullptr)); 192cb93a386Sopenharmony_ci recorder.saveLayer({ nullptr, nullptr, filter.get(), 0}); 193cb93a386Sopenharmony_ci recorder.drawRect(draw, opaqueDrawPaint); 194cb93a386Sopenharmony_ci recorder.restore(); 195cb93a386Sopenharmony_ci assert_savelayer_draw_restore(r, &record, 18, false); 196cb93a386Sopenharmony_ci} 197cb93a386Sopenharmony_ci#endif 198cb93a386Sopenharmony_ci 199cb93a386Sopenharmony_cistatic void assert_merge_svg_opacity_and_filter_layers(skiatest::Reporter* r, 200cb93a386Sopenharmony_ci SkRecord* record, 201cb93a386Sopenharmony_ci int i, 202cb93a386Sopenharmony_ci bool shouldBeNoOped) { 203cb93a386Sopenharmony_ci SkRecordMergeSvgOpacityAndFilterLayers(record); 204cb93a386Sopenharmony_ci if (shouldBeNoOped) { 205cb93a386Sopenharmony_ci assert_type<SkRecords::NoOp>(r, *record, i); 206cb93a386Sopenharmony_ci assert_type<SkRecords::NoOp>(r, *record, i + 6); 207cb93a386Sopenharmony_ci } else { 208cb93a386Sopenharmony_ci assert_type<SkRecords::SaveLayer>(r, *record, i); 209cb93a386Sopenharmony_ci assert_type<SkRecords::Restore>(r, *record, i + 6); 210cb93a386Sopenharmony_ci } 211cb93a386Sopenharmony_ci} 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_ciDEF_TEST(RecordOpts_MergeSvgOpacityAndFilterLayers, r) { 214cb93a386Sopenharmony_ci SkRecord record; 215cb93a386Sopenharmony_ci SkRecorder recorder(&record, W, H); 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_ci SkRect bounds = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(200)); 218cb93a386Sopenharmony_ci SkRect clip = SkRect::MakeWH(SkIntToScalar(50), SkIntToScalar(60)); 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci SkPaint alphaOnlyLayerPaint; 221cb93a386Sopenharmony_ci alphaOnlyLayerPaint.setColor(0x03000000); // Only alpha. 222cb93a386Sopenharmony_ci SkPaint translucentLayerPaint; 223cb93a386Sopenharmony_ci translucentLayerPaint.setColor(0x03040506); // Not only alpha. 224cb93a386Sopenharmony_ci SkPaint xfermodePaint; 225cb93a386Sopenharmony_ci xfermodePaint.setBlendMode(SkBlendMode::kDstIn); 226cb93a386Sopenharmony_ci SkPaint colorFilterPaint; 227cb93a386Sopenharmony_ci colorFilterPaint.setColorFilter( 228cb93a386Sopenharmony_ci SkColorFilters::Blend(SK_ColorLTGRAY, SkBlendMode::kSrcIn)); 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ci SkPaint opaqueFilterLayerPaint; 231cb93a386Sopenharmony_ci opaqueFilterLayerPaint.setColor(0xFF020202); // Opaque. 232cb93a386Sopenharmony_ci SkPaint translucentFilterLayerPaint; 233cb93a386Sopenharmony_ci translucentFilterLayerPaint.setColor(0x0F020202); // Not opaque. 234cb93a386Sopenharmony_ci sk_sp<SkPicture> shape; 235cb93a386Sopenharmony_ci { 236cb93a386Sopenharmony_ci SkPictureRecorder picRecorder; 237cb93a386Sopenharmony_ci SkCanvas* canvas = picRecorder.beginRecording(SkIntToScalar(100), SkIntToScalar(100)); 238cb93a386Sopenharmony_ci SkPaint shapePaint; 239cb93a386Sopenharmony_ci shapePaint.setColor(SK_ColorWHITE); 240cb93a386Sopenharmony_ci canvas->drawRect(SkRect::MakeWH(SkIntToScalar(50), SkIntToScalar(50)), shapePaint); 241cb93a386Sopenharmony_ci shape = picRecorder.finishRecordingAsPicture(); 242cb93a386Sopenharmony_ci } 243cb93a386Sopenharmony_ci translucentFilterLayerPaint.setImageFilter(SkImageFilters::Picture(shape)); 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci int index = 0; 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci { 248cb93a386Sopenharmony_ci sk_sp<SkImageFilter> filter(SkImageFilters::Blur(3, 3, nullptr)); 249cb93a386Sopenharmony_ci // first (null) should be optimized, 2nd should not 250cb93a386Sopenharmony_ci SkImageFilter* filters[] = { nullptr, filter.get() }; 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_ci // Any combination of these should cause the pattern to be optimized. 253cb93a386Sopenharmony_ci SkRect* firstBounds[] = { nullptr, &bounds }; 254cb93a386Sopenharmony_ci SkPaint* firstPaints[] = { nullptr, &alphaOnlyLayerPaint }; 255cb93a386Sopenharmony_ci SkRect* secondBounds[] = { nullptr, &bounds }; 256cb93a386Sopenharmony_ci SkPaint* secondPaints[] = { &opaqueFilterLayerPaint, &translucentFilterLayerPaint }; 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci for (auto outerF : filters) { 259cb93a386Sopenharmony_ci bool outerNoOped = !outerF; 260cb93a386Sopenharmony_ci for (auto innerF : filters) { 261cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(firstBounds); ++ i) { 262cb93a386Sopenharmony_ci for (size_t j = 0; j < SK_ARRAY_COUNT(firstPaints); ++j) { 263cb93a386Sopenharmony_ci for (size_t k = 0; k < SK_ARRAY_COUNT(secondBounds); ++k) { 264cb93a386Sopenharmony_ci for (size_t m = 0; m < SK_ARRAY_COUNT(secondPaints); ++m) { 265cb93a386Sopenharmony_ci bool innerNoOped = !secondBounds[k] && !secondPaints[m] && !innerF; 266cb93a386Sopenharmony_ci 267cb93a386Sopenharmony_ci recorder.saveLayer({firstBounds[i], firstPaints[j], outerF, 0}); 268cb93a386Sopenharmony_ci recorder.save(); 269cb93a386Sopenharmony_ci recorder.clipRect(clip); 270cb93a386Sopenharmony_ci recorder.saveLayer({secondBounds[k], secondPaints[m], innerF, 0}); 271cb93a386Sopenharmony_ci recorder.restore(); 272cb93a386Sopenharmony_ci recorder.restore(); 273cb93a386Sopenharmony_ci recorder.restore(); 274cb93a386Sopenharmony_ci assert_merge_svg_opacity_and_filter_layers(r, &record, index, 275cb93a386Sopenharmony_ci outerNoOped); 276cb93a386Sopenharmony_ci #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK 277cb93a386Sopenharmony_ci assert_savelayer_restore(r, &record, index + 3, innerNoOped); 278cb93a386Sopenharmony_ci #endif 279cb93a386Sopenharmony_ci index += 7; 280cb93a386Sopenharmony_ci } 281cb93a386Sopenharmony_ci } 282cb93a386Sopenharmony_ci } 283cb93a386Sopenharmony_ci } 284cb93a386Sopenharmony_ci } 285cb93a386Sopenharmony_ci } 286cb93a386Sopenharmony_ci } 287cb93a386Sopenharmony_ci 288cb93a386Sopenharmony_ci // These should cause the pattern to stay unoptimized: 289cb93a386Sopenharmony_ci struct { 290cb93a386Sopenharmony_ci SkPaint* firstPaint; 291cb93a386Sopenharmony_ci SkPaint* secondPaint; 292cb93a386Sopenharmony_ci } noChangeTests[] = { 293cb93a386Sopenharmony_ci // No change: nullptr filter layer paint not implemented. 294cb93a386Sopenharmony_ci { &alphaOnlyLayerPaint, nullptr }, 295cb93a386Sopenharmony_ci // No change: layer paint is not alpha-only. 296cb93a386Sopenharmony_ci { &translucentLayerPaint, &opaqueFilterLayerPaint }, 297cb93a386Sopenharmony_ci // No change: layer paint has an xfereffect. 298cb93a386Sopenharmony_ci { &xfermodePaint, &opaqueFilterLayerPaint }, 299cb93a386Sopenharmony_ci // No change: filter layer paint has an xfereffect. 300cb93a386Sopenharmony_ci { &alphaOnlyLayerPaint, &xfermodePaint }, 301cb93a386Sopenharmony_ci // No change: layer paint has a color filter. 302cb93a386Sopenharmony_ci { &colorFilterPaint, &opaqueFilterLayerPaint }, 303cb93a386Sopenharmony_ci // No change: filter layer paint has a color filter (until the optimization accounts for 304cb93a386Sopenharmony_ci // constant color draws that can filter the color). 305cb93a386Sopenharmony_ci { &alphaOnlyLayerPaint, &colorFilterPaint } 306cb93a386Sopenharmony_ci }; 307cb93a386Sopenharmony_ci 308cb93a386Sopenharmony_ci for (size_t i = 0; i < SK_ARRAY_COUNT(noChangeTests); ++i) { 309cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, noChangeTests[i].firstPaint); 310cb93a386Sopenharmony_ci recorder.save(); 311cb93a386Sopenharmony_ci recorder.clipRect(clip); 312cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, noChangeTests[i].secondPaint); 313cb93a386Sopenharmony_ci recorder.restore(); 314cb93a386Sopenharmony_ci recorder.restore(); 315cb93a386Sopenharmony_ci recorder.restore(); 316cb93a386Sopenharmony_ci assert_merge_svg_opacity_and_filter_layers(r, &record, index, false); 317cb93a386Sopenharmony_ci index += 7; 318cb93a386Sopenharmony_ci } 319cb93a386Sopenharmony_ci 320cb93a386Sopenharmony_ci // Test the folded alpha value. 321cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, &alphaOnlyLayerPaint); 322cb93a386Sopenharmony_ci recorder.save(); 323cb93a386Sopenharmony_ci recorder.clipRect(clip); 324cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, &opaqueFilterLayerPaint); 325cb93a386Sopenharmony_ci recorder.restore(); 326cb93a386Sopenharmony_ci recorder.restore(); 327cb93a386Sopenharmony_ci recorder.restore(); 328cb93a386Sopenharmony_ci assert_merge_svg_opacity_and_filter_layers(r, &record, index, true); 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_ci const SkRecords::SaveLayer* saveLayer = assert_type<SkRecords::SaveLayer>(r, record, index + 3); 331cb93a386Sopenharmony_ci REPORTER_ASSERT(r, saveLayer != nullptr); 332cb93a386Sopenharmony_ci REPORTER_ASSERT(r, saveLayer->paint->getColor() == 0x03020202); 333cb93a386Sopenharmony_ci 334cb93a386Sopenharmony_ci index += 7; 335cb93a386Sopenharmony_ci 336cb93a386Sopenharmony_ci // Test that currently we do not fold alphas for patterns without the clip. This is just not 337cb93a386Sopenharmony_ci // implemented. 338cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, &alphaOnlyLayerPaint); 339cb93a386Sopenharmony_ci recorder.saveLayer(nullptr, &opaqueFilterLayerPaint); 340cb93a386Sopenharmony_ci recorder.restore(); 341cb93a386Sopenharmony_ci recorder.restore(); 342cb93a386Sopenharmony_ci SkRecordMergeSvgOpacityAndFilterLayers(&record); 343cb93a386Sopenharmony_ci assert_type<SkRecords::SaveLayer>(r, record, index); 344cb93a386Sopenharmony_ci assert_type<SkRecords::SaveLayer>(r, record, index + 1); 345cb93a386Sopenharmony_ci assert_type<SkRecords::Restore>(r, record, index + 2); 346cb93a386Sopenharmony_ci assert_type<SkRecords::Restore>(r, record, index + 3); 347cb93a386Sopenharmony_ci index += 4; 348cb93a386Sopenharmony_ci} 349cb93a386Sopenharmony_ci 350cb93a386Sopenharmony_cistatic void do_draw(SkCanvas* canvas, SkColor color, bool doLayer) { 351cb93a386Sopenharmony_ci canvas->drawColor(SK_ColorWHITE); 352cb93a386Sopenharmony_ci 353cb93a386Sopenharmony_ci SkPaint p; 354cb93a386Sopenharmony_ci p.setColor(color); 355cb93a386Sopenharmony_ci 356cb93a386Sopenharmony_ci if (doLayer) { 357cb93a386Sopenharmony_ci canvas->saveLayer(nullptr, nullptr); 358cb93a386Sopenharmony_ci p.setBlendMode(SkBlendMode::kSrc); 359cb93a386Sopenharmony_ci canvas->drawPaint(p); 360cb93a386Sopenharmony_ci canvas->restore(); 361cb93a386Sopenharmony_ci } else { 362cb93a386Sopenharmony_ci canvas->drawPaint(p); 363cb93a386Sopenharmony_ci } 364cb93a386Sopenharmony_ci} 365cb93a386Sopenharmony_ci 366cb93a386Sopenharmony_cistatic bool is_equal(SkSurface* a, SkSurface* b) { 367cb93a386Sopenharmony_ci const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); 368cb93a386Sopenharmony_ci SkPMColor ca, cb; 369cb93a386Sopenharmony_ci a->readPixels(info, &ca, sizeof(SkPMColor), 0, 0); 370cb93a386Sopenharmony_ci b->readPixels(info, &cb, sizeof(SkPMColor), 0, 0); 371cb93a386Sopenharmony_ci return ca == cb; 372cb93a386Sopenharmony_ci} 373cb93a386Sopenharmony_ci 374cb93a386Sopenharmony_ci// Test drawing w/ and w/o a simple layer (no bounds or paint), so see that drawing ops 375cb93a386Sopenharmony_ci// that *should* draw the same in fact do. 376cb93a386Sopenharmony_ci// 377cb93a386Sopenharmony_ci// Perform this test twice : once directly, and once via a picture 378cb93a386Sopenharmony_ci// 379cb93a386Sopenharmony_cistatic void do_savelayer_srcmode(skiatest::Reporter* r, SkColor color) { 380cb93a386Sopenharmony_ci for (int doPicture = 0; doPicture <= 1; ++doPicture) { 381cb93a386Sopenharmony_ci sk_sp<SkSurface> surf0 = SkSurface::MakeRasterN32Premul(10, 10); 382cb93a386Sopenharmony_ci sk_sp<SkSurface> surf1 = SkSurface::MakeRasterN32Premul(10, 10); 383cb93a386Sopenharmony_ci SkCanvas* c0 = surf0->getCanvas(); 384cb93a386Sopenharmony_ci SkCanvas* c1 = surf1->getCanvas(); 385cb93a386Sopenharmony_ci 386cb93a386Sopenharmony_ci SkPictureRecorder rec0, rec1; 387cb93a386Sopenharmony_ci if (doPicture) { 388cb93a386Sopenharmony_ci c0 = rec0.beginRecording(10, 10); 389cb93a386Sopenharmony_ci c1 = rec1.beginRecording(10, 10); 390cb93a386Sopenharmony_ci } 391cb93a386Sopenharmony_ci 392cb93a386Sopenharmony_ci do_draw(c0, color, false); 393cb93a386Sopenharmony_ci do_draw(c1, color, true); 394cb93a386Sopenharmony_ci 395cb93a386Sopenharmony_ci if (doPicture) { 396cb93a386Sopenharmony_ci surf0->getCanvas()->drawPicture(rec0.finishRecordingAsPicture()); 397cb93a386Sopenharmony_ci surf1->getCanvas()->drawPicture(rec1.finishRecordingAsPicture()); 398cb93a386Sopenharmony_ci } 399cb93a386Sopenharmony_ci 400cb93a386Sopenharmony_ci // we replicate the assert so we can see which line is reported if there is a failure 401cb93a386Sopenharmony_ci if (doPicture) { 402cb93a386Sopenharmony_ci REPORTER_ASSERT(r, is_equal(surf0.get(), surf1.get())); 403cb93a386Sopenharmony_ci } else { 404cb93a386Sopenharmony_ci REPORTER_ASSERT(r, is_equal(surf0.get(), surf1.get())); 405cb93a386Sopenharmony_ci } 406cb93a386Sopenharmony_ci } 407cb93a386Sopenharmony_ci} 408cb93a386Sopenharmony_ci 409cb93a386Sopenharmony_ciDEF_TEST(savelayer_srcmode_opaque, r) { 410cb93a386Sopenharmony_ci do_savelayer_srcmode(r, SK_ColorRED); 411cb93a386Sopenharmony_ci} 412cb93a386Sopenharmony_ci 413cb93a386Sopenharmony_ciDEF_TEST(savelayer_srcmode_alpha, r) { 414cb93a386Sopenharmony_ci do_savelayer_srcmode(r, 0x80FF0000); 415cb93a386Sopenharmony_ci} 416cb93a386Sopenharmony_ci 417