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