blob: 8eb28bb3c54e1b10fbf2ff624ec964f10aeb8353 [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
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000017#include "GrProgramStageFactory.h"
tomhudson@google.comd0c1a062012-07-12 17:23:52 +000018#include "effects/GrSingleTextureEffect.h"
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000019#include "gl/GrGLProgramStage.h"
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000020#include "gl/GrGLTexture.h"
21#include "GrCustomStage.h"
22
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) {
45 setUniformPoint3(uman, uni, SkPoint3(point.fX, -point.fY, point.fZ));
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000046}
47
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +000048void setUniformPoint3FlipY(const GrGLUniformManager& uman,
49 UniformHandle uni,
50 const SkPoint3& point,
51 int height) {
52 setUniformPoint3(uman, uni, SkPoint3(point.fX, height-point.fY, point.fZ));
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000053}
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +000054#endif
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +000055
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +000056// Shift matrix components to the left, as we advance pixels to the right.
57inline void shiftMatrixLeft(int m[9]) {
58 m[0] = m[1];
59 m[3] = m[4];
60 m[6] = m[7];
61 m[1] = m[2];
62 m[4] = m[5];
63 m[7] = m[8];
64}
65
66class DiffuseLightingType {
67public:
68 DiffuseLightingType(SkScalar kd)
69 : fKD(kd) {}
70 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
71 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
72 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
73 SkPoint3 color(lightColor * colorScale);
74 return SkPackARGB32(255,
75 SkScalarFloorToInt(color.fX),
76 SkScalarFloorToInt(color.fY),
77 SkScalarFloorToInt(color.fZ));
78 }
79private:
80 SkScalar fKD;
81};
82
83class SpecularLightingType {
84public:
85 SpecularLightingType(SkScalar ks, SkScalar shininess)
86 : fKS(ks), fShininess(shininess) {}
87 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
88 SkPoint3 halfDir(surfaceTolight);
89 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1)
90 halfDir.normalize();
91 SkScalar colorScale = SkScalarMul(fKS,
92 SkScalarPow(normal.dot(halfDir), fShininess));
93 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
94 SkPoint3 color(lightColor * colorScale);
95 return SkPackARGB32(SkScalarFloorToInt(color.maxComponent()),
96 SkScalarFloorToInt(color.fX),
97 SkScalarFloorToInt(color.fY),
98 SkScalarFloorToInt(color.fZ));
99 }
100private:
101 SkScalar fKS;
102 SkScalar fShininess;
103};
104
105inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
106 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
107}
108
109inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
110 SkPoint3 vector(SkScalarMul(-x, surfaceScale),
111 SkScalarMul(-y, surfaceScale),
112 SK_Scalar1);
113 vector.normalize();
114 return vector;
115}
116
117inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
118 return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
119 sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
120 surfaceScale);
121}
122
123inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
124 return pointToNormal(sobel( 0, 0, m[3], m[5], m[6], m[8], gOneThird),
125 sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
126 surfaceScale);
127}
128
129inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
130 return pointToNormal(sobel( 0, 0, m[3], m[4], m[6], m[7], gTwoThirds),
131 sobel(m[3], m[6], m[4], m[7], 0, 0, gTwoThirds),
132 surfaceScale);
133}
134
135inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
136 return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
137 sobel( 0, 0, m[1], m[7], m[2], m[8], gOneThird),
138 surfaceScale);
139}
140
141
142inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
143 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
144 sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
145 surfaceScale);
146}
147
148inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
149 return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
150 sobel(m[0], m[6], m[1], m[7], 0, 0, gOneThird),
151 surfaceScale);
152}
153
154inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
155 return pointToNormal(sobel(m[1], m[2], m[4], m[5], 0, 0, gTwoThirds),
156 sobel( 0, 0, m[1], m[4], m[2], m[5], gTwoThirds),
157 surfaceScale);
158}
159
160inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
161 return pointToNormal(sobel(m[0], m[2], m[3], m[5], 0, 0, gOneThird),
162 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
163 surfaceScale);
164}
165
166inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
167 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds),
168 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds),
169 surfaceScale);
170}
171
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000172template <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 +0000173 const LightType* l = static_cast<const LightType*>(light);
174 int y = 0;
175 {
176 const SkPMColor* row1 = src.getAddr32(0, 0);
177 const SkPMColor* row2 = src.getAddr32(0, 1);
178 SkPMColor* dptr = dst->getAddr32(0, 0);
179 int m[9];
180 int x = 0;
181 m[4] = SkGetPackedA32(*row1++);
182 m[5] = SkGetPackedA32(*row1++);
183 m[7] = SkGetPackedA32(*row2++);
184 m[8] = SkGetPackedA32(*row2++);
185 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000186 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000187 for (x = 1; x < src.width() - 1; ++x)
188 {
189 shiftMatrixLeft(m);
190 m[5] = SkGetPackedA32(*row1++);
191 m[8] = SkGetPackedA32(*row2++);
192 surfaceToLight = l->surfaceToLight(x, 0, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000193 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000194 }
195 shiftMatrixLeft(m);
196 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000197 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000198 }
199
200 for (++y; y < src.height() - 1; ++y) {
201 const SkPMColor* row0 = src.getAddr32(0, y - 1);
202 const SkPMColor* row1 = src.getAddr32(0, y);
203 const SkPMColor* row2 = src.getAddr32(0, y + 1);
204 SkPMColor* dptr = dst->getAddr32(0, y);
205 int m[9];
206 int x = 0;
207 m[1] = SkGetPackedA32(*row0++);
208 m[2] = SkGetPackedA32(*row0++);
209 m[4] = SkGetPackedA32(*row1++);
210 m[5] = SkGetPackedA32(*row1++);
211 m[7] = SkGetPackedA32(*row2++);
212 m[8] = SkGetPackedA32(*row2++);
213 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000214 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000215 for (x = 1; x < src.width() - 1; ++x) {
216 shiftMatrixLeft(m);
217 m[2] = SkGetPackedA32(*row0++);
218 m[5] = SkGetPackedA32(*row1++);
219 m[8] = SkGetPackedA32(*row2++);
220 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000221 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000222 }
223 shiftMatrixLeft(m);
224 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000225 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000226 }
227
228 {
229 const SkPMColor* row0 = src.getAddr32(0, src.height() - 2);
230 const SkPMColor* row1 = src.getAddr32(0, src.height() - 1);
231 int x = 0;
232 SkPMColor* dptr = dst->getAddr32(0, src.height() - 1);
233 int m[9];
234 m[1] = SkGetPackedA32(*row0++);
235 m[2] = SkGetPackedA32(*row0++);
236 m[4] = SkGetPackedA32(*row1++);
237 m[5] = SkGetPackedA32(*row1++);
238 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000239 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000240 for (x = 1; x < src.width() - 1; ++x)
241 {
242 shiftMatrixLeft(m);
243 m[2] = SkGetPackedA32(*row0++);
244 m[5] = SkGetPackedA32(*row1++);
245 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000246 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000247 }
248 shiftMatrixLeft(m);
249 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000250 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000251 }
252}
253
254SkPoint3 readPoint3(SkFlattenableReadBuffer& buffer) {
255 SkPoint3 point;
256 point.fX = buffer.readScalar();
257 point.fY = buffer.readScalar();
258 point.fZ = buffer.readScalar();
259 return point;
260};
261
262void writePoint3(const SkPoint3& point, SkFlattenableWriteBuffer& buffer) {
263 buffer.writeScalar(point.fX);
264 buffer.writeScalar(point.fY);
265 buffer.writeScalar(point.fZ);
266};
267
268class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
269public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000270 SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000271 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
272
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000273 virtual bool asNewCustomStage(GrCustomStage** stage, GrTexture*) const SK_OVERRIDE;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000274 SkScalar kd() const { return fKD; }
275
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000276protected:
277 explicit SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer);
278 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
279 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
280 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
281
282
283private:
284 typedef SkLightingImageFilter INHERITED;
285 SkScalar fKD;
286};
287
288class SkSpecularLightingImageFilter : public SkLightingImageFilter {
289public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000290 SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000291 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
292
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000293 virtual bool asNewCustomStage(GrCustomStage** stage, GrTexture*) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000294 SkScalar ks() const { return fKS; }
295 SkScalar shininess() const { return fShininess; }
296
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000297protected:
298 explicit SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer);
299 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE;
300 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
301 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
302
303private:
304 typedef SkLightingImageFilter INHERITED;
305 SkScalar fKS;
306 SkScalar fShininess;
307};
308
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000309#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000310
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000311class GrLightingEffect : public GrSingleTextureEffect {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000312public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000313 GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000314 virtual ~GrLightingEffect();
315
316 virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
317
318 const SkLight* light() const { return fLight; }
319 SkScalar surfaceScale() const { return fSurfaceScale; }
320private:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000321 typedef GrSingleTextureEffect INHERITED;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000322 const SkLight* fLight;
323 SkScalar fSurfaceScale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000324};
325
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000326class GrDiffuseLightingEffect : public GrLightingEffect {
327public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000328 GrDiffuseLightingEffect(GrTexture* texture,
329 const SkLight* light,
330 SkScalar surfaceScale,
331 SkScalar kd);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000332
333 static const char* Name() { return "DiffuseLighting"; }
334
335 typedef GrGLDiffuseLightingEffect GLProgramStage;
336
337 virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
338 virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
339 SkScalar kd() const { return fKD; }
340private:
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000341 GR_DECLARE_CUSTOM_STAGE_TEST;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000342 typedef GrLightingEffect INHERITED;
343 SkScalar fKD;
344};
345
346class GrSpecularLightingEffect : public GrLightingEffect {
347public:
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000348 GrSpecularLightingEffect(GrTexture* texture,
349 const SkLight* light,
350 SkScalar surfaceScale,
351 SkScalar ks,
352 SkScalar shininess);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000353
354 static const char* Name() { return "SpecularLighting"; }
355
356 typedef GrGLSpecularLightingEffect GLProgramStage;
357
358 virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
359 virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
360 SkScalar ks() const { return fKS; }
361 SkScalar shininess() const { return fShininess; }
362
363private:
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000364 GR_DECLARE_CUSTOM_STAGE_TEST;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000365 typedef GrLightingEffect INHERITED;
366 SkScalar fKS;
367 SkScalar fShininess;
368};
369
370///////////////////////////////////////////////////////////////////////////////
371
372class GrGLLight {
373public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000374 virtual ~GrGLLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000375 virtual void setupVariables(GrGLShaderBuilder* builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000376 virtual void emitVS(SkString* out) const {}
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000377 virtual void emitFuncs(GrGLShaderBuilder* builder) {}
bsalomon@google.com032b2212012-07-16 13:36:18 +0000378 virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
379 SkString* out,
380 const char* z) const = 0;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000381 virtual void emitLightColor(GrGLShaderBuilder*,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000382 const char *surfaceToLight) const;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000383 virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000384
385private:
386 typedef SkRefCnt INHERITED;
387
388protected:
bsalomon@google.com032b2212012-07-16 13:36:18 +0000389 UniformHandle fColorUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000390};
391
392///////////////////////////////////////////////////////////////////////////////
393
394class GrGLDistantLight : public GrGLLight {
395public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000396 virtual ~GrGLDistantLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000397 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000398 virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000399 virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
400 SkString* out,
401 const char* z) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000402private:
403 typedef GrGLLight INHERITED;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000404 UniformHandle fDirectionUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000405};
406
407///////////////////////////////////////////////////////////////////////////////
408
409class GrGLPointLight : public GrGLLight {
410public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000411 virtual ~GrGLPointLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000412 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000413 virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000414 virtual void emitVS(SkString* out) const SK_OVERRIDE;
415 virtual void emitSurfaceToLight(const GrGLShaderBuilder*,
416 SkString* out,
417 const char* z) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000418private:
419 typedef GrGLLight INHERITED;
420 SkPoint3 fLocation;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000421 UniformHandle fLocationUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000422};
423
424///////////////////////////////////////////////////////////////////////////////
425
426class GrGLSpotLight : public GrGLLight {
427public:
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000428 virtual ~GrGLSpotLight() {}
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000429 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000430 virtual void setData(const GrGLUniformManager&, const GrRenderTarget* rt, const SkLight* light) const SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000431 virtual void emitVS(SkString* out) const SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000432 virtual void emitFuncs(GrGLShaderBuilder* builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +0000433 virtual void emitSurfaceToLight(const GrGLShaderBuilder* builder,
434 SkString* out,
435 const char* z) const SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000436 virtual void emitLightColor(GrGLShaderBuilder*,
bsalomon@google.com032b2212012-07-16 13:36:18 +0000437 const char *surfaceToLight) const SK_OVERRIDE;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000438
439private:
440 typedef GrGLLight INHERITED;
441
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000442 SkString fLightColorFunc;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000443 UniformHandle fLocationUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000444 UniformHandle fExponentUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000445 UniformHandle fCosOuterConeAngleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000446 UniformHandle fCosInnerConeAngleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000447 UniformHandle fConeScaleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000448 UniformHandle fSUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000449};
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000450#else
451
452class GrGLLight;
453
454#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000455
456};
457
458///////////////////////////////////////////////////////////////////////////////
459
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000460class SkLight : public SkFlattenable {
461public:
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000462 SK_DECLARE_INST_COUNT(SkLight)
463
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000464 enum LightType {
465 kDistant_LightType,
466 kPoint_LightType,
467 kSpot_LightType,
468 };
469 virtual LightType type() const = 0;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000470 const SkPoint3& color() const { return fColor; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000471 virtual GrGLLight* createGLLight() const = 0;
472 virtual bool isEqual(const SkLight& other) const {
473 return fColor == other.fColor;
474 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000475
djsollen@google.com08337772012-06-26 14:33:13 +0000476protected:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000477 SkLight(SkColor color)
478 : fColor(SkIntToScalar(SkColorGetR(color)),
479 SkIntToScalar(SkColorGetG(color)),
480 SkIntToScalar(SkColorGetB(color))) {}
481 SkLight(SkFlattenableReadBuffer& buffer)
482 : INHERITED(buffer) {
483 fColor = readPoint3(buffer);
484 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000485 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
djsollen@google.com08337772012-06-26 14:33:13 +0000486 INHERITED::flatten(buffer);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000487 writePoint3(fColor, buffer);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000488 }
djsollen@google.com08337772012-06-26 14:33:13 +0000489
490private:
491 typedef SkFlattenable INHERITED;
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000492 SkPoint3 fColor;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000493};
494
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000495SK_DEFINE_INST_COUNT(SkLight)
496
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000497///////////////////////////////////////////////////////////////////////////////
498
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000499class SkDistantLight : public SkLight {
500public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000501 SkDistantLight(const SkPoint3& direction, SkColor color)
502 : INHERITED(color), fDirection(direction) {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000503 }
djsollen@google.com08337772012-06-26 14:33:13 +0000504
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000505 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
506 return fDirection;
507 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000508 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000509 virtual LightType type() const { return kDistant_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000510 const SkPoint3& direction() const { return fDirection; }
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000511 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
512#if SK_SUPPORT_GPU
513 return SkNEW(GrGLDistantLight);
514#else
515 SkDEBUGFAIL("Should not call in GPU-less build");
516 return NULL;
517#endif
518 }
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000519 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
520 if (other.type() != kDistant_LightType) {
521 return false;
522 }
523
524 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
525 return INHERITED::isEqual(other) &&
526 fDirection == o.fDirection;
527 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000528
529 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDistantLight)
530
djsollen@google.com08337772012-06-26 14:33:13 +0000531protected:
532 SkDistantLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
533 fDirection = readPoint3(buffer);
534 }
535 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
536 INHERITED::flatten(buffer);
537 writePoint3(fDirection, buffer);
538 }
539
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000540private:
djsollen@google.com08337772012-06-26 14:33:13 +0000541 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000542 SkPoint3 fDirection;
543};
544
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000545///////////////////////////////////////////////////////////////////////////////
546
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000547class SkPointLight : public SkLight {
548public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000549 SkPointLight(const SkPoint3& location, SkColor color)
550 : INHERITED(color), fLocation(location) {}
djsollen@google.com08337772012-06-26 14:33:13 +0000551
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000552 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
553 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
554 fLocation.fY - SkIntToScalar(y),
555 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
556 direction.normalize();
557 return direction;
558 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000559 SkPoint3 lightColor(const SkPoint3&) const { return color(); }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000560 virtual LightType type() const { return kPoint_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000561 const SkPoint3& location() const { return fLocation; }
562 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000563#if SK_SUPPORT_GPU
tomhudson@google.com300f5622012-07-20 14:15:22 +0000564 return SkNEW(GrGLPointLight);
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000565#else
566 SkDEBUGFAIL("Should not call in GPU-less build");
567 return NULL;
568#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000569 }
senorblanco@chromium.org6730cbb2012-07-11 16:35:00 +0000570 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000571 if (other.type() != kPoint_LightType) {
572 return false;
573 }
574 const SkPointLight& o = static_cast<const SkPointLight&>(other);
575 return INHERITED::isEqual(other) &&
576 fLocation == o.fLocation;
577 }
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000578
579 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPointLight)
580
djsollen@google.com08337772012-06-26 14:33:13 +0000581protected:
582 SkPointLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
583 fLocation = readPoint3(buffer);
584 }
585 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
586 INHERITED::flatten(buffer);
587 writePoint3(fLocation, buffer);
588 }
589
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000590private:
djsollen@google.com08337772012-06-26 14:33:13 +0000591 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000592 SkPoint3 fLocation;
593};
594
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000595///////////////////////////////////////////////////////////////////////////////
596
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000597class SkSpotLight : public SkLight {
598public:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000599 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
600 : INHERITED(color),
601 fLocation(location),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000602 fTarget(target),
603 fSpecularExponent(specularExponent)
604 {
605 fS = target - location;
606 fS.normalize();
607 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
608 const SkScalar antiAliasThreshold = SkFloatToScalar(0.016f);
609 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
610 fConeScale = SkScalarInvert(antiAliasThreshold);
611 }
djsollen@google.com08337772012-06-26 14:33:13 +0000612
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000613 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
614 SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
615 fLocation.fY - SkIntToScalar(y),
616 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
617 direction.normalize();
618 return direction;
619 };
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000620 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000621 SkScalar cosAngle = -surfaceToLight.dot(fS);
622 if (cosAngle < fCosOuterConeAngle) {
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000623 return SkPoint3(0, 0, 0);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000624 }
625 SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent);
626 if (cosAngle < fCosInnerConeAngle) {
627 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000628 return color() * SkScalarMul(scale, fConeScale);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000629 }
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000630 return color() * scale;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000631 }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000632 virtual GrGLLight* createGLLight() const SK_OVERRIDE {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000633#if SK_SUPPORT_GPU
tomhudson@google.com300f5622012-07-20 14:15:22 +0000634 return SkNEW(GrGLSpotLight);
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000635#else
636 SkDEBUGFAIL("Should not call in GPU-less build");
637 return NULL;
638#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000639 }
djsollen@google.com08337772012-06-26 14:33:13 +0000640 virtual LightType type() const { return kSpot_LightType; }
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000641 const SkPoint3& location() const { return fLocation; }
642 const SkPoint3& target() const { return fTarget; }
643 SkScalar specularExponent() const { return fSpecularExponent; }
644 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
645 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
646 SkScalar coneScale() const { return fConeScale; }
senorblanco@chromium.orgeb311842012-07-11 20:49:26 +0000647 const SkPoint3& s() const { return fS; }
djsollen@google.com08337772012-06-26 14:33:13 +0000648
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000649 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpotLight)
650
djsollen@google.com08337772012-06-26 14:33:13 +0000651protected:
652 SkSpotLight(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
653 fLocation = readPoint3(buffer);
654 fTarget = readPoint3(buffer);
655 fSpecularExponent = buffer.readScalar();
656 fCosOuterConeAngle = buffer.readScalar();
657 fCosInnerConeAngle = buffer.readScalar();
658 fConeScale = buffer.readScalar();
659 fS = readPoint3(buffer);
660 }
661 virtual void flatten(SkFlattenableWriteBuffer& buffer) const {
662 INHERITED::flatten(buffer);
663 writePoint3(fLocation, buffer);
664 writePoint3(fTarget, buffer);
665 buffer.writeScalar(fSpecularExponent);
666 buffer.writeScalar(fCosOuterConeAngle);
667 buffer.writeScalar(fCosInnerConeAngle);
668 buffer.writeScalar(fConeScale);
669 writePoint3(fS, buffer);
670 }
671
senorblanco@chromium.orgbd9fad62012-07-11 16:25:37 +0000672 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000673 if (other.type() != kSpot_LightType) {
674 return false;
675 }
676
677 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
678 return INHERITED::isEqual(other) &&
679 fLocation == o.fLocation &&
680 fTarget == o.fTarget &&
681 fSpecularExponent == o.fSpecularExponent &&
682 fCosOuterConeAngle == o.fCosOuterConeAngle;
683 }
684
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000685private:
djsollen@google.com08337772012-06-26 14:33:13 +0000686 typedef SkLight INHERITED;
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000687 SkPoint3 fLocation;
688 SkPoint3 fTarget;
689 SkScalar fSpecularExponent;
690 SkScalar fCosOuterConeAngle;
691 SkScalar fCosInnerConeAngle;
692 SkScalar fConeScale;
693 SkPoint3 fS;
694};
695
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000696///////////////////////////////////////////////////////////////////////////////
697
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000698SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale)
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000699 : fLight(light),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000700 fSurfaceScale(SkScalarDiv(surfaceScale, SkIntToScalar(255)))
701{
702 SkASSERT(fLight);
reed@google.com51f38662012-06-27 14:24:29 +0000703 // our caller knows that we take ownership of the light, so we don't
704 // need to call ref() here.
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000705}
706
707SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000708 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000709 SkScalar kd) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000710 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
711 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)), surfaceScale, kd));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000712}
713
714SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000715 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000716 SkScalar kd) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000717 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
718 (SkNEW_ARGS(SkPointLight, (location, lightColor)), surfaceScale, kd));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000719}
720
721SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000722 const SkPoint3& location, const SkPoint3& target,
723 SkScalar specularExponent, SkScalar cutoffAngle,
724 SkColor lightColor, SkScalar surfaceScale, SkScalar kd) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000725 return SkNEW_ARGS(SkDiffuseLightingImageFilter,
726 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, cutoffAngle, lightColor)),
727 surfaceScale, kd));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000728}
729
730SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000731 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000732 SkScalar ks, SkScalar shininess) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000733 return SkNEW_ARGS(SkSpecularLightingImageFilter,
tomhudson@google.com300f5622012-07-20 14:15:22 +0000734 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)), surfaceScale, ks, shininess));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000735}
736
737SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000738 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
739 SkScalar ks, SkScalar shininess) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000740 return SkNEW_ARGS(SkSpecularLightingImageFilter,
741 (SkNEW_ARGS(SkPointLight, (location, lightColor)), surfaceScale, ks, shininess));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000742}
743
744SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000745 const SkPoint3& location, const SkPoint3& target,
746 SkScalar specularExponent, SkScalar cutoffAngle,
747 SkColor lightColor, SkScalar surfaceScale,
748 SkScalar ks, SkScalar shininess) {
tomhudson@google.com300f5622012-07-20 14:15:22 +0000749 return SkNEW_ARGS(SkSpecularLightingImageFilter,
750 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, cutoffAngle, lightColor)),
751 surfaceScale, ks, shininess));
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000752}
753
754SkLightingImageFilter::~SkLightingImageFilter() {
755 fLight->unref();
756}
757
758SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer)
759 : INHERITED(buffer)
760{
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000761 fLight = buffer.readFlattenableT<SkLight>();
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000762 fSurfaceScale = buffer.readScalar();
763}
764
765void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
766 this->INHERITED::flatten(buffer);
djsollen@google.com08337772012-06-26 14:33:13 +0000767 buffer.writeFlattenable(fLight);
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000768 buffer.writeScalar(fSurfaceScale);
769}
770
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000771///////////////////////////////////////////////////////////////////////////////
772
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000773SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd)
774 : SkLightingImageFilter(light, surfaceScale),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000775 fKD(kd)
776{
777}
778
779SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer)
780 : INHERITED(buffer)
781{
782 fKD = buffer.readScalar();
783}
784
785void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
786 this->INHERITED::flatten(buffer);
787 buffer.writeScalar(fKD);
788}
789
790bool SkDiffuseLightingImageFilter::onFilterImage(Proxy*,
791 const SkBitmap& src,
792 const SkMatrix&,
793 SkBitmap* dst,
794 SkIPoint*) {
795 if (src.config() != SkBitmap::kARGB_8888_Config) {
796 return false;
797 }
798 SkAutoLockPixels alp(src);
799 if (!src.getPixels()) {
800 return false;
801 }
802 if (src.width() < 2 || src.height() < 2) {
803 return false;
804 }
805 dst->setConfig(src.config(), src.width(), src.height());
806 dst->allocPixels();
807
808 DiffuseLightingType lightingType(fKD);
809 switch (light()->type()) {
810 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000811 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000812 break;
813 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000814 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000815 break;
816 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000817 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000818 break;
819 }
820 return true;
821}
822
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000823bool SkDiffuseLightingImageFilter::asNewCustomStage(GrCustomStage** stage,
824 GrTexture* texture) const {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000825#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000826 if (stage) {
827 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
tomhudson@google.com300f5622012-07-20 14:15:22 +0000828 *stage = SkNEW_ARGS(GrDiffuseLightingEffect, (texture, light(), scale, kd()));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000829 }
830 return true;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000831#else
832 SkDEBUGFAIL("Should not call in GPU-less build");
833 return false;
834#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000835}
836
837///////////////////////////////////////////////////////////////////////////////
838
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000839SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess)
840 : SkLightingImageFilter(light, surfaceScale),
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000841 fKS(ks),
842 fShininess(shininess)
843{
844}
845
846SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkFlattenableReadBuffer& buffer)
847 : INHERITED(buffer)
848{
849 fKS = buffer.readScalar();
850 fShininess = buffer.readScalar();
851}
852
853void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
854 this->INHERITED::flatten(buffer);
855 buffer.writeScalar(fKS);
856 buffer.writeScalar(fShininess);
857}
858
859bool SkSpecularLightingImageFilter::onFilterImage(Proxy*,
860 const SkBitmap& src,
861 const SkMatrix&,
862 SkBitmap* dst,
863 SkIPoint*) {
864 if (src.config() != SkBitmap::kARGB_8888_Config) {
865 return false;
866 }
867 SkAutoLockPixels alp(src);
868 if (!src.getPixels()) {
869 return false;
870 }
871 if (src.width() < 2 || src.height() < 2) {
872 return false;
873 }
874 dst->setConfig(src.config(), src.width(), src.height());
875 dst->allocPixels();
876
877 SpecularLightingType lightingType(fKS, fShininess);
878 switch (light()->type()) {
879 case SkLight::kDistant_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000880 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000881 break;
882 case SkLight::kPoint_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000883 lightBitmap<SpecularLightingType, SkPointLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000884 break;
885 case SkLight::kSpot_LightType:
senorblanco@chromium.orgbdb1ec42012-07-09 14:29:51 +0000886 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, light(), src, dst, surfaceScale());
senorblanco@chromium.orgf49b4292012-06-22 21:01:23 +0000887 break;
888 }
889 return true;
890}
891
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000892bool SkSpecularLightingImageFilter::asNewCustomStage(GrCustomStage** stage,
893 GrTexture* texture) const {
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000894#if SK_SUPPORT_GPU
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000895 if (stage) {
896 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
tomhudson@google.com300f5622012-07-20 14:15:22 +0000897 *stage = SkNEW_ARGS(GrSpecularLightingEffect, (texture, light(), scale, ks(), shininess()));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000898 }
899 return true;
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000900#else
901 SkDEBUGFAIL("Should not call in GPU-less build");
902 return false;
903#endif
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000904}
905
906///////////////////////////////////////////////////////////////////////////////
907
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +0000908#if SK_SUPPORT_GPU
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000909
910namespace {
911SkPoint3 random_point3(SkRandom* random) {
912 return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
913 SkScalarToFloat(random->nextSScalar1()),
914 SkScalarToFloat(random->nextSScalar1()));
915}
916
917SkLight* create_random_light(SkRandom* random) {
918 int type = random->nextULessThan(3);
919 switch (type) {
920 case 0: {
921 return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU()));
922 }
923 case 1: {
924 return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU()));
925 }
926 case 2: {
927 return SkNEW_ARGS(SkSpotLight, (random_point3(random),
928 random_point3(random),
929 random->nextUScalar1(),
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000930 random->nextUScalar1(),
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000931 random->nextU()));
932 }
933 default:
934 GrCrash();
935 return NULL;
936 }
937}
938
939}
940
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000941class GrGLLightingEffect : public GrGLProgramStage {
942public:
943 GrGLLightingEffect(const GrProgramStageFactory& factory,
944 const GrCustomStage& stage);
945 virtual ~GrGLLightingEffect();
946
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000947 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000948 virtual void emitVS(GrGLShaderBuilder* builder,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000949 const char* vertexCoords) SK_OVERRIDE;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000950 virtual void emitFS(GrGLShaderBuilder* builder,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000951 const char* outputColor,
952 const char* inputColor,
953 const char* samplerName) SK_OVERRIDE;
954
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000955 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000956
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000957 static inline StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000958
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000959 virtual void setData(const GrGLUniformManager&,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000960 const GrCustomStage&,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +0000961 const GrRenderTarget*,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000962 int stageNum) SK_OVERRIDE;
963
964private:
965 typedef GrGLProgramStage INHERITED;
966
bsalomon@google.com032b2212012-07-16 13:36:18 +0000967 UniformHandle fImageIncrementUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000968 UniformHandle fSurfaceScaleUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +0000969 GrGLLight* fLight;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000970};
971
972///////////////////////////////////////////////////////////////////////////////
973
974class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
975public:
976 GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
977 const GrCustomStage& stage);
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000978 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000979 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000980 virtual void setData(const GrGLUniformManager&,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000981 const GrCustomStage&,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +0000982 const GrRenderTarget*,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000983 int stageNum) SK_OVERRIDE;
984
985private:
986 typedef GrGLLightingEffect INHERITED;
987
bsalomon@google.com032b2212012-07-16 13:36:18 +0000988 UniformHandle fKDUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +0000989};
990
991///////////////////////////////////////////////////////////////////////////////
992
993class GrGLSpecularLightingEffect : public GrGLLightingEffect {
994public:
995 GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
996 const GrCustomStage& stage);
bsalomon@google.com777c3aa2012-07-25 20:58:20 +0000997 virtual void setupVariables(GrGLShaderBuilder* builder) SK_OVERRIDE;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +0000998 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +0000999 virtual void setData(const GrGLUniformManager&,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001000 const GrCustomStage&,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001001 const GrRenderTarget*,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001002 int stageNum) SK_OVERRIDE;
1003
1004private:
1005 typedef GrGLLightingEffect INHERITED;
1006
bsalomon@google.com032b2212012-07-16 13:36:18 +00001007 UniformHandle fKSUni;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001008 UniformHandle fShininessUni;
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001009};
1010
1011///////////////////////////////////////////////////////////////////////////////
1012
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001013GrLightingEffect::GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale)
1014 : GrSingleTextureEffect(texture)
1015 , fLight(light)
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001016 , fSurfaceScale(surfaceScale) {
1017 fLight->ref();
1018}
1019
1020GrLightingEffect::~GrLightingEffect() {
1021 fLight->unref();
1022}
1023
1024bool GrLightingEffect::isEqual(const GrCustomStage& sBase) const {
1025 const GrLightingEffect& s =
1026 static_cast<const GrLightingEffect&>(sBase);
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001027 return INHERITED::isEqual(sBase) &&
1028 fLight->isEqual(*s.fLight) &&
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001029 fSurfaceScale == s.fSurfaceScale;
1030}
1031
1032///////////////////////////////////////////////////////////////////////////////
1033
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001034GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar kd)
1035 : INHERITED(texture, light, surfaceScale), fKD(kd) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001036}
1037
1038const GrProgramStageFactory& GrDiffuseLightingEffect::getFactory() const {
1039 return GrTProgramStageFactory<GrDiffuseLightingEffect>::getInstance();
1040}
1041
1042bool GrDiffuseLightingEffect::isEqual(const GrCustomStage& sBase) const {
1043 const GrDiffuseLightingEffect& s =
1044 static_cast<const GrDiffuseLightingEffect&>(sBase);
1045 return INHERITED::isEqual(sBase) &&
1046 this->kd() == s.kd();
1047}
1048
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001049GR_DEFINE_CUSTOM_STAGE_TEST(GrDiffuseLightingEffect);
1050
1051GrCustomStage* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
1052 GrContext* context,
1053 GrTexture* textures[]) {
1054 SkScalar surfaceScale = random->nextSScalar1();
1055 SkScalar kd = random->nextUScalar1();
1056 SkAutoTUnref<SkLight> light(create_random_light(random));
1057 return SkNEW_ARGS(GrDiffuseLightingEffect, (textures[GrCustomStageUnitTest::kAlphaTextureIdx],
1058 light, surfaceScale, kd));
1059}
1060
1061
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001062///////////////////////////////////////////////////////////////////////////////
1063
1064GrGLLightingEffect::GrGLLightingEffect(const GrProgramStageFactory& factory,
1065 const GrCustomStage& stage)
1066 : GrGLProgramStage(factory)
bsalomon@google.com032b2212012-07-16 13:36:18 +00001067 , fImageIncrementUni(kInvalidUniformHandle)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001068 , fSurfaceScaleUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001069 const GrLightingEffect& m = static_cast<const GrLightingEffect&>(stage);
1070 fLight = m.light()->createGLLight();
1071}
1072
1073GrGLLightingEffect::~GrGLLightingEffect() {
1074 delete fLight;
1075}
1076
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001077void GrGLLightingEffect::setupVariables(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001078 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1079 kVec2f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001080 "ImageIncrement");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001081 fSurfaceScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
1082 kFloat_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001083 "SurfaceScale");
1084 fLight->setupVariables(builder);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001085}
1086
bsalomon@google.com032b2212012-07-16 13:36:18 +00001087void GrGLLightingEffect::emitVS(GrGLShaderBuilder* builder,
1088 const char* vertexCoords) {
1089 fLight->emitVS(&builder->fVSCode);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001090}
1091
bsalomon@google.com032b2212012-07-16 13:36:18 +00001092void GrGLLightingEffect::emitFS(GrGLShaderBuilder* builder,
1093 const char* outputColor,
1094 const char* inputColor,
1095 const char* samplerName) {
1096 SkString* code = &builder->fFSCode;
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001097 fLight->emitFuncs(builder);
1098 SkString lightFunc;
1099 this->emitLightFunc(builder, &lightFunc);
1100 static const GrGLShaderVar gSobelArgs[] = {
1101 GrGLShaderVar("a", kFloat_GrSLType),
1102 GrGLShaderVar("b", kFloat_GrSLType),
1103 GrGLShaderVar("c", kFloat_GrSLType),
1104 GrGLShaderVar("d", kFloat_GrSLType),
1105 GrGLShaderVar("e", kFloat_GrSLType),
1106 GrGLShaderVar("f", kFloat_GrSLType),
1107 GrGLShaderVar("scale", kFloat_GrSLType),
1108 };
1109 SkString sobelFuncName;
1110 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1111 kFloat_GrSLType,
1112 "sobel",
1113 SK_ARRAY_COUNT(gSobelArgs),
1114 gSobelArgs,
1115 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1116 &sobelFuncName);
1117 static const GrGLShaderVar gPointToNormalArgs[] = {
1118 GrGLShaderVar("x", kFloat_GrSLType),
1119 GrGLShaderVar("y", kFloat_GrSLType),
1120 GrGLShaderVar("scale", kFloat_GrSLType),
1121 };
1122 SkString pointToNormalName;
1123 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1124 kVec3f_GrSLType,
1125 "pointToNormal",
1126 SK_ARRAY_COUNT(gPointToNormalArgs),
1127 gPointToNormalArgs,
1128 "\treturn normalize(vec3(-x * scale, -y * scale, 1));\n",
1129 &pointToNormalName);
1130
1131 static const GrGLShaderVar gInteriorNormalArgs[] = {
1132 GrGLShaderVar("m", kFloat_GrSLType, 9),
1133 GrGLShaderVar("surfaceScale", kFloat_GrSLType),
1134 };
1135 SkString interiorNormalBody;
1136 interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n"
1137 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n"
1138 "\t surfaceScale);\n",
1139 pointToNormalName.c_str(),
1140 sobelFuncName.c_str(),
1141 sobelFuncName.c_str());
1142 SkString interiorNormalName;
1143 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1144 kVec3f_GrSLType,
1145 "interiorNormal",
1146 SK_ARRAY_COUNT(gInteriorNormalArgs),
1147 gInteriorNormalArgs,
1148 interiorNormalBody.c_str(),
1149 &interiorNormalName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001150
bsalomon@google.com34bcb9f2012-08-28 18:20:18 +00001151 code->appendf("\t\tvec2 coord = %s;\n", builder->defaultTexCoordsName());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001152 code->appendf("\t\tfloat m[9];\n");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001153
1154 const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
1155 const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
1156
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001157 int index = 0;
1158 for (int dy = -1; dy <= 1; dy++) {
1159 for (int dx = -1; dx <= 1; dx++) {
1160 SkString texCoords;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001161 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001162 code->appendf("\t\tm[%d] = ", index++);
bsalomon@google.com868a8e72012-08-30 19:11:34 +00001163 builder->appendTextureLookup(code, samplerName, texCoords.c_str());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001164 code->appendf(".a;\n");
1165 }
1166 }
1167 code->appendf("\t\tvec3 surfaceToLight = ");
1168 SkString arg;
bsalomon@google.com032b2212012-07-16 13:36:18 +00001169 arg.appendf("%s * m[4]", surfScale);
1170 fLight->emitSurfaceToLight(builder, code, arg.c_str());
bsalomon@google.com868a8e72012-08-30 19:11:34 +00001171 code->append(";\n");
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001172 code->appendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1173 outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale);
1174 fLight->emitLightColor(builder, "surfaceToLight");
bsalomon@google.com868a8e72012-08-30 19:11:34 +00001175 code->append(");\n");
1176 GrGLSLMulVarBy4f(code, 2, outputColor, inputColor);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001177}
1178
twiz@google.coma5e65ec2012-08-02 15:15:16 +00001179GrGLProgramStage::StageKey GrGLLightingEffect::GenKey(const GrCustomStage& s,
1180 const GrGLCaps& caps) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001181 return static_cast<const GrLightingEffect&>(s).light()->type();
1182}
1183
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001184void GrGLLightingEffect::setData(const GrGLUniformManager& uman,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001185 const GrCustomStage& data,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001186 const GrRenderTarget* rt,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001187 int stageNum) {
1188 const GrLightingEffect& effect =
1189 static_cast<const GrLightingEffect&>(data);
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001190 GrGLTexture* texture = static_cast<GrGLTexture*>(data.texture(0));
1191 float ySign = texture->orientation() == GrGLTexture::kTopDown_Orientation ? -1.0f : 1.0f;
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001192 uman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1193 uman.set1f(fSurfaceScaleUni, effect.surfaceScale());
1194 fLight->setData(uman, rt, effect.light());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001195}
1196
1197///////////////////////////////////////////////////////////////////////////////
1198
1199///////////////////////////////////////////////////////////////////////////////
1200
1201GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrProgramStageFactory& factory,
1202 const GrCustomStage& stage)
1203 : INHERITED(factory, stage)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001204 , fKDUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001205}
1206
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001207void GrGLDiffuseLightingEffect::setupVariables(GrGLShaderBuilder* builder) {
1208 INHERITED::setupVariables(builder);
1209 fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kFloat_GrSLType, "KD");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001210}
1211
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001212void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001213 const char* kd = builder->getUniformCStr(fKDUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001214 static const GrGLShaderVar gLightArgs[] = {
1215 GrGLShaderVar("normal", kVec3f_GrSLType),
1216 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1217 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1218 };
1219 SkString lightBody;
1220 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1221 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1222 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1223 kVec4f_GrSLType,
1224 "light",
1225 SK_ARRAY_COUNT(gLightArgs),
1226 gLightArgs,
1227 lightBody.c_str(),
1228 funcName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001229}
1230
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001231void GrGLDiffuseLightingEffect::setData(const GrGLUniformManager& uman,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001232 const GrCustomStage& data,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001233 const GrRenderTarget* rt,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001234 int stageNum) {
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001235 INHERITED::setData(uman, data, rt, stageNum);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001236 const GrDiffuseLightingEffect& effect =
1237 static_cast<const GrDiffuseLightingEffect&>(data);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001238 uman.set1f(fKDUni, effect.kd());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001239}
1240
1241///////////////////////////////////////////////////////////////////////////////
1242
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001243GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess)
1244 : INHERITED(texture, light, surfaceScale),
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001245 fKS(ks),
1246 fShininess(shininess) {
1247}
1248
1249const GrProgramStageFactory& GrSpecularLightingEffect::getFactory() const {
1250 return GrTProgramStageFactory<GrSpecularLightingEffect>::getInstance();
1251}
1252
1253bool GrSpecularLightingEffect::isEqual(const GrCustomStage& sBase) const {
1254 const GrSpecularLightingEffect& s =
1255 static_cast<const GrSpecularLightingEffect&>(sBase);
1256 return INHERITED::isEqual(sBase) &&
1257 this->ks() == s.ks() &&
1258 this->shininess() == s.shininess();
1259}
1260
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001261GR_DEFINE_CUSTOM_STAGE_TEST(GrSpecularLightingEffect);
1262
1263GrCustomStage* GrSpecularLightingEffect::TestCreate(SkRandom* random,
1264 GrContext* context,
1265 GrTexture* textures[]) {
1266 SkScalar surfaceScale = random->nextSScalar1();
1267 SkScalar ks = random->nextUScalar1();
1268 SkScalar shininess = random->nextUScalar1();
1269 SkAutoTUnref<SkLight> light(create_random_light(random));
1270 return SkNEW_ARGS(GrSpecularLightingEffect, (textures[GrCustomStageUnitTest::kAlphaTextureIdx],
1271 light, surfaceScale, ks, shininess));
1272}
1273
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001274///////////////////////////////////////////////////////////////////////////////
1275
1276GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrProgramStageFactory& factory,
1277 const GrCustomStage& stage)
1278 : GrGLLightingEffect(factory, stage)
bsalomon@google.com032b2212012-07-16 13:36:18 +00001279 , fKSUni(kInvalidUniformHandle)
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001280 , fShininessUni(kInvalidUniformHandle) {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001281}
1282
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001283void GrGLSpecularLightingEffect::setupVariables(GrGLShaderBuilder* builder) {
1284 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001285 fKSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001286 kFloat_GrSLType, "KS");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001287 fShininessUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001288 kFloat_GrSLType, "Shininess");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001289}
1290
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001291void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001292 const char* ks = builder->getUniformCStr(fKSUni);
1293 const char* shininess = builder->getUniformCStr(fShininessUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001294
1295 static const GrGLShaderVar gLightArgs[] = {
1296 GrGLShaderVar("normal", kVec3f_GrSLType),
1297 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1298 GrGLShaderVar("lightColor", kVec3f_GrSLType)
1299 };
1300 SkString lightBody;
1301 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1302 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
1303 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1304 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1305 kVec4f_GrSLType,
1306 "light",
1307 SK_ARRAY_COUNT(gLightArgs),
1308 gLightArgs,
1309 lightBody.c_str(),
1310 funcName);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001311}
1312
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001313void GrGLSpecularLightingEffect::setData(const GrGLUniformManager& uman,
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001314 const GrCustomStage& data,
senorblanco@chromium.orgf4770d72012-07-13 18:25:06 +00001315 const GrRenderTarget* rt,
tomhudson@google.comd0c1a062012-07-12 17:23:52 +00001316 int stageNum) {
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001317 INHERITED::setData(uman, data, rt, stageNum);
1318 const GrSpecularLightingEffect& effect = static_cast<const GrSpecularLightingEffect&>(data);
1319 uman.set1f(fKSUni, effect.ks());
1320 uman.set1f(fShininessUni, effect.shininess());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001321}
1322
1323///////////////////////////////////////////////////////////////////////////////
1324
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001325void GrGLLight::emitLightColor(GrGLShaderBuilder* builder,
bsalomon@google.com032b2212012-07-16 13:36:18 +00001326 const char *surfaceToLight) const {
1327 const char* color = builder->getUniformCStr(fColorUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001328 builder->fFSCode.append(color);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001329}
1330
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001331void GrGLLight::setupVariables(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001332 fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001333 kVec3f_GrSLType, "LightColor");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001334}
1335
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001336void GrGLLight::setData(const GrGLUniformManager& uman,
1337 const GrRenderTarget* rt,
1338 const SkLight* light) const {
1339 setUniformPoint3(uman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001340}
1341
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001342///////////////////////////////////////////////////////////////////////////////
1343
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001344void GrGLDistantLight::setupVariables(GrGLShaderBuilder* builder) {
1345 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001346 fDirectionUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001347 "LightDirection");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001348}
1349
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001350void GrGLDistantLight::setData(const GrGLUniformManager& uman,
1351 const GrRenderTarget* rt,
1352 const SkLight* light) const {
1353 INHERITED::setData(uman, rt, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001354 SkASSERT(light->type() == SkLight::kDistant_LightType);
1355 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001356 setUniformNormal3(uman, fDirectionUni, distantLight->direction());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001357}
1358
bsalomon@google.com032b2212012-07-16 13:36:18 +00001359void GrGLDistantLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
1360 SkString* out,
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001361 const char* z) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001362 const char* dir = builder->getUniformCStr(fDirectionUni);
1363 out->append(dir);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001364}
1365
1366///////////////////////////////////////////////////////////////////////////////
1367
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001368void GrGLPointLight::setupVariables(GrGLShaderBuilder* builder) {
1369 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001370 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kVec3f_GrSLType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001371 "LightLocation");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001372}
1373
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001374void GrGLPointLight::setData(const GrGLUniformManager& uman,
1375 const GrRenderTarget* rt,
1376 const SkLight* light) const {
1377 INHERITED::setData(uman, rt, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001378 SkASSERT(light->type() == SkLight::kPoint_LightType);
1379 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001380 setUniformPoint3FlipY(uman, fLocationUni, pointLight->location(), rt->height());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001381}
1382
bsalomon@google.com032b2212012-07-16 13:36:18 +00001383void GrGLPointLight::emitVS(SkString* out) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001384}
1385
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001386void GrGLPointLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
1387 SkString* out,
1388 const char* z) const {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001389 const char* loc = builder->getUniformCStr(fLocationUni);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001390 out->appendf("normalize(%s - vec3(gl_FragCoord.xy, %s))", loc, z);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001391}
1392
1393///////////////////////////////////////////////////////////////////////////////
1394
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001395void GrGLSpotLight::setupVariables(GrGLShaderBuilder* builder) {
1396 INHERITED::setupVariables(builder);
bsalomon@google.com032b2212012-07-16 13:36:18 +00001397 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001398 kVec3f_GrSLType, "LightLocation");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001399 fExponentUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001400 kFloat_GrSLType, "Exponent");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001401 fCosInnerConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001402 kFloat_GrSLType, "CosInnerConeAngle");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001403 fCosOuterConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001404 kFloat_GrSLType, "CosOuterConeAngle");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001405 fConeScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001406 kFloat_GrSLType, "ConeScale");
bsalomon@google.com032b2212012-07-16 13:36:18 +00001407 fSUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
bsalomon@google.com777c3aa2012-07-25 20:58:20 +00001408 kVec3f_GrSLType, "S");
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001409}
1410
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001411void GrGLSpotLight::setData(const GrGLUniformManager& uman,
1412 const GrRenderTarget* rt,
1413 const SkLight* light) const {
1414 INHERITED::setData(uman, rt, light);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001415 SkASSERT(light->type() == SkLight::kSpot_LightType);
1416 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
bsalomon@google.comdbbc4e22012-07-25 17:48:39 +00001417 setUniformPoint3FlipY(uman, fLocationUni, spotLight->location(), rt->height());
1418 uman.set1f(fExponentUni, spotLight->specularExponent());
1419 uman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
1420 uman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
1421 uman.set1f(fConeScaleUni, spotLight->coneScale());
1422 setUniformNormal3(uman, fSUni, spotLight->s());
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001423}
1424
bsalomon@google.com032b2212012-07-16 13:36:18 +00001425void GrGLSpotLight::emitVS(SkString* out) const {
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001426}
1427
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001428void GrGLSpotLight::emitFuncs(GrGLShaderBuilder* builder) {
bsalomon@google.com032b2212012-07-16 13:36:18 +00001429 const char* exponent = builder->getUniformCStr(fExponentUni);
1430 const char* cosInner = builder->getUniformCStr(fCosInnerConeAngleUni);
1431 const char* cosOuter = builder->getUniformCStr(fCosOuterConeAngleUni);
1432 const char* coneScale = builder->getUniformCStr(fConeScaleUni);
1433 const char* s = builder->getUniformCStr(fSUni);
1434 const char* color = builder->getUniformCStr(fColorUni);
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001435 static const GrGLShaderVar gLightColorArgs[] = {
1436 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType)
1437 };
1438 SkString lightColorBody;
1439 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
1440 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
1441 lightColorBody.appendf("\t\treturn vec3(0);\n");
1442 lightColorBody.appendf("\t}\n");
1443 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
1444 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
1445 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
1446 color, cosOuter, coneScale);
1447 lightColorBody.appendf("\t}\n");
1448 lightColorBody.appendf("\treturn %s;\n", color);
1449 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1450 kVec3f_GrSLType,
1451 "lightColor",
1452 SK_ARRAY_COUNT(gLightColorArgs),
1453 gLightColorArgs,
1454 lightColorBody.c_str(),
1455 &fLightColorFunc);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001456}
1457
bsalomon@google.com032b2212012-07-16 13:36:18 +00001458void GrGLSpotLight::emitSurfaceToLight(const GrGLShaderBuilder* builder,
1459 SkString* out,
1460 const char* z) const {
1461 const char* location= builder->getUniformCStr(fLocationUni);
1462 out->appendf("normalize(%s - vec3(gl_FragCoord.xy, %s))", location, z);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001463}
1464
bsalomon@google.coma1bf0ff2012-08-07 17:36:29 +00001465void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder,
1466 const char *surfaceToLight) const {
1467 builder->fFSCode.appendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
senorblanco@chromium.org894790d2012-07-11 16:01:22 +00001468}
1469
bsalomon@google.comcf8fb1f2012-08-02 14:03:32 +00001470#endif
1471
djsollen@google.com08337772012-06-26 14:33:13 +00001472SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
1473 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
1474 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
1475 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDistantLight)
1476 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPointLight)
1477 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpotLight)
1478SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END