change SkImage_Gpu to handle all filters (w/ and w/o gpu support
The result is that the set of "generic" imagefilters (e.g. SkColorFilterImageFilter) that use drawing commands to return their results will now stay in the same domain as their src (i.e. gpu-src --> gpu-dst). ApplyFilterGM exercises this, and now asserts this same-domain invariant. BUG=skia:4467 Review URL: https://codereview.chromium.org/1401053003
This commit is contained in:
parent
1a197ea31e
commit
59dc0d22f5
@ -141,6 +141,11 @@ typedef SkImageFilter* (*ImageFilterFactory)();
|
||||
// hence this cast function
|
||||
template <typename T> ImageFilterFactory IFCCast(T arg) { return arg; }
|
||||
|
||||
// We expect that applying the filter will keep us in the same domain (raster or gpu)
|
||||
static void check_same_domain(SkImage* a, SkImage* b) {
|
||||
SkASSERT(a->isTextureBacked() == b->isTextureBacked());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare output of drawSprite and drawBitmap (esp. clipping and imagefilters)
|
||||
*/
|
||||
@ -180,6 +185,9 @@ protected:
|
||||
SkAutoTUnref<SkImage> image1(image0->applyFilter(filter, &offset1, true));
|
||||
SkAutoTUnref<SkImage> image2(image0->applyFilter(filter, &offset2, false));
|
||||
|
||||
check_same_domain(image0, image1);
|
||||
check_same_domain(image0, image2);
|
||||
|
||||
canvas->save();
|
||||
canvas->translate(30, 30);
|
||||
show_image(canvas, image0, SkIPoint::Make(0, 0)); // original
|
||||
|
@ -209,33 +209,52 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
|
||||
SkBitmap*, SkIPoint*) override {
|
||||
return false;
|
||||
bool filterImage(const SkImageFilter* filter, const SkBitmap& src,
|
||||
const SkImageFilter::Context& ctx, SkBitmap* dst, SkIPoint* offset) override {
|
||||
return filter->canFilterImageGPU() &&
|
||||
filter->filterImageGPU(this, src, ctx, dst, offset);
|
||||
}
|
||||
};
|
||||
|
||||
static SkIRect compute_fast_ibounds(SkImageFilter* filter, const SkIRect& srcBounds) {
|
||||
SkRect fastBounds;
|
||||
fastBounds.set(srcBounds);
|
||||
filter->computeFastBounds(fastBounds, &fastBounds);
|
||||
return fastBounds.roundOut();
|
||||
}
|
||||
|
||||
SkImage* SkImage_Gpu::onApplyFilter(SkImageFilter* filter, SkIPoint* offsetResult,
|
||||
bool forceResultToOriginalSize) const {
|
||||
if (!forceResultToOriginalSize || !filter->canFilterImageGPU()) {
|
||||
return this->INHERITED::onApplyFilter(filter, offsetResult, forceResultToOriginalSize);
|
||||
}
|
||||
const SkIRect srcBounds = SkIRect::MakeWH(this->width(), this->height());
|
||||
|
||||
SkBitmap src;
|
||||
GrWrapTextureInBitmap(fTexture, this->width(), this->height(), this->isOpaque(), &src);
|
||||
if (forceResultToOriginalSize) {
|
||||
SkBitmap src;
|
||||
GrWrapTextureInBitmap(fTexture, this->width(), this->height(), this->isOpaque(), &src);
|
||||
|
||||
GrContext* context = fTexture->getContext();
|
||||
SkGpuImageFilterProxy proxy(context);
|
||||
SkImageFilter::Context ctx(SkMatrix::I(),
|
||||
SkIRect::MakeWH(this->width(), this->height()),
|
||||
SkImageFilter::Cache::Get());
|
||||
const SkIRect clipBounds = srcBounds;
|
||||
SkGpuImageFilterProxy proxy(fTexture->getContext());
|
||||
SkImageFilter::Context ctx(SkMatrix::I(), clipBounds, SkImageFilter::Cache::Get());
|
||||
|
||||
SkBitmap dst;
|
||||
if (filter->filterImageGPU(&proxy, src, ctx, &dst, offsetResult)) {
|
||||
SkBitmap dst;
|
||||
if (!filter->filterImage(&proxy, src, ctx, &dst, offsetResult)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new SkImage_Gpu(dst.width(), dst.height(), kNeedNewImageUniqueID, dst.alphaType(),
|
||||
dst.getTexture(), SkSurface::kNo_Budgeted);
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
const SkIRect dstR = compute_fast_ibounds(filter, srcBounds);
|
||||
|
||||
SkImageInfo info = SkImageInfo::MakeN32Premul(dstR.width(), dstR.height());
|
||||
SkAutoTUnref<SkSurface> surface(this->onNewSurface(info));
|
||||
|
||||
SkPaint paint;
|
||||
paint.setImageFilter(filter);
|
||||
surface->getCanvas()->drawImage(this, SkIntToScalar(-dstR.x()), SkIntToScalar(-dstR.y()),
|
||||
&paint);
|
||||
|
||||
offsetResult->set(dstR.x(), dstR.y());
|
||||
return surface->newImageSnapshot();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user