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