18dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org/*
28dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org * Copyright 2014 Google Inc.
38dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org *
48dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
58dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org * found in the LICENSE file.
68dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org */
78dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org
88dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org#include "Test.h"
90a98d870448f66ea0df7c37a47b38cf2d3b734e5commit-bot@chromium.org#include "RecordTestUtils.h"
108dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org
118dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org#include "SkRecord.h"
128dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org#include "SkRecordOpts.h"
138dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org#include "SkRecorder.h"
148dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org#include "SkRecords.h"
15f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org#include "SkXfermode.h"
16f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
178dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.orgstatic const int W = 1920, H = 1080;
188dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org
19467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.orgDEF_TEST(RecordOpts_NoopDrawSaveRestore, r) {
20467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    SkRecord record;
21a095041f5148dd1e71f38d0546335ed94199104bcommit-bot@chromium.org    SkRecorder recorder(&record, W, H);
22467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org
23467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    // The save and restore are pointless if there's only draw commands in the middle.
24467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    recorder.save();
25467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org        recorder.drawRect(SkRect::MakeWH(200, 200), SkPaint());
26467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org        recorder.drawRect(SkRect::MakeWH(300, 300), SkPaint());
27467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org        recorder.drawRect(SkRect::MakeWH(100, 100), SkPaint());
28467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    recorder.restore();
29467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org
30467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    record.replace<SkRecords::NoOp>(2);  // NoOps should be allowed.
31467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org
32467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    SkRecordNoopSaveRestores(&record);
33467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org
34467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    assert_type<SkRecords::NoOp>(r, record, 0);
35467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    assert_type<SkRecords::DrawRect>(r, record, 1);
36467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    assert_type<SkRecords::NoOp>(r, record, 2);
37467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    assert_type<SkRecords::DrawRect>(r, record, 3);
38467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org    assert_type<SkRecords::NoOp>(r, record, 4);
39467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org}
40467705adf05ba99bbd9ccdf6a40eb463484a6fbfcommit-bot@chromium.org
417066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.orgDEF_TEST(RecordOpts_SingleNoopSaveRestore, r) {
427066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org    SkRecord record;
43a095041f5148dd1e71f38d0546335ed94199104bcommit-bot@chromium.org    SkRecorder recorder(&record, W, H);
447066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org
457066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org    recorder.save();
467066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org        recorder.clipRect(SkRect::MakeWH(200, 200));
477066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org    recorder.restore();
487066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org
497066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org    SkRecordNoopSaveRestores(&record);
507066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org    for (unsigned i = 0; i < 3; i++) {
517066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org        assert_type<SkRecords::NoOp>(r, record, i);
527066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org    }
537066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org}
547066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org
558dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.orgDEF_TEST(RecordOpts_NoopSaveRestores, r) {
568dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org    SkRecord record;
57a095041f5148dd1e71f38d0546335ed94199104bcommit-bot@chromium.org    SkRecorder recorder(&record, W, H);
588dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org
598dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org    // The second pass will clean up this pair after the first pass noops all the innards.
608dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org    recorder.save();
618dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org        // A simple pointless pair of save/restore.
628dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org        recorder.save();
638dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org        recorder.restore();
648dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org
658dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org        // As long as we don't draw in there, everything is a noop.
668dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org        recorder.save();
678dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org            recorder.clipRect(SkRect::MakeWH(200, 200));
688dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org            recorder.clipRect(SkRect::MakeWH(100, 100));
698dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org        recorder.restore();
708dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org    recorder.restore();
718dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org
728dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org    SkRecordNoopSaveRestores(&record);
738dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org    for (unsigned index = 0; index < 8; index++) {
747066bf3fbff7a54d3692414ec11ca419f3fd0ad5commit-bot@chromium.org        assert_type<SkRecords::NoOp>(r, record, index);
758dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org    }
768dac8b18eea8a729062440b85285d19fc890bb1acommit-bot@chromium.org}
77f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
7899d6a9ee8b3516de892d118c71aa5e6e5c865efdmtkleinDEF_TEST(RecordOpts_SaveSaveLayerRestoreRestore, r) {
7999d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    SkRecord record;
8099d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    SkRecorder recorder(&record, W, H);
8199d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein
8299d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    // A previous bug NoOp'd away the first 3 commands.
8399d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    recorder.save();
8499d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein        recorder.saveLayer(NULL, NULL);
8599d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein        recorder.restore();
8699d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    recorder.restore();
8799d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein
8899d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    SkRecordNoopSaveRestores(&record);
8999d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    assert_type<SkRecords::Save>     (r, record, 0);
9099d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    assert_type<SkRecords::SaveLayer>(r, record, 1);
9199d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    assert_type<SkRecords::Restore>  (r, record, 2);
9299d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein    assert_type<SkRecords::Restore>  (r, record, 3);
9399d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein}
9499d6a9ee8b3516de892d118c71aa5e6e5c865efdmtklein
95f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.orgstatic void assert_savelayer_restore(skiatest::Reporter* r,
96f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org                                     SkRecord* record,
97f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org                                     unsigned i,
98f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org                                     bool shouldBeNoOped) {
99f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    SkRecordNoopSaveLayerDrawRestores(record);
100f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    if (shouldBeNoOped) {
101f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        assert_type<SkRecords::NoOp>(r, *record, i);
102f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        assert_type<SkRecords::NoOp>(r, *record, i+2);
103f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    } else {
104f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        assert_type<SkRecords::SaveLayer>(r, *record, i);
105f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        assert_type<SkRecords::Restore>(r, *record, i+2);
106f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    }
107f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org}
108f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
109f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.orgDEF_TEST(RecordOpts_NoopSaveLayerDrawRestore, r) {
110f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    SkRecord record;
111a095041f5148dd1e71f38d0546335ed94199104bcommit-bot@chromium.org    SkRecorder recorder(&record, W, H);
112f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
113f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    SkRect bounds = SkRect::MakeWH(100, 200);
114f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    SkRect   draw = SkRect::MakeWH(50, 60);
115f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
116f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    SkPaint goodLayerPaint, badLayerPaint, worseLayerPaint;
117f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    goodLayerPaint.setColor(0x03000000);  // Only alpha.
118f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    badLayerPaint.setColor( 0x03040506);  // Not only alpha.
119f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    worseLayerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);  // Any effect will do.
120f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
121f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    SkPaint goodDrawPaint, badDrawPaint;
122f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    goodDrawPaint.setColor(0xFF020202);  // Opaque.
123f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    badDrawPaint.setColor( 0x0F020202);  // Not opaque.
124f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
125f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    // No change: optimization can't handle bounds.
126f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.saveLayer(&bounds, NULL);
127f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        recorder.drawRect(draw, goodDrawPaint);
128f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.restore();
129f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    assert_savelayer_restore(r, &record, 0, false);
130f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
131f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    // SaveLayer/Restore removed: no bounds + no paint = no point.
132f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.saveLayer(NULL, NULL);
133f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        recorder.drawRect(draw, goodDrawPaint);
134f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.restore();
135f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    assert_savelayer_restore(r, &record, 3, true);
136f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
137f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    // TODO(mtklein): test case with null draw paint
138f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
139f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    // No change: layer paint isn't alpha-only.
140f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.saveLayer(NULL, &badLayerPaint);
141f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        recorder.drawRect(draw, goodDrawPaint);
142f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.restore();
143f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    assert_savelayer_restore(r, &record, 6, false);
144f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
145f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    // No change: layer paint has an effect.
146f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.saveLayer(NULL, &worseLayerPaint);
147f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        recorder.drawRect(draw, goodDrawPaint);
148f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.restore();
149f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    assert_savelayer_restore(r, &record, 9, false);
150f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
151f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    // No change: draw paint isn't opaque.
152f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.saveLayer(NULL, &goodLayerPaint);
153f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        recorder.drawRect(draw, badDrawPaint);
154f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.restore();
155f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    assert_savelayer_restore(r, &record, 12, false);
156f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
157f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    // SaveLayer/Restore removed: we can fold in the alpha!
158f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.saveLayer(NULL, &goodLayerPaint);
159f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org        recorder.drawRect(draw, goodDrawPaint);
160f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    recorder.restore();
161f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    assert_savelayer_restore(r, &record, 15, true);
162f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org
163f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, record, 16);
164f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    REPORTER_ASSERT(r, drawRect != NULL);
165f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org    REPORTER_ASSERT(r, drawRect->paint.getColor() == 0x03020202);
166f5bf3cf0257dc3d18932bde51f8eae33442e071fcommit-bot@chromium.org}
167