Chromium Code Reviews| Index: src/gpu/SkGr.cpp |
| diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp |
| index 09c83b929a8c575b1a2b9e15116c76abc4968c5c..8429aa488292ffc61b8b85ec080ec290a4e6336f 100644 |
| --- a/src/gpu/SkGr.cpp |
| +++ b/src/gpu/SkGr.cpp |
| @@ -26,6 +26,8 @@ |
| #include "effects/GrBicubicEffect.h" |
| #include "effects/GrDitherEffect.h" |
| #include "effects/GrPorterDuffXferProcessor.h" |
|
robertphillips
2015/09/25 19:52:17
Fix order ?
bsalomon
2015/09/25 20:45:08
Done.
|
| +#include "effects/GrXfermodeFragmentProcessor.h" |
| +#include "effects/GrConstColorProcessor.h" |
|
egdaniel
2015/09/25 19:23:15
alphabetize
bsalomon
2015/09/25 20:45:07
Done.
|
| #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) { |
| +//////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
|
robertphillips
2015/09/25 19:52:17
for to -> to ?
bsalomon
2015/09/25 20:45:07
Done.
|
| +// Use a ptr to a nullptr for to indicate that the SkShader is ignored and not replaced. |
| +static const GrFragmentProcessor* kNullShaderFP = nullptr; |
| +static const GrFragmentProcessor** kIgnoreShader = &kNullShaderFP; |
| +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. |
| + grPaint->setColor(GrColor_WHITE); |
|
egdaniel
2015/09/25 19:23:15
seems a little strange to me to stay the GrPaint's
bsalomon
2015/09/25 20:45:08
I'll just delete the line.
|
| + |
| + GrColor shaderInput = SkColorToOpaqueGrColor(skPaint.getColor()); |
| + |
| + shaderFP = GrFragmentProcessor::ReplaceInput(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 |
|
robertphillips
2015/09/25 19:52:17
So in this case the GrPaint's color isn't premul?
bsalomon
2015/09/25 20:45:08
Yep, SkShader's FPs are now responsible for ingest
|
| + 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)); |
| + processor.reset(GrXfermodeFragmentProcessor::CreateFromSrcProcessor(processor, |
| + *primColorMode)); |
|
egdaniel
2015/09/25 19:23:15
does this not need to look at primitiveIsSrc?
bsalomon
2015/09/25 20:45:07
Done.
|
| + 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(), |
|
robertphillips
2015/09/25 19:52:17
xtra space ?
bsalomon
2015/09/25 20:45:07
Done.
|
| - &array)) { |
| + &array)) { |
| for (int i = 0; i < array.count(); ++i) { |
|
robertphillips
2015/09/25 19:52:17
grPaint->addColorFragmentProcessor(array[i])->unre
bsalomon
2015/09/25 20:45:08
Done.
|
| grPaint->addColorFragmentProcessor(array[i]); |
| 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,46 @@ 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) { |
| + 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(); |