add bilerp atlas support flag

Move the compile-time flag SK_EXPERIMENTAL_ADD_ATLAS_PADDING,
to a runtime flag in GrContextOptions.

Bug: chromium:1275890

Change-Id: I7e051cd4834ac44958b1431976535519e8bdaa3e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/482416
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2021-12-09 16:19:08 -05:00 committed by SkCQ
parent 0f2390f7fb
commit c279e7640b
9 changed files with 61 additions and 26 deletions

View File

@ -51,7 +51,7 @@ class DirectMaskGlyphVertexFillBenchmark : public Benchmark {
const SkPoint drawOrigin = glyphRunList.origin();
drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
GrSDFTControl control{false, props.isUseDeviceIndependentFonts(), 256, 256};
fBlob = GrTextBlob::Make(glyphRunList, paint, drawMatrix, control, &painter);
fBlob = GrTextBlob::Make(glyphRunList, paint, drawMatrix, false, control, &painter);
SkASSERT(!fBlob->subRunList().isEmpty());
GrAtlasSubRun* subRun = fBlob->subRunList().front().testingOnly_atlasSubRun();

View File

@ -25,7 +25,7 @@
#include "include/private/chromium/GrSlug.h"
#include "tools/ToolUtils.h"
#if SK_SUPPORT_GPU && defined(SK_EXPERIMENTAL_ADD_ATLAS_PADDING)
#if SK_SUPPORT_GPU && defined(SK_EXPERIMENTAL_SIMULATE_DRAWGLYPHRUNLIST_WITH_SLUG)
class SlugGM : public skiagm::GM {
public:
SlugGM(const char* txt)

View File

@ -270,6 +270,16 @@ struct SK_API GrContextOptions {
*/
bool fEnableExperimentalHardwareTessellation = false;
/**
* If true, then add 1 pixel padding to all glyph masks in the atlas to support bi-lerp
* rendering of all glyphs. This must be set to true to use GrSlug.
*/
#if defined(SK_EXPERIMENTAL_SIMULATE_DRAWGLYPHRUNLIST_WITH_SLUG) || defined(SK_EXPERIMENTAL_ADD_ATLAS_PADDING)
bool fSupportBilerpFromGlyphAtlas = true;
#else
bool fSupportBilerpFromGlyphAtlas = false;
#endif
/**
* Uses a reduced variety of shaders. May perform less optimally in steady state but can reduce
* jank due to shader compilations.

View File

@ -15,6 +15,11 @@ class SkCanvas;
class SkPaint;
class SkTextBlob;
// You can use GrSlug to simulate drawTextBlob by defining the following at compile time.
// SK_EXPERIMENTAL_SIMULATE_DRAWGLYPHRUNLIST_WITH_SLUG
// For Skia, add this to your args.gn file.
// extra_cflags = ["-D", "SK_EXPERIMENTAL_SIMULATE_DRAWGLYPHRUNLIST_WITH_SLUG"]
// GrSlug encapsulates an SkTextBlob at a specific origin, using a specific paint. It can be
// manipulated using matrix and clip changes to the canvas. If the canvas is transformed, then
// the GrSlug will also transform with smaller glyphs using bi-linear interpolation to render. You

View File

@ -505,7 +505,8 @@ GrOp::Owner AtlasTextOp::CreateOpTestingOnly(SurfaceDrawContext* sdc,
rContext->priv().getSDFTControl(sdc->surfaceProps().isUseDeviceIndependentFonts());
SkGlyphRunListPainter* painter = sdc->glyphRunPainter();
sk_sp<GrTextBlob> blob = GrTextBlob::Make(glyphRunList, skPaint, drawMatrix, control, painter);
sk_sp<GrTextBlob> blob = GrTextBlob::Make(
glyphRunList, skPaint, drawMatrix, false, control, painter);
if (blob->subRunList().isEmpty()) {
return nullptr;

View File

@ -31,9 +31,8 @@
#include "src/gpu/v1/Device_v1.h"
#include "src/gpu/v1/SurfaceDrawContext_v1.h"
// Defining SK_EXPERIMENTAL_ADD_ATLAS_PADDING will cause all glyphs in the atlas to have a one
// pixel border to support bi-lerping on demand.
// #define SK_EXPERIMENTAL_ADD_ATLAS_PADDING
// Note:
// In order to use GrSlugs, you need to set the fSupportBilerpFromGlyphAtlas on GrContextOptions.
// Naming conventions
// * drawMatrix - the CTM from the canvas.
@ -713,11 +712,11 @@ void DirectMaskSubRun::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cache)
std::tuple<bool, int>
DirectMaskSubRun::regenerateAtlas(int begin, int end, GrMeshDrawTarget* target) const {
#if defined(SK_EXPERIMENTAL_ADD_ATLAS_PADDING)
if (fBlob->supportBilerpAtlas()) {
return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 1, target, true);
#else
} else {
return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 0, target, false);
#endif
}
}
// The 99% case. No clip. Non-color only.
@ -1553,6 +1552,7 @@ GrTextBlob::~GrTextBlob() = default;
sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList,
const SkPaint& paint,
const SkMatrix& positionMatrix,
bool supportBilerpAtlas,
const GrSDFTControl& control,
SkGlyphRunListPainter* painter) {
// The difference in alignment from the per-glyph data to the SubRun;
@ -1573,8 +1573,9 @@ sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList,
void* allocation = ::operator new (allocationSize);
SkColor initialLuminance = SkPaintPriv::ComputeLuminanceColor(paint);
sk_sp<GrTextBlob> blob{new (allocation)
GrTextBlob(bytesNeededForSubRun, positionMatrix, initialLuminance)};
sk_sp<GrTextBlob> blob{
new (allocation) GrTextBlob(
bytesNeededForSubRun, supportBilerpAtlas, positionMatrix, initialLuminance)};
const uint64_t uniqueID = glyphRunList.uniqueID();
for (auto& glyphRun : glyphRunList) {
@ -1627,10 +1628,12 @@ const GrTextBlob::Key& GrTextBlob::key() const { return fKey; }
size_t GrTextBlob::size() const { return fSize; }
GrTextBlob::GrTextBlob(int allocSize,
bool supportBilerpAtlas,
const SkMatrix& positionMatrix,
SkColor initialLuminance)
: fAlloc{SkTAddOffset<char>(this, sizeof(GrTextBlob)), allocSize, allocSize/2}
, fSize{allocSize}
, fSupportBilerpAtlas{supportBilerpAtlas}
, fInitialPositionMatrix{positionMatrix}
, fInitialLuminance{initialLuminance} { }
@ -1698,6 +1701,7 @@ public:
using DevicePosition = skvx::Vec<2, int16_t>;
DirectMaskSubRunNoCache(GrMaskFormat format,
bool supportBilerpAtlas,
const SkRect& bounds,
SkSpan<const DevicePosition> devicePositions,
GlyphVector&& glyphs);
@ -1705,6 +1709,7 @@ public:
static GrAtlasSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
sk_sp<SkStrike>&& strike,
GrMaskFormat format,
bool supportBilerpAtlas,
GrSubRunAllocator* alloc);
size_t vertexStride(const SkMatrix& drawMatrix) const override;
@ -1732,6 +1737,9 @@ public:
private:
const GrMaskFormat fMaskFormat;
// Support bilerping from the atlas.
const bool fSupportBilerpAtlas;
// The vertex bounds in device space. The bounds are the joined rectangles of all the glyphs.
const SkRect fGlyphDeviceBounds;
const SkSpan<const DevicePosition> fLeftTopDevicePos;
@ -1745,10 +1753,12 @@ private:
};
DirectMaskSubRunNoCache::DirectMaskSubRunNoCache(GrMaskFormat format,
bool supportBilerpAtlas,
const SkRect& deviceBounds,
SkSpan<const DevicePosition> devicePositions,
GlyphVector&& glyphs)
: fMaskFormat{format}
, fSupportBilerpAtlas{supportBilerpAtlas}
, fGlyphDeviceBounds{deviceBounds}
, fLeftTopDevicePos{devicePositions}
, fGlyphs{std::move(glyphs)} { }
@ -1756,6 +1766,7 @@ DirectMaskSubRunNoCache::DirectMaskSubRunNoCache(GrMaskFormat format,
GrAtlasSubRunOwner DirectMaskSubRunNoCache::Make(const SkZip<SkGlyphVariant, SkPoint>& drawables,
sk_sp<SkStrike>&& strike,
GrMaskFormat format,
bool supportBilerpAtlas,
GrSubRunAllocator* alloc) {
DevicePosition* glyphLeftTop = alloc->makePODArray<DevicePosition>(drawables.size());
@ -1793,7 +1804,7 @@ GrAtlasSubRunOwner DirectMaskSubRunNoCache::Make(const SkZip<SkGlyphVariant, SkP
SkSpan<const DevicePosition> leftTop{glyphLeftTop, goodPosCount};
return alloc->makeUnique<DirectMaskSubRunNoCache>(
format, runBounds.rect(), leftTop,
format, supportBilerpAtlas, runBounds.rect(), leftTop,
GlyphVector{std::move(strike), {glyphIDs, goodPosCount}});
}
@ -1875,11 +1886,11 @@ void DirectMaskSubRunNoCache::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *
std::tuple<bool, int>
DirectMaskSubRunNoCache::regenerateAtlas(int begin, int end, GrMeshDrawTarget* target) const {
#if defined(SK_EXPERIMENTAL_ADD_ATLAS_PADDING)
if (fSupportBilerpAtlas) {
return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 1, target, true);
#else
} else {
return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 0, target, false);
#endif
}
}
// The 99% case. No clip. Non-color only.
@ -2389,7 +2400,10 @@ void GrSubRunNoCachePainter::processDeviceMasks(
auto addGlyphsWithSameFormat = [&] (const SkZip<SkGlyphVariant, SkPoint>& drawable,
GrMaskFormat format,
sk_sp<SkStrike>&& runStrike) {
this->draw(DirectMaskSubRunNoCache::Make(drawable, std::move(runStrike), format, fAlloc));
const bool padAtlas =
fSDC->recordingContext()->priv().options().fSupportBilerpFromGlyphAtlas;
this->draw(DirectMaskSubRunNoCache::Make(
drawable, std::move(runStrike), format, padAtlas, fAlloc));
};
add_multi_mask_format(addGlyphsWithSameFormat, drawables, std::move(strike));
@ -2818,11 +2832,7 @@ void DirectMaskSubRunSlug::testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache *cac
std::tuple<bool, int>
DirectMaskSubRunSlug::regenerateAtlas(int begin, int end, GrMeshDrawTarget* target) const {
#if defined(SK_EXPERIMENTAL_ADD_ATLAS_PADDING)
return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 1, target, true);
#else
return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 0, target, false);
#endif
return fGlyphs.regenerateAtlas(begin, end, fMaskFormat, 1, target, true);
}
// The 99% case. No clip. Non-color only.
@ -3662,6 +3672,8 @@ sk_sp<GrSlug>
SurfaceDrawContext::convertGlyphRunListToSlug(const SkMatrixProvider& viewMatrix,
const SkGlyphRunList& glyphRunList,
const SkPaint& paint) {
SkASSERT(fContext->priv().options().fSupportBilerpFromGlyphAtlas);
GrSDFTControl control =
this->recordingContext()->priv().getSDFTControl(
this->surfaceProps().isUseDeviceIndependentFonts());

View File

@ -222,6 +222,7 @@ public:
static sk_sp<GrTextBlob> Make(const SkGlyphRunList& glyphRunList,
const SkPaint& paint,
const SkMatrix& positionMatrix,
bool supportBilerpAtlas,
const GrSDFTControl& control,
SkGlyphRunListPainter* painter);
@ -238,6 +239,7 @@ public:
void addKey(const Key& key);
bool hasPerspective() const;
const SkMatrix& initialPositionMatrix() const { return fInitialPositionMatrix; }
bool supportBilerpAtlas() const { return fSupportBilerpAtlas; }
std::tuple<SkScalar, SkScalar> scaleBounds() const { return {fMaxMinScale, fMinMaxScale}; }
bool canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const;
@ -248,7 +250,10 @@ public:
const GrSubRunList& subRunList() const { return fSubRunList; }
private:
GrTextBlob(int allocSize, const SkMatrix& positionMatrix, SkColor initialLuminance);
GrTextBlob(int allocSize,
bool supportBilerpAtlas,
const SkMatrix& positionMatrix,
SkColor initialLuminance);
// Methods to satisfy SkGlyphRunPainterInterface
void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
@ -276,6 +281,9 @@ private:
// Overall size of this struct plus vertices and glyphs at the end.
const int fSize;
// Support using bilerp for directly mapped sub runs.
const bool fSupportBilerpAtlas;
// The initial view matrix combined with the initial origin. Used to determine if a cached
// subRun can be used in this draw situation.
const SkMatrix fInitialPositionMatrix;

View File

@ -52,8 +52,10 @@ void GrTextBlobCache::drawGlyphRunList(const GrClip* clip,
this->remove(blob.get());
}
const bool padAtlas =
sdc->recordingContext()->priv().options().fSupportBilerpFromGlyphAtlas;
blob = GrTextBlob::Make(
glyphRunList, paint, positionMatrix, control, sdc->glyphRunPainter());
glyphRunList, paint, positionMatrix, padAtlas, control, sdc->glyphRunPainter());
if (canCache) {
blob->addKey(key);

View File

@ -48,9 +48,6 @@
#include "src/image/SkSurface_Gpu.h"
#include "src/utils/SkUTF.h"
// Define this for testing text blob draw using a slug.
// #define SK_EXPERIMENTAL_SIMULATE_DRAWGLYPHRUNLIST_WITH_SLUG
#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fContext->priv().singleOwner())