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