RecordDrawTest.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. #include "tests/RecordTestUtils.h"
  8. #include "tests/Test.h"
  9. #include "include/core/SkSurface.h"
  10. #include "include/effects/SkDropShadowImageFilter.h"
  11. #include "src/core/SkImagePriv.h"
  12. #include "src/core/SkRecord.h"
  13. #include "src/core/SkRecordDraw.h"
  14. #include "src/core/SkRecordOpts.h"
  15. #include "src/core/SkRecorder.h"
  16. #include "src/core/SkRecords.h"
  17. #include "tools/debugger/DebugCanvas.h"
  18. static const int W = 1920, H = 1080;
  19. class JustOneDraw : public SkPicture::AbortCallback {
  20. public:
  21. JustOneDraw() : fCalls(0) {}
  22. bool abort() override { return fCalls++ > 0; }
  23. private:
  24. int fCalls;
  25. };
  26. DEF_TEST(RecordDraw_LazySaves, r) {
  27. // Record two commands.
  28. SkRecord record;
  29. SkRecorder recorder(&record, W, H);
  30. REPORTER_ASSERT(r, 0 == record.count());
  31. recorder.save();
  32. REPORTER_ASSERT(r, 0 == record.count()); // the save was not recorded (yet)
  33. recorder.drawColor(SK_ColorRED);
  34. REPORTER_ASSERT(r, 1 == record.count());
  35. recorder.scale(2, 2);
  36. REPORTER_ASSERT(r, 3 == record.count()); // now we see the save
  37. recorder.restore();
  38. REPORTER_ASSERT(r, 4 == record.count());
  39. assert_type<SkRecords::DrawPaint>(r, record, 0);
  40. assert_type<SkRecords::Save> (r, record, 1);
  41. assert_type<SkRecords::Concat> (r, record, 2);
  42. assert_type<SkRecords::Restore> (r, record, 3);
  43. recorder.save();
  44. recorder.save();
  45. recorder.restore();
  46. recorder.restore();
  47. REPORTER_ASSERT(r, 4 == record.count());
  48. }
  49. DEF_TEST(RecordDraw_Abort, r) {
  50. // Record two commands.
  51. SkRecord record;
  52. SkRecorder recorder(&record, W, H);
  53. recorder.drawRect(SkRect::MakeWH(200, 300), SkPaint());
  54. recorder.clipRect(SkRect::MakeWH(100, 200));
  55. SkRecord rerecord;
  56. SkRecorder canvas(&rerecord, W, H);
  57. JustOneDraw callback;
  58. SkRecordDraw(record, &canvas, nullptr, nullptr, 0, nullptr/*bbh*/, &callback);
  59. REPORTER_ASSERT(r, 1 == count_instances_of_type<SkRecords::DrawRect>(rerecord));
  60. REPORTER_ASSERT(r, 0 == count_instances_of_type<SkRecords::ClipRect>(rerecord));
  61. }
  62. DEF_TEST(RecordDraw_Unbalanced, r) {
  63. SkRecord record;
  64. SkRecorder recorder(&record, W, H);
  65. recorder.save(); // We won't balance this, but SkRecordDraw will for us.
  66. recorder.scale(2, 2);
  67. SkRecord rerecord;
  68. SkRecorder canvas(&rerecord, W, H);
  69. SkRecordDraw(record, &canvas, nullptr, nullptr, 0, nullptr/*bbh*/, nullptr/*callback*/);
  70. int save_count = count_instances_of_type<SkRecords::Save>(rerecord);
  71. int restore_count = count_instances_of_type<SkRecords::Save>(rerecord);
  72. REPORTER_ASSERT(r, save_count == restore_count);
  73. }
  74. DEF_TEST(RecordDraw_SetMatrixClobber, r) {
  75. // Set up an SkRecord that just scales by 2x,3x.
  76. SkRecord scaleRecord;
  77. SkRecorder scaleCanvas(&scaleRecord, W, H);
  78. SkMatrix scale;
  79. scale.setScale(2, 3);
  80. scaleCanvas.setMatrix(scale);
  81. // Set up an SkRecord with an initial +20, +20 translate.
  82. SkRecord translateRecord;
  83. SkRecorder translateCanvas(&translateRecord, W, H);
  84. SkMatrix translate;
  85. translate.setTranslate(20, 20);
  86. translateCanvas.setMatrix(translate);
  87. SkRecordDraw(scaleRecord, &translateCanvas, nullptr, nullptr, 0, nullptr/*bbh*/, nullptr/*callback*/);
  88. REPORTER_ASSERT(r, 4 == translateRecord.count());
  89. assert_type<SkRecords::SetMatrix>(r, translateRecord, 0);
  90. assert_type<SkRecords::Save> (r, translateRecord, 1);
  91. assert_type<SkRecords::SetMatrix>(r, translateRecord, 2);
  92. assert_type<SkRecords::Restore> (r, translateRecord, 3);
  93. // When we look at translateRecord now, it should have its first +20,+20 translate,
  94. // then a 2x,3x scale that's been concatted with that +20,+20 translate.
  95. const SkRecords::SetMatrix* setMatrix;
  96. setMatrix = assert_type<SkRecords::SetMatrix>(r, translateRecord, 0);
  97. REPORTER_ASSERT(r, setMatrix->matrix == translate);
  98. setMatrix = assert_type<SkRecords::SetMatrix>(r, translateRecord, 2);
  99. SkMatrix expected = scale;
  100. expected.postConcat(translate);
  101. REPORTER_ASSERT(r, setMatrix->matrix == expected);
  102. }
  103. // Like a==b, with a little slop recognizing that float equality can be weird.
  104. static bool sloppy_rect_eq(SkRect a, SkRect b) {
  105. SkRect inset(a), outset(a);
  106. inset.inset(1, 1);
  107. outset.outset(1, 1);
  108. return outset.contains(b) && !inset.contains(b);
  109. }
  110. // TODO This would be nice, but we can't get it right today.
  111. #if 0
  112. DEF_TEST(RecordDraw_BasicBounds, r) {
  113. SkRecord record;
  114. SkRecorder recorder(&record, W, H);
  115. recorder.save();
  116. recorder.clipRect(SkRect::MakeWH(400, 500));
  117. recorder.scale(2, 2);
  118. recorder.drawRect(SkRect::MakeWH(320, 240), SkPaint());
  119. recorder.restore();
  120. SkAutoTMalloc<SkRect> bounds(record.count());
  121. SkRecordFillBounds(SkRect::MakeWH(SkIntToScalar(W), SkIntToScalar(H)), record, bounds);
  122. for (int i = 0; i < record.count(); i++) {
  123. REPORTER_ASSERT(r, sloppy_rect_eq(SkRect::MakeWH(400, 480), bounds[i]));
  124. }
  125. }
  126. #endif
  127. // Base test to ensure start/stop range is respected
  128. DEF_TEST(RecordDraw_PartialStartStop, r) {
  129. static const int kWidth = 10, kHeight = 10;
  130. SkRect r1 = { 0, 0, kWidth, kHeight };
  131. SkRect r2 = { 0, 0, kWidth, kHeight/2 };
  132. SkRect r3 = { 0, 0, kWidth/2, kHeight };
  133. SkPaint p;
  134. SkRecord record;
  135. SkRecorder recorder(&record, kWidth, kHeight);
  136. recorder.drawRect(r1, p);
  137. recorder.drawRect(r2, p);
  138. recorder.drawRect(r3, p);
  139. SkRecord rerecord;
  140. SkRecorder canvas(&rerecord, kWidth, kHeight);
  141. SkRecordPartialDraw(record, &canvas, nullptr, 0, 1, 2, SkMatrix::I()); // replay just drawRect of r2
  142. REPORTER_ASSERT(r, 1 == count_instances_of_type<SkRecords::DrawRect>(rerecord));
  143. int index = find_first_instances_of_type<SkRecords::DrawRect>(rerecord);
  144. const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, rerecord, index);
  145. REPORTER_ASSERT(r, drawRect->rect == r2);
  146. }
  147. // A regression test for crbug.com/415468 and https://bug.skia.org/2957 .
  148. //
  149. // This also now serves as a regression test for crbug.com/418417. We used to adjust the
  150. // bounds for the saveLayer, clip, and restore to be greater than the bounds of the picture.
  151. // (We were applying the saveLayer paint to the bounds after restore, which makes no sense.)
  152. DEF_TEST(RecordDraw_SaveLayerAffectsClipBounds, r) {
  153. SkRecord record;
  154. SkRecorder recorder(&record, 50, 50);
  155. // We draw a rectangle with a long drop shadow. We used to not update the clip
  156. // bounds based on SaveLayer paints, so the drop shadow could be cut off.
  157. SkPaint paint;
  158. paint.setImageFilter(SkDropShadowImageFilter::Make(
  159. 20, 0, 0, 0, SK_ColorBLACK,
  160. SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
  161. nullptr));
  162. recorder.saveLayer(nullptr, &paint);
  163. recorder.clipRect(SkRect::MakeWH(20, 40));
  164. recorder.drawRect(SkRect::MakeWH(20, 40), SkPaint());
  165. recorder.restore();
  166. // Under the original bug, the right edge value of the drawRect would be 20 less than asserted
  167. // here because we intersected it with a clip that had not been adjusted for the drop shadow.
  168. //
  169. // The second bug showed up as adjusting the picture bounds (0,0,50,50) by the drop shadow too.
  170. // The saveLayer, clipRect, and restore bounds were incorrectly (0,0,70,50).
  171. SkAutoTMalloc<SkRect> bounds(record.count());
  172. SkRecordFillBounds(SkRect::MakeWH(50, 50), record, bounds);
  173. REPORTER_ASSERT(r, sloppy_rect_eq(bounds[0], SkRect::MakeLTRB(0, 0, 50, 50)));
  174. REPORTER_ASSERT(r, sloppy_rect_eq(bounds[1], SkRect::MakeLTRB(0, 0, 50, 50)));
  175. REPORTER_ASSERT(r, sloppy_rect_eq(bounds[2], SkRect::MakeLTRB(0, 0, 40, 40)));
  176. REPORTER_ASSERT(r, sloppy_rect_eq(bounds[3], SkRect::MakeLTRB(0, 0, 50, 50)));
  177. }
  178. // TODO This would be nice, but we can't get it right today.
  179. #if 0
  180. // When a saveLayer provides an explicit bound and has a complex paint (e.g., one that
  181. // affects transparent black), that bound should serve to shrink the area of the required
  182. // backing store.
  183. DEF_TEST(RecordDraw_SaveLayerBoundsAffectsClipBounds, r) {
  184. SkRecord record;
  185. SkRecorder recorder(&record, 50, 50);
  186. SkPaint p;
  187. p.setBlendMode(SkBlendMode::kSrc);
  188. SkRect layerBounds = SkRect::MakeLTRB(10, 10, 40, 40);
  189. recorder.saveLayer(&layerBounds, &p);
  190. recorder.drawRect(SkRect::MakeLTRB(20, 20, 30, 30), SkPaint());
  191. recorder.restore();
  192. SkAutoTMalloc<SkRect> bounds(record.count());
  193. SkRecordFillBounds(SkRect::MakeWH(50, 50), record, bounds);
  194. REPORTER_ASSERT(r, sloppy_rect_eq(bounds[0], SkRect::MakeLTRB(10, 10, 40, 40)));
  195. REPORTER_ASSERT(r, sloppy_rect_eq(bounds[1], SkRect::MakeLTRB(20, 20, 30, 30)));
  196. REPORTER_ASSERT(r, sloppy_rect_eq(bounds[2], SkRect::MakeLTRB(10, 10, 40, 40)));
  197. }
  198. #endif
  199. DEF_TEST(RecordDraw_drawImage, r){
  200. class SkCanvasMock : public SkCanvas {
  201. public:
  202. SkCanvasMock(int width, int height) : SkCanvas(width, height) {
  203. this->resetTestValues();
  204. }
  205. void onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
  206. const SkPaint* paint) override {
  207. fDrawImageCalled = true;
  208. }
  209. void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
  210. const SkPaint* paint, SrcRectConstraint) override {
  211. fDrawImageRectCalled = true;
  212. }
  213. void resetTestValues() {
  214. fDrawImageCalled = fDrawImageRectCalled = false;
  215. }
  216. bool fDrawImageCalled;
  217. bool fDrawImageRectCalled;
  218. };
  219. auto surface(SkSurface::MakeRasterN32Premul(10, 10));
  220. surface->getCanvas()->clear(SK_ColorGREEN);
  221. sk_sp<SkImage> image(surface->makeImageSnapshot());
  222. SkCanvasMock canvas(10, 10);
  223. {
  224. SkRecord record;
  225. SkRecorder recorder(&record, 10, 10);
  226. recorder.drawImage(image, 0, 0);
  227. SkRecordDraw(record, &canvas, nullptr, nullptr, 0, nullptr, nullptr);
  228. }
  229. REPORTER_ASSERT(r, canvas.fDrawImageCalled);
  230. canvas.resetTestValues();
  231. {
  232. SkRecord record;
  233. SkRecorder recorder(&record, 10, 10);
  234. recorder.drawImageRect(image, SkRect::MakeWH(10, 10), nullptr);
  235. SkRecordDraw(record, &canvas, nullptr, nullptr, 0, nullptr, nullptr);
  236. }
  237. REPORTER_ASSERT(r, canvas.fDrawImageRectCalled);
  238. }