| OLD | NEW | 
|---|
| 1 | 1 | 
| 2 /* | 2 /* | 
| 3  * Copyright 2015 Google Inc. | 3  * Copyright 2015 Google Inc. | 
| 4  * | 4  * | 
| 5  * Use of this source code is governed by a BSD-style license that can be | 5  * Use of this source code is governed by a BSD-style license that can be | 
| 6  * found in the LICENSE file. | 6  * found in the LICENSE file. | 
| 7  */ | 7  */ | 
| 8 | 8 | 
| 9 #include "SkBitmapProcState.h" | 9 #include "SkBitmapProcState.h" | 
| 10 #include "SkColor.h" | 10 #include "SkColor.h" | 
| 11 #include "SkEmptyShader.h" | 11 #include "SkEmptyShader.h" | 
| 12 #include "SkErrorInternals.h" | 12 #include "SkErrorInternals.h" | 
| 13 #include "SkLightingShader.h" | 13 #include "SkLightingShader.h" | 
| 14 #include "SkMathPriv.h" | 14 #include "SkMathPriv.h" | 
| 15 #include "SkPoint3.h" |  | 
| 16 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" | 
| 17 #include "SkWriteBuffer.h" | 16 #include "SkWriteBuffer.h" | 
| 18 | 17 | 
| 19 //////////////////////////////////////////////////////////////////////////// | 18 //////////////////////////////////////////////////////////////////////////// | 
| 20 | 19 | 
| 21 /* | 20 /* | 
| 22    SkLightingShader TODOs: | 21    SkLightingShader TODOs: | 
| 23         support other than clamp mode | 22         support other than clamp mode | 
| 24         allow 'diffuse' & 'normal' to be of different dimensions? | 23         allow 'diffuse' & 'normal' to be of different dimensions? | 
| 25         support different light types | 24         support different light types | 
| 26         support multiple lights | 25         support multiple lights | 
| 27         enforce normal map is 4 channel | 26         enforce normal map is 4 channel | 
| 28         use SkImages instead if SkBitmaps | 27         use SkImages instead if SkBitmaps | 
| 29 | 28 | 
| 30     To Test: | 29     To Test: | 
| 31         non-opaque diffuse textures | 30         non-opaque diffuse textures | 
| 32         A8 diffuse textures | 31         A8 diffuse textures | 
| 33         down & upsampled draws | 32         down & upsampled draws | 
| 34 */ | 33 */ | 
| 35 | 34 | 
| 36 | 35 | 
| 37 | 36 | 
| 38 /** \class SkLightingShaderImpl | 37 /** \class SkLightingShaderImpl | 
| 39     This subclass of shader applies lighting. | 38     This subclass of shader applies lighting. | 
| 40 */ | 39 */ | 
| 41 class SK_API SkLightingShaderImpl : public SkShader { | 40 class SK_API SkLightingShaderImpl : public SkShader { | 
| 42 public: | 41 public: | 
| 43 | 42 | 
| 44     /** Create a new lighting shader that uses the provided normal map and | 43     /** Create a new lighting shader that use the provided normal map, light | 
| 45         lights to light the diffuse bitmap. | 44         and ambient color to light the diffuse bitmap. | 
| 46         @param diffuse    the diffuse bitmap | 45         @param diffuse the diffuse bitmap | 
| 47         @param normal     the normal map | 46         @param normal  the normal map | 
| 48         @param lights     the lights applied to the normal map | 47         @param light   the light applied to the normal map | 
| 49         @param invNormRotation rotation applied to the normal map's normals | 48         @param ambient the linear (unpremul) ambient light color | 
| 50         @param diffLocalM the local matrix for the diffuse coordinates |  | 
| 51         @param normLocalM the local matrix for the normal coordinates |  | 
| 52     */ | 49     */ | 
| 53     SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, | 50     SkLightingShaderImpl(const SkBitmap& diffuse, const SkBitmap& normal, | 
| 54                          const SkLightingShader::Lights* lights, | 51                          const SkLightingShader::Light& light, | 
| 55                          const SkVector& invNormRotation, | 52                          const SkColor3f& ambient, const SkMatrix* localMatrix) | 
| 56                          const SkMatrix* diffLocalM, const SkMatrix* normLocalM) | 53         : INHERITED(localMatrix) | 
| 57         : INHERITED(diffLocalM) |  | 
| 58         , fDiffuseMap(diffuse) | 54         , fDiffuseMap(diffuse) | 
| 59         , fNormalMap(normal) | 55         , fNormalMap(normal) | 
| 60         , fLights(SkRef(lights)) | 56         , fLight(light) | 
| 61         , fInvNormRotation(invNormRotation) { | 57         , fAmbientColor(ambient) { | 
| 62 | 58         if (!fLight.fDirection.normalize()) { | 
| 63         if (normLocalM) { | 59             fLight.fDirection = SkPoint3::Make(0.0f, 0.0f, 1.0f); | 
| 64             fNormLocalMatrix = *normLocalM; |  | 
| 65         } else { |  | 
| 66             fNormLocalMatrix.reset(); |  | 
| 67         } | 60         } | 
| 68         // Pre-cache so future calls to fNormLocalMatrix.getType() are threadsaf
     e. |  | 
| 69         (void)fNormLocalMatrix.getType(); |  | 
| 70 |  | 
| 71     } | 61     } | 
| 72 | 62 | 
| 73     bool isOpaque() const override; | 63     bool isOpaque() const override; | 
| 74 | 64 | 
| 75     bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v
     iewM, | 65     bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v
     iewM, | 
| 76                              const SkMatrix* localMatrix, GrColor* color, | 66                              const SkMatrix* localMatrix, GrColor* color, | 
| 77                              GrProcessorDataManager*, GrFragmentProcessor** fp) 
     const override; | 67                              GrProcessorDataManager*, GrFragmentProcessor** fp) 
     const override; | 
| 78 | 68 | 
| 79     size_t contextSize() const override; | 69     size_t contextSize() const override; | 
| 80 | 70 | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 97 | 87 | 
| 98         typedef SkShader::Context INHERITED; | 88         typedef SkShader::Context INHERITED; | 
| 99     }; | 89     }; | 
| 100 | 90 | 
| 101     SK_TO_STRING_OVERRIDE() | 91     SK_TO_STRING_OVERRIDE() | 
| 102     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) | 92     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) | 
| 103 | 93 | 
| 104 protected: | 94 protected: | 
| 105     void flatten(SkWriteBuffer&) const override; | 95     void flatten(SkWriteBuffer&) const override; | 
| 106     Context* onCreateContext(const ContextRec&, void*) const override; | 96     Context* onCreateContext(const ContextRec&, void*) const override; | 
| 107     bool computeNormTotalInverse(const ContextRec& rec, SkMatrix* normTotalInver
     se) const; |  | 
| 108 | 97 | 
| 109 private: | 98 private: | 
| 110     SkBitmap  fDiffuseMap; | 99     SkBitmap                fDiffuseMap; | 
| 111     SkBitmap  fNormalMap; | 100     SkBitmap                fNormalMap; | 
| 112 | 101     SkLightingShader::Light fLight; | 
| 113     SkAutoTUnref<const SkLightingShader::Lights>   fLights; | 102     SkColor3f               fAmbientColor;  // linear (unpremul) color. Range is
      0..1/channel. | 
| 114 |  | 
| 115     SkMatrix  fNormLocalMatrix; |  | 
| 116     SkVector  fInvNormRotation; |  | 
| 117 | 103 | 
| 118     friend class SkLightingShader; | 104     friend class SkLightingShader; | 
| 119 | 105 | 
| 120     typedef SkShader INHERITED; | 106     typedef SkShader INHERITED; | 
| 121 }; | 107 }; | 
| 122 | 108 | 
| 123 //////////////////////////////////////////////////////////////////////////// | 109 //////////////////////////////////////////////////////////////////////////// | 
| 124 | 110 | 
| 125 #if SK_SUPPORT_GPU | 111 #if SK_SUPPORT_GPU | 
| 126 | 112 | 
| 127 #include "GrCoordTransform.h" | 113 #include "GrCoordTransform.h" | 
| 128 #include "GrFragmentProcessor.h" | 114 #include "GrFragmentProcessor.h" | 
| 129 #include "GrTextureAccess.h" | 115 #include "GrTextureAccess.h" | 
| 130 #include "gl/GrGLProcessor.h" | 116 #include "gl/GrGLProcessor.h" | 
| 131 #include "gl/builders/GrGLProgramBuilder.h" | 117 #include "gl/builders/GrGLProgramBuilder.h" | 
| 132 #include "SkGr.h" | 118 #include "SkGr.h" | 
| 133 | 119 | 
| 134 class LightingFP : public GrFragmentProcessor { | 120 class LightingFP : public GrFragmentProcessor { | 
| 135 public: | 121 public: | 
| 136     LightingFP(GrProcessorDataManager* pdm, GrTexture* diffuse, GrTexture* norma
     l, | 122     LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix, | 
| 137                const SkMatrix& diffMatrix, const SkMatrix& normMatrix, | 123                const SkVector3& lightDir, const SkColor3f& lightColor, | 
| 138                const GrTextureParams& diffParams, const GrTextureParams& normPar
     ams, | 124                const SkColor3f& ambientColor) | 
| 139                const SkLightingShader::Lights* lights, const SkVector& invNormRo
     tation) | 125         : fDeviceTransform(kDevice_GrCoordSet, matrix) | 
| 140         : fDiffDeviceTransform(kLocal_GrCoordSet, diffMatrix, diffuse, diffParam
     s.filterMode()) | 126         , fDiffuseTextureAccess(diffuse) | 
| 141         , fNormDeviceTransform(kLocal_GrCoordSet, normMatrix, normal, normParams
     .filterMode()) | 127         , fNormalTextureAccess(normal) | 
| 142         , fDiffuseTextureAccess(diffuse, diffParams) | 128         , fLightDir(lightDir) | 
| 143         , fNormalTextureAccess(normal, normParams) | 129         , fLightColor(lightColor) | 
| 144         , fInvNormRotation(invNormRotation) { | 130         , fAmbientColor(ambientColor) { | 
| 145         this->addCoordTransform(&fDiffDeviceTransform); | 131         this->addCoordTransform(&fDeviceTransform); | 
| 146         this->addCoordTransform(&fNormDeviceTransform); |  | 
| 147         this->addTextureAccess(&fDiffuseTextureAccess); | 132         this->addTextureAccess(&fDiffuseTextureAccess); | 
| 148         this->addTextureAccess(&fNormalTextureAccess); | 133         this->addTextureAccess(&fNormalTextureAccess); | 
| 149 | 134 | 
| 150         // fuse all ambient lights into a single one |  | 
| 151         fAmbientColor.set(0.0f, 0.0f, 0.0f); |  | 
| 152         for (int i = 0; i < lights->numLights(); ++i) { |  | 
| 153             if (SkLight::kAmbient_LightType == lights->light(i).type()) { |  | 
| 154                 fAmbientColor += lights->light(i).color(); |  | 
| 155             } else { |  | 
| 156                 // TODO: handle more than one of these |  | 
| 157                 fLightColor = lights->light(i).color(); |  | 
| 158                 fLightDir = lights->light(i).dir(); |  | 
| 159             } |  | 
| 160         } |  | 
| 161 |  | 
| 162         this->initClassID<LightingFP>(); | 135         this->initClassID<LightingFP>(); | 
| 163     } | 136     } | 
| 164 | 137 | 
| 165     class LightingGLFP : public GrGLFragmentProcessor { | 138     class LightingGLFP : public GrGLFragmentProcessor { | 
| 166     public: | 139     public: | 
| 167         LightingGLFP() { | 140         LightingGLFP() { | 
| 168             fLightDir.fX = 10000.0f; | 141             fLightDir.fX = 10000.0f; | 
| 169             fLightColor.fX = 0.0f; | 142             fLightColor.fX = 0.0f; | 
| 170             fAmbientColor.fX = 0.0f; | 143             fAmbientColor.fX = 0.0f; | 
| 171             fInvNormRotation.fX = 0.0f; |  | 
| 172         } | 144         } | 
| 173 | 145 | 
| 174         void emitCode(EmitArgs& args) override { | 146         void emitCode(EmitArgs& args) override { | 
| 175 | 147 | 
| 176             GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder()
     ; | 148             GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder()
     ; | 
| 177 | 149 | 
| 178             // add uniforms | 150             // add uniforms | 
| 179             const char* lightDirUniName = NULL; | 151             const char* lightDirUniName = NULL; | 
| 180             fLightDirUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragme
     nt_Visibility, | 152             fLightDirUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragme
     nt_Visibility, | 
| 181                                                      kVec3f_GrSLType, kDefault_G
     rSLPrecision, | 153                                                      kVec3f_GrSLType, kDefault_G
     rSLPrecision, | 
| 182                                                      "LightDir", &lightDirUniNam
     e); | 154                                                      "LightDir", &lightDirUniNam
     e); | 
| 183 | 155 | 
| 184             const char* lightColorUniName = NULL; | 156             const char* lightColorUniName = NULL; | 
| 185             fLightColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFrag
     ment_Visibility, | 157             fLightColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFrag
     ment_Visibility, | 
| 186                                                        kVec3f_GrSLType, kDefault
     _GrSLPrecision, | 158                                                        kVec3f_GrSLType, kDefault
     _GrSLPrecision, | 
| 187                                                        "LightColor", &lightColor
     UniName); | 159                                                        "LightColor", &lightColor
     UniName); | 
| 188 | 160 | 
| 189             const char* ambientColorUniName = NULL; | 161             const char* ambientColorUniName = NULL; | 
| 190             fAmbientColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFr
     agment_Visibility, | 162             fAmbientColorUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFr
     agment_Visibility, | 
| 191                                                          kVec3f_GrSLType, kDefau
     lt_GrSLPrecision, | 163                                                          kVec3f_GrSLType, kDefau
     lt_GrSLPrecision, | 
| 192                                                          "AmbientColor", &ambien
     tColorUniName); | 164                                                          "AmbientColor", &ambien
     tColorUniName); | 
| 193 | 165 | 
| 194             const char* xformUniName = NULL; |  | 
| 195             fXformUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_
     Visibility, |  | 
| 196                                                   kVec2f_GrSLType, kDefault_GrSL
     Precision, |  | 
| 197                                                   "Xform", &xformUniName); |  | 
| 198 |  | 
| 199             fpb->codeAppend("vec4 diffuseColor = "); | 166             fpb->codeAppend("vec4 diffuseColor = "); | 
| 200             fpb->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers
     [0], | 167             fpb->appendTextureLookupAndModulate(args.fInputColor, args.fSamplers
     [0], | 
| 201                                                 args.fCoords[0].c_str(), | 168                                                 args.fCoords[0].c_str(), | 
| 202                                                 args.fCoords[0].getType()); | 169                                                 args.fCoords[0].getType()); | 
| 203             fpb->codeAppend(";"); | 170             fpb->codeAppend(";"); | 
| 204 | 171 | 
| 205             fpb->codeAppend("vec4 normalColor = "); | 172             fpb->codeAppend("vec4 normalColor = "); | 
| 206             fpb->appendTextureLookup(args.fSamplers[1], | 173             fpb->appendTextureLookup(args.fSamplers[1], | 
| 207                                      args.fCoords[1].c_str(), | 174                                      args.fCoords[0].c_str(), | 
| 208                                      args.fCoords[1].getType()); | 175                                      args.fCoords[0].getType()); | 
| 209             fpb->codeAppend(";"); | 176             fpb->codeAppend(";"); | 
| 210 | 177 | 
| 211             fpb->codeAppend("vec3 normal = normalColor.rgb - vec3(0.5);"); | 178             fpb->codeAppend("vec3 normal = normalize(normalColor.rgb - vec3(0.5)
     );"); | 
| 212 | 179             fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName); | 
| 213             fpb->codeAppendf("mat3 m = mat3(%s.x, -%s.y, 0.0, %s.y, %s.x, 0.0, 0
     .0, 0.0, 1.0);", | 180             fpb->codeAppend("float NdotL = dot(normal, lightDir);"); | 
| 214                              xformUniName, xformUniName, xformUniName, xformUniN
     ame); |  | 
| 215 |  | 
| 216             // TODO: inverse map the light direction vectors in the vertex shade
     r rather than |  | 
| 217             // transforming all the normals here! |  | 
| 218             fpb->codeAppend("normal = normalize(m*normal);"); |  | 
| 219 |  | 
| 220             fpb->codeAppendf("float NdotL = clamp(dot(normal, %s), 0.0, 1.0);", 
     lightDirUniName); |  | 
| 221             // diffuse light | 181             // diffuse light | 
| 222             fpb->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;", lightCo
     lorUniName); | 182             fpb->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;", lightCo
     lorUniName); | 
| 223             // ambient light | 183             // ambient light | 
| 224             fpb->codeAppendf("result += %s;", ambientColorUniName); | 184             fpb->codeAppendf("result += %s;", ambientColorUniName); | 
| 225             fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", args.fOut
     putColor); | 185             fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", args.fOut
     putColor); | 
| 226         } | 186         } | 
| 227 | 187 | 
| 228         static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 188         static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | 
| 229                            GrProcessorKeyBuilder* b) { | 189                            GrProcessorKeyBuilder* b) { | 
| 230 //            const LightingFP& lightingFP = proc.cast<LightingFP>(); | 190 //            const LightingFP& lightingFP = proc.cast<LightingFP>(); | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 246             if (lightColor != fLightColor) { | 206             if (lightColor != fLightColor) { | 
| 247                 pdman.set3fv(fLightColorUni, 1, &lightColor.fX); | 207                 pdman.set3fv(fLightColorUni, 1, &lightColor.fX); | 
| 248                 fLightColor = lightColor; | 208                 fLightColor = lightColor; | 
| 249             } | 209             } | 
| 250 | 210 | 
| 251             const SkColor3f& ambientColor = lightingFP.ambientColor(); | 211             const SkColor3f& ambientColor = lightingFP.ambientColor(); | 
| 252             if (ambientColor != fAmbientColor) { | 212             if (ambientColor != fAmbientColor) { | 
| 253                 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX); | 213                 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX); | 
| 254                 fAmbientColor = ambientColor; | 214                 fAmbientColor = ambientColor; | 
| 255             } | 215             } | 
| 256 |  | 
| 257             const SkVector& invNormRotation = lightingFP.invNormRotation(); |  | 
| 258             if (invNormRotation != fInvNormRotation) { |  | 
| 259                 pdman.set2fv(fXformUni, 1, &invNormRotation.fX); |  | 
| 260                 fInvNormRotation = invNormRotation; |  | 
| 261             } |  | 
| 262         } | 216         } | 
| 263 | 217 | 
| 264     private: | 218     private: | 
| 265         SkVector3 fLightDir; | 219         SkVector3 fLightDir; | 
| 266         GrGLProgramDataManager::UniformHandle fLightDirUni; | 220         GrGLProgramDataManager::UniformHandle fLightDirUni; | 
| 267 | 221 | 
| 268         SkColor3f fLightColor; | 222         SkColor3f fLightColor; | 
| 269         GrGLProgramDataManager::UniformHandle fLightColorUni; | 223         GrGLProgramDataManager::UniformHandle fLightColorUni; | 
| 270 | 224 | 
| 271         SkColor3f fAmbientColor; | 225         SkColor3f fAmbientColor; | 
| 272         GrGLProgramDataManager::UniformHandle fAmbientColorUni; | 226         GrGLProgramDataManager::UniformHandle fAmbientColorUni; | 
| 273 |  | 
| 274         SkVector fInvNormRotation; |  | 
| 275         GrGLProgramDataManager::UniformHandle fXformUni; |  | 
| 276     }; | 227     }; | 
| 277 | 228 | 
| 278     void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
     onst override { | 229     void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
     onst override { | 
| 279         LightingGLFP::GenKey(*this, caps, b); | 230         LightingGLFP::GenKey(*this, caps, b); | 
| 280     } | 231     } | 
| 281 | 232 | 
| 282     const char* name() const override { return "LightingFP"; } | 233     const char* name() const override { return "LightingFP"; } | 
| 283 | 234 | 
| 284     void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 235     void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 
| 285         inout->mulByUnknownFourComponents(); | 236         inout->mulByUnknownFourComponents(); | 
| 286     } | 237     } | 
| 287 | 238 | 
| 288     const SkVector3& lightDir() const { return fLightDir; } | 239     const SkVector3& lightDir() const { return fLightDir; } | 
| 289     const SkColor3f& lightColor() const { return fLightColor; } | 240     const SkColor3f& lightColor() const { return fLightColor; } | 
| 290     const SkColor3f& ambientColor() const { return fAmbientColor; } | 241     const SkColor3f& ambientColor() const { return fAmbientColor; } | 
| 291     const SkVector& invNormRotation() const { return fInvNormRotation; } |  | 
| 292 | 242 | 
| 293 private: | 243 private: | 
| 294     GrGLFragmentProcessor* onCreateGLInstance() const override { return SkNEW(Li
     ghtingGLFP); } | 244     GrGLFragmentProcessor* onCreateGLInstance() const override { return SkNEW(Li
     ghtingGLFP); } | 
| 295 | 245 | 
| 296     bool onIsEqual(const GrFragmentProcessor& proc) const override { | 246     bool onIsEqual(const GrFragmentProcessor& proc) const override { | 
| 297         const LightingFP& lightingFP = proc.cast<LightingFP>(); | 247         const LightingFP& lightingFP = proc.cast<LightingFP>(); | 
| 298         return fDiffDeviceTransform == lightingFP.fDiffDeviceTransform && | 248         return fDeviceTransform == lightingFP.fDeviceTransform && | 
| 299                fNormDeviceTransform == lightingFP.fNormDeviceTransform && |  | 
| 300                fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess && | 249                fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess && | 
| 301                fNormalTextureAccess == lightingFP.fNormalTextureAccess && | 250                fNormalTextureAccess == lightingFP.fNormalTextureAccess && | 
| 302                fLightDir == lightingFP.fLightDir && | 251                fLightDir == lightingFP.fLightDir && | 
| 303                fLightColor == lightingFP.fLightColor && | 252                fLightColor == lightingFP.fLightColor && | 
| 304                fAmbientColor == lightingFP.fAmbientColor && | 253                fAmbientColor == lightingFP.fAmbientColor; | 
| 305                fInvNormRotation == lightingFP.fInvNormRotation; |  | 
| 306     } | 254     } | 
| 307 | 255 | 
| 308     GrCoordTransform fDiffDeviceTransform; | 256     GrCoordTransform fDeviceTransform; | 
| 309     GrCoordTransform fNormDeviceTransform; |  | 
| 310     GrTextureAccess  fDiffuseTextureAccess; | 257     GrTextureAccess  fDiffuseTextureAccess; | 
| 311     GrTextureAccess  fNormalTextureAccess; | 258     GrTextureAccess  fNormalTextureAccess; | 
| 312     SkVector3        fLightDir; | 259     SkVector3        fLightDir; | 
| 313     SkColor3f        fLightColor; | 260     SkColor3f        fLightColor; | 
| 314     SkColor3f        fAmbientColor; | 261     SkColor3f        fAmbientColor; | 
| 315 |  | 
| 316     SkVector         fInvNormRotation; |  | 
| 317 }; | 262 }; | 
| 318 | 263 | 
| 319 //////////////////////////////////////////////////////////////////////////// | 264 //////////////////////////////////////////////////////////////////////////// | 
| 320 | 265 | 
| 321 static bool make_mat(const SkBitmap& bm, |  | 
| 322                      const SkMatrix& localMatrix1, |  | 
| 323                      const SkMatrix* localMatrix2, |  | 
| 324                      SkMatrix* result) { |  | 
| 325 |  | 
| 326     result->setIDiv(bm.width(), bm.height()); |  | 
| 327 |  | 
| 328     SkMatrix lmInverse; |  | 
| 329     if (!localMatrix1.invert(&lmInverse)) { |  | 
| 330         return false; |  | 
| 331     } |  | 
| 332     if (localMatrix2) { |  | 
| 333         SkMatrix inv; |  | 
| 334         if (!localMatrix2->invert(&inv)) { |  | 
| 335             return false; |  | 
| 336         } |  | 
| 337         lmInverse.postConcat(inv); |  | 
| 338     } |  | 
| 339     result->preConcat(lmInverse); |  | 
| 340 |  | 
| 341     return true; |  | 
| 342 } |  | 
| 343 |  | 
| 344 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
     & paint, | 266 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
     & paint, | 
| 345                                                const SkMatrix& viewM, const SkMa
     trix* localMatrix, | 267                                                const SkMatrix& viewM, const SkMa
     trix* localMatrix, | 
| 346                                                GrColor* color, GrProcessorDataMa
     nager* pdm, | 268                                                GrColor* color, GrProcessorDataMa
     nager*, | 
| 347                                                GrFragmentProcessor** fp) const { | 269                                                GrFragmentProcessor** fp) const { | 
| 348     // we assume diffuse and normal maps have same width and height | 270     // we assume diffuse and normal maps have same width and height | 
| 349     // TODO: support different sizes | 271     // TODO: support different sizes | 
| 350     SkASSERT(fDiffuseMap.width() == fNormalMap.width() && | 272     SkASSERT(fDiffuseMap.width() == fNormalMap.width() && | 
| 351              fDiffuseMap.height() == fNormalMap.height()); | 273              fDiffuseMap.height() == fNormalMap.height()); | 
| 352     SkMatrix diffM, normM; | 274     SkMatrix matrix; | 
| 353 | 275     matrix.setIDiv(fDiffuseMap.width(), fDiffuseMap.height()); | 
| 354     if (!make_mat(fDiffuseMap, this->getLocalMatrix(), localMatrix, &diffM)) { | 276 | 
| 355         return false; | 277     SkMatrix lmInverse; | 
|  | 278     if (!this->getLocalMatrix().invert(&lmInverse)) { | 
|  | 279         return false; | 
|  | 280     } | 
|  | 281     if (localMatrix) { | 
|  | 282         SkMatrix inv; | 
|  | 283         if (!localMatrix->invert(&inv)) { | 
|  | 284             return false; | 
|  | 285         } | 
|  | 286         lmInverse.postConcat(inv); | 
|  | 287     } | 
|  | 288     matrix.preConcat(lmInverse); | 
|  | 289 | 
|  | 290     // Must set wrap and filter on the sampler before requesting a texture. In t
     wo places below | 
|  | 291     // we check the matrix scale factors to determine how to interpret the filte
     r quality setting. | 
|  | 292     // This completely ignores the complexity of the drawVertices case where exp
     licit local coords | 
|  | 293     // are provided by the caller. | 
|  | 294     GrTextureParams::FilterMode textureFilterMode = GrTextureParams::kBilerp_Fil
     terMode; | 
|  | 295     switch (paint.getFilterQuality()) { | 
|  | 296     case kNone_SkFilterQuality: | 
|  | 297         textureFilterMode = GrTextureParams::kNone_FilterMode; | 
|  | 298         break; | 
|  | 299     case kLow_SkFilterQuality: | 
|  | 300         textureFilterMode = GrTextureParams::kBilerp_FilterMode; | 
|  | 301         break; | 
|  | 302     case kMedium_SkFilterQuality:{ | 
|  | 303         SkMatrix matrix; | 
|  | 304         matrix.setConcat(viewM, this->getLocalMatrix()); | 
|  | 305         if (matrix.getMinScale() < SK_Scalar1) { | 
|  | 306             textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 
|  | 307         } else { | 
|  | 308             // Don't trigger MIP level generation unnecessarily. | 
|  | 309             textureFilterMode = GrTextureParams::kBilerp_FilterMode; | 
|  | 310         } | 
|  | 311         break; | 
|  | 312     } | 
|  | 313     case kHigh_SkFilterQuality: | 
|  | 314     default: | 
|  | 315         SkErrorInternals::SetError(kInvalidPaint_SkError, | 
|  | 316             "Sorry, I don't understand the filtering " | 
|  | 317             "mode you asked for.  Falling back to " | 
|  | 318             "MIPMaps."); | 
|  | 319         textureFilterMode = GrTextureParams::kMipMap_FilterMode; | 
|  | 320         break; | 
|  | 321 | 
| 356     } | 322     } | 
| 357 | 323 | 
| 358     if (!make_mat(fNormalMap, fNormLocalMatrix, localMatrix, &normM)) { |  | 
| 359         return false; |  | 
| 360     } |  | 
| 361 |  | 
| 362     bool doBicubic; |  | 
| 363     GrTextureParams::FilterMode diffFilterMode = GrSkFilterQualityToGrFilterMode
     ( |  | 
| 364                                         SkTMin(paint.getFilterQuality(), kMedium
     _SkFilterQuality), |  | 
| 365                                         viewM, |  | 
| 366                                         this->getLocalMatrix(), |  | 
| 367                                         &doBicubic); |  | 
| 368     SkASSERT(!doBicubic); |  | 
| 369 |  | 
| 370     GrTextureParams::FilterMode normFilterMode = GrSkFilterQualityToGrFilterMode
     ( |  | 
| 371                                         SkTMin(paint.getFilterQuality(), kMedium
     _SkFilterQuality), |  | 
| 372                                         viewM, |  | 
| 373                                         fNormLocalMatrix, |  | 
| 374                                         &doBicubic); |  | 
| 375     SkASSERT(!doBicubic); |  | 
| 376 |  | 
| 377     // TODO: support other tile modes | 324     // TODO: support other tile modes | 
| 378     GrTextureParams diffParams(kClamp_TileMode, diffFilterMode); | 325     GrTextureParams params(kClamp_TileMode, textureFilterMode); | 
| 379     SkAutoTUnref<GrTexture> diffuseTexture(GrRefCachedBitmapTexture(context, | 326     SkAutoTUnref<GrTexture> diffuseTexture(GrRefCachedBitmapTexture(context, fDi
     ffuseMap, ¶ms)); | 
| 380                                                                     fDiffuseMap,
      &diffParams)); |  | 
| 381     if (!diffuseTexture) { | 327     if (!diffuseTexture) { | 
| 382         SkErrorInternals::SetError(kInternalError_SkError, | 328         SkErrorInternals::SetError(kInternalError_SkError, | 
| 383             "Couldn't convert bitmap to texture."); | 329             "Couldn't convert bitmap to texture."); | 
| 384         return false; | 330         return false; | 
| 385     } | 331     } | 
| 386 | 332 | 
| 387     GrTextureParams normParams(kClamp_TileMode, normFilterMode); | 333     SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, fNor
     malMap, ¶ms)); | 
| 388     SkAutoTUnref<GrTexture> normalTexture(GrRefCachedBitmapTexture(context, |  | 
| 389                                                                    fNormalMap, &
     normParams)); |  | 
| 390     if (!normalTexture) { | 334     if (!normalTexture) { | 
| 391         SkErrorInternals::SetError(kInternalError_SkError, | 335         SkErrorInternals::SetError(kInternalError_SkError, | 
| 392             "Couldn't convert bitmap to texture."); | 336             "Couldn't convert bitmap to texture."); | 
| 393         return false; | 337         return false; | 
| 394     } | 338     } | 
| 395 | 339 | 
| 396 | 340     *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix, | 
| 397     *fp = SkNEW_ARGS(LightingFP, (pdm, diffuseTexture, normalTexture, | 341                                   fLight.fDirection, fLight.fColor, fAmbientColo
     r)); | 
| 398                                   diffM, normM, diffParams, normParams, fLights, |  | 
| 399                                   fInvNormRotation)); |  | 
| 400 |  | 
| 401     *color = GrColorPackA4(paint.getAlpha()); | 342     *color = GrColorPackA4(paint.getAlpha()); | 
| 402     return true; | 343     return true; | 
| 403 } | 344 } | 
| 404 #else | 345 #else | 
| 405 | 346 | 
| 406 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
     & paint, | 347 bool SkLightingShaderImpl::asFragmentProcessor(GrContext* context, const SkPaint
     & paint, | 
| 407                                                const SkMatrix& viewM, const SkMa
     trix* localMatrix, | 348                                                const SkMatrix& viewM, const SkMa
     trix* localMatrix, | 
| 408                                                GrColor* color, GrProcessorDataMa
     nager*, | 349                                                GrColor* color, GrProcessorDataMa
     nager*, | 
| 409                                                GrFragmentProcessor** fp) const { | 350                                                GrFragmentProcessor** fp) const { | 
| 410     SkDEBUGFAIL("Should not call in GPU-less build"); | 351     SkDEBUGFAIL("Should not call in GPU-less build"); | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 443     fFlags = flags; | 384     fFlags = flags; | 
| 444 } | 385 } | 
| 445 | 386 | 
| 446 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { | 387 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { | 
| 447     // The bitmap proc states have been created outside of the context on memory
      that will be freed | 388     // The bitmap proc states have been created outside of the context on memory
      that will be freed | 
| 448     // elsewhere. Call the destructors but leave the freeing of the memory to th
     e caller. | 389     // elsewhere. Call the destructors but leave the freeing of the memory to th
     e caller. | 
| 449     fDiffuseState->~SkBitmapProcState(); | 390     fDiffuseState->~SkBitmapProcState(); | 
| 450     fNormalState->~SkBitmapProcState(); | 391     fNormalState->~SkBitmapProcState(); | 
| 451 } | 392 } | 
| 452 | 393 | 
| 453 static inline SkPMColor convert(SkColor3f color, U8CPU a) { | 394 static inline int light(SkScalar light, int diff, SkScalar NdotL, SkScalar ambie
     nt) { | 
| 454     if (color.fX <= 0.0f) { | 395     SkScalar color = light * diff * NdotL + 255 * ambient; | 
| 455         color.fX = 0.0f; | 396     if (color <= 0.0f) { | 
| 456     } else if (color.fX >= 255.0f) { | 397         return 0; | 
| 457         color.fX = 255.0f; | 398     } else if (color >= 255.0f) { | 
| 458     } | 399         return 255; | 
| 459 | 400     } else { | 
| 460     if (color.fY <= 0.0f) { | 401         return (int) color; | 
| 461         color.fY = 0.0f; | 402     } | 
| 462     } else if (color.fY >= 255.0f) { |  | 
| 463         color.fY = 255.0f; |  | 
| 464     } |  | 
| 465 |  | 
| 466     if (color.fZ <= 0.0f) { |  | 
| 467         color.fZ = 0.0f; |  | 
| 468     } else if (color.fZ >= 255.0f) { |  | 
| 469         color.fZ = 255.0f; |  | 
| 470     } |  | 
| 471 |  | 
| 472     return SkPreMultiplyARGB(a, (int) color.fX,  (int) color.fY, (int) color.fZ)
     ; |  | 
| 473 } | 403 } | 
| 474 | 404 | 
| 475 // larger is better (fewer times we have to loop), but we shouldn't | 405 // larger is better (fewer times we have to loop), but we shouldn't | 
| 476 // take up too much stack-space (each one here costs 16 bytes) | 406 // take up too much stack-space (each could here costs 16 bytes) | 
| 477 #define TMP_COUNT     16 | 407 #define TMP_COUNT     16 | 
| 478 | 408 | 
| 479 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, | 409 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, | 
| 480                                                             SkPMColor result[], 
     int count) { | 410                                                             SkPMColor result[], 
     int count) { | 
| 481     const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader
     Impl&>(fShader); | 411     const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader
     Impl&>(fShader); | 
| 482 | 412 | 
| 483     uint32_t  tmpColor[TMP_COUNT], tmpNormal[TMP_COUNT]; | 413     SkPMColor   tmpColor[TMP_COUNT], tmpColor2[TMP_COUNT]; | 
| 484     SkPMColor tmpColor2[2*TMP_COUNT], tmpNormal2[2*TMP_COUNT]; | 414     SkPMColor   tmpNormal[TMP_COUNT], tmpNormal2[TMP_COUNT]; | 
| 485 | 415 | 
| 486     SkBitmapProcState::MatrixProc   diffMProc = fDiffuseState->getMatrixProc(); | 416     SkBitmapProcState::MatrixProc   diffMProc = fDiffuseState->getMatrixProc(); | 
| 487     SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32()
     ; | 417     SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32()
     ; | 
| 488 | 418 | 
| 489     SkBitmapProcState::MatrixProc   normalMProc = fNormalState->getMatrixProc(); | 419     SkBitmapProcState::MatrixProc   normalMProc = fNormalState->getMatrixProc(); | 
| 490     SkBitmapProcState::SampleProc32 normalSProc = fNormalState->getSampleProc32(
     ); | 420     SkBitmapProcState::SampleProc32 normalSProc = fNormalState->getSampleProc32(
     ); | 
| 491 | 421 | 
| 492     int diffMax = fDiffuseState->maxCountForBufferSize(sizeof(tmpColor[0]) * TMP
     _COUNT); |  | 
| 493     int normMax = fNormalState->maxCountForBufferSize(sizeof(tmpNormal[0]) * TMP
     _COUNT); |  | 
| 494     int max = SkTMin(diffMax, normMax); |  | 
| 495 |  | 
| 496     SkASSERT(fDiffuseState->fPixmap.addr()); | 422     SkASSERT(fDiffuseState->fPixmap.addr()); | 
| 497     SkASSERT(fNormalState->fPixmap.addr()); | 423     SkASSERT(fNormalState->fPixmap.addr()); | 
| 498 | 424 | 
| 499     SkPoint3 norm, xformedNorm; | 425     SkPoint3 norm; | 
|  | 426     SkScalar NdotL; | 
|  | 427     int r, g, b; | 
| 500 | 428 | 
| 501     do { | 429     do { | 
| 502         int n = count; | 430         int n = count; | 
| 503         if (n > max) { | 431         if (n > TMP_COUNT) { | 
| 504             n = max; | 432             n = TMP_COUNT; | 
| 505         } | 433         } | 
| 506 | 434 | 
| 507         diffMProc(*fDiffuseState, tmpColor, n, x, y); | 435         diffMProc(*fDiffuseState, tmpColor, n, x, y); | 
| 508         diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); | 436         diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); | 
| 509 | 437 | 
| 510         normalMProc(*fNormalState, tmpNormal, n, x, y); | 438         normalMProc(*fNormalState, tmpNormal, n, x, y); | 
| 511         normalSProc(*fNormalState, tmpNormal, n, tmpNormal2); | 439         normalSProc(*fNormalState, tmpNormal, n, tmpNormal2); | 
| 512 | 440 | 
| 513         for (int i = 0; i < n; ++i) { | 441         for (int i = 0; i < n; ++i) { | 
| 514             SkASSERT(0xFF == SkColorGetA(tmpNormal2[i]));  // opaque -> unpremul | 442             SkASSERT(0xFF == SkColorGetA(tmpNormal2[i]));  // opaque -> unpremul | 
| 515             norm.set(SkIntToScalar(SkGetPackedR32(tmpNormal2[i]))-127.0f, | 443             norm.set(SkIntToScalar(SkGetPackedR32(tmpNormal2[i]))-127.0f, | 
| 516                      SkIntToScalar(SkGetPackedG32(tmpNormal2[i]))-127.0f, | 444                      SkIntToScalar(SkGetPackedG32(tmpNormal2[i]))-127.0f, | 
| 517                      SkIntToScalar(SkGetPackedB32(tmpNormal2[i]))-127.0f); | 445                      SkIntToScalar(SkGetPackedB32(tmpNormal2[i]))-127.0f); | 
| 518             norm.normalize(); | 446             norm.normalize(); | 
| 519 | 447 | 
| 520             xformedNorm.fX = lightShader.fInvNormRotation.fX * norm.fX + | 448             SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | 
| 521                              lightShader.fInvNormRotation.fY * norm.fY; | 449             NdotL = norm.dot(lightShader.fLight.fDirection); | 
| 522             xformedNorm.fY = lightShader.fInvNormRotation.fX * norm.fX - |  | 
| 523                              lightShader.fInvNormRotation.fY * norm.fY; |  | 
| 524             xformedNorm.fZ = norm.fZ; |  | 
| 525 | 450 | 
| 526             SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | 451             // This is all done in linear unpremul color space | 
|  | 452             r = light(lightShader.fLight.fColor.fX, SkColorGetR(diffColor), Ndot
     L, | 
|  | 453                       lightShader.fAmbientColor.fX); | 
|  | 454             g = light(lightShader.fLight.fColor.fY, SkColorGetG(diffColor), Ndot
     L, | 
|  | 455                       lightShader.fAmbientColor.fY); | 
|  | 456             b = light(lightShader.fLight.fColor.fZ, SkColorGetB(diffColor), Ndot
     L, | 
|  | 457                       lightShader.fAmbientColor.fZ); | 
| 527 | 458 | 
| 528             SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); | 459             result[i] = SkPreMultiplyARGB(SkColorGetA(diffColor), r, g, b); | 
| 529             // This is all done in linear unpremul color space (each component 0
     ..255.0f though) |  | 
| 530             for (int l = 0; l < lightShader.fLights->numLights(); ++l) { |  | 
| 531                 const SkLight& light = lightShader.fLights->light(l); |  | 
| 532 |  | 
| 533                 if (SkLight::kAmbient_LightType == light.type()) { |  | 
| 534                     accum += light.color().makeScale(255.0f); |  | 
| 535                 } else { |  | 
| 536                     SkScalar NdotL = xformedNorm.dot(light.dir()); |  | 
| 537                     if (NdotL < 0.0f) { |  | 
| 538                         NdotL = 0.0f; |  | 
| 539                     } |  | 
| 540 |  | 
| 541                     accum.fX += light.color().fX * SkColorGetR(diffColor) * Ndot
     L; |  | 
| 542                     accum.fY += light.color().fY * SkColorGetG(diffColor) * Ndot
     L; |  | 
| 543                     accum.fZ += light.color().fZ * SkColorGetB(diffColor) * Ndot
     L; |  | 
| 544                 } |  | 
| 545             } |  | 
| 546 |  | 
| 547             result[i] = convert(accum, SkColorGetA(diffColor)); |  | 
| 548         } | 460         } | 
| 549 | 461 | 
| 550         result += n; | 462         result += n; | 
| 551         x += n; | 463         x += n; | 
| 552         count -= n; | 464         count -= n; | 
| 553     } while (count > 0); | 465     } while (count > 0); | 
| 554 } | 466 } | 
| 555 | 467 | 
| 556 //////////////////////////////////////////////////////////////////////////// | 468 //////////////////////////////////////////////////////////////////////////// | 
| 557 | 469 | 
| 558 #ifndef SK_IGNORE_TO_STRING | 470 #ifndef SK_IGNORE_TO_STRING | 
| 559 void SkLightingShaderImpl::toString(SkString* str) const { | 471 void SkLightingShaderImpl::toString(SkString* str) const { | 
| 560     str->appendf("LightingShader: ()"); | 472     str->appendf("LightingShader: ()"); | 
| 561 } | 473 } | 
| 562 #endif | 474 #endif | 
| 563 | 475 | 
| 564 SkFlattenable* SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) { | 476 SkFlattenable* SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) { | 
| 565     SkMatrix diffLocalM; | 477     SkMatrix localMatrix; | 
| 566     bool hasDiffLocalM = buf.readBool(); | 478     buf.readMatrix(&localMatrix); | 
| 567     if (hasDiffLocalM) { |  | 
| 568         buf.readMatrix(&diffLocalM); |  | 
| 569     } else { |  | 
| 570         diffLocalM.reset(); |  | 
| 571     } |  | 
| 572 |  | 
| 573     SkMatrix normLocalM; |  | 
| 574     bool hasNormLocalM = buf.readBool(); |  | 
| 575     if (hasNormLocalM) { |  | 
| 576         buf.readMatrix(&normLocalM); |  | 
| 577     } else { |  | 
| 578         normLocalM.reset(); |  | 
| 579     } |  | 
| 580 | 479 | 
| 581     SkBitmap diffuse; | 480     SkBitmap diffuse; | 
| 582     if (!buf.readBitmap(&diffuse)) { | 481     if (!buf.readBitmap(&diffuse)) { | 
| 583         return NULL; | 482         return NULL; | 
| 584     } | 483     } | 
| 585     diffuse.setImmutable(); | 484     diffuse.setImmutable(); | 
| 586 | 485 | 
| 587     SkBitmap normal; | 486     SkBitmap normal; | 
| 588     if (!buf.readBitmap(&normal)) { | 487     if (!buf.readBitmap(&normal)) { | 
| 589         return NULL; | 488         return NULL; | 
| 590     } | 489     } | 
| 591     normal.setImmutable(); | 490     normal.setImmutable(); | 
| 592 | 491 | 
| 593     int numLights = buf.readInt(); | 492     SkLightingShader::Light light; | 
| 594 | 493     if (!buf.readScalarArray(&light.fDirection.fX, 3)) { | 
| 595     SkLightingShader::Lights::Builder builder; | 494         return NULL; | 
| 596 | 495     } | 
| 597     for (int l = 0; l < numLights; ++l) { | 496     if (!buf.readScalarArray(&light.fColor.fX, 3)) { | 
| 598         bool isAmbient = buf.readBool(); | 497         return NULL; | 
| 599 |  | 
| 600         SkColor3f color; |  | 
| 601         if (!buf.readScalarArray(&color.fX, 3)) { |  | 
| 602             return NULL; |  | 
| 603         } |  | 
| 604 |  | 
| 605         if (isAmbient) { |  | 
| 606             builder.add(SkLight(color)); |  | 
| 607         } else { |  | 
| 608             SkVector3 dir; |  | 
| 609             if (!buf.readScalarArray(&dir.fX, 3)) { |  | 
| 610                 return NULL; |  | 
| 611             } |  | 
| 612             builder.add(SkLight(color, dir)); |  | 
| 613         } |  | 
| 614     } | 498     } | 
| 615 | 499 | 
| 616     SkAutoTUnref<const SkLightingShader::Lights> lights(builder.finish()); | 500     SkColor3f ambient; | 
|  | 501     if (!buf.readScalarArray(&ambient.fX, 3)) { | 
|  | 502         return NULL; | 
|  | 503     } | 
| 617 | 504 | 
| 618     return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, lights, | 505     return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, &l
     ocalMatrix)); | 
| 619                                              SkVector::Make(1.0f, 0.0f), |  | 
| 620                                              &diffLocalM, &normLocalM)); |  | 
| 621 } | 506 } | 
| 622 | 507 | 
| 623 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { | 508 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { | 
| 624     this->INHERITED::flatten(buf); | 509     buf.writeMatrix(this->getLocalMatrix()); | 
| 625 |  | 
| 626     bool hasNormLocalM = !fNormLocalMatrix.isIdentity(); |  | 
| 627     buf.writeBool(hasNormLocalM); |  | 
| 628     if (hasNormLocalM) { |  | 
| 629         buf.writeMatrix(fNormLocalMatrix); |  | 
| 630     } |  | 
| 631 | 510 | 
| 632     buf.writeBitmap(fDiffuseMap); | 511     buf.writeBitmap(fDiffuseMap); | 
| 633     buf.writeBitmap(fNormalMap); | 512     buf.writeBitmap(fNormalMap); | 
| 634 | 513     buf.writeScalarArray(&fLight.fDirection.fX, 3); | 
| 635     buf.writeInt(fLights->numLights()); | 514     buf.writeScalarArray(&fLight.fColor.fX, 3); | 
| 636     for (int l = 0; l < fLights->numLights(); ++l) { | 515     buf.writeScalarArray(&fAmbientColor.fX, 3); | 
| 637         const SkLight& light = fLights->light(l); |  | 
| 638 |  | 
| 639         bool isAmbient = SkLight::kAmbient_LightType == light.type(); |  | 
| 640 |  | 
| 641         buf.writeBool(isAmbient); |  | 
| 642         buf.writeScalarArray(&light.color().fX, 3); |  | 
| 643         if (!isAmbient) { |  | 
| 644             buf.writeScalarArray(&light.dir().fX, 3); |  | 
| 645         } |  | 
| 646     } |  | 
| 647 } |  | 
| 648 |  | 
| 649 bool SkLightingShaderImpl::computeNormTotalInverse(const ContextRec& rec, |  | 
| 650                                                    SkMatrix* normTotalInverse) c
     onst { |  | 
| 651     SkMatrix total; |  | 
| 652     total.setConcat(*rec.fMatrix, fNormLocalMatrix); |  | 
| 653 |  | 
| 654     const SkMatrix* m = &total; |  | 
| 655     if (rec.fLocalMatrix) { |  | 
| 656         total.setConcat(*m, *rec.fLocalMatrix); |  | 
| 657         m = &total; |  | 
| 658     } |  | 
| 659     return m->invert(normTotalInverse); |  | 
| 660 } | 516 } | 
| 661 | 517 | 
| 662 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, | 518 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, | 
| 663                                                          void* storage) const { | 519                                                          void* storage) const { | 
| 664 | 520 | 
| 665     SkMatrix diffTotalInv; | 521     SkMatrix totalInverse; | 
| 666     // computeTotalInverse was called in SkShader::createContext so we know it w
     ill succeed | 522     // Do this first, so we know the matrix can be inverted. | 
| 667     SkAssertResult(this->computeTotalInverse(rec, &diffTotalInv)); | 523     if (!this->computeTotalInverse(rec, &totalInverse)) { | 
| 668 |  | 
| 669     SkMatrix normTotalInv; |  | 
| 670     if (!this->computeNormTotalInverse(rec, &normTotalInv)) { |  | 
| 671         return NULL; | 524         return NULL; | 
| 672     } | 525     } | 
| 673 | 526 | 
| 674     void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); | 527     void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); | 
| 675     SkBitmapProcState* diffuseState = SkNEW_PLACEMENT(diffuseStateStorage, SkBit
     mapProcState); | 528     SkBitmapProcState* diffuseState = SkNEW_PLACEMENT(diffuseStateStorage, SkBit
     mapProcState); | 
| 676     SkASSERT(diffuseState); | 529     SkASSERT(diffuseState); | 
| 677 | 530 | 
| 678     diffuseState->fTileModeX = SkShader::kClamp_TileMode; | 531     diffuseState->fTileModeX = SkShader::kClamp_TileMode; | 
| 679     diffuseState->fTileModeY = SkShader::kClamp_TileMode; | 532     diffuseState->fTileModeY = SkShader::kClamp_TileMode; | 
| 680     diffuseState->fOrigBitmap = fDiffuseMap; | 533     diffuseState->fOrigBitmap = fDiffuseMap; | 
| 681     if (!diffuseState->chooseProcs(diffTotalInv, *rec.fPaint)) { | 534     if (!diffuseState->chooseProcs(totalInverse, *rec.fPaint)) { | 
| 682         diffuseState->~SkBitmapProcState(); | 535         diffuseState->~SkBitmapProcState(); | 
| 683         return NULL; | 536         return NULL; | 
| 684     } | 537     } | 
| 685 | 538 | 
| 686     void* normalStateStorage = (char*)storage + sizeof(LightingShaderContext) + 
     sizeof(SkBitmapProcState); | 539     void* normalStateStorage = (char*)storage + sizeof(LightingShaderContext) + 
     sizeof(SkBitmapProcState); | 
| 687     SkBitmapProcState* normalState = SkNEW_PLACEMENT(normalStateStorage, SkBitma
     pProcState); | 540     SkBitmapProcState* normalState = SkNEW_PLACEMENT(normalStateStorage, SkBitma
     pProcState); | 
| 688     SkASSERT(normalState); | 541     SkASSERT(normalState); | 
| 689 | 542 | 
| 690     normalState->fTileModeX = SkShader::kClamp_TileMode; | 543     normalState->fTileModeX = SkShader::kClamp_TileMode; | 
| 691     normalState->fTileModeY = SkShader::kClamp_TileMode; | 544     normalState->fTileModeY = SkShader::kClamp_TileMode; | 
| 692     normalState->fOrigBitmap = fNormalMap; | 545     normalState->fOrigBitmap = fNormalMap; | 
| 693     if (!normalState->chooseProcs(normTotalInv, *rec.fPaint)) { | 546     if (!normalState->chooseProcs(totalInverse, *rec.fPaint)) { | 
| 694         diffuseState->~SkBitmapProcState(); | 547         diffuseState->~SkBitmapProcState(); | 
| 695         normalState->~SkBitmapProcState(); | 548         normalState->~SkBitmapProcState(); | 
| 696         return NULL; | 549         return NULL; | 
| 697     } | 550     } | 
| 698 | 551 | 
| 699     return SkNEW_PLACEMENT_ARGS(storage, LightingShaderContext, (*this, rec, | 552     return SkNEW_PLACEMENT_ARGS(storage, LightingShaderContext, (*this, rec, | 
| 700                                                                  diffuseState, n
     ormalState)); | 553                                                                  diffuseState, n
     ormalState)); | 
| 701 } | 554 } | 
| 702 | 555 | 
| 703 /////////////////////////////////////////////////////////////////////////////// | 556 /////////////////////////////////////////////////////////////////////////////// | 
| 704 | 557 | 
| 705 static bool bitmap_is_too_big(const SkBitmap& bm) { | 558 static bool bitmap_is_too_big(const SkBitmap& bm) { | 
| 706     // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it | 559     // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it | 
| 707     // communicates between its matrix-proc and its sampler-proc. Until we can | 560     // communicates between its matrix-proc and its sampler-proc. Until we can | 
| 708     // widen that, we have to reject bitmaps that are larger. | 561     // widen that, we have to reject bitmaps that are larger. | 
| 709     // | 562     // | 
| 710     static const int kMaxSize = 65535; | 563     static const int kMaxSize = 65535; | 
| 711 | 564 | 
| 712     return bm.width() > kMaxSize || bm.height() > kMaxSize; | 565     return bm.width() > kMaxSize || bm.height() > kMaxSize; | 
| 713 } | 566 } | 
| 714 | 567 | 
| 715 SkShader* SkLightingShader::Create(const SkBitmap& diffuse, const SkBitmap& norm
     al, | 568 SkShader* SkLightingShader::Create(const SkBitmap& diffuse, const SkBitmap& norm
     al, | 
| 716                                    const Lights* lights, | 569                                    const SkLightingShader::Light& light, | 
| 717                                    const SkVector& invNormRotation, | 570                                    const SkColor3f& ambient, | 
| 718                                    const SkMatrix* diffLocalM, const SkMatrix* n
     ormLocalM) { | 571                                    const SkMatrix* localMatrix) { | 
| 719     if (diffuse.isNull() || bitmap_is_too_big(diffuse) || | 572     if (diffuse.isNull() || bitmap_is_too_big(diffuse) || | 
| 720         normal.isNull() || bitmap_is_too_big(normal) || | 573         normal.isNull() || bitmap_is_too_big(normal) || | 
| 721         diffuse.width() != normal.width() || | 574         diffuse.width() != normal.width() || | 
| 722         diffuse.height() != normal.height()) { | 575         diffuse.height() != normal.height()) { | 
| 723         return nullptr; | 576         return nullptr; | 
| 724     } | 577     } | 
| 725 | 578 | 
| 726     SkASSERT(SkScalarNearlyEqual(invNormRotation.lengthSqd(), SK_Scalar1)); | 579     return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, light, ambient, lo
     calMatrix)); | 
| 727 |  | 
| 728     return SkNEW_ARGS(SkLightingShaderImpl, (diffuse, normal, lights, |  | 
| 729                                              invNormRotation, diffLocalM, normLo
     calM)); |  | 
| 730 } | 580 } | 
| 731 | 581 | 
| 732 /////////////////////////////////////////////////////////////////////////////// | 582 /////////////////////////////////////////////////////////////////////////////// | 
| 733 | 583 | 
| 734 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) | 584 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) | 
| 735     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) | 585     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) | 
| 736 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 586 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 
| 737 | 587 | 
| 738 /////////////////////////////////////////////////////////////////////////////// | 588 /////////////////////////////////////////////////////////////////////////////// | 
| OLD | NEW | 
|---|