Add bilerp support to scaled emojis

Bug: skia:7562
Change-Id: Ibdf8e71050e909de87ca2beb3fb2b57327011364
Reviewed-on: https://skia-review.googlesource.com/111820
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2018-03-05 14:40:36 -05:00 committed by Skia Commit-Bot
parent 974aa8eaba
commit cf838c7450
8 changed files with 69 additions and 24 deletions

View File

@ -258,8 +258,10 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
flushInfo.fGeometryProcessor = this->setupDfProcessor(fullAtlasManager); flushInfo.fGeometryProcessor = this->setupDfProcessor(fullAtlasManager);
SkDEBUGCODE(dfPerspective = fGeoData[0].fViewMatrix.hasPerspective()); SkDEBUGCODE(dfPerspective = fGeoData[0].fViewMatrix.hasPerspective());
} else { } else {
GrSamplerState samplerState = fHasScaledGlyphs ? GrSamplerState::ClampBilerp()
: GrSamplerState::ClampNearest();
flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make( flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
this->color(), proxies, atlasPageCount, GrSamplerState::ClampNearest(), maskFormat, this->color(), proxies, atlasPageCount, samplerState, maskFormat,
localMatrix, this->usesLocalCoords()); localMatrix, this->usesLocalCoords());
} }
@ -349,8 +351,10 @@ void GrAtlasTextOp::flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) co
proxies, numProxies, GrSamplerState::ClampBilerp()); proxies, numProxies, GrSamplerState::ClampBilerp());
} }
} else { } else {
reinterpret_cast<GrBitmapTextGeoProc*>(gp)->addNewProxies( GrSamplerState samplerState = fHasScaledGlyphs ? GrSamplerState::ClampBilerp()
proxies, numProxies, GrSamplerState::ClampNearest()); : GrSamplerState::ClampNearest();
reinterpret_cast<GrBitmapTextGeoProc*>(gp)->addNewProxies(proxies, numProxies,
samplerState);
} }
} }
@ -398,6 +402,10 @@ bool GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
if (kColorBitmapMask_MaskType == fMaskType && this->color() != that->color()) { if (kColorBitmapMask_MaskType == fMaskType && this->color() != that->color()) {
return false; return false;
} }
if (fHasScaledGlyphs != that->fHasScaledGlyphs) {
return false;
}
} }
// Keep the batch vertex buffer size below 32K so we don't have to create a special one // Keep the batch vertex buffer size below 32K so we don't have to create a special one

View File

@ -41,8 +41,9 @@ public:
}; };
static std::unique_ptr<GrAtlasTextOp> MakeBitmap( static std::unique_ptr<GrAtlasTextOp> MakeBitmap(
GrPaint&& paint, GrMaskFormat maskFormat, GrPaint&& paint, GrMaskFormat maskFormat, int glyphCount,
int glyphCount, GrRestrictedAtlasManager* restrictedAtlasManager) { bool hasScaledGlyphs,
GrRestrictedAtlasManager* restrictedAtlasManager) {
std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(restrictedAtlasManager, std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(restrictedAtlasManager,
std::move(paint))); std::move(paint)));
@ -60,6 +61,7 @@ public:
op->fNumGlyphs = glyphCount; op->fNumGlyphs = glyphCount;
op->fGeoCount = 1; op->fGeoCount = 1;
op->fLuminanceColor = 0; op->fLuminanceColor = 0;
op->fHasScaledGlyphs = hasScaledGlyphs;
return op; return op;
} }
@ -183,15 +185,18 @@ private:
int fGeoDataAllocSize; int fGeoDataAllocSize;
uint32_t fSRGBFlags; uint32_t fSRGBFlags;
GrProcessorSet fProcessors; GrProcessorSet fProcessors;
bool fUsesLocalCoords; struct {
bool fCanCombineOnTouchOrOverlap; uint32_t fUsesLocalCoords : 1;
uint32_t fCanCombineOnTouchOrOverlap : 1;
uint32_t fUseGammaCorrectDistanceTable : 1;
uint32_t fHasScaledGlyphs : 1;
};
int fGeoCount; int fGeoCount;
int fNumGlyphs; int fNumGlyphs;
MaskType fMaskType; MaskType fMaskType;
// Distance field properties // Distance field properties
sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable; sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable;
SkColor fLuminanceColor; SkColor fLuminanceColor;
bool fUseGammaCorrectDistanceTable;
uint32_t fDFGPFlags = 0; uint32_t fDFGPFlags = 0;
typedef GrMeshDrawOp INHERITED; typedef GrMeshDrawOp INHERITED;

View File

@ -152,6 +152,7 @@ void GrAtlasTextBlob::appendGlyph(int runIndex,
subRun->appendVertices(vertexStride); subRun->appendVertices(vertexStride);
fGlyphs[subRun->glyphEndIndex()] = glyph; fGlyphs[subRun->glyphEndIndex()] = glyph;
subRun->glyphAppended(); subRun->glyphAppended();
subRun->setHasScaledGlyphs(SK_Scalar1 != scale);
} }
void GrAtlasTextBlob::appendPathGlyph(int runIndex, const SkPath& path, SkScalar x, SkScalar y, void GrAtlasTextBlob::appendPathGlyph(int runIndex, const SkPath& path, SkScalar x, SkScalar y,
@ -264,8 +265,8 @@ inline std::unique_ptr<GrAtlasTextOp> GrAtlasTextBlob::makeOp(
target->colorSpaceInfo().isGammaCorrect(), paint.luminanceColor(), target->colorSpaceInfo().isGammaCorrect(), paint.luminanceColor(),
info.hasUseLCDText(), useBGR, info.isAntiAliased()); info.hasUseLCDText(), useBGR, info.isAntiAliased());
} else { } else {
op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format, op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format, glyphCount,
glyphCount, restrictedAtlasManager); info.hasScaledGlyphs(), restrictedAtlasManager);
} }
GrAtlasTextOp::Geometry& geometry = op->geometry(); GrAtlasTextOp::Geometry& geometry = op->geometry();
geometry.fViewMatrix = viewMatrix; geometry.fViewMatrix = viewMatrix;
@ -355,9 +356,10 @@ void GrAtlasTextBlob::flush(GrRestrictedAtlasManager* restrictedAtlasManager,
SkRect rtBounds = SkRect::MakeWH(target->width(), target->height()); SkRect rtBounds = SkRect::MakeWH(target->width(), target->height());
SkRRect clipRRect; SkRRect clipRRect;
GrAA aa; GrAA aa;
// We can clip geometrically if we're not using SDFs, // We can clip geometrically if we're not using SDFs or scaled glyphs,
// and we have an axis-aligned rectangular non-AA clip // and we have an axis-aligned rectangular non-AA clip
if (!info.drawAsDistanceFields() && clip.isRRect(rtBounds, &clipRRect, &aa) && if (!info.drawAsDistanceFields() && !info.hasScaledGlyphs() &&
clip.isRRect(rtBounds, &clipRRect, &aa) &&
clipRRect.isRect() && GrAA::kNo == aa) { clipRRect.isRect() && GrAA::kNo == aa) {
skipClip = true; skipClip = true;
// We only need to do clipping work if the subrun isn't contained by the clip // We only need to do clipping work if the subrun isn't contained by the clip

View File

@ -435,13 +435,19 @@ private:
fFlags = hasW ? (fFlags | kHasWCoord_Flag) : fFlags & ~kHasWCoord_Flag; fFlags = hasW ? (fFlags | kHasWCoord_Flag) : fFlags & ~kHasWCoord_Flag;
} }
bool hasWCoord() const { return SkToBool(fFlags & kHasWCoord_Flag); } bool hasWCoord() const { return SkToBool(fFlags & kHasWCoord_Flag); }
void setHasScaledGlyphs(bool hasScaledGlyphs) {
fFlags = hasScaledGlyphs ? (fFlags | kHasScaledGlyphs_Flag)
: fFlags & ~kHasScaledGlyphs_Flag;
}
bool hasScaledGlyphs() const { return SkToBool(fFlags & kHasScaledGlyphs_Flag); }
private: private:
enum Flag { enum Flag {
kDrawAsSDF_Flag = 0x1, kDrawAsSDF_Flag = 0x01,
kUseLCDText_Flag = 0x2, kUseLCDText_Flag = 0x02,
kAntiAliased_Flag = 0x4, kAntiAliased_Flag = 0x04,
kHasWCoord_Flag = 0x8 kHasWCoord_Flag = 0x08,
kHasScaledGlyphs_Flag = 0x10
}; };
GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken; GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;

View File

@ -280,7 +280,8 @@ Regenerator::Result Regenerator::doRegen() {
if (!fFullAtlasManager->hasGlyph(glyph) && if (!fFullAtlasManager->hasGlyph(glyph) &&
!strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache, !strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache,
fFullAtlasManager, glyph, fFullAtlasManager, glyph,
fLazyCache->get(), fSubRun->maskFormat())) { fLazyCache->get(), fSubRun->maskFormat(),
fSubRun->hasScaledGlyphs())) {
fBrokenRun = glyphIdx > 0; fBrokenRun = glyphIdx > 0;
result.fFinished = false; result.fFinished = false;
return result; return result;

View File

@ -856,6 +856,7 @@ void GrAtlasTextContext::FallbackTextHelper::appendText(const SkGlyph& glyph, in
SkScalar scaledGlyphSize = maxDim * fMaxScale; SkScalar scaledGlyphSize = maxDim * fMaxScale;
if (!fViewMatrix.hasPerspective() && scaledGlyphSize > fMaxTextSize) { if (!fViewMatrix.hasPerspective() && scaledGlyphSize > fMaxTextSize) {
fUseScaledFallback = true; fUseScaledFallback = true;
fMaxTextSize -= 2; // Subtract 2 to account for the bilerp pad around the glyph
} }
} }

View File

@ -298,35 +298,57 @@ bool GrTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider,
GrAtlasManager* fullAtlasManager, GrAtlasManager* fullAtlasManager,
GrGlyph* glyph, GrGlyph* glyph,
SkGlyphCache* cache, SkGlyphCache* cache,
GrMaskFormat expectedMaskFormat) { GrMaskFormat expectedMaskFormat,
bool isScaledGlyph) {
SkASSERT(glyph); SkASSERT(glyph);
SkASSERT(cache); SkASSERT(cache);
SkASSERT(fCache.find(glyph->fPackedID)); SkASSERT(fCache.find(glyph->fPackedID));
int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat); int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat);
int width = glyph->width();
int height = glyph->height();
int rowBytes = width * bytesPerPixel;
size_t size = glyph->fBounds.area() * bytesPerPixel; size_t size = glyph->fBounds.area() * bytesPerPixel;
bool isSDFGlyph = GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(glyph->fPackedID);
bool addPad = isScaledGlyph && !isSDFGlyph;
if (addPad) {
width += 2;
rowBytes += 2*bytesPerPixel;
size += 2 * rowBytes;
height += 2;
size += 2 * (height + 2) * bytesPerPixel;
}
SkAutoSMalloc<1024> storage(size); SkAutoSMalloc<1024> storage(size);
const SkGlyph& skGlyph = GrToSkGlyph(cache, glyph->fPackedID); const SkGlyph& skGlyph = GrToSkGlyph(cache, glyph->fPackedID);
if (GrGlyph::kDistance_MaskStyle == GrGlyph::UnpackMaskStyle(glyph->fPackedID)) { if (isSDFGlyph) {
if (!get_packed_glyph_df_image(cache, skGlyph, glyph->width(), glyph->height(), if (!get_packed_glyph_df_image(cache, skGlyph, width, height,
storage.get())) { storage.get())) {
return false; return false;
} }
} else { } else {
void* dataPtr = storage.get();
if (addPad) {
sk_bzero(dataPtr, size);
dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel;
}
if (!get_packed_glyph_image(cache, skGlyph, glyph->width(), glyph->height(), if (!get_packed_glyph_image(cache, skGlyph, glyph->width(), glyph->height(),
glyph->width() * bytesPerPixel, expectedMaskFormat, rowBytes, expectedMaskFormat,
storage.get())) { dataPtr)) {
return false; return false;
} }
} }
bool success = fullAtlasManager->addToAtlas(resourceProvider, glyphCache, this, bool success = fullAtlasManager->addToAtlas(resourceProvider, glyphCache, this,
&glyph->fID, target, expectedMaskFormat, &glyph->fID, target, expectedMaskFormat,
glyph->width(), glyph->height(), width, height,
storage.get(), &glyph->fAtlasLocation); storage.get(), &glyph->fAtlasLocation);
if (success) { if (success) {
if (addPad) {
glyph->fAtlasLocation.fX += 1;
glyph->fAtlasLocation.fY += 1;
}
SkASSERT(GrDrawOpAtlas::kInvalidAtlasID != glyph->fID); SkASSERT(GrDrawOpAtlas::kInvalidAtlasID != glyph->fID);
fAtlasedGlyphs++; fAtlasedGlyphs++;
} }

View File

@ -65,7 +65,7 @@ public:
// get the actual glyph image itself when we get the glyph metrics. // get the actual glyph image itself when we get the glyph metrics.
bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrGlyphCache*, bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrGlyphCache*,
GrAtlasManager*, GrGlyph*, GrAtlasManager*, GrGlyph*,
SkGlyphCache*, GrMaskFormat expectedMaskFormat); SkGlyphCache*, GrMaskFormat expectedMaskFormat, bool isScaledGlyph);
// testing // testing
int countGlyphs() const { return fCache.count(); } int countGlyphs() const { return fCache.count(); }