Add glyph cache warming - prototype
A system for prewarming the cache using a single "RPC" This improve performance by ~5X. This is a checkin of rough code so I can use small changes clean it up. BUG=skia:7515 Change-Id: Id0192b4f533c257b0a7eea0170b1e25c336d6432 Reviewed-on: https://skia-review.googlesource.com/105440 Reviewed-by: Herb Derby <herb@google.com> Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Herb Derby <herb@google.com> Commit-Queue: Mike Klein <mtklein@chromium.org>
This commit is contained in:
parent
8b6a9ae701
commit
67c47f2329
@ -25,6 +25,7 @@ void SkRemoteGlyphCacheRenderer::prepareSerializeProcs(SkSerialProcs* procs) {
|
|||||||
SkScalerContext* SkRemoteGlyphCacheRenderer::generateScalerContext(
|
SkScalerContext* SkRemoteGlyphCacheRenderer::generateScalerContext(
|
||||||
const SkScalerContextRecDescriptor& desc, SkFontID typefaceId)
|
const SkScalerContextRecDescriptor& desc, SkFontID typefaceId)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto scaler = fScalerContextMap.find(desc);
|
auto scaler = fScalerContextMap.find(desc);
|
||||||
if (scaler == nullptr) {
|
if (scaler == nullptr) {
|
||||||
auto typefaceIter = fTypefaceMap.find(typefaceId);
|
auto typefaceIter = fTypefaceMap.find(typefaceId);
|
||||||
@ -35,6 +36,7 @@ SkScalerContext* SkRemoteGlyphCacheRenderer::generateScalerContext(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto tf = typefaceIter->get();
|
auto tf = typefaceIter->get();
|
||||||
|
// TODO: make effects really work.
|
||||||
SkScalerContextEffects effects;
|
SkScalerContextEffects effects;
|
||||||
auto mapSc = tf->createScalerContext(effects, &desc.desc(), false);
|
auto mapSc = tf->createScalerContext(effects, &desc.desc(), false);
|
||||||
scaler = fScalerContextMap.set(desc, std::move(mapSc));
|
scaler = fScalerContextMap.set(desc, std::move(mapSc));
|
||||||
@ -68,6 +70,11 @@ void SkRemoteGlyphCacheGPU::prepareDeserializeProcs(SkDeserialProcs* procs) {
|
|||||||
procs->fTypefaceCtx = this;
|
procs->fTypefaceCtx = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkTypeface* SkRemoteGlyphCacheGPU::lookupTypeface(SkFontID id) {
|
||||||
|
auto typeface = fMapIdToTypeface.find(id);
|
||||||
|
SkASSERT(typeface != nullptr);
|
||||||
|
return typeface->get();
|
||||||
|
}
|
||||||
|
|
||||||
sk_sp<SkTypeface> SkRemoteGlyphCacheGPU::decodeTypeface(const void* buf, size_t len) {
|
sk_sp<SkTypeface> SkRemoteGlyphCacheGPU::decodeTypeface(const void* buf, size_t len) {
|
||||||
WireTypeface wire;
|
WireTypeface wire;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define SkRemoteGlyphCache_DEFINED
|
#define SkRemoteGlyphCache_DEFINED
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
#include "SkData.h"
|
#include "SkData.h"
|
||||||
#include "SkDescriptor.h"
|
#include "SkDescriptor.h"
|
||||||
#include "SkSerialProcs.h"
|
#include "SkSerialProcs.h"
|
||||||
@ -23,9 +24,13 @@ public:
|
|||||||
auto desc = reinterpret_cast<SkDescriptor*>(&fDescriptor);
|
auto desc = reinterpret_cast<SkDescriptor*>(&fDescriptor);
|
||||||
desc->init();
|
desc->init();
|
||||||
desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
|
desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
|
||||||
|
desc->computeChecksum();
|
||||||
SkASSERT(sizeof(fDescriptor) == desc->getLength());
|
SkASSERT(sizeof(fDescriptor) == desc->getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit SkScalerContextRecDescriptor(const SkDescriptor& desc)
|
||||||
|
: SkScalerContextRecDescriptor(ExtractRec(desc)) { }
|
||||||
|
|
||||||
SkScalerContextRecDescriptor& operator=(const SkScalerContextRecDescriptor& rhs) {
|
SkScalerContextRecDescriptor& operator=(const SkScalerContextRecDescriptor& rhs) {
|
||||||
std::memcpy(&fDescriptor, &rhs.fDescriptor, rhs.desc().getLength());
|
std::memcpy(&fDescriptor, &rhs.fDescriptor, rhs.desc().getLength());
|
||||||
return *this;
|
return *this;
|
||||||
@ -47,6 +52,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static SkScalerContextRec ExtractRec(const SkDescriptor& desc) {
|
||||||
|
uint32_t size;
|
||||||
|
auto recPtr = desc.findEntry(kRec_SkDescriptorTag, &size);
|
||||||
|
|
||||||
|
SkScalerContextRec result;
|
||||||
|
std::memcpy(&result, recPtr, size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
// The system only passes descriptors without effects. That is why it uses a fixed size
|
// The system only passes descriptors without effects. That is why it uses a fixed size
|
||||||
// descriptor. storageFor is needed because some of the constructors below are private.
|
// descriptor. storageFor is needed because some of the constructors below are private.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -70,9 +83,7 @@ private:
|
|||||||
|
|
||||||
SkTHashMap<SkFontID, sk_sp<SkTypeface>> fTypefaceMap;
|
SkTHashMap<SkFontID, sk_sp<SkTypeface>> fTypefaceMap;
|
||||||
|
|
||||||
using DescriptorToContextMap =
|
using DescriptorToContextMap = SkTHashMap<SkScalerContextRecDescriptor,
|
||||||
SkTHashMap<
|
|
||||||
SkScalerContextRecDescriptor,
|
|
||||||
std::unique_ptr<SkScalerContext>,
|
std::unique_ptr<SkScalerContext>,
|
||||||
SkScalerContextRecDescriptor::Hash>;
|
SkScalerContextRecDescriptor::Hash>;
|
||||||
|
|
||||||
@ -84,6 +95,7 @@ public:
|
|||||||
explicit SkRemoteGlyphCacheGPU(std::unique_ptr<SkRemoteScalerContext> remoteScalerContext);
|
explicit SkRemoteGlyphCacheGPU(std::unique_ptr<SkRemoteScalerContext> remoteScalerContext);
|
||||||
|
|
||||||
void prepareDeserializeProcs(SkDeserialProcs* procs);
|
void prepareDeserializeProcs(SkDeserialProcs* procs);
|
||||||
|
SkTypeface* lookupTypeface(SkFontID id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sk_sp<SkTypeface> decodeTypeface(const void* buf, size_t len);
|
sk_sp<SkTypeface> decodeTypeface(const void* buf, size_t len);
|
||||||
|
@ -24,7 +24,6 @@ void SkScalerContextProxy::generateMetrics(SkGlyph* glyph) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkScalerContextProxy::generateImage(const SkGlyph& glyph) {
|
void SkScalerContextProxy::generateImage(const SkGlyph& glyph) {
|
||||||
fRemote->generateImage(*this->typefaceProxy(), this->getRec(), glyph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkScalerContextProxy::generatePath(SkGlyphID glyphID, SkPath* path) {
|
void SkScalerContextProxy::generatePath(SkGlyphID glyphID, SkPath* path) {
|
||||||
@ -32,10 +31,13 @@ void SkScalerContextProxy::generatePath(SkGlyphID glyphID, SkPath* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkScalerContextProxy::generateFontMetrics(SkPaint::FontMetrics* metrics) {
|
void SkScalerContextProxy::generateFontMetrics(SkPaint::FontMetrics* metrics) {
|
||||||
fRemote->generateFontMetrics(*this->typefaceProxy(), this->getRec(), metrics);
|
if (!fHaveFontMetrics) {
|
||||||
|
fRemote->generateFontMetrics(*this->typefaceProxy(), this->getRec(), &fFontMetrics);
|
||||||
|
}
|
||||||
|
fHaveFontMetrics = true;
|
||||||
|
*metrics = fFontMetrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkTypefaceProxy* SkScalerContextProxy::typefaceProxy() {
|
SkTypefaceProxy* SkScalerContextProxy::typefaceProxy() {
|
||||||
auto up = this->getTypeface();
|
return SkTypefaceProxy::DownCast(this->getTypeface());
|
||||||
return (SkTypefaceProxy *)up;
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "SkDescriptor.h"
|
#include "SkDescriptor.h"
|
||||||
#include "SkFontDescriptor.h"
|
#include "SkFontDescriptor.h"
|
||||||
#include "SkFontStyle.h"
|
#include "SkFontStyle.h"
|
||||||
|
#include "SkPaint.h"
|
||||||
#include "SkScalerContext.h"
|
#include "SkScalerContext.h"
|
||||||
#include "SkTypeface.h"
|
#include "SkTypeface.h"
|
||||||
|
|
||||||
@ -27,14 +28,6 @@ public:
|
|||||||
const SkTypefaceProxy& tf,
|
const SkTypefaceProxy& tf,
|
||||||
const SkScalerContextRec& rec,
|
const SkScalerContextRec& rec,
|
||||||
SkPaint::FontMetrics*) = 0;
|
SkPaint::FontMetrics*) = 0;
|
||||||
virtual void generateMetrics(
|
|
||||||
const SkTypefaceProxy& tf,
|
|
||||||
const SkScalerContextRec& rec,
|
|
||||||
SkGlyph* glyph) = 0;
|
|
||||||
virtual void generateImage(
|
|
||||||
const SkTypefaceProxy& tf,
|
|
||||||
const SkScalerContextRec& rec,
|
|
||||||
const SkGlyph& glyph) = 0;
|
|
||||||
virtual void generateMetricsAndImage(
|
virtual void generateMetricsAndImage(
|
||||||
const SkTypefaceProxy& tf,
|
const SkTypefaceProxy& tf,
|
||||||
const SkScalerContextRec& rec,
|
const SkScalerContextRec& rec,
|
||||||
@ -54,6 +47,11 @@ public:
|
|||||||
const SkDescriptor* desc,
|
const SkDescriptor* desc,
|
||||||
SkRemoteScalerContext* rsc);
|
SkRemoteScalerContext* rsc);
|
||||||
|
|
||||||
|
void setFontMetrics(const SkPaint::FontMetrics& fontMetrics) {
|
||||||
|
fFontMetrics = fontMetrics;
|
||||||
|
fHaveFontMetrics = true;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned generateGlyphCount(void) override { SK_ABORT("Should never be called."); return 0;}
|
unsigned generateGlyphCount(void) override { SK_ABORT("Should never be called."); return 0;}
|
||||||
uint16_t generateCharToGlyph(SkUnichar uni) override {
|
uint16_t generateCharToGlyph(SkUnichar uni) override {
|
||||||
@ -72,10 +70,13 @@ private:
|
|||||||
static constexpr size_t kMinGlyphCount = 8;
|
static constexpr size_t kMinGlyphCount = 8;
|
||||||
static constexpr size_t kMinGlyphImageSize = 16 /* height */ * 8 /* width */;
|
static constexpr size_t kMinGlyphImageSize = 16 /* height */ * 8 /* width */;
|
||||||
static constexpr size_t kMinAllocAmount = kMinGlyphImageSize * kMinGlyphCount;
|
static constexpr size_t kMinAllocAmount = kMinGlyphImageSize * kMinGlyphCount;
|
||||||
SkArenaAlloc fAlloc{kMinAllocAmount};
|
|
||||||
|
|
||||||
SkTypefaceProxy* typefaceProxy();
|
SkTypefaceProxy* typefaceProxy();
|
||||||
|
|
||||||
|
SkArenaAlloc fAlloc{kMinAllocAmount};
|
||||||
SkRemoteScalerContext* const fRemote;
|
SkRemoteScalerContext* const fRemote;
|
||||||
|
bool fHaveFontMetrics{false};
|
||||||
|
SkPaint::FontMetrics fFontMetrics;
|
||||||
typedef SkScalerContext INHERITED;
|
typedef SkScalerContext INHERITED;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -90,6 +91,10 @@ public:
|
|||||||
, fFontId{fontId}
|
, fFontId{fontId}
|
||||||
, fRsc{rsc} { }
|
, fRsc{rsc} { }
|
||||||
SkFontID fontID() const {return fFontId;}
|
SkFontID fontID() const {return fFontId;}
|
||||||
|
static SkTypefaceProxy* DownCast(SkTypeface* typeface) {
|
||||||
|
// TODO: how to check the safty of the down cast.
|
||||||
|
return (SkTypefaceProxy*) typeface;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int onGetUPEM() const override { SK_ABORT("Should never be called."); return 0; }
|
int onGetUPEM() const override { SK_ABORT("Should never be called."); return 0; }
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user