diff options
-rw-r--r-- | include/core/SkCanvas.h | 4 | ||||
-rw-r--r-- | include/utils/SkNoDrawCanvas.h | 2 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 56 | ||||
-rw-r--r-- | src/core/SkDevice.h | 66 | ||||
-rw-r--r-- | tools/remote_demo.cpp | 59 |
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( |