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
10 #if SK_SUPPORT_GPU
11
12 #include "GrContext.h"
13 #include "GrLayerCache.h"
14 #include "GrRecordReplaceDraw.h"
15 #include "RecordTestUtils.h"
16 #include "SkBBHFactory.h"
17 #include "SkPictureRecorder.h"
18 #include "SkRecordDraw.h"
19 #include "SkRecorder.h"
20 #include "SkUtils.h"
21
22 static const int kWidth = 100;
23 static const int kHeight = 100;
24
25 class JustOneDraw : public SkPicture::AbortCallback {
26 public:
JustOneDraw()27 JustOneDraw() : fCalls(0) {}
28
abort()29 bool abort() override { return fCalls++ > 0; }
30 private:
31 int fCalls;
32 };
33
34 // Make sure the abort callback works
DEF_TEST(RecordReplaceDraw_Abort,r)35 DEF_TEST(RecordReplaceDraw_Abort, r) {
36 SkAutoTUnref<const SkPicture> pic;
37
38 {
39 // Record two commands.
40 SkPictureRecorder recorder;
41 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
42
43 canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight)), SkPaint());
44 canvas->clipRect(SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight)));
45
46 pic.reset(recorder.endRecording());
47 }
48
49 SkRecord rerecord;
50 SkRecorder canvas(&rerecord, kWidth, kHeight);
51
52 JustOneDraw callback;
53 GrRecordReplaceDraw(pic, &canvas, nullptr, SkMatrix::I(), &callback);
54
55 switch (rerecord.count()) {
56 case 3:
57 assert_type<SkRecords::Save>(r, rerecord, 0);
58 assert_type<SkRecords::DrawRect>(r, rerecord, 1);
59 assert_type<SkRecords::Restore>(r, rerecord, 2);
60 break;
61 case 1:
62 assert_type<SkRecords::DrawRect>(r, rerecord, 0);
63 break;
64 default:
65 REPORTER_ASSERT(r, false);
66 }
67 }
68
69 // Make sure GrRecordReplaceDraw balances unbalanced saves
DEF_TEST(RecordReplaceDraw_Unbalanced,r)70 DEF_TEST(RecordReplaceDraw_Unbalanced, r) {
71 SkAutoTUnref<const SkPicture> pic;
72
73 {
74 SkPictureRecorder recorder;
75 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
76
77 // We won't balance this, but GrRecordReplaceDraw will for us.
78 canvas->save();
79 canvas->scale(2, 2);
80 pic.reset(recorder.endRecording());
81 }
82
83 SkRecord rerecord;
84 SkRecorder canvas(&rerecord, kWidth, kHeight);
85
86 GrRecordReplaceDraw(pic, &canvas, nullptr, SkMatrix::I(), nullptr/*callback*/);
87
88 // ensure rerecord is balanced (in this case by checking that the count is odd)
89 REPORTER_ASSERT(r, (rerecord.count() & 1) == 1);
90 }
91
92 // Test out the layer replacement functionality with and w/o a BBH
test_replacements(skiatest::Reporter * r,GrContext * context,bool doReplace)93 void test_replacements(skiatest::Reporter* r, GrContext* context, bool doReplace) {
94 SkAutoTUnref<const SkPicture> pic;
95
96 {
97 SkPictureRecorder recorder;
98 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
99 SkPaint paint;
100 canvas->saveLayer(nullptr, &paint);
101 canvas->clear(SK_ColorRED);
102 canvas->restore();
103 canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)),
104 SkPaint());
105 pic.reset(recorder.endRecording());
106 }
107
108 SkAutoTUnref<GrTexture> texture;
109 SkPaint paint;
110 GrLayerCache* layerCache = context->getLayerCache();
111
112 if (doReplace) {
113 int key[1] = { 0 };
114
115 GrCachedLayer* layer = layerCache->findLayerOrCreate(pic->uniqueID(), 0, 2,
116 SkIRect::MakeWH(kWidth, kHeight),
117 SkIRect::MakeWH(kWidth, kHeight),
118 SkMatrix::I(), key, 1, &paint);
119
120 GrSurfaceDesc desc;
121 desc.fConfig = kSkia8888_GrPixelConfig;
122 desc.fFlags = kRenderTarget_GrSurfaceFlag;
123 desc.fWidth = kWidth;
124 desc.fHeight = kHeight;
125 desc.fSampleCnt = 0;
126
127 texture.reset(context->textureProvider()->createTexture(
128 desc, SkBudgeted::kNo, nullptr, 0));
129 layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight), false);
130 }
131
132 SkRecord rerecord;
133 SkRecorder canvas(&rerecord, kWidth, kHeight);
134 GrRecordReplaceDraw(pic, &canvas, layerCache, SkMatrix::I(), nullptr/*callback*/);
135
136 int numLayers = count_instances_of_type<SkRecords::SaveLayer>(rerecord);
137 if (doReplace) {
138 REPORTER_ASSERT(r, 0 == numLayers);
139 } else {
140 REPORTER_ASSERT(r, 1 == numLayers);
141 }
142 }
143
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(RecordReplaceDraw,r,context)144 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(RecordReplaceDraw, r, context) {
145 test_replacements(r, context, false);
146 test_replacements(r, context, true);
147 }
148
149 #endif
150