SkImageFilter.cpp revision 42dacab4e7366d9f53989558cc8d045c3d065bcd
1/*
2 * Copyright 2012 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkImageFilter.h"
9
10#include "SkBitmap.h"
11#include "SkFlattenableBuffers.h"
12#include "SkRect.h"
13#if SK_SUPPORT_GPU
14#include "GrContext.h"
15#include "GrTexture.h"
16#include "SkImageFilterUtils.h"
17#endif
18
19SK_DEFINE_INST_COUNT(SkImageFilter)
20
21SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs)
22  : fInputCount(inputCount), fInputs(new SkImageFilter*[inputCount]) {
23    for (int i = 0; i < inputCount; ++i) {
24        fInputs[i] = inputs[i];
25        SkSafeRef(fInputs[i]);
26    }
27}
28
29SkImageFilter::SkImageFilter(SkImageFilter* input)
30  : fInputCount(1), fInputs(new SkImageFilter*[1]) {
31    fInputs[0] = input;
32    SkSafeRef(fInputs[0]);
33}
34
35SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2)
36  : fInputCount(2), fInputs(new SkImageFilter*[2]) {
37    fInputs[0] = input1;
38    fInputs[1] = input2;
39    SkSafeRef(fInputs[0]);
40    SkSafeRef(fInputs[1]);
41}
42
43SkImageFilter::~SkImageFilter() {
44    for (int i = 0; i < fInputCount; i++) {
45        SkSafeUnref(fInputs[i]);
46    }
47    delete[] fInputs;
48}
49
50SkImageFilter::SkImageFilter(SkFlattenableReadBuffer& buffer)
51    : fInputCount(buffer.readInt()), fInputs(new SkImageFilter*[fInputCount]) {
52    for (int i = 0; i < fInputCount; i++) {
53        if (buffer.readBool()) {
54            fInputs[i] = static_cast<SkImageFilter*>(buffer.readFlattenable());
55        } else {
56            fInputs[i] = NULL;
57        }
58    }
59}
60
61void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
62    buffer.writeInt(fInputCount);
63    for (int i = 0; i < fInputCount; i++) {
64        SkImageFilter* input = getInput(i);
65        buffer.writeBool(input != NULL);
66        if (input != NULL) {
67            buffer.writeFlattenable(input);
68        }
69    }
70}
71
72bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
73                                const SkMatrix& ctm,
74                                SkBitmap* result, SkIPoint* loc) {
75    SkASSERT(result);
76    SkASSERT(loc);
77    /*
78     *  Give the proxy first shot at the filter. If it returns false, ask
79     *  the filter to do it.
80     */
81    return (proxy && proxy->filterImage(this, src, ctm, result, loc)) ||
82           this->onFilterImage(proxy, src, ctm, result, loc);
83}
84
85bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
86                                 SkIRect* dst) {
87    SkASSERT(&src);
88    SkASSERT(dst);
89    return this->onFilterBounds(src, ctm, dst);
90}
91
92bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
93                                  SkBitmap*, SkIPoint*) {
94    return false;
95}
96
97bool SkImageFilter::canFilterImageGPU() const {
98    return this->asNewEffect(NULL, NULL);
99}
100
101bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
102                                   SkIPoint* offset) {
103#if SK_SUPPORT_GPU
104    SkBitmap input;
105    SkASSERT(fInputCount == 1);
106    if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, &input, offset)) {
107        return false;
108    }
109    GrTexture* srcTexture = input.getTexture();
110    SkRect rect;
111    src.getBounds(&rect);
112    GrContext* context = srcTexture->getContext();
113
114    GrTextureDesc desc;
115    desc.fFlags = kRenderTarget_GrTextureFlagBit,
116    desc.fWidth = input.width();
117    desc.fHeight = input.height();
118    desc.fConfig = kRGBA_8888_GrPixelConfig;
119
120    GrAutoScratchTexture dst(context, desc);
121    GrContext::AutoMatrix am;
122    am.setIdentity(context);
123    GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget());
124    GrContext::AutoClip acs(context, rect);
125    GrEffectRef* effect;
126    this->asNewEffect(&effect, srcTexture);
127    SkASSERT(effect);
128    SkAutoUnref effectRef(effect);
129    GrPaint paint;
130    paint.addColorEffect(effect);
131    context->drawRect(paint, rect);
132    SkAutoTUnref<GrTexture> resultTex(dst.detach());
133    SkImageFilterUtils::WrapTexture(resultTex, input.width(), input.height(), result);
134    return true;
135#else
136    return false;
137#endif
138}
139
140bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
141                                   SkIRect* dst) {
142    *dst = src;
143    return true;
144}
145
146bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*) const {
147    return false;
148}
149
150bool SkImageFilter::asColorFilter(SkColorFilter**) const {
151    return false;
152}
153