1f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org/*
2f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org * Copyright 2012 The Android Open Source Project
3f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org *
4f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be
5f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org * found in the LICENSE file.
6f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org */
7f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
8f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org#include "SkLightingImageFilter.h"
9f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org#include "SkBitmap.h"
10f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org#include "SkColorPriv.h"
118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
15300f562dedd02df2f41de443c8b58ab2ceaed0f0tomhudson@google.com#include "SkTypes.h"
16cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
17cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
18d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com#include "effects/GrSingleTextureEffect.h"
19b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h"
2030ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h"
21b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessor.h"
22b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h"
23894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
24894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLDiffuseLightingEffect;
25894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLSpecularLightingEffect;
26f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
27dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com// For brevity
287510b224e52b9518a8ddf7418db0e9c258f79539kkinnunentypedef GrGLProgramDataManager::UniformHandle UniformHandle;
29cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
30032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
31f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgnamespace {
32f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
33f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgconst SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3));
34f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgconst SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3));
354b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.orgconst SkScalar gOneHalf = 0.5f;
364b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.orgconst SkScalar gOneQuarter = 0.25f;
37f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
38cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
39b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid setUniformPoint3(const GrGLProgramDataManager& pdman, UniformHandle uni,
40b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                      const SkPoint3& point) {
41b9119a6b563bf737e34d22f8bb96fc09a606c76fbsalomon@google.com    GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(GrGLfloat));
427510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set3fv(uni, 1, &point.fX);
43894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
44894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
45b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid setUniformNormal3(const GrGLProgramDataManager& pdman, UniformHandle uni,
46b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                       const SkPoint3& point) {
477510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformPoint3(pdman, uni, SkPoint3(point.fX, point.fY, point.fZ));
48f4770d7e841a34d74d7f76a33312f4c5624da831senorblanco@chromium.org}
49cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
50f4770d7e841a34d74d7f76a33312f4c5624da831senorblanco@chromium.org
51f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// Shift matrix components to the left, as we advance pixels to the right.
52f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline void shiftMatrixLeft(int m[9]) {
53f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[0] = m[1];
54f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[3] = m[4];
55f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[6] = m[7];
56f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[1] = m[2];
57f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[4] = m[5];
58f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[7] = m[8];
59f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
60f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
61f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgclass DiffuseLightingType {
62f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
63f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    DiffuseLightingType(SkScalar kd)
64f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        : fKD(kd) {}
65b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
66b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                    const SkPoint3& lightColor) const {
67f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
68f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
69f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 color(lightColor * colorScale);
70f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return SkPackARGB32(255,
71b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fX), 255),
72b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fY), 255),
73b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fZ), 255));
74f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
75f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
76f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fKD;
77f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
78f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
79f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgclass SpecularLightingType {
80f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
81f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SpecularLightingType(SkScalar ks, SkScalar shininess)
82f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        : fKS(ks), fShininess(shininess) {}
83b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
84b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                    const SkPoint3& lightColor) const {
85f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 halfDir(surfaceTolight);
86f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        halfDir.fZ += SK_Scalar1;        // eye position is always (0, 0, 1)
87f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        halfDir.normalize();
88f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkScalar colorScale = SkScalarMul(fKS,
89f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            SkScalarPow(normal.dot(halfDir), fShininess));
90f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
91f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 color(lightColor * colorScale);
92b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org        return SkPackARGB32(SkClampMax(SkScalarRoundToInt(color.maxComponent()), 255),
93b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fX), 255),
94b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fY), 255),
95b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fZ), 255));
96f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
97f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
98f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fKS;
99f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fShininess;
100f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
101f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
102f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
103f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
104f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
105f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
106f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
107f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 vector(SkScalarMul(-x, surfaceScale),
108f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                    SkScalarMul(-y, surfaceScale),
109f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                    SK_Scalar1);
110f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    vector.normalize();
111f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return vector;
112f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
113f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
114f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
115f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
116f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
117f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
118f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
119f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
120f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
121f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(   0,    0, m[3], m[5], m[6], m[8], gOneThird),
122f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
123f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
124f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
125f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
126f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
127f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(   0,    0, m[3], m[4], m[6], m[7], gTwoThirds),
128f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[3], m[6], m[4], m[7],    0,    0, gTwoThirds),
129f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
130f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
131f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
132f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
133f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
134f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(   0,    0, m[1], m[7], m[2], m[8], gOneThird),
135f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
136f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
137f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
138f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
139f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
140f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
141f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
142f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
143f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
144f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
145f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
146f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
147f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[0], m[6], m[1], m[7],    0,    0, gOneThird),
148f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
149f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
150f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
151f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
152f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[1], m[2], m[4], m[5],    0,    0, gTwoThirds),
153f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(   0,    0, m[1], m[4], m[2], m[5], gTwoThirds),
154f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
155f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
156f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
157f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
158f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[0], m[2], m[3], m[5],    0,    0, gOneThird),
159f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
160f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
161f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
162f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
163f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orginline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
164f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0,  0, gTwoThirds),
165f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[0], m[3], m[1], m[4], 0,  0, gTwoThirds),
166f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
167f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
168f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
169b0a8a377f832c59cee939ad721e1f87d378b7142joshualitttemplate <class LightingType, class LightType> void lightBitmap(
170b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        const LightingType& lightingType, const SkLight* light, const SkBitmap& src, SkBitmap* dst,
171b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        SkScalar surfaceScale, const SkIRect& bounds) {
1724e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height());
173f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    const LightType* l = static_cast<const LightType*>(light);
1744e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    int left = bounds.left(), right = bounds.right();
1754e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    int bottom = bounds.bottom();
1764e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    int y = bounds.top();
1774e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkPMColor* dptr = dst->getAddr32(0, 0);
178f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    {
1794e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        int x = left;
1804e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        const SkPMColor* row1 = src.getAddr32(x, y);
1814e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        const SkPMColor* row2 = src.getAddr32(x, y + 1);
182f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        int m[9];
183f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[4] = SkGetPackedA32(*row1++);
184f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[5] = SkGetPackedA32(*row1++);
185f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[7] = SkGetPackedA32(*row2++);
186f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[8] = SkGetPackedA32(*row2++);
187f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
188b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight,
189b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
1904e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        for (++x; x < right - 1; ++x)
191f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        {
192f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            shiftMatrixLeft(m);
193f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            m[5] = SkGetPackedA32(*row1++);
194f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            m[8] = SkGetPackedA32(*row2++);
1954e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org            surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
196b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight,
197b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         l->lightColor(surfaceToLight));
198f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        }
199f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        shiftMatrixLeft(m);
200f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
201b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight,
202b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
203f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
204f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
2054e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    for (++y; y < bottom - 1; ++y) {
2064e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        int x = left;
2074e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        const SkPMColor* row0 = src.getAddr32(x, y - 1);
2084e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        const SkPMColor* row1 = src.getAddr32(x, y);
2094e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        const SkPMColor* row2 = src.getAddr32(x, y + 1);
210f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        int m[9];
211f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[1] = SkGetPackedA32(*row0++);
212f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[2] = SkGetPackedA32(*row0++);
213f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[4] = SkGetPackedA32(*row1++);
214f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[5] = SkGetPackedA32(*row1++);
215f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[7] = SkGetPackedA32(*row2++);
216f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[8] = SkGetPackedA32(*row2++);
217f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
218b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight,
219b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
2204e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        for (++x; x < right - 1; ++x) {
221f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            shiftMatrixLeft(m);
222f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            m[2] = SkGetPackedA32(*row0++);
223f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            m[5] = SkGetPackedA32(*row1++);
224f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            m[8] = SkGetPackedA32(*row2++);
225f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
226b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight,
227b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         l->lightColor(surfaceToLight));
228f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        }
229f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        shiftMatrixLeft(m);
230f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
231b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight,
232b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
233f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
234f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
235f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    {
2364e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        int x = left;
2374e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        const SkPMColor* row0 = src.getAddr32(x, bottom - 2);
2384e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        const SkPMColor* row1 = src.getAddr32(x, bottom - 1);
239f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        int m[9];
240f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[1] = SkGetPackedA32(*row0++);
241f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[2] = SkGetPackedA32(*row0++);
242f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[4] = SkGetPackedA32(*row1++);
243f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        m[5] = SkGetPackedA32(*row1++);
244f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
245b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight,
246b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
2474e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        for (++x; x < right - 1; ++x)
248f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        {
249f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            shiftMatrixLeft(m);
250f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            m[2] = SkGetPackedA32(*row0++);
251f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            m[5] = SkGetPackedA32(*row1++);
252f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
253b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight,
254b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         l->lightColor(surfaceToLight));
255f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        }
256f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        shiftMatrixLeft(m);
257f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
258b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight,
259b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
260f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
261f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
262f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
2638b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkPoint3 readPoint3(SkReadBuffer& buffer) {
264f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 point;
265f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    point.fX = buffer.readScalar();
266f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    point.fY = buffer.readScalar();
267f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    point.fZ = buffer.readScalar();
268c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    buffer.validate(SkScalarIsFinite(point.fX) &&
269c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                    SkScalarIsFinite(point.fY) &&
270c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                    SkScalarIsFinite(point.fZ));
271f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return point;
272f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
273f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
2748b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
275f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    buffer.writeScalar(point.fX);
276f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    buffer.writeScalar(point.fY);
277f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    buffer.writeScalar(point.fZ);
278f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
279f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
280f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgclass SkDiffuseLightingImageFilter : public SkLightingImageFilter {
281f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
2829fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter*,
2835e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                 const CropRect*, uint32_t uniqueID = 0);
2849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
285f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
286bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkScalar kd() const { return fKD; }
287bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org
288f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprotected:
2899fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale,
2905e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                 SkScalar kd, SkImageFilter* input, const CropRect* cropRect,
2915e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                 uint32_t uniqueID);
2929fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
2938b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    explicit SkDiffuseLightingImageFilter(SkReadBuffer& buffer);
2949fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
2958b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
2964cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
297ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                               SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
2981aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org#if SK_SUPPORT_GPU
299b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
300b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     const SkIRect& bounds) const SK_OVERRIDE;
3011aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org#endif
302f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
303f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
3049fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    friend class SkLightingImageFilter;
305f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    typedef SkLightingImageFilter INHERITED;
306f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fKD;
307f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
308f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
309f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgclass SkSpecularLightingImageFilter : public SkLightingImageFilter {
310f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
3119fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale,
312b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                 SkScalar ks, SkScalar shininess, SkImageFilter*, const CropRect*,
313b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                 uint32_t uniqueID = 0);
3149fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
315f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
316f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
317894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar ks() const { return fKS; }
318894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar shininess() const { return fShininess; }
319894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
320f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprotected:
3219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks,
3225e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                  SkScalar shininess, SkImageFilter* input, const CropRect*,
3235e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                  uint32_t uniqueID);
3249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
3258b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    explicit SkSpecularLightingImageFilter(SkReadBuffer& buffer);
3269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
3278b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
3284cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
329ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                               SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
3301aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org#if SK_SUPPORT_GPU
331b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&,
332b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     const SkIRect& bounds) const SK_OVERRIDE;
3331aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org#endif
334f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
335f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
336f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fKS;
337f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fShininess;
3389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    friend class SkLightingImageFilter;
3399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    typedef SkLightingImageFilter INHERITED;
340f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
341f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
342cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
343894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
344d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.comclass GrLightingEffect : public GrSingleTextureEffect {
345894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
346fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, const SkMatrix& matrix);
347894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    virtual ~GrLightingEffect();
348894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
349894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkLight* light() const { return fLight; }
350894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar surfaceScale() const { return fSurfaceScale; }
351fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    const SkMatrix& filterMatrix() const { return fFilterMatrix; }
352371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com
353371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com    virtual void getConstantColorComponents(GrColor* color,
354371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com                                            uint32_t* validFlags) const SK_OVERRIDE {
355371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com        // lighting shaders are complicated. We just throw up our hands.
356371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com        *validFlags = 0;
357371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com    }
358371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com
35968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.comprotected:
360b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
36168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
362894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
363d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com    typedef GrSingleTextureEffect INHERITED;
364894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkLight* fLight;
365894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar fSurfaceScale;
366fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkMatrix fFilterMatrix;
367894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
368894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
369894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrDiffuseLightingEffect : public GrLightingEffect {
370894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
371b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static GrFragmentProcessor* Create(GrTexture* texture,
372b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       const SkLight* light,
373b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       SkScalar surfaceScale,
374b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       const SkMatrix& matrix,
375b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       SkScalar kd) {
37655fad7af61c21d502acb9891d631e8aa29e3628cbsalomon        return SkNEW_ARGS(GrDiffuseLightingEffect, (texture,
37755fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                    light,
37855fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                    surfaceScale,
37955fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                    matrix,
38055fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                    kd));
3810ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    }
382894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
383894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    static const char* Name() { return "DiffuseLighting"; }
384894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
385b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLDiffuseLightingEffect GLProcessor;
386894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
387b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
388894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar kd() const { return fKD; }
38968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
390894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
391b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
39268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
3930ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    GrDiffuseLightingEffect(GrTexture* texture,
3940ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                            const SkLight* light,
3950ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                            SkScalar surfaceScale,
396fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                            const SkMatrix& matrix,
3970ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                            SkScalar kd);
3980ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
399b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
400894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrLightingEffect INHERITED;
401894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar fKD;
402894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
403894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
404894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrSpecularLightingEffect : public GrLightingEffect {
405894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
406b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static GrFragmentProcessor* Create(GrTexture* texture,
407b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       const SkLight* light,
408b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       SkScalar surfaceScale,
409b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       const SkMatrix& matrix,
410b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       SkScalar ks,
411b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       SkScalar shininess) {
41255fad7af61c21d502acb9891d631e8aa29e3628cbsalomon        return SkNEW_ARGS(GrSpecularLightingEffect, (texture,
41355fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                     light,
41455fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                     surfaceScale,
41555fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                     matrix,
41655fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                     ks,
41755fad7af61c21d502acb9891d631e8aa29e3628cbsalomon                                                     shininess));
4180ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    }
419894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    static const char* Name() { return "SpecularLighting"; }
420894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
421b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLSpecularLightingEffect GLProcessor;
422894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
423b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
424894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar ks() const { return fKS; }
425894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar shininess() const { return fShininess; }
426894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
427894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
428b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
42968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
4300ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    GrSpecularLightingEffect(GrTexture* texture,
4310ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                             const SkLight* light,
4320ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                             SkScalar surfaceScale,
433fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                             const SkMatrix& matrix,
4340ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                             SkScalar ks,
4350ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                             SkScalar shininess);
4360ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
437b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
438894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrLightingEffect INHERITED;
439894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar fKS;
440894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar fShininess;
441894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
442894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
443894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
444894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
445894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLLight {
446894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
4476730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org    virtual ~GrGLLight() {}
448894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
449ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    /**
450ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
451ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * below. It adds a vec3f uniform visible in the FS that represents the constant light color.
452ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     */
45330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    void emitLightColorUniform(GrGLProgramBuilder*);
454ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
455e862d16162fd46ad9b2832c8844b00c81bedbac0skia.committer@gmail.com    /**
456ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * These two functions are called from GrGLLightingEffect's emitCode() function.
457ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * emitSurfaceToLight places an expression in param out that is the vector from the surface to
458ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * the light. The expression will be used in the FS. emitLightColor writes an expression into
459ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * the FS that is the color of the light. Either function may add functions and/or uniforms to
460ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * the FS. The default of emitLightColor appends the name of the constant light color uniform
461ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * and so this function only needs to be overridden if the light color varies spatially.
462ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     */
46330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) = 0;
46430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitLightColor(GrGLProgramBuilder*, const char *surfaceToLight);
465ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
466ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
467ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    // INHERITED::setData().
4687510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager&,
469fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                         const SkLight* light) const;
470894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
471894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprotected:
472ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    /**
473ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
474ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * function.
475ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     */
476ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    UniformHandle lightColorUni() const { return fColorUni; }
477ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
478ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.comprivate:
479032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle fColorUni;
480ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
481ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    typedef SkRefCnt INHERITED;
482894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
483894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
484894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
485894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
486894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLDistantLight : public GrGLLight {
487894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
4886730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org    virtual ~GrGLDistantLight() {}
4897510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager&,
490fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                         const SkLight* light) const SK_OVERRIDE;
49130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE;
4928d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
493894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
494894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLight INHERITED;
495032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle fDirectionUni;
496894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
497894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
498894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
499894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
500894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLPointLight : public GrGLLight {
501894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
5026730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org    virtual ~GrGLPointLight() {}
5037510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager&,
504fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                         const SkLight* light) const SK_OVERRIDE;
50530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE;
5068d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
507894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
508894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLight INHERITED;
509032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle fLocationUni;
510894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
511894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
512894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
513894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
514894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLSpotLight : public GrGLLight {
515894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
5166730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org    virtual ~GrGLSpotLight() {}
5177510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    virtual void setData(const GrGLProgramDataManager&,
518fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                         const SkLight* light) const SK_OVERRIDE;
51930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitSurfaceToLight(GrGLProgramBuilder*, const char* z) SK_OVERRIDE;
52030ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitLightColor(GrGLProgramBuilder*, const char *surfaceToLight) SK_OVERRIDE;
5218d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
522894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
523894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLight INHERITED;
524894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
525a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString        fLightColorFunc;
526032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fLocationUni;
527032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fExponentUni;
528032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fCosOuterConeAngleUni;
529032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fCosInnerConeAngleUni;
530032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fConeScaleUni;
531032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fSUni;
532894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
533cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
534cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
535cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.comclass GrGLLight;
536cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
537cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
538894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
539f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
540f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
541894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
542894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
543790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.orgclass SkLight : public SkRefCnt {
544f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
5450456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com    SK_DECLARE_INST_COUNT(SkLight)
5460456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com
547f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    enum LightType {
548f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        kDistant_LightType,
549f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        kPoint_LightType,
550f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        kSpot_LightType,
551f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    };
552f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    virtual LightType type() const = 0;
553bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    const SkPoint3& color() const { return fColor; }
554894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    virtual GrGLLight* createGLLight() const = 0;
555894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    virtual bool isEqual(const SkLight& other) const {
556894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        return fColor == other.fColor;
557894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
5588d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    // Called to know whether the generated GrGLLight will require access to the fragment position.
5598d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    virtual bool requiresFragmentPosition() const = 0;
560fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    virtual SkLight* transform(const SkMatrix& matrix) const = 0;
561f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
562790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    // Defined below SkLight's subclasses.
5638b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    void flattenLight(SkWriteBuffer& buffer) const;
5648b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    static SkLight* UnflattenLight(SkReadBuffer& buffer);
565790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org
5660833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.comprotected:
567bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkLight(SkColor color)
568bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org      : fColor(SkIntToScalar(SkColorGetR(color)),
569bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org               SkIntToScalar(SkColorGetG(color)),
570bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org               SkIntToScalar(SkColorGetB(color))) {}
571fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkLight(const SkPoint3& color)
572fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org      : fColor(color) {}
5738b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkLight(SkReadBuffer& buffer) {
574bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org        fColor = readPoint3(buffer);
575bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    }
576790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org
5778b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
578790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org
5790833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
5800833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.comprivate:
581790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    typedef SkRefCnt INHERITED;
582bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkPoint3 fColor;
583f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
584f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
585894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
586894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
587f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgclass SkDistantLight : public SkLight {
588f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
589bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkDistantLight(const SkPoint3& direction, SkColor color)
590bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org      : INHERITED(color), fDirection(direction) {
591f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
5920833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
593f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
594f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return fDirection;
595f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    };
596bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkPoint3 lightColor(const SkPoint3&) const { return color(); }
597f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    virtual LightType type() const { return kDistant_LightType; }
598894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPoint3& direction() const { return fDirection; }
599cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com    virtual GrGLLight* createGLLight() const SK_OVERRIDE {
600cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
601cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        return SkNEW(GrGLDistantLight);
602cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
603cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        SkDEBUGFAIL("Should not call in GPU-less build");
604cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        return NULL;
605cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
606cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com    }
6078d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    virtual bool requiresFragmentPosition() const SK_OVERRIDE { return false; }
6088d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
6096730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org    virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
6106730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org        if (other.type() != kDistant_LightType) {
6116730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org            return false;
6126730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org        }
6136730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org
6146730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org        const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
6156730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org        return INHERITED::isEqual(other) &&
6166730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org               fDirection == o.fDirection;
6176730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org    }
618f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
6198b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
620790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        fDirection = readPoint3(buffer);
621790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    }
622f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
6230833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.comprotected:
624fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
625fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org      : INHERITED(color), fDirection(direction) {
626fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
627fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    virtual SkLight* transform(const SkMatrix& matrix) const {
628fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        return new SkDistantLight(direction(), color());
629fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
6308b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
6310833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        writePoint3(fDirection, buffer);
6320833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
6330833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
634f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
6350833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    typedef SkLight INHERITED;
636f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fDirection;
637f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
638f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
639894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
640894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
641f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgclass SkPointLight : public SkLight {
642f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
643bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkPointLight(const SkPoint3& location, SkColor color)
644bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org     : INHERITED(color), fLocation(location) {}
6450833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
646f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
647f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
648f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                           fLocation.fY - SkIntToScalar(y),
649f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                           fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
650f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        direction.normalize();
651f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return direction;
652f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    };
653bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkPoint3 lightColor(const SkPoint3&) const { return color(); }
654f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    virtual LightType type() const { return kPoint_LightType; }
655894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPoint3& location() const { return fLocation; }
656894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    virtual GrGLLight* createGLLight() const SK_OVERRIDE {
657cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
658300f562dedd02df2f41de443c8b58ab2ceaed0f0tomhudson@google.com        return SkNEW(GrGLPointLight);
659cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
660cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        SkDEBUGFAIL("Should not call in GPU-less build");
661cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        return NULL;
662cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
663894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
6648d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; }
6656730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org    virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
666894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        if (other.type() != kPoint_LightType) {
667894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org            return false;
668894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        }
669894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        const SkPointLight& o = static_cast<const SkPointLight&>(other);
670894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        return INHERITED::isEqual(other) &&
671894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fLocation == o.fLocation;
672894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
673fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    virtual SkLight* transform(const SkMatrix& matrix) const {
674fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
675fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        matrix.mapPoints(&location2, 1);
6761037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        // Use X scale and Y scale on Z and average the result
6771037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
6781037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        matrix.mapVectors(&locationZ, 1);
6791037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY));
680fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        return new SkPointLight(location, color());
681fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
682f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
6838b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
6840833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fLocation = readPoint3(buffer);
6850833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
686790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org
687790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.orgprotected:
688fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkPointLight(const SkPoint3& location, const SkPoint3& color)
689fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org     : INHERITED(color), fLocation(location) {}
6908b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
6910833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        writePoint3(fLocation, buffer);
6920833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
6930833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
694f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
6950833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    typedef SkLight INHERITED;
696f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fLocation;
697f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
698f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
699894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
700894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
701f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgclass SkSpotLight : public SkLight {
702f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
703bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
704bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org     : INHERITED(color),
705bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org       fLocation(location),
706f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fTarget(target),
7074b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org       fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax))
708f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    {
709f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fS = target - location;
710f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fS.normalize();
711f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
7124b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org       const SkScalar antiAliasThreshold = 0.016f;
713f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
714f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fConeScale = SkScalarInvert(antiAliasThreshold);
715f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
7160833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
717fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    virtual SkLight* transform(const SkMatrix& matrix) const {
718fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
719fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        matrix.mapPoints(&location2, 1);
7201037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        // Use X scale and Y scale on Z and average the result
7211037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
7221037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        matrix.mapVectors(&locationZ, 1);
7231037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY));
724fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
725fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        matrix.mapPoints(&target2, 1);
7261037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
7271037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        matrix.mapVectors(&targetZ, 1);
7281037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint3 target(target2.fX, target2.fY, SkScalarAve(targetZ.fX, targetZ.fY));
7291037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint3 s = target - location;
7301037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        s.normalize();
7311037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, s, color());
732fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
733fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org
734f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
735f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
736f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                           fLocation.fY - SkIntToScalar(y),
737f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                           fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
738f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        direction.normalize();
739f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return direction;
740f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    };
741bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
742f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkScalar cosAngle = -surfaceToLight.dot(fS);
743f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        if (cosAngle < fCosOuterConeAngle) {
744bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org            return SkPoint3(0, 0, 0);
745f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        }
746f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent);
747f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        if (cosAngle < fCosInnerConeAngle) {
748f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
749bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org            return color() * SkScalarMul(scale, fConeScale);
750f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        }
751bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org        return color() * scale;
752f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
753894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    virtual GrGLLight* createGLLight() const SK_OVERRIDE {
754cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
755300f562dedd02df2f41de443c8b58ab2ceaed0f0tomhudson@google.com        return SkNEW(GrGLSpotLight);
756cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
757cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        SkDEBUGFAIL("Should not call in GPU-less build");
758cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        return NULL;
759cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
760894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
7618d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; }
7620833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    virtual LightType type() const { return kSpot_LightType; }
763894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPoint3& location() const { return fLocation; }
764894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPoint3& target() const { return fTarget; }
765894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar specularExponent() const { return fSpecularExponent; }
766894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
767894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
768894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar coneScale() const { return fConeScale; }
769eb311845c1b412a9a7d851444a70ec24ab60fb2csenorblanco@chromium.org    const SkPoint3& s() const { return fS; }
7700833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
7718b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
7720833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fLocation = readPoint3(buffer);
7730833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fTarget = readPoint3(buffer);
7740833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fSpecularExponent = buffer.readScalar();
7750833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fCosOuterConeAngle = buffer.readScalar();
7760833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fCosInnerConeAngle = buffer.readScalar();
7770833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fConeScale = buffer.readScalar();
7780833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fS = readPoint3(buffer);
779c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
780c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                        SkScalarIsFinite(fCosOuterConeAngle) &&
781c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                        SkScalarIsFinite(fCosInnerConeAngle) &&
782c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                        SkScalarIsFinite(fConeScale));
7830833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
784790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.orgprotected:
785fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cosOuterConeAngle, SkScalar cosInnerConeAngle, SkScalar coneScale, const SkPoint3& s, const SkPoint3& color)
786fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org     : INHERITED(color),
787fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fLocation(location),
788fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fTarget(target),
789fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fSpecularExponent(specularExponent),
790fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fCosOuterConeAngle(cosOuterConeAngle),
791fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fCosInnerConeAngle(cosInnerConeAngle),
792fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fConeScale(coneScale),
793fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fS(s)
794fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    {
795fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
7968b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
7970833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        writePoint3(fLocation, buffer);
7980833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        writePoint3(fTarget, buffer);
7990833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        buffer.writeScalar(fSpecularExponent);
8000833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        buffer.writeScalar(fCosOuterConeAngle);
8010833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        buffer.writeScalar(fCosInnerConeAngle);
8020833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        buffer.writeScalar(fConeScale);
8030833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        writePoint3(fS, buffer);
8040833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
8050833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
806bd9fad67b841e94e2042bbc424f197887fe7c00esenorblanco@chromium.org    virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
807894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        if (other.type() != kSpot_LightType) {
808894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org            return false;
809894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        }
810894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
811894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
812894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        return INHERITED::isEqual(other) &&
813894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fLocation == o.fLocation &&
814894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fTarget == o.fTarget &&
815894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fSpecularExponent == o.fSpecularExponent &&
816894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fCosOuterConeAngle == o.fCosOuterConeAngle;
817894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
818894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
819f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
8204b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org    static const SkScalar kSpecularExponentMin;
8214b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org    static const SkScalar kSpecularExponentMax;
8224b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org
8230833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    typedef SkLight INHERITED;
824f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fLocation;
825f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fTarget;
826f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fSpecularExponent;
827f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fCosOuterConeAngle;
828f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fCosInnerConeAngle;
829f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fConeScale;
830f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fS;
831f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
832f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
8334b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org// According to the spec, the specular term should be in the range [1, 128] :
8344b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org// http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute
8354b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.orgconst SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
8364b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.orgconst SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
8374b681bc95b14e081f1cc5b68cb755d57fc8eb977commit-bot@chromium.org
838894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
839894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
8408b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLight::flattenLight(SkWriteBuffer& buffer) const {
841790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    // Write type first, then baseclass, then subclass.
842790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    buffer.writeInt(this->type());
843790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    writePoint3(fColor, buffer);
844790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    this->onFlattenLight(buffer);
845790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org}
846790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org
8478b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org/*static*/ SkLight* SkLight::UnflattenLight(SkReadBuffer& buffer) {
848790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    // Read type first.
849790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    const SkLight::LightType type = (SkLight::LightType)buffer.readInt();
850790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    switch (type) {
851790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        // Each of these constructors must first call SkLight's, so we'll read the baseclass
852790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        // then subclass, same order as flattenLight.
853790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        case SkLight::kDistant_LightType: return SkNEW_ARGS(SkDistantLight, (buffer));
854790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        case SkLight::kPoint_LightType:   return SkNEW_ARGS(SkPointLight, (buffer));
855790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        case SkLight::kSpot_LightType:    return SkNEW_ARGS(SkSpotLight, (buffer));
856790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        default:
857790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org            SkDEBUGFAIL("Unknown LightType.");
858cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org            buffer.validate(false);
859790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org            return NULL;
860790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    }
861790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org}
862790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
863790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org
8649ea3d57fde28a5fe4487a111dc3dd49418235e5esenorblancoSkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale,
8655e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                             SkImageFilter* input, const CropRect* cropRect,
8665e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                             uint32_t uniqueID)
8675e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco  : INHERITED(1, &input, cropRect, uniqueID)
8689fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed  , fLight(SkRef(light))
8699fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed  , fSurfaceScale(surfaceScale / 255)
8709fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed{}
8719fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
8729fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(const SkPoint3& direction,
8739fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                              SkColor lightColor,
8749fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                              SkScalar surfaceScale,
8759fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                              SkScalar kd,
8769fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                              SkImageFilter* input,
8779fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                              const CropRect* cropRect) {
8789fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkDistantLight, (direction, lightColor)));
8799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
880f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
881f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
8829fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(const SkPoint3& location,
8839fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkColor lightColor,
8849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkScalar surfaceScale,
8859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkScalar kd,
8869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkImageFilter* input,
8879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            const CropRect* cropRect) {
8889fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkPointLight, (location, lightColor)));
8899fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
890f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
891f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
8929fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(const SkPoint3& location,
8939fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                           const SkPoint3& target,
8949fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                           SkScalar specularExponent,
8959fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                           SkScalar cutoffAngle,
8969fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                           SkColor lightColor,
8979fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                           SkScalar surfaceScale,
8989fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                           SkScalar kd,
8999fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                           SkImageFilter* input,
9009fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                           const CropRect* cropRect) {
9019fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkSpotLight, (location, target, specularExponent,
9029fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                         cutoffAngle, lightColor)));
9039fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
904f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
905f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
9069fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(const SkPoint3& direction,
9079fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                               SkColor lightColor,
9089fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                               SkScalar surfaceScale,
9099fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                               SkScalar ks,
9109fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                               SkScalar shine,
9119fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                               SkImageFilter* input,
9129fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                               const CropRect* cropRect) {
9139fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkDistantLight, (direction, lightColor)));
9149fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
915f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
916f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
9179fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(const SkPoint3& location,
9189fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                             SkColor lightColor,
9199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                             SkScalar surfaceScale,
9209fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                             SkScalar ks,
9219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                             SkScalar shine,
9229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                             SkImageFilter* input,
9239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                             const CropRect* cropRect) {
9249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkPointLight, (location, lightColor)));
9259fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
926f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
927f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
9289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(const SkPoint3& location,
9299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            const SkPoint3& target,
9309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkScalar specularExponent,
9319fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkScalar cutoffAngle,
9329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkColor lightColor,
9339fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkScalar surfaceScale,
9349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkScalar ks,
9359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkScalar shine,
9369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            SkImageFilter* input,
9379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                            const CropRect* cropRect) {
9389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkLight> light(SkNEW_ARGS(SkSpotLight, (location, target, specularExponent,
9399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                         cutoffAngle, lightColor)));
9409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
941f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
942f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
9439fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkLightingImageFilter::~SkLightingImageFilter() {}
944f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
9459fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
9468b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkLightingImageFilter::SkLightingImageFilter(SkReadBuffer& buffer)
947ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org  : INHERITED(1, buffer) {
9489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    fLight.reset(SkLight::UnflattenLight(buffer));
949f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    fSurfaceScale = buffer.readScalar();
950c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    buffer.validate(SkScalarIsFinite(fSurfaceScale));
951f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
9529fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
953f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
9548b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
955f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    this->INHERITED::flatten(buffer);
956790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    fLight->flattenLight(buffer);
9579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.writeScalar(fSurfaceScale * 255);
958f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
959f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
960894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
961894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
9629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkDiffuseLightingImageFilter::Create(SkLight* light, SkScalar surfaceScale,
9635e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                                    SkScalar kd, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID) {
9649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (NULL == light) {
9659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
9669fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
9679fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) {
9689fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
9699fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
970ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    // According to the spec, kd can be any non-negative number :
971ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
9729fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (kd < 0) {
9739fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
9749fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
9755e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    return SkNEW_ARGS(SkDiffuseLightingImageFilter, (light, surfaceScale, kd, input, cropRect, uniqueID));
9769fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
9779fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
9785e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblancoSkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID)
9795e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco  : SkLightingImageFilter(light, surfaceScale, input, cropRect, uniqueID),
9809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    fKD(kd)
981f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org{
982f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
983f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
9849fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
9858b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkReadBuffer& buffer)
986f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org  : INHERITED(buffer)
987f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org{
988f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    fKD = buffer.readScalar();
989ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    buffer.validate(SkScalarIsFinite(fKD) && (fKD >= 0));
990f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
9919fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
9929fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
9939fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
9949fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
9959fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkLight> light(SkLight::UnflattenLight(buffer));
9969fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar surfaceScale = buffer.readScalar();
9979fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar kd = buffer.readScalar();
9985e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    return Create(light, surfaceScale, kd, common.getInput(0), &common.cropRect(), common.uniqueID());
9999fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
1000f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
10018b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1002f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    this->INHERITED::flatten(buffer);
1003f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    buffer.writeScalar(fKD);
1004f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1005f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
1006a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.orgbool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
1007a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org                                                 const SkBitmap& source,
10084cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                                 const Context& ctx,
1009f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                                                 SkBitmap* dst,
1010ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                                 SkIPoint* offset) const {
1011a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org    SkImageFilter* input = getInput(0);
1012a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org    SkBitmap src = source;
10136776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
10144cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
1015a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org        return false;
1016a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org    }
1017a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org
101828fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    if (src.colorType() != kN32_SkColorType) {
1019f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return false;
1020f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
1021118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect bounds;
1022118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
1023f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return false;
1024f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
10254e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
1026118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (bounds.width() < 2 || bounds.height() < 2) {
10274e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        return false;
10284e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    }
10294e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
1030118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkAutoLockPixels alp(src);
1031118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!src.getPixels()) {
1032f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return false;
1033f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
10344e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
1035848250415eddc54075f7eb8795e8db79e749c6abreed    if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
1036cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org        return false;
1037cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
1038f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
10394cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm()));
1040fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org
1041f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    DiffuseLightingType lightingType(fKD);
10426776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fX = bounds.left();
10436776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fY = bounds.top();
10446776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    bounds.offset(-srcOffset);
1045fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    switch (transformedLight->type()) {
1046f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        case SkLight::kDistant_LightType:
1047fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1048f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            break;
1049f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        case SkLight::kPoint_LightType:
1050fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1051f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            break;
1052f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        case SkLight::kSpot_LightType:
1053fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1054f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            break;
1055f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
10564e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
1057f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return true;
1058f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1059f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
1060cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
1061b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkDiffuseLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp,
1062b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                       GrTexture* texture,
1063b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                       const SkMatrix& matrix,
1064b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                       const SkIRect&) const {
1065b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    if (fp) {
1066894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
1067b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *fp = GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd());
1068894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
1069894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    return true;
1070894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1071d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
1072894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1073894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1074894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
10759fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkImageFilter* SkSpecularLightingImageFilter::Create(SkLight* light, SkScalar surfaceScale,
10765e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID) {
10779fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (NULL == light) {
10789fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
10799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
10809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) {
10819fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
10829fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
1083ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    // According to the spec, ks can be any non-negative number :
1084ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
10859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (ks < 0) {
10869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
10879fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
10889fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkNEW_ARGS(SkSpecularLightingImageFilter,
10895e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco                      (light, surfaceScale, ks, shininess, input, cropRect, uniqueID));
10909fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
10919fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
10925e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblancoSkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect, uint32_t uniqueID)
10935e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco  : SkLightingImageFilter(light, surfaceScale, input, cropRect, uniqueID),
10949fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    fKS(ks),
1095f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    fShininess(shininess)
1096f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org{
1097f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1098f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
10999fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
11008b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkReadBuffer& buffer)
11019fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    : INHERITED(buffer)
1102f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org{
1103f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    fKS = buffer.readScalar();
1104f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    fShininess = buffer.readScalar();
1105ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    buffer.validate(SkScalarIsFinite(fKS) && (fKS >= 0) &&
1106c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                    SkScalarIsFinite(fShininess));
1107f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
11089fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
11099fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
11109fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
11119fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
11129fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkLight> light(SkLight::UnflattenLight(buffer));
11139fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar surfaceScale = buffer.readScalar();
11149fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar ks = buffer.readScalar();
11159fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar shine = buffer.readScalar();
11165e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco    return Create(light, surfaceScale, ks, shine, common.getInput(0), &common.cropRect(), common.uniqueID());
11179fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
1118f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
11198b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1120f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    this->INHERITED::flatten(buffer);
1121f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    buffer.writeScalar(fKS);
1122f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    buffer.writeScalar(fShininess);
1123f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1124f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
1125a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.orgbool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
1126a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org                                                  const SkBitmap& source,
11274cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                                  const Context& ctx,
1128f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                                                  SkBitmap* dst,
1129ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                                  SkIPoint* offset) const {
1130a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org    SkImageFilter* input = getInput(0);
1131a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org    SkBitmap src = source;
11326776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
11334cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
1134a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org        return false;
1135a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org    }
1136a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org
113728fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org    if (src.colorType() != kN32_SkColorType) {
1138f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return false;
1139f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
11404e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
114129089179a66c06ef70da387111af75970f04ed53senorblanco@chromium.org    SkIRect bounds;
1142118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
1143f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return false;
1144f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
11454e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
114629089179a66c06ef70da387111af75970f04ed53senorblanco@chromium.org    if (bounds.width() < 2 || bounds.height() < 2) {
11470ef0501baf615149d6d84398d7594cd89f6e928dsenorblanco@chromium.org        return false;
11480ef0501baf615149d6d84398d7594cd89f6e928dsenorblanco@chromium.org    }
11490ef0501baf615149d6d84398d7594cd89f6e928dsenorblanco@chromium.org
1150118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkAutoLockPixels alp(src);
1151118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!src.getPixels()) {
1152118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return false;
1153118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
1154118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org
1155848250415eddc54075f7eb8795e8db79e749c6abreed    if (!dst->tryAllocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
1156cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org        return false;
1157cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
1158f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
1159f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SpecularLightingType lightingType(fKS, fShininess);
11606776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fX = bounds.left();
11616776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    offset->fY = bounds.top();
11626776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    bounds.offset(-srcOffset);
11634cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm()));
1164fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    switch (transformedLight->type()) {
1165f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        case SkLight::kDistant_LightType:
1166fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1167f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            break;
1168f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        case SkLight::kPoint_LightType:
1169fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            lightBitmap<SpecularLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1170f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            break;
1171f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        case SkLight::kSpot_LightType:
1172fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org            lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1173f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            break;
1174f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
1175f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return true;
1176f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1177f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
1178cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
1179b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkSpecularLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp,
1180b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                        GrTexture* texture,
1181b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                        const SkMatrix& matrix,
1182b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                        const SkIRect&) const {
1183b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    if (fp) {
1184894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
1185b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *fp = GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess());
1186894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
1187894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    return true;
1188894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1189d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
1190894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1191894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1192894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1193cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
1194a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1195a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.comnamespace {
1196e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.orgSkPoint3 random_point3(SkRandom* random) {
1197a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
1198a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                    SkScalarToFloat(random->nextSScalar1()),
1199a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                    SkScalarToFloat(random->nextSScalar1()));
1200a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com}
1201a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1202e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.orgSkLight* create_random_light(SkRandom* random) {
1203a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    int type = random->nextULessThan(3);
1204a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    switch (type) {
1205a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        case 0: {
1206a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com            return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU()));
1207a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        }
1208a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        case 1: {
1209a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com            return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU()));
1210a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        }
1211a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        case 2: {
1212a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com            return SkNEW_ARGS(SkSpotLight, (random_point3(random),
1213a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                            random_point3(random),
1214a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                            random->nextUScalar1(),
1215fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                                            random->nextUScalar1(),
1216a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                            random->nextU()));
1217a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        }
1218a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        default:
121988cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org            SkFAIL("Unexpected value.");
1220a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com            return NULL;
1221a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    }
1222a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com}
1223a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1224a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com}
1225a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1226b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrGLLightingEffect  : public GrGLFragmentProcessor {
1227894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
1228b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrGLLightingEffect(const GrBackendProcessorFactory&, const GrProcessor&);
1229894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    virtual ~GrGLLightingEffect();
1230894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
123130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitCode(GrGLProgramBuilder*,
1232b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrFragmentProcessor&,
1233b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                          const GrProcessorKey&,
1234ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                          const char* outputColor,
1235ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                          const char* inputColor,
123677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                          const TransformedCoordsArray&,
1237ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                          const TextureSamplerArray&) SK_OVERRIDE;
1238894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1239b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b);
1240894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1241ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    /**
1242ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * Subclasses of GrGLLightingEffect must call INHERITED::setData();
1243ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     */
1244b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
1245894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1246ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.comprotected:
124730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) = 0;
1248ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
1249894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
1250b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrGLFragmentProcessor INHERITED;
1251894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
125217fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com    UniformHandle       fImageIncrementUni;
125317fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com    UniformHandle       fSurfaceScaleUni;
125417fc651dbe2e0624f6c85fb6e081d28a87d5a08bbsalomon@google.com    GrGLLight*          fLight;
1255894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
1256894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1257894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1258894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1259894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLDiffuseLightingEffect  : public GrGLLightingEffect {
1260894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
1261b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrGLDiffuseLightingEffect(const GrBackendProcessorFactory&, const GrProcessor&);
126230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) SK_OVERRIDE;
1263b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
1264894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1265894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
1266894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLightingEffect INHERITED;
1267894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1268032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fKDUni;
1269894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
1270894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1271894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1272894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1273894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLSpecularLightingEffect  : public GrGLLightingEffect {
1274894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
1275b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrGLSpecularLightingEffect(const GrBackendProcessorFactory&, const GrProcessor&);
127630ba436f04e61d4505fb854d5fc56079636e0788joshualitt    virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) SK_OVERRIDE;
1277b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
1278894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1279894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
1280894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLightingEffect INHERITED;
1281894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1282032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fKSUni;
1283032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fShininessUni;
1284894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
1285894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1286894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1287894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
12884e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.orgGrLightingEffect::GrLightingEffect(GrTexture* texture,
12894e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                   const SkLight* light,
12904e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                   SkScalar surfaceScale,
1291fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                                   const SkMatrix& matrix)
12926267f81f3d60ce144ab2b09ea369420984d5c9d9bsalomon    : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
1293d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com    , fLight(light)
12944e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    , fSurfaceScale(surfaceScale)
1295fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    , fFilterMatrix(matrix) {
1296894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    fLight->ref();
12978d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    if (light->requiresFragmentPosition()) {
12988d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org        this->setWillReadFragmentPosition();
12998d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    }
1300894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1301894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1302894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgGrLightingEffect::~GrLightingEffect() {
1303894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    fLight->unref();
1304894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1305894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1306b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrLightingEffect::onIsEqual(const GrProcessor& sBase) const {
130749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrLightingEffect& s = sBase.cast<GrLightingEffect>();
130868b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    return this->texture(0) == s.texture(0) &&
1309d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com           fLight->isEqual(*s.fLight) &&
1310894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org           fSurfaceScale == s.fSurfaceScale;
1311894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1312894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1313894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1314894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
13154e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.orgGrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture,
13164e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                 const SkLight* light,
13174e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                 SkScalar surfaceScale,
1318fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                                                 const SkMatrix& matrix,
13194e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                 SkScalar kd)
1320fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    : INHERITED(texture, light, surfaceScale, matrix), fKD(kd) {
1321894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1322894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1323b0a8a377f832c59cee939ad721e1f87d378b7142joshualittconst GrBackendFragmentProcessorFactory& GrDiffuseLightingEffect::getFactory() const {
1324b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return GrTBackendFragmentProcessorFactory<GrDiffuseLightingEffect>::getInstance();
1325894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1326894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1327b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrDiffuseLightingEffect::onIsEqual(const GrProcessor& sBase) const {
132849586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrDiffuseLightingEffect& s = sBase.cast<GrDiffuseLightingEffect>();
132968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    return INHERITED::onIsEqual(sBase) &&
1330894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org            this->kd() == s.kd();
1331894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1332894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1333b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect);
1334a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1335b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
133683d081ae1d731b5039e99823620f5e287542ee39bsalomon                                              GrContext* context,
133783d081ae1d731b5039e99823620f5e287542ee39bsalomon                                              const GrDrawTargetCaps&,
133883d081ae1d731b5039e99823620f5e287542ee39bsalomon                                              GrTexture* textures[]) {
1339a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkScalar surfaceScale = random->nextSScalar1();
1340a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkScalar kd = random->nextUScalar1();
1341a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkAutoTUnref<SkLight> light(create_random_light(random));
1342fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkMatrix matrix;
1343fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    for (int i = 0; i < 9; i++) {
1344fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        matrix[i] = random->nextUScalar1();
1345fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
1346b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return GrDiffuseLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx],
1347fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                                           light, surfaceScale, matrix, kd);
1348a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com}
1349a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1350a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1351894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1352894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1353b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLLightingEffect::GrGLLightingEffect(const GrBackendProcessorFactory& factory,
1354b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                       const GrProcessor& fp)
135577af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com    : INHERITED(factory) {
1356b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrLightingEffect& m = fp.cast<GrLightingEffect>();
1357894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    fLight = m.light()->createGLLight();
1358894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1359894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1360894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgGrGLLightingEffect::~GrGLLightingEffect() {
1361894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    delete fLight;
1362894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1363894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
136430ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLLightingEffect::emitCode(GrGLProgramBuilder* builder,
1365b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                  const GrFragmentProcessor&,
1366b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                  const GrProcessorKey& key,
1367ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                  const char* outputColor,
1368ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                  const char* inputColor,
136977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                                  const TransformedCoordsArray& coords,
1370ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                  const TextureSamplerArray& samplers) {
137130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1372032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com                                              kVec2f_GrSLType,
1373777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                             "ImageIncrement");
137430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fSurfaceScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1375032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com                                           kFloat_GrSLType,
1376777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                           "SurfaceScale");
1377ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    fLight->emitLightColorUniform(builder);
1378a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString lightFunc;
1379a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    this->emitLightFunc(builder, &lightFunc);
1380a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    static const GrGLShaderVar gSobelArgs[] =  {
1381a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("a", kFloat_GrSLType),
1382a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("b", kFloat_GrSLType),
1383a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("c", kFloat_GrSLType),
1384a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("d", kFloat_GrSLType),
1385a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("e", kFloat_GrSLType),
1386a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("f", kFloat_GrSLType),
1387a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("scale", kFloat_GrSLType),
1388a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1389a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString sobelFuncName;
139030ba436f04e61d4505fb854d5fc56079636e0788joshualitt    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
139130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0);
139230ba436f04e61d4505fb854d5fc56079636e0788joshualitt
139330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->emitFunction(kFloat_GrSLType,
139474a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            "sobel",
139574a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            SK_ARRAY_COUNT(gSobelArgs),
139674a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            gSobelArgs,
139774a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
139874a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            &sobelFuncName);
1399a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    static const GrGLShaderVar gPointToNormalArgs[] =  {
1400a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("x", kFloat_GrSLType),
1401a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("y", kFloat_GrSLType),
1402a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("scale", kFloat_GrSLType),
1403a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1404a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString pointToNormalName;
140530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->emitFunction(kVec3f_GrSLType,
140674a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            "pointToNormal",
140774a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            SK_ARRAY_COUNT(gPointToNormalArgs),
140874a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            gPointToNormalArgs,
140974a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            "\treturn normalize(vec3(-x * scale, y * scale, 1));\n",
141074a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            &pointToNormalName);
1411a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1412a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    static const GrGLShaderVar gInteriorNormalArgs[] =  {
1413a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("m", kFloat_GrSLType, 9),
1414a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("surfaceScale", kFloat_GrSLType),
1415a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1416a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString interiorNormalBody;
1417a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n"
1418a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                               "\t       %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n"
1419a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                               "\t       surfaceScale);\n",
1420a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                pointToNormalName.c_str(),
1421a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                sobelFuncName.c_str(),
1422a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                                sobelFuncName.c_str());
1423a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString interiorNormalName;
142430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->emitFunction(kVec3f_GrSLType,
142574a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            "interiorNormal",
142674a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            SK_ARRAY_COUNT(gInteriorNormalArgs),
142774a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            gInteriorNormalArgs,
142874a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            interiorNormalBody.c_str(),
142974a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            &interiorNormalName);
1430894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
143130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
143230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend("\t\tfloat m[9];\n");
1433032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
1434032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
1435032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
1436032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
1437894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    int index = 0;
1438894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    for (int dy = -1; dy <= 1; dy++) {
1439894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        for (int dx = -1; dx <= 1; dx++) {
1440894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org            SkString texCoords;
1441032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com            texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
144230ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\tm[%d] = ", index++);
144330ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->appendTextureLookup(samplers[0], texCoords.c_str());
144430ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend(".a;\n");
1445894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        }
1446894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
144730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend("\t\tvec3 surfaceToLight = ");
1448894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkString arg;
1449032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    arg.appendf("%s * m[4]", surfScale);
1450f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    fLight->emitSurfaceToLight(builder, arg.c_str());
145130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend(";\n");
145230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1453f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                           outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale);
1454a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    fLight->emitLightColor(builder, "surfaceToLight");
145530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend(");\n");
1456f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    SkString modulate;
1457f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
145830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppend(modulate.c_str());
1459894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1460894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1461b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLLightingEffect::GenKey(const GrProcessor& proc,
1462b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                const GrGLCaps& caps, GrProcessorKeyBuilder* b) {
1463b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    b->add32(proc.cast<GrLightingEffect>().light()->type());
1464894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1465894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
14667510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLLightingEffect::setData(const GrGLProgramDataManager& pdman,
1467b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                 const GrProcessor& proc) {
1468b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1469c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com    GrTexture* texture = lighting.texture(0);
1470ef5dbe1cd90fe586f165e54cb6f7608942610793senorblanco@chromium.org    float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
14717510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
14727510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
1473fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkAutoTUnref<SkLight> transformedLight(lighting.light()->transform(lighting.filterMatrix()));
14747510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    fLight->setData(pdman, transformedLight);
1475894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1476894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1477894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1478894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1479894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1480894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1481b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendProcessorFactory& factory,
1482b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                     const GrProcessor& proc)
1483b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    : INHERITED(factory, proc) {
1484894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1485894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
148630ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLDiffuseLightingEffect::emitLightFunc(GrGLProgramBuilder* builder, SkString* funcName) {
1487ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* kd;
148830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fKDUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1489ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                 kFloat_GrSLType,
1490ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                 "KD",
1491ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                 &kd);
1492ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
1493a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    static const GrGLShaderVar gLightArgs[] = {
1494a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("normal", kVec3f_GrSLType),
1495a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1496a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("lightColor", kVec3f_GrSLType)
1497a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1498a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString lightBody;
1499a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1500a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
150130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType,
150230ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      "light",
150330ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      SK_ARRAY_COUNT(gLightArgs),
150430ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      gLightArgs,
150530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      lightBody.c_str(),
150630ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      funcName);
1507894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1508894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
15097510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLDiffuseLightingEffect::setData(const GrGLProgramDataManager& pdman,
1510b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                        const GrProcessor& proc) {
1511b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    INHERITED::setData(pdman, proc);
1512b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrDiffuseLightingEffect& diffuse = proc.cast<GrDiffuseLightingEffect>();
15137510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fKDUni, diffuse.kd());
1514894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1515894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1516894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1517894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
15184e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.orgGrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture,
15194e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                   const SkLight* light,
15204e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                   SkScalar surfaceScale,
1521fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                                                   const SkMatrix& matrix,
15224e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                   SkScalar ks,
15234e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                   SkScalar shininess)
1524fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    : INHERITED(texture, light, surfaceScale, matrix),
1525894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org      fKS(ks),
1526894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org      fShininess(shininess) {
1527894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1528894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1529b0a8a377f832c59cee939ad721e1f87d378b7142joshualittconst GrBackendFragmentProcessorFactory& GrSpecularLightingEffect::getFactory() const {
1530b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return GrTBackendFragmentProcessorFactory<GrSpecularLightingEffect>::getInstance();
1531894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1532894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1533b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool GrSpecularLightingEffect::onIsEqual(const GrProcessor& sBase) const {
153449586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrSpecularLightingEffect& s = sBase.cast<GrSpecularLightingEffect>();
153568b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    return INHERITED::onIsEqual(sBase) &&
1536894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org           this->ks() == s.ks() &&
1537894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org           this->shininess() == s.shininess();
1538894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1539894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1540b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect);
1541a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1542b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* GrSpecularLightingEffect::TestCreate(SkRandom* random,
1543b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                          GrContext* context,
1544b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                          const GrDrawTargetCaps&,
1545b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                          GrTexture* textures[]) {
1546a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkScalar surfaceScale = random->nextSScalar1();
1547a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkScalar ks = random->nextUScalar1();
1548a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkScalar shininess = random->nextUScalar1();
1549a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkAutoTUnref<SkLight> light(create_random_light(random));
1550fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkMatrix matrix;
1551fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    for (int i = 0; i < 9; i++) {
1552fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        matrix[i] = random->nextUScalar1();
1553fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
1554b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    return GrSpecularLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx],
1555fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                                            light, surfaceScale, matrix, ks, shininess);
1556a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com}
1557a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1558894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1559894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1560b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendProcessorFactory& factory,
1561b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                                       const GrProcessor& proc)
1562b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    : INHERITED(factory, proc) {
1563894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1564894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
156530ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLSpecularLightingEffect::emitLightFunc(GrGLProgramBuilder* builder, SkString* funcName) {
1566ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* ks;
1567ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* shininess;
1568ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
156930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fKSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1570ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                 kFloat_GrSLType, "KS", &ks);
157130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fShininessUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1572ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                        kFloat_GrSLType, "Shininess", &shininess);
1573a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1574a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    static const GrGLShaderVar gLightArgs[] = {
1575a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("normal", kVec3f_GrSLType),
1576a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1577a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("lightColor", kVec3f_GrSLType)
1578a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1579a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString lightBody;
1580a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1581a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
15827b734e08430f6b1d147dfa9f0c2c08d88aa7b714senorblanco@chromium.org    lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
15837b734e08430f6b1d147dfa9f0c2c08d88aa7b714senorblanco@chromium.org    lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n");
158430ba436f04e61d4505fb854d5fc56079636e0788joshualitt    builder->getFragmentShaderBuilder()->emitFunction(kVec4f_GrSLType,
158530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      "light",
158630ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      SK_ARRAY_COUNT(gLightArgs),
158730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      gLightArgs,
158830ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      lightBody.c_str(),
158930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                                                      funcName);
1590894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1591894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
15927510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLSpecularLightingEffect::setData(const GrGLProgramDataManager& pdman,
1593b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         const GrProcessor& effect) {
159449586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    INHERITED::setData(pdman, effect);
159549586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrSpecularLightingEffect& spec = effect.cast<GrSpecularLightingEffect>();
15967510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fKSUni, spec.ks());
15977510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fShininessUni, spec.shininess());
1598894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1599894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1600894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
160130ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLLight::emitLightColorUniform(GrGLProgramBuilder* builder) {
160230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1603777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                    kVec3f_GrSLType, "LightColor");
1604894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1605894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
160630ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLLight::emitLightColor(GrGLProgramBuilder* builder,
1607ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                               const char *surfaceToLight) {
1608b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    builder->getFragmentShaderBuilder()->codeAppend(builder->getUniformCStr(this->lightColorUni()));
1609ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com}
1610ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
16117510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLLight::setData(const GrGLProgramDataManager& pdman,
1612fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                        const SkLight* light) const {
16137510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformPoint3(pdman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
1614894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1615894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1616894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1617894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
16187510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLDistantLight::setData(const GrGLProgramDataManager& pdman,
1619fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                               const SkLight* light) const {
16207510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    INHERITED::setData(pdman, light);
1621894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkASSERT(light->type() == SkLight::kDistant_LightType);
1622894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
16237510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
1624894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1625894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
162630ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLDistantLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) {
1627ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* dir;
162830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fDirectionUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType,
1629ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                        "LightDirection", &dir);
163030ba436f04e61d4505fb854d5fc56079636e0788joshualitt    builder->getFragmentShaderBuilder()->codeAppend(dir);
1631894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1632894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1633894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1634894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
16357510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLPointLight::setData(const GrGLProgramDataManager& pdman,
1636fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                             const SkLight* light) const {
16377510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    INHERITED::setData(pdman, light);
1638894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkASSERT(light->type() == SkLight::kPoint_LightType);
1639894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
16407510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformPoint3(pdman, fLocationUni, pointLight->location());
1641894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1642894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
164330ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLPointLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) {
1644ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* loc;
164530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec3f_GrSLType,
1646ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                       "LightLocation", &loc);
164730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
164830ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
164930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            loc, fsBuilder->fragmentPosition(), z);
1650894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1651894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1652894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1653894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
16547510b224e52b9518a8ddf7418db0e9c258f79539kkinnunenvoid GrGLSpotLight::setData(const GrGLProgramDataManager& pdman,
1655fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                            const SkLight* light) const {
16567510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    INHERITED::setData(pdman, light);
1657894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkASSERT(light->type() == SkLight::kSpot_LightType);
1658894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
16597510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformPoint3(pdman, fLocationUni, spotLight->location());
16607510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fExponentUni, spotLight->specularExponent());
16617510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
16627510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
16637510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fConeScaleUni, spotLight->coneScale());
16647510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformNormal3(pdman, fSUni, spotLight->s());
1665894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1666894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
166730ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLSpotLight::emitSurfaceToLight(GrGLProgramBuilder* builder, const char* z) {
1668ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* location;
166930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fLocationUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1670ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                       kVec3f_GrSLType, "LightLocation", &location);
167130ba436f04e61d4505fb854d5fc56079636e0788joshualitt
167230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
167330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
167430ba436f04e61d4505fb854d5fc56079636e0788joshualitt            location, fsBuilder->fragmentPosition(), z);
1675894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1676894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
167730ba436f04e61d4505fb854d5fc56079636e0788joshualittvoid GrGLSpotLight::emitLightColor(GrGLProgramBuilder* builder,
1678ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                   const char *surfaceToLight) {
1679ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
1680ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class.
1681ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
1682ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* exponent;
1683ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* cosInner;
1684ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* cosOuter;
1685ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* coneScale;
1686ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* s;
168730ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fExponentUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1688ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                       kFloat_GrSLType, "Exponent", &exponent);
168930ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fCosInnerConeAngleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1690ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                                kFloat_GrSLType, "CosInnerConeAngle", &cosInner);
169130ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fCosOuterConeAngleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1692ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                                kFloat_GrSLType, "CosOuterConeAngle", &cosOuter);
169330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fConeScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1694ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                        kFloat_GrSLType, "ConeScale", &coneScale);
169530ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1696ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                kVec3f_GrSLType, "S", &s);
1697ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
1698a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    static const GrGLShaderVar gLightColorArgs[] = {
1699a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        GrGLShaderVar("surfaceToLight", kVec3f_GrSLType)
1700a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1701a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString lightColorBody;
1702a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
1703a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
1704a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\t\treturn vec3(0);\n");
1705a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\t}\n");
1706a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
1707a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
1708a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
1709a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                           color, cosOuter, coneScale);
1710a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\t}\n");
1711a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\treturn %s;\n", color);
171230ba436f04e61d4505fb854d5fc56079636e0788joshualitt    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
171330ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->emitFunction(kVec3f_GrSLType,
171474a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            "lightColor",
171574a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            SK_ARRAY_COUNT(gLightColorArgs),
171674a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            gLightColorArgs,
171774a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            lightColorBody.c_str(),
171874a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                            &fLightColorFunc);
1719e862d16162fd46ad9b2832c8844b00c81bedbac0skia.committer@gmail.com
172030ba436f04e61d4505fb854d5fc56079636e0788joshualitt    fsBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
1721894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1722894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1723cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
1724cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
17250833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
17260833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
17270833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
17280833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1729