Fix drawVertices when there is a paint alpha

Review URL: https://codereview.chromium.org/1382753002
This commit is contained in:
bsalomon 2015-10-01 08:34:17 -07:00 committed by Commit bot
parent 5827653e42
commit aa48d36397
3 changed files with 73 additions and 42 deletions

View File

@ -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,

View File

@ -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<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;
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()));

View File

@ -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