示例#1
0
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     const GrCircleEffect& _outer = args.fFp.cast<GrCircleEffect>();
     (void)_outer;
     auto edgeType = _outer.edgeType;
     (void)edgeType;
     auto center = _outer.center;
     (void)center;
     auto radius = _outer.radius;
     (void)radius;
     prevRadius = -1.0;
     circleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType,
                                                  "circle");
     fragBuilder->codeAppendf(
             "float2 prevCenter;\nfloat prevRadius = %f;\nhalf d;\n@if (%d == 2 || %d == 3) {\n "
             "   d = half((length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z);\n} else {\n "
             "   d = half((1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z);\n}\n@if "
             "((%d == 1 || %d == 3) || %d == 4) {\n    %s = %s * clamp(d, 0.0, 1.0);\n} else "
             "{\n    %s = d > 0.5 ? %s : half4(0.0);\n}\n",
             prevRadius, (int)_outer.edgeType, (int)_outer.edgeType,
             args.fUniformHandler->getUniformCStr(circleVar),
             args.fUniformHandler->getUniformCStr(circleVar),
             args.fUniformHandler->getUniformCStr(circleVar),
             args.fUniformHandler->getUniformCStr(circleVar),
             args.fUniformHandler->getUniformCStr(circleVar),
             args.fUniformHandler->getUniformCStr(circleVar), (int)_outer.edgeType,
             (int)_outer.edgeType, (int)_outer.edgeType, args.fOutputColor, args.fInputColor,
             args.fOutputColor, args.fInputColor);
 }
示例#2
0
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     const GrTiledGradientEffect& _outer = args.fFp.cast<GrTiledGradientEffect>();
     (void)_outer;
     auto mirror = _outer.mirror;
     (void)mirror;
     auto makePremul = _outer.makePremul;
     (void)makePremul;
     auto colorsAreOpaque = _outer.colorsAreOpaque;
     (void)colorsAreOpaque;
     SkString _child1("_child1");
     this->emitChild(_outer.gradLayout_index, &_child1, args);
     fragBuilder->codeAppendf(
             "half4 t = %s;\nif (!%s && t.y < 0.0) {\n    %s = half4(0.0);\n} else {\n    @if "
             "(%s) {\n        half t_1 = t.x - 1.0;\n        half tiled_t = (t_1 - 2.0 * "
             "floor(t_1 * 0.5)) - 1.0;\n        if (sk_Caps.mustDoOpBetweenFloorAndAbs) {\n     "
             "       tiled_t = clamp(tiled_t, -1.0, 1.0);\n        }\n        t.x = "
             "abs(tiled_t);\n    } else {\n        t.x = fract(t.x);\n    }",
             _child1.c_str(),
             (_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true"
                                                                                    : "false"),
             args.fOutputColor, (_outer.mirror ? "true" : "false"));
     SkString _input0("t");
     SkString _child0("_child0");
     this->emitChild(_outer.colorizer_index, _input0.c_str(), &_child0, args);
     fragBuilder->codeAppendf("\n    %s = %s;\n}\n@if (%s) {\n    %s.xyz *= %s.w;\n}\n",
                              args.fOutputColor, _child0.c_str(),
                              (_outer.makePremul ? "true" : "false"), args.fOutputColor,
                              args.fOutputColor);
 }
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     this->emitChild(0, args);
     fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
                                                 args.fInputColor);
     fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
 }
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     const GrCircleBlurFragmentProcessor& _outer =
             args.fFp.cast<GrCircleBlurFragmentProcessor>();
     (void)_outer;
     auto circleRect = _outer.circleRect();
     (void)circleRect;
     auto textureRadius = _outer.textureRadius();
     (void)textureRadius;
     auto solidRadius = _outer.solidRadius();
     (void)solidRadius;
     fCircleDataVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                       kDefault_GrSLPrecision, "circleData");
     fragBuilder->codeAppendf(
             "half2 vec = half2(half((sk_FragCoord.x - float(%s.x)) * float(%s.w)), "
             "half((sk_FragCoord.y - float(%s.y)) * float(%s.w)));\nhalf dist = "
             "float(length(vec)) + (0.5 - float(%s.z)) * float(%s.w);\n%s = %s * texture(%s, "
             "float2(half2(dist, 0.5))).%s.w;\n",
             args.fUniformHandler->getUniformCStr(fCircleDataVar),
             args.fUniformHandler->getUniformCStr(fCircleDataVar),
             args.fUniformHandler->getUniformCStr(fCircleDataVar),
             args.fUniformHandler->getUniformCStr(fCircleDataVar),
             args.fUniformHandler->getUniformCStr(fCircleDataVar),
             args.fUniformHandler->getUniformCStr(fCircleDataVar), args.fOutputColor,
             args.fInputColor ? args.fInputColor : "half4(1)",
             fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
             fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
 }
示例#5
0
void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
    const GrConvexPolyEffect& cpe = args.fFp.cast<GrConvexPolyEffect>();

    const char *edgeArrayName;
    fEdgeUniform = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag,
                                                         kVec3f_GrSLType,
                                                         kDefault_GrSLPrecision,
                                                         "edges",
                                                         cpe.getEdgeCount(),
                                                         &edgeArrayName);
    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
    fragBuilder->codeAppend("\t\tfloat edge;\n");
    const char* fragmentPos = fragBuilder->fragmentPosition();
    for (int i = 0; i < cpe.getEdgeCount(); ++i) {
        fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
                                 edgeArrayName, i, fragmentPos, fragmentPos);
        if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
            fragBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
        } else {
            fragBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
        }
        fragBuilder->codeAppend("\t\talpha *= edge;\n");
    }

    if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
        fragBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
    }
    fragBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor,
                             (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
}
                void emitCode(EmitArgs& args) override {
                    const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
                    const GrSwizzle& swizzle = sfp.swizzle();
                    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;

                    fragBuilder->codeAppendf("%s = %s.%s;",
                                             args.fOutputColor, args.fInputColor, swizzle.c_str());
                }
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     fragBuilder->codeAppendf("%s = ", args.fOutputColor);
     fragBuilder->appendTextureLookupAndModulate(args.fInputColor,
                                               args.fSamplers[0],
                                               args.fCoords[0].c_str(),
                                               args.fCoords[0].getType());
     fragBuilder->codeAppend(";");
 }
void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor,
                                        SkString* outputColor, EmitArgs& args) {

    SkASSERT(outputColor);
    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    outputColor->append(fragBuilder->getMangleString());
    fragBuilder->codeAppendf("vec4 %s;", outputColor->c_str());
    this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args);
}
void GrCircleBlurFragmentProcessor::GLSLProcessor::emitCode(EmitArgs& args) {
    const char *dataName;

    // The data is formatted as:
    // x,y  - the center of the circle
    // z    - inner radius that should map to 0th entry in the texture.
    // w    - the inverse of the distance over which the texture is stretched.
    fDataUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
                                                    kVec4f_GrSLType,
                                                    kDefault_GrSLPrecision,
                                                    "data",
                                                    &dataName);

    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;

    if (args.fInputColor) {
        fragBuilder->codeAppendf("vec4 src=%s;", args.fInputColor);
    } else {
        fragBuilder->codeAppendf("vec4 src=vec4(1);");
    }

    // We just want to compute "(length(vec) - %s.z + 0.5) * %s.w" but need to rearrange
    // for precision.
    fragBuilder->codeAppendf("vec2 vec = vec2( (sk_FragCoord.x - %s.x) * %s.w, "
                                              "(sk_FragCoord.y - %s.y) * %s.w );",
                             dataName, dataName, dataName, dataName);
    fragBuilder->codeAppendf("float dist = length(vec) + (0.5 - %s.z) * %s.w;",
                             dataName, dataName);

    fragBuilder->codeAppendf("float intensity = ");
    fragBuilder->appendTextureLookup(args.fTexSamplers[0], "vec2(dist, 0.5)");
    fragBuilder->codeAppend(".a;");

    fragBuilder->codeAppendf("%s = src * intensity;\n", args.fOutputColor );
}
示例#10
0
        void onEmitCode(EmitArgs& args) override {
            GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
            GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;

            // add uniform
            const char* xformUniName = nullptr;
            fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kMat22f_GrSLType,
                                                   kDefault_GrSLPrecision, "Xform", &xformUniName);

            SkString dstNormalColorName("dstNormalColor");
            this->emitChild(0, nullptr, &dstNormalColorName, args);
            fragBuilder->codeAppendf("vec3 normal = normalize(%s.rgb - vec3(0.5));",
                                     dstNormalColorName.c_str());

            // If there's no x & y components, return (0, 0, +/- 1) instead to avoid division by 0
            fragBuilder->codeAppend( "if (abs(normal.z) > 0.999) {");
            fragBuilder->codeAppendf("    %s = normalize(vec4(0.0, 0.0, normal.z, 0.0));",
                    args.fOutputColor);
            // Else, Normalizing the transformed X and Y, while keeping constant both Z and the
            // vector's angle in the XY plane. This maintains the "slope" for the surface while
            // appropriately rotating the normal regardless of any anisotropic scaling that occurs.
            // Here, we call 'scaling factor' the number that must divide the transformed X and Y so
            // that the normal's length remains equal to 1.
            fragBuilder->codeAppend( "} else {");
            fragBuilder->codeAppendf("    vec2 transformed = %s * normal.xy;",
                    xformUniName);
            fragBuilder->codeAppend( "    float scalingFactorSquared = "
                                                 "( (transformed.x * transformed.x) "
                                                   "+ (transformed.y * transformed.y) )"
                                                 "/(1.0 - (normal.z * normal.z));");
            fragBuilder->codeAppendf("    %s = vec4(transformed*inversesqrt(scalingFactorSquared),"
                                                   "normal.z, 0.0);",
                    args.fOutputColor);
            fragBuilder->codeAppend( "}");
        }
    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
        const GrBitmapTextGeoProc& btgp = args.fGP.cast<GrBitmapTextGeoProc>();

        GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
        GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
        GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;

        // emit attributes
        varyingHandler->emitAttributes(btgp);

        const char* atlasSizeInvName;
        fAtlasSizeInvUniform = uniformHandler->addUniform(kVertex_GrShaderFlag,
                                                          kFloat2_GrSLType,
                                                          kHigh_GrSLPrecision,
                                                          "AtlasSizeInv",
                                                          &atlasSizeInvName);

        GrGLSLVarying uv(kFloat2_GrSLType);
        GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
        GrGLSLVarying texIdx(texIdxType);
        append_index_uv_varyings(args, btgp.inTextureCoords().name(), atlasSizeInvName, &uv,
                                 &texIdx, nullptr);

        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        // Setup pass through color
        if (btgp.hasVertexColor()) {
            varyingHandler->addPassThroughAttribute(btgp.inColor(), args.fOutputColor);
        } else {
            this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
                                    &fColorUniform);
        }

        // Setup position
        gpArgs->fPositionVar = btgp.inPosition().asShaderVar();

        // emit transforms
        this->emitTransforms(vertBuilder,
                             varyingHandler,
                             uniformHandler,
                             btgp.inPosition().asShaderVar(),
                             btgp.localMatrix(),
                             args.fFPCoordTransformHandler);

        fragBuilder->codeAppend("half4 texColor;");
        append_multitexture_lookup(args, btgp.numTextureSamplers(),
                                   texIdx, uv.fsIn(), "texColor");

        if (btgp.maskFormat() == kARGB_GrMaskFormat) {
            // modulate by color
            fragBuilder->codeAppendf("%s = %s * texColor;", args.fOutputColor, args.fOutputColor);
            fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
        } else {
            fragBuilder->codeAppendf("%s = texColor;", args.fOutputCoverage);
        }
    }
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     const GrSimpleTextureEffect& _outer = args.fFp.cast<GrSimpleTextureEffect>();
     (void)_outer;
     auto matrix = _outer.matrix();
     (void)matrix;
     SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
     fragBuilder->codeAppendf(
             "%s = %s * texture(%s, %s).%s;\n", args.fOutputColor,
             args.fInputColor ? args.fInputColor : "half4(1)",
             fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
             sk_TransformedCoords2D_0.c_str(),
             fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
 }
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     const GrBlurredEdgeFragmentProcessor& _outer =
             args.fFp.cast<GrBlurredEdgeFragmentProcessor>();
     (void)_outer;
     auto mode = _outer.mode;
     (void)mode;
     fragBuilder->codeAppendf(
             "half factor = 1.0 - %s.w;\n@switch (%d) {\n    case 0:\n        factor = "
             "exp((-factor * factor) * 4.0) - 0.017999999999999999;\n        break;\n    case "
             "1:\n        factor = smoothstep(1.0, 0.0, factor);\n        break;\n}\n%s = "
             "half4(factor);\n",
             args.fInputColor, (int)_outer.mode, args.fOutputColor);
 }
    void emitCode(EmitArgs& args) override {
        const GrColorSpaceXformEffect& csxe = args.fFp.cast<GrColorSpaceXformEffect>();
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;

        fColorSpaceHelper.emitCode(uniformHandler, csxe.colorXform());

        SkString childColor("src_color");
        this->emitChild(0, &childColor, args);

        SkString xformedColor;
        fragBuilder->appendColorGamutXform(&xformedColor, childColor.c_str(), &fColorSpaceHelper);
        fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputColor, xformedColor.c_str(),
                                 args.fInputColor);
    }
示例#15
0
        void emitCode(EmitArgs& args) override {
            if (nullptr == args.fInputColor) {
                args.fInputColor = "vec4(1)";
            }

            GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
            fragBuilder->codeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n",
                                     SK_ITU_BT709_LUM_COEFF_R,
                                     SK_ITU_BT709_LUM_COEFF_G,
                                     SK_ITU_BT709_LUM_COEFF_B,
                                     args.fInputColor);
            fragBuilder->codeAppendf("\t%s = vec4(0, 0, 0, luma);\n",
                                     args.fOutputColor);

        }
示例#16
0
void GLDitherEffect::emitCode(EmitArgs& args) {
    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    // Generate a random number based on the fragment position. For this
    // random number generator, we use the "GLSL rand" function
    // that seems to be floating around on the internet. It works under
    // the assumption that sin(<big number>) oscillates with high frequency
    // and sampling it will generate "randomness". Since we're using this
    // for rendering and not cryptography it should be OK.

    // For each channel c, add the random offset to the pixel to either bump
    // it up or let it remain constant during quantization.
    fragBuilder->codeAppendf("\t\tfloat r = "
                             "fract(sin(dot(%s.xy ,vec2(12.9898,78.233))) * 43758.5453);\n",
                             fragBuilder->fragmentPosition());
    fragBuilder->codeAppendf("\t\t%s = (1.0/255.0) * vec4(r, r, r, r) + %s;\n",
                             args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str());
}
示例#17
0
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     const GrDitherEffect& _outer = args.fFp.cast<GrDitherEffect>();
     (void)_outer;
     fragBuilder->codeAppendf(
             "float value;\nfloat range;\n@switch (%d) {\n    case 0:\n        range = "
             "0.0039215686274509803;\n        break;\n    case 1:\n        range = "
             "0.015873015873015872;\n        break;\n    default:\n        range = "
             "0.0083333333333333332;\n        break;\n}\n@if (sk_Caps.integerSupport) {\n    "
             "int x = int(sk_FragCoord.x);\n    int y = int(sk_FragCoord.y);\n    uint m = "
             "uint((((((y & 1) << 5 | (x & 1) << 4) | (y & 2) << 2) | (x & 2) << 1) | (y & 4) "
             ">> 1) | (x & 4) >> 2);\n    value = float(m) / 64.0 - 0.4921875;\n} else {\n    "
             "value = fract(sin(dot(sk_FragCoord.xy, vec2(12.989800000000001, "
             "78.233000000000004))) * 43758.545299999998) - 0.5;\n}\n%s = vec4(clamp(%s.xyz + "
             "value * range, 0.0, %s.w), %s.w);\n",
             _outer.rangeType(), args.fOutputColor,
             args.fInputColor ? args.fInputColor : "vec4(1)",
             args.fInputColor ? args.fInputColor : "vec4(1)",
             args.fInputColor ? args.fInputColor : "vec4(1)");
 }
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     const GrEllipseEffect& _outer = args.fFp.cast<GrEllipseEffect>();
     (void)_outer;
     auto edgeType = _outer.edgeType();
     (void)edgeType;
     auto center = _outer.center();
     (void)center;
     auto radii = _outer.radii();
     (void)radii;
     prevRadii = float2(-1.0);
     useScale = !sk_Caps.floatIs32Bits;
     fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat4_GrSLType,
                                                    kDefault_GrSLPrecision, "ellipse");
     if (useScale) {
         fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat2_GrSLType,
                                                      kDefault_GrSLPrecision, "scale");
     }
     fragBuilder->codeAppendf(
             "float2 prevCenter;\nfloat2 prevRadii = float2(%f, %f);\nbool useScale = "
             "%s;\nfloat2 d = sk_FragCoord.xy - %s.xy;\n@if (useScale) {\n    d *= "
             "%s.y;\n}\nfloat2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat "
             "grad_dot = 4.0 * dot(Z, Z);\ngrad_dot = max(grad_dot, 0.0001);\nfloat approx_dist "
             "= implicit * inversesqrt(grad_dot);\n@if (useScale) {\n    approx_dist *= "
             "%s.x;\n}\nhalf alpha;\n@switch (%d) {\n    case 0:\n        alpha = "
             "half(approx_dist > 0.0 ? 0.0 : 1.0);\n        break;\n    case 1:\n      ",
             prevRadii.fX, prevRadii.fY, (useScale ? "true" : "false"),
             args.fUniformHandler->getUniformCStr(fEllipseVar),
             fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "float2(0)",
             args.fUniformHandler->getUniformCStr(fEllipseVar),
             fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "float2(0)",
             (int)_outer.edgeType());
     fragBuilder->codeAppendf(
             "  alpha = half(clamp(0.5 - approx_dist, 0.0, 1.0));\n        break;\n    case "
             "2:\n        alpha = half(approx_dist > 0.0 ? 1.0 : 0.0);\n        break;\n    "
             "case 3:\n        alpha = half(clamp(0.5 + approx_dist, 0.0, 1.0));\n        "
             "break;\n    default:\n        discard;\n}\n%s = %s * alpha;\n",
             args.fOutputColor, args.fInputColor ? args.fInputColor : "half4(1)");
 }
示例#19
0
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     const GrAARectEffect& _outer = args.fFp.cast<GrAARectEffect>();
     (void)_outer;
     auto edgeType = _outer.edgeType();
     (void)edgeType;
     auto rect = _outer.rect();
     (void)rect;
     prevRect = float4(-1.0);
     fRectUniformVar = args.fUniformHandler->addUniform(
             kFragment_GrShaderFlag, kFloat4_GrSLType, kDefault_GrSLPrecision, "rectUniform");
     fragBuilder->codeAppendf(
             "float4 prevRect = float4(%f, %f, %f, %f);\nhalf alpha;\n@switch (%d) {\n    case "
             "0:\n    case 2:\n        alpha = half(all(greaterThan(float4(sk_FragCoord.xy, "
             "%s.zw), float4(%s.xy, sk_FragCoord.xy))) ? 1 : 0);\n        break;\n    "
             "default:\n        half xSub, ySub;\n        xSub = half(min(sk_FragCoord.x - "
             "%s.x, 0.0));\n        xSub += half(min(%s.z - sk_FragCoord.x, 0.0));\n        "
             "ySub = half(min(sk_FragCoord.y - %s.y, 0.0));\n        ySub += half(min(%s.w - "
             "sk_FragCoord.y, 0.0));\n        alpha = half((1",
             prevRect.left(),
             prevRect.top(),
             prevRect.right(),
             prevRect.bottom(),
             (int)_outer.edgeType(),
             args.fUniformHandler->getUniformCStr(fRectUniformVar),
             args.fUniformHandler->getUniformCStr(fRectUniformVar),
             args.fUniformHandler->getUniformCStr(fRectUniformVar),
             args.fUniformHandler->getUniformCStr(fRectUniformVar),
             args.fUniformHandler->getUniformCStr(fRectUniformVar),
             args.fUniformHandler->getUniformCStr(fRectUniformVar));
     fragBuilder->codeAppendf(
             ".0 + max(float(xSub), -1.0)) * (1.0 + max(float(ySub), -1.0)));\n}\n@if (%d == 2 "
             "|| %d == 3) {\n    alpha = half(1.0 - float(alpha));\n}\n%s = %s * alpha;\n",
             (int)_outer.edgeType(),
             (int)_outer.edgeType(),
             args.fOutputColor,
             args.fInputColor);
 }
void GrGLCircleBlurFragmentProcessor::emitCode(EmitArgs& args) {

    const char *dataName;

    // The data is formatted as:
    // x,y  - the center of the circle
    // z    - the distance at which the intensity starts falling off (e.g., the start of the table)
    // w    - the inverse of the profile texture size
    fDataUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
                                                    kVec4f_GrSLType,
                                                    kDefault_GrSLPrecision,
                                                    "data",
                                                    &dataName);

    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    const char *fragmentPos = fragBuilder->fragmentPosition();

    if (args.fInputColor) {
        fragBuilder->codeAppendf("vec4 src=%s;", args.fInputColor);
    } else {
        fragBuilder->codeAppendf("vec4 src=vec4(1);");
    }

    // We just want to compute "length(vec) - %s.z + 0.5) * %s.w" but need to rearrange
    // for precision
    fragBuilder->codeAppendf("vec2 vec = vec2( (%s.x - %s.x) * %s.w , (%s.y - %s.y) * %s.w );",
                             fragmentPos, dataName, dataName,
                             fragmentPos, dataName, dataName);
    fragBuilder->codeAppendf("float dist = length(vec) + ( 0.5 - %s.z ) * %s.w;",
                             dataName, dataName);

    fragBuilder->codeAppendf("float intensity = ");
    fragBuilder->appendTextureLookup(args.fTexSamplers[0], "vec2(dist, 0.5)");
    fragBuilder->codeAppend(".a;");

    fragBuilder->codeAppendf("%s = src * intensity;\n", args.fOutputColor );
}
示例#21
0
 void emitCode(EmitArgs& args) override {
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     const GrMagnifierEffect& _outer = args.fFp.cast<GrMagnifierEffect>();
     (void)_outer;
     auto bounds = _outer.bounds();
     (void)bounds;
     auto srcRect = _outer.srcRect();
     (void)srcRect;
     auto xInvZoom = _outer.xInvZoom();
     (void)xInvZoom;
     auto yInvZoom = _outer.yInvZoom();
     (void)yInvZoom;
     auto xInvInset = _outer.xInvInset();
     (void)xInvInset;
     auto yInvInset = _outer.yInvInset();
     (void)yInvInset;
     fBoundsUniformVar = args.fUniformHandler->addUniform(
             kFragment_GrShaderFlag, kFloat4_GrSLType, kDefault_GrSLPrecision, "boundsUniform");
     fXInvZoomVar = args.fUniformHandler->addUniform(
             kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "xInvZoom");
     fYInvZoomVar = args.fUniformHandler->addUniform(
             kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "yInvZoom");
     fXInvInsetVar = args.fUniformHandler->addUniform(
             kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "xInvInset");
     fYInvInsetVar = args.fUniformHandler->addUniform(
             kFragment_GrShaderFlag, kFloat_GrSLType, kDefault_GrSLPrecision, "yInvInset");
     fOffsetVar = args.fUniformHandler->addUniform(
             kFragment_GrShaderFlag, kHalf2_GrSLType, kDefault_GrSLPrecision, "offset");
     SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
     fragBuilder->codeAppendf(
             "float2 coord = %s;\nfloat2 zoom_coord = float2(%s + half2(coord * "
             "float2(half2(half(%s), half(%s)))));\nfloat2 delta = (coord - %s.xy) * "
             "%s.zw;\ndelta = min(delta, float2(half2(1.0, 1.0) - half2(delta)));\ndelta *= "
             "float2(half2(half(%s), half(%s)));\nhalf weight = 0.0;\nif (delta.x < 2.0 && "
             "delta.y < 2.0) {\n    delta = float2(half2(2.0, 2.0) - half2(delta));\n    half "
             "dist = half(length(delta));\n    dist = half(max(2.0 - float(dist), 0.0));\n    "
             "weight = half(min(float(dist * dist), 1.0));\n} else {\n    ",
             sk_TransformedCoords2D_0.c_str(),
             args.fUniformHandler->getUniformCStr(fOffsetVar),
             args.fUniformHandler->getUniformCStr(fXInvZoomVar),
             args.fUniformHandler->getUniformCStr(fYInvZoomVar),
             args.fUniformHandler->getUniformCStr(fBoundsUniformVar),
             args.fUniformHandler->getUniformCStr(fBoundsUniformVar),
             args.fUniformHandler->getUniformCStr(fXInvInsetVar),
             args.fUniformHandler->getUniformCStr(fYInvInsetVar));
     fragBuilder->codeAppendf(
             "float2 delta_squared = delta * delta;\n    weight = half(min(min(delta_squared.x, "
             "delta_squared.y), 1.0));\n}\n%s = texture(%s, mix(coord, zoom_coord, "
             "float(weight))).%s;\n",
             args.fOutputColor,
             fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
             fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str());
 }
示例#22
0
    void emitCode(EmitArgs& args) override {
        const TwoPointConicalEffect& effect = args.fFp.cast<TwoPointConicalEffect>();
        GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
        this->emitUniforms(uniformHandler, effect);
        fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
                                               "Conical2FSParams");

        SkString p0; // r0 for radial case, r0^2 for strip case
        p0.appendf("%s", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
        const char* tName = "t"; // the gradient

        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
        const char* p = coords2D.c_str();

        if (effect.getType() == Type::kRadial) {
            char sign = effect.diffRadius() < 0 ? '-' : '+';
            fragBuilder->codeAppendf("half %s = %clength(%s) - %s;", tName, sign, p, p0.c_str());
        } else {
            // output will default to transparent black (we simply won't write anything
            // else to it if invalid, instead of discarding or returning prematurely)
            fragBuilder->codeAppendf("%s = half4(0.0,0.0,0.0,0.0);", args.fOutputColor);
            fragBuilder->codeAppendf("half temp = %s - %s.y * %s.y;", p0.c_str(), p, p);
            fragBuilder->codeAppendf("if (temp >= 0) {");
            fragBuilder->codeAppendf("half %s = %s.x + sqrt(temp);", tName, p);
        }
        this->emitColor(fragBuilder,
                        uniformHandler,
                        args.fShaderCaps,
                        effect,
                        tName,
                        args.fOutputColor,
                        args.fInputColor,
                        args.fTexSamplers);

        if (effect.getType() != Type::kRadial) {
            fragBuilder->codeAppendf("}");
        }
    }
void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
    const GrDisplacementMapEffect& displacementMap = args.fFp.cast<GrDisplacementMapEffect>();
    const GrTextureDomain& domain = displacementMap.domain();

    fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
                                                 kVec2f_GrSLType, kDefault_GrSLPrecision, "Scale");
    const char* scaleUni = args.fUniformHandler->getUniformCStr(fScaleUni);
    const char* dColor = "dColor";
    const char* cCoords = "cCoords";
    const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half float, use
                                   // a number smaller than that to approximate 0, but
                                   // leave room for 32-bit float GPU rounding errors.

    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    fragBuilder->codeAppendf("\t\tvec4 %s = ", dColor);
    fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fCoords[0].c_str(),
                                   args.fCoords[0].getType());
    fragBuilder->codeAppend(";\n");

    // Unpremultiply the displacement
    fragBuilder->codeAppendf(
        "\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
        dColor, dColor, nearZero, dColor, dColor);
    SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 1);
    fragBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.",
                             cCoords, coords2D.c_str(), scaleUni, dColor);

    switch (displacementMap.xChannelSelector()) {
      case SkDisplacementMapEffect::kR_ChannelSelectorType:
        fragBuilder->codeAppend("r");
        break;
      case SkDisplacementMapEffect::kG_ChannelSelectorType:
        fragBuilder->codeAppend("g");
        break;
      case SkDisplacementMapEffect::kB_ChannelSelectorType:
        fragBuilder->codeAppend("b");
        break;
      case SkDisplacementMapEffect::kA_ChannelSelectorType:
        fragBuilder->codeAppend("a");
        break;
      case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
      default:
        SkDEBUGFAIL("Unknown X channel selector");
    }

    switch (displacementMap.yChannelSelector()) {
      case SkDisplacementMapEffect::kR_ChannelSelectorType:
        fragBuilder->codeAppend("r");
        break;
      case SkDisplacementMapEffect::kG_ChannelSelectorType:
        fragBuilder->codeAppend("g");
        break;
      case SkDisplacementMapEffect::kB_ChannelSelectorType:
        fragBuilder->codeAppend("b");
        break;
      case SkDisplacementMapEffect::kA_ChannelSelectorType:
        fragBuilder->codeAppend("a");
        break;
      case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
      default:
        SkDEBUGFAIL("Unknown Y channel selector");
    }
    fragBuilder->codeAppend("-vec2(0.5));\t\t");

    fGLDomain.sampleTexture(fragBuilder,
                            args.fUniformHandler,
                            args.fGLSLCaps,
                            domain,
                            args.fOutputColor,
                            SkString(cCoords),
                            args.fTexSamplers[1]);
    fragBuilder->codeAppend(";\n");
}
void GrGLMorphologyEffect::emitCode(EmitArgs& args) {
    const GrMorphologyEffect& me = args.fFp.cast<GrMorphologyEffect>();

    GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    fPixelSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                               kFloat_GrSLType, kDefault_GrSLPrecision,
                                               "PixelSize");
    const char* pixelSizeInc = uniformHandler->getUniformCStr(fPixelSizeUni);
    fRangeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                           kVec2f_GrSLType, kDefault_GrSLPrecision,
                                           "Range");
    const char* range = uniformHandler->getUniformCStr(fRangeUni);

    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
    const char* func;
    switch (me.type()) {
        case GrMorphologyEffect::kErode_MorphologyType:
            fragBuilder->codeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", args.fOutputColor);
            func = "min";
            break;
        case GrMorphologyEffect::kDilate_MorphologyType:
            fragBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", args.fOutputColor);
            func = "max";
            break;
        default:
            SkFAIL("Unexpected type");
            func = ""; // suppress warning
            break;
    }

    const char* dir;
    switch (me.direction()) {
        case Gr1DKernelEffect::kX_Direction:
            dir = "x";
            break;
        case Gr1DKernelEffect::kY_Direction:
            dir = "y";
            break;
        default:
            SkFAIL("Unknown filter direction.");
            dir = ""; // suppress warning
    }

    int width = GrMorphologyEffect::WidthFromRadius(me.radius());

    // vec2 coord = coord2D;
    fragBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
    // coord.x -= radius * pixelSize;
    fragBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, me.radius(), pixelSizeInc);
    if (me.useRange()) {
        // highBound = min(highBound, coord.x + (width-1) * pixelSize);
        fragBuilder->codeAppendf("\t\tfloat highBound = min(%s.y, coord.%s + %f * %s);",
                                 range, dir, float(width - 1), pixelSizeInc);
        // coord.x = max(lowBound, coord.x);
        fragBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir);
    }
    fragBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", width);
    fragBuilder->codeAppendf("\t\t\t%s = %s(%s, ", args.fOutputColor, func, args.fOutputColor);
    fragBuilder->appendTextureLookup(args.fTexSamplers[0], "coord");
    fragBuilder->codeAppend(");\n");
    // coord.x += pixelSize;
    fragBuilder->codeAppendf("\t\t\tcoord.%s += %s;\n", dir, pixelSizeInc);
    if (me.useRange()) {
        // coord.x = min(highBound, coord.x);
        fragBuilder->codeAppendf("\t\t\tcoord.%s = min(highBound, coord.%s);", dir, dir);
    }
    fragBuilder->codeAppend("\t\t}\n");
    SkString modulate;
    GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
    fragBuilder->codeAppend(modulate.c_str());
}
示例#25
0
void GrGLPerlinNoise::emitCode(EmitArgs& args) {
    const GrPerlinNoiseEffect& pne = args.fFp.cast<GrPerlinNoiseEffect>();

    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);

    fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                   kVec2f_GrSLType, kDefault_GrSLPrecision,
                                                   "baseFrequency");
    const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);

    const char* stitchDataUni = nullptr;
    if (pne.stitchTiles()) {
        fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
                                                    "stitchData");
        stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
    }

    // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
    const char* chanCoordR  = "0.125";
    const char* chanCoordG  = "0.375";
    const char* chanCoordB  = "0.625";
    const char* chanCoordA  = "0.875";
    const char* chanCoord   = "chanCoord";
    const char* stitchData  = "stitchData";
    const char* ratio       = "ratio";
    const char* noiseVec    = "noiseVec";
    const char* noiseSmooth = "noiseSmooth";
    const char* floorVal    = "floorVal";
    const char* fractVal    = "fractVal";
    const char* uv          = "uv";
    const char* ab          = "ab";
    const char* latticeIdx  = "latticeIdx";
    const char* bcoords     = "bcoords";
    const char* lattice     = "lattice";
    const char* inc8bit     = "0.00390625";  // 1.0 / 256.0
    // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
    // [-1,1] vector and perform a dot product between that vector and the provided vector.
    const char* dotLattice  = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";

    // Add noise function
    static const GrGLSLShaderVar gPerlinNoiseArgs[] =  {
        GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
        GrGLSLShaderVar(noiseVec, kVec2f_GrSLType)
    };

    static const GrGLSLShaderVar gPerlinNoiseStitchArgs[] =  {
        GrGLSLShaderVar(chanCoord, kFloat_GrSLType),
        GrGLSLShaderVar(noiseVec, kVec2f_GrSLType),
        GrGLSLShaderVar(stitchData, kVec2f_GrSLType)
    };

    SkString noiseCode;

    noiseCode.appendf("\tvec4 %s;\n", floorVal);
    noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
    noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
    noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);

    // smooth curve : t * t * (3 - 2 * t)
    noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
        noiseSmooth, fractVal, fractVal, fractVal);

    // Adjust frequencies if we're stitching tiles
    if (pne.stitchTiles()) {
        noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
                          floorVal, stitchData, floorVal, stitchData);
        noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
                          floorVal, stitchData, floorVal, stitchData);
        noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
                          floorVal, stitchData, floorVal, stitchData);
        noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
                          floorVal, stitchData, floorVal, stitchData);
    }

    // Get texture coordinates and normalize
    noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
                      floorVal, floorVal);

    // Get permutation for x
    {
        SkString xCoords("");
        xCoords.appendf("vec2(%s.x, 0.5)", floorVal);

        noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
        fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
                                         kVec2f_GrSLType);
        noiseCode.append(".r;");
    }

    // Get permutation for x + 1
    {
        SkString xCoords("");
        xCoords.appendf("vec2(%s.z, 0.5)", floorVal);

        noiseCode.appendf("\n\t%s.y = ", latticeIdx);
        fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
                                         kVec2f_GrSLType);
        noiseCode.append(".r;");
    }

#if defined(SK_BUILD_FOR_ANDROID)
    // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
    // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
    // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
    // (or 0.484368 here). The following rounding operation prevents these precision issues from
    // affecting the result of the noise by making sure that we only have multiples of 1/255.
    // (Note that 1/255 is about 0.003921569, which is the value used here).
    noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
                      latticeIdx, latticeIdx);
#endif

    // Get (x,y) coordinates with the permutated x
    noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);

    noiseCode.appendf("\n\n\tvec2 %s;", uv);
    // Compute u, at offset (0,0)
    {
        SkString latticeCoords("");
        latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
        noiseCode.appendf("\n\tvec4 %s = ", lattice);
        fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
                                         kVec2f_GrSLType);
        noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
        noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
    }

    noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
    // Compute v, at offset (-1,0)
    {
        SkString latticeCoords("");
        latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
        noiseCode.append("\n\tlattice = ");
        fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
                                         kVec2f_GrSLType);
        noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
        noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
    }

    // Compute 'a' as a linear interpolation of 'u' and 'v'
    noiseCode.appendf("\n\tvec2 %s;", ab);
    noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);

    noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
    // Compute v, at offset (-1,-1)
    {
        SkString latticeCoords("");
        latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
        noiseCode.append("\n\tlattice = ");
        fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
                                         kVec2f_GrSLType);
        noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
        noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
    }

    noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
    // Compute u, at offset (0,-1)
    {
        SkString latticeCoords("");
        latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
        noiseCode.append("\n\tlattice = ");
        fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
                                         kVec2f_GrSLType);
        noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
        noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
    }

    // Compute 'b' as a linear interpolation of 'u' and 'v'
    noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
    // Compute the noise as a linear interpolation of 'a' and 'b'
    noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);

    SkString noiseFuncName;
    if (pne.stitchTiles()) {
        fragBuilder->emitFunction(kFloat_GrSLType,
                                  "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
                                  gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
    } else {
        fragBuilder->emitFunction(kFloat_GrSLType,
                                  "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
                                  gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
    }

    // There are rounding errors if the floor operation is not performed here
    fragBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
                             noiseVec, vCoords.c_str(), baseFrequencyUni);

    // Clear the color accumulator
    fragBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);

    if (pne.stitchTiles()) {
        // Set up TurbulenceInitial stitch values.
        fragBuilder->codeAppendf("vec2 %s = %s;", stitchData, stitchDataUni);
    }

    fragBuilder->codeAppendf("float %s = 1.0;", ratio);

    // Loop over all octaves
    fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());

    fragBuilder->codeAppendf("%s += ", args.fOutputColor);
    if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) {
        fragBuilder->codeAppend("abs(");
    }
    if (pne.stitchTiles()) {
        fragBuilder->codeAppendf(
            "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
                 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
            noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
            noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
            noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
            noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
    } else {
        fragBuilder->codeAppendf(
            "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
                 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
            noiseFuncName.c_str(), chanCoordR, noiseVec,
            noiseFuncName.c_str(), chanCoordG, noiseVec,
            noiseFuncName.c_str(), chanCoordB, noiseVec,
            noiseFuncName.c_str(), chanCoordA, noiseVec);
    }
    if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) {
        fragBuilder->codeAppendf(")"); // end of "abs("
    }
    fragBuilder->codeAppendf(" * %s;", ratio);

    fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
    fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);

    if (pne.stitchTiles()) {
        fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
    }
    fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves

    if (pne.type() == SkPerlinNoiseShader::kFractalNoise_Type) {
        // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
        // by fractalNoise and (turbulenceFunctionResult) by turbulence.
        fragBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
                                 args.fOutputColor,args.fOutputColor);
    }

    // Clamp values
    fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);

    // Pre-multiply the result
    fragBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
                             args.fOutputColor, args.fOutputColor,
                             args.fOutputColor, args.fOutputColor);
}
void GrGLAlphaThresholdFragmentProcessor::emitCode(EmitArgs& args) {
    GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    fInnerThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                    kFloat_GrSLType, kDefault_GrSLPrecision,
                                                    "inner_threshold");
    fOuterThresholdVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                    kFloat_GrSLType, kDefault_GrSLPrecision,
                                                    "outer_threshold");

    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
    SkString maskCoords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 1);

    fragBuilder->codeAppendf("vec2 coord = %s;", coords2D.c_str());
    fragBuilder->codeAppendf("vec2 mask_coord = %s;", maskCoords2D.c_str());
    fragBuilder->codeAppend("vec4 input_color = ");
    fragBuilder->appendTextureLookup(args.fTexSamplers[0], "coord");
    fragBuilder->codeAppend(";");
    fragBuilder->codeAppend("vec4 mask_color = ");
    fragBuilder->appendTextureLookup(args.fTexSamplers[1], "mask_coord");
    fragBuilder->codeAppend(";");

    fragBuilder->codeAppendf("float inner_thresh = %s;",
                             uniformHandler->getUniformCStr(fInnerThresholdVar));
    fragBuilder->codeAppendf("float outer_thresh = %s;",
                             uniformHandler->getUniformCStr(fOuterThresholdVar));
    fragBuilder->codeAppend("float mask = mask_color.a;");

    fragBuilder->codeAppend("vec4 color = input_color;");
    fragBuilder->codeAppend("if (mask < 0.5) {"
                            "if (color.a > outer_thresh) {"
                            "float scale = outer_thresh / color.a;"
                            "color.rgb *= scale;"
                            "color.a = outer_thresh;"
                            "}"
                            "} else if (color.a < inner_thresh) {"
                            "float scale = inner_thresh / max(0.001, color.a);"
                            "color.rgb *= scale;"
                            "color.a = inner_thresh;"
                            "}");

    fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
                             (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr4("color")).c_str());
}
        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
            const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>();
            GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
            GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
            GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
            GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;

            // emit attributes
            varyingHandler->emitAttributes(gp);

            // Setup pass through color
            if (gp.hasVertexColor()) {
                GrGLSLVarying varying(kHalf4_GrSLType);
                varyingHandler->addVarying("color", &varying);

                // There are several optional steps to process the color. Start with the attribute:
                vertBuilder->codeAppendf("half4 color = %s;", gp.inColor()->fName);

                // Linearize
                if (gp.linearizeColor()) {
                    SkString srgbFuncName;
                    static const GrShaderVar gSrgbArgs[] = {
                        GrShaderVar("x", kHalf_GrSLType),
                    };
                    vertBuilder->emitFunction(kHalf_GrSLType,
                                              "srgb_to_linear",
                                              SK_ARRAY_COUNT(gSrgbArgs),
                                              gSrgbArgs,
                                              "return (x <= 0.04045) ? (x / 12.92) "
                                              ": pow((x + 0.055) / 1.055, 2.4);",
                                              &srgbFuncName);
                    vertBuilder->codeAppendf("color = half4(%s(%s.r), %s(%s.g), %s(%s.b), %s.a);",
                                             srgbFuncName.c_str(), gp.inColor()->fName,
                                             srgbFuncName.c_str(), gp.inColor()->fName,
                                             srgbFuncName.c_str(), gp.inColor()->fName,
                                             gp.inColor()->fName);
                }

                // For SkColor, do a red/blue swap and premul
                if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) {
                    vertBuilder->codeAppend("color = half4(color.a * color.bgr, color.a);");
                }

                // Do color-correction to destination gamut
                if (gp.linearizeColor()) {
                    fColorSpaceHelper.emitCode(uniformHandler, gp.fColorSpaceXform.get(),
                                               kVertex_GrShaderFlag);
                    if (fColorSpaceHelper.isValid()) {
                        SkString xformedColor;
                        vertBuilder->appendColorGamutXform(&xformedColor, "color",
                                                           &fColorSpaceHelper);
                        vertBuilder->codeAppendf("color = %s;", xformedColor.c_str());
                    }
                }
                vertBuilder->codeAppendf("%s = color;\n", varying.vsOut());
                fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
            } else {
                this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
                                        &fColorUniform);
            }

            // Setup position
            this->writeOutputPosition(vertBuilder,
                                      uniformHandler,
                                      gpArgs,
                                      gp.inPosition()->fName,
                                      gp.viewMatrix(),
                                      &fViewMatrixUniform);

            if (gp.hasExplicitLocalCoords()) {
                // emit transforms with explicit local coords
                this->emitTransforms(vertBuilder,
                                     varyingHandler,
                                     uniformHandler,
                                     gp.inLocalCoords()->asShaderVar(),
                                     gp.localMatrix(),
                                     args.fFPCoordTransformHandler);
            } else {
                // emit transforms with position
                this->emitTransforms(vertBuilder,
                                     varyingHandler,
                                     uniformHandler,
                                     gp.inPosition()->asShaderVar(),
                                     gp.localMatrix(),
                                     args.fFPCoordTransformHandler);
            }

            // Setup coverage as pass through
            if (gp.hasVertexCoverage()) {
                fragBuilder->codeAppendf("half alpha = 1.0;");
                varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha");
                fragBuilder->codeAppendf("%s = half4(alpha);", args.fOutputCoverage);
            } else if (gp.coverage() == 0xff) {
                fragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
            } else {
                const char* fragCoverage;
                fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                              kHalf_GrSLType,
                                                              "Coverage",
                                                              &fragCoverage);
                fragBuilder->codeAppendf("%s = half4(%s);", args.fOutputCoverage, fragCoverage);
            }
        }
示例#28
0
    void emitCode(EmitArgs& args) override {
        const TwoPointConicalEffect& effect = args.fFp.cast<TwoPointConicalEffect>();
        GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
        this->emitUniforms(uniformHandler, effect);
        fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
                                               "Conical2FSParams");

        SkString p0; // 1 / r1
        SkString p1; // f = focalX = r0 / (r0 - r1)
        p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
        p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
        const char* tName = "t"; // the gradient

        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
        const char* p = coords2D.c_str();

        if (effect.isFocalOnCircle()) {
            fragBuilder->codeAppendf("half x_t = dot(%s, %s) / %s.x;", p, p, p);
        } else if (effect.isWellBehaved()) {
            fragBuilder->codeAppendf("half x_t = length(%s) - %s.x * %s;", p, p, p0.c_str());
        } else {
            char sign = (effect.isSwapped() || !effect.isRadiusIncreasing()) ? '-' : ' ';
            fragBuilder->codeAppendf("half temp = %s.x * %s.x - %s.y * %s.y;", p, p, p, p);
            // Initialize x_t to illegal state
            fragBuilder->codeAppendf("half x_t = -1;");

            // Only do sqrt if temp >= 0; this is significantly slower than checking temp >= 0 in
            // the if statement that checks r(t) >= 0. But GPU may break if we sqrt a negative
            // float. (Although I havevn't observed that on any devices so far, and the old approach
            // also does sqrt negative value without a check.) If the performance is really
            // critical, maybe we should just compute the area where temp and x_t are always
            // valid and drop all these ifs.
            fragBuilder->codeAppendf("if (temp >= 0) {");
            fragBuilder->codeAppendf("x_t = (%csqrt(temp) - %s.x * %s);", sign, p, p0.c_str());
            fragBuilder->codeAppendf("}");
        }

        // empty sign is positive
        char sign = effect.isRadiusIncreasing() ? ' ' : '-';

        // "+ 0" is much faster than "+ p1" so we specialize the natively focal case where p1 = 0.
        fragBuilder->codeAppendf("half %s = %cx_t + %s;", tName, sign,
                effect.isNativelyFocal() ? "0" : p1.c_str());

        if (!effect.isWellBehaved()) {
            // output will default to transparent black (we simply won't write anything
            // else to it if invalid, instead of discarding or returning prematurely)
            fragBuilder->codeAppendf("%s = half4(0.0,0.0,0.0,0.0);", args.fOutputColor);
            fragBuilder->codeAppendf("if (x_t > 0.0) {");
        }

        if (effect.isSwapped()) {
            fragBuilder->codeAppendf("%s = 1 - %s;", tName, tName);
        }

        this->emitColor(fragBuilder,
                        uniformHandler,
                        args.fShaderCaps,
                        effect,
                        tName,
                        args.fOutputColor,
                        args.fInputColor,
                        args.fTexSamplers);
        if (!effect.isWellBehaved()) {
            fragBuilder->codeAppend("};");
        }
    }
void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inputColor,
                                                const char* outputColor, EmitArgs& args) {
    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;

    fragBuilder->onBeforeChildProcEmitCode();  // call first so mangleString is updated

    const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);

    /*
     * We now want to find the subset of coords and samplers that belong to the child and its
     * descendants and put that into childCoords and childSamplers. To do so, we'll do a forwards
     * linear search.
     *
     * Explanation:
     * Each GrFragmentProcessor has a copy of all the transforms and textures of itself and
     * all procs in its subtree. For example, suppose we have frag proc A, who has two children B
     * and D. B has a child C, and D has two children E and F. Each frag proc's transforms array
     * contains its own transforms, followed by the transforms of all its descendants (i.e. preorder
     * traversal). Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms respectively.
     *
     *                                   (A)
     *                        [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2]
     *                                  /    \
     *                                /        \
     *                            (B)           (D)
     *                        [b1,b2,c1]   [d1,e1,e2,e3,f1,f2]
     *                          /             /    \
     *                        /             /        \
     *                      (C)          (E)          (F)
     *                     [c1]      [e1,e2,e3]      [f1,f2]
     *
     * So if we're inside proc A's emitCode, and A is about to call emitCode on proc D, we want the
     * EmitArgs that's passed onto D to only contain its and its descendants' coords. The
     * EmitArgs given to A would contain the transforms [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2], and we want
     * to extract the subset [d1,e1,e2,e3,f1,f2] to pass on to D. We can do this with a linear
     * search since we know that A has 1 transform (using A.numTransformsExclChildren()), and B's
     * subtree has 3 transforms (using B.numTransforms()), so we know the start of D's transforms is
     * 4 after the start of A's transforms.
     * Textures work the same way as transforms.
     */
    int firstCoordAt = args.fFp.numTransformsExclChildren();
    int firstSamplerAt = args.fFp.numTexturesExclChildren();
    for (int i = 0; i < childIndex; ++i) {
        firstCoordAt += args.fFp.childProcessor(i).numTransforms();
        firstSamplerAt += args.fFp.childProcessor(i).numTextures();
    }
    GrGLSLTransformedCoordsArray childCoords;
    TextureSamplerArray childSamplers;
    if (childProc.numTransforms() > 0) {
        childCoords.push_back_n(childProc.numTransforms(), &args.fCoords[firstCoordAt]);
    }
    if (childProc.numTextures() > 0) {
        childSamplers.push_back_n(childProc.numTextures(), &args.fSamplers[firstSamplerAt]);
    }

    // emit the code for the child in its own scope
    fragBuilder->codeAppend("{\n");
    fragBuilder->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex,
                             fragBuilder->getMangleString().c_str(), childProc.name());
    EmitArgs childArgs(fragBuilder,
                       args.fUniformHandler,
                       args.fGLSLCaps,
                       childProc,
                       outputColor,
                       inputColor,
                       childCoords,
                       childSamplers);
    this->childProcessor(childIndex)->emitCode(childArgs);
    fragBuilder->codeAppend("}\n");

    fragBuilder->onAfterChildProcEmitCode();
}
示例#30
0
void GrColorCubeEffect::GLSLProcessor::emitCode(EmitArgs& args) {
    if (nullptr == args.fInputColor) {
        args.fInputColor = "vec4(1)";
    }

    GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    fColorCubeSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                   kFloat_GrSLType, kDefault_GrSLPrecision,
                                                   "Size");
    const char* colorCubeSizeUni = uniformHandler->getUniformCStr(fColorCubeSizeUni);
    fColorCubeInvSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                      kFloat_GrSLType, kDefault_GrSLPrecision,
                                                      "InvSize");
    const char* colorCubeInvSizeUni = uniformHandler->getUniformCStr(fColorCubeInvSizeUni);

    const char* nonZeroAlpha = "nonZeroAlpha";
    const char* unPMColor = "unPMColor";
    const char* cubeIdx = "cubeIdx";
    const char* cCoords1 = "cCoords1";
    const char* cCoords2 = "cCoords2";

    // Note: if implemented using texture3D in OpenGL ES older than OpenGL ES 3.0,
    //       the shader might need "#extension GL_OES_texture_3D : enable".

    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;

    // Unpremultiply color
    fragBuilder->codeAppendf("\tfloat %s = max(%s.a, 0.00001);\n", nonZeroAlpha, args.fInputColor);
    fragBuilder->codeAppendf("\tvec4 %s = vec4(%s.rgb / %s, %s);\n",
                             unPMColor, args.fInputColor, nonZeroAlpha, nonZeroAlpha);

    // Fit input color into the cube.
    fragBuilder->codeAppendf(
        "vec3 %s = vec3(%s.rg * vec2((%s - 1.0) * %s) + vec2(0.5 * %s), %s.b * (%s - 1.0));\n",
        cubeIdx, unPMColor, colorCubeSizeUni, colorCubeInvSizeUni, colorCubeInvSizeUni,
        unPMColor, colorCubeSizeUni);

    // Compute y coord for for texture fetches.
    fragBuilder->codeAppendf("vec2 %s = vec2(%s.r, (floor(%s.b) + %s.g) * %s);\n",
                             cCoords1, cubeIdx, cubeIdx, cubeIdx, colorCubeInvSizeUni);
    fragBuilder->codeAppendf("vec2 %s = vec2(%s.r, (ceil(%s.b) + %s.g) * %s);\n",
                             cCoords2, cubeIdx, cubeIdx, cubeIdx, colorCubeInvSizeUni);

    // Apply the cube.
    fragBuilder->codeAppendf("%s = vec4(mix(", args.fOutputColor);
    fragBuilder->appendTextureLookup(args.fSamplers[0], cCoords1);
    fragBuilder->codeAppend(".bgr, ");
    fragBuilder->appendTextureLookup(args.fSamplers[0], cCoords2);

    // Premultiply color by alpha. Note that the input alpha is not modified by this shader.
    fragBuilder->codeAppendf(".bgr, fract(%s.b)) * vec3(%s), %s.a);\n",
                             cubeIdx, nonZeroAlpha, args.fInputColor);
}