Simplify scan converter's args
All scan converters need an SkIRect clipBounds and a bool containedInClip. However, we previously sent in an SkRegion and a SkIRect*, and convert them into clipBounds and containedInClip all over the places. This CL converts them only once inside do_fill_path and change all args to SkIRect and bool. Bug: skia: Change-Id: I05f1d76322942d8817860fd33991f7f7ce918e7c Reviewed-on: https://skia-review.googlesource.com/52741 Reviewed-by: Cary Clark <caryclark@google.com> Commit-Queue: Yuqian Li <liyuqian@google.com>
This commit is contained in:
parent
837c6c7c0c
commit
3a5e1fee08
@ -135,7 +135,7 @@ static inline bool TryBlitFatAntiRect(SkBlitter* blitter, const SkPath& path, co
|
||||
}
|
||||
|
||||
using FillPathFunc = std::function<void(const SkPath& path, SkBlitter* blitter, bool isInverse,
|
||||
const SkIRect& ir, const SkRegion* clipRgn, const SkIRect* clipRect, bool forceRLE)>;
|
||||
const SkIRect& ir, const SkIRect& clipBounds, bool containedInClip, bool forceRLE)>;
|
||||
|
||||
static inline void do_fill_path(const SkPath& path, const SkRegion& origClip, SkBlitter* blitter,
|
||||
bool forceRLE, const int SHIFT, FillPathFunc fillPathFunc) {
|
||||
@ -216,7 +216,7 @@ static inline void do_fill_path(const SkPath& path, const SkRegion& origClip, Sk
|
||||
|
||||
SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop);
|
||||
|
||||
fillPathFunc(path, blitter, isInverse, ir, clipRgn, clipRect, forceRLE);
|
||||
fillPathFunc(path, blitter, isInverse, ir, clipRgn->getBounds(), clipRect == nullptr, forceRLE);
|
||||
|
||||
if (isInverse) {
|
||||
sk_blit_below(blitter, ir, *clipRgn);
|
||||
|
@ -134,7 +134,7 @@ public:
|
||||
// We need this mask blitter because it significantly accelerates small path filling.
|
||||
class MaskAdditiveBlitter : public AdditiveBlitter {
|
||||
public:
|
||||
MaskAdditiveBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip,
|
||||
MaskAdditiveBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds,
|
||||
bool isInverse);
|
||||
~MaskAdditiveBlitter() override {
|
||||
fRealBlitter->blitMask(fMask, fClipRect);
|
||||
@ -202,7 +202,7 @@ private:
|
||||
};
|
||||
|
||||
MaskAdditiveBlitter::MaskAdditiveBlitter(
|
||||
SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip, bool isInverse) {
|
||||
SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds, bool isInverse) {
|
||||
SkASSERT(canHandleRect(ir));
|
||||
SkASSERT(!isInverse);
|
||||
|
||||
@ -217,7 +217,7 @@ MaskAdditiveBlitter::MaskAdditiveBlitter(
|
||||
fRow = nullptr;
|
||||
|
||||
fClipRect = ir;
|
||||
if (!fClipRect.intersect(clip.getBounds())) {
|
||||
if (!fClipRect.intersect(clipBounds)) {
|
||||
SkASSERT(0);
|
||||
fClipRect.setEmpty();
|
||||
}
|
||||
@ -276,7 +276,7 @@ void MaskAdditiveBlitter::blitAntiRect(int x, int y, int width, int height,
|
||||
|
||||
class RunBasedAdditiveBlitter : public AdditiveBlitter {
|
||||
public:
|
||||
RunBasedAdditiveBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip,
|
||||
RunBasedAdditiveBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds,
|
||||
bool isInverse);
|
||||
~RunBasedAdditiveBlitter() override;
|
||||
|
||||
@ -372,16 +372,16 @@ protected:
|
||||
};
|
||||
|
||||
RunBasedAdditiveBlitter::RunBasedAdditiveBlitter(
|
||||
SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip, bool isInverse) {
|
||||
SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds, bool isInverse) {
|
||||
fRealBlitter = realBlitter;
|
||||
|
||||
SkIRect sectBounds;
|
||||
if (isInverse) {
|
||||
// We use the clip bounds instead of the ir, since we may be asked to
|
||||
//draw outside of the rect when we're a inverse filltype
|
||||
sectBounds = clip.getBounds();
|
||||
sectBounds = clipBounds;
|
||||
} else {
|
||||
if (!sectBounds.intersect(ir, clip.getBounds())) {
|
||||
if (!sectBounds.intersect(ir, clipBounds)) {
|
||||
sectBounds.setEmpty();
|
||||
}
|
||||
}
|
||||
@ -471,8 +471,8 @@ int RunBasedAdditiveBlitter::getWidth() { return fWidth; }
|
||||
// In those cases, we can easily accumulate alpha greater than 0xFF.
|
||||
class SafeRLEAdditiveBlitter : public RunBasedAdditiveBlitter {
|
||||
public:
|
||||
SafeRLEAdditiveBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip,
|
||||
bool isInverse) : RunBasedAdditiveBlitter(realBlitter, ir, clip, isInverse) {}
|
||||
SafeRLEAdditiveBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds,
|
||||
bool isInverse) : RunBasedAdditiveBlitter(realBlitter, ir, clipBounds, isInverse) {}
|
||||
|
||||
void blitAntiH(int x, int y, const SkAlpha antialias[], int len) override;
|
||||
void blitAntiH(int x, int y, const SkAlpha alpha) override;
|
||||
@ -1675,9 +1675,7 @@ static SK_ALWAYS_INLINE void aaa_fill_path(const SkPath& path, const SkIRect& cl
|
||||
void SkScan::AAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter* blitter,
|
||||
bool forceRLE) {
|
||||
FillPathFunc fillPathFunc = [](const SkPath& path, SkBlitter* blitter, bool isInverse,
|
||||
const SkIRect& ir, const SkRegion* clipRgn, const SkIRect* clipRect, bool forceRLE){
|
||||
const SkIRect& clipBounds = clipRgn->getBounds();
|
||||
|
||||
const SkIRect& ir, const SkIRect& clipBounds, bool containedInClip, bool forceRLE){
|
||||
// The mask blitter (where we store intermediate alpha values directly in a mask, and then
|
||||
// call the real blitter once in the end to blit the whole mask) is faster than the RLE
|
||||
// blitter when the blit region is small enough (i.e., canHandleRect(ir)).
|
||||
@ -1687,16 +1685,16 @@ void SkScan::AAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter
|
||||
// much overhead. Hence we'll use blitFatAntiRect to avoid the mask and its overhead.
|
||||
if (MaskAdditiveBlitter::canHandleRect(ir) && !isInverse && !forceRLE) {
|
||||
#ifdef SK_SUPPORT_LEGACY_SMALLRECT_AA
|
||||
MaskAdditiveBlitter additiveBlitter(blitter, ir, *clipRgn, isInverse);
|
||||
MaskAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse);
|
||||
aaa_fill_path(path, clipBounds, &additiveBlitter, ir.fTop, ir.fBottom,
|
||||
clipRect == nullptr, true, forceRLE);
|
||||
containedInClip, true, forceRLE);
|
||||
#else
|
||||
// blitFatAntiRect is slower than the normal AAA flow without MaskAdditiveBlitter.
|
||||
// Hence only tryBlitFatAntiRect when MaskAdditiveBlitter would have been used.
|
||||
if (!TryBlitFatAntiRect(blitter, path, clipBounds)) {
|
||||
MaskAdditiveBlitter additiveBlitter(blitter, ir, *clipRgn, isInverse);
|
||||
MaskAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse);
|
||||
aaa_fill_path(path, clipBounds, &additiveBlitter, ir.fTop, ir.fBottom,
|
||||
clipRect == nullptr, true, forceRLE);
|
||||
containedInClip, true, forceRLE);
|
||||
}
|
||||
#endif
|
||||
} else if (!isInverse && path.isConvex()) {
|
||||
@ -1704,16 +1702,16 @@ void SkScan::AAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter
|
||||
// aaa_walk_convex_edges won't generate alphas above 255. Hence we don't need
|
||||
// SafeRLEAdditiveBlitter (which is slow due to clamping). The basic RLE blitter
|
||||
// RunBasedAdditiveBlitter would suffice.
|
||||
RunBasedAdditiveBlitter additiveBlitter(blitter, ir, *clipRgn, isInverse);
|
||||
RunBasedAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse);
|
||||
aaa_fill_path(path, clipBounds, &additiveBlitter, ir.fTop, ir.fBottom,
|
||||
clipRect == nullptr, false, forceRLE);
|
||||
containedInClip, false, forceRLE);
|
||||
} else {
|
||||
// If the filling area might not be convex, the more involved aaa_walk_edges would
|
||||
// be called and we have to clamp the alpha downto 255. The SafeRLEAdditiveBlitter
|
||||
// does that at a cost of performance.
|
||||
SafeRLEAdditiveBlitter additiveBlitter(blitter, ir, *clipRgn, isInverse);
|
||||
SafeRLEAdditiveBlitter additiveBlitter(blitter, ir, clipBounds, isInverse);
|
||||
aaa_fill_path(path, clipBounds, &additiveBlitter, ir.fTop, ir.fBottom,
|
||||
clipRect == nullptr, false, forceRLE);
|
||||
containedInClip, false, forceRLE);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
class BaseSuperBlitter : public SkBlitter {
|
||||
public:
|
||||
BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
|
||||
const SkRegion& clip, bool isInverse);
|
||||
const SkIRect& clipBounds, bool isInverse);
|
||||
|
||||
/// Must be explicitly defined on subclasses.
|
||||
virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
|
||||
@ -71,17 +71,17 @@ protected:
|
||||
SkIRect fSectBounds;
|
||||
};
|
||||
|
||||
BaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlit, const SkIRect& ir, const SkRegion& clip,
|
||||
bool isInverse) {
|
||||
BaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlit, const SkIRect& ir,
|
||||
const SkIRect& clipBounds, bool isInverse) {
|
||||
fRealBlitter = realBlit;
|
||||
|
||||
SkIRect sectBounds;
|
||||
if (isInverse) {
|
||||
// We use the clip bounds instead of the ir, since we may be asked to
|
||||
//draw outside of the rect when we're a inverse filltype
|
||||
sectBounds = clip.getBounds();
|
||||
sectBounds = clipBounds;
|
||||
} else {
|
||||
if (!sectBounds.intersect(ir, clip.getBounds())) {
|
||||
if (!sectBounds.intersect(ir, clipBounds)) {
|
||||
sectBounds.setEmpty();
|
||||
}
|
||||
}
|
||||
@ -102,7 +102,8 @@ BaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlit, const SkIRect& ir, const
|
||||
/// Run-length-encoded supersampling antialiased blitter.
|
||||
class SuperBlitter : public BaseSuperBlitter {
|
||||
public:
|
||||
SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip, bool isInverse);
|
||||
SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds,
|
||||
bool isInverse);
|
||||
|
||||
~SuperBlitter() override {
|
||||
this->flush();
|
||||
@ -147,9 +148,9 @@ private:
|
||||
int fOffsetX;
|
||||
};
|
||||
|
||||
SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip,
|
||||
SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect& clipBounds,
|
||||
bool isInverse)
|
||||
: BaseSuperBlitter(realBlitter, ir, clip, isInverse)
|
||||
: BaseSuperBlitter(realBlitter, ir, clipBounds, isInverse)
|
||||
{
|
||||
fRunsToBuffer = realBlitter->requestRowsPreserved();
|
||||
fRunsBuffer = realBlitter->allocBlitMemory(fRunsToBuffer * this->getRunsSz());
|
||||
@ -393,7 +394,7 @@ void SuperBlitter::blitRect(int x, int y, int width, int height) {
|
||||
/// Masked supersampling antialiased blitter.
|
||||
class MaskSuperBlitter : public BaseSuperBlitter {
|
||||
public:
|
||||
MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion&, bool isInverse);
|
||||
MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkIRect&, bool isInverse);
|
||||
~MaskSuperBlitter() override {
|
||||
fRealBlitter->blitMask(fMask, fClipRect);
|
||||
}
|
||||
@ -431,9 +432,9 @@ private:
|
||||
uint32_t fStorage[(kMAX_STORAGE >> 2) + 1];
|
||||
};
|
||||
|
||||
MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, const SkRegion& clip,
|
||||
bool isInverse)
|
||||
: BaseSuperBlitter(realBlitter, ir, clip, isInverse)
|
||||
MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
|
||||
const SkIRect& clipBounds, bool isInverse)
|
||||
: BaseSuperBlitter(realBlitter, ir, clipBounds, isInverse)
|
||||
{
|
||||
SkASSERT(CanHandleRect(ir));
|
||||
SkASSERT(!isInverse);
|
||||
@ -444,7 +445,7 @@ MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, co
|
||||
fMask.fFormat = SkMask::kA8_Format;
|
||||
|
||||
fClipRect = ir;
|
||||
if (!fClipRect.intersect(clip.getBounds())) {
|
||||
if (!fClipRect.intersect(clipBounds)) {
|
||||
SkASSERT(0);
|
||||
fClipRect.setEmpty();
|
||||
}
|
||||
@ -627,27 +628,16 @@ void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
|
||||
#endif
|
||||
|
||||
FillPathFunc fillPathFunc = [](const SkPath& path, SkBlitter* blitter, bool isInverse,
|
||||
const SkIRect& ir, const SkRegion* clipRgn, const SkIRect* clipRect, bool forceRLE){
|
||||
SkIRect superRect, *superClipRect = nullptr;
|
||||
if (clipRect) {
|
||||
superRect.set(SkLeftShift(clipRect->fLeft, SHIFT),
|
||||
SkLeftShift(clipRect->fTop, SHIFT),
|
||||
SkLeftShift(clipRect->fRight, SHIFT),
|
||||
SkLeftShift(clipRect->fBottom, SHIFT));
|
||||
superClipRect = &superRect;
|
||||
}
|
||||
|
||||
const SkIRect& ir, const SkIRect& clipBounds, bool containedInClip, bool forceRLE){
|
||||
// MaskSuperBlitter can't handle drawing outside of ir, so we can't use it
|
||||
// if we're an inverse filltype
|
||||
if (!isInverse && MaskSuperBlitter::CanHandleRect(ir) && !forceRLE) {
|
||||
MaskSuperBlitter superBlit(blitter, ir, *clipRgn, isInverse);
|
||||
MaskSuperBlitter superBlit(blitter, ir, clipBounds, isInverse);
|
||||
SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop);
|
||||
sk_fill_path(path, clipRgn->getBounds(), &superBlit, ir.fTop, ir.fBottom, SHIFT,
|
||||
superClipRect == nullptr);
|
||||
sk_fill_path(path, clipBounds, &superBlit, ir.fTop, ir.fBottom, SHIFT, containedInClip);
|
||||
} else {
|
||||
SuperBlitter superBlit(blitter, ir, *clipRgn, isInverse);
|
||||
sk_fill_path(path, clipRgn->getBounds(), &superBlit, ir.fTop, ir.fBottom, SHIFT,
|
||||
superClipRect == nullptr);
|
||||
SuperBlitter superBlit(blitter, ir, clipBounds, isInverse);
|
||||
sk_fill_path(path, clipBounds, &superBlit, ir.fTop, ir.fBottom, SHIFT, containedInClip);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -150,13 +150,12 @@ public:
|
||||
};
|
||||
|
||||
template<class Deltas> static SK_ALWAYS_INLINE
|
||||
void gen_alpha_deltas(const SkPath& path, const SkRegion& clipRgn, Deltas& result,
|
||||
void gen_alpha_deltas(const SkPath& path, const SkIRect& clipBounds, Deltas& result,
|
||||
SkBlitter* blitter, bool skipRect, bool pathContainedInClip) {
|
||||
// 1. Build edges
|
||||
SkEdgeBuilder builder;
|
||||
SkIRect ir = path.getBounds().roundOut();
|
||||
const SkIRect& clipRect = clipRgn.getBounds();
|
||||
int count = builder.build_edges(path, &clipRect, 0, pathContainedInClip,
|
||||
int count = builder.build_edges(path, &clipBounds, 0, pathContainedInClip,
|
||||
SkEdgeBuilder::kBezier);
|
||||
if (count == 0) {
|
||||
return;
|
||||
@ -266,7 +265,7 @@ void gen_alpha_deltas(const SkPath& path, const SkRegion& clipRgn, Deltas& resul
|
||||
if (lowerCeil <= upperFloor + SK_Fixed1) { // only one row is affected by the currE
|
||||
SkFixed rowHeight = currE->fLowerY - currE->fUpperY;
|
||||
SkFixed nextX = currE->fX + SkFixedMul(currE->fDX, rowHeight);
|
||||
if (iy >= clipRect.fTop && iy < clipRect.fBottom) {
|
||||
if (iy >= clipBounds.fTop && iy < clipBounds.fBottom) {
|
||||
add_coverage_delta_segment<true>(iy, rowHeight, currE, nextX, &result);
|
||||
}
|
||||
continue;
|
||||
@ -305,7 +304,8 @@ void gen_alpha_deltas(const SkPath& path, const SkRegion& clipRgn, Deltas& resul
|
||||
}
|
||||
|
||||
// last partial row
|
||||
if (SkIntToFixed(iy) < currE->fLowerY && iy >= clipRect.fTop && iy < clipRect.fBottom) {
|
||||
if (SkIntToFixed(iy) < currE->fLowerY &&
|
||||
iy >= clipBounds.fTop && iy < clipBounds.fBottom) {
|
||||
rowHeight = currE->fLowerY - SkIntToFixed(iy);
|
||||
nextX = currE->fX + SkFixedMul(currE->fDX, rowHeight);
|
||||
add_coverage_delta_segment<true>(iy, rowHeight, currE, nextX, &result);
|
||||
@ -319,12 +319,11 @@ void SkScan::DAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter
|
||||
bool forceRLE) {
|
||||
|
||||
FillPathFunc fillPathFunc = [](const SkPath& path, SkBlitter* blitter, bool isInverse,
|
||||
const SkIRect& ir, const SkRegion* clipRgn, const SkIRect* clipRect, bool forceRLE){
|
||||
const SkIRect& ir, const SkIRect& clipBounds, bool containedInClip, bool forceRLE){
|
||||
bool isEvenOdd = path.getFillType() & 1;
|
||||
bool isConvex = path.isConvex();
|
||||
bool skipRect = isConvex && !isInverse;
|
||||
|
||||
const SkIRect& clipBounds = clipRgn->getBounds();
|
||||
SkIRect clippedIR = ir;
|
||||
clippedIR.intersect(clipBounds);
|
||||
|
||||
@ -345,12 +344,12 @@ void SkScan::DAAFillPath(const SkPath& path, const SkRegion& origClip, SkBlitter
|
||||
// Everything before can be done out of order in the threaded backend.
|
||||
if (!forceRLE && !isInverse && SkCoverageDeltaMask::Suitable(clippedIR)) {
|
||||
SkCoverageDeltaMask deltaMask(&alloc, clippedIR);
|
||||
gen_alpha_deltas(path, *clipRgn, deltaMask, blitter, skipRect, clipRect == nullptr);
|
||||
gen_alpha_deltas(path, clipBounds, deltaMask, blitter, skipRect, containedInClip);
|
||||
deltaMask.convertCoverageToAlpha(isEvenOdd, isInverse, isConvex);
|
||||
blitter->blitMask(deltaMask.prepareSkMask(), clippedIR);
|
||||
} else {
|
||||
SkCoverageDeltaList deltaList(&alloc, clippedIR.fTop, clippedIR.fBottom, forceRLE);
|
||||
gen_alpha_deltas(path, *clipRgn, deltaList, blitter, skipRect, clipRect == nullptr);
|
||||
gen_alpha_deltas(path, clipBounds, deltaList, blitter, skipRect, containedInClip);
|
||||
blitter->blitCoverageDeltas(&deltaList, clipBounds, isEvenOdd, isInverse, isConvex);
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user