Make GMs aware of what tool they're being run in.

Add a saveLayer set of draws to convex_poly_clip and fix GPU bug where polygon clips don't account for the translation between clip and device space.

BUG=skia:2051
R=robertphillips@google.com, reed@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/148283017

git-svn-id: http://skia.googlecode.com/svn/trunk@13371 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-02-07 21:13:11 +00:00
parent 5bc7339aab
commit b21fac156d
8 changed files with 123 additions and 53 deletions

View File

@ -55,6 +55,7 @@ public:
virtual SkBenchmark* operator()() const SK_OVERRIDE {
skiagm::GM* gm = fGMFactory(NULL);
gm->setMode(skiagm::GM::kBench_Mode);
return SkNEW_ARGS(SkGMBench, (gm));
}

View File

@ -83,7 +83,12 @@ protected:
}
virtual SkISize onISize() SK_OVERRIDE {
return make_isize(435, 540);
// When benchmarking the saveLayer set of draws is skipped.
int w = 435;
if (kBench_Mode != this->getMode()) {
w *= 2;
}
return make_isize(w, 540);
}
virtual void onOnceBeforeDraw() SK_OVERRIDE {
@ -140,47 +145,70 @@ protected:
SkIntToScalar(size.fHeight));
canvas->drawBitmapRectToRect(fBmp, NULL, dstRect, &bgPaint);
for (SkTLList<Clip>::Iter iter(fClips, SkTLList<Clip>::Iter::kHead_IterStart);
NULL != iter.get();
iter.next()) {
const Clip* clip = iter.get();
SkScalar x = 0;
for (int aa = 0; aa < 2; ++aa) {
canvas->save();
canvas->translate(x, y);
clip->setOnCanvas(canvas, SkRegion::kIntersect_Op, SkToBool(aa));
canvas->drawBitmap(fBmp, 0, 0);
canvas->restore();
x += fBmp.width() + kMargin;
static const char kTxt[] = "Clip Me!";
SkPaint txtPaint;
txtPaint.setTextSize(23.f);
txtPaint.setAntiAlias(true);
txtPaint.setColor(SK_ColorDKGRAY);
SkScalar textW = txtPaint.measureText(kTxt, SK_ARRAY_COUNT(kTxt)-1);
SkScalar startX = 0;
int testLayers = kBench_Mode != this->getMode();
for (int doLayer = 0; doLayer <= testLayers; ++doLayer) {
for (SkTLList<Clip>::Iter iter(fClips, SkTLList<Clip>::Iter::kHead_IterStart);
NULL != iter.get();
iter.next()) {
const Clip* clip = iter.get();
SkScalar x = startX;
for (int aa = 0; aa < 2; ++aa) {
if (doLayer) {
SkRect bounds;
clip->getBounds(&bounds);
bounds.outset(2, 2);
bounds.offset(x, y);
canvas->saveLayer(&bounds, NULL);
} else {
canvas->save();
}
canvas->translate(x, y);
clip->setOnCanvas(canvas, SkRegion::kIntersect_Op, SkToBool(aa));
canvas->drawBitmap(fBmp, 0, 0);
canvas->restore();
x += fBmp.width() + kMargin;
}
for (int aa = 0; aa < 2; ++aa) {
SkPaint clipOutlinePaint;
clipOutlinePaint.setAntiAlias(true);
clipOutlinePaint.setColor(0x50505050);
clipOutlinePaint.setStyle(SkPaint::kStroke_Style);
clipOutlinePaint.setStrokeWidth(0);
if (doLayer) {
SkRect bounds;
clip->getBounds(&bounds);
bounds.outset(2, 2);
bounds.offset(x, y);
canvas->saveLayer(&bounds, NULL);
} else {
canvas->save();
}
canvas->translate(x, y);
SkPath closedClipPath;
clip->asClosedPath(&closedClipPath);
canvas->drawPath(closedClipPath, clipOutlinePaint);
clip->setOnCanvas(canvas, SkRegion::kIntersect_Op, SkToBool(aa));
canvas->scale(1.f, 1.8f);
canvas->drawText(kTxt, SK_ARRAY_COUNT(kTxt)-1,
0, 1.5f * txtPaint.getTextSize(),
txtPaint);
canvas->restore();
x += textW + 2 * kMargin;
}
y += fBmp.height() + kMargin;
}
for (int aa = 0; aa < 2; ++aa) {
static const char kTxt[] = "Clip Me!";
SkPaint txtPaint;
txtPaint.setTextSize(23.f);
txtPaint.setAntiAlias(true);
txtPaint.setColor(SK_ColorDKGRAY);
SkPaint clipOutlinePaint;
clipOutlinePaint.setAntiAlias(true);
clipOutlinePaint.setColor(0x50505050);
clipOutlinePaint.setStyle(SkPaint::kStroke_Style);
clipOutlinePaint.setStrokeWidth(0);
canvas->save();
canvas->translate(x, y);
SkPath closedClipPath;
clip->asClosedPath(&closedClipPath);
canvas->drawPath(closedClipPath, clipOutlinePaint);
clip->setOnCanvas(canvas, SkRegion::kIntersect_Op, SkToBool(aa));
canvas->scale(1.f, 1.8f);
canvas->drawText(kTxt, SK_ARRAY_COUNT(kTxt)-1,
0, 1.5f * txtPaint.getTextSize(),
txtPaint);
canvas->restore();
x += fBmp.width() + kMargin;
}
y += fBmp.height() + kMargin;
y = 0;
startX += 2 * fBmp.width() + SkScalarCeilToInt(2 * textW) + 6 * kMargin;
}
}
@ -242,6 +270,20 @@ private:
ClipType getType() const { return fClipType; }
void getBounds(SkRect* bounds) const {
switch (fClipType) {
case kPath_ClipType:
*bounds = fPath.getBounds();
break;
case kRect_ClipType:
*bounds = fRect;
break;
case kNone_ClipType:
SkDEBUGFAIL("Uninitialized Clip.");
break;
}
}
private:
ClipType fClipType;
SkPath fPath;

View File

@ -11,6 +11,7 @@ using namespace skiagm;
SkString GM::gResourcePath;
GM::GM() {
fMode = kGM_Mode;
fBGColor = SK_ColorWHITE;
fCanvasIsDeferred = false;
fHaveCalledOnceBeforeDraw = false;

18
gm/gm.h
View File

@ -53,6 +53,15 @@ namespace skiagm {
kAsBench_Flag = 1 << 10, // Run the GM as a benchmark in the bench tool
};
enum Mode {
kGM_Mode,
kSample_Mode,
kBench_Mode,
};
void setMode(Mode mode) { fMode = mode; }
Mode getMode() const { return fMode; }
void draw(SkCanvas*);
void drawBackground(SkCanvas*);
void drawContent(SkCanvas*);
@ -101,10 +110,10 @@ namespace skiagm {
fCanvasIsDeferred = isDeferred;
}
const SkMatrix& getStarterMatrix() { return fStarterMatrix; }
void setStarterMatrix(const SkMatrix& matrix) {
fStarterMatrix = matrix;
}
const SkMatrix& getStarterMatrix() { return fStarterMatrix; }
void setStarterMatrix(const SkMatrix& matrix) {
fStarterMatrix = matrix;
}
protected:
static SkString gResourcePath;
@ -118,6 +127,7 @@ namespace skiagm {
virtual SkMatrix onGetInitialTransform() const { return SkMatrix::I(); }
private:
Mode fMode;
SkString fShortName;
SkColor fBGColor;
bool fCanvasIsDeferred; // work-around problem in srcmode.cpp

View File

@ -386,7 +386,9 @@ SkGMSampleViewFactory::SkGMSampleViewFactory(GMFactoryFunc func)
}
SkView* SkGMSampleViewFactory::operator() () const {
return new GMSampleView(fFunc(NULL));
skiagm::GM* gm = fFunc(NULL);
gm->setMode(skiagm::GM::kSample_Mode);
return new GMSampleView(gm);
}
SkViewRegister* SkViewRegister::gHead;

View File

@ -158,18 +158,23 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
// clips against the edges.
if (1 == elements.count() && SkClipStack::Element::kPath_Type == elements.tail()->getType() &&
SkRegion::kReplace_Op == elements.tail()->getOp()) {
const SkPath& p = elements.tail()->getPath();
const SkPath& path = elements.tail()->getPath();
bool isAA = GR_AA_CLIP && elements.tail()->isAA();
SkAutoTUnref<GrEffectRef> effect;
if (rt->isMultisampled()) {
// A coverage effect for AA clipping won't play nicely with MSAA.
if (!isAA) {
effect.reset(GrConvexPolyEffect::Create(GrConvexPolyEffect::kFillNoAA_EdgeType, p));
SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
SkIntToScalar(-clipDataIn->fOrigin.fY) };
effect.reset(GrConvexPolyEffect::Create(GrConvexPolyEffect::kFillNoAA_EdgeType,
path, &offset));
}
} else {
SkVector offset = { SkIntToScalar(-clipDataIn->fOrigin.fX),
SkIntToScalar(-clipDataIn->fOrigin.fY) };
GrConvexPolyEffect::EdgeType type = isAA ? GrConvexPolyEffect::kFillAA_EdgeType :
GrConvexPolyEffect::kFillNoAA_EdgeType;
effect.reset(GrConvexPolyEffect::Create(type, p));
effect.reset(GrConvexPolyEffect::Create(type, path, &offset));
}
if (effect) {
are->set(fGpu->drawState());

View File

@ -97,7 +97,7 @@ GrGLEffect::EffectKey GrGLConvexPolyEffect::GenKey(const GrDrawEffect& drawEffec
//////////////////////////////////////////////////////////////////////////////
GrEffectRef* GrConvexPolyEffect::Create(EdgeType type, const SkPath& path) {
GrEffectRef* GrConvexPolyEffect::Create(EdgeType type, const SkPath& path, const SkVector* offset) {
if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
!path.isConvex() ||
path.isInverseFillType()) {
@ -114,6 +114,13 @@ GrEffectRef* GrConvexPolyEffect::Create(EdgeType type, const SkPath& path) {
SkPath::Direction dir;
SkAssertResult(path.cheapComputeDirection(&dir));
SkVector t;
if (NULL == offset) {
t.set(0, 0);
} else {
t = *offset;
}
int count = path.getPoints(pts, kMaxEdges);
int n = 0;
for (int lastPt = count - 1, i = 0; i < count; lastPt = i++) {
@ -127,7 +134,8 @@ GrEffectRef* GrConvexPolyEffect::Create(EdgeType type, const SkPath& path) {
edges[3 * n] = -v.fY;
edges[3 * n + 1] = v.fX;
}
edges[3 * n + 2] = -(edges[3 * n] * pts[i].fX + edges[3 * n + 1] * pts[i].fY);
SkPoint p = pts[i] + t;
edges[3 * n + 2] = -(edges[3 * n] * p.fX + edges[3 * n + 1] * p.fY);
++n;
}
}

View File

@ -57,9 +57,10 @@ public:
/**
* Creates an effect that clips against the path. If the path is not a convex polygon, is
* inverse filled, or has too many edges, this will return NULL.
* inverse filled, or has too many edges, this will return NULL. If offset is non-NULL, then
* the path is translated by the vector.
*/
static GrEffectRef* Create(EdgeType, const SkPath&);
static GrEffectRef* Create(EdgeType, const SkPath&, const SkVector* offset= NULL);
virtual ~GrConvexPolyEffect();