virtual void emitCode(GrGLFPBuilder* builder,
                          const GrFragmentProcessor&,
                          const char* outputColor,
                          const char* inputColor,
                          const TransformedCoordsArray& coords,
                          const TextureSamplerArray& samplers) override {
        // Using highp for GLES here in order to avoid some precision issues on specific GPUs.
        GrGLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, kHigh_GrSLPrecision);
        SkString tmpDecl;
        tmpVar.appendDecl(builder->ctxInfo(), &tmpDecl);

        GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();

        fsBuilder->codeAppendf("%s;", tmpDecl.c_str());

        fsBuilder->codeAppendf("%s = ", tmpVar.c_str());
        fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
        fsBuilder->codeAppend(";");

        if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
            SkASSERT(fSwapRedAndBlue);
            fsBuilder->codeAppendf("%s = %s.bgra;", outputColor, tmpVar.c_str());
        } else {
            const char* swiz = fSwapRedAndBlue ? "bgr" : "rgb";
            switch (fPMConversion) {
                case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion:
                    fsBuilder->codeAppendf(
                        "%s = vec4(ceil(%s.%s * %s.a * 255.0) / 255.0, %s.a);",
                        tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
                    break;
                case GrConfigConversionEffect::kMulByAlpha_RoundDown_PMConversion:
                    // Add a compensation(0.001) here to avoid the side effect of the floor operation.
                    // In Intel GPUs, the integer value converted from floor(%s.r * 255.0) / 255.0
                    // is less than the integer value converted from  %s.r by 1 when the %s.r is
                    // converted from the integer value 2^n, such as 1, 2, 4, 8, etc.
                    fsBuilder->codeAppendf(
                        "%s = vec4(floor(%s.%s * %s.a * 255.0 + 0.001) / 255.0, %s.a);",
                        tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
                    break;
                case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion:
                    fsBuilder->codeAppendf(
                        "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.%s / %s.a * 255.0) / 255.0, %s.a);",
                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
                    break;
                case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion:
                    fsBuilder->codeAppendf(
                        "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.%s / %s.a * 255.0) / 255.0, %s.a);",
                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
                    break;
                default:
                    SkFAIL("Unknown conversion op.");
                    break;
            }
            fsBuilder->codeAppendf("%s = %s;", outputColor, tmpVar.c_str());
        }
        SkString modulate;
        GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
        fsBuilder->codeAppend(modulate.c_str());
    }
Ejemplo n.º 2
0
void GrGLConvolutionEffect::emitCode(EmitArgs& args) {
    const GrConvolutionEffect& ce = args.fFp.cast<GrConvolutionEffect>();

    GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    fImageIncrementUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility,
                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
                                                    "ImageIncrement");
    if (ce.useBounds()) {
        fBoundsUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility,
                                                kVec2f_GrSLType, kDefault_GrSLPrecision,
                                                "Bounds");
    }

    int width = Gr1DKernelEffect::WidthFromRadius(ce.radius());

    fKernelUni = uniformHandler->addUniformArray(GrGLSLUniformHandler::kFragment_Visibility,
                                                 kFloat_GrSLType, kDefault_GrSLPrecision,
                                                 "Kernel", width);

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

    fragBuilder->codeAppendf("%s = vec4(0, 0, 0, 0);", args.fOutputColor);

    const GrGLSLShaderVar& kernel = uniformHandler->getUniformVariable(fKernelUni);
    const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);

    fragBuilder->codeAppendf("vec2 coord = %s - %d.0 * %s;", coords2D.c_str(), ce.radius(), imgInc);

    // Manually unroll loop because some drivers don't; yields 20-30% speedup.
    for (int i = 0; i < width; i++) {
        SkString index;
        SkString kernelIndex;
        index.appendS32(i);
        kernel.appendArrayAccess(index.c_str(), &kernelIndex);

        if (ce.useBounds()) {
            // We used to compute a bool indicating whether we're in bounds or not, cast it to a
            // float, and then mul weight*texture_sample by the float. However, the Adreno 430 seems
            // to have a bug that caused corruption.
            const char* bounds = uniformHandler->getUniformCStr(fBoundsUni);
            const char* component = ce.direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x";
            fragBuilder->codeAppendf("if (coord.%s >= %s.x && coord.%s <= %s.y) {",
                                     component, bounds, component, bounds);
        }
        fragBuilder->codeAppendf("\t\t%s += ", args.fOutputColor);
        fragBuilder->appendTextureLookup(args.fSamplers[0], "coord");
        fragBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str());
        if (ce.useBounds()) {
            fragBuilder->codeAppend("}");
        }
        fragBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc);
    }

    SkString modulate;
    GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
    fragBuilder->codeAppend(modulate.c_str());
}
void GrGLMagnifierEffect::emitCode(GrGLFPBuilder* builder,
                                   const GrFragmentProcessor&,
                                   const char* outputColor,
                                   const char* inputColor,
                                   const TransformedCoordsArray& coords,
                                   const TextureSamplerArray& samplers) {
    fOffsetVar = builder->addUniform(
        GrGLProgramBuilder::kFragment_Visibility |
        GrGLProgramBuilder::kVertex_Visibility,
        kVec2f_GrSLType, kDefault_GrSLPrecision, "Offset");
    fInvZoomVar = builder->addUniform(
        GrGLProgramBuilder::kFragment_Visibility |
        GrGLProgramBuilder::kVertex_Visibility,
        kVec2f_GrSLType, kDefault_GrSLPrecision, "InvZoom");
    fInvInsetVar = builder->addUniform(
        GrGLProgramBuilder::kFragment_Visibility |
        GrGLProgramBuilder::kVertex_Visibility,
        kVec2f_GrSLType, kDefault_GrSLPrecision, "InvInset");
    fBoundsVar = builder->addUniform(
        GrGLProgramBuilder::kFragment_Visibility |
        GrGLProgramBuilder::kVertex_Visibility,
        kVec4f_GrSLType, kDefault_GrSLPrecision, "Bounds");

    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
    fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
    fsBuilder->codeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n",
                           builder->getUniformCStr(fOffsetVar),
                           coords2D.c_str(),
                           builder->getUniformCStr(fInvZoomVar));
    const char* bounds = builder->getUniformCStr(fBoundsVar);
    fsBuilder->codeAppendf("\t\tvec2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds);
    fsBuilder->codeAppendf("\t\tdelta = min(delta, vec2(1.0, 1.0) - delta);\n");
    fsBuilder->codeAppendf("\t\tdelta = delta * %s;\n", builder->getUniformCStr(fInvInsetVar));

    fsBuilder->codeAppend("\t\tfloat weight = 0.0;\n");
    fsBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n");
    fsBuilder->codeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n");
    fsBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n");
    fsBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n");
    fsBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n");
    fsBuilder->codeAppend("\t\t} else {\n");
    fsBuilder->codeAppend("\t\t\tvec2 delta_squared = delta * delta;\n");
    fsBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n");
    fsBuilder->codeAppend("\t\t}\n");

    fsBuilder->codeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n");
    fsBuilder->codeAppend("\t\tvec4 output_color = ");
    fsBuilder->appendTextureLookup(samplers[0], "mix_coord");
    fsBuilder->codeAppend(";\n");

    fsBuilder->codeAppendf("\t\t%s = output_color;", outputColor);
    SkString modulate;
    GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
    fsBuilder->codeAppend(modulate.c_str());
}
Ejemplo n.º 4
0
void GrGLConvolutionEffect::emitCode(GrGLFPBuilder* builder,
                                     const GrFragmentProcessor&,
                                     const char* outputColor,
                                     const char* inputColor,
                                     const TransformedCoordsArray& coords,
                                     const TextureSamplerArray& samplers) {
    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                             kVec2f_GrSLType, kDefault_GrSLPrecision,
                                             "ImageIncrement");
    if (this->useBounds()) {
        fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                         kVec2f_GrSLType, kDefault_GrSLPrecision,
                                         "Bounds");
    }
    fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
                                          kFloat_GrSLType, kDefault_GrSLPrecision,
                                          "Kernel", this->width());

    GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);

    fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);

    int width = this->width();
    const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni);
    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);

    fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc);

    // Manually unroll loop because some drivers don't; yields 20-30% speedup.
    for (int i = 0; i < width; i++) {
        SkString index;
        SkString kernelIndex;
        index.appendS32(i);
        kernel.appendArrayAccess(index.c_str(), &kernelIndex);
        fsBuilder->codeAppendf("\t\t%s += ", outputColor);
        fsBuilder->appendTextureLookup(samplers[0], "coord");
        if (this->useBounds()) {
            const char* bounds = builder->getUniformCStr(fBoundsUni);
            const char* component = this->direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x";
            fsBuilder->codeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.y)",
                component, bounds, component, bounds);
        }
        fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str());
        fsBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc);
    }

    SkString modulate;
    GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
    fsBuilder->codeAppend(modulate.c_str());
}
Ejemplo n.º 5
0
void GrGLMagnifierEffect::emitCode(EmitArgs& args) {
    GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    fOffsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                            kVec2f_GrSLType, kDefault_GrSLPrecision,
                                            "Offset");
    fInvZoomVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                             kVec2f_GrSLType, kDefault_GrSLPrecision,
                                             "InvZoom");
    fInvInsetVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                              kVec2f_GrSLType, kDefault_GrSLPrecision,
                                              "InvInset");
    fBoundsVar = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                            kVec4f_GrSLType, kDefault_GrSLPrecision,
                                            "Bounds");

    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
    fragBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
    fragBuilder->codeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n",
                             uniformHandler->getUniformCStr(fOffsetVar),
                             coords2D.c_str(),
                             uniformHandler->getUniformCStr(fInvZoomVar));
    const char* bounds = uniformHandler->getUniformCStr(fBoundsVar);
    fragBuilder->codeAppendf("\t\tvec2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds);
    fragBuilder->codeAppendf("\t\tdelta = min(delta, vec2(1.0, 1.0) - delta);\n");
    fragBuilder->codeAppendf("\t\tdelta = delta * %s;\n",
                             uniformHandler->getUniformCStr(fInvInsetVar));

    fragBuilder->codeAppend("\t\tfloat weight = 0.0;\n");
    fragBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n");
    fragBuilder->codeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n");
    fragBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n");
    fragBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n");
    fragBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n");
    fragBuilder->codeAppend("\t\t} else {\n");
    fragBuilder->codeAppend("\t\t\tvec2 delta_squared = delta * delta;\n");
    fragBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n");
    fragBuilder->codeAppend("\t\t}\n");

    fragBuilder->codeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n");
    fragBuilder->codeAppend("\t\tvec4 output_color = ");
    fragBuilder->appendTextureLookup(args.fTexSamplers[0], "mix_coord");
    fragBuilder->codeAppend(";\n");

    fragBuilder->codeAppendf("\t\t%s = output_color;", args.fOutputColor);
    SkString modulate;
    GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
    fragBuilder->codeAppend(modulate.c_str());
}
Ejemplo n.º 6
0
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());
}
Ejemplo n.º 7
0
void GrGLMorphologyEffect::emitCode(GrGLFPBuilder* builder,
                                    const GrFragmentProcessor&,
                                    const char* outputColor,
                                    const char* inputColor,
                                    const TransformedCoordsArray& coords,
                                    const TextureSamplerArray& samplers) {
    fPixelSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                            kFloat_GrSLType, kDefault_GrSLPrecision,
                                            "PixelSize");
    const char* pixelSizeInc = builder->getUniformCStr(fPixelSizeUni);
    fRangeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                            kVec2f_GrSLType, kDefault_GrSLPrecision,
                                            "Range");
    const char* range = builder->getUniformCStr(fRangeUni);

    GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
    const char* func;
    switch (fType) {
        case GrMorphologyEffect::kErode_MorphologyType:
            fsBuilder->codeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", outputColor);
            func = "min";
            break;
        case GrMorphologyEffect::kDilate_MorphologyType:
            fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor);
            func = "max";
            break;
        default:
            SkFAIL("Unexpected type");
            func = ""; // suppress warning
            break;
    }

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

    // vec2 coord = coord2D;
    fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
    // coord.x -= radius * pixelSize;
    fsBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, fRadius, pixelSizeInc);
    if (fUseRange) {
        // highBound = min(highBound, coord.x + (width-1) * pixelSize);
        fsBuilder->codeAppendf("\t\tfloat highBound = min(%s.y, coord.%s + %f * %s);",
                               range, dir, float(width() - 1), pixelSizeInc);
        // coord.x = max(lowBound, coord.x);
        fsBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir);
    }
    fsBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", width());
    fsBuilder->codeAppendf("\t\t\t%s = %s(%s, ", outputColor, func, outputColor);
    fsBuilder->appendTextureLookup(samplers[0], "coord");
    fsBuilder->codeAppend(");\n");
    // coord.x += pixelSize;
    fsBuilder->codeAppendf("\t\t\tcoord.%s += %s;\n", dir, pixelSizeInc);
    if (fUseRange) {
        // coord.x = min(highBound, coord.x);
        fsBuilder->codeAppendf("\t\t\tcoord.%s = min(highBound, coord.%s);", dir, dir);
    }
    fsBuilder->codeAppend("\t\t}\n");
    SkString modulate;
    GrGLSLMulVarBy4f(&modulate, outputColor, inputColor);
    fsBuilder->codeAppend(modulate.c_str());
}
Ejemplo n.º 8
0
    void emitCode(EmitArgs& args) override {
        const GrConfigConversionEffect& cce = args.fFp.cast<GrConfigConversionEffect>();
        const GrSwizzle& swizzle = cce.swizzle();
        GrConfigConversionEffect::PMConversion pmConversion = cce.pmConversion();

        // Using highp for GLES here in order to avoid some precision issues on specific GPUs.
        GrGLSLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, kHigh_GrSLPrecision);
        SkString tmpDecl;
        tmpVar.appendDecl(args.fGLSLCaps, &tmpDecl);

        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;

        fragBuilder->codeAppendf("%s;", tmpDecl.c_str());

        fragBuilder->codeAppendf("%s = ", tmpVar.c_str());
        fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fCoords[0].c_str(),
                                       args.fCoords[0].getType());
        fragBuilder->codeAppend(";");

        if (GrConfigConversionEffect::kNone_PMConversion == pmConversion) {
            SkASSERT(GrSwizzle::RGBA() != swizzle);
            fragBuilder->codeAppendf("%s = %s.%s;", args.fOutputColor, tmpVar.c_str(),
                                     swizzle.c_str());
        } else {
            switch (pmConversion) {
                case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion:
                    fragBuilder->codeAppendf(
                        "%s = vec4(ceil(%s.rgb * %s.a * 255.0) / 255.0, %s.a);",
                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str());
                    break;
                case GrConfigConversionEffect::kMulByAlpha_RoundDown_PMConversion:
                    // Add a compensation(0.001) here to avoid the side effect of the floor operation.
                    // In Intel GPUs, the integer value converted from floor(%s.r * 255.0) / 255.0
                    // is less than the integer value converted from  %s.r by 1 when the %s.r is
                    // converted from the integer value 2^n, such as 1, 2, 4, 8, etc.
                    fragBuilder->codeAppendf(
                        "%s = vec4(floor(%s.rgb * %s.a * 255.0 + 0.001) / 255.0, %s.a);",
                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str());

                    break;
                case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion:
                    fragBuilder->codeAppendf(
                        "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0) / 255.0, %s.a);",
                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(),
                        tmpVar.c_str());
                    break;
                case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion:
                    fragBuilder->codeAppendf(
                        "%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0) / 255.0, %s.a);",
                        tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(),
                        tmpVar.c_str());
                    break;
                default:
                    SkFAIL("Unknown conversion op.");
                    break;
            }
            fragBuilder->codeAppendf("%s = %s.%s;", args.fOutputColor, tmpVar.c_str(),
                                     swizzle.c_str());
        }
        SkString modulate;
        GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
        fragBuilder->codeAppend(modulate.c_str());
    }
Ejemplo n.º 9
0
void GrGLMatrixConvolutionEffect::emitCode(EmitArgs& args) {
    const GrTextureDomain& domain = args.fFp.cast<GrMatrixConvolutionEffect>().domain();
    GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
    fImageIncrementUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility,
                                                    kVec2f_GrSLType, kDefault_GrSLPrecision,
                                                    "ImageIncrement");
    fKernelUni = uniformHandler->addUniformArray(GrGLSLUniformHandler::kFragment_Visibility,
                                                 kFloat_GrSLType, kDefault_GrSLPrecision,
                                                 "Kernel",
                                                 fKernelSize.width() * fKernelSize.height());
    fKernelOffsetUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility,
                                                  kVec2f_GrSLType, kDefault_GrSLPrecision,
                                                  "KernelOffset");
    fGainUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility,
                                          kFloat_GrSLType, kDefault_GrSLPrecision, "Gain");
    fBiasUni = uniformHandler->addUniform(GrGLSLUniformHandler::kFragment_Visibility,
                                          kFloat_GrSLType, kDefault_GrSLPrecision, "Bias");

    const char* kernelOffset = uniformHandler->getUniformCStr(fKernelOffsetUni);
    const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
    const char* kernel = uniformHandler->getUniformCStr(fKernelUni);
    const char* gain = uniformHandler->getUniformCStr(fGainUni);
    const char* bias = uniformHandler->getUniformCStr(fBiasUni);
    int kWidth = fKernelSize.width();
    int kHeight = fKernelSize.height();

    GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
    SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
    fragBuilder->codeAppend("vec4 sum = vec4(0, 0, 0, 0);");
    fragBuilder->codeAppendf("vec2 coord = %s - %s * %s;", coords2D.c_str(), kernelOffset, imgInc);
    fragBuilder->codeAppend("vec4 c;");

    for (int y = 0; y < kHeight; y++) {
        for (int x = 0; x < kWidth; x++) {
            GrGLSLShaderBuilder::ShaderBlock block(fragBuilder);
            fragBuilder->codeAppendf("float k = %s[%d * %d + %d];", kernel, y, kWidth, x);
            SkString coord;
            coord.printf("coord + vec2(%d, %d) * %s", x, y, imgInc);
            fDomain.sampleTexture(fragBuilder,
                                  uniformHandler,
                                  args.fGLSLCaps,
                                  domain,
                                  "c",
                                  coord,
                                  args.fSamplers[0]);
            if (!fConvolveAlpha) {
                fragBuilder->codeAppend("c.rgb /= c.a;");
                fragBuilder->codeAppend("c.rgb = clamp(c.rgb, 0.0, 1.0);");
            }
            fragBuilder->codeAppend("sum += c * k;");
        }
    }
    if (fConvolveAlpha) {
        fragBuilder->codeAppendf("%s = sum * %s + %s;", args.fOutputColor, gain, bias);
        fragBuilder->codeAppendf("%s.rgb = clamp(%s.rgb, 0.0, %s.a);",
                                 args.fOutputColor, args.fOutputColor, args.fOutputColor);
    } else {
        fDomain.sampleTexture(fragBuilder,
                              uniformHandler,
                              args.fGLSLCaps,
                              domain,
                              "c",
                              coords2D,
                              args.fSamplers[0]);
        fragBuilder->codeAppendf("%s.a = c.a;", args.fOutputColor);
        fragBuilder->codeAppendf("%s.rgb = sum.rgb * %s + %s;", args.fOutputColor, gain, bias);
        fragBuilder->codeAppendf("%s.rgb *= %s.a;", args.fOutputColor, args.fOutputColor);
    }

    SkString modulate;
    GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
    fragBuilder->codeAppend(modulate.c_str());
}