blob: fc819deb178ba493731f8d409a89d95303e135c6 [file] [log] [blame]
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +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 "SkLightingImageFilter.h"
9#include "SkBitmap.h"
10#include "SkColorPriv.h"
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000011#include "SkFlattenableBuffers.h"
12#include "SkOrderedReadBuffer.h"
13#include "SkOrderedWriteBuffer.h"
tomhudson@google.com300f5622012-07-20 14:15:22 +000014#include "SkTypes.h"
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000015
16#if SK_SUPPORT_GPU
tomhudson@google.comd0c1a062012-07-12 17:23:52 +000017#include "effects/GrSingleTextureEffect.h"
bsalomon@google.comd698f772012-10-25 13:22:00 +000018#include "gl/GrGLEffect.h"
bsalomon@google.com17fc6512012-11-02 21:45:01 +000019#include "gl/GrGLEffectMatrix.h"
bsalomon@google.coma469c282012-10-24 18:28:34 +000020#include "GrEffect.h"
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +000021#include "GrTBackendEffectFactory.h"
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000022
23class GrGLDiffuseLightingEffect;
24class GrGLSpecularLightingEffect;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000025
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000026// For brevity
27typedef GrGLUniformManager::UniformHandle UniformHandle;
28static const UniformHandle kInvalidUniformHandle = GrGLUniformManager::kInvalidUniformHandle;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000029#endif
bsalomon@google.com032b2212012-07-16 13:36:18 +000030
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000031namespace {
32
33const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3));
34const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3));
35const SkScalar gOneHalf = SkFloatToScalar(0.5f);
36const SkScalar gOneQuarter = SkFloatToScalar(0.25f);
37
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000038#if SK_SUPPORT_GPU
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000039void setUniformPoint3(const GrGLUniformManager& uman, UniformHandle uni, const SkPoint3& point) {
bsalomon@google.comb9119a62012-07-25 17:55:26 +000040 GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(GrGLfloat));
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000041 uman.set3fv(uni, 0, 1, &point.fX);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000042}
43
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000044void setUniformNormal3(const GrGLUniformManager& uman, UniformHandle uni, const SkPoint3& point) {
bsalomon@google.com706f6682012-10-23 14:53:55 +000045 setUniformPoint3(uman, uni, SkPoint3(point.fX, point.fY, point.fZ));
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000046}
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000047#endif
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000048
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000049// Shift matrix components to the left, as we advance pixels to the right.
50inline void shiftMatrixLeft(int m[9]) {
51 m[0] = m[1];
52 m[3] = m[4];
53 m[6] = m[7];
54 m[1] = m[2];
55 m[4] = m[5];
56 m[7] = m[8];
57}
58
59class DiffuseLightingType {
60public:
61 DiffuseLightingType(SkScalar kd)
62 : fKD(kd) {}
63 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
64 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
65 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
66 SkPoint3 color(lightColor * colorScale);
67 return SkPackARGB32(255,
68 SkScalarFloorToInt(color.fX),
69 SkScalarFloorToInt(color.fY),
70 SkScalarFloorToInt(color.fZ));
71 }
72private:
73 SkScalar fKD;
74};
75
76class SpecularLightingType {
77public:
78 SpecularLightingType(SkScalar ks, SkScalar shininess)
79 : fKS(ks), fShininess(shininess) {}
80 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
81 SkPoint3 halfDir(surfaceTolight);
82 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1)
83 halfDir.normalize();
84 SkScalar colorScale = SkScalarMul(fKS,
85 SkScalarPow(normal.dot(halfDir), fShininess));
86 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
87 SkPoint3 color(lightColor * colorScale);
88 return SkPackARGB32(SkScalarFloorToInt(color.maxComponent()),
89 SkScalarFloorToInt(color.fX),
90 SkScalarFloorToInt(color.fY),
91 SkScalarFloorToInt(color.fZ));
92 }
93private:
94 SkScalar fKS;
95 SkScalar fShininess;
96};
97
98inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
99 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
100}
101
102inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
103 SkPoint3 vector(SkScalarMul(-x, surfaceScale),
104 SkScalarMul(-y, surfaceScale),
105 SK_Scalar1);
106 vector.normalize();
107 return vector;
108}
109
110inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
111 return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
112 sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
113 surfaceScale);
114}
115
116inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
117 return pointToNormal(sobel( 0, 0, m[3], m[5], m[6], m[8], gOneThird),
118 sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
119 surfaceScale);
120}
121
122inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
123 return pointToNormal(sobel( 0, 0, m[3], m[4], m[6], m[7], gTwoThirds),
124 sobel(m[3], m[6], m[4], m[7], 0, 0, gTwoThirds),
125 surfaceScale);
126}
127
128inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
129 return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
130 sobel( 0, 0, m[1], m[7], m[2], m[8], gOneThird),
131 surfaceScale);
132}
133
134
135inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
136 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
137 sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
138 surfaceScale);
139}
140
141inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
142 return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
143 sobel(m[0], m[6], m[1], m[7], 0, 0, gOneThird),
144 surfaceScale);
145}
146
147inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
148 return pointToNormal(sobel(m[1], m[2], m[4], m[5], 0, 0, gTwoThirds),
149 sobel( 0, 0, m[1], m[4], m[2], m[5], gTwoThirds),
150 surfaceScale);
151}
152
153inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
154 return pointToNormal(sobel(m[0], m[2], m[3], m[5], 0, 0, gOneThird),
155 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
156 surfaceScale);
157}
158
159inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
160 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds),
161 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds),
162 surfaceScale);
163}
164
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000165template <class LightingType, class LightType> void lightBitmap(const LightingType& lightingType, const SkLight* light, const SkBitmap& src, SkBitmap* dst, SkScalar surfaceScale) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000166 const LightType* l = static_cast<const LightType*>(light);
167 int y = 0;
168 {
169 const SkPMColor* row1 = src.getAddr32(0, 0);
170 const SkPMColor* row2 = src.getAddr32(0, 1);
171 SkPMColor* dptr = dst->getAddr32(0, 0);
172 int m[9];
173 int x = 0;
174 m[4] = SkGetPackedA32(*row1++);
175 m[5] = SkGetPackedA32(*row1++);
176 m[7] = SkGetPackedA32(*row2++);
177 m[8] = SkGetPackedA32(*row2++);
178 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000179 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000180 for (x = 1; x < src.width() - 1; ++x)
181 {
182 shiftMatrixLeft(m);
183 m[5] = SkGetPackedA32(*row1++);
184 m[8] = SkGetPackedA32(*row2++);
185 surfaceToLight = l->surfaceToLight(x, 0, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000186 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000187 }
188 shiftMatrixLeft(m);
189 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000190 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000191 }
192
193 for (++y; y < src.height() - 1; ++y) {
194 const SkPMColor* row0 = src.getAddr32(0, y - 1);
195 const SkPMColor* row1 = src.getAddr32(0, y);
196 const SkPMColor* row2 = src.getAddr32(0, y + 1);
197 SkPMColor* dptr = dst->getAddr32(0, y);
198 int m[9];
199 int x = 0;
200 m[1] = SkGetPackedA32(*row0++);
201 m[2] = SkGetPackedA32(*row0++);
202 m[4] = SkGetPackedA32(*row1++);
203 m[5] = SkGetPackedA32(*row1++);
204 m[7] = SkGetPackedA32(*row2++);
205 m[8] = SkGetPackedA32(*row2++);
206 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000207 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000208 for (x = 1; x < src.width() - 1; ++x) {
209 shiftMatrixLeft(m);
210 m[2] = SkGetPackedA32(*row0++);
211 m[5] = SkGetPackedA32(*row1++);
212 m[8] = SkGetPackedA32(*row2++);
213 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000214 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000215 }
216 shiftMatrixLeft(m);
217 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000218 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000219 }
220
221 {
222 const SkPMColor* row0 = src.getAddr32(0, src.height() - 2);
223 const SkPMColor* row1 = src.getAddr32(0, src.height() - 1);
224 int x = 0;
225 SkPMColor* dptr = dst->getAddr32(0, src.height() - 1);
226 int m[9];
227 m[1] = SkGetPackedA32(*row0++);
228 m[2] = SkGetPackedA32(*row0++);
229 m[4] = SkGetPackedA32(*row1++);
230 m[5] = SkGetPackedA32(*row1++);
231 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000232 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000233 for (x = 1; x < src.width() - 1; ++x)
234 {
235 shiftMatrixLeft(m);
236 m[2] = SkGetPackedA32(*row0++);
237 m[5] = SkGetPackedA32(*row1++);
238 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000239 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000240 }
241 shiftMatrixLeft(m);
242 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000243 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000244 }
245}
246
247SkPoint3 readPoint3(SkFlattenableReadBuffer& buffer) {
248 SkPoint3 point;
249 point.fX = buffer.readScalar();
250 point.fY = buffer.readScalar();
251 point.fZ = buffer.readScalar();
252 return point;
253};
254
255void writePoint3(const SkPoint3& point, SkFlattenableWriteBuffer& buffer) {
256 buffer.writeScalar(point.fX);
257 buffer.writeScalar(point.fY);
258 buffer.writeScalar(point.fZ);
259};
260
261class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
262public:
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000263 SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale,
264 SkScalar kd, SkImageFilter* input);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000265 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
266
bsalomon@google.com021fc732012-10-25 12:47:42 +0000267 virtual bool asNewEffect(GrEffect** effect, GrTexture*) const SK_OVERRIDE;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000268 SkScalar kd() const { return fKD; }
269
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000270protected:
271 explicit SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer);
272 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
273 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
274 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
275
276
277private:
278 typedef SkLightingImageFilter INHERITED;
279 SkScalar fKD;
280};
281
282class SkSpecularLightingImageFilter : public SkLightingImageFilter {
283public:
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000284 SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000285 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
286
bsalomon@google.com021fc732012-10-25 12:47:42 +0000287 virtual bool asNewEffect(GrEffect** effect, GrTexture*) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000288 SkScalar ks() const { return fKS; }
289 SkScalar shininess() const { return fShininess; }
290
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000291protected:
292 explicit SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer);
293 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
294 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
295 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
296
297private:
298 typedef SkLightingImageFilter INHERITED;
299 SkScalar fKS;
300 SkScalar fShininess;
301};
302
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000303#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000304
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000305class GrLightingEffect : public GrSingleTextureEffect {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000306public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000307 GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000308 virtual ~GrLightingEffect();
309
bsalomon@google.coma469c282012-10-24 18:28:34 +0000310 virtual bool isEqual(const GrEffect&) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000311
312 const SkLight* light() const { return fLight; }
313 SkScalar surfaceScale() const { return fSurfaceScale; }
bsalomon@google.com371e1052013-01-11 21:08:55 +0000314
315 virtual void getConstantColorComponents(GrColor* color,
316 uint32_t* validFlags) const SK_OVERRIDE {
317 // lighting shaders are complicated. We just throw up our hands.
318 *validFlags = 0;
319 }
320
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000321private:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000322 typedef GrSingleTextureEffect INHERITED;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000323 const SkLight* fLight;
324 SkScalar fSurfaceScale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000325};
326
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000327class GrDiffuseLightingEffect : public GrLightingEffect {
328public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000329 GrDiffuseLightingEffect(GrTexture* texture,
330 const SkLight* light,
331 SkScalar surfaceScale,
332 SkScalar kd);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000333
334 static const char* Name() { return "DiffuseLighting"; }
335
bsalomon@google.com422e81a2012-10-25 14:11:03 +0000336 typedef GrGLDiffuseLightingEffect GLEffect;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000337
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000338 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
bsalomon@google.coma469c282012-10-24 18:28:34 +0000339 virtual bool isEqual(const GrEffect&) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000340 SkScalar kd() const { return fKD; }
341private:
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000342 GR_DECLARE_EFFECT_TEST;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000343 typedef GrLightingEffect INHERITED;
344 SkScalar fKD;
345};
346
347class GrSpecularLightingEffect : public GrLightingEffect {
348public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000349 GrSpecularLightingEffect(GrTexture* texture,
350 const SkLight* light,
351 SkScalar surfaceScale,
352 SkScalar ks,
353 SkScalar shininess);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000354
355 static const char* Name() { return "SpecularLighting"; }
356
bsalomon@google.com422e81a2012-10-25 14:11:03 +0000357 typedef GrGLSpecularLightingEffect GLEffect;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000358
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000359 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
bsalomon@google.coma469c282012-10-24 18:28:34 +0000360 virtual bool isEqual(const GrEffect&) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000361 SkScalar ks() const { return fKS; }
362 SkScalar shininess() const { return fShininess; }
363
364private:
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000365 GR_DECLARE_EFFECT_TEST;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000366 typedef GrLightingEffect INHERITED;
367 SkScalar fKS;
368 SkScalar fShininess;
369};
370
371///////////////////////////////////////////////////////////////////////////////
372
373class GrGLLight {
374public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000375 virtual ~GrGLLight() {}
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000376
377 /**
378 * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
379 * below. It adds a vec3f uniform visible in the FS that represents the constant light color.
380 */
381 void emitLightColorUniform(GrGLShaderBuilder*);
382
skia.committer@gmail.come862d162012-10-31 02:01:18 +0000383 /**
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000384 * These two functions are called from GrGLLightingEffect's emitCode() function.
385 * emitSurfaceToLight places an expression in param out that is the vector from the surface to
386 * the light. The expression will be used in the FS. emitLightColor writes an expression into
387 * the FS that is the color of the light. Either function may add functions and/or uniforms to
388 * the FS. The default of emitLightColor appends the name of the constant light color uniform
389 * and so this function only needs to be overridden if the light color varies spatially.
390 */
391 virtual void emitSurfaceToLight(GrGLShaderBuilder*, SkString* out, const char* z) = 0;
392 virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight);
393
394 // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
395 // INHERITED::setData().
bsalomon@google.com706f6682012-10-23 14:53:55 +0000396 virtual void setData(const GrGLUniformManager&, const SkLight* light) const;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000397
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000398protected:
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000399 /**
400 * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
401 * function.
402 */
403 UniformHandle lightColorUni() const { return fColorUni; }
404
405private:
bsalomon@google.com032b2212012-07-16 13:36:18 +0000406 UniformHandle fColorUni;
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000407
408 typedef SkRefCnt INHERITED;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000409};
410
411///////////////////////////////////////////////////////////////////////////////
412
413class GrGLDistantLight : public GrGLLight {
414public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000415 virtual ~GrGLDistantLight() {}
bsalomon@google.com706f6682012-10-23 14:53:55 +0000416 virtual void setData(const GrGLUniformManager&, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000417 virtual void emitSurfaceToLight(GrGLShaderBuilder*, SkString* out, const char* z) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000418private:
419 typedef GrGLLight INHERITED;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000420 UniformHandle fDirectionUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000421};
422
423///////////////////////////////////////////////////////////////////////////////
424
425class GrGLPointLight : public GrGLLight {
426public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000427 virtual ~GrGLPointLight() {}
bsalomon@google.com706f6682012-10-23 14:53:55 +0000428 virtual void setData(const GrGLUniformManager&, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000429 virtual void emitSurfaceToLight(GrGLShaderBuilder*, SkString* out, const char* z) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000430private:
431 typedef GrGLLight INHERITED;
432 SkPoint3 fLocation;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000433 UniformHandle fLocationUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000434};
435
436///////////////////////////////////////////////////////////////////////////////
437
438class GrGLSpotLight : public GrGLLight {
439public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000440 virtual ~GrGLSpotLight() {}
bsalomon@google.com706f6682012-10-23 14:53:55 +0000441 virtual void setData(const GrGLUniformManager&, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000442 virtual void emitSurfaceToLight(GrGLShaderBuilder*, SkString* out, const char* z) SK_OVERRIDE;
443 virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000444private:
445 typedef GrGLLight INHERITED;
446
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000447 SkString fLightColorFunc;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000448 UniformHandle fLocationUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000449 UniformHandle fExponentUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000450 UniformHandle fCosOuterConeAngleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000451 UniformHandle fCosInnerConeAngleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000452 UniformHandle fConeScaleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000453 UniformHandle fSUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000454};
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000455#else
456
457class GrGLLight;
458
459#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000460
461};
462
463///////////////////////////////////////////////////////////////////////////////
464
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000465class SkLight : public SkFlattenable {
466public:
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000467 SK_DECLARE_INST_COUNT(SkLight)
468
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000469 enum LightType {
470 kDistant_LightType,
471 kPoint_LightType,
472 kSpot_LightType,
473 };
474 virtual LightType type() const = 0;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000475 const SkPoint3& color() const { return fColor; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000476 virtual GrGLLight* createGLLight() const = 0;
477 virtual bool isEqual(const SkLight& other) const {
478 return fColor == other.fColor;
479 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000480
djsollen@google.com08337772012-06-26 14:33:13 +0000481protected:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000482 SkLight(SkColor color)
483 : fColor(SkIntToScalar(SkColorGetR(color)),
484 SkIntToScalar(SkColorGetG(color)),
485 SkIntToScalar(SkColorGetB(color))) {}
486 SkLight(SkFlattenableReadBuffer& buffer)
487 : INHERITED(buffer) {
488 fColor = readPoint3(buffer);
489 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000490 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
djsollen@google.com08337772012-06-26 14:33:13 +0000491 INHERITED::flatten(buffer);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000492 writePoint3(fColor, buffer);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000493 }
djsollen@google.com08337772012-06-26 14:33:13 +0000494
495private:
496 typedef SkFlattenable INHERITED;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000497 SkPoint3 fColor;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000498};
499
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000500SK_DEFINE_INST_COUNT(SkLight)
501
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000502///////////////////////////////////////////////////////////////////////////////
503
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000504class SkDistantLight : public SkLight {
505public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000506 SkDistantLight(const SkPoint3& direction, SkColor color)
507 : INHERITED(color), fDirection(direction) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000508 }
djsollen@google.com08337772012-06-26 14:33:13 +0000509
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000510 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
511 return fDirection;
512 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000513 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000514 virtual LightType type() const { return kDistant_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000515 const SkPoint3& direction() const { return fDirection; }
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000516 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
517#if SK_SUPPORT_GPU
518 return SkNEW(GrGLDistantLight);
519#else
520 SkDEBUGFAIL("Should not call in GPU-less build");
521 return NULL;
522#endif
523 }
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000524 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
525 if (other.type() != kDistant_LightType) {
526 return false;
527 }
528
529 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
530 return INHERITED::isEqual(other) &&
531 fDirection == o.fDirection;
532 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000533
534 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDistantLight)
535
djsollen@google.com08337772012-06-26 14:33:13 +0000536protected:
537 SkDistantLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
538 fDirection = readPoint3(buffer);
539 }
540 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
541 INHERITED::flatten(buffer);
542 writePoint3(fDirection, buffer);
543 }
544
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000545private:
djsollen@google.com08337772012-06-26 14:33:13 +0000546 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000547 SkPoint3 fDirection;
548};
549
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000550///////////////////////////////////////////////////////////////////////////////
551
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000552class SkPointLight : public SkLight {
553public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000554 SkPointLight(const SkPoint3& location, SkColor color)
555 : INHERITED(color), fLocation(location) {}
djsollen@google.com08337772012-06-26 14:33:13 +0000556
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000557 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
558 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
559 fLocation.fY - SkIntToScalar(y),
560 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
561 direction.normalize();
562 return direction;
563 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000564 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000565 virtual LightType type() const { return kPoint_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000566 const SkPoint3& location() const { return fLocation; }
567 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000568#if SK_SUPPORT_GPU
tomhudson@google.com300f5622012-07-20 14:15:22 +0000569 return SkNEW(GrGLPointLight);
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000570#else
571 SkDEBUGFAIL("Should not call in GPU-less build");
572 return NULL;
573#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000574 }
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000575 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000576 if (other.type() != kPoint_LightType) {
577 return false;
578 }
579 const SkPointLight& o = static_cast<const SkPointLight&>(other);
580 return INHERITED::isEqual(other) &&
581 fLocation == o.fLocation;
582 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000583
584 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPointLight)
585
djsollen@google.com08337772012-06-26 14:33:13 +0000586protected:
587 SkPointLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
588 fLocation = readPoint3(buffer);
589 }
590 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
591 INHERITED::flatten(buffer);
592 writePoint3(fLocation, buffer);
593 }
594
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000595private:
djsollen@google.com08337772012-06-26 14:33:13 +0000596 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000597 SkPoint3 fLocation;
598};
599
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000600///////////////////////////////////////////////////////////////////////////////
601
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000602class SkSpotLight : public SkLight {
603public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000604 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
605 : INHERITED(color),
606 fLocation(location),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000607 fTarget(target),
608 fSpecularExponent(specularExponent)
609 {
610 fS = target - location;
611 fS.normalize();
612 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
613 const SkScalar antiAliasThreshold = SkFloatToScalar(0.016f);
614 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
615 fConeScale = SkScalarInvert(antiAliasThreshold);
616 }
djsollen@google.com08337772012-06-26 14:33:13 +0000617
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000618 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
619 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
620 fLocation.fY - SkIntToScalar(y),
621 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
622 direction.normalize();
623 return direction;
624 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000625 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000626 SkScalar cosAngle = -surfaceToLight.dot(fS);
627 if (cosAngle < fCosOuterConeAngle) {
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000628 return SkPoint3(0, 0, 0);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000629 }
630 SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent);
631 if (cosAngle < fCosInnerConeAngle) {
632 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000633 return color() * SkScalarMul(scale, fConeScale);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000634 }
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000635 return color() * scale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000636 }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000637 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000638#if SK_SUPPORT_GPU
tomhudson@google.com300f5622012-07-20 14:15:22 +0000639 return SkNEW(GrGLSpotLight);
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000640#else
641 SkDEBUGFAIL("Should not call in GPU-less build");
642 return NULL;
643#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000644 }
djsollen@google.com08337772012-06-26 14:33:13 +0000645 virtual LightType type() const { return kSpot_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000646 const SkPoint3& location() const { return fLocation; }
647 const SkPoint3& target() const { return fTarget; }
648 SkScalar specularExponent() const { return fSpecularExponent; }
649 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
650 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
651 SkScalar coneScale() const { return fConeScale; }
senorblanco@chromium.orgeb311842012-07-11 20:49:26 +0000652 const SkPoint3& s() const { return fS; }
djsollen@google.com08337772012-06-26 14:33:13 +0000653
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000654 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpotLight)
655
djsollen@google.com08337772012-06-26 14:33:13 +0000656protected:
657 SkSpotLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
658 fLocation = readPoint3(buffer);
659 fTarget = readPoint3(buffer);
660 fSpecularExponent = buffer.readScalar();
661 fCosOuterConeAngle = buffer.readScalar();
662 fCosInnerConeAngle = buffer.readScalar();
663 fConeScale = buffer.readScalar();
664 fS = readPoint3(buffer);
665 }
666 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
667 INHERITED::flatten(buffer);
668 writePoint3(fLocation, buffer);
669 writePoint3(fTarget, buffer);
670 buffer.writeScalar(fSpecularExponent);
671 buffer.writeScalar(fCosOuterConeAngle);
672 buffer.writeScalar(fCosInnerConeAngle);
673 buffer.writeScalar(fConeScale);
674 writePoint3(fS, buffer);
675 }
676
senorblanco@chromium.orgbd9fad62012-07-11 16:25:37 +0000677 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000678 if (other.type() != kSpot_LightType) {
679 return false;
680 }
681
682 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
683 return INHERITED::isEqual(other) &&
684 fLocation == o.fLocation &&
685 fTarget == o.fTarget &&
686 fSpecularExponent == o.fSpecularExponent &&
687 fCosOuterConeAngle == o.fCosOuterConeAngle;
688 }
689
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000690private:
djsollen@google.com08337772012-06-26 14:33:13 +0000691 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000692 SkPoint3 fLocation;
693 SkPoint3 fTarget;
694 SkScalar fSpecularExponent;
695 SkScalar fCosOuterConeAngle;
696 SkScalar fCosInnerConeAngle;
697 SkScalar fConeScale;
698 SkPoint3 fS;
699};
700
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000701///////////////////////////////////////////////////////////////////////////////
702
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000703SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkImageFilter* input)
704 : INHERITED(input),
705 fLight(light),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000706 fSurfaceScale(SkScalarDiv(surfaceScale, SkIntToScalar(255)))
707{
708 SkASSERT(fLight);
reed@google.com51f38662012-06-27 14:24:29 +0000709 // our caller knows that we take ownership of the light, so we don't
710 // need to call ref() here.
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000711}
712
713SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000714 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000715 SkScalar kd, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000716 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000717 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)), surfaceScale, kd,
718 input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000719}
720
721SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000722 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000723 SkScalar kd, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000724 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000725 (SkNEW_ARGS(SkPointLight, (location, lightColor)), surfaceScale, kd,
726 input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000727}
728
729SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000730 const SkPoint3& location, const SkPoint3& target,
731 SkScalar specularExponent, SkScalar cutoffAngle,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000732 SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
733 SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000734 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000735 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent,
736 cutoffAngle, lightColor)),
737 surfaceScale, kd, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000738}
739
740SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000741 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000742 SkScalar ks, SkScalar shininess, SkImageFilter* input) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000743 return SkNEW_ARGS(SkSpecularLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000744 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)),
745 surfaceScale, ks, shininess, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000746}
747
748SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000749 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000750 SkScalar ks, SkScalar shininess, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000751 return SkNEW_ARGS(SkSpecularLightingImageFilter,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000752 (SkNEW_ARGS(SkPointLight, (location, lightColor)),
753 surfaceScale, ks, shininess, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000754}
755
756SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000757 const SkPoint3& location, const SkPoint3& target,
758 SkScalar specularExponent, SkScalar cutoffAngle,
759 SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000760 SkScalar ks, SkScalar shininess, SkImageFilter* input) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000761 return SkNEW_ARGS(SkSpecularLightingImageFilter,
762 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, cutoffAngle, lightColor)),
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000763 surfaceScale, ks, shininess, input));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000764}
765
766SkLightingImageFilter::~SkLightingImageFilter() {
767 fLight->unref();
768}
769
770SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer)
771 : INHERITED(buffer)
772{
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000773 fLight = buffer.readFlattenableT<SkLight>();
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000774 fSurfaceScale = buffer.readScalar();
775}
776
777void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
778 this->INHERITED::flatten(buffer);
djsollen@google.com08337772012-06-26 14:33:13 +0000779 buffer.writeFlattenable(fLight);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000780 buffer.writeScalar(fSurfaceScale);
781}
782
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000783///////////////////////////////////////////////////////////////////////////////
784
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000785SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input)
786 : SkLightingImageFilter(light, surfaceScale, input),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000787 fKD(kd)
788{
789}
790
791SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer)
792 : INHERITED(buffer)
793{
794 fKD = buffer.readScalar();
795}
796
797void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
798 this->INHERITED::flatten(buffer);
799 buffer.writeScalar(fKD);
800}
801
802bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
803 const SkBitmap& src,
804 const SkMatrix&,
805 SkBitmap* dst,
806 SkIPoint*) {
807 if (src.config() != SkBitmap::kARGB_8888_Config) {
808 return false;
809 }
810 SkAutoLockPixels alp(src);
811 if (!src.getPixels()) {
812 return false;
813 }
814 if (src.width() < 2 || src.height() < 2) {
815 return false;
816 }
817 dst->setConfig(src.config(), src.width(), src.height());
818 dst->allocPixels();
819
820 DiffuseLightingType lightingType(fKD);
821 switch (light()->type()) {
822 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000823 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000824 break;
825 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000826 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000827 break;
828 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000829 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000830 break;
831 }
832 return true;
833}
834
bsalomon@google.com021fc732012-10-25 12:47:42 +0000835bool SkDiffuseLightingImageFilter::asNewEffect(GrEffect** effect,
bsalomon@google.com8ea78d82012-10-24 20:11:30 +0000836 GrTexture* texture) const {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000837#if SK_SUPPORT_GPU
bsalomon@google.com021fc732012-10-25 12:47:42 +0000838 if (effect) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000839 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
bsalomon@google.com021fc732012-10-25 12:47:42 +0000840 *effect = SkNEW_ARGS(GrDiffuseLightingEffect, (texture, light(), scale, kd()));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000841 }
842 return true;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000843#else
844 SkDEBUGFAIL("Should not call in GPU-less build");
845 return false;
846#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000847}
848
849///////////////////////////////////////////////////////////////////////////////
850
senorblanco@chromium.org254eae22012-10-05 17:38:00 +0000851SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input)
852 : SkLightingImageFilter(light, surfaceScale, input),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000853 fKS(ks),
854 fShininess(shininess)
855{
856}
857
858SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer)
859 : INHERITED(buffer)
860{
861 fKS = buffer.readScalar();
862 fShininess = buffer.readScalar();
863}
864
865void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
866 this->INHERITED::flatten(buffer);
867 buffer.writeScalar(fKS);
868 buffer.writeScalar(fShininess);
869}
870
871bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
872 const SkBitmap& src,
873 const SkMatrix&,
874 SkBitmap* dst,
875 SkIPoint*) {
876 if (src.config() != SkBitmap::kARGB_8888_Config) {
877 return false;
878 }
879 SkAutoLockPixels alp(src);
880 if (!src.getPixels()) {
881 return false;
882 }
883 if (src.width() < 2 || src.height() < 2) {
884 return false;
885 }
886 dst->setConfig(src.config(), src.width(), src.height());
887 dst->allocPixels();
888
889 SpecularLightingType lightingType(fKS, fShininess);
890 switch (light()->type()) {
891 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000892 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000893 break;
894 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000895 lightBitmap<SpecularLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000896 break;
897 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000898 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000899 break;
900 }
901 return true;
902}
903
bsalomon@google.com021fc732012-10-25 12:47:42 +0000904bool SkSpecularLightingImageFilter::asNewEffect(GrEffect** effect,
bsalomon@google.com8ea78d82012-10-24 20:11:30 +0000905 GrTexture* texture) const {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000906#if SK_SUPPORT_GPU
bsalomon@google.com021fc732012-10-25 12:47:42 +0000907 if (effect) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000908 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
bsalomon@google.com021fc732012-10-25 12:47:42 +0000909 *effect = SkNEW_ARGS(GrSpecularLightingEffect, (texture, light(), scale, ks(), shininess()));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000910 }
911 return true;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000912#else
913 SkDEBUGFAIL("Should not call in GPU-less build");
914 return false;
915#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000916}
917
918///////////////////////////////////////////////////////////////////////////////
919
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000920#if SK_SUPPORT_GPU
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000921
922namespace {
923SkPoint3 random_point3(SkRandom* random) {
924 return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
925 SkScalarToFloat(random->nextSScalar1()),
926 SkScalarToFloat(random->nextSScalar1()));
927}
928
929SkLight* create_random_light(SkRandom* random) {
930 int type = random->nextULessThan(3);
931 switch (type) {
932 case 0: {
933 return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU()));
934 }
935 case 1: {
936 return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU()));
937 }
938 case 2: {
939 return SkNEW_ARGS(SkSpotLight, (random_point3(random),
940 random_point3(random),
941 random->nextUScalar1(),
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000942 random->nextUScalar1(),
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000943 random->nextU()));
944 }
945 default:
946 GrCrash();
947 return NULL;
948 }
949}
950
951}
952
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000953class GrGLLightingEffect : public GrGLEffect {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000954public:
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000955 GrGLLightingEffect(const GrBackendEffectFactory& factory,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000956 const GrEffect& effect);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000957 virtual ~GrGLLightingEffect();
958
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000959 virtual void emitCode(GrGLShaderBuilder*,
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000960 const GrEffectStage&,
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000961 EffectKey,
962 const char* vertexCoords,
963 const char* outputColor,
964 const char* inputColor,
965 const TextureSamplerArray&) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000966
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +0000967 static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000968
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000969 /**
970 * Subclasses of GrGLLightingEffect must call INHERITED::setData();
971 */
bsalomon@google.com28a15fb2012-10-26 17:53:18 +0000972 virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000973
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000974protected:
975 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0;
976
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000977private:
bsalomon@google.comae5ef112012-10-29 14:53:53 +0000978 typedef GrGLEffect INHERITED;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000979
bsalomon@google.com17fc6512012-11-02 21:45:01 +0000980 UniformHandle fImageIncrementUni;
981 UniformHandle fSurfaceScaleUni;
982 GrGLLight* fLight;
983 GrGLEffectMatrix fEffectMatrix;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000984};
985
986///////////////////////////////////////////////////////////////////////////////
987
988class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
989public:
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000990 GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000991 const GrEffect& effect);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000992 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
bsalomon@google.com28a15fb2012-10-26 17:53:18 +0000993 virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000994
995private:
996 typedef GrGLLightingEffect INHERITED;
997
bsalomon@google.com032b2212012-07-16 13:36:18 +0000998 UniformHandle fKDUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000999};
1000
1001///////////////////////////////////////////////////////////////////////////////
1002
1003class GrGLSpecularLightingEffect : public GrGLLightingEffect {
1004public:
bsalomon@google.com396e61f2012-10-25 19:00:29 +00001005 GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory,
bsalomon@google.com021fc732012-10-25 12:47:42 +00001006 const GrEffect& effect);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001007 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
bsalomon@google.com28a15fb2012-10-26 17:53:18 +00001008 virtual void setData(const GrGLUniformManager&, const GrEffectStage&) SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001009
1010private:
1011 typedef GrGLLightingEffect INHERITED;
1012
bsalomon@google.com032b2212012-07-16 13:36:18 +00001013 UniformHandle fKSUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001014 UniformHandle fShininessUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001015};
1016
1017///////////////////////////////////////////////////////////////////////////////
1018
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001019GrLightingEffect::GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale)
bsalomon@google.com17fc6512012-11-02 21:45:01 +00001020 : INHERITED(texture, MakeDivByTextureWHMatrix(texture))
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001021 , fLight(light)
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001022 , fSurfaceScale(surfaceScale) {
1023 fLight->ref();
1024}
1025
1026GrLightingEffect::~GrLightingEffect() {
1027 fLight->unref();
1028}
1029
bsalomon@google.coma469c282012-10-24 18:28:34 +00001030bool GrLightingEffect::isEqual(const GrEffect& sBase) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001031 const GrLightingEffect& s =
1032 static_cast<const GrLightingEffect&>(sBase);
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001033 return INHERITED::isEqual(sBase) &&
1034 fLight->isEqual(*s.fLight) &&
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001035 fSurfaceScale == s.fSurfaceScale;
1036}
1037
1038///////////////////////////////////////////////////////////////////////////////
1039
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001040GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar kd)
1041 : INHERITED(texture, light, surfaceScale), fKD(kd) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001042}
1043
bsalomon@google.com396e61f2012-10-25 19:00:29 +00001044const GrBackendEffectFactory& GrDiffuseLightingEffect::getFactory() const {
1045 return GrTBackendEffectFactory<GrDiffuseLightingEffect>::getInstance();
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001046}
1047
bsalomon@google.coma469c282012-10-24 18:28:34 +00001048bool GrDiffuseLightingEffect::isEqual(const GrEffect& sBase) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001049 const GrDiffuseLightingEffect& s =
1050 static_cast<const GrDiffuseLightingEffect&>(sBase);
1051 return INHERITED::isEqual(sBase) &&
1052 this->kd() == s.kd();
1053}
1054
bsalomon@google.comf271cc72012-10-24 19:35:13 +00001055GR_DEFINE_EFFECT_TEST(GrDiffuseLightingEffect);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001056
bsalomon@google.coma469c282012-10-24 18:28:34 +00001057GrEffect* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
1058 GrContext* context,
1059 GrTexture* textures[]) {
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001060 SkScalar surfaceScale = random->nextSScalar1();
1061 SkScalar kd = random->nextUScalar1();
1062 SkAutoTUnref<SkLight> light(create_random_light(random));
bsalomon@google.com6f261be2012-10-24 19:07:10 +00001063 return SkNEW_ARGS(GrDiffuseLightingEffect, (textures[GrEffectUnitTest::kAlphaTextureIdx],
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001064 light, surfaceScale, kd));
1065}
1066
1067
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001068///////////////////////////////////////////////////////////////////////////////
1069
bsalomon@google.com396e61f2012-10-25 19:00:29 +00001070GrGLLightingEffect::GrGLLightingEffect(const GrBackendEffectFactory& factory,
bsalomon@google.com021fc732012-10-25 12:47:42 +00001071 const GrEffect& effect)
bsalomon@google.com374e7592012-10-23 17:30:45 +00001072 : INHERITED(factory)
bsalomon@google.com032b2212012-07-16 13:36:18 +00001073 , fImageIncrementUni(kInvalidUniformHandle)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001074 , fSurfaceScaleUni(kInvalidUniformHandle) {
bsalomon@google.com021fc732012-10-25 12:47:42 +00001075 const GrLightingEffect& m = static_cast<const GrLightingEffect&>(effect);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001076 fLight = m.light()->createGLLight();
1077}
1078
1079GrGLLightingEffect::~GrGLLightingEffect() {
1080 delete fLight;
1081}
1082
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001083void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder,
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +00001084 const GrEffectStage&,
bsalomon@google.com17fc6512012-11-02 21:45:01 +00001085 EffectKey key,
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001086 const char* vertexCoords,
1087 const char* outputColor,
1088 const char* inputColor,
1089 const TextureSamplerArray& samplers) {
bsalomon@google.com17fc6512012-11-02 21:45:01 +00001090 const char* coords;
1091 fEffectMatrix.emitCodeMakeFSCoords2D(builder, key, vertexCoords, &coords);
1092
bsalomon@google.com032b2212012-07-16 13:36:18 +00001093 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1094 kVec2f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001095 "ImageIncrement");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001096 fSurfaceScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1097 kFloat_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001098 "SurfaceScale");
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001099 fLight->emitLightColorUniform(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001100 SkString* code = &builder->fFSCode;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001101 SkString lightFunc;
1102 this->emitLightFunc(builder, &lightFunc);
1103 static const GrGLShaderVar gSobelArgs[] = {
1104 GrGLShaderVar("a", kFloat_GrSLType),
1105 GrGLShaderVar("b", kFloat_GrSLType),
1106 GrGLShaderVar("c", kFloat_GrSLType),
1107 GrGLShaderVar("d", kFloat_GrSLType),
1108 GrGLShaderVar("e", kFloat_GrSLType),
1109 GrGLShaderVar("f", kFloat_GrSLType),
1110 GrGLShaderVar("scale", kFloat_GrSLType),
1111 };
1112 SkString sobelFuncName;
1113 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1114 kFloat_GrSLType,
1115 "sobel",
1116 SK_ARRAY_COUNT(gSobelArgs),
1117 gSobelArgs,
1118 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1119 &sobelFuncName);
1120 static const GrGLShaderVar gPointToNormalArgs[] = {
1121 GrGLShaderVar("x", kFloat_GrSLType),
1122 GrGLShaderVar("y", kFloat_GrSLType),
1123 GrGLShaderVar("scale", kFloat_GrSLType),
1124 };
1125 SkString pointToNormalName;
1126 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1127 kVec3f_GrSLType,
1128 "pointToNormal",
1129 SK_ARRAY_COUNT(gPointToNormalArgs),
1130 gPointToNormalArgs,
bsalomon@google.com706f6682012-10-23 14:53:55 +00001131 "\treturn normalize(vec3(-x * scale, y * scale, 1));\n",
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001132 &pointToNormalName);
1133
1134 static const GrGLShaderVar gInteriorNormalArgs[] = {
1135 GrGLShaderVar("m", kFloat_GrSLType, 9),
1136 GrGLShaderVar("surfaceScale", kFloat_GrSLType),
1137 };
1138 SkString interiorNormalBody;
1139 interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n"
1140 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n"
1141 "\t surfaceScale);\n",
1142 pointToNormalName.c_str(),
1143 sobelFuncName.c_str(),
1144 sobelFuncName.c_str());
1145 SkString interiorNormalName;
1146 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1147 kVec3f_GrSLType,
1148 "interiorNormal",
1149 SK_ARRAY_COUNT(gInteriorNormalArgs),
1150 gInteriorNormalArgs,
1151 interiorNormalBody.c_str(),
1152 &interiorNormalName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001153
bsalomon@google.com17fc6512012-11-02 21:45:01 +00001154 code->appendf("\t\tvec2 coord = %s;\n", coords);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001155 code->appendf("\t\tfloat m[9];\n");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001156
1157 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
1158 const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
1159
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001160 int index = 0;
1161 for (int dy = -1; dy <= 1; dy++) {
1162 for (int dx = -1; dx <= 1; dx++) {
1163 SkString texCoords;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001164 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001165 code->appendf("\t\tm[%d] = ", index++);
bsalomon@google.comf06df1b2012-09-06 20:22:31 +00001166 builder->appendTextureLookup(code, samplers[0], texCoords.c_str());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001167 code->appendf(".a;\n");
1168 }
1169 }
1170 code->appendf("\t\tvec3 surfaceToLight = ");
1171 SkString arg;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001172 arg.appendf("%s * m[4]", surfScale);
1173 fLight->emitSurfaceToLight(builder, code, arg.c_str());
bsalomon@google.com868a8e72012-08-30 19:11:34 +00001174 code->append(";\n");
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001175 code->appendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1176 outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale);
1177 fLight->emitLightColor(builder, "surfaceToLight");
bsalomon@google.com868a8e72012-08-30 19:11:34 +00001178 code->append(");\n");
1179 GrGLSLMulVarBy4f(code, 2, outputColor, inputColor);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001180}
1181
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +00001182GrGLEffect::EffectKey GrGLLightingEffect::GenKey(const GrEffectStage& s,
1183 const GrGLCaps& caps) {
bsalomon@google.com17fc6512012-11-02 21:45:01 +00001184 const GrLightingEffect& effect = static_cast<const GrLightingEffect&>(*s.getEffect());
1185 EffectKey key = static_cast<const GrLightingEffect&>(*s.getEffect()).light()->type();
1186 key <<= GrGLEffectMatrix::kKeyBits;
1187 EffectKey matrixKey = GrGLEffectMatrix::GenKey(effect.getMatrix(),
1188 s.getCoordChangeMatrix(),
1189 effect.texture(0));
1190 return key | matrixKey;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001191}
1192
bsalomon@google.com28a15fb2012-10-26 17:53:18 +00001193void GrGLLightingEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
1194 const GrLightingEffect& effect =static_cast<const GrLightingEffect&>(*stage.getEffect());
bsalomon@google.com2d0bade2012-10-26 19:01:17 +00001195 GrTexture* texture = effect.texture(0);
1196 float ySign = texture->origin() == GrSurface::kTopLeft_Origin ? -1.0f : 1.0f;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001197 uman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1198 uman.set1f(fSurfaceScaleUni, effect.surfaceScale());
bsalomon@google.com706f6682012-10-23 14:53:55 +00001199 fLight->setData(uman, effect.light());
bsalomon@google.com17fc6512012-11-02 21:45:01 +00001200 fEffectMatrix.setData(uman,
1201 effect.getMatrix(),
1202 stage.getCoordChangeMatrix(),
1203 effect.texture(0));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001204}
1205
1206///////////////////////////////////////////////////////////////////////////////
1207
1208///////////////////////////////////////////////////////////////////////////////
1209
bsalomon@google.com396e61f2012-10-25 19:00:29 +00001210GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory,
bsalomon@google.com17fc6512012-11-02 21:45:01 +00001211 const GrEffect& effect)
bsalomon@google.com021fc732012-10-25 12:47:42 +00001212 : INHERITED(factory, effect)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001213 , fKDUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001214}
1215
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001216void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001217 const char* kd;
1218 fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1219 kFloat_GrSLType,
1220 "KD",
1221 &kd);
1222
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001223 static const GrGLShaderVar gLightArgs[] = {
1224 GrGLShaderVar("normal", kVec3f_GrSLType),
1225 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1226 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1227 };
1228 SkString lightBody;
1229 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1230 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1231 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1232 kVec4f_GrSLType,
1233 "light",
1234 SK_ARRAY_COUNT(gLightArgs),
1235 gLightArgs,
1236 lightBody.c_str(),
1237 funcName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001238}
1239
bsalomon@google.com28a15fb2012-10-26 17:53:18 +00001240void GrGLDiffuseLightingEffect::setData(const GrGLUniformManager& uman,
1241 const GrEffectStage& stage) {
1242 INHERITED::setData(uman, stage);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001243 const GrDiffuseLightingEffect& effect =
bsalomon@google.com28a15fb2012-10-26 17:53:18 +00001244 static_cast<const GrDiffuseLightingEffect&>(*stage.getEffect());
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001245 uman.set1f(fKDUni, effect.kd());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001246}
1247
1248///////////////////////////////////////////////////////////////////////////////
1249
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001250GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess)
1251 : INHERITED(texture, light, surfaceScale),
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001252 fKS(ks),
1253 fShininess(shininess) {
1254}
1255
bsalomon@google.com396e61f2012-10-25 19:00:29 +00001256const GrBackendEffectFactory& GrSpecularLightingEffect::getFactory() const {
1257 return GrTBackendEffectFactory<GrSpecularLightingEffect>::getInstance();
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001258}
1259
bsalomon@google.coma469c282012-10-24 18:28:34 +00001260bool GrSpecularLightingEffect::isEqual(const GrEffect& sBase) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001261 const GrSpecularLightingEffect& s =
1262 static_cast<const GrSpecularLightingEffect&>(sBase);
1263 return INHERITED::isEqual(sBase) &&
1264 this->ks() == s.ks() &&
1265 this->shininess() == s.shininess();
1266}
1267
bsalomon@google.comf271cc72012-10-24 19:35:13 +00001268GR_DEFINE_EFFECT_TEST(GrSpecularLightingEffect);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001269
bsalomon@google.coma469c282012-10-24 18:28:34 +00001270GrEffect* GrSpecularLightingEffect::TestCreate(SkRandom* random,
1271 GrContext* context,
1272 GrTexture* textures[]) {
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001273 SkScalar surfaceScale = random->nextSScalar1();
1274 SkScalar ks = random->nextUScalar1();
1275 SkScalar shininess = random->nextUScalar1();
1276 SkAutoTUnref<SkLight> light(create_random_light(random));
bsalomon@google.com6f261be2012-10-24 19:07:10 +00001277 return SkNEW_ARGS(GrSpecularLightingEffect, (textures[GrEffectUnitTest::kAlphaTextureIdx],
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001278 light, surfaceScale, ks, shininess));
1279}
1280
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001281///////////////////////////////////////////////////////////////////////////////
1282
bsalomon@google.com396e61f2012-10-25 19:00:29 +00001283GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory,
bsalomon@google.com021fc732012-10-25 12:47:42 +00001284 const GrEffect& effect)
1285 : GrGLLightingEffect(factory, effect)
bsalomon@google.com032b2212012-07-16 13:36:18 +00001286 , fKSUni(kInvalidUniformHandle)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001287 , fShininessUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001288}
1289
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001290void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001291 const char* ks;
1292 const char* shininess;
1293
1294 fKSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1295 kFloat_GrSLType, "KS", &ks);
1296 fShininessUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1297 kFloat_GrSLType, "Shininess", &shininess);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001298
1299 static const GrGLShaderVar gLightArgs[] = {
1300 GrGLShaderVar("normal", kVec3f_GrSLType),
1301 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1302 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1303 };
1304 SkString lightBody;
1305 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1306 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
senorblanco@chromium.org7b734e02012-10-29 19:47:06 +00001307 lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
1308 lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n");
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001309 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1310 kVec4f_GrSLType,
1311 "light",
1312 SK_ARRAY_COUNT(gLightArgs),
1313 gLightArgs,
1314 lightBody.c_str(),
1315 funcName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001316}
1317
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001318void GrGLSpecularLightingEffect::setData(const GrGLUniformManager& uman,
bsalomon@google.com28a15fb2012-10-26 17:53:18 +00001319 const GrEffectStage& stage) {
1320 INHERITED::setData(uman, stage);
1321 const GrSpecularLightingEffect& effect =
1322 static_cast<const GrSpecularLightingEffect&>(*stage.getEffect());
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001323 uman.set1f(fKSUni, effect.ks());
1324 uman.set1f(fShininessUni, effect.shininess());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001325}
1326
1327///////////////////////////////////////////////////////////////////////////////
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001328void GrGLLight::emitLightColorUniform(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001329 fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001330 kVec3f_GrSLType, "LightColor");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001331}
1332
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001333void GrGLLight::emitLightColor(GrGLShaderBuilder* builder,
1334 const char *surfaceToLight) {
1335 builder->fFSCode.append(builder->getUniformCStr(this->lightColorUni()));
1336}
1337
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001338void GrGLLight::setData(const GrGLUniformManager& uman,
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001339 const SkLight* light) const {
1340 setUniformPoint3(uman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001341}
1342
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001343///////////////////////////////////////////////////////////////////////////////
1344
bsalomon@google.com706f6682012-10-23 14:53:55 +00001345void GrGLDistantLight::setData(const GrGLUniformManager& uman, const SkLight* light) const {
1346 INHERITED::setData(uman, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001347 SkASSERT(light->type() == SkLight::kDistant_LightType);
1348 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001349 setUniformNormal3(uman, fDirectionUni, distantLight->direction());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001350}
1351
bsalomon@google.com706f6682012-10-23 14:53:55 +00001352void GrGLDistantLight::emitSurfaceToLight(GrGLShaderBuilder* builder,
bsalomon@google.com032b2212012-07-16 13:36:18 +00001353 SkString* out,
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001354 const char* z) {
1355 const char* dir;
1356 fDirectionUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
1357 "LightDirection", &dir);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001358 out->append(dir);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001359}
1360
1361///////////////////////////////////////////////////////////////////////////////
1362
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001363void GrGLPointLight::setData(const GrGLUniformManager& uman,
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001364 const SkLight* light) const {
bsalomon@google.com706f6682012-10-23 14:53:55 +00001365 INHERITED::setData(uman, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001366 SkASSERT(light->type() == SkLight::kPoint_LightType);
1367 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
bsalomon@google.com706f6682012-10-23 14:53:55 +00001368 setUniformPoint3(uman, fLocationUni, pointLight->location());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001369}
1370
bsalomon@google.com706f6682012-10-23 14:53:55 +00001371void GrGLPointLight::emitSurfaceToLight(GrGLShaderBuilder* builder,
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001372 SkString* out,
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001373 const char* z) {
1374 const char* loc;
1375 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
1376 "LightLocation", &loc);
bsalomon@google.com706f6682012-10-23 14:53:55 +00001377 out->appendf("normalize(%s - vec3(%s.xy, %s))", loc, builder->fragmentPosition(), z);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001378}
1379
1380///////////////////////////////////////////////////////////////////////////////
1381
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001382void GrGLSpotLight::setData(const GrGLUniformManager& uman,
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001383 const SkLight* light) const {
bsalomon@google.com706f6682012-10-23 14:53:55 +00001384 INHERITED::setData(uman, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001385 SkASSERT(light->type() == SkLight::kSpot_LightType);
1386 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
bsalomon@google.com706f6682012-10-23 14:53:55 +00001387 setUniformPoint3(uman, fLocationUni, spotLight->location());
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001388 uman.set1f(fExponentUni, spotLight->specularExponent());
1389 uman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
1390 uman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
1391 uman.set1f(fConeScaleUni, spotLight->coneScale());
1392 setUniformNormal3(uman, fSUni, spotLight->s());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001393}
1394
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001395void GrGLSpotLight::emitSurfaceToLight(GrGLShaderBuilder* builder,
1396 SkString* out,
1397 const char* z) {
1398 const char* location;
1399 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1400 kVec3f_GrSLType, "LightLocation", &location);
1401 out->appendf("normalize(%s - vec3(%s.xy, %s))", location, builder->fragmentPosition(), z);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001402}
1403
bsalomon@google.comae5ef112012-10-29 14:53:53 +00001404void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder,
1405 const char *surfaceToLight) {
1406
1407 const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class.
1408
1409 const char* exponent;
1410 const char* cosInner;
1411 const char* cosOuter;
1412 const char* coneScale;
1413 const char* s;
1414 fExponentUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1415 kFloat_GrSLType, "Exponent", &exponent);
1416 fCosInnerConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1417 kFloat_GrSLType, "CosInnerConeAngle", &cosInner);
1418 fCosOuterConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1419 kFloat_GrSLType, "CosOuterConeAngle", &cosOuter);
1420 fConeScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1421 kFloat_GrSLType, "ConeScale", &coneScale);
1422 fSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1423 kVec3f_GrSLType, "S", &s);
1424
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001425 static const GrGLShaderVar gLightColorArgs[] = {
1426 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType)
1427 };
1428 SkString lightColorBody;
1429 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
1430 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
1431 lightColorBody.appendf("\t\treturn vec3(0);\n");
1432 lightColorBody.appendf("\t}\n");
1433 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
1434 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
1435 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
1436 color, cosOuter, coneScale);
1437 lightColorBody.appendf("\t}\n");
1438 lightColorBody.appendf("\treturn %s;\n", color);
1439 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1440 kVec3f_GrSLType,
1441 "lightColor",
1442 SK_ARRAY_COUNT(gLightColorArgs),
1443 gLightColorArgs,
1444 lightColorBody.c_str(),
1445 &fLightColorFunc);
skia.committer@gmail.come862d162012-10-31 02:01:18 +00001446
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001447 builder->fFSCode.appendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001448}
1449
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +00001450#endif
1451
djsollen@google.com08337772012-06-26 14:33:13 +00001452SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
1453 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
1454 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
1455 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDistantLight)
1456 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPointLight)
1457 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpotLight)
1458SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END