use SkGlyphDigest for MaskSummary
Use SkGlyphDigest in the remote glyph cache. This allows future CLs to use maximum glyph information for calculating scale factors. Move SkGlyphDigest to a more central location in the code. Bugs: chromium:1280180 Change-Id: Id916d39b8a46a29723bc9f244969c8d00162e5df Reviewed-on: https://skia-review.googlesource.com/c/skia/+/493197 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
parent
3e1354a592
commit
55b4dc3f7a
@ -278,28 +278,6 @@ private:
|
||||
void commonMaskLoop(
|
||||
SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects, Rejector&& reject);
|
||||
|
||||
// Keep track of if the glyph draw has been totally satisfied. It could be that this
|
||||
// strike can not draw the glyph, and it must be rejected to be handled by fallback.
|
||||
// For example, if a glyph has canDrawAsMask sent, then that data is on the GPU, and this
|
||||
// strike totally satisfies this result. If canDrawAsMask is false, then this glyph must be
|
||||
// rejected, and handled by a later stage using a latter strike.
|
||||
struct MaskSummary {
|
||||
static_assert(SkPackedGlyphID::kMaskAll < (1u << 30), "SkPackedGlyphID is too big.");
|
||||
uint32_t packedID:30;
|
||||
uint32_t canDrawAsMask:1;
|
||||
uint32_t canDrawAsSDFT:1;
|
||||
};
|
||||
|
||||
struct MaskSummaryTraits {
|
||||
static SkPackedGlyphID GetKey(MaskSummary summary) {
|
||||
return SkPackedGlyphID{summary.packedID};
|
||||
}
|
||||
|
||||
static uint32_t Hash(SkPackedGlyphID packedID) {
|
||||
return packedID.hash();
|
||||
}
|
||||
};
|
||||
|
||||
// Same thing as MaskSummary, but for paths.
|
||||
struct PathSummary {
|
||||
constexpr static uint16_t kIsPath = 0;
|
||||
@ -340,7 +318,7 @@ private:
|
||||
LowerRangeBitVector fSentLowGlyphIDs;
|
||||
|
||||
// The masks and paths that currently reside in the GPU process.
|
||||
SkTHashTable<MaskSummary, SkPackedGlyphID, MaskSummaryTraits> fSentGlyphs;
|
||||
SkTHashTable<SkGlyphDigest, uint32_t, SkGlyphDigest> fSentGlyphs;
|
||||
SkTHashTable<PathSummary, SkPackedGlyphID, PathSummaryTraits> fSentPaths;
|
||||
|
||||
// The Masks, SDFT Mask, and Paths that need to be sent to the GPU task for the processed
|
||||
@ -462,20 +440,19 @@ void RemoteStrike::commonMaskLoop(
|
||||
SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects, Rejector&& reject) {
|
||||
drawables->forEachGlyphID(
|
||||
[&](size_t i, SkPackedGlyphID packedID, SkPoint position) {
|
||||
MaskSummary* summary = fSentGlyphs.find(packedID);
|
||||
if (summary == nullptr) {
|
||||
SkGlyphDigest* digest = fSentGlyphs.find(packedID.value());
|
||||
if (digest == nullptr) {
|
||||
// Put the new SkGlyph in the glyphs to send.
|
||||
this->ensureScalerContext();
|
||||
fMasksToSend.emplace_back(fContext->makeGlyph(packedID, &fPathAlloc));
|
||||
SkGlyph* glyph = &fMasksToSend.back();
|
||||
|
||||
MaskSummary newSummary =
|
||||
{packedID.value(), CanDrawAsMask(*glyph), CanDrawAsSDFT(*glyph)};
|
||||
summary = fSentGlyphs.set(newSummary);
|
||||
SkGlyphDigest newDigest{0, *glyph};
|
||||
digest = fSentGlyphs.set(newDigest);
|
||||
}
|
||||
|
||||
// Reject things that are too big.
|
||||
if (reject(*summary)) {
|
||||
if (reject(*digest)) {
|
||||
rejects->reject(i);
|
||||
}
|
||||
});
|
||||
@ -487,33 +464,32 @@ void RemoteStrike::prepareForMaskDrawing(
|
||||
SkPackedGlyphID packedID = variant.packedID();
|
||||
if (fSentLowGlyphIDs.test(packedID)) {
|
||||
#ifdef SK_DEBUG
|
||||
MaskSummary* summary = fSentGlyphs.find(packedID);
|
||||
SkASSERT(summary != nullptr);
|
||||
SkASSERT(summary->canDrawAsMask && summary->canDrawAsSDFT);
|
||||
SkGlyphDigest* digest = fSentGlyphs.find(packedID.value());
|
||||
SkASSERT(digest != nullptr);
|
||||
SkASSERT(digest->canDrawAsMask() && digest->canDrawAsSDFT());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
MaskSummary* summary = fSentGlyphs.find(packedID);
|
||||
if (summary == nullptr) {
|
||||
SkGlyphDigest* digest = fSentGlyphs.find(packedID.value());
|
||||
if (digest == nullptr) {
|
||||
|
||||
// Put the new SkGlyph in the glyphs to send.
|
||||
this->ensureScalerContext();
|
||||
fMasksToSend.emplace_back(fContext->makeGlyph(packedID, &fPathAlloc));
|
||||
SkGlyph* glyph = &fMasksToSend.back();
|
||||
|
||||
MaskSummary newSummary =
|
||||
{packedID.value(), CanDrawAsMask(*glyph), CanDrawAsSDFT(*glyph)};
|
||||
SkGlyphDigest newDigest{0, *glyph};
|
||||
|
||||
summary = fSentGlyphs.set(newSummary);
|
||||
digest = fSentGlyphs.set(newDigest);
|
||||
|
||||
if (summary->canDrawAsMask && summary->canDrawAsSDFT) {
|
||||
if (digest->canDrawAsMask() && digest->canDrawAsSDFT()) {
|
||||
fSentLowGlyphIDs.setIfLower(packedID);
|
||||
}
|
||||
}
|
||||
|
||||
// Reject things that are too big.
|
||||
if (!summary->canDrawAsMask) {
|
||||
if (!digest->canDrawAsMask()) {
|
||||
rejects->reject(i);
|
||||
}
|
||||
}
|
||||
@ -522,7 +498,7 @@ void RemoteStrike::prepareForMaskDrawing(
|
||||
void RemoteStrike::prepareForSDFTDrawing(
|
||||
SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) {
|
||||
this->commonMaskLoop(drawables, rejects,
|
||||
[](MaskSummary summary){return !summary.canDrawAsSDFT;});
|
||||
[](SkGlyphDigest digest){return !digest.canDrawAsSDFT();});
|
||||
}
|
||||
|
||||
void RemoteStrike::prepareForPathDrawing(
|
||||
|
@ -349,3 +349,12 @@ void SkGlyph::ensureIntercepts(const SkScalar* bounds, SkScalar scale, SkScalar
|
||||
}
|
||||
offsetResults(intercept, array, count);
|
||||
}
|
||||
|
||||
SkGlyphDigest::SkGlyphDigest(size_t index, const SkGlyph& glyph)
|
||||
: fPackedGlyphID{glyph.getPackedID().value()}
|
||||
, fIndex{SkTo<uint32_t>(index)}
|
||||
, fIsEmpty(glyph.isEmpty())
|
||||
, fIsColor(glyph.isColor())
|
||||
, fCanDrawAsMask{SkStrikeForGPU::CanDrawAsMask(glyph)}
|
||||
, fCanDrawAsSDFT{SkStrikeForGPU::CanDrawAsSDFT(glyph)}
|
||||
, fMaxDimension{(uint16_t)glyph.maxDimension()} {}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "include/private/SkVx.h"
|
||||
#include "src/core/SkMask.h"
|
||||
#include "src/core/SkMathPriv.h"
|
||||
#include "src/core/SkStrikeForGPU.h"
|
||||
|
||||
class SkArenaAlloc;
|
||||
class SkScalerContext;
|
||||
@ -238,7 +239,41 @@ inline SkGlyphRect rect_intersection(SkGlyphRect a, SkGlyphRect b) {
|
||||
}
|
||||
} // namespace skglyph
|
||||
|
||||
struct SkGlyphPrototype;
|
||||
class SkGlyph;
|
||||
|
||||
// SkGlyphDigest contains a digest of information for making GPU drawing decisions. It can be
|
||||
// referenced instead of the glyph itself in many situations. In the remote glyphs cache the
|
||||
// SkGlyphDigest is the only information that needs to be stored in the cache.
|
||||
class SkGlyphDigest {
|
||||
public:
|
||||
// Default ctor is only needed for the hash table.
|
||||
SkGlyphDigest() = default;
|
||||
SkGlyphDigest(size_t index, const SkGlyph& glyph);
|
||||
int index() const {return fIndex; }
|
||||
bool isEmpty() const {return fIsEmpty; }
|
||||
bool isColor() const {return fIsColor; }
|
||||
bool canDrawAsMask() const {return fCanDrawAsMask;}
|
||||
bool canDrawAsSDFT() const {return fCanDrawAsSDFT;}
|
||||
uint32_t packedGlyphID() const {return fPackedGlyphID;}
|
||||
|
||||
// Support mapping from SkPackedGlyphID stored in the digest.
|
||||
static uint32_t GetKey(SkGlyphDigest digest) {
|
||||
return digest.packedGlyphID();
|
||||
}
|
||||
static uint32_t Hash(uint32_t packedGlyphID) {
|
||||
return SkGoodHash()(packedGlyphID);
|
||||
}
|
||||
|
||||
private:
|
||||
static_assert(SkPackedGlyphID::kEndData == 20);
|
||||
uint64_t fPackedGlyphID : SkPackedGlyphID::kEndData;
|
||||
uint64_t fIndex : SkPackedGlyphID::kEndData;
|
||||
uint64_t fIsEmpty : 1;
|
||||
uint64_t fIsColor : 1;
|
||||
uint64_t fCanDrawAsMask : 1;
|
||||
uint64_t fCanDrawAsSDFT : 1;
|
||||
uint64_t fMaxDimension : 16;
|
||||
};
|
||||
|
||||
class SkGlyph {
|
||||
public:
|
||||
@ -372,7 +407,7 @@ private:
|
||||
// Support horizontal and vertical skipping strike-through / underlines.
|
||||
// The caller walks the linked list looking for a match. For a horizontal underline,
|
||||
// the fBounds contains the top and bottom of the underline. The fInterval pair contains the
|
||||
// beginning and end of of the intersection of the bounds and the glyph's path.
|
||||
// beginning and end of the intersection of the bounds and the glyph's path.
|
||||
// If interval[0] >= interval[1], no intersection was found.
|
||||
struct Intercept {
|
||||
Intercept* fNext;
|
||||
|
@ -21,38 +21,6 @@
|
||||
|
||||
class SkScalerContext;
|
||||
|
||||
// The value stored in fDigestForPackedGlyphID.
|
||||
// index() is the index into fGlyphForIndex.
|
||||
class SkGlyphDigest {
|
||||
public:
|
||||
// Default ctor is only needed for the hash table.
|
||||
SkGlyphDigest() = default;
|
||||
SkGlyphDigest(size_t i, const SkGlyph& glyph)
|
||||
: fPackedGlyphID{glyph.getPackedID().value()}
|
||||
, fIndex{SkTo<uint32_t>(i)}
|
||||
, fIsEmpty(glyph.isEmpty())
|
||||
, fIsColor(glyph.isColor())
|
||||
, fCanDrawAsMask{SkStrikeForGPU::CanDrawAsMask(glyph)}
|
||||
, fCanDrawAsSDFT{SkStrikeForGPU::CanDrawAsSDFT(glyph)}
|
||||
, fMaxDimension{(uint16_t)glyph.maxDimension()} {}
|
||||
int index() const {return fIndex; }
|
||||
bool isEmpty() const {return fIsEmpty; }
|
||||
bool isColor() const {return fIsColor; }
|
||||
bool canDrawAsMask() const {return fCanDrawAsMask;}
|
||||
bool canDrawAsSDFT() const {return fCanDrawAsSDFT;}
|
||||
uint32_t packedGlyphID() const {return fPackedGlyphID;}
|
||||
|
||||
private:
|
||||
static_assert(SkPackedGlyphID::kEndData == 20);
|
||||
uint64_t fPackedGlyphID : SkPackedGlyphID::kEndData;
|
||||
uint64_t fIndex : SkPackedGlyphID::kEndData;
|
||||
uint64_t fIsEmpty : 1;
|
||||
uint64_t fIsColor : 1;
|
||||
uint64_t fCanDrawAsMask : 1;
|
||||
uint64_t fCanDrawAsSDFT : 1;
|
||||
uint64_t fMaxDimension : 16;
|
||||
};
|
||||
|
||||
// This class represents a strike: a specific combination of typeface, size, matrix, etc., and
|
||||
// holds the glyphs for that strike.
|
||||
class SkScalerCache {
|
||||
@ -153,15 +121,7 @@ private:
|
||||
// SkGlyphDigest's fIndex field stores the index. This pointer provides an unchanging
|
||||
// reference to the SkGlyph as long as the strike is alive, and fGlyphForIndex
|
||||
// provides a dense index for glyphs.
|
||||
struct DigestTraits {
|
||||
static uint32_t GetKey(SkGlyphDigest digest) {
|
||||
return digest.packedGlyphID();
|
||||
}
|
||||
static uint32_t Hash(uint32_t packedGlyphID) {
|
||||
return SkGoodHash()(packedGlyphID);
|
||||
}
|
||||
};
|
||||
SkTHashTable<SkGlyphDigest, uint32_t, DigestTraits> fDigestForPackedGlyphID SK_GUARDED_BY(fMu);
|
||||
SkTHashTable<SkGlyphDigest, uint32_t, SkGlyphDigest> fDigestForPackedGlyphID SK_GUARDED_BY(fMu);
|
||||
std::vector<SkGlyph*> fGlyphForIndex SK_GUARDED_BY(fMu);
|
||||
|
||||
// so we don't grow our arrays a lot
|
||||
|
Loading…
Reference in New Issue
Block a user