Reland "Support clip masks for SaveLayerRec and drawSpecial in Ganesh"
This reverts commit3c3b194f3b
. 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 commit053b293993
. > > 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:
parent
0d997665e6
commit
beb7cd291a
@ -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"
|
||||
|
@ -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
|
||||
|
@ -416,6 +416,10 @@
|
||||
"vk",
|
||||
"gm",
|
||||
"_",
|
||||
"savelayer_clipmask",
|
||||
"vk",
|
||||
"gm",
|
||||
"_",
|
||||
"aarectmodes",
|
||||
"vk",
|
||||
"gm",
|
||||
|
@ -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'])
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user