blob: 1c5f56e2073a3312a606866bbe2e7adbb7c78601 [file] [log] [blame]
jvanverth50530632015-04-27 10:36:27 -07001/*
2* Copyright 2013 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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrPathProcessor.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/private/SkTo.h"
11#include "src/gpu/GrShaderCaps.h"
12#include "src/gpu/gl/GrGLGpu.h"
John Rosasco24cbdab2019-09-25 14:14:35 -070013#ifdef SK_GL
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/gl/GrGLVaryingHandler.h"
John Rosasco24cbdab2019-09-25 14:14:35 -070015#endif
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
17#include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h"
18#include "src/gpu/glsl/GrGLSLUniformHandler.h"
19#include "src/gpu/glsl/GrGLSLVarying.h"
jvanverthcba99b82015-06-24 06:59:57 -070020
egdaniele659a582015-11-13 09:55:43 -080021class GrGLPathProcessor : public GrGLSLPrimitiveProcessor {
joshualitt102081a2015-09-11 11:52:17 -070022public:
Brian Osmancf860852018-10-31 14:04:39 -040023 GrGLPathProcessor() : fColor(SK_PMColor4fILLEGAL) {}
joshualitt102081a2015-09-11 11:52:17 -070024
25 static void GenKey(const GrPathProcessor& pathProc,
Brian Salomon94efbf52016-11-29 13:43:05 -050026 const GrShaderCaps&,
joshualitt102081a2015-09-11 11:52:17 -070027 GrProcessorKeyBuilder* b) {
Brian Salomonbfd51832017-01-04 13:22:08 -050028 b->add32(SkToInt(pathProc.viewMatrix().hasPerspective()));
joshualitt102081a2015-09-11 11:52:17 -070029 }
30
31 void emitCode(EmitArgs& args) override {
Chris Dalton60283612018-02-14 13:38:14 -070032 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
joshualitt102081a2015-09-11 11:52:17 -070033 const GrPathProcessor& pathProc = args.fGP.cast<GrPathProcessor>();
34
cdaltonc08f1962016-02-12 12:14:06 -080035 if (!pathProc.viewMatrix().hasPerspective()) {
36 args.fVaryingHandler->setNoPerspective();
37 }
38
joshualitt102081a2015-09-11 11:52:17 -070039 // emit transforms
Brian Salomon510eb152020-02-27 13:52:16 -050040 this->emitTransforms(args.fVaryingHandler, args.fUniformHandler,
41 args.fFPCoordTransformHandler);
joshualitt102081a2015-09-11 11:52:17 -070042
43 // Setup uniform color
Brian Salomonbfd51832017-01-04 13:22:08 -050044 const char* stagedLocalVarName;
Ethan Nicholas16464c32020-04-06 13:53:05 -040045 fColorUniform = args.fUniformHandler->addUniform(nullptr,
46 kFragment_GrShaderFlag,
Ethan Nicholasf7b88202017-09-18 14:10:39 -040047 kHalf4_GrSLType,
Brian Salomonbfd51832017-01-04 13:22:08 -050048 "Color",
49 &stagedLocalVarName);
50 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
joshualitt102081a2015-09-11 11:52:17 -070051
52 // setup constant solid coverage
Ethan Nicholasf7b88202017-09-18 14:10:39 -040053 fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
joshualitt102081a2015-09-11 11:52:17 -070054 }
55
Ethan Nicholasd4efe682019-08-29 16:10:13 -040056 SkString matrix_to_sksl(const SkMatrix& m) {
57 return SkStringPrintf("float3x3(%f, %f, %f, %f, %f, %f, %f, %f, %f)", m[0], m[1], m[2],
58 m[3], m[4], m[5], m[6], m[7], m[8]);
59 }
60
egdaniel0eafe792015-11-20 14:01:22 -080061 void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
Brian Salomon510eb152020-02-27 13:52:16 -050062 GrGLSLUniformHandler* uniformHandler,
bsalomona624bf32016-09-20 09:12:47 -070063 FPCoordTransformHandler* transformHandler) {
Brian Salomon7d8b3972019-11-26 22:34:44 -050064 for (int i = 0; *transformHandler; ++*transformHandler, ++i) {
65 auto [coordTransform, fp] = transformHandler->get();
joshualitt102081a2015-09-11 11:52:17 -070066
Brian Salomon510eb152020-02-27 13:52:16 -050067 SkString matrix;
Brian Salomon510eb152020-02-27 13:52:16 -050068 GrShaderVar fragmentVar;
Brian Salomon8d1dcd72020-03-20 21:06:41 -040069 GrShaderVar transformVar;
Brian Salomon510eb152020-02-27 13:52:16 -050070 if (fp.isSampledWithExplicitCoords()) {
71 if (coordTransform.isNoOp()) {
72 transformHandler->omitCoordsForCurrCoordTransform();
73 continue;
74 } else {
75 const char* name;
76 SkString strUniName;
77 strUniName.printf("CoordTransformMatrix_%d", i);
Brian Salomon8d1dcd72020-03-20 21:06:41 -040078 auto& uni = fUniformTransform.push_back();
79 if (coordTransform.matrix().isScaleTranslate()) {
80 uni.fType = kFloat4_GrSLType;
81 } else {
82 uni.fType = kFloat3x3_GrSLType;
83 }
84 uni.fHandle = uniformHandler
Ethan Nicholas16464c32020-04-06 13:53:05 -040085 ->addUniform(nullptr,
86 kFragment_GrShaderFlag,
Brian Salomon8d1dcd72020-03-20 21:06:41 -040087 uni.fType,
88 strUniName.c_str(),
89 &name)
90 .toIndex();
91 transformVar = uniformHandler->getUniformVariable(uni.fHandle);
Brian Salomon510eb152020-02-27 13:52:16 -050092 }
93 } else {
94 SkString strVaryingName;
95 strVaryingName.printf("TransformedCoord_%d", i);
Brian Salomon8d1dcd72020-03-20 21:06:41 -040096 GrSLType varyingType = coordTransform.matrix().hasPerspective() ? kHalf3_GrSLType
97 : kHalf2_GrSLType;
Brian Salomon510eb152020-02-27 13:52:16 -050098 GrGLSLVarying v(varyingType);
John Rosasco24cbdab2019-09-25 14:14:35 -070099#ifdef SK_GL
Brian Salomon510eb152020-02-27 13:52:16 -0500100 GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*)varyingHandler;
101 fVaryingTransform.push_back().fHandle =
102 glVaryingHandler->addPathProcessingVarying(strVaryingName.c_str(), &v)
103 .toIndex();
John Rosasco24cbdab2019-09-25 14:14:35 -0700104#endif
Brian Salomon510eb152020-02-27 13:52:16 -0500105 fVaryingTransform.back().fType = varyingType;
106 matrix = matrix_to_sksl(coordTransform.matrix());
107 fragmentVar = {SkString(v.fsIn()), varyingType};
108 }
Brian Salomon8d1dcd72020-03-20 21:06:41 -0400109 transformHandler->specifyCoordsForCurrCoordTransform(transformVar, fragmentVar);
joshualitt102081a2015-09-11 11:52:17 -0700110 }
111 }
112
egdaniel018fb622015-10-28 07:26:40 -0700113 void setData(const GrGLSLProgramDataManager& pd,
bsalomona624bf32016-09-20 09:12:47 -0700114 const GrPrimitiveProcessor& primProc,
Brian Salomonc241b582019-11-27 08:57:17 -0500115 const CoordTransformRange& transformRange) override {
joshualitt102081a2015-09-11 11:52:17 -0700116 const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
Brian Salomonbfd51832017-01-04 13:22:08 -0500117 if (pathProc.color() != fColor) {
Brian Osmancf860852018-10-31 14:04:39 -0400118 pd.set4fv(fColorUniform, 1, pathProc.color().vec());
joshualitt102081a2015-09-11 11:52:17 -0700119 fColor = pathProc.color();
120 }
joshualitt102081a2015-09-11 11:52:17 -0700121
Brian Salomon510eb152020-02-27 13:52:16 -0500122 int v = 0, u = 0;
Brian Salomonc241b582019-11-27 08:57:17 -0500123 for (auto [transform, fp] : transformRange) {
Brian Salomonb10a6622020-02-20 13:36:01 -0500124 if (fp.isSampledWithExplicitCoords()) {
Brian Salomon510eb152020-02-27 13:52:16 -0500125 if (transform.isNoOp()) {
126 continue;
127 }
128 if (fUniformTransform[u].fHandle.isValid()) {
129 SkMatrix m = GetTransformMatrix(transform, SkMatrix::I());
130 if (!SkMatrixPriv::CheapEqual(fUniformTransform[u].fCurrentValue, m)) {
131 fUniformTransform[u].fCurrentValue = m;
Brian Salomon8d1dcd72020-03-20 21:06:41 -0400132 if (fUniformTransform[u].fType == kFloat4_GrSLType) {
133 float values[4] = {m.getScaleX(), m.getTranslateX(),
134 m.getScaleY(), m.getTranslateY()};
135 pd.set4fv(fUniformTransform[u].fHandle.toIndex(), 1, values);
136 } else {
137 SkASSERT(fUniformTransform[u].fType == kFloat3x3_GrSLType);
138 pd.setSkMatrix(fUniformTransform[u].fHandle.toIndex(), m);
139 }
Brian Salomon510eb152020-02-27 13:52:16 -0500140 }
141 }
142 ++u;
Brian Salomonb10a6622020-02-20 13:36:01 -0500143 } else {
Brian Salomon510eb152020-02-27 13:52:16 -0500144 SkASSERT(fVaryingTransform[v].fHandle.isValid());
145 SkMatrix m = GetTransformMatrix(transform, pathProc.localMatrix());
146 if (!SkMatrixPriv::CheapEqual(fVaryingTransform[v].fCurrentValue, m)) {
147 fVaryingTransform[v].fCurrentValue = m;
148 SkASSERT(fVaryingTransform[v].fType == kHalf2_GrSLType ||
149 fVaryingTransform[v].fType == kHalf3_GrSLType);
150 int components = fVaryingTransform[v].fType == kHalf2_GrSLType ? 2 : 3;
151 pd.setPathFragmentInputTransform(fVaryingTransform[v].fHandle, components, m);
152 }
153 ++v;
Brian Salomon7eabfe82019-12-02 14:20:20 -0500154 }
joshualitt102081a2015-09-11 11:52:17 -0700155 }
156 }
157
158private:
Brian Salomon510eb152020-02-27 13:52:16 -0500159 using VaryingHandle = GrGLSLProgramDataManager::VaryingHandle;
160
161 // Varying transforms are used for non-explicitly sampled FPs. We provide a matrix
162 // to GL as fixed function state and it uses it to compute a varying that we pick up
163 // in the FS as the output of the coord transform.
bsalomon790c90b2016-09-12 12:56:58 -0700164 struct TransformVarying {
Brian Salomon510eb152020-02-27 13:52:16 -0500165 VaryingHandle fHandle;
166 SkMatrix fCurrentValue = SkMatrix::InvalidMatrix();
167 GrSLType fType = kVoid_GrSLType;
168 };
169 // For explicitly sampled FPs we stick a uniform in the FS and apply it to the explicit coords
170 // to implement the CoordTransform.
171 struct TransformUniform {
172 UniformHandle fHandle;
173 SkMatrix fCurrentValue = SkMatrix::InvalidMatrix();
Brian Salomon8d1dcd72020-03-20 21:06:41 -0400174 GrSLType fType = kVoid_GrSLType;
egdanielfe8a8392016-05-09 10:22:19 -0700175 };
176
Brian Salomon510eb152020-02-27 13:52:16 -0500177 SkTArray<TransformVarying, true> fVaryingTransform;
178 SkTArray<TransformUniform, true> fUniformTransform;
egdanielfe8a8392016-05-09 10:22:19 -0700179
joshualitt102081a2015-09-11 11:52:17 -0700180 UniformHandle fColorUniform;
Brian Osmancf860852018-10-31 14:04:39 -0400181 SkPMColor4f fColor;
joshualitt102081a2015-09-11 11:52:17 -0700182
egdaniele659a582015-11-13 09:55:43 -0800183 typedef GrGLSLPrimitiveProcessor INHERITED;
joshualitt102081a2015-09-11 11:52:17 -0700184};
185
Brian Osmancf860852018-10-31 14:04:39 -0400186GrPathProcessor::GrPathProcessor(const SkPMColor4f& color,
joshualitt8072caa2015-02-12 14:20:52 -0800187 const SkMatrix& viewMatrix,
188 const SkMatrix& localMatrix)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400189 : INHERITED(kGrPathProcessor_ClassID)
190 , fColor(color)
Brian Salomon92aee3d2016-12-21 09:20:25 -0500191 , fViewMatrix(viewMatrix)
Ethan Nicholasabff9562017-10-09 10:54:08 -0400192 , fLocalMatrix(localMatrix) {}
joshualitt8072caa2015-02-12 14:20:52 -0800193
Brian Salomon94efbf52016-11-29 13:43:05 -0500194void GrPathProcessor::getGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800195 GrProcessorKeyBuilder* b) const {
joshualitt465283c2015-09-11 08:19:35 -0700196 GrGLPathProcessor::GenKey(*this, caps, b);
joshualitt8072caa2015-02-12 14:20:52 -0800197}
198
Brian Salomon94efbf52016-11-29 13:43:05 -0500199GrGLSLPrimitiveProcessor* GrPathProcessor::createGLSLInstance(const GrShaderCaps& caps) const {
jvanverth50530632015-04-27 10:36:27 -0700200 SkASSERT(caps.pathRenderingSupport());
joshualitt465283c2015-09-11 08:19:35 -0700201 return new GrGLPathProcessor();
joshualitt8072caa2015-02-12 14:20:52 -0800202}