Fix image filter crop offsets for GPU path.

This is the GPU-side version of
https://codereview.chromium.org/112803004/.
Also factored the crop offset unit test into a function, so we can
call it with both CPU & GPU devices.

R=bsalomon@google.com

Review URL: https://codereview.chromium.org/153113003

git-svn-id: http://skia.googlecode.com/svn/trunk@13292 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
senorblanco@chromium.org 2014-02-03 22:22:16 +00:00
parent 29af1f35d7
commit aba651c3f1
3 changed files with 83 additions and 59 deletions

View File

@ -148,12 +148,14 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMa
#if SK_SUPPORT_GPU
SkBitmap input;
SkASSERT(fInputCount == 1);
if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, ctm, &input, offset)) {
SkIPoint srcOffset = SkIPoint::Make(0, 0);
if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, ctm, &input, &srcOffset)) {
return false;
}
GrTexture* srcTexture = input.getTexture();
SkIRect bounds;
src.getBounds(&bounds);
bounds.offset(srcOffset);
if (!this->applyCropRect(&bounds, ctm)) {
return false;
}
@ -173,6 +175,9 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMa
GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget());
GrContext::AutoClip acs(context, dstRect);
GrEffectRef* effect;
offset->fX = bounds.left();
offset->fY = bounds.top();
bounds.offset(-srcOffset);
SkMatrix matrix(ctm);
matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
this->asNewEffect(&effect, srcTexture, matrix, bounds);
@ -184,8 +189,6 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMa
SkAutoTUnref<GrTexture> resultTex(dst.detach());
SkImageFilterUtils::WrapTexture(resultTex, bounds.width(), bounds.height(), result);
offset->fX += bounds.left();
offset->fY += bounds.top();
return true;
#else
return false;

View File

@ -240,17 +240,22 @@ bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
SkBitmap* result, SkIPoint* offset) {
#if SK_SUPPORT_GPU
SkBitmap input;
if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) {
SkIPoint srcOffset = SkIPoint::Make(0, 0);
if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, &srcOffset)) {
return false;
}
GrTexture* source = input.getTexture();
SkIRect rect;
src.getBounds(&rect);
rect.offset(srcOffset);
if (!this->applyCropRect(&rect, ctm)) {
return false;
}
SkVector sigma, localSigma = SkVector::Make(fSigma.width(), fSigma.height());
ctm.mapVectors(&sigma, &localSigma, 1);
offset->fX = rect.fLeft;
offset->fY = rect.fTop;
rect.offset(-srcOffset);
SkAutoTUnref<GrTexture> tex(SkGpuBlurUtils::GaussianBlur(source->getContext(),
source,
false,
@ -258,8 +263,6 @@ bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
true,
sigma.x(),
sigma.y()));
offset->fX = rect.fLeft;
offset->fY = rect.fTop;
return SkImageFilterUtils::WrapTexture(tex, rect.width(), rect.height(), result);
#else
SkDEBUGFAIL("Should not call in GPU-less build");

View File

@ -26,6 +26,11 @@
#include "SkXfermodeImageFilter.h"
#include "Test.h"
#if SK_SUPPORT_GPU
#include "GrContextFactory.h"
#include "SkGpuDevice.h"
#endif
static const int kBitmapSize = 4;
static void make_small_bitmap(SkBitmap& bitmap) {
@ -156,64 +161,77 @@ DEF_TEST(ImageFilter, reporter) {
!bicubic->filterImage(&proxy, bitmap, SkMatrix::I(), &result, &loc));
}
}
}
{
// Check that all filters offset to their absolute crop rect,
// unaffected by the input crop rect.
// Tests pass by not asserting.
SkBitmap bitmap, temp;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
temp.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
bitmap.allocPixels();
temp.allocPixels();
bitmap.eraseARGB(0, 0, 0, 0);
SkBitmapDevice device(temp);
SkDeviceImageFilterProxy proxy(&device);
static void test_crop_rects(SkBaseDevice* device, skiatest::Reporter* reporter) {
// Check that all filters offset to their absolute crop rect,
// unaffected by the input crop rect.
// Tests pass by not asserting.
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
bitmap.allocPixels();
bitmap.eraseARGB(0, 0, 0, 0);
SkDeviceImageFilterProxy proxy(device);
SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
SkAutoTUnref<SkImageFilter> input(make_grayscale(NULL, &inputCropRect));
SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80));
SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60));
SkAutoTUnref<SkImageFilter> input(make_grayscale(NULL, &inputCropRect));
SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
SkPoint3 location(0, 0, SK_Scalar1);
SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
SkScalar kernel[9] = {
SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
};
SkISize kernelSize = SkISize::Make(3, 3);
SkScalar gain = SK_Scalar1, bias = 0;
SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode));
SkPoint3 location(0, 0, SK_Scalar1);
SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1);
SkScalar kernel[9] = {
SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
};
SkISize kernelSize = SkISize::Make(3, 3);
SkScalar gain = SK_Scalar1, bias = 0;
SkImageFilter* filters[] = {
SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
new SkDisplacementMapEffect(SkDisplacementMapEffect::kR_ChannelSelectorType,
SkDisplacementMapEffect::kB_ChannelSelectorType,
40.0f, input.get(), input.get(), &cropRect),
new SkBlurImageFilter(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
new SkDropShadowImageFilter(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input.get(), &cropRect),
SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
new SkMatrixConvolutionImageFilter(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
new SkMergeImageFilter(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
new SkOffsetImageFilter(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
new SkOffsetImageFilter(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
new SkDilateImageFilter(3, 2, input.get(), &cropRect),
new SkErodeImageFilter(2, 3, input.get(), &cropRect),
new SkTileImageFilter(inputCropRect.rect(), cropRect.rect(), input.get()),
new SkXfermodeImageFilter(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
};
SkImageFilter* filters[] = {
SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect),
new SkDisplacementMapEffect(SkDisplacementMapEffect::kR_ChannelSelectorType,
SkDisplacementMapEffect::kB_ChannelSelectorType,
40.0f, input.get(), input.get(), &cropRect),
new SkBlurImageFilter(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
new SkDropShadowImageFilter(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input.get(), &cropRect),
SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect),
SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect),
new SkMatrixConvolutionImageFilter(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect),
new SkMergeImageFilter(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect),
new SkOffsetImageFilter(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
new SkOffsetImageFilter(SK_Scalar1, SK_Scalar1, input.get(), &cropRect),
new SkDilateImageFilter(3, 2, input.get(), &cropRect),
new SkErodeImageFilter(2, 3, input.get(), &cropRect),
new SkTileImageFilter(inputCropRect.rect(), cropRect.rect(), input.get()),
new SkXfermodeImageFilter(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect),
};
for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
SkImageFilter* filter = filters[i];
SkBitmap result;
SkIPoint offset;
REPORTER_ASSERT(reporter, filter->filterImage(&proxy, bitmap, SkMatrix::I(), &result, &offset));
REPORTER_ASSERT(reporter, offset.fX == 20 && offset.fY == 30);
}
for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
SkImageFilter* filter = filters[i];
SkBitmap result;
SkIPoint offset;
SkString str;
str.printf("filter %ld", i);
REPORTER_ASSERT_MESSAGE(reporter, filter->filterImage(&proxy, bitmap, SkMatrix::I(), &result, &offset), str.c_str());
REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str());
}
for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
SkSafeUnref(filters[i]);
}
for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
SkSafeUnref(filters[i]);
}
}
DEF_TEST(ImageFilterCropRect, reporter) {
SkBitmap temp;
temp.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
temp.allocPixels();
SkBitmapDevice device(temp);
test_crop_rects(&device, reporter);
}
DEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) {
GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0));
SkGpuDevice device(context, SkBitmap::kARGB_8888_Config, 100, 100);
test_crop_rects(&device, reporter);
}