1d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips/*
2d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips * Copyright 2014 Google Inc.
3d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips *
4d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips * Use of this source code is governed by a BSD-style license that can be
5d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips * found in the LICENSE file.
6d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips */
7d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
8d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips#include "Test.h"
9d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
10d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon#if SK_SUPPORT_GPU
11d309e7aa0efa2d5dd7e7b1af97026fcd3a047e98bsalomon
121530283c483cb88aa725bce50a6d193dd00ee570kkinnunen#include "GrContext.h"
13e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips#include "GrLayerCache.h"
14ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips#include "GrRecordReplaceDraw.h"
15ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips#include "RecordTestUtils.h"
16d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips#include "SkBBHFactory.h"
17ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips#include "SkPictureRecorder.h"
18d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips#include "SkRecordDraw.h"
19d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips#include "SkRecorder.h"
20d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips#include "SkUtils.h"
21d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
22d982eb22d7bce655a609e9b481b3ddfeff361067robertphillipsstatic const int kWidth = 100;
23d982eb22d7bce655a609e9b481b3ddfeff361067robertphillipsstatic const int kHeight = 100;
24d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
25783fe16b8ed1cd1cff34eacc33296874a32f293brobertphillipsclass JustOneDraw : public SkPicture::AbortCallback {
26d982eb22d7bce655a609e9b481b3ddfeff361067robertphillipspublic:
27d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    JustOneDraw() : fCalls(0) {}
28d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
2936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool abort() override { return fCalls++ > 0; }
30d982eb22d7bce655a609e9b481b3ddfeff361067robertphillipsprivate:
31d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    int fCalls;
32d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips};
33d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
34d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips// Make sure the abort callback works
35d982eb22d7bce655a609e9b481b3ddfeff361067robertphillipsDEF_TEST(RecordReplaceDraw_Abort, r) {
36ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    SkAutoTUnref<const SkPicture> pic;
37ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips
38ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    {
39ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        // Record two commands.
40ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        SkPictureRecorder recorder;
41ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
42ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips
43ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight)), SkPaint());
44ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        canvas->clipRect(SkRect::MakeWH(SkIntToScalar(kWidth), SkIntToScalar(kHeight)));
45ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips
46ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        pic.reset(recorder.endRecording());
47ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    }
48d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
49d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    SkRecord rerecord;
50d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    SkRecorder canvas(&rerecord, kWidth, kHeight);
51d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
52d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    JustOneDraw callback;
5396fcdcc219d2a0d3579719b84b28bede76efba64halcanary    GrRecordReplaceDraw(pic, &canvas, nullptr, SkMatrix::I(), &callback);
54d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
552ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    switch (rerecord.count()) {
562ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        case 3:
572ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            assert_type<SkRecords::Save>(r, rerecord, 0);
582ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            assert_type<SkRecords::DrawRect>(r, rerecord, 1);
592ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            assert_type<SkRecords::Restore>(r, rerecord, 2);
602ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
612ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        case 1:
622ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            assert_type<SkRecords::DrawRect>(r, rerecord, 0);
632ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            break;
642ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        default:
652ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed            REPORTER_ASSERT(r, false);
662ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
67d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips}
68d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
69d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips// Make sure GrRecordReplaceDraw balances unbalanced saves
70d982eb22d7bce655a609e9b481b3ddfeff361067robertphillipsDEF_TEST(RecordReplaceDraw_Unbalanced, r) {
71ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    SkAutoTUnref<const SkPicture> pic;
72ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips
73ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    {
74ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        SkPictureRecorder recorder;
75ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
76ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips
77ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        // We won't balance this, but GrRecordReplaceDraw will for us.
78ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        canvas->save();
792ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed        canvas->scale(2, 2);
80ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        pic.reset(recorder.endRecording());
81ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    }
82d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
83d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    SkRecord rerecord;
84d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    SkRecorder canvas(&rerecord, kWidth, kHeight);
85d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
8696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    GrRecordReplaceDraw(pic, &canvas, nullptr, SkMatrix::I(), nullptr/*callback*/);
87d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
887bc0b42567a304313a9c6eaaeba28076d24cbd85reed    // ensure rerecord is balanced (in this case by checking that the count is odd)
897bc0b42567a304313a9c6eaaeba28076d24cbd85reed    REPORTER_ASSERT(r, (rerecord.count() & 1) == 1);
90d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips}
91d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
92d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips// Test out the layer replacement functionality with and w/o a BBH
9307b41eb962fdb007f788fcd82e338d7aef126064robertphillipsvoid test_replacements(skiatest::Reporter* r, GrContext* context, bool doReplace) {
94ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    SkAutoTUnref<const SkPicture> pic;
95ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips
96ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    {
97ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        SkPictureRecorder recorder;
9807b41eb962fdb007f788fcd82e338d7aef126064robertphillips        SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
99c88cedaf8806cc9afa36497dc93eb0d1c329fb6cmtklein        SkPaint paint;
10096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        canvas->saveLayer(nullptr, &paint);
101ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        canvas->clear(SK_ColorRED);
102ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        canvas->restore();
103ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        canvas->drawRect(SkRect::MakeWH(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)),
104ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips                         SkPaint());
105ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips        pic.reset(recorder.endRecording());
106ee6631ef90fb5a9c80de6eacd37632f11367a088robertphillips    }
107d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
10807b41eb962fdb007f788fcd82e338d7aef126064robertphillips    SkAutoTUnref<GrTexture> texture;
109c88cedaf8806cc9afa36497dc93eb0d1c329fb6cmtklein    SkPaint paint;
110e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips    GrLayerCache* layerCache = context->getLayerCache();
111e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips
11207b41eb962fdb007f788fcd82e338d7aef126064robertphillips    if (doReplace) {
11307b41eb962fdb007f788fcd82e338d7aef126064robertphillips        int key[1] = { 0 };
114e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips
11507b41eb962fdb007f788fcd82e338d7aef126064robertphillips        GrCachedLayer* layer = layerCache->findLayerOrCreate(pic->uniqueID(), 0, 2,
11607b41eb962fdb007f788fcd82e338d7aef126064robertphillips                                                             SkIRect::MakeWH(kWidth, kHeight),
11707b41eb962fdb007f788fcd82e338d7aef126064robertphillips                                                             SkIRect::MakeWH(kWidth, kHeight),
11807b41eb962fdb007f788fcd82e338d7aef126064robertphillips                                                             SkMatrix::I(), key, 1, &paint);
119d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
12007b41eb962fdb007f788fcd82e338d7aef126064robertphillips        GrSurfaceDesc desc;
12107b41eb962fdb007f788fcd82e338d7aef126064robertphillips        desc.fConfig = kSkia8888_GrPixelConfig;
12207b41eb962fdb007f788fcd82e338d7aef126064robertphillips        desc.fFlags = kRenderTarget_GrSurfaceFlag;
12307b41eb962fdb007f788fcd82e338d7aef126064robertphillips        desc.fWidth = kWidth;
12407b41eb962fdb007f788fcd82e338d7aef126064robertphillips        desc.fHeight = kHeight;
12507b41eb962fdb007f788fcd82e338d7aef126064robertphillips        desc.fSampleCnt = 0;
12607b41eb962fdb007f788fcd82e338d7aef126064robertphillips
1275ec26ae9bfca635ccc98283aad5deda11519d826bsalomon        texture.reset(context->textureProvider()->createTexture(
1285ec26ae9bfca635ccc98283aad5deda11519d826bsalomon                desc, SkBudgeted::kNo, nullptr, 0));
12960029a5397f75aae4bdb994f26bd297edc3e433crobertphillips        layer->setTexture(texture, SkIRect::MakeWH(kWidth, kHeight), false);
13007b41eb962fdb007f788fcd82e338d7aef126064robertphillips    }
131d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
132d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    SkRecord rerecord;
133d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips    SkRecorder canvas(&rerecord, kWidth, kHeight);
13496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    GrRecordReplaceDraw(pic, &canvas, layerCache, SkMatrix::I(), nullptr/*callback*/);
135d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
13607b41eb962fdb007f788fcd82e338d7aef126064robertphillips    int numLayers = count_instances_of_type<SkRecords::SaveLayer>(rerecord);
13707b41eb962fdb007f788fcd82e338d7aef126064robertphillips    if (doReplace) {
13807b41eb962fdb007f788fcd82e338d7aef126064robertphillips        REPORTER_ASSERT(r, 0 == numLayers);
13907b41eb962fdb007f788fcd82e338d7aef126064robertphillips    } else {
14007b41eb962fdb007f788fcd82e338d7aef126064robertphillips        REPORTER_ASSERT(r, 1 == numLayers);
1412ff1fcede1e9525285c5de1f35fb2dcb0fab32bdreed    }
142d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips}
143d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
1441530283c483cb88aa725bce50a6d193dd00ee570kkinnunenDEF_GPUTEST_FOR_RENDERING_CONTEXTS(RecordReplaceDraw, r, context) {
1451530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    test_replacements(r, context, false);
1461530283c483cb88aa725bce50a6d193dd00ee570kkinnunen    test_replacements(r, context, true);
147e99d499caa7dbc80b58e0faf5ce137e7d30cc5d0robertphillips}
148d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips
149d982eb22d7bce655a609e9b481b3ddfeff361067robertphillips#endif
150