diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 5289019cc9..e2feefc31e 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1742,42 +1742,50 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode, SkAutoSTMalloc<128, GrColor> convertedColors(0); if (colors) { - // need to convert byte order and from non-PM to PM + // need to convert byte order and from non-PM to PM. TODO: Keep unpremul until after + // interpolation. convertedColors.reset(vertexCount); - SkColor color; for (int i = 0; i < vertexCount; ++i) { - color = colors[i]; - if (paint.getAlpha() != 255) { - color = SkColorSetA(color, SkMulDiv255Round(SkColorGetA(color), paint.getAlpha())); - } - /// TODO: Perform the premul after interpolating - convertedColors[i] = SkColorToPremulGrColor(color); + convertedColors[i] = SkColorToPremulGrColor(colors[i]); } colors = convertedColors.get(); } GrPaint grPaint; - if (texs && colors && paint.getShader()) { - // When there are texs and colors the shader and colors are combined using xmode. A null - // xmode is defined to mean modulate. - SkXfermode::Mode colorMode; - if (xmode) { - if (!xmode->asMode(&colorMode)) { + if (texs && paint.getShader()) { + if (colors) { + // When there are texs and colors the shader and colors are combined using xmode. A null + // xmode is defined to mean modulate. + SkXfermode::Mode colorMode; + if (xmode) { + if (!xmode->asMode(&colorMode)) { + return; + } + } else { + colorMode = SkXfermode::kModulate_Mode; + } + if (!SkPaintToGrPaintWithXfermode(this->context(), paint, *draw.fMatrix, colorMode, + false, &grPaint)) { return; } } else { - colorMode = SkXfermode::kModulate_Mode; + // We have a shader, but no colors to blend it against. + if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { + return; + } } - if (!SkPaintToGrPaintWithXfermode(this->context(), paint, *draw.fMatrix, colorMode, false, - &grPaint)) { - return; + } else { + if (colors) { + // We have colors, but either have no shader or no texture coords (which implies that + // we should ignore the shader). + if (!SkPaintToGrPaintWithPrimitiveColor(this->context(), paint, &grPaint)) { + return; + } + } else { + // No colors and no shaders. Just draw with the paint color. + if (!SkPaintToGrPaintNoShader(this->context(), paint, &grPaint)) { + return; + } } - } else if (!texs) { - // Defined to ignore the shader unless texs is provided. - if (!SkPaintToGrPaintNoShader(this->context(), paint, &grPaint)) { - return; - } - } else if (!SkPaintToGrPaint(this->context(), paint, *draw.fMatrix, &grPaint)) { - return; } fDrawContext->drawVertices(fRenderTarget, diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index a726939788..ce1ce32eb3 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -677,6 +677,14 @@ bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut, //////////////////////////////////////////////////////////////////////////////////////////////// +static inline bool blend_requires_shader(const SkXfermode::Mode mode, bool primitiveIsSrc) { + if (primitiveIsSrc) { + return SkXfermode::kSrc_Mode != mode; + } else { + return SkXfermode::kDst_Mode != mode; + } +} + static inline bool skpaint_to_grpaint_impl(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM, @@ -689,15 +697,18 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context, // Setup the initial color considering the shader, the SkPaint color, and the presence or not // of per-vertex colors. SkAutoTUnref 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; + const GrFragmentProcessor* shaderFP = nullptr; + if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc)) { + if (shaderProcessor) { + shaderFP = *shaderProcessor; + } else if (const SkShader* shader = skPaint.getShader()) { + aufp.reset(shader->asFragmentProcessor(context, viewM, nullptr, + skPaint.getFilterQuality(), + grPaint->getProcessorDataManager())); + shaderFP = aufp; + if (!shaderFP) { + return false; + } } } @@ -761,11 +772,13 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context, grPaint->addColorFragmentProcessor(processor); } - grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor()) | 0xFF000000); + grPaint->setColor(SkColorToOpaqueGrColor(skPaint.getColor())); GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor()); - grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create( - paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref(); + if (GrColor_WHITE != paintAlpha) { + grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create( + paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref(); + } } else { // No shader, no primitive color. grPaint->setColor(SkColorToPremulGrColor(skPaint.getColor())); diff --git a/src/gpu/SkGrPriv.h b/src/gpu/SkGrPriv.h index 25fda57d9e..36601fc3e3 100644 --- a/src/gpu/SkGrPriv.h +++ b/src/gpu/SkGrPriv.h @@ -54,19 +54,20 @@ void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& ima bool GrMakeStretchedKey(const GrUniqueKey& origKey, const SkGrStretch&, GrUniqueKey* stretchedKey); /** Converts an SkPaint to a GrPaint for a given GrContext. The matrix is required in order - to convert the SkShader (if any) on the SkPaint. */ + to convert the SkShader (if any) on the SkPaint. The primitive itself has no color. */ bool SkPaintToGrPaint(GrContext*, const SkPaint& skPaint, const SkMatrix& viewM, GrPaint* grPaint); -/** Ignores the SkShader (if any) on skPaint. */ +/** Same as above but ignores the SkShader (if any) on skPaint. */ bool SkPaintToGrPaintNoShader(GrContext* context, const SkPaint& skPaint, GrPaint* grPaint); /** Replaces the SkShader (if any) on skPaint with the passed in GrFragmentProcessor. The processor - should expect an unpremul input color and produce a premultiplied output color. */ + should expect an unpremul input color and produce a premultiplied output color. There is + no primitive color. */ bool SkPaintToGrPaintReplaceShader(GrContext*, const SkPaint& skPaint, const GrFragmentProcessor* shaderFP, @@ -75,8 +76,7 @@ bool SkPaintToGrPaintReplaceShader(GrContext*, /** Blends the SkPaint's shader (or color if no shader) with the color which specified via a GrBatch's GrPrimitiveProcesssor. Currently there is a bool param to indicate whether the primitive color is the dst or src color to the blend in order to work around differences between - drawVertices and drawAtlas. - */ + drawVertices and drawAtlas. */ bool SkPaintToGrPaintWithXfermode(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM, @@ -84,6 +84,16 @@ bool SkPaintToGrPaintWithXfermode(GrContext* context, bool primitiveIsSrc, GrPaint* grPaint); +/** This is used when there is a primitive color, but the shader should be ignored. Currently, + the expectation is that the primitive color will be premultiplied, though it really should be + unpremultiplied so that interpolation is done in unpremul space. The paint's alpha will be + applied to the primitive color after interpolation. */ +inline bool SkPaintToGrPaintWithPrimitiveColor(GrContext* context, const SkPaint& skPaint, + GrPaint* grPaint) { + return SkPaintToGrPaintWithXfermode(context, skPaint, SkMatrix::I(), SkXfermode::kDst_Mode, + false, grPaint); +} + bool GrTextureUsageSupported(const GrCaps&, int width, int height, SkImageUsageType); #endif