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"
10a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.h"
1162745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett#include "SkColorSpaceXformer.h"
1260aaeb2b551d5e3e90baacac315e899e26f758f1Cary Clark#include "SkImageFilterPriv.h"
133d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips#include "SkPoint3.h"
148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
15ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips#include "SkSpecialImage.h"
16300f562dedd02df2f41de443c8b58ab2ceaed0f0tomhudson@google.com#include "SkTypes.h"
173d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips#include "SkWriteBuffer.h"
18cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
19cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
20cabe20cafd5f091a68bbc2c0c48755ba9b61b0b7kkinnunen#include "GrContext.h"
2102fa32c6d1ef4b7b05aa06df8be4add42a1712d3csmartdalton#include "GrFixedClip.h"
22eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt#include "GrFragmentProcessor.h"
23cabe20cafd5f091a68bbc2c0c48755ba9b61b0b7kkinnunen#include "GrPaint.h"
247f6cd90f0c8f6e8dd658cb1b1c587b833adfc364Robert Phillips#include "GrRenderTargetContext.h"
25646e4293f06d9de6d44dbfa3c32cdc15a6f5906eRobert Phillips#include "GrTexture.h"
267f6cd90f0c8f6e8dd658cb1b1c587b833adfc364Robert Phillips#include "GrTextureProxy.h"
277f6cd90f0c8f6e8dd658cb1b1c587b833adfc364Robert Phillips
281de87df0b743e30619b8ba93ab0169fd41d0feaerobertphillips#include "SkGr.h"
299bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco#include "effects/GrTextureDomain.h"
3064c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h"
312d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h"
32018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h"
337ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h"
3494efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon#include "../private/GrGLSL.h"
35894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
36894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLDiffuseLightingEffect;
37894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLSpecularLightingEffect;
38f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
39dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com// For brevity
40018fb62d12d1febf121fe265da5b6117b86a6541egdanieltypedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
41cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
42032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
4380ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breedconst SkScalar gOneThird = SkIntToScalar(1) / 3;
4480ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breedconst SkScalar gTwoThirds = SkIntToScalar(2) / 3;
454b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.orgconst SkScalar gOneHalf = 0.5f;
464b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.orgconst SkScalar gOneQuarter = 0.25f;
47f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
48cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
4962745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic void setUniformPoint3(const GrGLSLProgramDataManager& pdman, UniformHandle uni,
5062745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett                             const SkPoint3& point) {
51018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(float));
527510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set3fv(uni, 1, &point.fX);
53894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
54894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
5562745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic void setUniformNormal3(const GrGLSLProgramDataManager& pdman, UniformHandle uni,
5662745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett                              const SkPoint3& point) {
573d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    setUniformPoint3(pdman, uni, point);
58f4770d7e841a34d74d7f76a33312f4c5624da831senorblanco@chromium.org}
59cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
60f4770d7e841a34d74d7f76a33312f4c5624da831senorblanco@chromium.org
61f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org// Shift matrix components to the left, as we advance pixels to the right.
6262745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline void shiftMatrixLeft(int m[9]) {
63f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[0] = m[1];
64f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[3] = m[4];
65f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[6] = m[7];
66f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[1] = m[2];
67f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[4] = m[5];
68f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    m[7] = m[8];
69f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
70f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
71992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverthstatic inline void fast_normalize(SkPoint3* vector) {
72992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth    // add a tiny bit so we don't have to worry about divide-by-zero
73992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth    SkScalar magSq = vector->dot(*vector) + SK_ScalarNearlyZero;
74992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth    SkScalar scale = sk_float_rsqrt(magSq);
75992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth    vector->fX *= scale;
76992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth    vector->fY *= scale;
77992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth    vector->fZ *= scale;
78992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth}
79992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth
80959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillipsstatic SkPoint3 read_point3(SkReadBuffer& buffer) {
810c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkPoint3 point;
820c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    point.fX = buffer.readScalar();
830c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    point.fY = buffer.readScalar();
840c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    point.fZ = buffer.readScalar();
850c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    buffer.validate(SkScalarIsFinite(point.fX) &&
860c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed                    SkScalarIsFinite(point.fY) &&
870c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed                    SkScalarIsFinite(point.fZ));
880c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    return point;
890c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed};
900c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
91959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillipsstatic void write_point3(const SkPoint3& point, SkWriteBuffer& buffer) {
920c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    buffer.writeScalar(point.fX);
930c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    buffer.writeScalar(point.fY);
940c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    buffer.writeScalar(point.fZ);
950c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed};
960c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
970c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedclass GrGLLight;
980c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedclass SkImageFilterLight : public SkRefCnt {
990c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedpublic:
1000c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    enum LightType {
1010c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed        kDistant_LightType,
1020c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed        kPoint_LightType,
1030c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed        kSpot_LightType,
104959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips
105959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        kLast_LightType = kSpot_LightType
1060c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    };
1070c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual LightType type() const = 0;
1080c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    const SkPoint3& color() const { return fColor; }
1090c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual GrGLLight* createGLLight() const = 0;
1100c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual bool isEqual(const SkImageFilterLight& other) const {
1110c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed        return fColor == other.fColor;
1120c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    }
1130c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
1140c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1150c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer*) const = 0;
1160c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1170c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    // Defined below SkLight's subclasses.
1180c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    void flattenLight(SkWriteBuffer& buffer) const;
1190c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    static SkImageFilterLight* UnflattenLight(SkReadBuffer& buffer);
1200c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1210c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const = 0;
1220c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual SkPoint3 lightColor(const SkPoint3& surfaceToLight) const = 0;
1230c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1240c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedprotected:
1250c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkImageFilterLight(SkColor color) {
1260c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed        fColor = SkPoint3::Make(SkIntToScalar(SkColorGetR(color)),
1270c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed                                SkIntToScalar(SkColorGetG(color)),
1280c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed                                SkIntToScalar(SkColorGetB(color)));
1290c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    }
130959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips    SkImageFilterLight(const SkPoint3& color) : fColor(color) {}
131959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips
1320c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkImageFilterLight(SkReadBuffer& buffer) {
133959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        fColor = read_point3(buffer);
1340c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    }
1350c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1360c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
1370c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1380c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1390c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedprivate:
1400c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    typedef SkRefCnt INHERITED;
1410c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkPoint3 fColor;
1420c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed};
1430c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1440c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedclass BaseLightingType {
1450c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedpublic:
1460c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    BaseLightingType() {}
1470c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual ~BaseLightingType() {}
1480c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1490c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    virtual SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
1500c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed                            const SkPoint3& lightColor) const= 0;
1510c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed};
1520c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed
1530c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedclass DiffuseLightingType : public BaseLightingType {
154f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
155f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    DiffuseLightingType(SkScalar kd)
156f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        : fKD(kd) {}
157b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
1580c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed                    const SkPoint3& lightColor) const override {
1598be952ad8c9deefe19cff36f9ad217563400f817Mike Reed        SkScalar colorScale = fKD * normal.dot(surfaceTolight);
160f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
1613d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 color = lightColor.makeScale(colorScale);
162f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return SkPackARGB32(255,
163b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fX), 255),
164b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fY), 255),
165b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fZ), 255));
166f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
167f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
168f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fKD;
169f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
170f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
1713d32d768cd8b66c49c070495c08f7933b9dd2423robertphillipsstatic SkScalar max_component(const SkPoint3& p) {
1723d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    return p.x() > p.y() ? (p.x() > p.z() ? p.x() : p.z()) : (p.y() > p.z() ? p.y() : p.z());
1733d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips}
1743d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
1750c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedclass SpecularLightingType : public BaseLightingType {
176f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
177f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SpecularLightingType(SkScalar ks, SkScalar shininess)
178f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        : fKS(ks), fShininess(shininess) {}
179b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
1800c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed                    const SkPoint3& lightColor) const override {
181f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 halfDir(surfaceTolight);
182f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        halfDir.fZ += SK_Scalar1;        // eye position is always (0, 0, 1)
183992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth        fast_normalize(&halfDir);
1848be952ad8c9deefe19cff36f9ad217563400f817Mike Reed        SkScalar colorScale = fKS * SkScalarPow(normal.dot(halfDir), fShininess);
185f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
1863d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 color = lightColor.makeScale(colorScale);
1873d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return SkPackARGB32(SkClampMax(SkScalarRoundToInt(max_component(color)), 255),
188b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fX), 255),
189b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fY), 255),
190b9c95978c614e8f6bc00bdf565cff57388d8c659senorblanco@chromium.org                            SkClampMax(SkScalarRoundToInt(color.fZ), 255));
191f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
192f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
193f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fKS;
194f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fShininess;
195f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
196f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
19762745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
1988be952ad8c9deefe19cff36f9ad217563400f817Mike Reed    return (-a + b - 2 * c + 2 * d -e + f) * scale;
199f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
200f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
20162745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
2028be952ad8c9deefe19cff36f9ad217563400f817Mike Reed    SkPoint3 vector = SkPoint3::Make(-x * surfaceScale, -y * surfaceScale, 1);
203992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth    fast_normalize(&vector);
204f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return vector;
205f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
206f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
20762745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
208f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
209f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
210f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
211f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
212f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
21362745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
214f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(   0,    0, m[3], m[5], m[6], m[8], gOneThird),
215f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
216f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
217f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
218f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
21962745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
220f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(   0,    0, m[3], m[4], m[6], m[7], gTwoThirds),
221f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[3], m[6], m[4], m[7],    0,    0, gTwoThirds),
222f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
223f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
224f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
22562745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
226f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
227f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(   0,    0, m[1], m[7], m[2], m[8], gOneThird),
228f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
229f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
230f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
231f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
23262745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
233f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
234f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
235f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
236f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
237f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
23862745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
239f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
240f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[0], m[6], m[1], m[7],    0,    0, gOneThird),
241f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
242f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
243f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
24462745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
245f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[1], m[2], m[4], m[5],    0,    0, gTwoThirds),
246f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(   0,    0, m[1], m[4], m[2], m[5], gTwoThirds),
247f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
248f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
249f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
25062745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
251f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[0], m[2], m[3], m[5],    0,    0, gOneThird),
252f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
253f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
254f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
255f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
25662745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
257f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0,  0, gTwoThirds),
258f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         sobel(m[0], m[3], m[1], m[4], 0,  0, gTwoThirds),
259f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org                         surfaceScale);
260f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
261f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
26284f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco
26384f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblancoclass UncheckedPixelFetcher {
26484f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblancopublic:
26584f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco    static inline uint32_t Fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) {
26684f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        return SkGetPackedA32(*src.getAddr32(x, y));
26784f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco    }
26884f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco};
26984f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco
27084f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco// The DecalPixelFetcher is used when the destination crop rect exceeds the input bitmap bounds.
27184f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblancoclass DecalPixelFetcher {
27284f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblancopublic:
27384f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco    static inline uint32_t Fetch(const SkBitmap& src, int x, int y, const SkIRect& bounds) {
27484f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        if (x < bounds.fLeft || x >= bounds.fRight || y < bounds.fTop || y >= bounds.fBottom) {
27584f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            return 0;
27684f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        } else {
27784f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            return SkGetPackedA32(*src.getAddr32(x, y));
27884f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        }
27984f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco    }
28084f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco};
28184f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco
2820c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedtemplate <class PixelFetcher>
2830c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedstatic void lightBitmap(const BaseLightingType& lightingType,
2840c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed                 const SkImageFilterLight* l,
28584f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco                 const SkBitmap& src,
28684f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco                 SkBitmap* dst,
28784f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco                 SkScalar surfaceScale,
28884f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco                 const SkIRect& bounds) {
2894e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height());
2904e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    int left = bounds.left(), right = bounds.right();
2914e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    int bottom = bounds.bottom();
2924e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    int y = bounds.top();
29384f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco    SkIRect srcBounds = src.bounds();
2944e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkPMColor* dptr = dst->getAddr32(0, 0);
295f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    {
2964e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        int x = left;
297f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        int m[9];
29884f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[4] = PixelFetcher::Fetch(src, x,     y,     srcBounds);
29984f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[5] = PixelFetcher::Fetch(src, x + 1, y,     srcBounds);
30084f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[7] = PixelFetcher::Fetch(src, x,     y + 1, srcBounds);
30184f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds);
302f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
303b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight,
304b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
3054e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        for (++x; x < right - 1; ++x)
306f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        {
307f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            shiftMatrixLeft(m);
30884f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            m[5] = PixelFetcher::Fetch(src, x + 1, y,     srcBounds);
30984f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds);
3104e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org            surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
311b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight,
312b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         l->lightColor(surfaceToLight));
313f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        }
314f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        shiftMatrixLeft(m);
315f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
316b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight,
317b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
318f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
319f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
3204e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    for (++y; y < bottom - 1; ++y) {
3214e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        int x = left;
322f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        int m[9];
32384f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[1] = PixelFetcher::Fetch(src, x,     y - 1, srcBounds);
32484f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[2] = PixelFetcher::Fetch(src, x + 1, y - 1, srcBounds);
32584f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[4] = PixelFetcher::Fetch(src, x,     y,     srcBounds);
32684f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[5] = PixelFetcher::Fetch(src, x + 1, y,     srcBounds);
32784f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[7] = PixelFetcher::Fetch(src, x,     y + 1, srcBounds);
32884f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds);
329f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
330b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight,
331b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
3324e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        for (++x; x < right - 1; ++x) {
333f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            shiftMatrixLeft(m);
33484f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            m[2] = PixelFetcher::Fetch(src, x + 1, y - 1, srcBounds);
33584f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            m[5] = PixelFetcher::Fetch(src, x + 1, y,     srcBounds);
33684f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            m[8] = PixelFetcher::Fetch(src, x + 1, y + 1, srcBounds);
337f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
338b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight,
339b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         l->lightColor(surfaceToLight));
340f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        }
341f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        shiftMatrixLeft(m);
342f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
343b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight,
344b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
345f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
346f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
347f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    {
3484e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        int x = left;
349f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        int m[9];
35084f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[1] = PixelFetcher::Fetch(src, x,     bottom - 2, srcBounds);
35184f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[2] = PixelFetcher::Fetch(src, x + 1, bottom - 2, srcBounds);
35284f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[4] = PixelFetcher::Fetch(src, x,     bottom - 1, srcBounds);
35384f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco        m[5] = PixelFetcher::Fetch(src, x + 1, bottom - 1, srcBounds);
354f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
355b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight,
356b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
3574e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        for (++x; x < right - 1; ++x)
358f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        {
359f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            shiftMatrixLeft(m);
36084f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            m[2] = PixelFetcher::Fetch(src, x + 1, bottom - 2, srcBounds);
36184f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            m[5] = PixelFetcher::Fetch(src, x + 1, bottom - 1, srcBounds);
362f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org            surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
363b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight,
364b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                         l->lightColor(surfaceToLight));
365f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        }
366f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        shiftMatrixLeft(m);
367f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
368b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight,
369b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                     l->lightColor(surfaceToLight));
370f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
371f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
372f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
3730c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reedstatic void lightBitmap(const BaseLightingType& lightingType,
37484f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco                 const SkImageFilterLight* light,
37584f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco                 const SkBitmap& src,
37684f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco                 SkBitmap* dst,
37784f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco                 SkScalar surfaceScale,
37884f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco                 const SkIRect& bounds) {
37984f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco    if (src.bounds().contains(bounds)) {
3800c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed        lightBitmap<UncheckedPixelFetcher>(
38184f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            lightingType, light, src, dst, surfaceScale, bounds);
38284f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco    } else {
3830c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed        lightBitmap<DecalPixelFetcher>(
38484f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco            lightingType, light, src, dst, surfaceScale, bounds);
38584f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco    }
38684f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco}
38784f0e745839a0cb5ff5055f5ea0726bdd83b920bsenorblanco
388d0d37cace08f12abf8d316e6949e947551d418e6senorblancoenum BoundaryMode {
389d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kTopLeft_BoundaryMode,
390d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kTop_BoundaryMode,
391d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kTopRight_BoundaryMode,
392d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kLeft_BoundaryMode,
393d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kInterior_BoundaryMode,
394d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kRight_BoundaryMode,
395d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kBottomLeft_BoundaryMode,
396d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kBottom_BoundaryMode,
397d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kBottomRight_BoundaryMode,
398d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
399d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    kBoundaryModeCount,
400d0d37cace08f12abf8d316e6949e947551d418e6senorblanco};
401d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
402d0d37cace08f12abf8d316e6949e947551d418e6senorblancoclass SkLightingImageFilterInternal : public SkLightingImageFilter {
403d0d37cace08f12abf8d316e6949e947551d418e6senorblancoprotected:
40412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    SkLightingImageFilterInternal(sk_sp<SkImageFilterLight> light,
405d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                  SkScalar surfaceScale,
40612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                  sk_sp<SkImageFilter> input,
407d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                  const CropRect* cropRect)
40812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips        : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect) {
40912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    }
410d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
411d0d37cace08f12abf8d316e6949e947551d418e6senorblanco#if SK_SUPPORT_GPU
412fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    sk_sp<SkSpecialImage> filterImageGPU(SkSpecialImage* source,
413ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                         SkSpecialImage* input,
414ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                         const SkIRect& bounds,
4152a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                                         const SkMatrix& matrix,
4162a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                                         const OutputProperties& outputProperties) const;
417aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon    virtual std::unique_ptr<GrFragmentProcessor> makeFragmentProcessor(
418aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon            sk_sp<GrTextureProxy>,
419aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon            const SkMatrix&,
420aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon            const SkIRect* srcBounds,
421aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon            BoundaryMode boundaryMode) const = 0;
422d0d37cace08f12abf8d316e6949e947551d418e6senorblanco#endif
423d0d37cace08f12abf8d316e6949e947551d418e6senorblancoprivate:
424d0d37cace08f12abf8d316e6949e947551d418e6senorblanco#if SK_SUPPORT_GPU
425296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    void drawRect(GrRenderTargetContext*,
4268e1c4e672553ecae2745168514240705f3516773Robert Phillips                  sk_sp<GrTextureProxy> srcProxy,
427d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                  const SkMatrix& matrix,
428d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                  const GrClip& clip,
429d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                  const SkRect& dstRect,
430d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                  BoundaryMode boundaryMode,
4319bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                  const SkIRect* srcBounds,
432d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                  const SkIRect& bounds) const;
433d0d37cace08f12abf8d316e6949e947551d418e6senorblanco#endif
434d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    typedef SkLightingImageFilter INHERITED;
435d0d37cace08f12abf8d316e6949e947551d418e6senorblanco};
436d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
437d0d37cace08f12abf8d316e6949e947551d418e6senorblanco#if SK_SUPPORT_GPU
438296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillipsvoid SkLightingImageFilterInternal::drawRect(GrRenderTargetContext* renderTargetContext,
4398e1c4e672553ecae2745168514240705f3516773Robert Phillips                                             sk_sp<GrTextureProxy> srcProxy,
440d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                             const SkMatrix& matrix,
441d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                             const GrClip& clip,
442d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                             const SkRect& dstRect,
443d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                             BoundaryMode boundaryMode,
4449bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                             const SkIRect* srcBounds,
445d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                             const SkIRect& bounds) const {
446d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
447d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    GrPaint paint;
448f3569f0f6d312570c7344b345f8b3a03a892f751Brian Salomon    paint.setGammaCorrect(renderTargetContext->colorSpaceInfo().isGammaCorrect());
449aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon    auto fp = this->makeFragmentProcessor(std::move(srcProxy), matrix, srcBounds, boundaryMode);
45006ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    paint.addColorFragmentProcessor(std::move(fp));
451374772bd61951f01bf84fe17bf53d8867681c9aereed    paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
45282f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon    renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
45382f44319159bb98dcacdbbec7ea643dde5ed024bBrian Salomon                                        srcRect);
454d0d37cace08f12abf8d316e6949e947551d418e6senorblanco}
455d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
4562a75e5df300a2838f943ca52a52a85a5cf69802bbrianosmansk_sp<SkSpecialImage> SkLightingImageFilterInternal::filterImageGPU(
4572a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                                                   SkSpecialImage* source,
4582a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                                                   SkSpecialImage* input,
4592a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                                                   const SkIRect& offsetBounds,
4602a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                                                   const SkMatrix& matrix,
4612a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman                                                   const OutputProperties& outputProperties) const {
462ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    SkASSERT(source->isTextureBacked());
463ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
464ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    GrContext* context = source->getContext();
465ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
4668e1c4e672553ecae2745168514240705f3516773Robert Phillips    sk_sp<GrTextureProxy> inputProxy(input->asTextureProxyRef(context));
4678e1c4e672553ecae2745168514240705f3516773Robert Phillips    SkASSERT(inputProxy);
468d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
4697f6cd90f0c8f6e8dd658cb1b1c587b833adfc364Robert Phillips    sk_sp<GrRenderTargetContext> renderTargetContext(context->makeDeferredRenderTargetContext(
4707f6cd90f0c8f6e8dd658cb1b1c587b833adfc364Robert Phillips                                SkBackingFit::kApprox, offsetBounds.width(), offsetBounds.height(),
4717f6cd90f0c8f6e8dd658cb1b1c587b833adfc364Robert Phillips                                GrRenderableConfigForColorSpace(outputProperties.colorSpace()),
4727f6cd90f0c8f6e8dd658cb1b1c587b833adfc364Robert Phillips                                sk_ref_sp(outputProperties.colorSpace())));
4731105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman    if (!renderTargetContext) {
474ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
475d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    }
476d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
477846c051a4800b3cea341a0195db24297d6d9047fcdalton    SkIRect dstIRect = SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height());
478846c051a4800b3cea341a0195db24297d6d9047fcdalton    SkRect dstRect = SkRect::Make(dstIRect);
479ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
480d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    // setup new clip
481846c051a4800b3cea341a0195db24297d6d9047fcdalton    GrFixedClip clip(dstIRect);
482d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
483ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    const SkIRect inputBounds = SkIRect::MakeWH(input->width(), input->height());
484d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1);
485d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect top = SkRect::MakeXYWH(1, 0, dstRect.width() - 2, 1);
486d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect topRight = SkRect::MakeXYWH(dstRect.width() - 1, 0, 1, 1);
487d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect left = SkRect::MakeXYWH(0, 1, 1, dstRect.height() - 2);
488d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect interior = dstRect.makeInset(1, 1);
489d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect right = SkRect::MakeXYWH(dstRect.width() - 1, 1, 1, dstRect.height() - 2);
490d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect bottomLeft = SkRect::MakeXYWH(0, dstRect.height() - 1, 1, 1);
491d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect bottom = SkRect::MakeXYWH(1, dstRect.height() - 1, dstRect.width() - 2, 1);
492d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1);
493ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips
494ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    const SkIRect* pSrcBounds = inputBounds.contains(offsetBounds) ? nullptr : &inputBounds;
495296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, topLeft,
496ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                   kTopLeft_BoundaryMode, pSrcBounds, offsetBounds);
497296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, top,
4981105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman                   kTop_BoundaryMode, pSrcBounds, offsetBounds);
499296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, topRight,
500ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                   kTopRight_BoundaryMode, pSrcBounds, offsetBounds);
501296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, left,
5021105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman                   kLeft_BoundaryMode, pSrcBounds, offsetBounds);
503296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, interior,
504ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                   kInterior_BoundaryMode, pSrcBounds, offsetBounds);
505296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, right,
5061105224f9701e57ec5ce0354d6a380b664f5c638Brian Osman                   kRight_BoundaryMode, pSrcBounds, offsetBounds);
507296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, bottomLeft,
508ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                   kBottomLeft_BoundaryMode, pSrcBounds, offsetBounds);
509296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, bottom,
510ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                   kBottom_BoundaryMode, pSrcBounds, offsetBounds);
511296b1ccf9b8e9c8b945645efcbaa9c71c7135f58Robert Phillips    this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, bottomRight,
512ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                   kBottomRight_BoundaryMode, pSrcBounds, offsetBounds);
513ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
5147f6cd90f0c8f6e8dd658cb1b1c587b833adfc364Robert Phillips    return SkSpecialImage::MakeDeferredFromGpu(
515f3569f0f6d312570c7344b345f8b3a03a892f751Brian Salomon            context,
516f3569f0f6d312570c7344b345f8b3a03a892f751Brian Salomon            SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height()),
517f3569f0f6d312570c7344b345f8b3a03a892f751Brian Salomon            kNeedNewImageUniqueID_SpecialImage,
518f3569f0f6d312570c7344b345f8b3a03a892f751Brian Salomon            renderTargetContext->asTextureProxyRef(),
519f3569f0f6d312570c7344b345f8b3a03a892f751Brian Salomon            renderTargetContext->colorSpaceInfo().refColorSpace());
520d0d37cace08f12abf8d316e6949e947551d418e6senorblanco}
521d0d37cace08f12abf8d316e6949e947551d418e6senorblanco#endif
522d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
523d0d37cace08f12abf8d316e6949e947551d418e6senorblancoclass SkDiffuseLightingImageFilter : public SkLightingImageFilterInternal {
524f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
52512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilterLight> light,
52612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                     SkScalar surfaceScale,
52712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                     SkScalar kd,
52812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                     sk_sp<SkImageFilter>,
52912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                     const CropRect*);
5309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
531f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    SK_TO_STRING_OVERRIDE()
532f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
533bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkScalar kd() const { return fKD; }
534bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org
535f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprotected:
53612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light, SkScalar surfaceScale,
53712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                 SkScalar kd,
53812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                 sk_sp<SkImageFilter> input, const CropRect* cropRect);
53936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer& buffer) const override;
540ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
541ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
542ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                        SkIPoint* offset) const override;
54362745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
544ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
5451aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org#if SK_SUPPORT_GPU
546aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon    std::unique_ptr<GrFragmentProcessor> makeFragmentProcessor(sk_sp<GrTextureProxy>,
547aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                               const SkMatrix&,
548aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                               const SkIRect* bounds,
549aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                               BoundaryMode) const override;
5501aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org#endif
551f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
552f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
5539fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    friend class SkLightingImageFilter;
554f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fKD;
555ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
556ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    typedef SkLightingImageFilterInternal INHERITED;
557f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
558f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
559d0d37cace08f12abf8d316e6949e947551d418e6senorblancoclass SkSpecularLightingImageFilter : public SkLightingImageFilterInternal {
560f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
56112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilterLight> light,
56212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                     SkScalar surfaceScale,
56312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                     SkScalar ks, SkScalar shininess,
56412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                     sk_sp<SkImageFilter>, const CropRect*);
5659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
566f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    SK_TO_STRING_OVERRIDE()
567f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
568f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
569894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar ks() const { return fKS; }
570894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar shininess() const { return fShininess; }
571894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
572f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprotected:
57312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,
57412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                  SkScalar surfaceScale, SkScalar ks,
57512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                  SkScalar shininess,
57612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                  sk_sp<SkImageFilter> input, const CropRect*);
57736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer& buffer) const override;
578ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
579ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
580ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                        SkIPoint* offset) const override;
58162745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
582ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
5831aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org#if SK_SUPPORT_GPU
584aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon    std::unique_ptr<GrFragmentProcessor> makeFragmentProcessor(sk_sp<GrTextureProxy>,
585aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                               const SkMatrix&,
586aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                               const SkIRect* bounds,
587aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                               BoundaryMode) const override;
5881aa68723b8ef4ce0b6db9fe51e7d8051cdd543ffsenorblanco@chromium.org#endif
589f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
590f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
591f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fKS;
592f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fShininess;
5939fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    friend class SkLightingImageFilter;
594d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    typedef SkLightingImageFilterInternal INHERITED;
595f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
596f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
597cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
598894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
5996cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomonclass GrLightingEffect : public GrFragmentProcessor {
600894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
6016b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    const SkImageFilterLight* light() const { return fLight.get(); }
602894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar surfaceScale() const { return fSurfaceScale; }
603fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    const SkMatrix& filterMatrix() const { return fFilterMatrix; }
604d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    BoundaryMode boundaryMode() const { return fBoundaryMode; }
6059bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco    const GrTextureDomain& domain() const { return fDomain; }
606371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com
607b4b7a4c9ea2e399db550f93e3754c351e5b2079arobertphillipsprotected:
608abff956455637b12eab374fd44b99e1338799113Ethan Nicholas    GrLightingEffect(ClassID classID, sk_sp<GrTextureProxy>, sk_sp<const SkImageFilterLight> light,
6096b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                     SkScalar surfaceScale, const SkMatrix& matrix, BoundaryMode boundaryMode,
6106b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                     const SkIRect* srcBounds);
6116b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon
6126b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    GrLightingEffect(const GrLightingEffect& that);
613b4b7a4c9ea2e399db550f93e3754c351e5b2079arobertphillips
6141c9686bfa5e2de3e06f1d1b9691105afb6659e85Robert Phillips    bool onIsEqual(const GrFragmentProcessor&) const override;
6151a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel
616894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
6176cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon    GrCoordTransform fCoordTransform;
6186cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon    GrTextureDomain fDomain;
6196cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon    TextureSampler fTextureSampler;
6206b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    sk_sp<const SkImageFilterLight> fLight;
621894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar fSurfaceScale;
622fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkMatrix fFilterMatrix;
623d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    BoundaryMode fBoundaryMode;
6242f0dbc761a626473c19db7de561c7072b12953c5robertphillips
6256cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon    typedef GrFragmentProcessor INHERITED;
626894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
627894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
628894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrDiffuseLightingEffect : public GrLightingEffect {
629894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
630aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon    static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
631aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     sk_sp<const SkImageFilterLight> light,
632aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     SkScalar surfaceScale,
633aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     const SkMatrix& matrix,
634aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     SkScalar kd,
635aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     BoundaryMode boundaryMode,
636aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     const SkIRect* srcBounds) {
637aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        return std::unique_ptr<GrFragmentProcessor>(
6386b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                new GrDiffuseLightingEffect(std::move(proxy), std::move(light), surfaceScale,
6396b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                                            matrix, kd, boundaryMode, srcBounds));
6400ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    }
641894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
64236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const char* name() const override { return "DiffuseLighting"; }
643eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
644aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon    std::unique_ptr<GrFragmentProcessor> clone() const override {
645aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        return std::unique_ptr<GrFragmentProcessor>(new GrDiffuseLightingEffect(*this));
6466b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    }
6476b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon
648894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar kd() const { return fKD; }
64968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
650894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
65157d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
652b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix
65394efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
6544b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix
65536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onIsEqual(const GrFragmentProcessor&) const override;
65668b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
657fbcef6eb8abad142daf45418516550f7635b4a52Robert Phillips    GrDiffuseLightingEffect(sk_sp<GrTextureProxy>,
6586b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                            sk_sp<const SkImageFilterLight> light,
6590ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                            SkScalar surfaceScale,
660fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                            const SkMatrix& matrix,
661d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                            SkScalar kd,
6629bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                            BoundaryMode boundaryMode,
6639bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                            const SkIRect* srcBounds);
6640ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
6656b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    explicit GrDiffuseLightingEffect(const GrDiffuseLightingEffect& that);
6666b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon
6670c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
668696b29346e85307a05af47768d358161eba3f6bdRobert Phillips    SkScalar fKD;
6698e1c4e672553ecae2745168514240705f3516773Robert Phillips
6708e1c4e672553ecae2745168514240705f3516773Robert Phillips    typedef GrLightingEffect INHERITED;
671894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
672894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
673894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrSpecularLightingEffect : public GrLightingEffect {
674894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
675aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon    static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
676aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     sk_sp<const SkImageFilterLight> light,
677aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     SkScalar surfaceScale,
678aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     const SkMatrix& matrix,
679aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     SkScalar ks,
680aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     SkScalar shininess,
681aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     BoundaryMode boundaryMode,
682aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon                                                     const SkIRect* srcBounds) {
683aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        return std::unique_ptr<GrFragmentProcessor>(
6846b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                new GrSpecularLightingEffect(std::move(proxy), std::move(light), surfaceScale,
6856b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                                             matrix, ks, shininess, boundaryMode, srcBounds));
6860ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com    }
687894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
68836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    const char* name() const override { return "SpecularLighting"; }
689eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
690aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon    std::unique_ptr<GrFragmentProcessor> clone() const override {
691aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        return std::unique_ptr<GrFragmentProcessor>(new GrSpecularLightingEffect(*this));
6926b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    }
6936b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon
69457d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
695894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
696894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar ks() const { return fKS; }
697894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar shininess() const { return fShininess; }
698894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
699894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
70094efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
7014b3050b410254d0cb38df9a30ae2e209124fa1a2wangyix
70236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    bool onIsEqual(const GrFragmentProcessor&) const override;
70368b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
704fbcef6eb8abad142daf45418516550f7635b4a52Robert Phillips    GrSpecularLightingEffect(sk_sp<GrTextureProxy>,
7056b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                             sk_sp<const SkImageFilterLight> light,
7060ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                             SkScalar surfaceScale,
707fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                             const SkMatrix& matrix,
7080ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com                             SkScalar ks,
709d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                             SkScalar shininess,
7109bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                             BoundaryMode boundaryMode,
7119bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                             const SkIRect* srcBounds);
7120ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
7136b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    explicit GrSpecularLightingEffect(const GrSpecularLightingEffect&);
7146b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon
7150c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon    GR_DECLARE_FRAGMENT_PROCESSOR_TEST
716894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar fKS;
717894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar fShininess;
7188e1c4e672553ecae2745168514240705f3516773Robert Phillips
7198e1c4e672553ecae2745168514240705f3516773Robert Phillips    typedef GrLightingEffect INHERITED;
720894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
721894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
722894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
723894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
724894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLLight {
725894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
7266730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org    virtual ~GrGLLight() {}
727894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
728ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    /**
729ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
730f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas     * below. It adds a half3 uniform visible in the FS that represents the constant light color.
731ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     */
7327ea439b2203855db97330b25945b87dd4b170b8begdaniel    void emitLightColorUniform(GrGLSLUniformHandler*);
733ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
734e862d16162fd46ad9b2832c8844b00c81bedbac0skia.committer@gmail.com    /**
735ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * These two functions are called from GrGLLightingEffect's emitCode() function.
736ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * emitSurfaceToLight places an expression in param out that is the vector from the surface to
737ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * the light. The expression will be used in the FS. emitLightColor writes an expression into
738ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * the FS that is the color of the light. Either function may add functions and/or uniforms to
739ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * the FS. The default of emitLightColor appends the name of the constant light color uniform
740ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * and so this function only needs to be overridden if the light color varies spatially.
741ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     */
7427ea439b2203855db97330b25945b87dd4b170b8begdaniel    virtual void emitSurfaceToLight(GrGLSLUniformHandler*,
7438528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                                    GrGLSLFPFragmentBuilder*,
7447ea439b2203855db97330b25945b87dd4b170b8begdaniel                                    const char* z) = 0;
7457ea439b2203855db97330b25945b87dd4b170b8begdaniel    virtual void emitLightColor(GrGLSLUniformHandler*,
7468528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                                GrGLSLFPFragmentBuilder*,
7474ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                const char *surfaceToLight);
748ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
749ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
750ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    // INHERITED::setData().
751018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    virtual void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const;
752894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
753894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprotected:
754ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    /**
755ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
756ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     * function.
757ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     */
758ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    UniformHandle lightColorUni() const { return fColorUni; }
759ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
760ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.comprivate:
761032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle fColorUni;
762ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
763ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    typedef SkRefCnt INHERITED;
764894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
765894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
766894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
767894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
768894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLDistantLight : public GrGLLight {
769894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
770d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~GrGLDistantLight() override {}
771018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
7728528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton    void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
7738d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
774894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
775894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLight INHERITED;
776032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle fDirectionUni;
777894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
778894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
779894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
780894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
781894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLPointLight : public GrGLLight {
782894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
783d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~GrGLPointLight() override {}
784018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
7858528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton    void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
7868d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
787894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
788894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLight INHERITED;
789032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle fLocationUni;
790894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
791894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
792894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
793894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
794894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLSpotLight : public GrGLLight {
795894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
796d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~GrGLSpotLight() override {}
797018fb62d12d1febf121fe265da5b6117b86a6541egdaniel    void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
7988528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton    void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
7997ea439b2203855db97330b25945b87dd4b170b8begdaniel    void emitLightColor(GrGLSLUniformHandler*,
8008528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                        GrGLSLFPFragmentBuilder*,
8014ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                        const char *surfaceToLight) override;
8028d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
803894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
804894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLight INHERITED;
805894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
806a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString        fLightColorFunc;
807032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fLocationUni;
808032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fExponentUni;
809032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fCosOuterConeAngleUni;
810032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fCosInnerConeAngleUni;
811032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fConeScaleUni;
812032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fSUni;
813894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
814cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
815cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
816cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.comclass GrGLLight;
817cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
818cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
819894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
820894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
821894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
822894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
823894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
82462745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic SkColor xform_color(const SkPoint3& color, SkColorSpaceXformer* xformer) {
82562745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    SkColor origColor = SkColorSetARGBInline(0xFF,
82662745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett                                             SkScalarRoundToInt(color.fX),
82762745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett                                             SkScalarRoundToInt(color.fY),
82862745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett                                             SkScalarRoundToInt(color.fZ));
82962745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    return xformer->apply(origColor);
83062745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett}
83162745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett
8322f0dbc761a626473c19db7de561c7072b12953c5robertphillipsclass SkDistantLight : public SkImageFilterLight {
833f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
834bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkDistantLight(const SkPoint3& direction, SkColor color)
835bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org      : INHERITED(color), fDirection(direction) {
836f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
8370833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
8380c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
839f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return fDirection;
840fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    }
8410c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
84236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    LightType type() const override { return kDistant_LightType; }
843894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPoint3& direction() const { return fDirection; }
84436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    GrGLLight* createGLLight() const override {
845cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
846385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return new GrGLDistantLight;
847cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
848cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        SkDEBUGFAIL("Should not call in GPU-less build");
84996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
850cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
851cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com    }
8528d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
85362745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer* xformer) const override {
85462745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett        return sk_make_sp<SkDistantLight>(fDirection, xform_color(this->color(), xformer));
85562745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    }
85662745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett
8572f0dbc761a626473c19db7de561c7072b12953c5robertphillips    bool isEqual(const SkImageFilterLight& other) const override {
8586730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org        if (other.type() != kDistant_LightType) {
8596730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org            return false;
8606730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org        }
8616730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org
8626730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org        const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
8636730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org        return INHERITED::isEqual(other) &&
8646730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org               fDirection == o.fDirection;
8656730cbb80a2366c1333f48b7cd0397daed337a8bsenorblanco@chromium.org    }
866f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
8678b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
868959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        fDirection = read_point3(buffer);
869790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    }
870f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
8710833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.comprotected:
872fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
873fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org      : INHERITED(color), fDirection(direction) {
874fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
8752f0dbc761a626473c19db7de561c7072b12953c5robertphillips    SkImageFilterLight* transform(const SkMatrix& matrix) const override {
876fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        return new SkDistantLight(direction(), color());
877fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
87836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onFlattenLight(SkWriteBuffer& buffer) const override {
879959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        write_point3(fDirection, buffer);
8800833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
8810833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
882f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
883f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fDirection;
8842f0dbc761a626473c19db7de561c7072b12953c5robertphillips
8852f0dbc761a626473c19db7de561c7072b12953c5robertphillips    typedef SkImageFilterLight INHERITED;
886f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
887f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
888894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
889894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
8902f0dbc761a626473c19db7de561c7072b12953c5robertphillipsclass SkPointLight : public SkImageFilterLight {
891f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
892bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org    SkPointLight(const SkPoint3& location, SkColor color)
893bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org     : INHERITED(color), fLocation(location) {}
8940833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
8950c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
8963d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
8973d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips                                            fLocation.fY - SkIntToScalar(y),
8988be952ad8c9deefe19cff36f9ad217563400f817Mike Reed                                            fLocation.fZ - SkIntToScalar(z) * surfaceScale);
899992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth        fast_normalize(&direction);
900f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return direction;
901fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    }
9020c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
90336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    LightType type() const override { return kPoint_LightType; }
904894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPoint3& location() const { return fLocation; }
90536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    GrGLLight* createGLLight() const override {
906cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
907385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return new GrGLPointLight;
908cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
909cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        SkDEBUGFAIL("Should not call in GPU-less build");
91096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
911cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
912894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
91362745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett
91462745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer* xformer) const override {
91562745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett        return sk_make_sp<SkPointLight>(fLocation, xform_color(this->color(), xformer));
91662745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    }
91762745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett
9182f0dbc761a626473c19db7de561c7072b12953c5robertphillips    bool isEqual(const SkImageFilterLight& other) const override {
919894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        if (other.type() != kPoint_LightType) {
920894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org            return false;
921894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        }
922894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        const SkPointLight& o = static_cast<const SkPointLight&>(other);
923894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        return INHERITED::isEqual(other) &&
924894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fLocation == o.fLocation;
925894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
9262f0dbc761a626473c19db7de561c7072b12953c5robertphillips    SkImageFilterLight* transform(const SkMatrix& matrix) const override {
927fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
928fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        matrix.mapPoints(&location2, 1);
9291037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        // Use X scale and Y scale on Z and average the result
9301037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
9311037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        matrix.mapVectors(&locationZ, 1);
9329d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        SkPoint3 location = SkPoint3::Make(location2.fX,
9339d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                                           location2.fY,
9343d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips                                           SkScalarAve(locationZ.fX, locationZ.fY));
935fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        return new SkPointLight(location, color());
936fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
937f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
9388b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
939959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        fLocation = read_point3(buffer);
9400833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
941790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org
942790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.orgprotected:
943fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkPointLight(const SkPoint3& location, const SkPoint3& color)
944fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org     : INHERITED(color), fLocation(location) {}
94536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onFlattenLight(SkWriteBuffer& buffer) const override {
946959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        write_point3(fLocation, buffer);
9470833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
9480833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
949f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
950f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fLocation;
9512f0dbc761a626473c19db7de561c7072b12953c5robertphillips
9522f0dbc761a626473c19db7de561c7072b12953c5robertphillips    typedef SkImageFilterLight INHERITED;
953f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
954f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
955894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
956894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
9572f0dbc761a626473c19db7de561c7072b12953c5robertphillipsclass SkSpotLight : public SkImageFilterLight {
958f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgpublic:
959d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkSpotLight(const SkPoint3& location,
960d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                const SkPoint3& target,
961d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                SkScalar specularExponent,
962d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                SkScalar cutoffAngle,
963d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                SkColor color)
964bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org     : INHERITED(color),
965bdb1ec453a36b3e8e8800713aef0dce934e6a6a7senorblanco@chromium.org       fLocation(location),
966f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fTarget(target),
96762745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett       fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax)),
96862745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett       fCutoffAngle(cutoffAngle)
969f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    {
970f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fS = target - location;
971992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth       fast_normalize(&fS);
972f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
9734b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org       const SkScalar antiAliasThreshold = 0.016f;
974f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
975f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org       fConeScale = SkScalarInvert(antiAliasThreshold);
976f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
9770833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
97862745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer* xformer) const override {
97962745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett        return sk_make_sp<SkSpotLight>(fLocation, fTarget, fSpecularExponent, fCutoffAngle,
98062745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett                                       xform_color(this->color(), xformer));
98162745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    }
98262745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett
9832f0dbc761a626473c19db7de561c7072b12953c5robertphillips    SkImageFilterLight* transform(const SkMatrix& matrix) const override {
984fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
985fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        matrix.mapPoints(&location2, 1);
9861037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        // Use X scale and Y scale on Z and average the result
9871037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
9881037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        matrix.mapVectors(&locationZ, 1);
9893d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 location = SkPoint3::Make(location2.fX, location2.fY,
9903d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips                                           SkScalarAve(locationZ.fX, locationZ.fY));
991fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
992fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org        matrix.mapPoints(&target2, 1);
9931037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
9941037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        matrix.mapVectors(&targetZ, 1);
9953d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 target = SkPoint3::Make(target2.fX, target2.fY,
9963d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips                                         SkScalarAve(targetZ.fX, targetZ.fY));
9971037d92bbc10cafb61d050638e8cbe5a3aa6706fcommit-bot@chromium.org        SkPoint3 s = target - location;
998992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth        fast_normalize(&s);
999d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        return new SkSpotLight(location,
1000d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                               target,
1001d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                               fSpecularExponent,
1002d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                               fCosOuterConeAngle,
1003d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                               fCosInnerConeAngle,
1004d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                               fConeScale,
1005d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                               s,
1006d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                               color());
1007fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
1008fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org
10090c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
10103d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
10113d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips                                            fLocation.fY - SkIntToScalar(y),
10128be952ad8c9deefe19cff36f9ad217563400f817Mike Reed                                            fLocation.fZ - SkIntToScalar(z) * surfaceScale);
1013992c7612394a26e36ba355f6d8d3801d8d8f1260jvanverth        fast_normalize(&direction);
1014f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        return direction;
1015fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    }
10160c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    SkPoint3 lightColor(const SkPoint3& surfaceToLight) const override {
1017f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        SkScalar cosAngle = -surfaceToLight.dot(fS);
10183d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkScalar scale = 0;
10193d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        if (cosAngle >= fCosOuterConeAngle) {
10203d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips            scale = SkScalarPow(cosAngle, fSpecularExponent);
10213d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips            if (cosAngle < fCosInnerConeAngle) {
10228be952ad8c9deefe19cff36f9ad217563400f817Mike Reed                scale *= (cosAngle - fCosOuterConeAngle) * fConeScale;
10233d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips            }
1024f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org        }
10253d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return this->color().makeScale(scale);
1026f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
102736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    GrGLLight* createGLLight() const override {
1028cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
1029385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        return new GrGLSpotLight;
1030cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#else
1031cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com        SkDEBUGFAIL("Should not call in GPU-less build");
103296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1033cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
1034894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
103536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    LightType type() const override { return kSpot_LightType; }
1036894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPoint3& location() const { return fLocation; }
1037894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPoint3& target() const { return fTarget; }
1038894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar specularExponent() const { return fSpecularExponent; }
1039894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
1040894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
1041894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkScalar coneScale() const { return fConeScale; }
1042eb311845c1b412a9a7d851444a70ec24ab60fb2csenorblanco@chromium.org    const SkPoint3& s() const { return fS; }
10430833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
10448b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
1045959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        fLocation = read_point3(buffer);
1046959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        fTarget = read_point3(buffer);
10470833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fSpecularExponent = buffer.readScalar();
10480833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fCosOuterConeAngle = buffer.readScalar();
10490833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fCosInnerConeAngle = buffer.readScalar();
10500833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        fConeScale = buffer.readScalar();
1051959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        fS = read_point3(buffer);
1052c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
1053c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                        SkScalarIsFinite(fCosOuterConeAngle) &&
1054c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                        SkScalarIsFinite(fCosInnerConeAngle) &&
1055c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org                        SkScalarIsFinite(fConeScale));
10560833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
1057790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.orgprotected:
1058d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkSpotLight(const SkPoint3& location,
1059d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                const SkPoint3& target,
1060d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                SkScalar specularExponent,
1061d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                SkScalar cosOuterConeAngle,
1062d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                SkScalar cosInnerConeAngle,
1063d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                SkScalar coneScale,
1064d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                const SkPoint3& s,
1065d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                const SkPoint3& color)
1066fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org     : INHERITED(color),
1067fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fLocation(location),
1068fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fTarget(target),
1069fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fSpecularExponent(specularExponent),
1070fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fCosOuterConeAngle(cosOuterConeAngle),
1071fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fCosInnerConeAngle(cosInnerConeAngle),
1072fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fConeScale(coneScale),
1073fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org       fS(s)
1074fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    {
1075fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
107636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void onFlattenLight(SkWriteBuffer& buffer) const override {
1077959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        write_point3(fLocation, buffer);
1078959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        write_point3(fTarget, buffer);
10790833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        buffer.writeScalar(fSpecularExponent);
10800833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        buffer.writeScalar(fCosOuterConeAngle);
10810833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        buffer.writeScalar(fCosInnerConeAngle);
10820833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com        buffer.writeScalar(fConeScale);
1083959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips        write_point3(fS, buffer);
10840833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    }
10850833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com
10862f0dbc761a626473c19db7de561c7072b12953c5robertphillips    bool isEqual(const SkImageFilterLight& other) const override {
1087894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        if (other.type() != kSpot_LightType) {
1088894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org            return false;
1089894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        }
1090894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1091894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
1092894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        return INHERITED::isEqual(other) &&
1093894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fLocation == o.fLocation &&
1094894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fTarget == o.fTarget &&
1095894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fSpecularExponent == o.fSpecularExponent &&
1096894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org               fCosOuterConeAngle == o.fCosOuterConeAngle;
1097894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
1098894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1099f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.orgprivate:
11000bccd8749bdce79b2d71518fe65783b1a9b06445caryclark    static const SkScalar kSpecularExponentMin;
11010bccd8749bdce79b2d71518fe65783b1a9b06445caryclark    static const SkScalar kSpecularExponentMax;
11020bccd8749bdce79b2d71518fe65783b1a9b06445caryclark
1103f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fLocation;
1104f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fTarget;
1105f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fSpecularExponent;
110662745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    SkScalar fCutoffAngle;
1107f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fCosOuterConeAngle;
1108f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fCosInnerConeAngle;
1109f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkScalar fConeScale;
1110f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SkPoint3 fS;
11112f0dbc761a626473c19db7de561c7072b12953c5robertphillips
11122f0dbc761a626473c19db7de561c7072b12953c5robertphillips    typedef SkImageFilterLight INHERITED;
1113f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org};
1114f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
11150bccd8749bdce79b2d71518fe65783b1a9b06445caryclark// According to the spec, the specular term should be in the range [1, 128] :
11160bccd8749bdce79b2d71518fe65783b1a9b06445caryclark// http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute
11170bccd8749bdce79b2d71518fe65783b1a9b06445caryclarkconst SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
11180bccd8749bdce79b2d71518fe65783b1a9b06445caryclarkconst SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
11190bccd8749bdce79b2d71518fe65783b1a9b06445caryclark
1120894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1121894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
11222f0dbc761a626473c19db7de561c7072b12953c5robertphillipsvoid SkImageFilterLight::flattenLight(SkWriteBuffer& buffer) const {
1123790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    // Write type first, then baseclass, then subclass.
1124790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    buffer.writeInt(this->type());
1125959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips    write_point3(fColor, buffer);
1126790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    this->onFlattenLight(buffer);
1127790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org}
1128790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org
11292f0dbc761a626473c19db7de561c7072b12953c5robertphillips/*static*/ SkImageFilterLight* SkImageFilterLight::UnflattenLight(SkReadBuffer& buffer) {
1130de5c50268c3ff0af507c0a9b47ab58809b89867cMike Reed    SkImageFilterLight::LightType type = buffer.read32LE(SkImageFilterLight::kLast_LightType);
1131959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips
1132790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    switch (type) {
1133790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        // Each of these constructors must first call SkLight's, so we'll read the baseclass
1134790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        // then subclass, same order as flattenLight.
1135385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        case SkImageFilterLight::kDistant_LightType:
1136385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            return new SkDistantLight(buffer);
1137385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        case SkImageFilterLight::kPoint_LightType:
1138385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            return new SkPointLight(buffer);
1139385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        case SkImageFilterLight::kSpot_LightType:
1140385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            return new SkSpotLight(buffer);
1141790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org        default:
1142959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips            // Should never get here due to prior check of SkSafeRange
1143790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org            SkDEBUGFAIL("Unknown LightType.");
114496fcdcc219d2a0d3579719b84b28bede76efba64halcanary            return nullptr;
1145790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    }
1146790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org}
1147790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
1148790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org
114912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipsSkLightingImageFilter::SkLightingImageFilter(sk_sp<SkImageFilterLight> light,
115012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                             SkScalar surfaceScale,
115112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                             sk_sp<SkImageFilter> input, const CropRect* cropRect)
115212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    : INHERITED(&input, 1, cropRect)
115312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    , fLight(std::move(light))
115412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    , fSurfaceScale(surfaceScale / 255) {
1155f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1156f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
115782b043e87380a64ea4ca736b293ec0ee5c30e676robertphillipsSkLightingImageFilter::~SkLightingImageFilter() {}
115882b043e87380a64ea4ca736b293ec0ee5c30e676robertphillips
115912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipssk_sp<SkImageFilter> SkLightingImageFilter::MakeDistantLitDiffuse(const SkPoint3& direction,
116012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                  SkColor lightColor,
116112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                  SkScalar surfaceScale,
116212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                  SkScalar kd,
116312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                  sk_sp<SkImageFilter> input,
116412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                  const CropRect* cropRect) {
116512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1166fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
116712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                              std::move(input), cropRect);
1168f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1169f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
117012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipssk_sp<SkImageFilter> SkLightingImageFilter::MakePointLitDiffuse(const SkPoint3& location,
117112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                SkColor lightColor,
117212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                SkScalar surfaceScale,
117312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                SkScalar kd,
117412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                sk_sp<SkImageFilter> input,
117512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                const CropRect* cropRect) {
117612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
117712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
117812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                              std::move(input), cropRect);
1179f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1180f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
118112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipssk_sp<SkImageFilter> SkLightingImageFilter::MakeSpotLitDiffuse(const SkPoint3& location,
118212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                               const SkPoint3& target,
118312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                               SkScalar specularExponent,
118412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                               SkScalar cutoffAngle,
11859fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                               SkColor lightColor,
11869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                               SkScalar surfaceScale,
118712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                               SkScalar kd,
118812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                               sk_sp<SkImageFilter> input,
11899fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                                                               const CropRect* cropRect) {
119012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    sk_sp<SkImageFilterLight> light(
119112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
119212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
119312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                              std::move(input), cropRect);
1194f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1195f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
119612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipssk_sp<SkImageFilter> SkLightingImageFilter::MakeDistantLitSpecular(const SkPoint3& direction,
119712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                   SkColor lightColor,
119812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                   SkScalar surfaceScale,
119912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                   SkScalar ks,
120012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                   SkScalar shine,
120112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                   sk_sp<SkImageFilter> input,
120212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                   const CropRect* cropRect) {
120312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
120412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shine,
120512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                               std::move(input), cropRect);
1206f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1207f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
120812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipssk_sp<SkImageFilter> SkLightingImageFilter::MakePointLitSpecular(const SkPoint3& location,
120912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                 SkColor lightColor,
121012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                 SkScalar surfaceScale,
121112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                 SkScalar ks,
121212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                 SkScalar shine,
121312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                 sk_sp<SkImageFilter> input,
121412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                 const CropRect* cropRect) {
121512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
121612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shine,
121712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                               std::move(input), cropRect);
1218f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1219f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
122012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipssk_sp<SkImageFilter> SkLightingImageFilter::MakeSpotLitSpecular(const SkPoint3& location,
122112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                const SkPoint3& target,
122212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                SkScalar specularExponent,
122312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                SkScalar cutoffAngle,
122412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                SkColor lightColor,
122512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                SkScalar surfaceScale,
122612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                SkScalar ks,
122712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                SkScalar shine,
122812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                sk_sp<SkImageFilter> input,
122912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                const CropRect* cropRect) {
123012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    sk_sp<SkImageFilterLight> light(
123112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips            new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
123212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shine,
123312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                               std::move(input), cropRect);
123412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips}
1235f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
12368b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1237f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    this->INHERITED::flatten(buffer);
1238790c3f4e095c57b1e2412a46e7d71f28babf07c8commit-bot@chromium.org    fLight->flattenLight(buffer);
12399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.writeScalar(fSurfaceScale * 255);
1240f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1241f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
12426b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomonsk_sp<const SkImageFilterLight> SkLightingImageFilter::refLight() const { return fLight; }
12436b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon
1244894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1245894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
124612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipssk_sp<SkImageFilter> SkDiffuseLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
124712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                        SkScalar surfaceScale,
124812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                        SkScalar kd,
124912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                        sk_sp<SkImageFilter> input,
125012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                        const CropRect* cropRect) {
125112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    if (!light) {
125296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
12539fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
12549fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) {
125596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
12569fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
1257ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    // According to the spec, kd can be any non-negative number :
1258ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
12599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (kd < 0) {
126096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
12619fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
1262fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein    return sk_sp<SkImageFilter>(new SkDiffuseLightingImageFilter(std::move(light), surfaceScale,
126312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                 kd, std::move(input), cropRect));
12649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
12659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
126612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipsSkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light,
1267d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                           SkScalar surfaceScale,
1268d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                           SkScalar kd,
126912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                           sk_sp<SkImageFilter> input,
1270d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                           const CropRect* cropRect)
127112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
127212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    , fKD(kd) {
1273f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1274f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
127560c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
12769fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1277959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips
127812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
12799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar surfaceScale = buffer.readScalar();
12809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar kd = buffer.readScalar();
1281959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips
128212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    return Make(std::move(light), surfaceScale, kd, common.getInput(0), &common.cropRect());
12839fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
1284f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
12858b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1286f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    this->INHERITED::flatten(buffer);
1287f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    buffer.writeScalar(fKD);
1288f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1289f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
1290ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillipssk_sp<SkSpecialImage> SkDiffuseLightingImageFilter::onFilterImage(SkSpecialImage* source,
1291ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                                  const Context& ctx,
1292ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                                  SkIPoint* offset) const {
1293ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    SkIPoint inputOffset = SkIPoint::Make(0, 0);
1294ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
1295ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!input) {
1296ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1297a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org    }
1298a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org
1299ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1300ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                  input->width(), input->height());
1301118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect bounds;
1302ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1303ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1304ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    }
1305ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1306ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    offset->fX = bounds.left();
1307ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    offset->fY = bounds.top();
1308ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    bounds.offset(-inputOffset);
1309ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1310ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips#if SK_SUPPORT_GPU
1311ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (source->isTextureBacked()) {
1312ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        SkMatrix matrix(ctx.ctm());
1313ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1314ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
13152a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        return this->filterImageGPU(source, input.get(), bounds, matrix, ctx.outputProperties());
1316f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
1317ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips#endif
13184e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
1319118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (bounds.width() < 2 || bounds.height() < 2) {
1320ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1321ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    }
1322ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1323ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    SkBitmap inputBM;
1324ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1325ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!input->getROPixels(&inputBM)) {
1326ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
13274e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    }
13284e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
1329ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (inputBM.colorType() != kN32_SkColorType) {
1330ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1331ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    }
1332ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1333ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!inputBM.getPixels()) {
1334ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1335f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
13364e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
1337ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1338ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1339ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    SkBitmap dst;
1340ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!dst.tryAllocPixels(info)) {
1341ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1342cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
1343ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
13447b7ecfc046f7ec810482266db3430d1358b7a5bfsenorblanco    SkMatrix matrix(ctx.ctm());
1345ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1346ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1347ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1348fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org
1349f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    DiffuseLightingType lightingType(fKD);
13500c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    lightBitmap(lightingType,
1351ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                             transformedLight.get(),
1352ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                             inputBM,
1353ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                             &dst,
1354d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                             surfaceScale(),
1355d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                             bounds);
13564e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
13573e302275b324172c845627cbd00cee8a06571bafrobertphillips    return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
1358ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                          dst);
1359f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1360f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
136162745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettsk_sp<SkImageFilter> SkDiffuseLightingImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer)
136262745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettconst {
136362745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    SkASSERT(1 == this->countInputs());
13646d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    auto input = xformer->apply(this->getInput(0));
13656d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    auto light = this->light()->makeColorSpace(xformer);
13666d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    if (input.get() != this->getInput(0) || light.get() != this->light()) {
13676d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed        return SkDiffuseLightingImageFilter::Make(std::move(light), 255.0f * this->surfaceScale(),
13686d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed                                                  fKD, std::move(input), this->getCropRectIfSet());
13696d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    }
13706d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    return this->refMe();
137162745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett}
137262745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett
1373f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING
1374f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkDiffuseLightingImageFilter::toString(SkString* str) const {
1375f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->appendf("SkDiffuseLightingImageFilter: (");
1376f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->appendf("kD: %f\n", fKD);
1377f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->append(")");
1378f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips}
1379f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif
1380f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips
1381cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
1382aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomonstd::unique_ptr<GrFragmentProcessor> SkDiffuseLightingImageFilter::makeFragmentProcessor(
1383aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        sk_sp<GrTextureProxy> proxy,
1384aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        const SkMatrix& matrix,
1385aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        const SkIRect* srcBounds,
1386aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        BoundaryMode boundaryMode) const {
13878be952ad8c9deefe19cff36f9ad217563400f817Mike Reed    SkScalar scale = this->surfaceScale() * 255;
13886b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    return GrDiffuseLightingEffect::Make(std::move(proxy), this->refLight(), scale, matrix,
13896b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                                         this->kd(), boundaryMode, srcBounds);
1390894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1391d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
1392894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1393894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1394894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
139512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipssk_sp<SkImageFilter> SkSpecularLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
139612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                         SkScalar surfaceScale,
139712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                         SkScalar ks,
139812fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                         SkScalar shininess,
139912fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                         sk_sp<SkImageFilter> input,
140012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                         const CropRect* cropRect) {
140112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    if (!light) {
140296fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
14039fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
14049fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) {
140596fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
14069fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
1407ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    // According to the spec, ks can be any non-negative number :
1408ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
14099fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    if (ks < 0) {
141096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
14119fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
141212fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    return sk_sp<SkImageFilter>(new SkSpecularLightingImageFilter(std::move(light), surfaceScale,
141312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                  ks, shininess,
141412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                                  std::move(input), cropRect));
14159fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
14169fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
141712fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillipsSkSpecularLightingImageFilter::SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,
1418d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                             SkScalar surfaceScale,
1419d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                             SkScalar ks,
1420d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                             SkScalar shininess,
142112fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                                                             sk_sp<SkImageFilter> input,
1422d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                             const CropRect* cropRect)
142312fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
142412fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    , fKS(ks)
142512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    , fShininess(shininess) {
1426f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1427f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
142860c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
14299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
143012fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
14319fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar surfaceScale = buffer.readScalar();
14329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar ks = buffer.readScalar();
14339fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkScalar shine = buffer.readScalar();
1434959ccc2aefbaf0bc8b58f44d2fc85cddb1d027cfRobert Phillips
143512fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips    return Make(std::move(light), surfaceScale, ks, shine, common.getInput(0),
143612fa47d33f1e9eb69bb20d9daad2eccfc7288944robertphillips                &common.cropRect());
14379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
1438f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
14398b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1440f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    this->INHERITED::flatten(buffer);
1441f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    buffer.writeScalar(fKS);
1442f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    buffer.writeScalar(fShininess);
1443f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1444f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
1445ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillipssk_sp<SkSpecialImage> SkSpecularLightingImageFilter::onFilterImage(SkSpecialImage* source,
1446ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                                   const Context& ctx,
1447ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                                   SkIPoint* offset) const {
1448ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    SkIPoint inputOffset = SkIPoint::Make(0, 0);
1449ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
1450ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!input) {
1451ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1452a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org    }
1453a8aef8bf04b10ad648c448c16f56d8c487819112commit-bot@chromium.org
1454ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1455ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                  input->width(), input->height());
1456ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    SkIRect bounds;
1457ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1458ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1459f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
14604e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
1461ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    offset->fX = bounds.left();
1462ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    offset->fY = bounds.top();
1463ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    bounds.offset(-inputOffset);
1464ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1465ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips#if SK_SUPPORT_GPU
1466ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (source->isTextureBacked()) {
1467ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        SkMatrix matrix(ctx.ctm());
1468ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1469ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
14702a75e5df300a2838f943ca52a52a85a5cf69802bbrianosman        return this->filterImageGPU(source, input.get(), bounds, matrix, ctx.outputProperties());
1471f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    }
1472ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips#endif
14734e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
147429089179a66c06ef70da387111af75970f04ed53senorblanco@chromium.org    if (bounds.width() < 2 || bounds.height() < 2) {
1475ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1476ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    }
1477ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1478ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    SkBitmap inputBM;
1479ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1480ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!input->getROPixels(&inputBM)) {
1481ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1482ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    }
1483ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1484ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (inputBM.colorType() != kN32_SkColorType) {
1485ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
14860ef0501baf615149d6d84398d7594cd89f6e928dsenorblanco@chromium.org    }
14870ef0501baf615149d6d84398d7594cd89f6e928dsenorblanco@chromium.org
1488ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!inputBM.getPixels()) {
1489ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1490118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
1491118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org
1492ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1493ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1494ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    SkBitmap dst;
1495ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    if (!dst.tryAllocPixels(info)) {
1496ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips        return nullptr;
1497cd3b15ca6364a04b0eeeb4f89c7daa8aefe854c8commit-bot@chromium.org    }
1498ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1499f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org    SpecularLightingType lightingType(fKS, fShininess);
1500ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
15017b7ecfc046f7ec810482266db3430d1358b7a5bfsenorblanco    SkMatrix matrix(ctx.ctm());
1502ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1503ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
1504ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips    sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1505ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
15060c182fc77e044edddb6606b7cf51b9a5b6c2eb54Mike Reed    lightBitmap(lightingType,
1507ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                              transformedLight.get(),
1508ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                              inputBM,
1509ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips                                                              &dst,
1510d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                              surfaceScale(),
1511d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                              bounds);
1512ad3dc0da218cc43c9917a256d4afb8cf0d7c5899robertphillips
15133e302275b324172c845627cbd00cee8a06571bafrobertphillips    return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()), dst);
1514f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org}
1515f49b429ceface4f75f5f96570ea5a8b94896529dsenorblanco@chromium.org
151662745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettsk_sp<SkImageFilter> SkSpecularLightingImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer)
151762745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettconst {
151862745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett    SkASSERT(1 == this->countInputs());
151962745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett
15206d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    auto input = xformer->apply(this->getInput(0));
15216d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    auto light = this->light()->makeColorSpace(xformer);
15226d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    if (input.get() != this->getInput(0) || light.get() != this->light()) {
15236d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed        return SkSpecularLightingImageFilter::Make(std::move(light),
15246d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed                                                   255.0f * this->surfaceScale(), fKS, fShininess,
15256d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed                                                   std::move(input), this->getCropRectIfSet());
15266d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    }
15276d9f42984d94a2e9116dd951d47cd65cd8f4d401Mike Reed    return this->refMe();
152862745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett}
152962745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett
1530f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING
1531f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkSpecularLightingImageFilter::toString(SkString* str) const {
1532f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->appendf("SkSpecularLightingImageFilter: (");
1533f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->appendf("kS: %f shininess: %f", fKS, fShininess);
1534f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips    str->append(")");
1535f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips}
1536f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif
1537f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips
1538cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
1539aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomonstd::unique_ptr<GrFragmentProcessor> SkSpecularLightingImageFilter::makeFragmentProcessor(
1540aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        sk_sp<GrTextureProxy> proxy,
1541aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        const SkMatrix& matrix,
1542aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        const SkIRect* srcBounds,
1543aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomon        BoundaryMode boundaryMode) const {
15448be952ad8c9deefe19cff36f9ad217563400f817Mike Reed    SkScalar scale = this->surfaceScale() * 255;
15456b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    return GrSpecularLightingEffect::Make(std::move(proxy), this->refLight(), scale, matrix,
15466b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                                          this->ks(), this->shininess(), boundaryMode, srcBounds);
1547894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1548d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
1549894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1550894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1551894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1552cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#if SK_SUPPORT_GPU
1553a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
155462745a8bba20d7ca91167915eb459339bcfb8862Matt Sarettstatic SkString emitNormalFunc(BoundaryMode mode,
155562745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett                               const char* pointToNormalName,
155662745a8bba20d7ca91167915eb459339bcfb8862Matt Sarett                               const char* sobelFuncName) {
1557d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkString result;
1558d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    switch (mode) {
1559d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    case kTopLeft_BoundaryMode:
1560d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        result.printf("\treturn %s(%s(0.0, 0.0, m[4], m[5], m[7], m[8], %g),\n"
1561d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1562d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          surfaceScale);\n",
1563d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      pointToNormalName, sobelFuncName, gTwoThirds,
1564d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName, gTwoThirds);
1565d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1566d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    case kTop_BoundaryMode:
1567d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        result.printf("\treturn %s(%s(0.0, 0.0, m[3], m[5], m[6], m[8], %g),\n"
1568d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1569d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          surfaceScale);\n",
1570d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      pointToNormalName, sobelFuncName, gOneThird,
1571d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName, gOneHalf);
1572d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1573d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    case kTopRight_BoundaryMode:
1574d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        result.printf("\treturn %s(%s( 0.0,  0.0, m[3], m[4], m[6], m[7], %g),\n"
1575d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          %s(m[3], m[6], m[4], m[7],  0.0,  0.0, %g),\n"
1576d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          surfaceScale);\n",
1577d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      pointToNormalName, sobelFuncName, gTwoThirds,
1578d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName, gTwoThirds);
1579d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1580d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    case kLeft_BoundaryMode:
1581d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], m[7], m[8], %g),\n"
1582d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          %s( 0.0,  0.0, m[1], m[7], m[2], m[8], %g),\n"
1583d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          surfaceScale);\n",
1584d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      pointToNormalName, sobelFuncName, gOneHalf,
1585d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName, gOneThird);
1586d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1587d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    case kInterior_BoundaryMode:
1588d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], %g),\n"
1589d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          %s(m[0], m[6], m[1], m[7], m[2], m[8], %g),\n"
1590d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          surfaceScale);\n",
1591d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      pointToNormalName, sobelFuncName, gOneQuarter,
1592d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName, gOneQuarter);
1593d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1594d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    case kRight_BoundaryMode:
1595d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], m[6], m[7], %g),\n"
1596d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          %s(m[0], m[6], m[1], m[7],  0.0,  0.0, %g),\n"
1597d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          surfaceScale);\n",
1598d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      pointToNormalName, sobelFuncName, gOneHalf,
1599d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName, gOneThird);
1600d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1601d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    case kBottomLeft_BoundaryMode:
1602d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5],  0.0,  0.0, %g),\n"
1603d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          %s( 0.0,  0.0, m[1], m[4], m[2], m[5], %g),\n"
1604d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          surfaceScale);\n",
1605d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      pointToNormalName, sobelFuncName, gTwoThirds,
1606d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName, gTwoThirds);
1607d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1608d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    case kBottom_BoundaryMode:
1609d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5],  0.0,  0.0, %g),\n"
1610d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          %s(m[0], m[3], m[1], m[4], m[2], m[5], %g),\n"
1611d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          surfaceScale);\n",
1612d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      pointToNormalName, sobelFuncName, gOneThird,
1613d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName, gOneHalf);
1614d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1615d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    case kBottomRight_BoundaryMode:
1616d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4],  0.0,  0.0, %g),\n"
1617d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          %s(m[0], m[3], m[1], m[4],  0.0,  0.0, %g),\n"
1618d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      "\t          surfaceScale);\n",
1619d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                      pointToNormalName, sobelFuncName, gTwoThirds,
1620d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName, gTwoThirds);
1621d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1622d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    default:
1623d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        SkASSERT(false);
1624d0d37cace08f12abf8d316e6949e947551d418e6senorblanco        break;
1625d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    }
1626d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    return result;
1627d0d37cace08f12abf8d316e6949e947551d418e6senorblanco}
1628d0d37cace08f12abf8d316e6949e947551d418e6senorblanco
1629587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomonclass GrGLLightingEffect : public GrGLSLFragmentProcessor {
1630894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
1631d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    GrGLLightingEffect() : fLight(nullptr) { }
1632d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon    ~GrGLLightingEffect() override { delete fLight; }
1633894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
16347c157a988845fb00f9024d6db6dda142c3458033wangyix    void emitCode(EmitArgs&) override;
1635894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
163694efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon    static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
1637894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1638b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected:
1639ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    /**
1640b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix     * Subclasses of GrGLLightingEffect must call INHERITED::onSetData();
1641ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com     */
1642ab015efc48c462ffdffebb45c02cd19efb254983Brian Salomon    void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1643894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
16447ea439b2203855db97330b25945b87dd4b170b8begdaniel    virtual void emitLightFunc(GrGLSLUniformHandler*,
16458528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                               GrGLSLFPFragmentBuilder*,
16467ea439b2203855db97330b25945b87dd4b170b8begdaniel                               SkString* funcName) = 0;
1647ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
1648894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
164964c4728c70001ed074fecf5c4e083781987b12e9egdaniel    typedef GrGLSLFragmentProcessor INHERITED;
1650894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
16519bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco    UniformHandle              fImageIncrementUni;
16529bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco    UniformHandle              fSurfaceScaleUni;
16539bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco    GrTextureDomain::GLDomain  fDomain;
16549bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco    GrGLLight*                 fLight;
1655894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
1656894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1657894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1658894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1659894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLDiffuseLightingEffect  : public GrGLLightingEffect {
1660894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
16618528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton    void emitLightFunc(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, SkString* funcName) override;
1662b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix
1663b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected:
1664ab015efc48c462ffdffebb45c02cd19efb254983Brian Salomon    void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1665894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1666894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
1667894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLightingEffect INHERITED;
1668894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1669032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fKDUni;
1670894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
1671894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1672894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1673894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1674894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgclass GrGLSpecularLightingEffect  : public GrGLLightingEffect {
1675894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgpublic:
16768528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton    void emitLightFunc(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, SkString* funcName) override;
1677b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix
1678b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyixprotected:
1679ab015efc48c462ffdffebb45c02cd19efb254983Brian Salomon    void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1680894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1681894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.orgprivate:
1682894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    typedef GrGLLightingEffect INHERITED;
1683894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1684032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fKSUni;
1685032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    UniformHandle   fShininessUni;
1686894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org};
1687894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1688894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1689894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
16908e1c4e672553ecae2745168514240705f3516773Robert Phillipsstatic GrTextureDomain create_domain(GrTextureProxy* proxy, const SkIRect* srcBounds,
1691e98234f231d66848e149db683c11b6388e10b233Robert Phillips                                     GrTextureDomain::Mode mode) {
16929bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco    if (srcBounds) {
1693e98234f231d66848e149db683c11b6388e10b233Robert Phillips        SkRect texelDomain = GrTextureDomain::MakeTexelDomainForMode(*srcBounds, mode);
16948e1c4e672553ecae2745168514240705f3516773Robert Phillips        return GrTextureDomain(proxy, texelDomain, mode);
16959bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco    } else {
1696e98234f231d66848e149db683c11b6388e10b233Robert Phillips        return GrTextureDomain::IgnoredDomain();
16979bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco    }
16989bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco}
16999bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco
1700abff956455637b12eab374fd44b99e1338799113Ethan NicholasGrLightingEffect::GrLightingEffect(ClassID classID,
1701abff956455637b12eab374fd44b99e1338799113Ethan Nicholas                                   sk_sp<GrTextureProxy> proxy,
17026b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                                   sk_sp<const SkImageFilterLight> light,
17034e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                   SkScalar surfaceScale,
1704d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                   const SkMatrix& matrix,
17059bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                   BoundaryMode boundaryMode,
17069bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                   const SkIRect* srcBounds)
1707f3b995b628ef76bff28b9721dd1e182336156086Brian Salomon        // Perhaps this could advertise the opaque or coverage-as-alpha optimizations?
1708abff956455637b12eab374fd44b99e1338799113Ethan Nicholas        : INHERITED(classID, kNone_OptimizationFlags)
17096cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon        , fCoordTransform(proxy.get())
17106cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon        , fDomain(create_domain(proxy.get(), srcBounds, GrTextureDomain::kDecal_Mode))
17116cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon        , fTextureSampler(std::move(proxy))
17126b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon        , fLight(std::move(light))
1713587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        , fSurfaceScale(surfaceScale)
1714587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        , fFilterMatrix(matrix)
17156cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon        , fBoundaryMode(boundaryMode) {
17166cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon    this->addCoordTransform(&fCoordTransform);
17176cd51b51d6603a3100b147c45f38697f2f199fc6Brian Salomon    this->addTextureSampler(&fTextureSampler);
1718894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1719894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
17206b17ff664ea8ead5a5d3e83436772dd0286603f5Brian SalomonGrLightingEffect::GrLightingEffect(const GrLightingEffect& that)
1721abff956455637b12eab374fd44b99e1338799113Ethan Nicholas        : INHERITED(that.classID(), that.optimizationFlags())
17226b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon        , fCoordTransform(that.fCoordTransform)
17236b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon        , fDomain(that.fDomain)
17246b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon        , fTextureSampler(that.fTextureSampler)
17256b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon        , fLight(that.fLight)
17266b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon        , fSurfaceScale(that.fSurfaceScale)
17276b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon        , fFilterMatrix(that.fFilterMatrix)
17286b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon        , fBoundaryMode(that.fBoundaryMode) {
17296b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    this->addCoordTransform(&fCoordTransform);
17306b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    this->addTextureSampler(&fTextureSampler);
1731894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1732894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
17330e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
173449586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrLightingEffect& s = sBase.cast<GrLightingEffect>();
1735420d7e9a79358908850c74192b4949375563449absalomon    return fLight->isEqual(*s.fLight) &&
1736d0d37cace08f12abf8d316e6949e947551d418e6senorblanco           fSurfaceScale == s.fSurfaceScale &&
1737d0d37cace08f12abf8d316e6949e947551d418e6senorblanco           fBoundaryMode == s.fBoundaryMode;
1738894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1739894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1740894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1741894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1742fbcef6eb8abad142daf45418516550f7635b4a52Robert PhillipsGrDiffuseLightingEffect::GrDiffuseLightingEffect(sk_sp<GrTextureProxy> proxy,
17436b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                                                 sk_sp<const SkImageFilterLight>light,
17444e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                 SkScalar surfaceScale,
1745fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                                                 const SkMatrix& matrix,
1746d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                 SkScalar kd,
17479bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                                 BoundaryMode boundaryMode,
17489bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                                 const SkIRect* srcBounds)
1749abff956455637b12eab374fd44b99e1338799113Ethan Nicholas        : INHERITED(kGrDiffuseLightingEffect_ClassID, std::move(proxy), std::move(light),
1750abff956455637b12eab374fd44b99e1338799113Ethan Nicholas                    surfaceScale, matrix, boundaryMode, srcBounds)
1751abff956455637b12eab374fd44b99e1338799113Ethan Nicholas        , fKD(kd) {}
17526b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon
17536b17ff664ea8ead5a5d3e83436772dd0286603f5Brian SalomonGrDiffuseLightingEffect::GrDiffuseLightingEffect(const GrDiffuseLightingEffect& that)
1754abff956455637b12eab374fd44b99e1338799113Ethan Nicholas        : INHERITED(that), fKD(that.fKD) {}
1755894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
17560e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrDiffuseLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
175749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrDiffuseLightingEffect& s = sBase.cast<GrDiffuseLightingEffect>();
1758d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    return INHERITED::onIsEqual(sBase) && this->kd() == s.kd();
1759894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1760894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
176194efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomonvoid GrDiffuseLightingEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
176257d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel                                                    GrProcessorKeyBuilder* b) const {
1763eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    GrGLDiffuseLightingEffect::GenKey(*this, caps, b);
1764eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
1765eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
176657d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* GrDiffuseLightingEffect::onCreateGLSLInstance() const {
1767d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    return new GrGLDiffuseLightingEffect;
1768eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
1769eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
1770b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect);
1771a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
17726f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS
17730c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon
17740c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomonstatic SkPoint3 random_point3(SkRandom* random) {
17750c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon    return SkPoint3::Make(SkScalarToFloat(random->nextSScalar1()),
17760c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon                          SkScalarToFloat(random->nextSScalar1()),
17770c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon                          SkScalarToFloat(random->nextSScalar1()));
17780c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon}
17790c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon
17800c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomonstatic SkImageFilterLight* create_random_light(SkRandom* random) {
17810c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon    int type = random->nextULessThan(3);
17820c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon    switch (type) {
17830c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon        case 0: {
17840c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon            return new SkDistantLight(random_point3(random), random->nextU());
17850c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon        }
17860c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon        case 1: {
17870c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon            return new SkPointLight(random_point3(random), random->nextU());
17880c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon        }
17890c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon        case 2: {
17900c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon            return new SkSpotLight(random_point3(random), random_point3(random),
17910c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon                                   random->nextUScalar1(), random->nextUScalar1(), random->nextU());
17920c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon        }
17930c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon        default:
1794b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner            SK_ABORT("Unexpected value.");
17950c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon            return nullptr;
17960c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon    }
17970c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon}
17980c26a9dbd0b6546731df63c01411cb2aaa5ba236Brian Salomon
1799aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomonstd::unique_ptr<GrFragmentProcessor> GrDiffuseLightingEffect::TestCreate(GrProcessorTestData* d) {
18008e1c4e672553ecae2745168514240705f3516773Robert Phillips    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
18018e1c4e672553ecae2745168514240705f3516773Robert Phillips                                        : GrProcessorUnitTest::kAlphaTextureIdx;
18028e1c4e672553ecae2745168514240705f3516773Robert Phillips    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
18030067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    SkScalar surfaceScale = d->fRandom->nextSScalar1();
18040067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    SkScalar kd = d->fRandom->nextUScalar1();
180567b39de70fb5d10caebfc75f418754186e5226c3Hal Canary    sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
1806fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkMatrix matrix;
1807fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    for (int i = 0; i < 9; i++) {
18080067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt        matrix[i] = d->fRandom->nextUScalar1();
1809fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
18108e1c4e672553ecae2745168514240705f3516773Robert Phillips    SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, proxy->width()),
18118e1c4e672553ecae2745168514240705f3516773Robert Phillips                                          d->fRandom->nextRangeU(0, proxy->height()),
18128e1c4e672553ecae2745168514240705f3516773Robert Phillips                                          d->fRandom->nextRangeU(0, proxy->width()),
18138e1c4e672553ecae2745168514240705f3516773Robert Phillips                                          d->fRandom->nextRangeU(0, proxy->height()));
18140067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
18156b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    return GrDiffuseLightingEffect::Make(std::move(proxy), std::move(light), surfaceScale, matrix,
18166b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                                         kd, mode, &srcBounds);
1817a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com}
18186f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#endif
1819a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1820a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
1821894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1822894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
18237c157a988845fb00f9024d6db6dda142c3458033wangyixvoid GrGLLightingEffect::emitCode(EmitArgs& args) {
1824d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    const GrLightingEffect& le = args.fFp.cast<GrLightingEffect>();
1825d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    if (!fLight) {
1826d3b32bf8322877cf263229735aef4f04df5415c4robertphillips        fLight = le.light()->createGLLight();
1827d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    }
1828d3b32bf8322877cf263229735aef4f04df5415c4robertphillips
18297ea439b2203855db97330b25945b87dd4b170b8begdaniel    GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
18305e58ceea8569f0d90ff7e3daf5de2def50407212cdalton    fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1831f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                                                    kHalf2_GrSLType, "ImageIncrement");
18325e58ceea8569f0d90ff7e3daf5de2def50407212cdalton    fSurfaceScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1833f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                                                  kHalf_GrSLType, "SurfaceScale");
18347ea439b2203855db97330b25945b87dd4b170b8begdaniel    fLight->emitLightColorUniform(uniformHandler);
18358528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
1836a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString lightFunc;
18377ea439b2203855db97330b25945b87dd4b170b8begdaniel    this->emitLightFunc(uniformHandler, fragBuilder, &lightFunc);
183899938a8ef24e2dd5b39f78638742e9b50ab6d9bfBrian Salomon    static const GrShaderVar gSobelArgs[] =  {
1839f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("a", kHalf_GrSLType),
1840f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("b", kHalf_GrSLType),
1841f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("c", kHalf_GrSLType),
1842f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("d", kHalf_GrSLType),
1843f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("e", kHalf_GrSLType),
1844f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("f", kHalf_GrSLType),
1845f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("scale", kHalf_GrSLType),
1846a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1847a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString sobelFuncName;
18481a1aa9303484106a955e5549bf8ae24950f54e7absalomon    SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
18494ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel
1850f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->emitFunction(kHalf_GrSLType,
18514ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              "sobel",
18524ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              SK_ARRAY_COUNT(gSobelArgs),
18534ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              gSobelArgs,
18544ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
18554ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              &sobelFuncName);
185699938a8ef24e2dd5b39f78638742e9b50ab6d9bfBrian Salomon    static const GrShaderVar gPointToNormalArgs[] =  {
1857f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("x", kHalf_GrSLType),
1858f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("y", kHalf_GrSLType),
1859f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("scale", kHalf_GrSLType),
1860a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1861a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString pointToNormalName;
1862f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->emitFunction(kHalf3_GrSLType,
18634ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              "pointToNormal",
18644ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              SK_ARRAY_COUNT(gPointToNormalArgs),
18654ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              gPointToNormalArgs,
1866f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                              "\treturn normalize(half3(-x * scale, -y * scale, 1));\n",
18674ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              &pointToNormalName);
1868a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
186999938a8ef24e2dd5b39f78638742e9b50ab6d9bfBrian Salomon    static const GrShaderVar gInteriorNormalArgs[] =  {
1870f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("m", kHalf_GrSLType, 9),
1871f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("surfaceScale", kHalf_GrSLType),
1872a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1873d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    SkString normalBody = emitNormalFunc(le.boundaryMode(),
1874d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         pointToNormalName.c_str(),
1875d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                         sobelFuncName.c_str());
1876d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    SkString normalName;
1877f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->emitFunction(kHalf3_GrSLType,
18784ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              "normal",
18794ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              SK_ARRAY_COUNT(gInteriorNormalArgs),
18804ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              gInteriorNormalArgs,
18814ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              normalBody.c_str(),
18824ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              &normalName);
1883894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
18848aa4569c139a7a7ac38c62b25e3af40309cc2ee2Ethan Nicholas    fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
1885f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->codeAppend("\t\thalf m[9];\n");
1886032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
18877ea439b2203855db97330b25945b87dd4b170b8begdaniel    const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
18887ea439b2203855db97330b25945b87dd4b170b8begdaniel    const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni);
1889032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
1890894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    int index = 0;
1891d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    for (int dy = 1; dy >= -1; dy--) {
1892894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        for (int dx = -1; dx <= 1; dx++) {
1893894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org            SkString texCoords;
1894f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            texCoords.appendf("coord + half2(%d, %d) * %s", dx, dy, imgInc);
18959bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco            SkString temp;
18969bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco            temp.appendf("temp%d", index);
1897f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas            fragBuilder->codeAppendf("half4 %s;", temp.c_str());
18989bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco            fDomain.sampleTexture(fragBuilder,
18999bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                  args.fUniformHandler,
19001edc5b92fecefb79f01cf0e302646eacf32b06c7Brian Salomon                                  args.fShaderCaps,
19019bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                  le.domain(),
19029bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                  temp.c_str(),
19039bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                  texCoords,
19043f6f76f98b6b37d17d1492791ff0feb1b7586bd6cdalton                                  args.fTexSamplers[0]);
19059bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco            fragBuilder->codeAppendf("m[%d] = %s.a;", index, temp.c_str());
19069bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco            index++;
1907894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org        }
1908894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    }
1909f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->codeAppend("\t\thalf3 surfaceToLight = ");
1910894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    SkString arg;
1911032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    arg.appendf("%s * m[4]", surfScale);
19127ea439b2203855db97330b25945b87dd4b170b8begdaniel    fLight->emitSurfaceToLight(uniformHandler, fragBuilder, arg.c_str());
19134ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppend(";\n");
19144ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
19154ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                             args.fOutputColor, lightFunc.c_str(), normalName.c_str(), surfScale);
19167ea439b2203855db97330b25945b87dd4b170b8begdaniel    fLight->emitLightColor(uniformHandler, fragBuilder, "surfaceToLight");
19174ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppend(");\n");
19182983f4022d756def4f93579ee519cd31c8f24d61Ethan Nicholas    fragBuilder->codeAppendf("%s *= %s;\n", args.fOutputColor, args.fInputColor);
1919894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1920894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1921b0a8a377f832c59cee939ad721e1f87d378b7142joshualittvoid GrGLLightingEffect::GenKey(const GrProcessor& proc,
192294efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon                                const GrShaderCaps& caps, GrProcessorKeyBuilder* b) {
1923d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1924d0d37cace08f12abf8d316e6949e947551d418e6senorblanco    b->add32(lighting.boundaryMode() << 2 | lighting.light()->type());
19259bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco    b->add32(GrTextureDomain::GLDomain::DomainKey(lighting.domain()));
1926894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1927894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1928018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1929ab015efc48c462ffdffebb45c02cd19efb254983Brian Salomon                                   const GrFragmentProcessor& proc) {
1930b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1931d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    if (!fLight) {
1932d3b32bf8322877cf263229735aef4f04df5415c4robertphillips        fLight = lighting.light()->createGLLight();
1933d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    }
1934d3b32bf8322877cf263229735aef4f04df5415c4robertphillips
1935c686ce39f06d556d55befd290e0eb82851c7d33bRobert Phillips    GrTextureProxy* proxy = lighting.textureSampler(0).proxy();
1936c686ce39f06d556d55befd290e0eb82851c7d33bRobert Phillips    GrTexture* texture = proxy->priv().peekTexture();
19379bee2e5894bb8dd374392f238bc429e16f239583Robert Phillips
1938c686ce39f06d556d55befd290e0eb82851c7d33bRobert Phillips    float ySign = proxy->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
19397510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
19407510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
194167b39de70fb5d10caebfc75f418754186e5226c3Hal Canary    sk_sp<SkImageFilterLight> transformedLight(
194267b39de70fb5d10caebfc75f418754186e5226c3Hal Canary            lighting.light()->transform(lighting.filterMatrix()));
1943c686ce39f06d556d55befd290e0eb82851c7d33bRobert Phillips    fDomain.setData(pdman, lighting.domain(), proxy);
194467b39de70fb5d10caebfc75f418754186e5226c3Hal Canary    fLight->setData(pdman, transformedLight.get());
1945894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1946894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1947894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1948894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1949894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1950894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
19517ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLDiffuseLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandler,
19528528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                                              GrGLSLFPFragmentBuilder* fragBuilder,
19534ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                              SkString* funcName) {
1954ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* kd;
1955f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KD", &kd);
1956ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
195799938a8ef24e2dd5b39f78638742e9b50ab6d9bfBrian Salomon    static const GrShaderVar gLightArgs[] = {
1958f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("normal", kHalf3_GrSLType),
1959f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("surfaceToLight", kHalf3_GrSLType),
1960f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("lightColor", kHalf3_GrSLType)
1961a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
1962a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString lightBody;
1963f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    lightBody.appendf("\thalf colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1964f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    lightBody.appendf("\treturn half4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1965f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->emitFunction(kHalf4_GrSLType,
19664ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              "light",
19674ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              SK_ARRAY_COUNT(gLightArgs),
19684ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              gLightArgs,
19694ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              lightBody.c_str(),
19704ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              funcName);
1971894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1972894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1973018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLDiffuseLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1974ab015efc48c462ffdffebb45c02cd19efb254983Brian Salomon                                          const GrFragmentProcessor& proc) {
1975b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix    INHERITED::onSetData(pdman, proc);
1976b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    const GrDiffuseLightingEffect& diffuse = proc.cast<GrDiffuseLightingEffect>();
19777510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fKDUni, diffuse.kd());
1978894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
1979894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1980894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
1981894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
1982fbcef6eb8abad142daf45418516550f7635b4a52Robert PhillipsGrSpecularLightingEffect::GrSpecularLightingEffect(sk_sp<GrTextureProxy> proxy,
19836b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                                                   sk_sp<const SkImageFilterLight> light,
19844e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                   SkScalar surfaceScale,
1985fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org                                                   const SkMatrix& matrix,
19864e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org                                                   SkScalar ks,
1987d0d37cace08f12abf8d316e6949e947551d418e6senorblanco                                                   SkScalar shininess,
19889bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                                   BoundaryMode boundaryMode,
19899bd5f746ca45ebec0ed3b54dcbd6cf5fc2754c3csenorblanco                                                   const SkIRect* srcBounds)
1990abff956455637b12eab374fd44b99e1338799113Ethan Nicholas        : INHERITED(kGrSpecularLightingEffect_ClassID, std::move(proxy), std::move(light),
1991abff956455637b12eab374fd44b99e1338799113Ethan Nicholas                    surfaceScale, matrix, boundaryMode, srcBounds)
19926b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon        , fKS(ks)
1993abff956455637b12eab374fd44b99e1338799113Ethan Nicholas        , fShininess(shininess) {}
19946b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon
19956b17ff664ea8ead5a5d3e83436772dd0286603f5Brian SalomonGrSpecularLightingEffect::GrSpecularLightingEffect(const GrSpecularLightingEffect& that)
1996abff956455637b12eab374fd44b99e1338799113Ethan Nicholas        : INHERITED(that), fKS(that.fKS), fShininess(that.fShininess) {}
1997894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
19980e08fc17e4718f7ce4e38f793695896473e96948bsalomonbool GrSpecularLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
199949586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrSpecularLightingEffect& s = sBase.cast<GrSpecularLightingEffect>();
200068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    return INHERITED::onIsEqual(sBase) &&
2001894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org           this->ks() == s.ks() &&
2002894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org           this->shininess() == s.shininess();
2003894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2004894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
200594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomonvoid GrSpecularLightingEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
200657d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel                                                     GrProcessorKeyBuilder* b) const {
2007eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    GrGLSpecularLightingEffect::GenKey(*this, caps, b);
2008eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
2009eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
201057d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* GrSpecularLightingEffect::onCreateGLSLInstance() const {
2011d3b32bf8322877cf263229735aef4f04df5415c4robertphillips    return new GrGLSpecularLightingEffect;
2012eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}
2013eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
2014b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect);
2015a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
20166f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS
2017aff329b8e9b239bca1d93b13a914fbef45ccf7feBrian Salomonstd::unique_ptr<GrFragmentProcessor> GrSpecularLightingEffect::TestCreate(GrProcessorTestData* d) {
20188e1c4e672553ecae2745168514240705f3516773Robert Phillips    int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
20198e1c4e672553ecae2745168514240705f3516773Robert Phillips                                        : GrProcessorUnitTest::kAlphaTextureIdx;
20208e1c4e672553ecae2745168514240705f3516773Robert Phillips    sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
20210067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    SkScalar surfaceScale = d->fRandom->nextSScalar1();
20220067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    SkScalar ks = d->fRandom->nextUScalar1();
20230067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    SkScalar shininess = d->fRandom->nextUScalar1();
202467b39de70fb5d10caebfc75f418754186e5226c3Hal Canary    sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
2025fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkMatrix matrix;
2026fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    for (int i = 0; i < 9; i++) {
20270067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt        matrix[i] = d->fRandom->nextUScalar1();
2028fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    }
20290067ff5e0f85084dd2b5ad9886b526482b89a116joshualitt    BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
20308e1c4e672553ecae2745168514240705f3516773Robert Phillips    SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, proxy->width()),
20318e1c4e672553ecae2745168514240705f3516773Robert Phillips                                          d->fRandom->nextRangeU(0, proxy->height()),
20328e1c4e672553ecae2745168514240705f3516773Robert Phillips                                          d->fRandom->nextRangeU(0, proxy->width()),
20338e1c4e672553ecae2745168514240705f3516773Robert Phillips                                          d->fRandom->nextRangeU(0, proxy->height()));
20346b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon    return GrSpecularLightingEffect::Make(std::move(proxy), std::move(light), surfaceScale, matrix,
20356b17ff664ea8ead5a5d3e83436772dd0286603f5Brian Salomon                                          ks, shininess, mode, &srcBounds);
2036a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com}
20376f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#endif
2038a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
2039894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
2040894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
20417ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLSpecularLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandler,
20428528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                                               GrGLSLFPFragmentBuilder* fragBuilder,
20434ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                               SkString* funcName) {
2044ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* ks;
2045ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* shininess;
2046ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
2047f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KS", &ks);
20485e58ceea8569f0d90ff7e3daf5de2def50407212cdalton    fShininessUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2049f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas                                               kHalf_GrSLType,
20507ea439b2203855db97330b25945b87dd4b170b8begdaniel                                               "Shininess",
20517ea439b2203855db97330b25945b87dd4b170b8begdaniel                                               &shininess);
2052a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
205399938a8ef24e2dd5b39f78638742e9b50ab6d9bfBrian Salomon    static const GrShaderVar gLightArgs[] = {
2054f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("normal", kHalf3_GrSLType),
2055f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("surfaceToLight", kHalf3_GrSLType),
2056f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("lightColor", kHalf3_GrSLType)
2057a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
2058a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString lightBody;
2059f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    lightBody.appendf("\thalf3 halfDir = half3(normalize(surfaceToLight + half3(0, 0, 1)));\n");
20608aa4569c139a7a7ac38c62b25e3af40309cc2ee2Ethan Nicholas    lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n",
20619bc39bbd1a18d61e4e9c3808c33ea003a8e49938Brian Osman                      ks, shininess);
2062f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    lightBody.appendf("\thalf3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
2063f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    lightBody.appendf("\treturn half4(color, max(max(color.r, color.g), color.b));\n");
2064f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->emitFunction(kHalf4_GrSLType,
20654ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              "light",
20664ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              SK_ARRAY_COUNT(gLightArgs),
20674ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              gLightArgs,
20684ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              lightBody.c_str(),
20694ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              funcName);
2070894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2071894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
2072018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLSpecularLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
2073ab015efc48c462ffdffebb45c02cd19efb254983Brian Salomon                                           const GrFragmentProcessor& effect) {
2074b1daa86732fe70aa4630c89d75ff0fd619d77c77wangyix    INHERITED::onSetData(pdman, effect);
207549586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    const GrSpecularLightingEffect& spec = effect.cast<GrSpecularLightingEffect>();
20767510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fKSUni, spec.ks());
20777510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fShininessUni, spec.shininess());
2078894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2079894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
2080894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
20817ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLLight::emitLightColorUniform(GrGLSLUniformHandler* uniformHandler) {
2082f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "LightColor");
2083894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2084894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
20857ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
20868528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                               GrGLSLFPFragmentBuilder* fragBuilder,
20874ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                               const char *surfaceToLight) {
20887ea439b2203855db97330b25945b87dd4b170b8begdaniel    fragBuilder->codeAppend(uniformHandler->getUniformCStr(this->lightColorUni()));
2089ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com}
2090ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
2091018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLLight::setData(const GrGLSLProgramDataManager& pdman,
20922f0dbc761a626473c19db7de561c7072b12953c5robertphillips                        const SkImageFilterLight* light) const {
20933d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    setUniformPoint3(pdman, fColorUni,
20943d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips                     light->color().makeScale(SkScalarInvert(SkIntToScalar(255))));
2095894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2096894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
2097894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
2098894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
2099018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLDistantLight::setData(const GrGLSLProgramDataManager& pdman,
21002f0dbc761a626473c19db7de561c7072b12953c5robertphillips                               const SkImageFilterLight* light) const {
21017510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    INHERITED::setData(pdman, light);
21022f0dbc761a626473c19db7de561c7072b12953c5robertphillips    SkASSERT(light->type() == SkImageFilterLight::kDistant_LightType);
2103894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
21047510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
2105894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2106894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
21077ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLDistantLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
21088528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                                          GrGLSLFPFragmentBuilder* fragBuilder,
21094ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                          const char* z) {
2110ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* dir;
2111f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
21127ea439b2203855db97330b25945b87dd4b170b8begdaniel                                               "LightDirection", &dir);
21134ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppend(dir);
2114894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2115894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
2116894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
2117894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
2118018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLPointLight::setData(const GrGLSLProgramDataManager& pdman,
21192f0dbc761a626473c19db7de561c7072b12953c5robertphillips                             const SkImageFilterLight* light) const {
21207510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    INHERITED::setData(pdman, light);
21212f0dbc761a626473c19db7de561c7072b12953c5robertphillips    SkASSERT(light->type() == SkImageFilterLight::kPoint_LightType);
2122894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
21237510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformPoint3(pdman, fLocationUni, pointLight->location());
2124894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2125894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
21267ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLPointLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
21278528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                                        GrGLSLFPFragmentBuilder* fragBuilder,
21284ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                        const char* z) {
2129ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* loc;
2130f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
21317ea439b2203855db97330b25945b87dd4b170b8begdaniel                                              "LightLocation", &loc);
2132f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
21333865711259e25a90a1d72480f848863ada202067Ethan Nicholas                             loc, z);
2134894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2135894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
2136894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org///////////////////////////////////////////////////////////////////////////////
2137894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
2138018fb62d12d1febf121fe265da5b6117b86a6541egdanielvoid GrGLSpotLight::setData(const GrGLSLProgramDataManager& pdman,
21392f0dbc761a626473c19db7de561c7072b12953c5robertphillips                            const SkImageFilterLight* light) const {
21407510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    INHERITED::setData(pdman, light);
21412f0dbc761a626473c19db7de561c7072b12953c5robertphillips    SkASSERT(light->type() == SkImageFilterLight::kSpot_LightType);
2142894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org    const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
21437510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformPoint3(pdman, fLocationUni, spotLight->location());
21447510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fExponentUni, spotLight->specularExponent());
21457510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
21467510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
21477510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    pdman.set1f(fConeScaleUni, spotLight->coneScale());
21487510b224e52b9518a8ddf7418db0e9c258f79539kkinnunen    setUniformNormal3(pdman, fSUni, spotLight->s());
2149894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2150894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
21517ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLSpotLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
21528528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                                       GrGLSLFPFragmentBuilder* fragBuilder,
21534ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                                       const char* z) {
2154ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* location;
2155f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
21567ea439b2203855db97330b25945b87dd4b170b8begdaniel                                              "LightLocation", &location);
215730ba436f04e61d4505fb854d5fc56079636e0788joshualitt
2158f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
21593865711259e25a90a1d72480f848863ada202067Ethan Nicholas                             location, z);
2160894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2161894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
21627ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLSpotLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
21638528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                                   GrGLSLFPFragmentBuilder* fragBuilder,
2164ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com                                   const char *surfaceToLight) {
2165ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
21667ea439b2203855db97330b25945b87dd4b170b8begdaniel    const char* color = uniformHandler->getUniformCStr(this->lightColorUni()); // created by parent class.
2167ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
2168ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* exponent;
2169ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* cosInner;
2170ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* cosOuter;
2171ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* coneScale;
2172ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com    const char* s;
2173f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
21747ea439b2203855db97330b25945b87dd4b170b8begdaniel                                              "Exponent", &exponent);
2175f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
21767ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                       "CosInnerConeAngle", &cosInner);
2177f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
21787ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                       "CosOuterConeAngle", &cosOuter);
2179f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
21807ea439b2203855db97330b25945b87dd4b170b8begdaniel                                               "ConeScale", &coneScale);
2181f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "S", &s);
2182ae5ef113ebd7f20f1bea952a0ed9bb6d47cbda92bsalomon@google.com
218399938a8ef24e2dd5b39f78638742e9b50ab6d9bfBrian Salomon    static const GrShaderVar gLightColorArgs[] = {
2184f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas        GrShaderVar("surfaceToLight", kHalf3_GrSLType)
2185a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    };
2186a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    SkString lightColorBody;
2187f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    lightColorBody.appendf("\thalf cosAngle = -dot(surfaceToLight, %s);\n", s);
2188a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
2189f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    lightColorBody.appendf("\t\treturn half3(0);\n");
2190a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\t}\n");
2191f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    lightColorBody.appendf("\thalf scale = pow(cosAngle, %s);\n", exponent);
2192a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
2193a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
2194a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                           color, cosOuter, coneScale);
2195a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    lightColorBody.appendf("\t}\n");
21960bccd8749bdce79b2d71518fe65783b1a9b06445caryclark    lightColorBody.appendf("\treturn %s;\n", color);
2197f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas    fragBuilder->emitFunction(kHalf3_GrSLType,
21984ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              "lightColor",
21994ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              SK_ARRAY_COUNT(gLightColorArgs),
22004ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              gLightColorArgs,
22014ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              lightColorBody.c_str(),
22024ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                              &fLightColorFunc);
22034ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel
22044ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel    fragBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
2205894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org}
2206894790d77c56cd4bae8070331d275c6d2897e33csenorblanco@chromium.org
2207cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com#endif
2208cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com
22090833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
22100833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
22110833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
22120833777df1f05adafd9b70c666a72d80defa4f6bdjsollen@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
2213