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