From 4a1f5fc94295c5861af74dd35e1c44a8ce55f9e8 Mon Sep 17 00:00:00 2001 From: Herb Derby Date: Fri, 10 Jul 2020 16:39:28 -0400 Subject: [PATCH] move makeAtlasTextOp to SubRun When SubRun is sub classable, makeAtlasTextOp will be part of the virtual API. Change-Id: Ib316bca200de38c5aba64e0bef5fa43966e6f13a Reviewed-on: https://skia-review.googlesource.com/c/skia/+/301983 Reviewed-by: Robert Phillips Commit-Queue: Herb Derby --- src/gpu/GrRenderTargetContext.cpp | 134 +----------------------------- src/gpu/GrRenderTargetContext.h | 10 --- src/gpu/ops/GrAtlasTextOp.cpp | 2 +- src/gpu/text/GrTextBlob.cpp | 131 +++++++++++++++++++++++++++++ src/gpu/text/GrTextBlob.h | 7 ++ 5 files changed, 140 insertions(+), 144 deletions(-) diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 2dbdb5bb21ae6..59f9c0639402f 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -47,7 +47,6 @@ #include "src/gpu/GrTracing.h" #include "src/gpu/SkGr.h" #include "src/gpu/effects/GrBicubicEffect.h" -#include "src/gpu/effects/GrDistanceFieldGeoProc.h" #include "src/gpu/effects/GrRRectEffect.h" #include "src/gpu/geometry/GrQuad.h" #include "src/gpu/geometry/GrQuadUtils.h" @@ -480,137 +479,6 @@ void GrRenderTargetContext::drawTextPaths(const GrClip* clip, } } -static SkPMColor4f generate_filtered_color(const SkPaint& paint, const GrColorInfo& colorInfo) { - SkColor4f c = paint.getColor4f(); - if (auto* xform = colorInfo.colorSpaceXformFromSRGB()) { - c = xform->apply(c); - } - if (auto* cf = paint.getColorFilter()) { - c = cf->filterColor4f(c, colorInfo.colorSpace(), colorInfo.colorSpace()); - } - return c.premul(); -} - -std::tuple> -GrRenderTargetContext::makeAtlasTextOp(const GrClip* clip, - const SkMatrixProvider& viewMatrix, - const SkGlyphRunList& glyphRunList, - GrTextBlob::SubRun* subRun) { - SkASSERT(subRun->glyphCount() != 0); - - SkPoint drawOrigin = glyphRunList.origin(); - const SkPaint& drawPaint = glyphRunList.paint(); - const SkMatrix& drawMatrix = viewMatrix.localToDevice(); - GrRecordingContext* context = this->fContext; - GrOpMemoryPool* pool = context->priv().opMemoryPool(); - const GrColorInfo& colorInfo = this->colorInfo(); - - // We can clip geometrically using clipRect and ignore clip if we're not using SDFs or - // transformed glyphs, and we have an axis-aligned rectangular non-AA clip. - std::unique_ptr op; - if (!subRun->drawAsDistanceFields()) { - SkIRect clipRect = SkIRect::MakeEmpty(); - if (!subRun->needsTransform()) { - // We only need to do clipping work if the SubRun isn't contained by the clip - SkRect subRunBounds = subRun->deviceRect(drawMatrix, drawOrigin); - SkRect renderTargetBounds = SkRect::MakeWH(this->width(), this->height()); - if (clip == nullptr && !renderTargetBounds.intersects(subRunBounds)) { - // If the SubRun is completely outside, don't add an op for it. - return {nullptr, nullptr}; - } else if (clip != nullptr) { - GrClip::PreClipResult result = clip->preApply(subRunBounds); - if (result.fEffect == GrClip::Effect::kClipped) { - if (result.fIsRRect && result.fRRect.isRect() && - result.fAA == GrAA::kNo) { - // Clip geometrically during onPrepare using clipRect. - result.fRRect.getBounds().round(&clipRect); - clip = nullptr; - } - } else if (result.fEffect == GrClip::Effect::kClippedOut) { - return {nullptr, nullptr}; - } - } - } - - if (!clipRect.isEmpty()) { SkASSERT(clip == nullptr); } - - // Produce the Bitmap Op. - GrPaint grPaint; - if (kARGB_GrMaskFormat == subRun->maskFormat()) { - SkPaintToGrPaintWithPrimitiveColor( - context, colorInfo, drawPaint, viewMatrix, &grPaint); - } else { - SkPaintToGrPaint(context, colorInfo, drawPaint, viewMatrix, &grPaint); - } - - // This is the color the op will use to draw. - SkPMColor4f drawingColor = generate_filtered_color(drawPaint, colorInfo); - - GrAtlasTextOp::MaskType maskType = [&]() { - switch (subRun->maskFormat()) { - case kA8_GrMaskFormat: return GrAtlasTextOp::kGrayscaleCoverageMask_MaskType; - case kA565_GrMaskFormat: return GrAtlasTextOp::kLCDCoverageMask_MaskType; - case kARGB_GrMaskFormat: return GrAtlasTextOp::kColorBitmapMask_MaskType; - // Needed to placate some compilers. - default: return GrAtlasTextOp::kGrayscaleCoverageMask_MaskType; - } - }(); - - op = pool->allocate(maskType, - std::move(grPaint), - subRun, - drawMatrix, - drawOrigin, - clipRect, - drawingColor, - 0, - false, - 0); - } else { - GrPaint grPaint; - SkPaintToGrPaint(context, colorInfo, drawPaint, viewMatrix, &grPaint); - - // This is the color the op will use to draw. - SkPMColor4f drawingColor = generate_filtered_color(drawPaint, colorInfo); - - const SkSurfaceProps& props = this->surfaceProps(); - bool isBGR = SkPixelGeometryIsBGR(props.pixelGeometry()); - bool isLCD = subRun->hasUseLCDText() && SkPixelGeometryIsH(props.pixelGeometry()); - using MT = GrAtlasTextOp::MaskType; - MT maskType = !subRun->isAntiAliased() ? MT::kAliasedDistanceField_MaskType - : isLCD ? (isBGR ? MT::kLCDBGRDistanceField_MaskType - : MT::kLCDDistanceField_MaskType) - : MT::kGrayscaleDistanceField_MaskType; - - bool useGammaCorrectDistanceTable = colorInfo.isLinearlyBlended(); - uint32_t DFGPFlags = drawMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; - DFGPFlags |= drawMatrix.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0; - DFGPFlags |= drawMatrix.hasPerspective() ? kPerspective_DistanceFieldEffectFlag : 0; - DFGPFlags |= useGammaCorrectDistanceTable ? kGammaCorrect_DistanceFieldEffectFlag : 0; - DFGPFlags |= MT::kAliasedDistanceField_MaskType == maskType ? - kAliased_DistanceFieldEffectFlag : 0; - - if (isLCD) { - DFGPFlags |= kUseLCD_DistanceFieldEffectFlag; - DFGPFlags |= MT::kLCDBGRDistanceField_MaskType == maskType ? - kBGR_DistanceFieldEffectFlag : 0; - } - - op = pool->allocate(maskType, - std::move(grPaint), - subRun, - drawMatrix, - drawOrigin, - SkIRect::MakeEmpty(), - drawingColor, - SkPaintPriv::ComputeLuminanceColor(drawPaint), - useGammaCorrectDistanceTable, - DFGPFlags); - } - - return {clip, std::move(op)}; -} - void GrRenderTargetContext::drawGlyphRunList(const GrClip* clip, const SkMatrixProvider& viewMatrix, const SkGlyphRunList& glyphRunList) { @@ -694,7 +562,7 @@ void GrRenderTargetContext::drawGlyphRunList(const GrClip* clip, if (subRun->drawAsPaths()) { this->drawTextPaths(clip, viewMatrix, glyphRunList, subRun); } else { - auto [drawingClip, op] = this->makeAtlasTextOp(clip, viewMatrix, glyphRunList, subRun); + auto [drawingClip, op] = subRun->makeAtlasTextOp(clip, viewMatrix, glyphRunList, this); if (op != nullptr) { this->addDrawOp(drawingClip, std::move(op)); } diff --git a/src/gpu/GrRenderTargetContext.h b/src/gpu/GrRenderTargetContext.h index e4db7c8bc51c0..3a5acf009049a 100644 --- a/src/gpu/GrRenderTargetContext.h +++ b/src/gpu/GrRenderTargetContext.h @@ -518,16 +518,6 @@ class GrRenderTargetContext : public GrSurfaceContext, public GrOpsTaskClosedObs const SkGlyphRunList& glyphRunList, GrTextBlob::SubRun* subRun); - /** - * Make the AtlasTextOp - returns the op and the original clip or nullptr for the clip if the - * op is going to clip geometrically. - */ - std::tuple> - makeAtlasTextOp(const GrClip*, - const SkMatrixProvider& viewMatrix, - const SkGlyphRunList& glyphRunList, - GrTextBlob::SubRun* subRun); - /** * Draw the text specified by the SkGlyphRunList. * diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp index 6714077e74c58..71c4c60ef0f9c 100644 --- a/src/gpu/ops/GrAtlasTextOp.cpp +++ b/src/gpu/ops/GrAtlasTextOp.cpp @@ -509,7 +509,7 @@ std::unique_ptr GrAtlasTextOp::CreateOpTestingOnly(GrRenderTargetConte std::unique_ptr op; std::tie(std::ignore, op) = - rtc->makeAtlasTextOp(nullptr, mtxProvider, glyphRunList, blob->firstSubRun()); + blob->firstSubRun()->makeAtlasTextOp(nullptr, mtxProvider, glyphRunList, rtc); return op; } diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp index e3fcad861ebee..3701b09476f5e 100644 --- a/src/gpu/text/GrTextBlob.cpp +++ b/src/gpu/text/GrTextBlob.cpp @@ -7,6 +7,7 @@ #include "include/core/SkColorFilter.h" #include "include/gpu/GrContext.h" +#include "include/gpu/GrRecordingContext.h" #include "include/private/SkTemplates.h" #include "src/core/SkMaskFilterBase.h" #include "src/core/SkMatrixPriv.h" @@ -15,7 +16,13 @@ #include "src/core/SkStrikeSpec.h" #include "src/gpu/GrBlurUtils.h" #include "src/gpu/GrClip.h" +#include "src/gpu/GrMemoryPool.h" +#include "src/gpu/GrRecordingContextPriv.h" +#include "src/gpu/GrRenderTargetContext.h" +#include "src/gpu/GrRenderTargetContextPriv.h" #include "src/gpu/GrStyle.h" +#include "src/gpu/SkGr.h" +#include "src/gpu/effects/GrDistanceFieldGeoProc.h" #include "src/gpu/geometry/GrStyledShape.h" #include "src/gpu/ops/GrAtlasTextOp.h" #include "src/gpu/text/GrAtlasManager.h" @@ -58,6 +65,130 @@ GrTextBlob::SubRun::SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec) , fVertexBounds{SkRect::MakeEmpty()} , fVertexData{SkSpan{}} { } +static SkPMColor4f generate_filtered_color(const SkPaint& paint, const GrColorInfo& colorInfo) { + SkColor4f c = paint.getColor4f(); + if (auto* xform = colorInfo.colorSpaceXformFromSRGB()) { + c = xform->apply(c); + } + if (auto* cf = paint.getColorFilter()) { + c = cf->filterColor4f(c, colorInfo.colorSpace(), colorInfo.colorSpace()); + } + return c.premul(); +} + +std::tuple > +GrTextBlob::SubRun::makeAtlasTextOp(const GrClip* clip, + const SkMatrixProvider& viewMatrix, + const SkGlyphRunList& glyphRunList, + GrRenderTargetContext* rtc) { + SkASSERT(this->glyphCount() != 0); + + SkPoint drawOrigin = glyphRunList.origin(); + const SkPaint& drawPaint = glyphRunList.paint(); + const SkMatrix& drawMatrix = viewMatrix.localToDevice(); + GrRecordingContext* context = rtc->priv().getContext(); + GrOpMemoryPool* pool = context->priv().opMemoryPool(); + const GrColorInfo& colorInfo = rtc->colorInfo(); + + // This is the color the op will use to draw. + SkPMColor4f drawingColor = generate_filtered_color(drawPaint, colorInfo); + + GrPaint grPaint; + if (this->maskFormat() == kARGB_GrMaskFormat) { + SkPaintToGrPaintWithPrimitiveColor( + context, colorInfo, drawPaint, viewMatrix, &grPaint); + } else { + SkPaintToGrPaint(context, colorInfo, drawPaint, viewMatrix, &grPaint); + } + + // We can clip geometrically using clipRect and ignore clip if we're not using SDFs or + // transformed glyphs, and we have an axis-aligned rectangular non-AA clip. + std::unique_ptr op; + if (!this->drawAsDistanceFields()) { + SkIRect clipRect = SkIRect::MakeEmpty(); + if (!this->needsTransform()) { + // We only need to do clipping work if the SubRun isn't contained by the clip + SkRect subRunBounds = this->deviceRect(drawMatrix, drawOrigin); + SkRect renderTargetBounds = SkRect::MakeWH(rtc->width(), rtc->height()); + if (clip == nullptr && !renderTargetBounds.intersects(subRunBounds)) { + // If the SubRun is completely outside, don't add an op for it. + return {nullptr, nullptr}; + } else if (clip != nullptr) { + GrClip::PreClipResult result = clip->preApply(subRunBounds); + if (result.fEffect == GrClip::Effect::kClipped) { + if (result.fIsRRect && result.fRRect.isRect() && + result.fAA == GrAA::kNo) { + // Clip geometrically during onPrepare using clipRect. + result.fRRect.getBounds().round(&clipRect); + clip = nullptr; + } + } else if (result.fEffect == GrClip::Effect::kClippedOut) { + return {nullptr, nullptr}; + } + } + } + + if (!clipRect.isEmpty()) { SkASSERT(clip == nullptr); } + + GrAtlasTextOp::MaskType maskType = [&]() { + switch (this->maskFormat()) { + case kA8_GrMaskFormat: return GrAtlasTextOp::kGrayscaleCoverageMask_MaskType; + case kA565_GrMaskFormat: return GrAtlasTextOp::kLCDCoverageMask_MaskType; + case kARGB_GrMaskFormat: return GrAtlasTextOp::kColorBitmapMask_MaskType; + // Needed to placate some compilers. + default: return GrAtlasTextOp::kGrayscaleCoverageMask_MaskType; + } + }(); + + op = pool->allocate(maskType, + std::move(grPaint), + this, + drawMatrix, + drawOrigin, + clipRect, + drawingColor, + 0, + false, + 0); + } else { + const SkSurfaceProps& props = rtc->surfaceProps(); + bool isBGR = SkPixelGeometryIsBGR(props.pixelGeometry()); + bool isLCD = this->hasUseLCDText() && SkPixelGeometryIsH(props.pixelGeometry()); + using MT = GrAtlasTextOp::MaskType; + MT maskType = !this->isAntiAliased() ? MT::kAliasedDistanceField_MaskType + : isLCD ? (isBGR ? MT::kLCDBGRDistanceField_MaskType + : MT::kLCDDistanceField_MaskType) + : MT::kGrayscaleDistanceField_MaskType; + + bool useGammaCorrectDistanceTable = colorInfo.isLinearlyBlended(); + uint32_t DFGPFlags = drawMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0; + DFGPFlags |= drawMatrix.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0; + DFGPFlags |= drawMatrix.hasPerspective() ? kPerspective_DistanceFieldEffectFlag : 0; + DFGPFlags |= useGammaCorrectDistanceTable ? kGammaCorrect_DistanceFieldEffectFlag : 0; + DFGPFlags |= MT::kAliasedDistanceField_MaskType == maskType ? + kAliased_DistanceFieldEffectFlag : 0; + + if (isLCD) { + DFGPFlags |= kUseLCD_DistanceFieldEffectFlag; + DFGPFlags |= MT::kLCDBGRDistanceField_MaskType == maskType ? + kBGR_DistanceFieldEffectFlag : 0; + } + + op = pool->allocate(maskType, + std::move(grPaint), + this, + drawMatrix, + drawOrigin, + SkIRect::MakeEmpty(), + drawingColor, + SkPaintPriv::ComputeLuminanceColor(drawPaint), + useGammaCorrectDistanceTable, + DFGPFlags); + } + + return {clip, std::move(op)}; +} + void GrTextBlob::SubRun::resetBulkUseToken() { fBulkUseToken.reset(); } GrDrawOpAtlas::BulkUseTokenUpdater* GrTextBlob::SubRun::bulkUseToken() { return &fBulkUseToken; } diff --git a/src/gpu/text/GrTextBlob.h b/src/gpu/text/GrTextBlob.h index 527014bd65535..e629e63647e0c 100644 --- a/src/gpu/text/GrTextBlob.h +++ b/src/gpu/text/GrTextBlob.h @@ -25,6 +25,7 @@ class GrAtlasManager; class GrAtlasTextOp; class GrDeferredUploadTarget; +class GrDrawOp; class GrGlyph; class GrStrikeCache; @@ -264,6 +265,12 @@ class GrTextBlob::SubRun { // SubRun for paths SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec); + std::tuple> + makeAtlasTextOp(const GrClip* clip, + const SkMatrixProvider& viewMatrix, + const SkGlyphRunList& glyphRunList, + GrRenderTargetContext* rtc); + // TODO when this object is more internal, drop the privacy void resetBulkUseToken(); GrDrawOpAtlas::BulkUseTokenUpdater* bulkUseToken();