| Index: src/core/SkRemote.cpp
|
| diff --git a/src/core/SkRemote.cpp b/src/core/SkRemote.cpp
|
| index 7c662d323343e90798f79c8a9a495825fd09448c..21fbdf3d978a078077f2bcba953545f11874d5c7 100644
|
| --- a/src/core/SkRemote.cpp
|
| +++ b/src/core/SkRemote.cpp
|
| @@ -72,210 +72,141 @@ namespace SkRemote {
|
|
|
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
|
| - class LookupScope {
|
| + class CachingEncoder final : public Encoder {
|
| public:
|
| - LookupScope(Cache* cache, Encoder* encoder) : fCache(cache), fEncoder(encoder) {}
|
| - ~LookupScope() { for (ID id : fToUndefine) { fEncoder->undefine(id); } }
|
| - void undefineWhenDone(ID id) { fToUndefine.push_back(id); }
|
| -
|
| - template <typename T>
|
| - ID lookup(const T& val) {
|
| - ID id;
|
| - if (!fCache->lookup(val, &id, this)) {
|
| - fEncoder->define(id, val);
|
| - }
|
| - return id;
|
| - }
|
| + explicit CachingEncoder(Encoder* wrapped) : fWrapped(wrapped) {}
|
|
|
| private:
|
| - Cache* fCache;
|
| - Encoder* fEncoder;
|
| - SkSTArray<4, ID> fToUndefine;
|
| - };
|
| + struct Undef {
|
| + Encoder* fEncoder;
|
| + template <typename T>
|
| + void operator()(const T&, ID* id) const { fEncoder->undefine(*id); }
|
| + };
|
|
|
| + ~CachingEncoder() override {
|
| + Undef undef{fWrapped};
|
| + fMatrix .foreach(undef);
|
| + fMisc .foreach(undef);
|
| + fPath .foreach(undef);
|
| + fStroke .foreach(undef);
|
| + fShader .foreach(undef);
|
| + fXfermode.foreach(undef);
|
| + }
|
|
|
| - Cache* Cache::CreateNeverCache() {
|
| - struct NeverCache final : public Cache {
|
| - NeverCache()
|
| - : fNextMatrix (Type::kMatrix)
|
| - , fNextMisc (Type::kMisc)
|
| - , fNextPath (Type::kPath)
|
| - , fNextStroke (Type::kStroke)
|
| - , fNextShader (Type::kShader)
|
| - , fNextXfermode(Type::kXfermode)
|
| - {}
|
| - void cleanup(Encoder*) override {}
|
| -
|
| - static bool Helper(ID* next, ID* id, LookupScope* ls) {
|
| - *id = ++(*next);
|
| - ls->undefineWhenDone(*id);
|
| - return false;
|
| + template <typename Map, typename T>
|
| + ID define(Map* map, const T& v) {
|
| + if (const ID* id = map->find(v)) {
|
| + return *id;
|
| }
|
| + ID id = fWrapped->define(v);
|
| + map->set(v, id);
|
| + return id;
|
| + }
|
|
|
| - bool lookup(const SkMatrix&, ID* id, LookupScope* ls) override {
|
| - return Helper(&fNextMatrix, id, ls);
|
| - }
|
| - bool lookup(const Misc&, ID* id, LookupScope* ls) override {
|
| - return Helper(&fNextMisc, id, ls);
|
| - }
|
| - bool lookup(const SkPath&, ID* id, LookupScope* ls) override {
|
| - return Helper(&fNextPath, id, ls);
|
| - }
|
| - bool lookup(const Stroke&, ID* id, LookupScope* ls) override {
|
| - return Helper(&fNextStroke, id, ls);
|
| - }
|
| - bool lookup(const SkShader* shader, ID* id, LookupScope* ls) override {
|
| - if (!shader) {
|
| - *id = ID(Type::kShader);
|
| - return true; // Null IDs are always defined.
|
| - }
|
| - return Helper(&fNextShader, id, ls);
|
| - }
|
| - bool lookup(const SkXfermode* xfermode, ID* id, LookupScope* ls) override {
|
| - if (!xfermode) {
|
| - *id = ID(Type::kXfermode);
|
| - return true; // Null IDs are always defined.
|
| - }
|
| - return Helper(&fNextXfermode, id, ls);
|
| - }
|
| + ID define(const SkMatrix& v) override { return this->define(&fMatrix, v); }
|
| + ID define(const Misc& v) override { return this->define(&fMisc, v); }
|
| + ID define(const SkPath& v) override { return this->define(&fPath, v); }
|
| + ID define(const Stroke& v) override { return this->define(&fStroke, v); }
|
| + ID define(SkShader* v) override { return this->define(&fShader, v); }
|
| + ID define(SkXfermode* v) override { return this->define(&fXfermode, v); }
|
|
|
| - ID fNextMatrix,
|
| - fNextMisc,
|
| - fNextPath,
|
| - fNextStroke,
|
| - fNextShader,
|
| - fNextXfermode;
|
| - };
|
| - return new NeverCache;
|
| - }
|
| + void undefine(ID) override {}
|
|
|
| - // These can't be declared locally inside AlwaysCache because of the templating. :(
|
| - namespace {
|
| - template <typename T, typename Map>
|
| - static bool always_cache_lookup(const T& val, Map* map, ID* next, ID* id) {
|
| - if (const ID* found = map->find(val)) {
|
| - *id = *found;
|
| - return true;
|
| - }
|
| - *id = ++(*next);
|
| - map->set(val, *id);
|
| - return false;
|
| - }
|
| + void save() override { fWrapped-> save(); }
|
| + void restore() override { fWrapped->restore(); }
|
|
|
| - struct Undefiner {
|
| - Encoder* fEncoder;
|
| + void setMatrix(ID matrix) override { fWrapped->setMatrix(matrix); }
|
|
|
| - template <typename T>
|
| - void operator()(const T&, ID* id) const { fEncoder->undefine(*id); }
|
| - };
|
| + void clipPath(ID path, SkRegion::Op op, bool aa) override {
|
| + fWrapped->clipPath(path, op, aa);
|
| + }
|
| + void fillPath(ID path, ID misc, ID shader, ID xfermode) override {
|
| + fWrapped->fillPath(path, misc, shader, xfermode);
|
| + }
|
| + void strokePath(ID path, ID misc, ID shader, ID xfermode, ID stroke) override {
|
| + fWrapped->strokePath(path, misc, shader, xfermode, stroke);
|
| + }
|
|
|
| - // Maps const T* -> ID, and refs the key. nullptr always maps to ID(kType).
|
| + // Maps const T* -> ID, and refs the key.
|
| template <typename T, Type kType>
|
| class RefKeyMap {
|
| public:
|
| RefKeyMap() {}
|
| - ~RefKeyMap() { fMap.foreach([](const T* key, ID*) { key->unref(); }); }
|
| + ~RefKeyMap() { fMap.foreach([](const T* key, ID*) { SkSafeUnref(key); }); }
|
|
|
| - void set(const T* key, const ID& id) {
|
| - SkASSERT(key && id.type() == kType);
|
| - fMap.set(SkRef(key), id);
|
| + void set(const T* key, ID id) {
|
| + SkASSERT(id.type() == kType);
|
| + fMap.set(SkSafeRef(key), id);
|
| }
|
|
|
| void remove(const T* key) {
|
| - SkASSERT(key);
|
| fMap.remove(key);
|
| - key->unref();
|
| + SkSafeUnref(key);
|
| }
|
|
|
| const ID* find(const T* key) const {
|
| - static const ID nullID(kType);
|
| - return key ? fMap.find(key) : &nullID;
|
| + return fMap.find(key);
|
| }
|
|
|
| template <typename Fn>
|
| - void foreach(const Fn& fn) { fMap.foreach(fn); }
|
| + void foreach(const Fn& fn) {
|
| + fMap.foreach(fn);
|
| + }
|
| private:
|
| SkTHashMap<const T*, ID> fMap;
|
| };
|
| - } // namespace
|
| -
|
| - Cache* Cache::CreateAlwaysCache() {
|
| - struct AlwaysCache final : public Cache {
|
| - AlwaysCache()
|
| - : fNextMatrix (Type::kMatrix)
|
| - , fNextMisc (Type::kMisc)
|
| - , fNextPath (Type::kPath)
|
| - , fNextStroke (Type::kStroke)
|
| - , fNextShader (Type::kShader)
|
| - , fNextXfermode(Type::kXfermode)
|
| - {}
|
| -
|
| - void cleanup(Encoder* encoder) override {
|
| - Undefiner undef{encoder};
|
| - fMatrix .foreach(undef);
|
| - fMisc .foreach(undef);
|
| - fPath .foreach(undef);
|
| - fStroke .foreach(undef);
|
| - fShader .foreach(undef);
|
| - fXfermode.foreach(undef);
|
| - }
|
|
|
| + SkTHashMap<SkMatrix, ID> fMatrix;
|
| + SkTHashMap<Misc, ID, MiscHash> fMisc;
|
| + SkTHashMap<SkPath, ID> fPath;
|
| + SkTHashMap<Stroke, ID> fStroke;
|
| + RefKeyMap<SkShader, Type::kShader> fShader;
|
| + RefKeyMap<SkXfermode, Type::kXfermode> fXfermode;
|
|
|
| - bool lookup(const SkMatrix& matrix, ID* id, LookupScope*) override {
|
| - return always_cache_lookup(matrix, &fMatrix, &fNextMatrix, id);
|
| - }
|
| - bool lookup(const Misc& misc, ID* id, LookupScope*) override {
|
| - return always_cache_lookup(misc, &fMisc, &fNextMisc, id);
|
| - }
|
| - bool lookup(const SkPath& path, ID* id, LookupScope*) override {
|
| - return always_cache_lookup(path, &fPath, &fNextPath, id);
|
| - }
|
| - bool lookup(const Stroke& stroke, ID* id, LookupScope*) override {
|
| - return always_cache_lookup(stroke, &fStroke, &fNextStroke, id);
|
| - }
|
| - bool lookup(const SkShader* shader, ID* id, LookupScope*) override {
|
| - return always_cache_lookup(shader, &fShader, &fNextShader, id);
|
| - }
|
| - bool lookup(const SkXfermode* xfermode, ID* id, LookupScope*) override {
|
| - return always_cache_lookup(xfermode, &fXfermode, &fNextXfermode, id);
|
| - }
|
| + Encoder* fWrapped;
|
| + };
|
|
|
| - SkTHashMap<SkMatrix, ID> fMatrix;
|
| - SkTHashMap<Misc, ID, MiscHash> fMisc;
|
| - SkTHashMap<SkPath, ID> fPath;
|
| - SkTHashMap<Stroke, ID> fStroke;
|
| - RefKeyMap<SkShader, Type::kShader> fShader;
|
| - RefKeyMap<SkXfermode, Type::kXfermode> fXfermode;
|
| -
|
| - ID fNextMatrix,
|
| - fNextMisc,
|
| - fNextPath,
|
| - fNextStroke,
|
| - fNextShader,
|
| - fNextXfermode;
|
| - };
|
| - return new AlwaysCache;
|
| - }
|
| + Encoder* Encoder::CreateCachingEncoder(Encoder* wrapped) { return new CachingEncoder(wrapped); }
|
| +
|
| + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
| +
|
| + // Calls Encoder::define() when created, Encoder::undefine() when destroyed.
|
| + class Client::AutoID : ::SkNoncopyable {
|
| + public:
|
| + template <typename T>
|
| + explicit AutoID(Encoder* encoder, const T& val)
|
| + : fEncoder(encoder)
|
| + , fID(encoder->define(val)) {}
|
| + ~AutoID() { if (fEncoder) fEncoder->undefine(fID); }
|
| +
|
| + AutoID(AutoID&& o) : fEncoder(o.fEncoder), fID(o.fID) {
|
| + o.fEncoder = nullptr;
|
| + }
|
| + AutoID& operator=(AutoID&&) = delete;
|
| +
|
| + operator ID () const { return fID; }
|
| +
|
| + private:
|
| + Encoder* fEncoder;
|
| + const ID fID;
|
| + };
|
| +
|
| + template <typename T>
|
| + Client::AutoID Client::id(const T& val) { return AutoID(fEncoder, val); }
|
|
|
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
|
| - Client::Client(Cache* cache, Encoder* encoder)
|
| + Client::Client(Encoder* encoder)
|
| : SkCanvas(1,1)
|
| - , fCache(cache)
|
| , fEncoder(encoder)
|
| {}
|
|
|
| - Client::~Client() {
|
| - fCache->cleanup(fEncoder);
|
| - }
|
| -
|
| void Client::willSave() { fEncoder->save(); }
|
| void Client::didRestore() { fEncoder->restore(); }
|
|
|
| void Client::didConcat (const SkMatrix&) { this->didSetMatrix(this->getTotalMatrix()); }
|
| void Client::didSetMatrix(const SkMatrix& matrix) {
|
| - LookupScope ls(fCache, fEncoder);
|
| - fEncoder->setMatrix(ls.lookup(matrix));
|
| + fEncoder->setMatrix(this->id(matrix));
|
| }
|
|
|
| void Client::onDrawOval(const SkRect& oval, const SkPaint& paint) {
|
| @@ -306,17 +237,16 @@ namespace SkRemote {
|
| }
|
|
|
| void Client::onDrawPath(const SkPath& path, const SkPaint& paint) {
|
| - LookupScope ls(fCache, fEncoder);
|
| - ID p = ls.lookup(path),
|
| - m = ls.lookup(Misc::CreateFrom(paint)),
|
| - s = ls.lookup(paint.getShader()),
|
| - x = ls.lookup(paint.getXfermode());
|
| + auto p = this->id(path),
|
| + m = this->id(Misc::CreateFrom(paint)),
|
| + s = this->id(paint.getShader()),
|
| + x = this->id(paint.getXfermode());
|
|
|
| if (paint.getStyle() == SkPaint::kFill_Style) {
|
| fEncoder->fillPath(p, m, s, x);
|
| } else {
|
| // TODO: handle kStrokeAndFill_Style
|
| - fEncoder->strokePath(p, m, s, x, ls.lookup(Stroke::CreateFrom(paint)));
|
| + fEncoder->strokePath(p, m, s, x, this->id(Stroke::CreateFrom(paint)));
|
| }
|
| }
|
|
|
| @@ -368,20 +298,26 @@ namespace SkRemote {
|
| }
|
|
|
| void Client::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
|
| - LookupScope ls(fCache, fEncoder);
|
| - fEncoder->clipPath(ls.lookup(path), op, edgeStyle == kSoft_ClipEdgeStyle);
|
| + fEncoder->clipPath(this->id(path), op, edgeStyle == kSoft_ClipEdgeStyle);
|
| }
|
|
|
| // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
|
| Server::Server(SkCanvas* canvas) : fCanvas(canvas) {}
|
|
|
| - void Server::define(ID id, const SkMatrix& v) { fMatrix .set(id, v); }
|
| - void Server::define(ID id, const Misc& v) { fMisc .set(id, v); }
|
| - void Server::define(ID id, const SkPath& v) { fPath .set(id, v); }
|
| - void Server::define(ID id, const Stroke& v) { fStroke .set(id, v); }
|
| - void Server::define(ID id, SkShader* v) { fShader .set(id, v); }
|
| - void Server::define(ID id, SkXfermode* v) { fXfermode.set(id, v); }
|
| + template <typename Map, typename T>
|
| + ID Server::define(Type type, Map* map, const T& val) {
|
| + ID id(type, fNextID++);
|
| + map->set(id, val);
|
| + return id;
|
| + }
|
| +
|
| + ID Server::define(const SkMatrix& v) { return this->define(Type::kMatrix, &fMatrix, v); }
|
| + ID Server::define(const Misc& v) { return this->define(Type::kMisc, &fMisc, v); }
|
| + ID Server::define(const SkPath& v) { return this->define(Type::kPath, &fPath, v); }
|
| + ID Server::define(const Stroke& v) { return this->define(Type::kStroke, &fStroke, v); }
|
| + ID Server::define(SkShader* v) { return this->define(Type::kShader, &fShader, v); }
|
| + ID Server::define(SkXfermode* v) { return this->define(Type::kXfermode, &fXfermode, v); }
|
|
|
| void Server::undefine(ID id) {
|
| switch(id.type()) {
|
| @@ -391,8 +327,6 @@ namespace SkRemote {
|
| case Type::kStroke: return fStroke .remove(id);
|
| case Type::kShader: return fShader .remove(id);
|
| case Type::kXfermode: return fXfermode.remove(id);
|
| -
|
| - case Type::kNone: SkASSERT(false);
|
| };
|
| }
|
|
|
|
|