aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2015-10-21 10:46:02 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-10-21 10:46:02 -0700
commitb6b8f2727f6b08bbc307aeebac23beeba1e4984f (patch)
tree99bd4ea9af4e0a206b6f84c1baf2036d3e217526 /src
parent0d3f061262a53b775f0a92b0abf8a4a846290d65 (diff)
SkRemote: refactoring
- Cache becomes CachingEncoder that wraps another Encoder - Encoders provide IDs - syntaxy improvements to Client - ID isn't really protocol sensitive. - I don't think we need Type::kNone. No diffs. https://gold.skia.org/search2?issue=1418863002&unt=true&query=source_type%3Dgm&master=false&include=true BUG=skia: Review URL: https://codereview.chromium.org/1418863002
Diffstat (limited to 'src')
-rw-r--r--src/core/SkRemote.cpp284
-rw-r--r--src/core/SkRemote.h109
-rw-r--r--src/core/SkRemote_protocol.h26
3 files changed, 162 insertions, 257 deletions
diff --git a/src/core/SkRemote.cpp b/src/core/SkRemote.cpp
index 7c662d3233..21fbdf3d97 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);
};
}
diff --git a/src/core/SkRemote.h b/src/core/SkRemote.h
index 6e95f3a158..cbfcf9b381 100644
--- a/src/core/SkRemote.h
+++ b/src/core/SkRemote.h
@@ -18,7 +18,26 @@
// TODO: document
namespace SkRemote {
- // TODO: document
+
+ // General purpose identifier. Holds a Type and a 56-bit value.
+ class ID {
+ public:
+ ID() {}
+ ID(Type type, uint64_t val) {
+ fVal = (uint64_t)type << 56 | val;
+ SkASSERT(this->type() == type && this->val() == val);
+ }
+
+ Type type() const { return (Type)(fVal >> 56); }
+ uint64_t val() const { return fVal & ~((uint64_t)0xFF << 56); }
+
+ bool operator==(ID o) const { return fVal == o.fVal; }
+
+ private:
+ uint64_t fVal;
+ };
+
+ // Fields from SkPaint used by stroke, fill, and text draws.
struct Misc {
SkColor fColor;
SkFilterQuality fFilterQuality;
@@ -28,7 +47,7 @@ namespace SkRemote {
void applyTo(SkPaint*) const;
};
- // TODO: document
+ // Fields from SkPaint used by stroke draws only.
struct Stroke {
SkScalar fWidth, fMiter;
SkPaint::Cap fCap;
@@ -42,12 +61,14 @@ namespace SkRemote {
struct Encoder {
virtual ~Encoder() {}
- virtual void define(ID, const SkMatrix&) = 0;
- virtual void define(ID, const Misc&) = 0;
- virtual void define(ID, const SkPath&) = 0;
- virtual void define(ID, const Stroke&) = 0;
- virtual void define(ID, SkShader*) = 0;
- virtual void define(ID, SkXfermode*) = 0;
+ static Encoder* CreateCachingEncoder(Encoder*);
+
+ virtual ID define(const SkMatrix&) = 0;
+ virtual ID define(const Misc&) = 0;
+ virtual ID define(const SkPath&) = 0;
+ virtual ID define(const Stroke&) = 0;
+ virtual ID define(SkShader*) = 0;
+ virtual ID define(SkXfermode*) = 0;
virtual void undefine(ID) = 0;
@@ -64,41 +85,17 @@ namespace SkRemote {
virtual void strokePath(ID path, ID misc, ID shader, ID xfermode, ID stroke) = 0;
};
- class LookupScope;
-
- // The Cache interface encapsulates the caching logic of the Client.
- //
- // Each lookup() method must always fill ID* with a valid value,
- // but ID may be cached. If so, the lookup() method returns true;
- // if not the lookup() method returns false and the Client must
- // then define() this ID -> Thing mapping before using the ID.
- //
- // The Caches may also add IDs to the LookupScope's list of IDs to
- // undefine() on destruction. This lets the Cache purge IDs.
- struct Cache {
- virtual ~Cache() {}
-
- static Cache* CreateNeverCache(); // Never caches anything.
- static Cache* CreateAlwaysCache(); // Caches by value (not deep pointer equality).
- // TODO: static Cache* CreateDeepCache(); // Caches by deep value.
-
- virtual bool lookup(const SkMatrix&, ID*, LookupScope*) = 0;
- virtual bool lookup(const Misc&, ID*, LookupScope*) = 0;
- virtual bool lookup(const SkPath&, ID*, LookupScope*) = 0;
- virtual bool lookup(const Stroke&, ID*, LookupScope*) = 0;
- virtual bool lookup(const SkShader*, ID*, LookupScope*) = 0;
- virtual bool lookup(const SkXfermode*, ID*, LookupScope*) = 0;
-
- virtual void cleanup(Encoder*) = 0;
- };
-
- // TODO: document
+ // An SkCanvas that translates to Encoder calls.
class Client final : public SkCanvas {
public:
- Client(Cache*, Encoder*);
- ~Client();
+ explicit Client(Encoder*);
private:
+ class AutoID;
+
+ template <typename T>
+ AutoID id(const T&);
+
void willSave() override;
void didRestore() override;
@@ -123,22 +120,21 @@ namespace SkRemote {
void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar,
const SkPaint&) override;
- Cache* fCache;
Encoder* fEncoder;
};
- // TODO: document
+ // An Encoder that translates back to SkCanvas calls.
class Server final : public Encoder {
public:
explicit Server(SkCanvas*);
private:
- void define(ID, const SkMatrix&) override;
- void define(ID, const Misc&) override;
- void define(ID, const SkPath&) override;
- void define(ID, const Stroke&) override;
- void define(ID, SkShader*) override;
- void define(ID, SkXfermode*) override;
+ ID define(const SkMatrix&) override;
+ ID define(const Misc&) override;
+ ID define(const SkPath&) override;
+ ID define(const Stroke&) override;
+ ID define(SkShader*) override;
+ ID define(SkXfermode*) override;
void undefine(ID) override;
@@ -185,25 +181,22 @@ namespace SkRemote {
template <typename T, Type kType>
class ReffedIDMap {
public:
- ReffedIDMap() {
- // A null ID always maps to nullptr.
- fMap.set(ID(kType), nullptr);
- }
+ ReffedIDMap() {}
~ReffedIDMap() {
// A well-behaved client always cleans up its definitions.
- SkASSERT(fMap.count() == 1);
+ SkASSERT(fMap.count() == 0);
}
void set(const ID& id, T* val) {
- SkASSERT(id.type() == kType && val);
- fMap.set(id, SkRef(val));
+ SkASSERT(id.type() == kType);
+ fMap.set(id, SkSafeRef(val));
}
void remove(const ID& id) {
SkASSERT(id.type() == kType);
T** val = fMap.find(id);
- SkASSERT(val && *val);
- (*val)->unref();
+ SkASSERT(val);
+ SkSafeUnref(*val);
fMap.remove(id);
}
@@ -218,6 +211,9 @@ namespace SkRemote {
SkTHashMap<ID, T*> fMap;
};
+ template <typename Map, typename T>
+ ID define(Type, Map*, const T&);
+
IDMap<SkMatrix, Type::kMatrix> fMatrix;
IDMap<Misc , Type::kMisc > fMisc;
IDMap<SkPath , Type::kPath > fPath;
@@ -226,6 +222,7 @@ namespace SkRemote {
ReffedIDMap<SkXfermode, Type::kXfermode> fXfermode;
SkCanvas* fCanvas;
+ uint64_t fNextID = 0;
};
} // namespace SkRemote
diff --git a/src/core/SkRemote_protocol.h b/src/core/SkRemote_protocol.h
index d34a4b6c4b..b89d491379 100644
--- a/src/core/SkRemote_protocol.h
+++ b/src/core/SkRemote_protocol.h
@@ -15,8 +15,6 @@ namespace SkRemote {
// It is safe to append to this enum without breaking protocol compatibility.
// Resorting, deleting, or inserting anywhere but the end will break compatibility.
enum class Type : uint8_t {
- kNone,
-
kMatrix,
kMisc,
kPath,
@@ -25,30 +23,6 @@ namespace SkRemote {
kXfermode,
};
- class ID {
- public:
- explicit ID(Type type = Type::kNone) : fVal((uint64_t)type << 56) {}
- ID(Type type, uint64_t val) {
- fVal = (uint64_t)type << 56 | val;
- SkASSERT(this->type() == type && this->val() == val);
- }
-
- Type type() const { return (Type)(fVal >> 56); }
- uint64_t val() const { return fVal & ~((uint64_t)0xFF << 56); }
-
- bool operator==(ID o) const { return fVal == o.fVal; }
- ID operator++() {
- ++fVal;
- SkASSERT(this->val() != 0); // Overflow is particularly bad as it'd change our Type.
- return *this;
- }
-
- private:
- // High 8 bits hold a Type. Low 56 bits are unique within that Type.
- // Any change to this format will break protocol compatibility.
- uint64_t fVal;
- };
-
} // namespace SkRemote
#endif//SkRemote_protocol_DEFINED