| Index: src/gpu/SkGr.cpp
|
| diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
|
| index 09c83b929a8c575b1a2b9e15116c76abc4968c5c..e0892d8ab974e88db4034b429cba09727ab8cb93 100644
|
| --- a/src/gpu/SkGr.cpp
|
| +++ b/src/gpu/SkGr.cpp
|
| @@ -24,8 +24,10 @@
|
| #include "SkTextureCompressor.h"
|
| #include "SkYUVPlanesCache.h"
|
| #include "effects/GrBicubicEffect.h"
|
| +#include "effects/GrConstColorProcessor.h"
|
| #include "effects/GrDitherEffect.h"
|
| #include "effects/GrPorterDuffXferProcessor.h"
|
| +#include "effects/GrXfermodeFragmentProcessor.h"
|
| #include "effects/GrYUVtoRGBEffect.h"
|
|
|
| #ifndef SK_IGNORE_ETC1_SUPPORT
|
| @@ -706,46 +708,132 @@ bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut,
|
| return true;
|
| }
|
|
|
| -///////////////////////////////////////////////////////////////////////////////
|
|
|
| -bool SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor paintColor,
|
| - bool constantColor, GrPaint* grPaint) {
|
| +////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| +static inline bool skpaint_to_grpaint_impl(GrContext* context,
|
| + const SkPaint& skPaint,
|
| + const SkMatrix& viewM,
|
| + const GrFragmentProcessor** shaderProcessor,
|
| + SkXfermode::Mode* primColorMode,
|
| + bool primitiveIsSrc,
|
| + GrPaint* grPaint) {
|
| grPaint->setAntiAlias(skPaint.isAntiAlias());
|
|
|
| - SkXfermode* mode = skPaint.getXfermode();
|
| - GrXPFactory* xpFactory = nullptr;
|
| - if (!SkXfermode::AsXPFactory(mode, &xpFactory)) {
|
| - // Fall back to src-over
|
| - // return false here?
|
| - xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
|
| + // Setup the initial color considering the shader, the SkPaint color, and the presence or not
|
| + // of per-vertex colors.
|
| + SkAutoTUnref<const GrFragmentProcessor> aufp;
|
| + const GrFragmentProcessor* shaderFP = NULL;
|
| + if (shaderProcessor) {
|
| + shaderFP = *shaderProcessor;
|
| + } else if (const SkShader* shader = skPaint.getShader()) {
|
| + aufp.reset(shader->asFragmentProcessor(context, viewM, NULL, skPaint.getFilterQuality(),
|
| + grPaint->getProcessorDataManager()));
|
| + shaderFP = aufp;
|
| + if (!shaderFP) {
|
| + return false;
|
| + }
|
| }
|
| - SkASSERT(xpFactory);
|
| - grPaint->setXPFactory(xpFactory)->unref();
|
|
|
| - //set the color of the paint to the one of the parameter
|
| - grPaint->setColor(paintColor);
|
| + // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is
|
| + // a known constant value. In that case we can simply apply a color filter during this
|
| + // conversion without converting the color filter to a GrFragmentProcessor.
|
| + bool applyColorFilterToPaintColor = false;
|
| + if (shaderFP) {
|
| + if (primColorMode) {
|
| + // There is a blend between the primitive color and the shader color. The shader sees
|
| + // the opaque paint color. The shader's output is blended using the provided mode by
|
| + // the primitive color. The blended color is then modulated by the paint's alpha.
|
| +
|
| + // The geometry processor will insert the primitive color to start the color chain, so
|
| + // the GrPaint color will be ignored.
|
| +
|
| + GrColor shaderInput = SkColorToOpaqueGrColor(skPaint.getColor());
|
| +
|
| + shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput);
|
| + aufp.reset(shaderFP);
|
| +
|
| + if (primitiveIsSrc) {
|
| + shaderFP = GrXfermodeFragmentProcessor::CreateFromDstProcessor(shaderFP,
|
| + *primColorMode);
|
| + } else {
|
| + shaderFP = GrXfermodeFragmentProcessor::CreateFromSrcProcessor(shaderFP,
|
| + *primColorMode);
|
| + }
|
| + aufp.reset(shaderFP);
|
| + // The above may return null if compose results in a pass through of the prim color.
|
| + if (shaderFP) {
|
| + grPaint->addColorFragmentProcessor(shaderFP);
|
| + }
|
| +
|
| + GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
|
| + if (GrColor_WHITE != paintAlpha) {
|
| + grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
|
| + paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
|
| + }
|
| + } else {
|
| + // The shader's FP sees the paint unpremul color
|
| + grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor()));
|
| + grPaint->addColorFragmentProcessor(shaderFP);
|
| + }
|
| + } else {
|
| + if (primColorMode) {
|
| + // There is a blend between the primitive color and the paint color. The blend considers
|
| + // the opaque paint color. The paint's alpha is applied to the post-blended color.
|
| + SkAutoTUnref<const GrFragmentProcessor> processor(
|
| + GrConstColorProcessor::Create(SkColorToOpaqueGrColor(skPaint.getColor()),
|
| + GrConstColorProcessor::kIgnore_InputMode));
|
| + if (primitiveIsSrc) {
|
| + processor.reset(GrXfermodeFragmentProcessor::CreateFromDstProcessor(processor,
|
| + *primColorMode));
|
| + } else {
|
| + processor.reset(GrXfermodeFragmentProcessor::CreateFromSrcProcessor(processor,
|
| + *primColorMode));
|
| +
|
| + }
|
| + if (processor) {
|
| + grPaint->addColorFragmentProcessor(processor);
|
| + }
|
| +
|
| + grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor()) | 0xFF000000);
|
| +
|
| + GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
|
| + grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create(
|
| + paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref();
|
| + } else {
|
| + // No shader, no primitive color.
|
| + grPaint->setColor(SkColorToPremulGrColor(skPaint.getColor()));
|
| + applyColorFilterToPaintColor = true;
|
| + }
|
| + }
|
|
|
| SkColorFilter* colorFilter = skPaint.getColorFilter();
|
| if (colorFilter) {
|
| - // if the source color is a constant then apply the filter here once rather than per pixel
|
| - // in a shader.
|
| - if (constantColor) {
|
| - SkColor filtered = colorFilter->filterColor(skPaint.getColor());
|
| - grPaint->setColor(SkColor2GrColor(filtered));
|
| + if (applyColorFilterToPaintColor) {
|
| + grPaint->setColor(SkColorToPremulGrColor(colorFilter->filterColor(skPaint.getColor())));
|
| } else {
|
| SkTDArray<const GrFragmentProcessor*> array;
|
| - // return false if failed?
|
| if (colorFilter->asFragmentProcessors(context, grPaint->getProcessorDataManager(),
|
| &array)) {
|
| for (int i = 0; i < array.count(); ++i) {
|
| - grPaint->addColorFragmentProcessor(array[i]);
|
| - array[i]->unref();
|
| + grPaint->addColorFragmentProcessor(array[i])->unref();
|
| }
|
| + } else {
|
| + return false;
|
| }
|
| }
|
| }
|
|
|
| + SkXfermode* mode = skPaint.getXfermode();
|
| + GrXPFactory* xpFactory = nullptr;
|
| + if (!SkXfermode::AsXPFactory(mode, &xpFactory)) {
|
| + // Fall back to src-over
|
| + // return false here?
|
| + xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
|
| + }
|
| + SkASSERT(xpFactory);
|
| + grPaint->setXPFactory(xpFactory)->unref();
|
| +
|
| #ifndef SK_IGNORE_GPU_DITHER
|
| if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0) {
|
| grPaint->addColorFragmentProcessor(GrDitherEffect::Create())->unref();
|
| @@ -754,29 +842,49 @@ bool SkPaint2GrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrColor
|
| return true;
|
| }
|
|
|
| -bool SkPaint2GrPaint(GrContext* context,const SkPaint& skPaint, const SkMatrix& viewM,
|
| - bool constantColor, GrPaint* grPaint) {
|
| - SkShader* shader = skPaint.getShader();
|
| - if (nullptr == shader) {
|
| - return SkPaint2GrPaintNoShader(context, skPaint, SkColor2GrColor(skPaint.getColor()),
|
| - constantColor, grPaint);
|
| - }
|
| -
|
| - GrColor paintColor = SkColor2GrColor(skPaint.getColor());
|
| +bool SkPaintToGrPaint(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM,
|
| + GrPaint* grPaint) {
|
| + return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, nullptr, false, grPaint);
|
| +}
|
|
|
| - const GrFragmentProcessor* fp = shader->asFragmentProcessor(context, viewM, NULL,
|
| - skPaint.getFilterQuality(), grPaint->getProcessorDataManager());
|
| - if (!fp) {
|
| +/** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. */
|
| +bool SkPaintToGrPaintReplaceShader(GrContext* context,
|
| + const SkPaint& skPaint,
|
| + const GrFragmentProcessor* shaderFP,
|
| + GrPaint* grPaint) {
|
| + if (!shaderFP) {
|
| return false;
|
| }
|
| - grPaint->addColorFragmentProcessor(fp)->unref();
|
| - constantColor = false;
|
| + return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), &shaderFP, nullptr, false,
|
| + grPaint);
|
| +}
|
| +
|
| +/** Ignores the SkShader (if any) on skPaint. */
|
| +bool SkPaintToGrPaintNoShader(GrContext* context,
|
| + const SkPaint& skPaint,
|
| + GrPaint* grPaint) {
|
| + // Use a ptr to a nullptr to to indicate that the SkShader is ignored and not replaced.
|
| + static const GrFragmentProcessor* kNullShaderFP = nullptr;
|
| + static const GrFragmentProcessor** kIgnoreShader = &kNullShaderFP;
|
| + return skpaint_to_grpaint_impl(context, skPaint, SkMatrix::I(), kIgnoreShader, nullptr, false,
|
| + grPaint);
|
| +}
|
|
|
| - // The grcolor is automatically set when calling asFragmentProcessor.
|
| - // If the shader can be seen as an effect it returns true and adds its effect to the grpaint.
|
| - return SkPaint2GrPaintNoShader(context, skPaint, paintColor, constantColor, grPaint);
|
| +/** Blends the SkPaint's shader (or color if no shader) with a per-primitive color which must
|
| +be setup as a vertex attribute using the specified SkXfermode::Mode. */
|
| +bool SkPaintToGrPaintWithXfermode(GrContext* context,
|
| + const SkPaint& skPaint,
|
| + const SkMatrix& viewM,
|
| + SkXfermode::Mode primColorMode,
|
| + bool primitiveIsSrc,
|
| + GrPaint* grPaint) {
|
| + return skpaint_to_grpaint_impl(context, skPaint, viewM, nullptr, &primColorMode, primitiveIsSrc,
|
| + grPaint);
|
| }
|
|
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| SkImageInfo GrMakeInfoFromTexture(GrTexture* tex, int w, int h, bool isOpaque) {
|
| #ifdef SK_DEBUG
|
| const GrSurfaceDesc& desc = tex->desc();
|
|
|