bigrrectaaeffect.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright 2015 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 "gm/gm.h"
  8. #include "include/core/SkBlendMode.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkColor.h"
  11. #include "include/core/SkMatrix.h"
  12. #include "include/core/SkPaint.h"
  13. #include "include/core/SkRRect.h"
  14. #include "include/core/SkRect.h"
  15. #include "include/core/SkScalar.h"
  16. #include "include/core/SkSize.h"
  17. #include "include/core/SkString.h"
  18. #include "include/core/SkTypes.h"
  19. #include "include/gpu/GrContext.h"
  20. #include "include/private/GrSharedEnums.h"
  21. #include "include/private/GrTypesPriv.h"
  22. #include "src/gpu/GrCaps.h"
  23. #include "src/gpu/GrFragmentProcessor.h"
  24. #include "src/gpu/GrPaint.h"
  25. #include "src/gpu/GrRenderTargetContext.h"
  26. #include "src/gpu/GrRenderTargetContextPriv.h"
  27. #include "src/gpu/effects/GrPorterDuffXferProcessor.h"
  28. #include "src/gpu/effects/GrRRectEffect.h"
  29. #include "src/gpu/ops/GrDrawOp.h"
  30. #include "src/gpu/ops/GrFillRectOp.h"
  31. #include "tools/ToolUtils.h"
  32. #include <memory>
  33. #include <utility>
  34. namespace skiagm {
  35. ///////////////////////////////////////////////////////////////////////////////
  36. class BigRRectAAEffectGM : public GpuGM {
  37. public:
  38. BigRRectAAEffectGM(const SkRRect& rrect, const char* name)
  39. : fRRect(rrect)
  40. , fName(name) {
  41. this->setBGColor(ToolUtils::color_to_565(SK_ColorBLUE));
  42. // Each test case draws the rrect with gaps around it.
  43. fTestWidth = SkScalarCeilToInt(rrect.width()) + 2 * kGap;
  44. fTestHeight = SkScalarCeilToInt(rrect.height()) + 2 * kGap;
  45. // Add a pad between test cases.
  46. fTestOffsetX = fTestWidth + kPad;
  47. fTestOffsetY = fTestHeight + kPad;
  48. // We draw two tests in x (fill and inv-fill) and pad around
  49. // all four sides of the image.
  50. fWidth = 2 * fTestOffsetX + kPad;
  51. fHeight = fTestOffsetY + kPad;
  52. }
  53. protected:
  54. SkString onShortName() override {
  55. SkString name;
  56. name.printf("big_rrect_%s_aa_effect", fName);
  57. return name;
  58. }
  59. SkISize onISize() override { return SkISize::Make(fWidth, fHeight); }
  60. void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
  61. SkCanvas* canvas) override {
  62. SkPaint paint;
  63. int y = kPad;
  64. int x = kPad;
  65. constexpr GrClipEdgeType kEdgeTypes[] = {
  66. GrClipEdgeType::kFillAA,
  67. GrClipEdgeType::kInverseFillAA,
  68. };
  69. SkRect testBounds = SkRect::MakeIWH(fTestWidth, fTestHeight);
  70. for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
  71. GrClipEdgeType edgeType = kEdgeTypes[et];
  72. canvas->save();
  73. canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
  74. // Draw a background for the test case
  75. SkPaint paint;
  76. paint.setColor(SK_ColorWHITE);
  77. canvas->drawRect(testBounds, paint);
  78. SkRRect rrect = fRRect;
  79. rrect.offset(SkIntToScalar(x + kGap), SkIntToScalar(y + kGap));
  80. const auto& caps = *renderTargetContext->caps()->shaderCaps();
  81. auto fp = GrRRectEffect::Make(edgeType, rrect, caps);
  82. SkASSERT(fp);
  83. if (fp) {
  84. GrPaint grPaint;
  85. grPaint.setColor4f({ 0, 0, 0, 1.f });
  86. grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
  87. grPaint.addCoverageFragmentProcessor(std::move(fp));
  88. SkRect bounds = testBounds;
  89. bounds.offset(SkIntToScalar(x), SkIntToScalar(y));
  90. renderTargetContext->priv().testingOnly_addDrawOp(
  91. GrFillRectOp::MakeNonAARect(context, std::move(grPaint),
  92. SkMatrix::I(), bounds));
  93. }
  94. canvas->restore();
  95. x = x + fTestOffsetX;
  96. }
  97. }
  98. private:
  99. // pad between test cases
  100. static constexpr int kPad = 7;
  101. // gap between rect for each case that is rendered and exterior of rrect
  102. static constexpr int kGap = 3;
  103. SkRRect fRRect;
  104. int fWidth;
  105. int fHeight;
  106. int fTestWidth;
  107. int fTestHeight;
  108. int fTestOffsetX;
  109. int fTestOffsetY;
  110. const char* fName;
  111. typedef GM INHERITED;
  112. };
  113. ///////////////////////////////////////////////////////////////////////////////
  114. // This value is motivated by bug chromium:477684. It has to be large to cause overflow in
  115. // the shader
  116. constexpr int kSize = 700;
  117. DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRect(SkRect::MakeIWH(kSize, kSize)), "rect"); )
  118. DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize, kSize)), "circle"); )
  119. DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeOval(SkRect::MakeIWH(kSize - 1, kSize - 10)), "ellipse"); )
  120. // The next two have small linear segments between the corners
  121. DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 10.f), "circular_corner"); )
  122. DEF_GM( return new BigRRectAAEffectGM (SkRRect::MakeRectXY(SkRect::MakeIWH(kSize - 1, kSize - 10), kSize/2.f - 10.f, kSize/2.f - 15.f), "elliptical_corner"); )
  123. }