Don't draw if SkShader::asNewFragmentProcessor fails.

BUG=chromium:473156

Review URL: https://codereview.chromium.org/1089063002
This commit is contained in:
bsalomon 2015-04-15 14:18:34 -07:00 committed by Commit bot
parent bc0273524b
commit bed83a66f5
8 changed files with 144 additions and 36 deletions

62
gm/badpaint.cpp Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm.h"
#include "SkCanvas.h"
#include "SkShader.h"
/** This GM draws with invalid paints. It should draw nothing other than the background. */
class BadPaintGM : public skiagm::GM {
public:
BadPaintGM() {}
protected:
SkString onShortName() override { return SkString("badpaint"); }
SkISize onISize() override { return SkISize::Make(100, 100); }
void onOnceBeforeDraw() override {
SkBitmap emptyBmp;
SkBitmap blueBmp;
blueBmp.allocN32Pixels(10, 10);
blueBmp.eraseColor(SK_ColorBLUE);
SkMatrix badMatrix;
badMatrix.setAll(0, 0, 0, 0, 0, 0, 0, 0, 0);
#if 0 // This crashes pipe!
// Empty bitmap.
fPaints.push_back().setColor(SK_ColorGREEN);
fPaints.back().setShader(SkShader::CreateBitmapShader(emptyBmp, SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode))->unref();
#endif
// Non-invertible local matrix.
fPaints.push_back().setColor(SK_ColorGREEN);
fPaints.back().setShader(SkShader::CreateBitmapShader(blueBmp, SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode,
&badMatrix))->unref();
}
void onDraw(SkCanvas* canvas) override {
SkRect rect = SkRect::MakeXYWH(10, 10, 80, 80);
for (int i = 0; i < fPaints.count(); ++i) {
canvas->drawRect(rect, fPaints[i]);
}
}
private:
SkTArray<SkPaint> fPaints;
typedef skiagm::GM INHERITED;
};
/////////////////////////////////////////////////////////////////////////////////////
DEF_GM( return SkNEW(BadPaintGM); )

View File

@ -104,7 +104,8 @@ protected:
} else {
skPaint.setColor(kPaintColors[paintType]);
}
SkPaint2GrPaintShader(context, rt, skPaint, viewMatrix, false, &grPaint);
SkAssertResult(SkPaint2GrPaint(context, rt, skPaint, viewMatrix, false,
&grPaint));
GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m;
GrColor color = kColors[procColor];

View File

@ -26,6 +26,7 @@
'../gm/arcofzorro.cpp',
'../gm/arithmode.cpp',
'../gm/astcbitmap.cpp',
'../gm/badpaint.cpp',
'../gm/beziereffects.cpp',
'../gm/beziers.cpp',
'../gm/bigblurs.cpp',

View File

@ -81,14 +81,14 @@ GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTexture
// an optimization where the color filter can be applied to the SkPaint's
// color once while converting to GrPaint and then ignored. TODO: Remove this
// bool and use the invariant info to automatically apply the color filter.
void SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget*, const SkPaint& skPaint,
bool SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget*, const SkPaint& skPaint,
GrColor paintColor, bool constantColor, GrPaint* grPaint);
// This function is similar to skPaint2GrPaintNoShader but also converts
// skPaint's shader to a GrFragmentProcessor if possible.
// constantColor has the same meaning as in skPaint2GrPaintNoShader.
void SkPaint2GrPaintShader(GrContext* context, GrRenderTarget*, const SkPaint& skPaint,
const SkMatrix& viewM, bool constantColor, GrPaint* grPaint);
bool SkPaint2GrPaint(GrContext* context, GrRenderTarget*, const SkPaint& skPaint,
const SkMatrix& viewM, bool constantColor, GrPaint* grPaint);
////////////////////////////////////////////////////////////////////////////////
// Classes

View File

@ -247,7 +247,9 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
// Though for the time being runs in the textblob can override the paint, they only touch font
// info.
GrPaint grPaint;
SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint);
if (!SkPaint2GrPaint(fContext, rt, skPaint, viewMatrix, true, &grPaint)) {
return;
}
if (cacheBlob) {
if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, blurRec, viewMatrix, x, y)) {

View File

@ -116,7 +116,9 @@ void GrTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, const S
runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint));
GrPaint grPaint;
SkPaint2GrPaintShader(fContext, fRenderTarget, runPaint, viewMatrix, true, &grPaint);
if (!SkPaint2GrPaint(fContext, fRenderTarget, runPaint, viewMatrix, true, &grPaint)) {
return;
}
switch (it.positioning()) {
case SkTextBlob::kDefault_Positioning:

View File

@ -365,7 +365,9 @@ void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawPaint", fContext);
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
return;
}
fContext->drawPaint(fRenderTarget, fClip, grPaint, *draw.fMatrix);
}
@ -390,7 +392,10 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) {
GrStrokeInfo strokeInfo(paint, SkPaint::kStroke_Style);
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true,
&grPaint)) {
return;
}
SkPath path;
path.setIsVolatile(true);
path.moveTo(pts[0]);
@ -407,7 +412,9 @@ void SkGpuDevice::drawPoints(const SkDraw& draw, SkCanvas::PointMode mode,
}
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
return;
}
fContext->drawVertices(fRenderTarget,
fClip,
@ -479,7 +486,9 @@ void SkGpuDevice::drawRect(const SkDraw& draw, const SkRect& rect,
}
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
return;
}
fContext->drawRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, rect, &strokeInfo);
}
@ -493,7 +502,9 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rect,
CHECK_SHOULD_DRAW(draw);
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
return;
}
GrStrokeInfo strokeInfo(paint);
if (paint.getMaskFilter()) {
@ -561,7 +572,10 @@ void SkGpuDevice::drawDRRect(const SkDraw& draw, const SkRRect& outer,
CHECK_SHOULD_DRAW(draw);
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true,
&grPaint)) {
return;
}
if (NULL == paint.getMaskFilter() && NULL == paint.getPathEffect()) {
fContext->drawDRRect(fRenderTarget, fClip, grPaint, *draw.fMatrix, outer, inner);
@ -609,7 +623,9 @@ void SkGpuDevice::drawOval(const SkDraw& draw, const SkRect& oval,
}
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
return;
}
fContext->drawOval(fRenderTarget, fClip, grPaint, *draw.fMatrix, oval, strokeInfo);
}
@ -804,7 +820,9 @@ void SkGpuDevice::internalDrawPath(const SkPath& origSrcPath, const SkPaint& pai
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, viewMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, viewMatrix, true, &grPaint)) {
return;
}
const SkRect* cullRect = NULL; // TODO: what is our bounds?
SkStrokeRec* strokePtr = strokeInfo.getStrokeRecPtr();
@ -1478,7 +1496,10 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
bool alphaOnly = !(kAlpha_8_SkColorType == bitmap.colorType());
GrColor paintColor = (alphaOnly) ? SkColor2GrColorJustAlpha(paint.getColor()) :
SkColor2GrColor(paint.getColor());
SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint, paintColor, false, &grPaint);
if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint, paintColor, false,
&grPaint)) {
return;
}
fContext->drawNonAARectToRect(fRenderTarget, fClip, grPaint, viewMatrix, dstRect,
paintRect);
@ -1551,8 +1572,10 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
GrPaint grPaint;
grPaint.addColorTextureProcessor(texture, SkMatrix::I());
SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint,
SkColor2GrColorJustAlpha(paint.getColor()), false, &grPaint);
if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint,
SkColor2GrColorJustAlpha(paint.getColor()), false, &grPaint)) {
return;
}
fContext->drawNonAARectToRect(fRenderTarget,
fClip,
@ -1665,8 +1688,10 @@ void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
GrPaint grPaint;
grPaint.addColorTextureProcessor(devTex, SkMatrix::I());
SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint,
SkColor2GrColorJustAlpha(paint.getColor()), false, &grPaint);
if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint,
SkColor2GrColorJustAlpha(paint.getColor()), false, &grPaint)) {
return;
}
SkRect dstRect = SkRect::MakeXYWH(SkIntToScalar(x),
SkIntToScalar(y),
@ -1741,8 +1766,10 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
copy.setStrokeWidth(0);
// we ignore the shader if texs is null.
SkPaint2GrPaintNoShader(this->context(), fRenderTarget, copy,
SkColor2GrColor(copy.getColor()), NULL == colors, &grPaint);
if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, copy,
SkColor2GrColor(copy.getColor()), NULL == colors, &grPaint)) {
return;
}
primType = kLines_GrPrimitiveType;
int triangleCount = 0;
@ -1781,12 +1808,16 @@ void SkGpuDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
primType = gVertexMode2PrimitiveType[vmode];
if (NULL == texs || NULL == paint.getShader()) {
SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint,
SkColor2GrColor(paint.getColor()),
NULL == colors, &grPaint);
if (!SkPaint2GrPaintNoShader(this->context(), fRenderTarget, paint,
SkColor2GrColor(paint.getColor()),
NULL == colors, &grPaint)) {
return;
}
} else {
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix,
NULL == colors, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix,
NULL == colors, &grPaint)) {
return;
}
}
}
@ -1835,7 +1866,9 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawText", fContext);
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
return;
}
SkDEBUGCODE(this->validate();)
@ -1850,7 +1883,9 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, size_t byteL
CHECK_SHOULD_DRAW(draw);
GrPaint grPaint;
SkPaint2GrPaintShader(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint);
if (!SkPaint2GrPaint(this->context(), fRenderTarget, paint, *draw.fMatrix, true, &grPaint)) {
return;
}
SkDEBUGCODE(this->validate();)

View File

@ -642,7 +642,7 @@ bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut,
///////////////////////////////////////////////////////////////////////////////
void SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint,
bool SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint,
GrColor paintColor, bool constantColor, GrPaint* grPaint) {
grPaint->setDither(skPaint.isDither());
@ -652,6 +652,7 @@ void SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget* rt, const SkPai
GrXPFactory* xpFactory = NULL;
if (!SkXfermode::AsXPFactory(mode, &xpFactory)) {
// Fall back to src-over
// return false here?
xpFactory = GrPorterDuffXPFactory::Create(SkXfermode::kSrcOver_Mode);
}
SkASSERT(xpFactory);
@ -669,6 +670,7 @@ void SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget* rt, const SkPai
grPaint->setColor(SkColor2GrColor(filtered));
} else {
SkTDArray<GrFragmentProcessor*> array;
// return false if failed?
if (colorFilter->asFragmentProcessors(context, &array)) {
for (int i = 0; i < array.count(); ++i) {
grPaint->addColorProcessor(array[i]);
@ -699,15 +701,15 @@ void SkPaint2GrPaintNoShader(GrContext* context, GrRenderTarget* rt, const SkPai
}
}
#endif
return true;
}
void SkPaint2GrPaintShader(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint,
const SkMatrix& viewM, bool constantColor, GrPaint* grPaint) {
bool SkPaint2GrPaint(GrContext* context, GrRenderTarget* rt, const SkPaint& skPaint,
const SkMatrix& viewM, bool constantColor, GrPaint* grPaint) {
SkShader* shader = skPaint.getShader();
if (NULL == shader) {
SkPaint2GrPaintNoShader(context, rt, skPaint, SkColor2GrColor(skPaint.getColor()),
constantColor, grPaint);
return;
return SkPaint2GrPaintNoShader(context, rt, skPaint, SkColor2GrColor(skPaint.getColor()),
constantColor, grPaint);
}
GrColor paintColor = SkColor2GrColor(skPaint.getColor());
@ -719,7 +721,10 @@ void SkPaint2GrPaintShader(GrContext* context, GrRenderTarget* rt, const SkPaint
// Allow the shader to modify paintColor and also create an effect to be installed as
// the first color effect on the GrPaint.
GrFragmentProcessor* fp = NULL;
if (shader->asFragmentProcessor(context, skPaint, viewM, NULL, &paintColor, &fp) && fp) {
if (!shader->asFragmentProcessor(context, skPaint, viewM, NULL, &paintColor, &fp)) {
return false;
}
if (fp) {
grPaint->addColorProcessor(fp)->unref();
constantColor = false;
}
@ -727,5 +732,5 @@ void SkPaint2GrPaintShader(GrContext* context, GrRenderTarget* rt, const SkPaint
// 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.
SkPaint2GrPaintNoShader(context, rt, skPaint, paintColor, constantColor, grPaint);
return SkPaint2GrPaintNoShader(context, rt, skPaint, paintColor, constantColor, grPaint);
}