Fix two GPU image filters handling of subset inputs

Added a GM that demonstrates the bug. Should draw a blur with
the center masked out, and a circular blurry shape that's
roughly the inverse. On raster, this was already the result.
On GPU, the blurred/eroded layer becomes a subset with an
origin other than (0,0), and that layer was shifted.

I *think* this is the correct fix - we are including 'offset'
in the texture matrices, but that's just based on the crop
rects and adjustments from each filter. We still need to adjust
the texture coords for the subsets themselves.

Bug: chromium:905548
Change-Id: I19c936adad90311aef243a9395a270d2e015df2f
Reviewed-on: https://skia-review.googlesource.com/c/173321
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Brian Osman 2018-12-03 11:17:51 -05:00 committed by Skia Commit-Bot
parent 7e000220c3
commit c32aeb326e
4 changed files with 59 additions and 12 deletions

38
gm/crbug_905548.cpp Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "gm.h"
#include "SkArithmeticImageFilter.h"
#include "SkBlurImageFilter.h"
#include "SkImageSource.h"
#include "SkMorphologyImageFilter.h"
#include "SkSurface.h"
#include "SkXfermodeImageFilter.h"
DEF_SIMPLE_GM(crbug_905548, canvas, 100, 200) {
auto surface = canvas->makeSurface(SkImageInfo::MakeN32Premul(100, 100));
if (!surface) {
surface = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(100, 100));
}
surface->getCanvas()->clear(0);
surface->getCanvas()->drawCircle(50, 50, 45, SkPaint());
auto imageSource = SkImageSource::Make(surface->makeImageSnapshot());
auto blurred = SkBlurImageFilter::Make(15, 15, imageSource);
auto eroded = SkErodeImageFilter::Make(0, 0, blurred);
auto blended = SkXfermodeImageFilter::Make(SkBlendMode::kDstOut, eroded, imageSource, nullptr);
SkPaint paint;
paint.setImageFilter(blended);
canvas->drawRect(SkRect::MakeWH(100, 100), paint);
auto mult = SkArithmeticImageFilter::Make(1, 0, 0, 0, false, eroded, imageSource, nullptr);
paint.setImageFilter(mult);
canvas->translate(0, 100);
canvas->drawRect(SkRect::MakeWH(100, 100), paint);
}

View File

@ -102,6 +102,7 @@ gm_sources = [
"$_gm/crbug_887103.cpp",
"$_gm/crbug_892988.cpp",
"$_gm/crbug_899512.cpp",
"$_gm/crbug_905548.cpp",
"$_gm/croppedrects.cpp",
"$_gm/crosscontextimage.cpp",
"$_gm/cubicpaths.cpp",

View File

@ -308,11 +308,13 @@ sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
std::unique_ptr<GrFragmentProcessor> bgFP;
if (backgroundProxy) {
SkMatrix backgroundMatrix = SkMatrix::MakeTrans(-SkIntToScalar(backgroundOffset.fX),
-SkIntToScalar(backgroundOffset.fY));
SkIRect bgSubset = background->subset();
SkMatrix backgroundMatrix = SkMatrix::MakeTrans(
SkIntToScalar(bgSubset.left() - backgroundOffset.fX),
SkIntToScalar(bgSubset.top() - backgroundOffset.fY));
bgFP = GrTextureDomainEffect::Make(
std::move(backgroundProxy), backgroundMatrix,
GrTextureDomain::MakeTexelDomain(background->subset()),
GrTextureDomain::MakeTexelDomain(bgSubset),
GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
bgFP = GrColorSpaceXformEffect::Make(std::move(bgFP), background->getColorSpace(),
background->alphaType(),
@ -323,11 +325,13 @@ sk_sp<SkSpecialImage> ArithmeticImageFilterImpl::filterImageGPU(
}
if (foregroundProxy) {
SkMatrix foregroundMatrix = SkMatrix::MakeTrans(-SkIntToScalar(foregroundOffset.fX),
-SkIntToScalar(foregroundOffset.fY));
SkIRect fgSubset = foreground->subset();
SkMatrix foregroundMatrix = SkMatrix::MakeTrans(
SkIntToScalar(fgSubset.left() - foregroundOffset.fX),
SkIntToScalar(fgSubset.top() - foregroundOffset.fY));
auto foregroundFP = GrTextureDomainEffect::Make(
std::move(foregroundProxy), foregroundMatrix,
GrTextureDomain::MakeTexelDomain(foreground->subset()),
GrTextureDomain::MakeTexelDomain(fgSubset),
GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
foregroundFP = GrColorSpaceXformEffect::Make(std::move(foregroundFP),
foreground->getColorSpace(),

View File

@ -276,10 +276,12 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU(
std::unique_ptr<GrFragmentProcessor> bgFP;
if (backgroundProxy) {
SkMatrix bgMatrix = SkMatrix::MakeTrans(-SkIntToScalar(backgroundOffset.fX),
-SkIntToScalar(backgroundOffset.fY));
SkIRect bgSubset = background->subset();
SkMatrix bgMatrix = SkMatrix::MakeTrans(
SkIntToScalar(bgSubset.left() - backgroundOffset.fX),
SkIntToScalar(bgSubset.top() - backgroundOffset.fY));
bgFP = GrTextureDomainEffect::Make(std::move(backgroundProxy), bgMatrix,
GrTextureDomain::MakeTexelDomain(background->subset()),
GrTextureDomain::MakeTexelDomain(bgSubset),
GrTextureDomain::kDecal_Mode,
GrSamplerState::Filter::kNearest);
bgFP = GrColorSpaceXformEffect::Make(std::move(bgFP), background->getColorSpace(),
@ -291,11 +293,13 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU(
}
if (foregroundProxy) {
SkMatrix fgMatrix = SkMatrix::MakeTrans(-SkIntToScalar(foregroundOffset.fX),
-SkIntToScalar(foregroundOffset.fY));
SkIRect fgSubset = foreground->subset();
SkMatrix fgMatrix = SkMatrix::MakeTrans(
SkIntToScalar(fgSubset.left() - foregroundOffset.fX),
SkIntToScalar(fgSubset.top() - foregroundOffset.fY));
auto foregroundFP = GrTextureDomainEffect::Make(
std::move(foregroundProxy), fgMatrix,
GrTextureDomain::MakeTexelDomain(foreground->subset()),
GrTextureDomain::MakeTexelDomain(fgSubset),
GrTextureDomain::kDecal_Mode, GrSamplerState::Filter::kNearest);
foregroundFP = GrColorSpaceXformEffect::Make(std::move(foregroundFP),
foreground->getColorSpace(),