blob: d8be726d6ece51d71cab5a0ea9a713c28c3bbf09 [file] [log] [blame]
Chris Daltoncc604e52017-10-06 16:27:32 -06001/*
2 * Copyright 2017 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 "SkTypes.h"
9#include "Test.h"
10
11#if SK_SUPPORT_GPU
12
13#include "GrContext.h"
14#include "GrContextPriv.h"
15#include "GrClip.h"
16#include "GrRenderTargetContext.h"
17#include "GrRenderTargetContextPriv.h"
18#include "GrShape.h"
19#include "GrPathRenderer.h"
20#include "GrPaint.h"
21#include "SkMatrix.h"
22#include "SkRect.h"
23#include "ccpr/GrCoverageCountingPathRenderer.h"
24#include <cmath>
25
26static constexpr int kCanvasSize = 100;
27
28class CCPRPathDrawer {
29public:
30 CCPRPathDrawer(GrContext* ctx)
31 : fCtx(ctx)
32 , fCCPR(GrCoverageCountingPathRenderer::CreateIfSupported(*fCtx->caps()))
33 , fRTC(fCtx->makeDeferredRenderTargetContext(SkBackingFit::kExact, kCanvasSize,
34 kCanvasSize, kRGBA_8888_GrPixelConfig,
35 nullptr)) {
36 if (fCCPR) {
37 fCtx->contextPriv().addOnFlushCallbackObject(fCCPR.get());
38 }
39 }
40
41 ~CCPRPathDrawer() {
42 if (fCCPR) {
43 fCtx->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(fCCPR.get());
44 }
45 }
46
47 bool valid() { return fCCPR && fRTC; }
48
49 void clear() { fRTC->clear(nullptr, 0, true); }
50
51 void drawPath(const SkPath& path, GrColor4f color = GrColor4f(0, 1, 0, 1)) {
52 GrPaint paint;
53 paint.setColor4f(color);
54 GrNoClip noClip;
55 SkIRect clipBounds = SkIRect::MakeWH(kCanvasSize, kCanvasSize);
56 SkMatrix matrix = SkMatrix::I();
57 GrShape shape(path);
58 fCCPR->drawPath({fCtx, std::move(paint), &GrUserStencilSettings::kUnused, fRTC.get(),
59 &noClip, &clipBounds, &matrix, &shape, GrAAType::kCoverage, false});
60 }
61
62 void flush() {
63 fCtx->flush();
64 }
65
66private:
67 GrContext* const fCtx;
68 sk_sp<GrCoverageCountingPathRenderer> fCCPR;
69 sk_sp<GrRenderTargetContext> fRTC;
70};
71
72DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrCCPRTest, reporter, ctxInfo) {
73 GrContext* const ctx = ctxInfo.grContext();
74 if (!GrCoverageCountingPathRenderer::IsSupported(*ctx->caps())) {
75 return;
76 }
77
78 CCPRPathDrawer ccpr(ctx);
79 if (!ccpr.valid()) {
80 ERRORF(reporter, "could not create render target context for ccpr.");
81 return;
82 }
83
84 // Test very busy paths.
85 static constexpr int kNumBusyVerbs = 1 << 17;
86 ccpr.clear();
87 SkPath busyPath;
88 busyPath.moveTo(0, 0); // top left
89 busyPath.lineTo(kCanvasSize, kCanvasSize); // bottom right
90 for (int i = 2; i < kNumBusyVerbs; ++i) {
91 float offset = i * ((float)kCanvasSize / kNumBusyVerbs);
92 busyPath.lineTo(kCanvasSize - offset, kCanvasSize + offset); // offscreen
93 }
94 ccpr.drawPath(busyPath);
95
96 ccpr.flush(); // If this doesn't crash, the test passed.
97 // If it does, maybe fiddle with fMaxInstancesPerDrawArraysWithoutCrashing in your
98 // platform's GrGLCaps.
99}
100
101#endif