OLD | NEW |
| (Empty) |
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: | |
27 JustOneDraw() : fCalls(0) {} | |
28 | |
29 bool abort() override { return fCalls++ > 0; } | |
30 private: | |
31 int fCalls; | |
32 }; | |
33 | |
34 // Make sure the abort callback works | |
35 DEF_TEST(RecordReplaceDraw_Abort, r) { | |
36 sk_sp<SkPicture> pic; | |
37 | |
38 { | |
39 // Record two commands. | |
40 SkPictureRecorder recorder; | |
41 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntT
oScalar(kHeight)); | |
42 | |
43 canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHe
ight)), SkPaint()); | |
44 canvas->clipRect(SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHe
ight))); | |
45 | |
46 pic = recorder.finishRecordingAsPicture(); | |
47 } | |
48 | |
49 SkRecord rerecord; | |
50 SkRecorder canvas(&rerecord, kWidth, kHeight); | |
51 | |
52 JustOneDraw callback; | |
53 GrRecordReplaceDraw(pic.get(), &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 | |
70 DEF_TEST(RecordReplaceDraw_Unbalanced, r) { | |
71 sk_sp<SkPicture> pic; | |
72 | |
73 { | |
74 SkPictureRecorder recorder; | |
75 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntT
oScalar(kHeight)); | |
76 | |
77 // We won't balance this, but GrRecordReplaceDraw will for us. | |
78 canvas->save(); | |
79 canvas->scale(2, 2); | |
80 pic = recorder.finishRecordingAsPicture(); | |
81 | |
82 // we may have optimized everything away. If so, just return | |
83 if (pic->approximateOpCount() == 0) { | |
84 return; | |
85 } | |
86 } | |
87 | |
88 SkRecord rerecord; | |
89 SkRecorder canvas(&rerecord, kWidth, kHeight); | |
90 | |
91 GrRecordReplaceDraw(pic.get(), &canvas, nullptr, SkMatrix::I(), nullptr/*cal
lback*/); | |
92 | |
93 // ensure rerecord is balanced (in this case by checking that the count is o
dd) | |
94 REPORTER_ASSERT(r, (rerecord.count() & 1) == 1); | |
95 } | |
96 | |
97 // Test out the layer replacement functionality with and w/o a BBH | |
98 void test_replacements(skiatest::Reporter* r, GrContext* context, bool doReplace
) { | |
99 sk_sp<SkPicture> pic; | |
100 | |
101 { | |
102 SkPictureRecorder recorder; | |
103 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntT
oScalar(kHeight)); | |
104 SkPaint paint; | |
105 canvas->saveLayer(nullptr, &paint); | |
106 canvas->clear(SK_ColorRED); | |
107 canvas->restore(); | |
108 canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth / 2), SkIntToScalar
(kHeight / 2)), | |
109 SkPaint()); | |
110 pic = recorder.finishRecordingAsPicture(); | |
111 } | |
112 | |
113 SkAutoTUnref<GrTexture> texture; | |
114 SkPaint paint; | |
115 GrLayerCache* layerCache = context->getLayerCache(); | |
116 | |
117 if (doReplace) { | |
118 int key[1] = { 0 }; | |
119 | |
120 GrCachedLayer* layer = layerCache->findLayerOrCreate(pic->uniqueID(), 0,
2, | |
121 SkIRect::MakeWH(kWi
dth, kHeight), | |
122 SkIRect::MakeWH(kWi
dth, kHeight), | |
123 SkMatrix::I(), key,
1, &paint); | |
124 | |
125 GrSurfaceDesc desc; | |
126 desc.fConfig = kSkia8888_GrPixelConfig; | |
127 desc.fFlags = kRenderTarget_GrSurfaceFlag; | |
128 desc.fWidth = kWidth; | |
129 desc.fHeight = kHeight; | |
130 desc.fSampleCnt = 0; | |
131 | |
132 // Giving the texture some initial data so the Gpu (specifically vulkan)
does not complain | |
133 // when reading from an uninitialized texture. | |
134 SkAutoTMalloc<uint32_t> srcBuffer(kWidth*kHeight); | |
135 memset(srcBuffer.get(), 0, kWidth*kHeight*sizeof(uint32_t)); | |
136 | |
137 texture.reset(context->textureProvider()->createTexture( | |
138 desc, SkBudgeted::kNo, srcBuffer.get(), 0)); | |
139 layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight), false); | |
140 } | |
141 | |
142 SkRecord rerecord; | |
143 SkRecorder canvas(&rerecord, kWidth, kHeight); | |
144 GrRecordReplaceDraw(pic.get(), &canvas, layerCache, SkMatrix::I(), nullptr/*
callback*/); | |
145 | |
146 int numLayers = count_instances_of_type<SkRecords::SaveLayer>(rerecord); | |
147 if (doReplace) { | |
148 REPORTER_ASSERT(r, 0 == numLayers); | |
149 } else { | |
150 REPORTER_ASSERT(r, 1 == numLayers); | |
151 } | |
152 } | |
153 | |
154 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(RecordReplaceDraw, r, ctxInfo) { | |
155 test_replacements(r, ctxInfo.grContext(), true); | |
156 test_replacements(r, ctxInfo.grContext(), false); | |
157 } | |
158 | |
159 #endif | |
OLD | NEW |