• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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