Skip to content

Commit

Permalink
move makeAtlasTextOp to SubRun
Browse files Browse the repository at this point in the history
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 <robertphillips@google.com>
Commit-Queue: Herb Derby <herb@google.com>
  • Loading branch information
herbderby authored and Skia Commit-Bot committed Jul 10, 2020
1 parent 4284f75 commit 4a1f5fc
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 144 deletions.
134 changes: 1 addition & 133 deletions src/gpu/GrRenderTargetContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<const GrClip*, std::unique_ptr<GrDrawOp>>
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<GrDrawOp> 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<GrAtlasTextOp>(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<GrAtlasTextOp>(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) {
Expand Down Expand Up @@ -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));
}
Expand Down
10 changes: 0 additions & 10 deletions src/gpu/GrRenderTargetContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<const GrClip*, std::unique_ptr<GrDrawOp>>
makeAtlasTextOp(const GrClip*,
const SkMatrixProvider& viewMatrix,
const SkGlyphRunList& glyphRunList,
GrTextBlob::SubRun* subRun);

/**
* Draw the text specified by the SkGlyphRunList.
*
Expand Down
2 changes: 1 addition & 1 deletion src/gpu/ops/GrAtlasTextOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ std::unique_ptr<GrDrawOp> GrAtlasTextOp::CreateOpTestingOnly(GrRenderTargetConte

std::unique_ptr<GrDrawOp> op;
std::tie(std::ignore, op) =
rtc->makeAtlasTextOp(nullptr, mtxProvider, glyphRunList, blob->firstSubRun());
blob->firstSubRun()->makeAtlasTextOp(nullptr, mtxProvider, glyphRunList, rtc);
return op;
}

Expand Down
131 changes: 131 additions & 0 deletions src/gpu/text/GrTextBlob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -58,6 +65,130 @@ GrTextBlob::SubRun::SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec)
, fVertexBounds{SkRect::MakeEmpty()}
, fVertexData{SkSpan<VertexData>{}} { }

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<const GrClip*, std::unique_ptr<GrDrawOp> >
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<GrDrawOp> 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<GrAtlasTextOp>(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<GrAtlasTextOp>(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; }
Expand Down
7 changes: 7 additions & 0 deletions src/gpu/text/GrTextBlob.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
class GrAtlasManager;
class GrAtlasTextOp;
class GrDeferredUploadTarget;
class GrDrawOp;
class GrGlyph;
class GrStrikeCache;

Expand Down Expand Up @@ -264,6 +265,12 @@ class GrTextBlob::SubRun {
// SubRun for paths
SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec);

std::tuple<const GrClip*, std::unique_ptr<GrDrawOp>>
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();
Expand Down

0 comments on commit 4a1f5fc

Please sign in to comment.