Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(343)

Side by Side Diff: src/effects/SkArithmeticImageFilter.cpp

Issue 16064002: Provide a GPU implementation of SkArithmeticMode (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Fix spacing Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « include/effects/SkArithmeticImageFilter.h ('k') | src/effects/SkArithmeticMode.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2013 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 "SkArithmeticImageFilter.h"
9 #include "SkArithmeticMode.h"
10 #include "SkCanvas.h"
11 #include "SkColorPriv.h"
12 #include "SkFlattenableBuffers.h"
13 #if SK_SUPPORT_GPU
14 #include "GrContext.h"
15 #include "gl/GrGLEffect.h"
16 #include "gl/GrGLEffectMatrix.h"
17 #include "GrTBackendEffectFactory.h"
18 #include "SkImageFilterUtils.h"
19 #endif
20
21 ///////////////////////////////////////////////////////////////////////////////
22
23 SkArithmeticImageFilter::SkArithmeticImageFilter(SkScalar k1, SkScalar k2, SkSca lar k3, SkScalar k4, SkImageFilter* background, SkImageFilter* foreground)
24 : INHERITED(background, foreground), fK1(k1), fK2(k2), fK3(k3), fK4(k4)
25 {
26 }
27
28 SkArithmeticImageFilter::~SkArithmeticImageFilter() {
29 }
30
31 SkArithmeticImageFilter::SkArithmeticImageFilter(SkFlattenableReadBuffer& buffer )
32 : INHERITED(buffer)
33 {
34 fK1 = buffer.readScalar();
35 fK2 = buffer.readScalar();
36 fK3 = buffer.readScalar();
37 fK4 = buffer.readScalar();
38 }
39
40 void SkArithmeticImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
41 this->INHERITED::flatten(buffer);
42 buffer.writeScalar(fK1);
43 buffer.writeScalar(fK2);
44 buffer.writeScalar(fK3);
45 buffer.writeScalar(fK4);
46 }
47
48 bool SkArithmeticImageFilter::onFilterImage(Proxy* proxy,
49 const SkBitmap& src,
50 const SkMatrix& ctm,
51 SkBitmap* dst,
52 SkIPoint* offset) {
53 SkBitmap background = src, foreground = src;
54 SkImageFilter* foregroundInput = getInput(0);
55 SkImageFilter* backgroundInput = getInput(1);
56 if (backgroundInput && !backgroundInput->filterImage(proxy, src, ctm, &backg round, offset)) {
57 return false;
58 }
59 if (foregroundInput && !foregroundInput->filterImage(proxy, src, ctm, &foreg round, offset)) {
60 return false;
61 }
62 dst->setConfig(background.config(), background.width(), background.height()) ;
63 dst->allocPixels();
64 SkCanvas canvas(*dst);
65 SkPaint paint;
66 SkAutoTUnref<SkXfermode> mode(SkArithmeticMode::Create(fK1, fK2, fK3, fK4));
67 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
68 canvas.drawBitmap(background, 0, 0, &paint);
69 paint.setXfermode(mode);
70 canvas.drawBitmap(foreground, 0, 0, &paint);
71 return true;
72 }
73
74 ///////////////////////////////////////////////////////////////////////////////
75
76 #if SK_SUPPORT_GPU
77 class GrGLArithmeticEffect : public GrGLEffect {
78 public:
79 GrGLArithmeticEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
80 virtual ~GrGLArithmeticEffect();
81
82 virtual void emitCode(GrGLShaderBuilder*,
83 const GrDrawEffect&,
84 EffectKey,
85 const char* outputColor,
86 const char* inputColor,
87 const TextureSamplerArray&) SK_OVERRIDE;
88
89 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
90
91 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE;
92
93 private:
94 static const GrEffect::CoordsType kCoordsType = GrEffect::kLocal_CoordsType;
95
96 GrGLUniformManager::UniformHandle fK1Uni, fK2Uni, fK3Uni, fK4Uni;
97 GrGLEffectMatrix fForegroundEffectMatrix;
98 GrGLEffectMatrix fBackgroundEffectMatrix;
99
100 typedef GrGLEffect INHERITED;
101 };
102
103 ///////////////////////////////////////////////////////////////////////////////
104
105 class GrArithmeticEffect : public GrEffect {
106 public:
107 static GrEffectRef* Create(float k1, float k2, float k3, float k4,
108 GrTexture* foreground,
109 GrTexture* background) {
110 AutoEffectUnref effect(SkNEW_ARGS(GrArithmeticEffect, (k1, k2, k3, k4, f oreground, background)));
111 return CreateEffectRef(effect);
112 }
113
114 virtual ~GrArithmeticEffect();
115
116 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
117
118 typedef GrGLArithmeticEffect GLEffect;
119 static const char* Name() { return "Arithmetic"; }
120
121 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE;
122
123 float k1() const { return fK1; }
124 float k2() const { return fK2; }
125 float k3() const { return fK3; }
126 float k4() const { return fK4; }
127
128 private:
129 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
130
131 GrArithmeticEffect(float k1, float k2, float k3, float k4, GrTexture* foregr ound, GrTexture* background);
132 float fK1, fK2, fK3, fK4;
133 GrTextureAccess fForegroundAccess;
134 GrTextureAccess fBackgroundAccess;
135
136 typedef GrEffect INHERITED;
137
138 };
139
140 bool SkArithmeticImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
141 SkBitmap backgroundBM;
142 if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, &backgro undBM)) {
143 return false;
144 }
145 GrTexture* background = (GrTexture*) backgroundBM.getTexture();
146 SkBitmap foregroundBM;
147 if (!SkImageFilterUtils::GetInputResultGPU(getInput(1), proxy, src, &foregro undBM)) {
148 return false;
149 }
150 GrTexture* foreground = (GrTexture*) foregroundBM.getTexture();
151 GrContext* context = foreground->getContext();
152
153 GrTextureDesc desc;
154 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
155 desc.fWidth = src.width();
156 desc.fHeight = src.height();
157 desc.fConfig = kSkia8888_GrPixelConfig;
158
159 GrAutoScratchTexture ast(context, desc);
160 SkAutoTUnref<GrTexture> dst(ast.detach());
161
162 GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
163
164 GrPaint paint;
165 paint.colorStage(0)->setEffect(
166 GrArithmeticEffect::Create(SkScalarToFloat(fK1),
167 SkScalarToFloat(fK2),
168 SkScalarToFloat(fK3),
169 SkScalarToFloat(fK4),
170 foreground,
171 background))->unref();
172 SkRect srcRect;
173 src.getBounds(&srcRect);
174 context->drawRect(paint, srcRect);
175 return SkImageFilterUtils::WrapTexture(dst, src.width(), src.height(), resul t);
176 }
177
178 ///////////////////////////////////////////////////////////////////////////////
179
180 GrArithmeticEffect::GrArithmeticEffect(float k1,
181 float k2,
182 float k3,
183 float k4,
184 GrTexture* foreground,
185 GrTexture* background)
186 : fK1(k1), fK2(k2), fK3(k3), fK4(k4)
187 , fForegroundAccess(foreground)
188 , fBackgroundAccess(background) {
189 this->addTextureAccess(&fForegroundAccess);
190 this->addTextureAccess(&fBackgroundAccess);
191 }
192
193 GrArithmeticEffect::~GrArithmeticEffect() {
194 }
195
196 bool GrArithmeticEffect::onIsEqual(const GrEffect& sBase) const {
197 const GrArithmeticEffect& s = CastEffect<GrArithmeticEffect>(sBase);
198 return fForegroundAccess.getTexture() == s.fForegroundAccess.getTexture() &&
199 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture() &&
200 fK1 == s.fK1 &&
201 fK2 == s.fK2 &&
202 fK3 == s.fK3 &&
203 fK4 == s.fK4;
204 }
205
206 const GrBackendEffectFactory& GrArithmeticEffect::getFactory() const {
207 return GrTBackendEffectFactory<GrArithmeticEffect>::getInstance();
208 }
209
210 void GrArithmeticEffect::getConstantColorComponents(GrColor* color, uint32_t* va lidFlags) const {
211 // TODO: optimize this
212 *validFlags = 0;
213 }
214
215 ///////////////////////////////////////////////////////////////////////////////
216
217 GrGLArithmeticEffect::GrGLArithmeticEffect(const GrBackendEffectFactory& factory ,
218 const GrDrawEffect& drawEffect)
219 : INHERITED(factory)
220 , fForegroundEffectMatrix(kCoordsType)
221 , fBackgroundEffectMatrix(kCoordsType) {
222 }
223
224 GrGLArithmeticEffect::~GrGLArithmeticEffect() {
225 }
226
227 void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder,
228 const GrDrawEffect&,
229 EffectKey key,
230 const char* outputColor,
231 const char* inputColor,
232 const TextureSamplerArray& samplers) {
233 const char* fgCoords;
234 const char* bgCoords;
235 GrSLType fgCoordsType = fForegroundEffectMatrix.emitCode(builder, key, &fgCo ords, NULL, "FG");
236 GrSLType bgCoordsType = fBackgroundEffectMatrix.emitCode(builder, key, &bgCo ords, NULL, "BG");
237
238 fK1Uni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon 2013/05/28 14:21:20 Just wondering if it'd make sense to use a vec4 fo
Stephen White 2013/05/28 15:08:34 Yeah, I thought of that. Just thought it might mak
239 kFloat_GrSLType, "k1");
240 const char* k1Uni = builder->getUniformCStr(fK1Uni);
241
242 fK2Uni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
243 kFloat_GrSLType, "k2");
244 const char* k2Uni = builder->getUniformCStr(fK2Uni);
245
246 fK3Uni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
247 kFloat_GrSLType, "k3");
248 const char* k3Uni = builder->getUniformCStr(fK3Uni);
249
250 fK4Uni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
251 kFloat_GrSLType, "k4");
252 const char* k4Uni = builder->getUniformCStr(fK4Uni);
253
254 builder->fsCodeAppend("\t\tvec4 fgColor = ");
255 builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
256 samplers[0],
257 fgCoords,
258 fgCoordsType);
259 builder->fsCodeAppend(";\n");
260
261 builder->fsCodeAppend("\t\tvec4 bgColor = ");
262 builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
263 samplers[1],
264 bgCoords,
265 bgCoordsType);
266 builder->fsCodeAppend(";\n");
267 builder->fsCodeAppend("\t\tfgColor.rgb = clamp(fgColor.rgb / fgColor.a, 0.0, 1.0);\n");
bsalomon 2013/05/28 14:21:20 What does clamp do if the first param is NaN?
Stephen White 2013/05/28 15:08:34 It returns zero, as far as I can tell (empirically
268 builder->fsCodeAppend("\t\tbgColor.rgb = clamp(bgColor.rgb / bgColor.a, 0.0, 1.0);\n");
269
270 builder->fsCodeAppendf("\t\t%s = %s * bgColor * fgColor + %s * bgColor + %s * fgColor + %s;\n", outputColor, k1Uni, k2Uni, k3Uni, k4Uni);
271 builder->fsCodeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);\n", outputColor, outpu tColor);
272 builder->fsCodeAppendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
273 }
274
275 void GrGLArithmeticEffect::setData(const GrGLUniformManager& uman, const GrDrawE ffect& drawEffect) {
276 const GrArithmeticEffect& arith = drawEffect.castEffect<GrArithmeticEffect>( );
277 GrTexture* fgTex = arith.texture(0);
278 GrTexture* bgTex = arith.texture(1);
279 fForegroundEffectMatrix.setData(uman,
280 GrEffect::MakeDivByTextureWHMatrix(fgTex),
281 drawEffect,
282 fgTex);
283 fBackgroundEffectMatrix.setData(uman,
284 GrEffect::MakeDivByTextureWHMatrix(bgTex),
285 drawEffect,
286 bgTex);
287
288 uman.set1f(fK1Uni, arith.k1());
289 uman.set1f(fK2Uni, arith.k2());
290 uman.set1f(fK3Uni, arith.k3());
291 uman.set1f(fK4Uni, arith.k4());
292 }
293
294 GrGLEffect::EffectKey GrGLArithmeticEffect::GenKey(const GrDrawEffect& drawEffec t, const GrGLCaps&) {
295 const GrArithmeticEffect& arith = drawEffect.castEffect<GrArithmeticEffect>( );
296
297 GrTexture* fgTex = arith.texture(0);
298 GrTexture* bgTex = arith.texture(1);
299
300 EffectKey fgKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatri x(fgTex),
301 drawEffect,
302 kCoordsType,
303 fgTex);
304
305 EffectKey bgKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatri x(bgTex),
306 drawEffect,
307 kCoordsType,
308 bgTex);
309 bgKey <<= GrGLEffectMatrix::kKeyBits;
310 return bgKey | fgKey;
311 }
312 #endif
OLDNEW
« no previous file with comments | « include/effects/SkArithmeticImageFilter.h ('k') | src/effects/SkArithmeticMode.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698