RecordOptsTest.cpp revision 2ff1fcede1e9525285c5de1f35fb2dcb0fab32bd
1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Test.h"
9#include "RecordTestUtils.h"
10
11#include "SkRecord.h"
12#include "SkRecordOpts.h"
13#include "SkRecorder.h"
14#include "SkRecords.h"
15#include "SkXfermode.h"
16
17static const int W = 1920, H = 1080;
18
19DEF_TEST(RecordOpts_NoopDraw, r) {
20    SkRecord record;
21    SkRecorder recorder(&record, W, H);
22
23    recorder.drawRect(SkRect::MakeWH(200, 200), SkPaint());
24    recorder.drawRect(SkRect::MakeWH(300, 300), SkPaint());
25    recorder.drawRect(SkRect::MakeWH(100, 100), SkPaint());
26
27    record.replace<SkRecords::NoOp>(1);  // NoOps should be allowed.
28
29    SkRecordNoopSaveRestores(&record);
30
31    REPORTER_ASSERT(r, 2 == count_instances_of_type<SkRecords::DrawRect>(record));
32}
33
34DEF_TEST(RecordOpts_SingleNoopSaveRestore, r) {
35    SkRecord record;
36    SkRecorder recorder(&record, W, H);
37
38    recorder.save();
39        recorder.clipRect(SkRect::MakeWH(200, 200));
40    recorder.restore();
41
42    SkRecordNoopSaveRestores(&record);
43    for (unsigned i = 0; i < 3; i++) {
44        assert_type<SkRecords::NoOp>(r, record, i);
45    }
46}
47
48DEF_TEST(RecordOpts_NoopSaveRestores, r) {
49    SkRecord record;
50    SkRecorder recorder(&record, W, H);
51
52    // The second pass will clean up this pair after the first pass noops all the innards.
53    recorder.save();
54        // A simple pointless pair of save/restore.
55        recorder.save();
56        recorder.restore();
57
58        // As long as we don't draw in there, everything is a noop.
59        recorder.save();
60            recorder.clipRect(SkRect::MakeWH(200, 200));
61            recorder.clipRect(SkRect::MakeWH(100, 100));
62        recorder.restore();
63    recorder.restore();
64
65    SkRecordNoopSaveRestores(&record);
66    for (unsigned index = 0; index < record.count(); index++) {
67        assert_type<SkRecords::NoOp>(r, record, index);
68    }
69}
70
71DEF_TEST(RecordOpts_SaveSaveLayerRestoreRestore, r) {
72    SkRecord record;
73    SkRecorder recorder(&record, W, H);
74
75    // A previous bug NoOp'd away the first 3 commands.
76    recorder.save();
77        recorder.saveLayer(NULL, NULL);
78        recorder.restore();
79    recorder.restore();
80
81    SkRecordNoopSaveRestores(&record);
82    switch (record.count()) {
83        case 4:
84            assert_type<SkRecords::Save>     (r, record, 0);
85            assert_type<SkRecords::SaveLayer>(r, record, 1);
86            assert_type<SkRecords::Restore>  (r, record, 2);
87            assert_type<SkRecords::Restore>  (r, record, 3);
88            break;
89        case 2:
90            assert_type<SkRecords::SaveLayer>(r, record, 0);
91            assert_type<SkRecords::Restore>  (r, record, 1);
92            break;
93        case 0:
94            break;
95        default:
96            REPORTER_ASSERT(r, false);
97    }
98}
99
100static void assert_savelayer_restore(skiatest::Reporter* r,
101                                     SkRecord* record,
102                                     unsigned i,
103                                     bool shouldBeNoOped) {
104    SkRecordNoopSaveLayerDrawRestores(record);
105    if (shouldBeNoOped) {
106        assert_type<SkRecords::NoOp>(r, *record, i);
107        assert_type<SkRecords::NoOp>(r, *record, i+2);
108    } else {
109        assert_type<SkRecords::SaveLayer>(r, *record, i);
110        assert_type<SkRecords::Restore>(r, *record, i+2);
111    }
112}
113
114DEF_TEST(RecordOpts_NoopSaveLayerDrawRestore, r) {
115    SkRecord record;
116    SkRecorder recorder(&record, W, H);
117
118    SkRect bounds = SkRect::MakeWH(100, 200);
119    SkRect   draw = SkRect::MakeWH(50, 60);
120
121    SkPaint goodLayerPaint, badLayerPaint, worseLayerPaint;
122    goodLayerPaint.setColor(0x03000000);  // Only alpha.
123    badLayerPaint.setColor( 0x03040506);  // Not only alpha.
124    worseLayerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);  // Any effect will do.
125
126    SkPaint goodDrawPaint, badDrawPaint;
127    goodDrawPaint.setColor(0xFF020202);  // Opaque.
128    badDrawPaint.setColor( 0x0F020202);  // Not opaque.
129
130    // No change: optimization can't handle bounds.
131    recorder.saveLayer(&bounds, NULL);
132        recorder.drawRect(draw, goodDrawPaint);
133    recorder.restore();
134    assert_savelayer_restore(r, &record, 0, false);
135
136    // SaveLayer/Restore removed: no bounds + no paint = no point.
137    recorder.saveLayer(NULL, NULL);
138        recorder.drawRect(draw, goodDrawPaint);
139    recorder.restore();
140    assert_savelayer_restore(r, &record, 3, true);
141
142    // TODO(mtklein): test case with null draw paint
143
144    // No change: layer paint isn't alpha-only.
145    recorder.saveLayer(NULL, &badLayerPaint);
146        recorder.drawRect(draw, goodDrawPaint);
147    recorder.restore();
148    assert_savelayer_restore(r, &record, 6, false);
149
150    // No change: layer paint has an effect.
151    recorder.saveLayer(NULL, &worseLayerPaint);
152        recorder.drawRect(draw, goodDrawPaint);
153    recorder.restore();
154    assert_savelayer_restore(r, &record, 9, false);
155
156    // No change: draw paint isn't opaque.
157    recorder.saveLayer(NULL, &goodLayerPaint);
158        recorder.drawRect(draw, badDrawPaint);
159    recorder.restore();
160    assert_savelayer_restore(r, &record, 12, false);
161
162    // SaveLayer/Restore removed: we can fold in the alpha!
163    recorder.saveLayer(NULL, &goodLayerPaint);
164        recorder.drawRect(draw, goodDrawPaint);
165    recorder.restore();
166    assert_savelayer_restore(r, &record, 15, true);
167
168    const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, record, 16);
169    REPORTER_ASSERT(r, drawRect != NULL);
170    REPORTER_ASSERT(r, drawRect->paint.getColor() == 0x03020202);
171}
172