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
Родитель 5bc7339aab
Коммит b21fac156d
8 изменённых файлов: 123 добавлений и 53 удалений

Просмотреть файл

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

Просмотреть файл

@ -83,7 +83,12 @@ protected:
} }
virtual SkISize onISize() SK_OVERRIDE { 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 { virtual void onOnceBeforeDraw() SK_OVERRIDE {
@ -140,47 +145,70 @@ protected:
SkIntToScalar(size.fHeight)); SkIntToScalar(size.fHeight));
canvas->drawBitmapRectToRect(fBmp, NULL, dstRect, &bgPaint); canvas->drawBitmapRectToRect(fBmp, NULL, dstRect, &bgPaint);
for (SkTLList<Clip>::Iter iter(fClips, SkTLList<Clip>::Iter::kHead_IterStart); static const char kTxt[] = "Clip Me!";
NULL != iter.get(); SkPaint txtPaint;
iter.next()) { txtPaint.setTextSize(23.f);
const Clip* clip = iter.get(); txtPaint.setAntiAlias(true);
SkScalar x = 0; txtPaint.setColor(SK_ColorDKGRAY);
for (int aa = 0; aa < 2; ++aa) { SkScalar textW = txtPaint.measureText(kTxt, SK_ARRAY_COUNT(kTxt)-1);
canvas->save();
canvas->translate(x, y); SkScalar startX = 0;
clip->setOnCanvas(canvas, SkRegion::kIntersect_Op, SkToBool(aa)); int testLayers = kBench_Mode != this->getMode();
canvas->drawBitmap(fBmp, 0, 0); for (int doLayer = 0; doLayer <= testLayers; ++doLayer) {
canvas->restore(); for (SkTLList<Clip>::Iter iter(fClips, SkTLList<Clip>::Iter::kHead_IterStart);
x += fBmp.width() + kMargin; 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) { y = 0;
static const char kTxt[] = "Clip Me!"; startX += 2 * fBmp.width() + SkScalarCeilToInt(2 * textW) + 6 * kMargin;
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;
} }
} }
@ -242,6 +270,20 @@ private:
ClipType getType() const { return fClipType; } 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: private:
ClipType fClipType; ClipType fClipType;
SkPath fPath; SkPath fPath;

Просмотреть файл

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

18
gm/gm.h
Просмотреть файл

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

Просмотреть файл

@ -386,7 +386,9 @@ SkGMSampleViewFactory::SkGMSampleViewFactory(GMFactoryFunc func)
} }
SkView* SkGMSampleViewFactory::operator() () const { 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; SkViewRegister* SkViewRegister::gHead;

Просмотреть файл

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

Просмотреть файл

@ -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 || if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
!path.isConvex() || !path.isConvex() ||
path.isInverseFillType()) { path.isInverseFillType()) {
@ -114,6 +114,13 @@ GrEffectRef* GrConvexPolyEffect::Create(EdgeType type, const SkPath& path) {
SkPath::Direction dir; SkPath::Direction dir;
SkAssertResult(path.cheapComputeDirection(&dir)); SkAssertResult(path.cheapComputeDirection(&dir));
SkVector t;
if (NULL == offset) {
t.set(0, 0);
} else {
t = *offset;
}
int count = path.getPoints(pts, kMaxEdges); int count = path.getPoints(pts, kMaxEdges);
int n = 0; int n = 0;
for (int lastPt = count - 1, i = 0; i < count; lastPt = i++) { 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] = -v.fY;
edges[3 * n + 1] = v.fX; 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; ++n;
} }
} }

Просмотреть файл

@ -57,9 +57,10 @@ public:
/** /**
* Creates an effect that clips against the path. If the path is not a convex polygon, is * 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(); virtual ~GrConvexPolyEffect();