1 /* 2 * Copyright 2021 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 // This test only works with the GPU backend. 9 10 #include "gm/gm.h" 11 #include "include/core/SkBlendMode.h" 12 #include "include/core/SkCanvas.h" 13 #include "include/core/SkMatrix.h" 14 #include "include/core/SkPaint.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/private/gpu/ganesh/GrTypesPriv.h" 20 #include "src/core/SkCanvasPriv.h" 21 #include "src/gpu/ganesh/GrCanvas.h" 22 #include "src/gpu/ganesh/GrFragmentProcessor.h" 23 #include "src/gpu/ganesh/GrPaint.h" 24 #include "src/gpu/ganesh/SurfaceDrawContext.h" 25 #include "src/gpu/ganesh/effects/GrPorterDuffXferProcessor.h" 26 #include "tools/gpu/TestOps.h" 27 28 #include <memory> 29 #include <utility> 30 31 class GrAppliedClip; 32 33 namespace skiagm { 34 35 /** 36 * This GM directly exercises a GrProcessor that clips against rects. 37 */ 38 class AARectEffect : public GpuGM { 39 public: AARectEffect()40 AARectEffect() { this->setBGColor(0xFFFFFFFF); } 41 42 protected: getName() const43 SkString getName() const override { return SkString("aa_rect_effect"); } 44 getISize()45 SkISize getISize() override { return SkISize::Make(210, 250); } 46 onOnceBeforeDraw()47 void onOnceBeforeDraw() override {} 48 onDraw(GrRecordingContext * rContext,SkCanvas * canvas,SkString * errorMsg)49 DrawResult onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) override { 50 auto sdc = skgpu::ganesh::TopDeviceSurfaceDrawContext(canvas); 51 if (!sdc) { 52 *errorMsg = kErrorMsg_DrawSkippedGpuOnly; 53 return DrawResult::kSkip; 54 } 55 56 SkScalar y = 12.f; 57 static constexpr SkScalar kDX = 12.f; 58 static constexpr SkScalar kOutset = 5.f; 59 60 static constexpr SkRect kRects[] = { 61 // integer edges 62 SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f), 63 // half-integer edges 64 SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f), 65 // vertically/horizontally thin rects that cover pixel centers 66 SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f), 67 SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 0.75f), 68 // vertically/horizontally thin rects that don't cover pixel centers 69 SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f), 70 SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f), 71 // small in x and y 72 SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f), 73 }; 74 75 for (auto r : kRects) { 76 SkScalar x = kDX; 77 78 for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) { 79 SkRect rect = r.makeOffset(x, y); 80 GrClipEdgeType edgeType = static_cast<GrClipEdgeType>(et); 81 auto fp = GrFragmentProcessor::Rect(/*inputFP=*/nullptr, edgeType, rect); 82 SkASSERT(fp); 83 84 GrPaint grPaint; 85 grPaint.setColor4f({ 0, 0, 0, 1.f }); 86 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc)); 87 grPaint.setCoverageFragmentProcessor(std::move(fp)); 88 auto drawRect = rect.makeOutset(kOutset, kOutset); 89 auto op = sk_gpu_test::test_ops::MakeRect(rContext, std::move(grPaint), drawRect); 90 sdc->addDrawOp(std::move(op)); 91 92 x += SkScalarCeilToScalar(rect.width() + kDX); 93 } 94 95 // Draw rect without and with AA using normal API for reference 96 canvas->save(); 97 canvas->translate(x, y); 98 SkPaint paint; 99 canvas->drawRect(r, paint); 100 x += SkScalarCeilToScalar(r.width() + kDX); 101 paint.setAntiAlias(true); 102 canvas->drawRect(r, paint); 103 canvas->restore(); 104 105 y += SkScalarCeilToScalar(r.height() + 20.f); 106 } 107 108 return DrawResult::kOk; 109 } 110 111 private: 112 using INHERITED = GM; 113 }; 114 115 DEF_GM(return new AARectEffect;) 116 } // namespace skiagm 117