Home | History | Annotate | Download | only in tests
      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