aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Herb Derby <herb@google.com>2018-03-15 17:34:40 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-16 20:28:36 +0000
commit76d69b44bbba118a6769b5fb267588ccac41a815 (patch)
tree2fdb871fb4f7ae9b00721661cd3fa361ba4cbfbd
parent7278d68cac9e39970144909df449113d43fff480 (diff)
Apply filterTextFlags so the fonts are the same.
In order to apply filterTextFlags correctly, teach TrackLayerDevice how to process save and restore layers. At this point, I don't see any other traffic than the cache warming traffic. This code has a performance between 82% and 105% of just drawing the picture. BUG=skia:7515 Change-Id: I44736be46884f18b6d120d4b5ca582f34dbdff0f Reviewed-on: https://skia-review.googlesource.com/114641 Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Herb Derby <herb@google.com>
-rw-r--r--include/core/SkCanvas.h4
-rw-r--r--include/utils/SkNoDrawCanvas.h2
-rw-r--r--src/core/SkCanvas.cpp56
-rw-r--r--src/core/SkDevice.h66
-rw-r--r--tools/remote_demo.cpp59
5 files changed, 118 insertions, 69 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index a426d1e546..e90408dc33 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -2445,6 +2445,7 @@ public:
void private_draw_shadow_rec(const SkPath&, const SkDrawShadowRec&);
+
protected:
// default impl defers to getDevice()->newSurface(info)
virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props);
@@ -2559,6 +2560,8 @@ protected:
bool clipRectBounds(const SkRect* bounds, SaveLayerFlags flags, SkIRect* intersection,
const SkImageFilter* imageFilter = nullptr);
+ SkBaseDevice* getTopDevice() const;
+
private:
/** After calling saveLayer(), there can be any number of devices that make
up the top-most drawing area. LayerIter can be used to iterate through
@@ -2620,7 +2623,6 @@ private:
}
SkBaseDevice* getDevice() const;
- SkBaseDevice* getTopDevice() const;
class MCRec;
diff --git a/include/utils/SkNoDrawCanvas.h b/include/utils/SkNoDrawCanvas.h
index 7475956704..4c67226946 100644
--- a/include/utils/SkNoDrawCanvas.h
+++ b/include/utils/SkNoDrawCanvas.h
@@ -29,6 +29,8 @@ public:
// TODO: investigate the users of this ctor.
SkNoDrawCanvas(const SkIRect&);
+ explicit SkNoDrawCanvas(SkBaseDevice* device);
+
// Optimization to reset state to be the same as after construction.
void resetCanvas(int width, int height) {
resetForNextPicture(SkIRect::MakeWH(width, height));
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 2f31335286..24a6d4ab26 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -52,58 +52,6 @@
#define RETURN_ON_NULL(ptr) do { if (nullptr == (ptr)) return; } while (0)
#define RETURN_ON_FALSE(pred) do { if (!(pred)) return; } while (0)
-class SkNoPixelsDevice : public SkBaseDevice {
-public:
- SkNoPixelsDevice(const SkIRect& bounds, const SkSurfaceProps& props)
- : SkBaseDevice(SkImageInfo::MakeUnknown(bounds.width(), bounds.height()), props)
- {
- // this fails if we enable this assert: DiscardableImageMapTest.GetDiscardableImagesInRectMaxImage
- //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
- }
-
- void resetForNextPicture(const SkIRect& bounds) {
- //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
- this->privateResize(bounds.width(), bounds.height());
- }
-
-protected:
- // We don't track the clip at all (for performance), but we have to respond to some queries.
- // We pretend to be wide-open. We could pretend to always be empty, but that *seems* worse.
- void onSave() override {}
- void onRestore() override {}
- void onClipRect(const SkRect& rect, SkClipOp, bool aa) override {}
- void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override {}
- void onClipPath(const SkPath& path, SkClipOp, bool aa) override {}
- void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override {}
- void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override {}
- bool onClipIsAA() const override { return false; }
- void onAsRgnClip(SkRegion* rgn) const override {
- rgn->setRect(SkIRect::MakeWH(this->width(), this->height()));
- }
- ClipType onGetClipType() const override {
- return kRect_ClipType;
- }
-
- void drawPaint(const SkPaint& paint) override {}
- void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override {}
- void drawRect(const SkRect&, const SkPaint&) override {}
- void drawOval(const SkRect&, const SkPaint&) override {}
- void drawRRect(const SkRRect&, const SkPaint&) override {}
- void drawPath(const SkPath&, const SkPaint&, const SkMatrix*, bool) override {}
- void drawBitmap(const SkBitmap&, SkScalar x, SkScalar y, const SkPaint&) override {}
- void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
- void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
- SkCanvas::SrcRectConstraint) override {}
- void drawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override {}
- void drawPosText(const void*, size_t, const SkScalar[], int, const SkPoint&,
- const SkPaint&) override {}
- void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override {}
- void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override {}
-
-private:
- typedef SkBaseDevice INHERITED;
-};
-
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
@@ -974,7 +922,6 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlag
return true;
}
-
int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
return this->saveLayer(SaveLayerRec(bounds, paint, 0));
}
@@ -2907,6 +2854,9 @@ SkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
SkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
: INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
+SkNoDrawCanvas::SkNoDrawCanvas(SkBaseDevice *device)
+ : INHERITED(device) {}
+
SkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
(void)this->INHERITED::getSaveLayerStrategy(rec);
return kNoLayer_SaveLayerStrategy;
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index c7b993cf22..6739230115 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -11,6 +11,7 @@
#include "SkRefCnt.h"
#include "SkCanvas.h"
#include "SkColor.h"
+#include "SkRegion.h"
#include "SkSurfaceProps.h"
class SkBitmap;
@@ -20,7 +21,6 @@ class SkImageFilterCache;
struct SkIRect;
class SkMatrix;
class SkRasterHandleAllocator;
-class SkRegion;
class SkSpecialImage;
class SkBaseDevice : public SkRefCnt {
@@ -125,6 +125,12 @@ public:
void setGlobalCTM(const SkMatrix& ctm);
virtual void validateDevBounds(const SkIRect&) {}
+ /**
+ * Returns the text-related flags, possibly modified based on the state of the
+ * device (e.g. support for LCD).
+ */
+ uint32_t filterTextFlags(const SkPaint&) const;
+
protected:
enum TileUsage {
kPossible_TileUsage, //!< the created device may be drawn tiled
@@ -135,12 +141,6 @@ protected:
uint32_t fFlags; // SkPaint::getFlags()
};
- /**
- * Returns the text-related flags, possibly modified based on the state of the
- * device (e.g. support for LCD).
- */
- uint32_t filterTextFlags(const SkPaint&) const;
-
virtual bool onShouldDisableLCD(const SkPaint&) const { return false; }
virtual void onSave() {}
@@ -390,6 +390,58 @@ private:
typedef SkRefCnt INHERITED;
};
+class SkNoPixelsDevice : public SkBaseDevice {
+public:
+ SkNoPixelsDevice(const SkIRect& bounds, const SkSurfaceProps& props)
+ : SkBaseDevice(SkImageInfo::MakeUnknown(bounds.width(), bounds.height()), props)
+ {
+ // this fails if we enable this assert: DiscardableImageMapTest.GetDiscardableImagesInRectMaxImage
+ //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
+ }
+
+ void resetForNextPicture(const SkIRect& bounds) {
+ //SkASSERT(bounds.width() >= 0 && bounds.height() >= 0);
+ this->privateResize(bounds.width(), bounds.height());
+ }
+
+protected:
+ // We don't track the clip at all (for performance), but we have to respond to some queries.
+ // We pretend to be wide-open. We could pretend to always be empty, but that *seems* worse.
+ void onSave() override {}
+ void onRestore() override {}
+ void onClipRect(const SkRect& rect, SkClipOp, bool aa) override {}
+ void onClipRRect(const SkRRect& rrect, SkClipOp, bool aa) override {}
+ void onClipPath(const SkPath& path, SkClipOp, bool aa) override {}
+ void onClipRegion(const SkRegion& deviceRgn, SkClipOp) override {}
+ void onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) override {}
+ bool onClipIsAA() const override { return false; }
+ void onAsRgnClip(SkRegion* rgn) const override {
+ rgn->setRect(SkIRect::MakeWH(this->width(), this->height()));
+ }
+ ClipType onGetClipType() const override {
+ return kRect_ClipType;
+ }
+
+ void drawPaint(const SkPaint& paint) override {}
+ void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override {}
+ void drawRect(const SkRect&, const SkPaint&) override {}
+ void drawOval(const SkRect&, const SkPaint&) override {}
+ void drawRRect(const SkRRect&, const SkPaint&) override {}
+ void drawPath(const SkPath&, const SkPaint&, const SkMatrix*, bool) override {}
+ void drawBitmap(const SkBitmap&, SkScalar x, SkScalar y, const SkPaint&) override {}
+ void drawSprite(const SkBitmap&, int, int, const SkPaint&) override {}
+ void drawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint&,
+ SkCanvas::SrcRectConstraint) override {}
+ void drawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override {}
+ void drawPosText(const void*, size_t, const SkScalar[], int, const SkPoint&,
+ const SkPaint&) override {}
+ void drawDevice(SkBaseDevice*, int, int, const SkPaint&) override {}
+ void drawVertices(const SkVertices*, SkBlendMode, const SkPaint&) override {}
+
+private:
+ typedef SkBaseDevice INHERITED;
+};
+
class SkAutoDeviceCTMRestore : SkNoncopyable {
public:
SkAutoDeviceCTMRestore(SkBaseDevice* device, const SkMatrix& ctm)
diff --git a/tools/remote_demo.cpp b/tools/remote_demo.cpp
index b8cfdc76f7..8ff7d2986d 100644
--- a/tools/remote_demo.cpp
+++ b/tools/remote_demo.cpp
@@ -21,6 +21,7 @@
#include "SkTextBlobRunIterator.h"
#include "SkGlyphCache.h"
#include "SkDrawFilter.h"
+#include "SkDevice.h"
#include <type_traits>
#include <chrono>
@@ -51,8 +52,13 @@ static bool gUseGpu = true;
static bool gPurgeFontCaches = true;
static bool gUseProcess = true;
+static int gFontMetrics;
+static int gMetricsImage;
+static int gPath;
+
enum direction : int {kRead = 0, kWrite = 1};
+#define INSTRUMENT 0
template <typename T>
class SkArraySlice : public std::tuple<const T*, size_t> {
@@ -300,6 +306,18 @@ public:
};
};
+
+class TrackLayerDevice : public SkNoPixelsDevice {
+public:
+ TrackLayerDevice(const SkIRect& bounds, const SkSurfaceProps& props)
+ : SkNoPixelsDevice(bounds, props) { }
+ SkBaseDevice* onCreateDevice(const CreateInfo& cinfo, const SkPaint*) override {
+ const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
+ return new TrackLayerDevice(this->getGlobalBounds(), surfaceProps);
+ }
+};
+
+
class TextBlobFilterCanvas : public SkNoDrawCanvas {
public:
struct StrikeSpec {
@@ -323,7 +341,7 @@ public:
const SkMatrix& deviceMatrix,
const SkSurfaceProps& props,
SkScalerContextFlags flags)
- : SkNoDrawCanvas(width, height)
+ : SkNoDrawCanvas{new TrackLayerDevice{SkIRect::MakeWH(width, height), props}}
, fDeviceMatrix{deviceMatrix}
, fSurfaceProps{props}
, fScalerContextFlags{flags} { }
@@ -422,6 +440,10 @@ public:
protected:
+ SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override {
+ return kFullLayer_SaveLayerStrategy;
+ }
+
void onDrawTextBlob(
const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) override
{
@@ -433,6 +455,7 @@ protected:
// applyFontToPaint() always overwrites the exact same attributes,
// so it is safe to not re-seed the paint for this reason.
it.applyFontToPaint(&runPaint);
+ runPaint.setFlags(this->getTopDevice()->filterTextFlags(runPaint));
if (auto looper = runPaint.getLooper()) {
this->processLooper(position, it, runPaint, looper, this);
} else {
@@ -441,6 +464,16 @@ protected:
}
}
+ void onDrawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override {
+ SK_ABORT("DrawText");
+ }
+ void onDrawPosText(const void*, size_t, const SkPoint[], const SkPaint&) override {
+ SK_ABORT("DrawPosText");
+ }
+ void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) override {
+ SK_ABORT("DrawPosTextH");
+ }
+
private:
using PosFn = SkPoint(*)(int index, const SkScalar* pos);
using MapFn = SkPoint(*)(const SkMatrix& m, SkPoint pt);
@@ -633,13 +666,14 @@ public:
void generateFontMetrics(const SkTypefaceProxy& tf,
const SkScalerContextRec& rec,
SkPaint::FontMetrics* metrics) override {
+ gFontMetrics += 1;
//SK_ABORT("generateFontMetrics should not be called.");
// Send generateFontMetrics
Op* op = this->startOpWrite(OpCode::kFontMetrics, tf, rec);
fTransport->endWrite();
-#if 1
+#if INSTRUMENT
SkScalerContextRecDescriptor rd{rec};
std::cout << " metrics font op rec tf: " << rec.fFontID
<< " tf id: " << tf.fontID()
@@ -656,15 +690,16 @@ public:
const SkScalerContextRec& rec,
SkArenaAlloc* alloc,
SkGlyph* glyph) override {
+ gMetricsImage += 1;
//SK_ABORT("generateMetricsAndImage should not be called.");
// Send generateMetricsAndImage
SkScalerContextRecDescriptor rd{rec};
-#if 1
+#if INSTRUMENT
std::cout << " metrics image op rec tf: " << rec.fFontID
<< " tf id: " << tf.fontID()
<< " rec: " << rd.desc().getChecksum()
- << " glyphid: " << glyph->getPackedID().getPackedID()
+ << " glyphid: " << glyph->getPackedID().getPackedID() << "\n"
<< rec.dump().c_str() << std::endl;
#endif
Op* op = this->startOpWrite(OpCode::kGlyphMetricsAndImage, tf, rec);
@@ -690,6 +725,7 @@ public:
void generatePath(const SkTypefaceProxy& tf,
const SkScalerContextRec& rec,
SkGlyphID glyph, SkPath* path) override {
+ gPath += 1;
// Send generatePath
SkScalerContextRecDescriptor rd{rec};
@@ -722,7 +758,7 @@ static void prepopulate_cache(
sk_sp<SkPicture> pic,
TextBlobFilterCanvas* filter) {
- filter->drawPicture(pic);
+ pic->playback(filter);
transport->startEmplace<Op>(OpCode::kPrepopulateCache, SkFontID{0},
SkScalerContextRec{});
@@ -747,7 +783,7 @@ static void prepopulate_cache(
};
strike = SkGlyphCache::CreateStrikeExclusive(*desc,creator);
}
-#if 1
+#if INSTRUMENT
std::cout << std::hex << "prepop cache " << (intptr_t)cache
<< " desc: " << desc->getChecksum()
<< " typeface id: " << tf->uniqueID()
@@ -771,7 +807,9 @@ static void prepopulate_cache(
// needed for font metrics mistake.
Transport in = Transport::DoubleBuffer(*transport);
+#if INSTRUMENT
SkDebugf("========= Sending prep cache ========\n");
+#endif
in.startRead();
filter->readDataFromTransport(&in, perStrike, perGlyph, finishStrike);
@@ -797,7 +835,8 @@ static void final_draw(std::string outFilename,
SkMatrix deviceMatrix = SkMatrix::I();
// kFakeGammaAndBoostContrast
TextBlobFilterCanvas filter(
- r.width(), r.height(), deviceMatrix, s->props(), SkScalerContextFlags::kFakeGammaAndBoostContrast);
+ r.width(), r.height(), deviceMatrix, s->props(),
+ SkScalerContextFlags::kFakeGammaAndBoostContrast);
if (cache != nullptr) {
for (int i = 0; i < 0; i++) {
@@ -815,7 +854,7 @@ static void final_draw(std::string outFilename,
}
std::chrono::duration<double> total_seconds{0.0};
- for (int i = 0; i < 1; i++) { // 20
+ for (int i = 0; i < 100; i++) { // 20
if (gPurgeFontCaches) {
SkGraphics::PurgeFontCache();
}
@@ -860,6 +899,10 @@ static void gpu(int readFd, int writeFd) {
rc.prepareDeserializeProcs(&procs);
final_draw("test.png", &transport, &procs, picData.get(), &rc);
+
+ if (gFontMetrics + gMetricsImage + gPath > 0) {
+ fprintf(stderr, "exceptions - fm: %d mi: %d p: %d\n", gFontMetrics, gMetricsImage, gPath);
+ }
}
static int renderer(