140a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org/* 240a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org * Copyright 2012 The Android Open Source Project 340a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org * 440a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be 540a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org * found in the LICENSE file. 640a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org */ 740a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org 840a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org#include "SkImageFilter.h" 930ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org 1030ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org#include "SkBitmap.h" 1130ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org#include "SkFlattenableBuffers.h" 1240a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org#include "SkRect.h" 132f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org#if SK_SUPPORT_GPU 142f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org#include "GrContext.h" 152f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org#include "GrTexture.h" 162f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org#include "SkImageFilterUtils.h" 172f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org#endif 1840a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org 1940a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.orgSK_DEFINE_INST_COUNT(SkImageFilter) 2040a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org 21c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.orgSkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const SkIRect* cropRect) 22c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org : fInputCount(inputCount), 23c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org fInputs(new SkImageFilter*[inputCount]), 24c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) { 2552b453755a3f9f0bb43d4631f0a189246a99cedcsenorblanco@chromium.org for (int i = 0; i < inputCount; ++i) { 2630ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org fInputs[i] = inputs[i]; 2730ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org SkSafeRef(fInputs[i]); 2830ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org } 2930ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org} 3030ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org 31c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.orgSkImageFilter::SkImageFilter(SkImageFilter* input, const SkIRect* cropRect) 32c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org : fInputCount(1), 33c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org fInputs(new SkImageFilter*[1]), 34c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) { 35633e80d26879db936d77962eae3d50ca9ad99fbcsenorblanco@chromium.org fInputs[0] = input; 36633e80d26879db936d77962eae3d50ca9ad99fbcsenorblanco@chromium.org SkSafeRef(fInputs[0]); 37633e80d26879db936d77962eae3d50ca9ad99fbcsenorblanco@chromium.org} 38633e80d26879db936d77962eae3d50ca9ad99fbcsenorblanco@chromium.org 39c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.orgSkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const SkIRect* cropRect) 40c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org : fInputCount(2), fInputs(new SkImageFilter*[2]), 41c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) { 42633e80d26879db936d77962eae3d50ca9ad99fbcsenorblanco@chromium.org fInputs[0] = input1; 43633e80d26879db936d77962eae3d50ca9ad99fbcsenorblanco@chromium.org fInputs[1] = input2; 44633e80d26879db936d77962eae3d50ca9ad99fbcsenorblanco@chromium.org SkSafeRef(fInputs[0]); 45633e80d26879db936d77962eae3d50ca9ad99fbcsenorblanco@chromium.org SkSafeRef(fInputs[1]); 4630ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org} 4730ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org 4830ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.orgSkImageFilter::~SkImageFilter() { 4952b453755a3f9f0bb43d4631f0a189246a99cedcsenorblanco@chromium.org for (int i = 0; i < fInputCount; i++) { 5030ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org SkSafeUnref(fInputs[i]); 5130ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org } 5230ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org delete[] fInputs; 5330ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org} 5430ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org 556dfcd8019c80e926683b6173db149da8b3524b99skia.committer@gmail.comSkImageFilter::SkImageFilter(SkFlattenableReadBuffer& buffer) 5652b453755a3f9f0bb43d4631f0a189246a99cedcsenorblanco@chromium.org : fInputCount(buffer.readInt()), fInputs(new SkImageFilter*[fInputCount]) { 5752b453755a3f9f0bb43d4631f0a189246a99cedcsenorblanco@chromium.org for (int i = 0; i < fInputCount; i++) { 5830ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org if (buffer.readBool()) { 5930ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org fInputs[i] = static_cast<SkImageFilter*>(buffer.readFlattenable()); 6030ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org } else { 6130ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org fInputs[i] = NULL; 6230ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org } 6330ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org } 64c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org buffer.readIRect(&fCropRect); 6530ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org} 6630ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org 6730ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.orgvoid SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { 6852b453755a3f9f0bb43d4631f0a189246a99cedcsenorblanco@chromium.org buffer.writeInt(fInputCount); 6952b453755a3f9f0bb43d4631f0a189246a99cedcsenorblanco@chromium.org for (int i = 0; i < fInputCount; i++) { 7030ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org SkImageFilter* input = getInput(i); 7130ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org buffer.writeBool(input != NULL); 7230ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org if (input != NULL) { 7330ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org buffer.writeFlattenable(input); 7430ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org } 7530ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org } 76c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org buffer.writeIRect(fCropRect); 7730ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org} 7830ac0dbd00cc752c5a4bb3127bea8de624de37c3senorblanco@chromium.org 7940a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.orgbool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src, 8040a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org const SkMatrix& ctm, 8140a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org SkBitmap* result, SkIPoint* loc) { 8240a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org SkASSERT(result); 8340a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org SkASSERT(loc); 8440a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org /* 8540a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org * Give the proxy first shot at the filter. If it returns false, ask 8640a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org * the filter to do it. 8740a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org */ 8840a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org return (proxy && proxy->filterImage(this, src, ctm, result, loc)) || 8940a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org this->onFilterImage(proxy, src, ctm, result, loc); 9040a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org} 9140a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org 9240a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.orgbool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm, 9340a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org SkIRect* dst) { 9440a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org SkASSERT(&src); 9540a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org SkASSERT(dst); 9640a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org return this->onFilterBounds(src, ctm, dst); 9740a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org} 9840a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org 9940a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.orgbool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&, 10040a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org SkBitmap*, SkIPoint*) { 10140a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org return false; 10240a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org} 10340a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org 10440a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.orgbool SkImageFilter::canFilterImageGPU() const { 105846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org return this->asNewEffect(NULL, NULL, SkIPoint::Make(0, 0)); 10640a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org} 10740a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org 1086bdc8c54bc474b0a2abe4c0d9bdd47b8e3d29ef6commit-bot@chromium.orgbool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm, 1096bdc8c54bc474b0a2abe4c0d9bdd47b8e3d29ef6commit-bot@chromium.org SkBitmap* result, SkIPoint* offset) { 1102f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org#if SK_SUPPORT_GPU 1112f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org SkBitmap input; 1122f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org SkASSERT(fInputCount == 1); 1136bdc8c54bc474b0a2abe4c0d9bdd47b8e3d29ef6commit-bot@chromium.org if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, ctm, &input, offset)) { 1142f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org return false; 1152f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org } 11687816f8e3e4e8633221d6e2c20c2ecdab3b6b6fccommit-bot@chromium.org GrTexture* srcTexture = input.getTexture(); 117846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org SkIRect bounds; 118846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org src.getBounds(&bounds); 119846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org if (!this->applyCropRect(&bounds)) { 120846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org return false; 121846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org } 122846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org SkRect srcRect = SkRect::Make(bounds); 123846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); 1242f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org GrContext* context = srcTexture->getContext(); 1252f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org 1262f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org GrTextureDesc desc; 1272f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org desc.fFlags = kRenderTarget_GrTextureFlagBit, 128846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org desc.fWidth = bounds.width(); 129846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org desc.fHeight = bounds.height(); 1302f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org desc.fConfig = kRGBA_8888_GrPixelConfig; 1312f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org 1322f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org GrAutoScratchTexture dst(context, desc); 1332f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org GrContext::AutoMatrix am; 1342f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org am.setIdentity(context); 1352f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget()); 136846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org GrContext::AutoClip acs(context, dstRect); 1372f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org GrEffectRef* effect; 138846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org this->asNewEffect(&effect, srcTexture, SkIPoint::Make(bounds.left(), bounds.top())); 1392f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org SkASSERT(effect); 1402f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org SkAutoUnref effectRef(effect); 1412f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org GrPaint paint; 1424de2cfb9a63682aa6624f781a7454956ef6619a7commit-bot@chromium.org paint.addColorEffect(effect); 143846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org context->drawRectToRect(paint, dstRect, srcRect); 144846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org 1452f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org SkAutoTUnref<GrTexture> resultTex(dst.detach()); 146846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org SkImageFilterUtils::WrapTexture(resultTex, bounds.width(), bounds.height(), result); 147846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org offset->fX += bounds.left(); 148846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.org offset->fY += bounds.top(); 1492f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org return true; 1502f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org#else 151868224802ab329ab4eb527ba07ea660bdcac60f7senorblanco@chromium.org return false; 1522f91984aefff09d732188437c374b82a863e6754senorblanco@chromium.org#endif 15340a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org} 15440a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org 155c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.orgbool SkImageFilter::applyCropRect(SkIRect* rect) const { 156c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org return rect->intersect(fCropRect); 157c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org} 158c97456b20f8c3496ca88c48f82bb4428399b15cfsenorblanco@chromium.org 15940a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.orgbool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 16040a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org SkIRect* dst) { 16140a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org *dst = src; 16240a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org return true; 16340a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org} 16440a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org 165846089636a8b41a1bcfc370159fd1aa9ec7625c6senorblanco@chromium.orgbool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkIPoint& offset) const { 16640a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org return false; 16740a3e261f94e6bdfa35ccea7f43c6e462c7ce432senorblanco@chromium.org} 16852b453755a3f9f0bb43d4631f0a189246a99cedcsenorblanco@chromium.org 16989820941d3235c89e15142daae082da5b892e5d4sugoi@google.combool SkImageFilter::asColorFilter(SkColorFilter**) const { 17089820941d3235c89e15142daae082da5b892e5d4sugoi@google.com return false; 17152b453755a3f9f0bb43d4631f0a189246a99cedcsenorblanco@chromium.org} 172