blob: 473683bc56ac27f65d841c54e5cf640cd40c64cd [file] [log] [blame]
robertphillipsd982eb22014-09-03 11:04:30 -07001/*
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
robertphillipsd982eb22014-09-03 11:04:30 -07008#include "Test.h"
robertphillipsd982eb22014-09-03 11:04:30 -07009
bsalomond309e7a2015-04-30 14:18:54 -070010#if SK_SUPPORT_GPU
11
robertphillipse99d4992014-12-03 07:33:57 -080012#include "GrContextFactory.h"
13#include "GrLayerCache.h"
robertphillipsee6631e2014-09-29 05:32:49 -070014#include "GrRecordReplaceDraw.h"
15#include "RecordTestUtils.h"
robertphillipsd982eb22014-09-03 11:04:30 -070016#include "SkBBHFactory.h"
robertphillipsee6631e2014-09-29 05:32:49 -070017#include "SkPictureRecorder.h"
robertphillipsd982eb22014-09-03 11:04:30 -070018#include "SkRecordDraw.h"
19#include "SkRecorder.h"
20#include "SkUtils.h"
robertphillipsd982eb22014-09-03 11:04:30 -070021
22static const int kWidth = 100;
23static const int kHeight = 100;
24
robertphillips783fe162015-01-07 07:28:41 -080025class JustOneDraw : public SkPicture::AbortCallback {
robertphillipsd982eb22014-09-03 11:04:30 -070026public:
27 JustOneDraw() : fCalls(0) {}
28
mtklein36352bf2015-03-25 18:17:31 -070029 bool abort() override { return fCalls++ > 0; }
robertphillipsd982eb22014-09-03 11:04:30 -070030private:
31 int fCalls;
32};
33
34// Make sure the abort callback works
35DEF_TEST(RecordReplaceDraw_Abort, r) {
robertphillipsee6631e2014-09-29 05:32:49 -070036 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 }
robertphillipsd982eb22014-09-03 11:04:30 -070048
49 SkRecord rerecord;
50 SkRecorder canvas(&rerecord, kWidth, kHeight);
51
robertphillipsd982eb22014-09-03 11:04:30 -070052 JustOneDraw callback;
robertphillipse99d4992014-12-03 07:33:57 -080053 GrRecordReplaceDraw(pic, &canvas, NULL, SkMatrix::I(), &callback);
robertphillipsd982eb22014-09-03 11:04:30 -070054
reed2ff1fce2014-12-11 07:07:37 -080055 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 }
robertphillipsd982eb22014-09-03 11:04:30 -070067}
68
69// Make sure GrRecordReplaceDraw balances unbalanced saves
70DEF_TEST(RecordReplaceDraw_Unbalanced, r) {
robertphillipsee6631e2014-09-29 05:32:49 -070071 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();
reed2ff1fce2014-12-11 07:07:37 -080079 canvas->scale(2, 2);
robertphillipsee6631e2014-09-29 05:32:49 -070080 pic.reset(recorder.endRecording());
81 }
robertphillipsd982eb22014-09-03 11:04:30 -070082
83 SkRecord rerecord;
84 SkRecorder canvas(&rerecord, kWidth, kHeight);
85
robertphillipse99d4992014-12-03 07:33:57 -080086 GrRecordReplaceDraw(pic, &canvas, NULL, SkMatrix::I(), NULL/*callback*/);
robertphillipsd982eb22014-09-03 11:04:30 -070087
reed7bc0b422014-12-11 07:30:58 -080088 // ensure rerecord is balanced (in this case by checking that the count is odd)
89 REPORTER_ASSERT(r, (rerecord.count() & 1) == 1);
robertphillipsd982eb22014-09-03 11:04:30 -070090}
91
robertphillipsd982eb22014-09-03 11:04:30 -070092// Test out the layer replacement functionality with and w/o a BBH
robertphillipse99d4992014-12-03 07:33:57 -080093void test_replacements(skiatest::Reporter* r, GrContext* context, bool useBBH) {
robertphillipsee6631e2014-09-29 05:32:49 -070094 SkAutoTUnref<const SkPicture> pic;
95
96 {
97 SkRTreeFactory bbhFactory;
98 SkPictureRecorder recorder;
mtklein4477c3c2014-10-27 10:27:10 -070099 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight),
robertphillipsee6631e2014-09-29 05:32:49 -0700100 useBBH ? &bbhFactory : NULL);
101
mtkleinc88ceda2014-12-04 07:53:21 -0800102 SkPaint paint;
103 canvas->saveLayer(NULL, &paint);
robertphillipsee6631e2014-09-29 05:32:49 -0700104 canvas->clear(SK_ColorRED);
105 canvas->restore();
106 canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)),
107 SkPaint());
robertphillipsee6631e2014-09-29 05:32:49 -0700108 pic.reset(recorder.endRecording());
109 }
robertphillipsd982eb22014-09-03 11:04:30 -0700110
robertphillipse99d4992014-12-03 07:33:57 -0800111 unsigned key[1] = { 0 };
robertphillips01d6e5f2014-12-01 09:09:27 -0800112
mtkleinc88ceda2014-12-04 07:53:21 -0800113 SkPaint paint;
robertphillipse99d4992014-12-03 07:33:57 -0800114 GrLayerCache* layerCache = context->getLayerCache();
mtkleinc88ceda2014-12-04 07:53:21 -0800115 GrCachedLayer* layer = layerCache->findLayerOrCreate(pic->uniqueID(), 0, 2,
robertphillipse99d4992014-12-03 07:33:57 -0800116 SkIRect::MakeWH(kWidth, kHeight),
robertphillips478dd722014-12-16 08:25:55 -0800117 SkIRect::MakeWH(kWidth, kHeight),
mtkleinc88ceda2014-12-04 07:53:21 -0800118 SkMatrix::I(), key, 1, &paint);
robertphillipse99d4992014-12-03 07:33:57 -0800119
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
bsalomond309e7a2015-04-30 14:18:54 -0700127 SkAutoTUnref<GrTexture> texture(context->textureProvider()->createTexture(desc,
128 false, NULL, 0));
robertphillipse99d4992014-12-03 07:33:57 -0800129 layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight));
robertphillipsd982eb22014-09-03 11:04:30 -0700130
131 SkAutoTUnref<SkBBoxHierarchy> bbh;
132
robertphillipsd982eb22014-09-03 11:04:30 -0700133 SkRecord rerecord;
134 SkRecorder canvas(&rerecord, kWidth, kHeight);
robertphillipse99d4992014-12-03 07:33:57 -0800135 GrRecordReplaceDraw(pic, &canvas, layerCache, SkMatrix::I(), NULL/*callback*/);
robertphillipsd982eb22014-09-03 11:04:30 -0700136
reed2ff1fce2014-12-11 07:07:37 -0800137 int recount = rerecord.count();
robertphillips478dd722014-12-16 08:25:55 -0800138 REPORTER_ASSERT(r, 2 == recount || 4 == recount);
reed2ff1fce2014-12-11 07:07:37 -0800139
140 int index = 0;
robertphillips478dd722014-12-16 08:25:55 -0800141 if (4 == recount) {
reed2ff1fce2014-12-11 07:07:37 -0800142 assert_type<SkRecords::Save>(r, rerecord, 0);
143 index += 1;
144 }
robertphillips478dd722014-12-16 08:25:55 -0800145 assert_type<SkRecords::DrawSprite>(r, rerecord, index + 0);
146 assert_type<SkRecords::DrawRect>(r, rerecord, index + 1);
147 if (4 == recount) {
148 assert_type<SkRecords::Restore>(r, rerecord, 3);
reed2ff1fce2014-12-11 07:07:37 -0800149 }
robertphillipsd982eb22014-09-03 11:04:30 -0700150}
151
robertphillipse99d4992014-12-03 07:33:57 -0800152DEF_GPUTEST(RecordReplaceDraw, r, factory) {
153 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
154 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
155 if (!GrContextFactory::IsRenderingGLContext(glType)) {
156 continue;
157 }
158 GrContext* context = factory->get(glType);
159 if (NULL == context) {
160 continue;
161 }
162
163 test_replacements(r, context, true);
164 test_replacements(r, context, false);
165 }
166}
robertphillipsd982eb22014-09-03 11:04:30 -0700167
168#endif