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 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 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 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 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