blob: ff060a1a52cb8e764905959f62d06af9617e53ee [file] [log] [blame]
senorblanco@chromium.orgbf2768b2012-08-20 15:43:14 +00001/*
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"
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +00009
10#include "SkBitmap.h"
11#include "SkFlattenableBuffers.h"
senorblanco@chromium.orgbf2768b2012-08-20 15:43:14 +000012#include "SkRect.h"
senorblanco@chromium.orgd043cce2013-04-08 19:43:22 +000013#if SK_SUPPORT_GPU
14#include "GrContext.h"
15#include "GrTexture.h"
16#include "SkImageFilterUtils.h"
17#endif
senorblanco@chromium.orgbf2768b2012-08-20 15:43:14 +000018
19SK_DEFINE_INST_COUNT(SkImageFilter)
20
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +000021SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const SkIRect* cropRect)
22 : fInputCount(inputCount),
23 fInputs(new SkImageFilter*[inputCount]),
24 fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +000025 for (int i = 0; i < inputCount; ++i) {
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +000026 fInputs[i] = inputs[i];
27 SkSafeRef(fInputs[i]);
28 }
29}
30
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +000031SkImageFilter::SkImageFilter(SkImageFilter* input, const SkIRect* cropRect)
32 : fInputCount(1),
33 fInputs(new SkImageFilter*[1]),
34 fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
senorblanco@chromium.orgc2e8cef2012-10-22 15:07:14 +000035 fInputs[0] = input;
36 SkSafeRef(fInputs[0]);
37}
38
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +000039SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const SkIRect* cropRect)
40 : fInputCount(2), fInputs(new SkImageFilter*[2]),
41 fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
senorblanco@chromium.orgc2e8cef2012-10-22 15:07:14 +000042 fInputs[0] = input1;
43 fInputs[1] = input2;
44 SkSafeRef(fInputs[0]);
45 SkSafeRef(fInputs[1]);
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +000046}
47
48SkImageFilter::~SkImageFilter() {
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +000049 for (int i = 0; i < fInputCount; i++) {
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +000050 SkSafeUnref(fInputs[i]);
51 }
52 delete[] fInputs;
53}
54
skia.committer@gmail.comfc843592012-10-11 02:01:14 +000055SkImageFilter::SkImageFilter(SkFlattenableReadBuffer& buffer)
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +000056 : fInputCount(buffer.readInt()), fInputs(new SkImageFilter*[fInputCount]) {
57 for (int i = 0; i < fInputCount; i++) {
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +000058 if (buffer.readBool()) {
59 fInputs[i] = static_cast<SkImageFilter*>(buffer.readFlattenable());
60 } else {
61 fInputs[i] = NULL;
62 }
63 }
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +000064 buffer.readIRect(&fCropRect);
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +000065}
66
67void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +000068 buffer.writeInt(fInputCount);
69 for (int i = 0; i < fInputCount; i++) {
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +000070 SkImageFilter* input = getInput(i);
71 buffer.writeBool(input != NULL);
72 if (input != NULL) {
73 buffer.writeFlattenable(input);
74 }
75 }
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +000076 buffer.writeIRect(fCropRect);
senorblanco@chromium.org9f25de72012-10-10 20:36:13 +000077}
78
senorblanco@chromium.orgbf2768b2012-08-20 15:43:14 +000079bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
80 const SkMatrix& ctm,
81 SkBitmap* result, SkIPoint* loc) {
82 SkASSERT(result);
83 SkASSERT(loc);
84 /*
85 * Give the proxy first shot at the filter. If it returns false, ask
86 * the filter to do it.
87 */
88 return (proxy && proxy->filterImage(this, src, ctm, result, loc)) ||
89 this->onFilterImage(proxy, src, ctm, result, loc);
90}
91
92bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
93 SkIRect* dst) {
94 SkASSERT(&src);
95 SkASSERT(dst);
96 return this->onFilterBounds(src, ctm, dst);
97}
98
99bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
100 SkBitmap*, SkIPoint*) {
101 return false;
102}
103
104bool SkImageFilter::canFilterImageGPU() const {
senorblanco@chromium.orgd043cce2013-04-08 19:43:22 +0000105 return this->asNewEffect(NULL, NULL);
senorblanco@chromium.orgbf2768b2012-08-20 15:43:14 +0000106}
107
commit-bot@chromium.org7b320702013-07-10 21:22:18 +0000108bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result,
109 SkIPoint* offset) {
senorblanco@chromium.orgd043cce2013-04-08 19:43:22 +0000110#if SK_SUPPORT_GPU
111 SkBitmap input;
112 SkASSERT(fInputCount == 1);
commit-bot@chromium.org7b320702013-07-10 21:22:18 +0000113 if (!SkImageFilterUtils::GetInputResultGPU(this->getInput(0), proxy, src, &input, offset)) {
senorblanco@chromium.orgd043cce2013-04-08 19:43:22 +0000114 return false;
115 }
commit-bot@chromium.orgb8d00db2013-06-26 19:18:23 +0000116 GrTexture* srcTexture = input.getTexture();
senorblanco@chromium.orgd043cce2013-04-08 19:43:22 +0000117 SkRect rect;
118 src.getBounds(&rect);
119 GrContext* context = srcTexture->getContext();
120
121 GrTextureDesc desc;
122 desc.fFlags = kRenderTarget_GrTextureFlagBit,
123 desc.fWidth = input.width();
124 desc.fHeight = input.height();
125 desc.fConfig = kRGBA_8888_GrPixelConfig;
126
127 GrAutoScratchTexture dst(context, desc);
128 GrContext::AutoMatrix am;
129 am.setIdentity(context);
130 GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget());
131 GrContext::AutoClip acs(context, rect);
132 GrEffectRef* effect;
133 this->asNewEffect(&effect, srcTexture);
134 SkASSERT(effect);
135 SkAutoUnref effectRef(effect);
136 GrPaint paint;
commit-bot@chromium.org42dacab2013-07-13 17:24:24 +0000137 paint.addColorEffect(effect);
senorblanco@chromium.orgd043cce2013-04-08 19:43:22 +0000138 context->drawRect(paint, rect);
139 SkAutoTUnref<GrTexture> resultTex(dst.detach());
140 SkImageFilterUtils::WrapTexture(resultTex, input.width(), input.height(), result);
141 return true;
142#else
senorblanco@chromium.orgc2594f42013-01-30 19:08:47 +0000143 return false;
senorblanco@chromium.orgd043cce2013-04-08 19:43:22 +0000144#endif
senorblanco@chromium.orgbf2768b2012-08-20 15:43:14 +0000145}
146
senorblanco@chromium.orgccf225c2013-07-22 20:03:22 +0000147bool SkImageFilter::applyCropRect(SkIRect* rect) const {
148 return rect->intersect(fCropRect);
149}
150
senorblanco@chromium.orgbf2768b2012-08-20 15:43:14 +0000151bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
152 SkIRect* dst) {
153 *dst = src;
154 return true;
155}
156
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000157bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*) const {
senorblanco@chromium.orgbf2768b2012-08-20 15:43:14 +0000158 return false;
159}
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +0000160
sugoi@google.coma1c511b2013-02-21 15:02:28 +0000161bool SkImageFilter::asColorFilter(SkColorFilter**) const {
162 return false;
senorblanco@chromium.org8d21f6c2012-10-12 19:14:06 +0000163}