blob: 55f47cee6cd1a571c52d5350268f98f3271b1a27 [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
8#if SK_SUPPORT_GPU
9
10#include "Test.h"
robertphillipsd982eb22014-09-03 11:04:30 -070011
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
mtklein72c9faa2015-01-09 10:06:39 -080029 bool abort() SK_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
bsalomond0423582015-02-06 08:49:24 -0800127 SkAutoTUnref<GrTexture> texture(context->createTexture(desc, false, NULL, 0));
robertphillipse99d4992014-12-03 07:33:57 -0800128 layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight));
robertphillipsd982eb22014-09-03 11:04:30 -0700129
130 SkAutoTUnref<SkBBoxHierarchy> bbh;
131
robertphillipsd982eb22014-09-03 11:04:30 -0700132 SkRecord rerecord;
133 SkRecorder canvas(&rerecord, kWidth, kHeight);
robertphillipse99d4992014-12-03 07:33:57 -0800134 GrRecordReplaceDraw(pic, &canvas, layerCache, SkMatrix::I(), NULL/*callback*/);
robertphillipsd982eb22014-09-03 11:04:30 -0700135
reed2ff1fce2014-12-11 07:07:37 -0800136 int recount = rerecord.count();
robertphillips478dd722014-12-16 08:25:55 -0800137 REPORTER_ASSERT(r, 2 == recount || 4 == recount);
reed2ff1fce2014-12-11 07:07:37 -0800138
139 int index = 0;
robertphillips478dd722014-12-16 08:25:55 -0800140 if (4 == recount) {
reed2ff1fce2014-12-11 07:07:37 -0800141 assert_type<SkRecords::Save>(r, rerecord, 0);
142 index += 1;
143 }
robertphillips478dd722014-12-16 08:25:55 -0800144 assert_type<SkRecords::DrawSprite>(r, rerecord, index + 0);
145 assert_type<SkRecords::DrawRect>(r, rerecord, index + 1);
146 if (4 == recount) {
147 assert_type<SkRecords::Restore>(r, rerecord, 3);
reed2ff1fce2014-12-11 07:07:37 -0800148 }
robertphillipsd982eb22014-09-03 11:04:30 -0700149}
150
robertphillipse99d4992014-12-03 07:33:57 -0800151DEF_GPUTEST(RecordReplaceDraw, r, factory) {
152 for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
153 GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
154 if (!GrContextFactory::IsRenderingGLContext(glType)) {
155 continue;
156 }
157 GrContext* context = factory->get(glType);
158 if (NULL == context) {
159 continue;
160 }
161
162 test_replacements(r, context, true);
163 test_replacements(r, context, false);
164 }
165}
robertphillipsd982eb22014-09-03 11:04:30 -0700166
167#endif