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 "include/private/GrRecordingContext.h"
9#include "include/private/SkTemplates.h"
10#include "src/gpu/GrAppliedClip.h"
11#include "src/gpu/GrMemoryPool.h"
12#include "src/gpu/GrProgramInfo.h"
13#include "src/gpu/GrRecordingContextPriv.h"
14#include "src/gpu/GrRenderTargetContext.h"
15#include "src/gpu/GrRenderTargetPriv.h"
16#include "src/gpu/ops/GrDrawPathOp.h"
17#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
18
19static constexpr GrUserStencilSettings kCoverPass{
20 GrUserStencilSettings::StaticInit<
21 0x0000,
22 GrUserStencilTest::kNotEqual,
23 0xffff,
24 GrUserStencilOp::kZero,
25 GrUserStencilOp::kKeep,
26 0xffff>()
27};
28
29GrDrawPathOpBase::GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
30 GrPathRendering::FillType fill, GrAA aa)
31 : INHERITED(classID)
32 , fViewMatrix(viewMatrix)
33 , fInputColor(paint.getColor4f())
34 , fFillType(fill)
35 , fDoAA(GrAA::kYes == aa)
36 , fProcessorSet(std::move(paint)) {}
37
38#ifdef SK_DEBUG
39SkString GrDrawPathOp::dumpInfo() const {
40 SkString string;
41 string.printf("PATH: 0x%p", fPath.get());
42 string.append(INHERITED::dumpInfo());
43 return string;
44}
45#endif
46
47const GrProcessorSet::Analysis& GrDrawPathOpBase::doProcessorAnalysis(
48 const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
49 GrClampType clampType) {
50 fAnalysis = fProcessorSet.finalize(
51 fInputColor, GrProcessorAnalysisCoverage::kNone, clip, &kCoverPass,
52 hasMixedSampledCoverage, caps, clampType, &fInputColor);
53 return fAnalysis;
54}
55
56//////////////////////////////////////////////////////////////////////////////
57
58void init_stencil_pass_settings(const GrOpFlushState& flushState,
59 GrPathRendering::FillType fillType, GrStencilSettings* stencil) {
60 const GrAppliedClip* appliedClip = flushState.drawOpArgs().appliedClip();
61 bool stencilClip = appliedClip && appliedClip->hasStencilClip();
62 GrRenderTarget* rt = flushState.drawOpArgs().proxy()->peekRenderTarget();
63 stencil->reset(GrPathRendering::GetStencilPassSettings(fillType), stencilClip,
64 rt->renderTargetPriv().numStencilBits());
65}
66
67//////////////////////////////////////////////////////////////////////////////
68
69std::unique_ptr<GrDrawOp> GrDrawPathOp::Make(GrRecordingContext* context,
70 const SkMatrix& viewMatrix,
71 GrPaint&& paint,
72 GrAA aa,
73 sk_sp<const GrPath> path) {
74 GrOpMemoryPool* pool = context->priv().opMemoryPool();
75
76 return pool->allocate<GrDrawPathOp>(viewMatrix, std::move(paint), aa, std::move(path));
77}
78
79void GrDrawPathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
80 GrPipeline::InputFlags pipelineFlags = GrPipeline::InputFlags::kNone;
81 if (this->doAA()) {
82 pipelineFlags |= GrPipeline::InputFlags::kHWAntialias;
83 }
84
85 auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(flushState,
86 this->detachProcessorSet(),
87 pipelineFlags,
88 &kCoverPass);
89
90 sk_sp<GrPathProcessor> pathProc(GrPathProcessor::Create(this->color(), this->viewMatrix()));
91
92 GrRenderTargetProxy* proxy = flushState->proxy();
93 GrProgramInfo programInfo(proxy->numSamples(),
94 proxy->numStencilSamples(),
95 proxy->backendFormat(),
96 flushState->writeView()->origin(),
97 pipeline,
98 pathProc.get(),
99 GrPrimitiveType::kPath);
100
101 flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
102 flushState->bindTextures(programInfo.primProc(), nullptr, programInfo.pipeline());
103
104 GrStencilSettings stencil;
105 init_stencil_pass_settings(*flushState, this->fillType(), &stencil);
106 flushState->gpu()->pathRendering()->drawPath(proxy->peekRenderTarget(),
107 programInfo, stencil, fPath.get());
108}
109
110//////////////////////////////////////////////////////////////////////////////
111
112inline void pre_translate_transform_values(const float* xforms,
113 GrPathRendering::PathTransformType type, int count,
114 SkScalar x, SkScalar y, float* dst) {
115 if (0 == x && 0 == y) {
116 memcpy(dst, xforms, count * GrPathRendering::PathTransformSize(type) * sizeof(float));
117 return;
118 }
119 switch (type) {
120 case GrPathRendering::kNone_PathTransformType:
121 SK_ABORT("Cannot pre-translate kNone_PathTransformType.");
122 break;
123 case GrPathRendering::kTranslateX_PathTransformType:
124 SkASSERT(0 == y);
125 for (int i = 0; i < count; i++) {
126 dst[i] = xforms[i] + x;
127 }
128 break;
129 case GrPathRendering::kTranslateY_PathTransformType:
130 SkASSERT(0 == x);
131 for (int i = 0; i < count; i++) {
132 dst[i] = xforms[i] + y;
133 }
134 break;
135 case GrPathRendering::kTranslate_PathTransformType:
136 for (int i = 0; i < 2 * count; i += 2) {
137 dst[i] = xforms[i] + x;
138 dst[i + 1] = xforms[i + 1] + y;
139 }
140 break;
141 case GrPathRendering::kAffine_PathTransformType:
142 for (int i = 0; i < 6 * count; i += 6) {
143 dst[i] = xforms[i];
144 dst[i + 1] = xforms[i + 1];
145 dst[i + 2] = xforms[i] * x + xforms[i + 1] * y + xforms[i + 2];
146 dst[i + 3] = xforms[i + 3];
147 dst[i + 4] = xforms[i + 4];
148 dst[i + 5] = xforms[i + 3] * x + xforms[i + 4] * y + xforms[i + 5];
149 }
150 break;
151 default:
152 SK_ABORT("Unknown transform type.");
153 break;
154 }
155}
156