DefaultPathRendererTest.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright 2017 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/SkColor.h"
  9. #include "include/core/SkColorSpace.h"
  10. #include "include/core/SkImageInfo.h"
  11. #include "include/core/SkMatrix.h"
  12. #include "include/core/SkPath.h"
  13. #include "include/core/SkRect.h"
  14. #include "include/core/SkRefCnt.h"
  15. #include "include/core/SkStrokeRec.h"
  16. #include "include/core/SkSurface.h"
  17. #include "include/core/SkTypes.h"
  18. #include "include/gpu/GrBackendSurface.h"
  19. #include "include/gpu/GrContext.h"
  20. #include "include/gpu/GrContextOptions.h"
  21. #include "include/gpu/GrTypes.h"
  22. #include "include/private/GrTypesPriv.h"
  23. #include "include/private/SkColorData.h"
  24. #include "src/gpu/GrCaps.h"
  25. #include "src/gpu/GrClip.h"
  26. #include "src/gpu/GrContextPriv.h"
  27. #include "src/gpu/GrFragmentProcessor.h"
  28. #include "src/gpu/GrPaint.h"
  29. #include "src/gpu/GrRenderTargetContext.h"
  30. #include "src/gpu/GrStyle.h"
  31. #include "src/gpu/effects/generated/GrConstColorProcessor.h"
  32. #include "tests/Test.h"
  33. #include "tools/gpu/GrContextFactory.h"
  34. #include <utility>
  35. static void only_allow_default(GrContextOptions* options) {
  36. options->fGpuPathRenderers = GpuPathRenderers::kNone;
  37. }
  38. static SkBitmap read_back(GrRenderTargetContext* rtc, int width, int height) {
  39. SkImageInfo dstII = SkImageInfo::MakeN32Premul(width, height);
  40. SkBitmap bm;
  41. bm.allocPixels(dstII);
  42. rtc->readPixels(dstII, bm.getAddr(0, 0), bm.rowBytes(), {0, 0});
  43. return bm;
  44. }
  45. static SkPath make_path(const SkRect& outer, int inset, SkPath::FillType fill) {
  46. SkPath p;
  47. p.addRect(outer, SkPath::kCW_Direction);
  48. p.addRect(outer.makeInset(inset, inset), SkPath::kCCW_Direction);
  49. p.setFillType(fill);
  50. return p;
  51. }
  52. static const int kBigSize = 64; // This should be a power of 2
  53. static const int kPad = 3;
  54. // From crbug.com/769898:
  55. // create an approx fit render target context that will have extra space (i.e., npot)
  56. // draw an inverse wound concave path into it - forcing use of the stencil-using path renderer
  57. // throw the RTC away so the backing GrSurface/GrStencilBuffer can be reused
  58. // create a new render target context that will reuse the prior GrSurface
  59. // draw a normally wound concave path that touches outside of the approx fit RTC's content rect
  60. //
  61. // When the bug manifests the GrDefaultPathRenderer/GrMSAAPathRenderer is/was leaving the stencil
  62. // buffer outside of the first content rect in a bad state and the second draw would be incorrect.
  63. static void run_test(GrContext* ctx, skiatest::Reporter* reporter) {
  64. SkPath invPath = make_path(SkRect::MakeXYWH(0, 0, kBigSize, kBigSize),
  65. kBigSize/2-1, SkPath::kInverseWinding_FillType);
  66. SkPath path = make_path(SkRect::MakeXYWH(0, 0, kBigSize, kBigSize),
  67. kPad, SkPath::kWinding_FillType);
  68. GrStyle style(SkStrokeRec::kFill_InitStyle);
  69. {
  70. auto rtc = ctx->priv().makeDeferredRenderTargetContext(
  71. SkBackingFit::kApprox, kBigSize/2 + 1, kBigSize/2 + 1,
  72. GrColorType::kRGBA_8888, nullptr);
  73. rtc->clear(nullptr, { 0, 0, 0, 1 }, GrRenderTargetContext::CanClearFullscreen::kYes);
  74. GrPaint paint;
  75. const SkPMColor4f color = { 1.0f, 0.0f, 0.0f, 1.0f };
  76. auto fp = GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kIgnore);
  77. paint.addColorFragmentProcessor(std::move(fp));
  78. rtc->drawPath(GrNoClip(), std::move(paint), GrAA::kNo,
  79. SkMatrix::I(), invPath, style);
  80. rtc->flush(SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo());
  81. }
  82. {
  83. auto rtc = ctx->priv().makeDeferredRenderTargetContext(
  84. SkBackingFit::kExact, kBigSize, kBigSize, GrColorType::kRGBA_8888, nullptr);
  85. rtc->clear(nullptr, { 0, 0, 0, 1 }, GrRenderTargetContext::CanClearFullscreen::kYes);
  86. GrPaint paint;
  87. const SkPMColor4f color = { 0.0f, 1.0f, 0.0f, 1.0f };
  88. auto fp = GrConstColorProcessor::Make(color, GrConstColorProcessor::InputMode::kIgnore);
  89. paint.addColorFragmentProcessor(std::move(fp));
  90. rtc->drawPath(GrNoClip(), std::move(paint), GrAA::kNo,
  91. SkMatrix::I(), path, style);
  92. SkBitmap bm = read_back(rtc.get(), kBigSize, kBigSize);
  93. bool correct = true;
  94. for (int y = kBigSize/2+1; y < kBigSize-kPad-1 && correct; ++y) {
  95. for (int x = kPad+1; x < kBigSize-kPad-1 && correct; ++x) {
  96. correct = bm.getColor(x, y) == SK_ColorBLACK;
  97. REPORTER_ASSERT(reporter, correct);
  98. }
  99. }
  100. }
  101. }
  102. DEF_GPUTEST_FOR_CONTEXTS(GrDefaultPathRendererTest,
  103. sk_gpu_test::GrContextFactory::IsRenderingContext,
  104. reporter, ctxInfo, only_allow_default) {
  105. GrContext* ctx = ctxInfo.grContext();
  106. run_test(ctx, reporter);
  107. }