ClearTest.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * Copyright 2016 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 "include/core/SkBitmap.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkColor.h"
  10. #include "include/core/SkColorSpace.h"
  11. #include "include/core/SkImageInfo.h"
  12. #include "include/core/SkPaint.h"
  13. #include "include/core/SkRect.h"
  14. #include "include/core/SkRefCnt.h"
  15. #include "include/core/SkSurface.h"
  16. #include "include/core/SkTypes.h"
  17. #include "include/gpu/GrBackendSurface.h"
  18. #include "include/gpu/GrContext.h"
  19. #include "include/gpu/GrContextOptions.h"
  20. #include "include/private/GrTypesPriv.h"
  21. #include "include/private/SkColorData.h"
  22. #include "src/gpu/GrCaps.h"
  23. #include "src/gpu/GrColor.h"
  24. #include "src/gpu/GrContextPriv.h"
  25. #include "src/gpu/GrRenderTargetContext.h"
  26. #include "tests/Test.h"
  27. #include "tools/gpu/GrContextFactory.h"
  28. #include <cstdint>
  29. #include <cstring>
  30. #include <memory>
  31. static bool check_rect(GrRenderTargetContext* rtc, const SkIRect& rect, uint32_t expectedValue,
  32. uint32_t* actualValue, int* failX, int* failY) {
  33. int w = rect.width();
  34. int h = rect.height();
  35. std::unique_ptr<uint32_t[]> pixels(new uint32_t[w * h]);
  36. memset(pixels.get(), ~expectedValue, sizeof(uint32_t) * w * h);
  37. SkImageInfo dstInfo = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  38. if (!rtc->readPixels(dstInfo, pixels.get(), 0, {rect.fLeft, rect.fTop})) {
  39. return false;
  40. }
  41. for (int y = 0; y < h; ++y) {
  42. for (int x = 0; x < w; ++x) {
  43. uint32_t pixel = pixels.get()[y * w + x];
  44. if (pixel != expectedValue) {
  45. *actualValue = pixel;
  46. *failX = x + rect.fLeft;
  47. *failY = y + rect.fTop;
  48. return false;
  49. }
  50. }
  51. }
  52. return true;
  53. }
  54. sk_sp<GrRenderTargetContext> newRTC(GrContext* context, int w, int h) {
  55. return context->priv().makeDeferredRenderTargetContext(SkBackingFit::kExact, w, h,
  56. GrColorType::kRGBA_8888, nullptr);
  57. }
  58. static void clear_op_test(skiatest::Reporter* reporter, GrContext* context) {
  59. static const int kW = 10;
  60. static const int kH = 10;
  61. SkIRect fullRect = SkIRect::MakeWH(kW, kH);
  62. sk_sp<GrRenderTargetContext> rtContext;
  63. // A rectangle that is inset by one on all sides and the 1-pixel wide rectangles that surround
  64. // it.
  65. SkIRect mid1Rect = SkIRect::MakeXYWH(1, 1, kW-2, kH-2);
  66. SkIRect outerLeftEdge = SkIRect::MakeXYWH(0, 0, 1, kH);
  67. SkIRect outerTopEdge = SkIRect::MakeXYWH(0, 0, kW, 1);
  68. SkIRect outerRightEdge = SkIRect::MakeXYWH(kW-1, 0, 1, kH);
  69. SkIRect outerBottomEdge = SkIRect::MakeXYWH(0, kH-1, kW, 1);
  70. // A rectangle that is inset by two on all sides and the 1-pixel wide rectangles that surround
  71. // it.
  72. SkIRect mid2Rect = SkIRect::MakeXYWH(2, 2, kW-4, kH-4);
  73. SkIRect innerLeftEdge = SkIRect::MakeXYWH(1, 1, 1, kH-2);
  74. SkIRect innerTopEdge = SkIRect::MakeXYWH(1, 1, kW-2, 1);
  75. SkIRect innerRightEdge = SkIRect::MakeXYWH(kW-2, 1, 1, kH-2);
  76. SkIRect innerBottomEdge = SkIRect::MakeXYWH(1, kH-2, kW-2, 1);
  77. uint32_t actualValue;
  78. int failX, failY;
  79. static const GrColor kColor1 = 0xABCDEF01;
  80. static const GrColor kColor2 = ~kColor1;
  81. static const SkPMColor4f kColor1f = SkPMColor4f::FromBytes_RGBA(kColor1);
  82. static const SkPMColor4f kColor2f = SkPMColor4f::FromBytes_RGBA(kColor2);
  83. rtContext = newRTC(context, kW, kH);
  84. SkASSERT(rtContext);
  85. // Check a full clear
  86. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  87. if (!check_rect(rtContext.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
  88. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
  89. failX, failY);
  90. }
  91. rtContext = newRTC(context, kW, kH);
  92. SkASSERT(rtContext);
  93. // Check two full clears, same color
  94. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  95. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  96. if (!check_rect(rtContext.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
  97. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
  98. failX, failY);
  99. }
  100. rtContext = newRTC(context, kW, kH);
  101. SkASSERT(rtContext);
  102. // Check two full clears, different colors
  103. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  104. rtContext->clear(&fullRect, kColor2f, GrRenderTargetContext::CanClearFullscreen::kNo);
  105. if (!check_rect(rtContext.get(), fullRect, kColor2, &actualValue, &failX, &failY)) {
  106. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor2, actualValue,
  107. failX, failY);
  108. }
  109. rtContext = newRTC(context, kW, kH);
  110. SkASSERT(rtContext);
  111. // Test a full clear followed by a same color inset clear
  112. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  113. rtContext->clear(&mid1Rect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  114. if (!check_rect(rtContext.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
  115. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
  116. failX, failY);
  117. }
  118. rtContext = newRTC(context, kW, kH);
  119. SkASSERT(rtContext);
  120. // Test a inset clear followed by same color full clear
  121. rtContext->clear(&mid1Rect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  122. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  123. if (!check_rect(rtContext.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
  124. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
  125. failX, failY);
  126. }
  127. rtContext = newRTC(context, kW, kH);
  128. SkASSERT(rtContext);
  129. // Test a full clear followed by a different color inset clear
  130. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  131. rtContext->clear(&mid1Rect, kColor2f, GrRenderTargetContext::CanClearFullscreen::kNo);
  132. if (!check_rect(rtContext.get(), mid1Rect, kColor2, &actualValue, &failX, &failY)) {
  133. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor2, actualValue,
  134. failX, failY);
  135. }
  136. if (!check_rect(rtContext.get(), outerLeftEdge, kColor1, &actualValue, &failX, &failY) ||
  137. !check_rect(rtContext.get(), outerTopEdge, kColor1, &actualValue, &failX, &failY) ||
  138. !check_rect(rtContext.get(), outerRightEdge, kColor1, &actualValue, &failX, &failY) ||
  139. !check_rect(rtContext.get(), outerBottomEdge, kColor1, &actualValue, &failX, &failY)) {
  140. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
  141. failX, failY);
  142. }
  143. rtContext = newRTC(context, kW, kH);
  144. SkASSERT(rtContext);
  145. // Test a inset clear followed by a different full clear
  146. rtContext->clear(&mid1Rect, kColor2f, GrRenderTargetContext::CanClearFullscreen::kNo);
  147. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  148. if (!check_rect(rtContext.get(), fullRect, kColor1, &actualValue, &failX, &failY)) {
  149. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
  150. failX, failY);
  151. }
  152. rtContext = newRTC(context, kW, kH);
  153. SkASSERT(rtContext);
  154. // Check three nested clears from largest to smallest where outermost and innermost are same
  155. // color.
  156. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  157. rtContext->clear(&mid1Rect, kColor2f, GrRenderTargetContext::CanClearFullscreen::kNo);
  158. rtContext->clear(&mid2Rect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  159. if (!check_rect(rtContext.get(), mid2Rect, kColor1, &actualValue, &failX, &failY)) {
  160. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
  161. failX, failY);
  162. }
  163. if (!check_rect(rtContext.get(), innerLeftEdge, kColor2, &actualValue, &failX, &failY) ||
  164. !check_rect(rtContext.get(), innerTopEdge, kColor2, &actualValue, &failX, &failY) ||
  165. !check_rect(rtContext.get(), innerRightEdge, kColor2, &actualValue, &failX, &failY) ||
  166. !check_rect(rtContext.get(), innerBottomEdge, kColor2, &actualValue, &failX, &failY)) {
  167. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor2, actualValue,
  168. failX, failY);
  169. }
  170. if (!check_rect(rtContext.get(), outerLeftEdge, kColor1, &actualValue, &failX, &failY) ||
  171. !check_rect(rtContext.get(), outerTopEdge, kColor1, &actualValue, &failX, &failY) ||
  172. !check_rect(rtContext.get(), outerRightEdge, kColor1, &actualValue, &failX, &failY) ||
  173. !check_rect(rtContext.get(), outerBottomEdge, kColor1, &actualValue, &failX, &failY)) {
  174. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
  175. failX, failY);
  176. }
  177. rtContext = newRTC(context, kW, kH);
  178. SkASSERT(rtContext);
  179. // Swap the order of the second two clears in the above test.
  180. rtContext->clear(&fullRect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  181. rtContext->clear(&mid2Rect, kColor1f, GrRenderTargetContext::CanClearFullscreen::kNo);
  182. rtContext->clear(&mid1Rect, kColor2f, GrRenderTargetContext::CanClearFullscreen::kNo);
  183. if (!check_rect(rtContext.get(), mid1Rect, kColor2, &actualValue, &failX, &failY)) {
  184. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor2, actualValue,
  185. failX, failY);
  186. }
  187. if (!check_rect(rtContext.get(), outerLeftEdge, kColor1, &actualValue, &failX, &failY) ||
  188. !check_rect(rtContext.get(), outerTopEdge, kColor1, &actualValue, &failX, &failY) ||
  189. !check_rect(rtContext.get(), outerRightEdge, kColor1, &actualValue, &failX, &failY) ||
  190. !check_rect(rtContext.get(), outerBottomEdge, kColor1, &actualValue, &failX, &failY)) {
  191. ERRORF(reporter, "Expected 0x%08x but got 0x%08x at (%d, %d).", kColor1, actualValue,
  192. failX, failY);
  193. }
  194. }
  195. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ClearOp, reporter, ctxInfo) {
  196. // Regular clear
  197. clear_op_test(reporter, ctxInfo.grContext());
  198. // Force drawing for clears
  199. GrContextOptions options(ctxInfo.options());
  200. options.fUseDrawInsteadOfClear = GrContextOptions::Enable::kYes;
  201. sk_gpu_test::GrContextFactory workaroundFactory(options);
  202. clear_op_test(reporter, workaroundFactory.get(ctxInfo.type()));
  203. }
  204. void fullscreen_clear_with_layer_test(skiatest::Reporter* reporter, GrContext* context) {
  205. const SkImageInfo ii = SkImageInfo::Make(400, 77, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  206. sk_sp<SkSurface> surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, ii);
  207. SkCanvas* canvas = surf->getCanvas();
  208. SkPaint paints[2];
  209. paints[0].setColor(SK_ColorGREEN);
  210. paints[1].setColor(SK_ColorGRAY);
  211. static const int kLeftX = 158;
  212. static const int kMidX = 258;
  213. static const int kRightX = 383;
  214. static const int kTopY = 26;
  215. static const int kBotY = 51;
  216. const SkRect rects[2] = {
  217. { kLeftX, kTopY, kMidX, kBotY },
  218. { kMidX, kTopY, kRightX, kBotY },
  219. };
  220. for (int i = 0; i < 2; ++i) {
  221. // the bounds parameter is required to cause a full screen clear
  222. canvas->saveLayer(&rects[i], nullptr);
  223. canvas->drawRect(rects[i], paints[i]);
  224. canvas->restore();
  225. }
  226. SkBitmap bm;
  227. bm.allocPixels(ii, 0);
  228. SkAssertResult(surf->readPixels(bm, 0, 0));
  229. bool isCorrect = true;
  230. for (int y = kTopY; isCorrect && y < kBotY; ++y) {
  231. const uint32_t* sl = bm.getAddr32(0, y);
  232. for (int x = kLeftX; x < kMidX; ++x) {
  233. if (SK_ColorGREEN != sl[x]) {
  234. isCorrect = false;
  235. break;
  236. }
  237. }
  238. for (int x = kMidX; x < kRightX; ++x) {
  239. if (SK_ColorGRAY != sl[x]) {
  240. isCorrect = false;
  241. break;
  242. }
  243. }
  244. }
  245. REPORTER_ASSERT(reporter, isCorrect);
  246. }
  247. // From crbug.com/768134
  248. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(FullScreenClearWithLayers, reporter, ctxInfo) {
  249. // Regular clear
  250. fullscreen_clear_with_layer_test(reporter, ctxInfo.grContext());
  251. // Use draws for clears
  252. GrContextOptions options(ctxInfo.options());
  253. options.fUseDrawInsteadOfClear = GrContextOptions::Enable::kYes;
  254. sk_gpu_test::GrContextFactory workaroundFactory(options);
  255. fullscreen_clear_with_layer_test(reporter, workaroundFactory.get(ctxInfo.type()));
  256. }