Reland "Support clip masks for SaveLayerRec and drawSpecial in Ganesh"

This reverts commit 3c3b194f3b.

Reason for revert: Seems to be a problem with Inteliris 655, which already
 has an extensive blacklist, so adding this test to it

Original change's description:
> Revert "Support clip masks for SaveLayerRec and drawSpecial in Ganesh"
>
> This reverts commit 053b293993.
>
> Reason for revert: breaks on Intel Vulkan
>
> Original change's description:
> > Support clip masks for SaveLayerRec and drawSpecial in Ganesh
> >
> > Change-Id: I2e37e28fcbd3631bccc65253604015871503a089
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/205929
> > Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> > Reviewed-by: Robert Phillips <robertphillips@google.com>
> >
> Change-Id: Ic230fa9bcb16c97f218b94922a280f5b86a90491
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/206203
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: 8961
Change-Id: Ie32071bc2be7501066f7b6cf6d40cfb48dbd9986
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/206393
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
Michael Ludwig 2019-04-08 11:11:42 -04:00 committed by Skia Commit-Bot
parent 0d997665e6
commit beb7cd291a
5 changed files with 118 additions and 13 deletions

View File

@ -6,6 +6,7 @@
*/
#include "SkCanvasPriv.h"
#include "SkShaderMaskFilter.h"
#include "ToolUtils.h"
#include "gm.h"
@ -276,6 +277,63 @@ DEF_SIMPLE_GM(savelayer_coverage, canvas, 500, 500) {
canvas->restore();
}
DEF_SIMPLE_GM(savelayer_clipmask_maskfilter, canvas, 500, 500) {
// Offscreen surface for making the clip mask and mask filter images
auto surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(100, 100));
SkPaint maskPaint;
maskPaint.setColor(SK_ColorWHITE);
maskPaint.setAntiAlias(true);
// Draw a centered circle for the mask filter
surf->getCanvas()->clear(SK_ColorTRANSPARENT);
surf->getCanvas()->drawCircle(50.f, 50.f, 50.f, maskPaint);
auto maskFilterImage = surf->makeImageSnapshot();
sk_sp<SkMaskFilter> maskFilter = SkShaderMaskFilter::Make(maskFilterImage->makeShader());
// Cut out a cross for the clip mask
surf->getCanvas()->clear(SK_ColorTRANSPARENT);
surf->getCanvas()->drawRect(SkRect::MakeLTRB(0.f, 0.f, 40.f, 40.f), maskPaint);
surf->getCanvas()->drawRect(SkRect::MakeLTRB(60.f, 0.f, 100.f, 40.f), maskPaint);
surf->getCanvas()->drawRect(SkRect::MakeLTRB(0.f, 60.f, 40.f, 100.f), maskPaint);
surf->getCanvas()->drawRect(SkRect::MakeLTRB(60.f, 60.f, 100.f, 100.f), maskPaint);
auto clipMaskImage = surf->makeImageSnapshot();
SkMatrix clipMatrix = SkMatrix::I();
SkRect clipBounds = SkRect::MakeWH(100, 100);
// On the main canvas, save a 100x100 layer three times, applying clip mask, mask filter, or
// both, translating across the GM for each configuration.
canvas->clear(SK_ColorGRAY);
canvas->translate(25.f, 0.f);
// Clip mask only
SkCanvas::SaveLayerRec rec;
rec.fBounds = &clipBounds;
rec.fClipMask = clipMaskImage.get();
rec.fClipMatrix = &clipMatrix;
canvas->saveLayer(rec);
canvas->clear(SK_ColorWHITE);
canvas->restore();
canvas->translate(125.f, 0.f);
// Mask filter only
maskPaint.setMaskFilter(maskFilter);
rec.fClipMask = nullptr;
rec.fPaint = &maskPaint;
canvas->saveLayer(rec);
canvas->clear(SK_ColorWHITE);
canvas->restore();
canvas->translate(125.f, 0.f);
// Both
rec.fClipMask = clipMaskImage.get();
canvas->saveLayer(rec);
canvas->clear(SK_ColorWHITE);
canvas->restore();
}
#include "SkFont.h"
#include "SkGradientShader.h"
#include "SkTextBlob.h"

View File

@ -625,8 +625,6 @@ public:
clipMatrix uses alpha channel of image, transformed by clipMatrix, to clip
layer when drawn to SkCanvas.
Implementation is not complete; has no effect if SkBaseDevice is GPU-backed.
@param bounds layer dimensions; may be nullptr
@param paint graphics state applied to layer when overlaying prior
layer; may be nullptr

View File

@ -416,6 +416,10 @@
"vk",
"gm",
"_",
"savelayer_clipmask",
"vk",
"gm",
"_",
"aarectmodes",
"vk",
"gm",

View File

@ -668,6 +668,8 @@ def dm_flags(api, bot):
match.append('~FloatingPointTextureTest$')
if 'Vulkan' in bot and 'Win10' in bot and 'IntelIris655' in bot:
# skia:8961
blacklist(['vk', 'gm', '_', 'savelayer_clipmask'])
# skia:8659
blacklist(['vk', 'gm', '_', 'aarectmodes'])
blacklist(['vk', 'gm', '_', 'aaxfermodes'])

View File

@ -21,6 +21,7 @@
#include "GrTextureAdjuster.h"
#include "GrTracing.h"
#include "SkCanvasPriv.h"
#include "SkClipStack.h"
#include "SkDraw.h"
#include "SkGr.h"
#include "SkImageFilter.h"
@ -1021,8 +1022,6 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const
ASSERT_SINGLE_OWNER
GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice", "drawSpecial", fContext.get());
// TODO: clipImage support.
sk_sp<SkSpecialImage> result;
if (paint.getImageFilter()) {
SkIPoint offset = { 0, 0 };
@ -1046,10 +1045,11 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const
const GrPixelConfig config = proxy->config();
SkMatrix ctm = this->ctm();
ctm.postTranslate(-SkIntToScalar(left), -SkIntToScalar(top));
SkPaint tmpUnfiltered(paint);
if (tmpUnfiltered.getMaskFilter()) {
SkMatrix ctm = this->ctm();
ctm.postTranslate(-SkIntToScalar(left), -SkIntToScalar(top));
tmpUnfiltered.setMaskFilter(tmpUnfiltered.getMaskFilter()->makeWithMatrix(ctm));
}
@ -1071,14 +1071,57 @@ void SkGpuDevice::drawSpecial(SkSpecialImage* special, int left, int top, const
}
const SkIRect& subset = result->subset();
SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(left, top, subset.width(), subset.height()));
SkRect srcRect = SkRect::Make(subset);
if (clipImage) {
// Add the image as a simple texture effect applied to coverage. Accessing content outside
// of the clip image should behave as if it were a decal (i.e. zero coverage). However, to
// limit pixels touched and hardware checks, we draw the clip image geometry to get the
// decal effect.
GrSamplerState sampler = paint.getFilterQuality() > kNone_SkFilterQuality ?
GrSamplerState::ClampBilerp() : GrSamplerState::ClampNearest();
sk_sp<GrTextureProxy> clipProxy = as_IB(clipImage)->asTextureProxyRef(this->context(),
sampler, nullptr);
// Fold clip matrix into ctm
ctm.preConcat(clipMatrix);
SkMatrix inverseClipMatrix;
fRenderTargetContext->fillRectToRect(
this->clip(),
std::move(grPaint),
GrAA(tmpUnfiltered.isAntiAlias()),
SkMatrix::I(),
SkRect::Make(SkIRect::MakeXYWH(left, top, subset.width(), subset.height())),
SkRect::Make(subset));
std::unique_ptr<GrFragmentProcessor> cfp;
if (clipProxy && ctm.invert(&inverseClipMatrix)) {
cfp = GrSimpleTextureEffect::Make(std::move(clipProxy), inverseClipMatrix, sampler);
if (clipImage->colorType() != kAlpha_8_SkColorType) {
cfp = GrFragmentProcessor::SwizzleOutput(std::move(cfp), GrSwizzle::AAAA());
}
}
if (cfp) {
// If the grPaint already has coverage, this adds an additional stage that multiples
// the image's alpha channel with the prior coverage.
grPaint.addCoverageFragmentProcessor(std::move(cfp));
// Undo the offset that was needed for shader coord transforms to get the transform for
// the actual drawn geometry.
ctm.postTranslate(SkIntToScalar(left), SkIntToScalar(top));
inverseClipMatrix.preTranslate(-SkIntToScalar(left), -SkIntToScalar(top));
SkRect clipGeometry = SkRect::MakeWH(clipImage->width(), clipImage->height());
if (!clipGeometry.contains(inverseClipMatrix.mapRect(dstRect))) {
// Draw the clip geometry since it is smaller, using dstRect as an extra scissor
SkClipStack clip(this->cs());
clip.clipDevRect(SkIRect::MakeXYWH(left, top, subset.width(), subset.height()),
SkClipOp::kIntersect);
SkMatrix local = SkMatrix::Concat(SkMatrix::MakeRectToRect(
dstRect, srcRect, SkMatrix::kFill_ScaleToFit), ctm);
fRenderTargetContext->fillRectWithLocalMatrix(GrClipStackClip(&clip),
std::move(grPaint), GrAA(paint.isAntiAlias()), ctm, clipGeometry, local);
return;
}
// Else fall through and draw the subset since that is contained in the clip geometry
}
// Else some issue configuring the coverage FP, so just draw without the clip mask image
}
// Draw directly in screen space, possibly with an extra coverage processor
fRenderTargetContext->fillRectToRect(this->clip(), std::move(grPaint),
GrAA(paint.isAntiAlias()), SkMatrix::I(), dstRect, srcRect);
}
void SkGpuDevice::drawBitmapRect(const SkBitmap& bitmap,