void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { const PLSFinishEffect& fe = args.fGP.cast<PLSFinishEffect>(); GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder; GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; fUseEvenOdd = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType, kLow_GrSLPrecision, "useEvenOdd"); const char* useEvenOdd = uniformHandler->getUniformCStr(fUseEvenOdd); varyingHandler->emitAttributes(fe); this->setupPosition(vsBuilder, gpArgs, fe.inPosition()->fName); this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar, fe.inPosition()->fName, fe.localMatrix(), args.fTransformsIn, args.fTransformsOut); GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder; SkAssertResult(fsBuilder->enableFeature( GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature)); fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL); fsBuilder->codeAppend("float coverage;"); fsBuilder->codeAppendf("if (%s != 0.0) {", useEvenOdd); fsBuilder->codeAppend("coverage = float(abs(pls.windings[0]) % 2) * 0.25;"); fsBuilder->codeAppend("coverage += float(abs(pls.windings[1]) % 2) * 0.25;"); fsBuilder->codeAppend("coverage += float(abs(pls.windings[2]) % 2) * 0.25;"); fsBuilder->codeAppend("coverage += float(abs(pls.windings[3]) % 2) * 0.25;"); fsBuilder->codeAppend("} else {"); fsBuilder->codeAppend("coverage = pls.windings[0] != 0 ? 0.25 : 0.0;"); fsBuilder->codeAppend("coverage += pls.windings[1] != 0 ? 0.25 : 0.0;"); fsBuilder->codeAppend("coverage += pls.windings[2] != 0 ? 0.25 : 0.0;"); fsBuilder->codeAppend("coverage += pls.windings[3] != 0 ? 0.25 : 0.0;"); fsBuilder->codeAppend("}"); if (!fe.colorIgnored()) { this->setupUniformColor(fsBuilder, uniformHandler, args.fOutputColor, &fColorUniform); } fsBuilder->codeAppendf("%s = vec4(coverage);", args.fOutputCoverage); fsBuilder->codeAppendf("%s = vec4(1.0, 0.0, 1.0, 1.0);", args.fOutputColor); }
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { const PLSQuadEdgeEffect& qe = args.fGP.cast<PLSQuadEdgeEffect>(); GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder; GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; // emit attributes varyingHandler->emitAttributes(qe); GrGLSLVertToFrag uv(kVec2f_GrSLType); varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qe.inUV()->fName); GrGLSLVertToFrag ep1(kVec2f_GrSLType); varyingHandler->addVarying("endpoint1", &ep1, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);", ep1.vsOut(), qe.inEndpoint1()->fName, qe.inEndpoint1()->fName); GrGLSLVertToFrag ep2(kVec2f_GrSLType); varyingHandler->addVarying("endpoint2", &ep2, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);", ep2.vsOut(), qe.inEndpoint2()->fName, qe.inEndpoint2()->fName); GrGLSLVertToFrag delta(kVec2f_GrSLType); varyingHandler->addVarying("delta", &delta, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;", delta.vsOut(), ep1.vsOut(), ep2.vsOut(), ep2.vsOut(), ep1.vsOut()); GrGLSLVertToFrag windings(kInt_GrSLType); varyingHandler->addFlatVarying("windings", &windings, kLow_GrSLPrecision); vsBuilder->codeAppendf("%s = %s;", windings.vsOut(), qe.inWindings()->fName); // Setup position this->setupPosition(vsBuilder, gpArgs, qe.inPosition()->fName); // emit transforms this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar, qe.inPosition()->fName, qe.localMatrix(), args.fTransformsIn, args.fTransformsOut); GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder; SkAssertResult(fsBuilder->enableFeature( GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature)); SkAssertResult(fsBuilder->enableFeature( GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); static const int QUAD_ARGS = 2; GrGLSLShaderVar inQuadArgs[QUAD_ARGS] = { GrGLSLShaderVar("dot", kFloat_GrSLType, 0, kHigh_GrSLPrecision), GrGLSLShaderVar("uv", kVec2f_GrSLType, 0, kHigh_GrSLPrecision) }; SkString inQuadName; const char* inQuadCode = "if (uv.x * uv.x <= uv.y) {" "return dot >= 0.0;" "} else {" "return false;" "}"; fsBuilder->emitFunction(kBool_GrSLType, "in_quad", QUAD_ARGS, inQuadArgs, inQuadCode, &inQuadName); fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL); // keep the derivative instructions outside the conditional fsBuilder->codeAppendf("highp vec2 uvdX = dFdx(%s);", uv.fsIn()); fsBuilder->codeAppendf("highp vec2 uvdY = dFdy(%s);", uv.fsIn()); fsBuilder->codeAppend("highp vec2 uvIncX = uvdX * 0.45 + uvdY * -0.1;"); fsBuilder->codeAppend("highp vec2 uvIncY = uvdX * 0.1 + uvdY * 0.55;"); fsBuilder->codeAppendf("highp vec2 uv = %s.xy - uvdX * 0.35 - uvdY * 0.25;", uv.fsIn()); fsBuilder->codeAppendf("highp vec2 firstSample = %s.xy - vec2(0.25);", fsBuilder->fragmentPosition()); fsBuilder->codeAppendf("highp float d = dot(%s, (firstSample - %s).yx) * 2.0;", delta.fsIn(), ep1.fsIn()); fsBuilder->codeAppendf("pls.windings[0] += %s(d, uv) ? %s : 0;", inQuadName.c_str(), windings.fsIn()); fsBuilder->codeAppend("uv += uvIncX;"); fsBuilder->codeAppendf("d += %s.x;", delta.fsIn()); fsBuilder->codeAppendf("pls.windings[1] += %s(d, uv) ? %s : 0;", inQuadName.c_str(), windings.fsIn()); fsBuilder->codeAppend("uv += uvIncY;"); fsBuilder->codeAppendf("d += %s.y;", delta.fsIn()); fsBuilder->codeAppendf("pls.windings[2] += %s(d, uv) ? %s : 0;", inQuadName.c_str(), windings.fsIn()); fsBuilder->codeAppend("uv -= uvIncX;"); fsBuilder->codeAppendf("d -= %s.x;", delta.fsIn()); fsBuilder->codeAppendf("pls.windings[3] += %s(d, uv) ? %s : 0;", inQuadName.c_str(), windings.fsIn()); }
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { const PLSAATriangleEffect& te = args.fGP.cast<PLSAATriangleEffect>(); GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder; GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler; GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; varyingHandler->emitAttributes(te); this->setupPosition(vsBuilder, gpArgs, te.inPosition()->fName); GrGLSLVertToFrag v1(kVec2f_GrSLType); varyingHandler->addVarying("Vertex1", &v1, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);", v1.vsOut(), te.inVertex1()->fName, te.inVertex1()->fName); GrGLSLVertToFrag v2(kVec2f_GrSLType); varyingHandler->addVarying("Vertex2", &v2, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);", v2.vsOut(), te.inVertex2()->fName, te.inVertex2()->fName); GrGLSLVertToFrag v3(kVec2f_GrSLType); varyingHandler->addVarying("Vertex3", &v3, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);", v3.vsOut(), te.inVertex3()->fName, te.inVertex3()->fName); GrGLSLVertToFrag delta1(kVec2f_GrSLType); varyingHandler->addVarying("delta1", &delta1, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;", delta1.vsOut(), v1.vsOut(), v2.vsOut(), v2.vsOut(), v1.vsOut()); GrGLSLVertToFrag delta2(kVec2f_GrSLType); varyingHandler->addVarying("delta2", &delta2, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;", delta2.vsOut(), v2.vsOut(), v3.vsOut(), v3.vsOut(), v2.vsOut()); GrGLSLVertToFrag delta3(kVec2f_GrSLType); varyingHandler->addVarying("delta3", &delta3, kHigh_GrSLPrecision); vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;", delta3.vsOut(), v3.vsOut(), v1.vsOut(), v1.vsOut(), v3.vsOut()); GrGLSLVertToFrag windings(kInt_GrSLType); varyingHandler->addFlatVarying("windings", &windings, kLow_GrSLPrecision); vsBuilder->codeAppendf("%s = %s;", windings.vsOut(), te.inWindings()->fName); // emit transforms this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar, te.inPosition()->fName, te.localMatrix(), args.fTransformsIn, args.fTransformsOut); GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder; SkAssertResult(fsBuilder->enableFeature( GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature)); SkAssertResult(fsBuilder->enableFeature( GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature)); fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL); // Compute four subsamples, each shifted a quarter pixel along x and y from // gl_FragCoord. The oriented box positioning of the subsamples is of course not // optimal, but it greatly simplifies the math and this simplification is necessary for // performance reasons. fsBuilder->codeAppendf("highp vec2 firstSample = %s.xy - vec2(0.25);", fsBuilder->fragmentPosition()); fsBuilder->codeAppendf("highp vec2 delta1 = %s;", delta1.fsIn()); fsBuilder->codeAppendf("highp vec2 delta2 = %s;", delta2.fsIn()); fsBuilder->codeAppendf("highp vec2 delta3 = %s;", delta3.fsIn()); // Check whether first sample is inside the triangle by computing three dot products. If // all are < 0, we're inside. The first vector in each case is half of what it is // "supposed" to be, because we re-use them later as adjustment factors for which half // is the correct value, so we multiply the dots by two to compensate. fsBuilder->codeAppendf("highp float d1 = dot(delta1, (firstSample - %s).yx) * 2.0;", v1.fsIn()); fsBuilder->codeAppendf("highp float d2 = dot(delta2, (firstSample - %s).yx) * 2.0;", v2.fsIn()); fsBuilder->codeAppendf("highp float d3 = dot(delta3, (firstSample - %s).yx) * 2.0;", v3.fsIn()); fsBuilder->codeAppend("highp float dmax = max(d1, max(d2, d3));"); fsBuilder->codeAppendf("pls.windings[0] += (dmax <= 0.0) ? %s : 0;", windings.fsIn()); // for subsequent samples, we don't recalculate the entire dot product -- just adjust it // to the value it would have if we did recompute it. fsBuilder->codeAppend("d1 += delta1.x;"); fsBuilder->codeAppend("d2 += delta2.x;"); fsBuilder->codeAppend("d3 += delta3.x;"); fsBuilder->codeAppend("dmax = max(d1, max(d2, d3));"); fsBuilder->codeAppendf("pls.windings[1] += (dmax <= 0.0) ? %s : 0;", windings.fsIn()); fsBuilder->codeAppend("d1 += delta1.y;"); fsBuilder->codeAppend("d2 += delta2.y;"); fsBuilder->codeAppend("d3 += delta3.y;"); fsBuilder->codeAppend("dmax = max(d1, max(d2, d3));"); fsBuilder->codeAppendf("pls.windings[2] += (dmax <= 0.0) ? %s : 0;", windings.fsIn()); fsBuilder->codeAppend("d1 -= delta1.x;"); fsBuilder->codeAppend("d2 -= delta2.x;"); fsBuilder->codeAppend("d3 -= delta3.x;"); fsBuilder->codeAppend("dmax = max(d1, max(d2, d3));"); fsBuilder->codeAppendf("pls.windings[3] += (dmax <= 0.0) ? %s : 0;", windings.fsIn()); }