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

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

Issue 22918012: Add luminance mask transfer modes. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Fix VS builds (no named variadic macro params support) Created 7 years, 4 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
OLDNEW
(Empty)
1 /*
2 * Copyright 2013 Google Inc.
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 "SkLumaXfermode.h"
9 #include "SkColorPriv.h"
10 #include "SkFlattenableBuffers.h"
11 #include "SkString.h"
12
13 #if SK_SUPPORT_GPU
14 #include "gl/GrGLEffect.h"
15 #include "gl/GrGLEffectMatrix.h"
16 #include "GrContext.h"
17 #include "GrTBackendEffectFactory.h"
18 #endif
19
20 static inline SkPMColor luma_proc(const SkPMColor a, const SkPMColor b) {
21 unsigned luma = SkComputeLuminance(SkGetPackedR32(b),
reed1 2013/08/22 18:35:51 Is the spec cool with computing luminance on the p
f(malita) 2013/08/22 19:25:52 Actually they explicitly mention non-premultiplied
22 SkGetPackedG32(b),
23 SkGetPackedB32(b));
24 return SkAlphaMulQ(a, SkAlpha255To256(luma));
25 }
26
27 template <typename T>
28 static inline const T* lumaOpA(SkXfermode::Mode mode,
29 const T* src, const T* dst) {
30 return SkXfermode::kSrcIn_Mode == mode ? src : dst;
31 }
32
33 template <typename T>
34 static inline const T* lumaOpB(SkXfermode::Mode mode,
35 const T* src, const T* dst) {
36 return SkXfermode::kSrcIn_Mode == mode ? dst : src;
37 }
38
39 SkXfermode* SkLumaMaskXfermode::Create(SkXfermode::Mode mode) {
40 return SkNEW_ARGS(SkLumaMaskXfermode, (mode));
41 }
42
43 SkLumaMaskXfermode::SkLumaMaskXfermode(SkXfermode::Mode mode)
44 : fMode(mode) {
45 SkASSERT(kSrcIn_Mode == mode || kDstIn_Mode == mode);
46 }
47
48 SkLumaMaskXfermode::SkLumaMaskXfermode(SkFlattenableReadBuffer& buffer)
49 : INHERITED(buffer)
50 , fMode((SkXfermode::Mode)buffer.readUInt()) {
51 SkASSERT(kSrcIn_Mode == fMode || kDstIn_Mode == fMode);
52 }
53
54 void SkLumaMaskXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
55 INHERITED::flatten(buffer);
56 buffer.writeUInt(fMode);
57 }
58
59 SkPMColor SkLumaMaskXfermode::xferColor(SkPMColor src, SkPMColor dst) const {
60 const SkPMColor* a = lumaOpA<SkPMColor>(fMode, &src, &dst);
61 const SkPMColor* b = lumaOpB<SkPMColor>(fMode, &src, &dst);
62 return luma_proc(*a, *b);
63 }
64
65 void SkLumaMaskXfermode::xfer32(SkPMColor dst[], const SkPMColor src[],
66 int count, const SkAlpha aa[]) const {
67 const SkPMColor* a = lumaOpA<SkPMColor>(fMode, src, dst);
68 const SkPMColor* b = lumaOpB<SkPMColor>(fMode, src, dst);
69
70 if (aa) {
71 for (int i = 0; i < count; ++i) {
72 unsigned cov = aa[i];
73 if (cov) {
74 unsigned resC = luma_proc(a[i], b[i]);
75 if (cov < 255) {
76 resC = SkAlphaMulQ(resC, SkAlpha255To256(cov));
77 }
78 dst[i] = resC;
79 }
80 }
81 } else {
82 for (int i = 0; i < count; ++i) {
83 dst[i] = luma_proc(a[i], b[i]);
84 }
85 }
86 }
87
88 #ifdef SK_DEVELOPER
89 void SkLumaMaskXfermode::toString(SkString* str) const {
90 str->printf("SkLumaMaskXfermode: mode: %s",
91 fMode == kSrcIn_Mode ? "SRC_IN" : "DST_IN");
92 }
93 #endif
94
95 #if SK_SUPPORT_GPU
96 //////////////////////////////////////////////////////////////////////////////
97
98 class GrGLLumaMaskEffect : public GrGLEffect {
99 public:
100 GrGLLumaMaskEffect(const GrBackendEffectFactory&, const GrDrawEffect&);
101 virtual ~GrGLLumaMaskEffect();
102
103 virtual void emitCode(GrGLShaderBuilder*,
104 const GrDrawEffect&,
105 EffectKey,
106 const char* outputColor,
107 const char* inputColor,
108 const TextureSamplerArray&) SK_OVERRIDE;
109
110 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&);
111 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE;
112
113 private:
114 static const GrEffect::CoordsType kCoordsType = GrEffect::kLocal_CoordsType;
115 GrGLEffectMatrix fBackgroundEffectMatrix;
116
117 typedef GrGLEffect INHERITED;
118 };
119
120 class GrLumaMaskEffect : public GrEffect {
121 public:
122 static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) {
123 AutoEffectUnref effect(SkNEW_ARGS(GrLumaMaskEffect, (mode, background))) ;
124 return CreateEffectRef(effect);
125 }
126
127 virtual ~GrLumaMaskEffect();
128
129 typedef GrGLLumaMaskEffect GLEffect;
130 static const char* Name() { return "LumaMask"; }
131 GrTexture* backgroundTexture() const { return fBackgroundAccess.getTexture() ; }
132
133 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
134 virtual void getConstantColorComponents(GrColor*, uint32_t*) const SK_OVERRI DE;
135
136 SkXfermode::Mode getMode() const { return fMode; }
137
138 private:
139 GrLumaMaskEffect(SkXfermode::Mode, GrTexture*);
140
141 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
142
143 SkXfermode::Mode fMode;
144 GrTextureAccess fBackgroundAccess;
145 };
146
147 //////////////////////////////////////////////////////////////////////////////
148
149 GrGLLumaMaskEffect::GrGLLumaMaskEffect(const GrBackendEffectFactory& factory,
150 const GrDrawEffect&)
151 : INHERITED(factory)
152 , fBackgroundEffectMatrix(kCoordsType) {
153 }
154
155 GrGLLumaMaskEffect::~GrGLLumaMaskEffect() {
156 }
157
158 void GrGLLumaMaskEffect::emitCode(GrGLShaderBuilder* builder,
159 const GrDrawEffect& drawEffect,
160 EffectKey key,
161 const char* outputColor,
162 const char* inputColor,
163 const TextureSamplerArray& samplers) {
164
165 const GrLumaMaskEffect& lumaEffect = drawEffect.castEffect<GrLumaMaskEffect> ();
166 GrTexture* backgroundTex = lumaEffect.backgroundTexture();
167 const char* dstColor;
168 if (backgroundTex) {
169 const char* bgCoords;
170 GrSLType bgCoordsType = fBackgroundEffectMatrix.emitCode(builder,
171 key,
172 &bgCoords,
173 NULL,
174 "BG");
175 builder->fsCodeAppend("\t\tvec4 bgColor = ");
176 builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
177 samplers[0],
178 bgCoords,
179 bgCoordsType);
180 builder->fsCodeAppendf(";\n");
181 dstColor = "bgColor";
182 } else {
183 dstColor = builder->dstColor();
184 }
185
186 SkASSERT(NULL != dstColor);
187
188 if (NULL == inputColor) {
189 inputColor = GrGLSLOnesVecf(4);
190 }
191
192 const char *opA = lumaOpA<char>(lumaEffect.getMode(), inputColor, dstColor);
193 const char *opB = lumaOpB<char>(lumaEffect.getMode(), inputColor, dstColor);
194
195 builder->fsCodeAppendf("\t\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb); \n",
196 SK_ITU_BT709_LUM_COEFF_R,
197 SK_ITU_BT709_LUM_COEFF_G,
198 SK_ITU_BT709_LUM_COEFF_B,
199 opB);
200 builder->fsCodeAppendf("\t\t%s = %s * luma;\n", outputColor, opA);
201 }
202
203 GrGLEffect::EffectKey GrGLLumaMaskEffect::GenKey(const GrDrawEffect& drawEffect,
204 const GrGLCaps&) {
205 const GrLumaMaskEffect& effect = drawEffect.castEffect<GrLumaMaskEffect>();
206 EffectKey modeKey = effect.getMode();
207 GrTexture* bgTex = effect.backgroundTexture();
208 EffectKey matrixKey = 0;
209 if (bgTex) {
210 matrixKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatrix( bgTex),
211 drawEffect,
212 GrGLLumaMaskEffect::kCoordsType,
213 bgTex);
214 }
215
216 return (modeKey << GrGLEffectMatrix::kKeyBits) | matrixKey;
217 }
218
219 void GrGLLumaMaskEffect::setData(const GrGLUniformManager& uman,
220 const GrDrawEffect& drawEffect) {
221 const GrLumaMaskEffect& luma = drawEffect.castEffect<GrLumaMaskEffect>();
222 GrTexture* bgTex = luma.backgroundTexture();
223 if (bgTex) {
224 fBackgroundEffectMatrix.setData(uman,
225 GrEffect::MakeDivByTextureWHMatrix(bgTex ),
226 drawEffect,
227 bgTex);
228 }
229 }
230
231 //////////////////////////////////////////////////////////////////////////////
232
233 GrLumaMaskEffect::GrLumaMaskEffect(SkXfermode::Mode mode, GrTexture* bg)
234 : fMode(mode) {
235 if (bg) {
236 fBackgroundAccess.reset(bg);
237 this->addTextureAccess(&fBackgroundAccess);
238 } else {
239 this->setWillReadDstColor();
240 }
241 }
242
243 GrLumaMaskEffect::~GrLumaMaskEffect() {
244 }
245
246 const GrBackendEffectFactory& GrLumaMaskEffect::getFactory() const {
247 return GrTBackendEffectFactory<GrLumaMaskEffect>::getInstance();
248 }
249
250 void GrLumaMaskEffect::getConstantColorComponents(GrColor*, uint32_t *validFlags ) const {
251 *validFlags = 0;
252 }
253
254 bool GrLumaMaskEffect::onIsEqual(const GrEffect& sBase) const {
255 const GrLumaMaskEffect& s = CastEffect<GrLumaMaskEffect>(sBase);
256 return fMode == s.fMode &&
257 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
258 }
259
260 //////////////////////////////////////////////////////////////////////////////
261
262 bool SkLumaMaskXfermode::asNewEffectOrCoeff(GrContext*, GrEffectRef** effect,
263 Coeff*, Coeff*,
264 GrTexture* background) const {
265 if (effect) {
266 *effect = GrLumaMaskEffect::Create(fMode, background);
267 }
268 return true;
269 }
270
271 #endif // SK_SUPPORT_GPU
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698