OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBitmapProcShader.h" | 8 #include "SkBitmapProcShader.h" |
9 #include "SkBitmapProcState.h" | 9 #include "SkBitmapProcState.h" |
10 #include "SkColor.h" | 10 #include "SkColor.h" |
(...skipping 23 matching lines...) Expand all Loading... | |
34 down & upsampled draws | 34 down & upsampled draws |
35 */ | 35 */ |
36 | 36 |
37 | 37 |
38 | 38 |
39 /** \class SkLightingShaderImpl | 39 /** \class SkLightingShaderImpl |
40 This subclass of shader applies lighting. | 40 This subclass of shader applies lighting. |
41 */ | 41 */ |
42 class SkLightingShaderImpl : public SkShader { | 42 class SkLightingShaderImpl : public SkShader { |
43 public: | 43 public: |
44 | |
45 /** Create a new lighting shader that uses the provided normal map and | 44 /** Create a new lighting shader that uses the provided normal map and |
46 lights to light the diffuse bitmap. | 45 lights to light the diffuse bitmap. |
47 @param diffuse the diffuse bitmap | 46 @param diffuseShader the shader that provides the diffuse colors |
48 @param lights the lights applied to the normal map | |
49 @param diffLocalM the local matrix for the diffuse coordinates | |
50 @param normalSource the source of normals for lighting computation | 47 @param normalSource the source of normals for lighting computation |
48 @param lights the lights applied to the geometry | |
51 */ | 49 */ |
52 SkLightingShaderImpl(const SkBitmap& diffuse, | 50 SkLightingShaderImpl(sk_sp<SkShader> diffuseShader, |
53 const sk_sp<SkLights> lights, | 51 sk_sp<SkNormalSource> normalSource, |
54 const SkMatrix* diffLocalM, | 52 const sk_sp<SkLights> lights) |
55 sk_sp<SkNormalSource> normalSource) | 53 : fDiffuseShader(std::move(diffuseShader)) |
56 : INHERITED(diffLocalM) | 54 , fNormalSource(std::move(normalSource)) |
57 , fDiffuseMap(diffuse) | 55 , fLights(std::move(lights)) {} |
58 , fLights(std::move(lights)) { | |
59 | |
60 fNormalSource = std::move(normalSource); | |
61 } | |
62 | 56 |
63 bool isOpaque() const override; | 57 bool isOpaque() const override; |
64 | 58 |
65 #if SK_SUPPORT_GPU | 59 #if SK_SUPPORT_GPU |
66 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, | 60 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, |
67 const SkMatrix& viewM, | 61 const SkMatrix& viewM, |
68 const SkMatrix* localMatrix, | 62 const SkMatrix* localMatrix, |
69 SkFilterQuality, | 63 SkFilterQuality, |
70 SkSourceGammaTreatment) const override; | 64 SkSourceGammaTreatment) const override; |
71 #endif | 65 #endif |
72 | 66 |
73 class LightingShaderContext : public SkShader::Context { | 67 class LightingShaderContext : public SkShader::Context { |
74 public: | 68 public: |
75 // The context takes ownership of the states. It will call their destruc tors | 69 // The context takes ownership of the states. It will call their destruc tors |
76 // but will NOT free the memory. | 70 // but will NOT free the memory. |
77 LightingShaderContext(const SkLightingShaderImpl&, const ContextRec&, | 71 LightingShaderContext(const SkLightingShaderImpl&, const ContextRec&, |
78 SkBitmapProcState* diffuseState, SkNormalSource::P rovider*); | 72 SkShader::Context* diffuseContext, SkNormalSource: :Provider*, |
73 void* heapAllocated); | |
79 ~LightingShaderContext() override; | 74 ~LightingShaderContext() override; |
80 | 75 |
81 void shadeSpan(int x, int y, SkPMColor[], int count) override; | 76 void shadeSpan(int x, int y, SkPMColor[], int count) override; |
82 | 77 |
83 uint32_t getFlags() const override { return fFlags; } | 78 uint32_t getFlags() const override { return fFlags; } |
84 | 79 |
85 private: | 80 private: |
86 SkBitmapProcState* fDiffuseState; | 81 SkShader::Context* fDiffuseContext; |
87 SkNormalSource::Provider* fNormalProvider; | 82 SkNormalSource::Provider* fNormalProvider; |
88 uint32_t fFlags; | 83 uint32_t fFlags; |
89 | 84 |
85 void* fHeapAllocated; | |
86 | |
90 typedef SkShader::Context INHERITED; | 87 typedef SkShader::Context INHERITED; |
91 }; | 88 }; |
92 | 89 |
93 SK_TO_STRING_OVERRIDE() | 90 SK_TO_STRING_OVERRIDE() |
94 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) | 91 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingShaderImpl) |
95 | 92 |
96 protected: | 93 protected: |
97 void flatten(SkWriteBuffer&) const override; | 94 void flatten(SkWriteBuffer&) const override; |
98 size_t onContextSize(const ContextRec&) const override; | 95 size_t onContextSize(const ContextRec&) const override; |
99 Context* onCreateContext(const ContextRec&, void*) const override; | 96 Context* onCreateContext(const ContextRec&, void*) const override; |
100 | 97 |
101 private: | 98 private: |
102 SkBitmap fDiffuseMap; | 99 sk_sp<SkShader> fDiffuseShader; |
100 sk_sp<SkNormalSource> fNormalSource; | |
103 sk_sp<SkLights> fLights; | 101 sk_sp<SkLights> fLights; |
104 | 102 |
105 sk_sp<SkNormalSource> fNormalSource; | |
106 | |
107 friend class SkLightingShader; | 103 friend class SkLightingShader; |
108 | 104 |
109 typedef SkShader INHERITED; | 105 typedef SkShader INHERITED; |
110 }; | 106 }; |
111 | 107 |
112 //////////////////////////////////////////////////////////////////////////// | 108 //////////////////////////////////////////////////////////////////////////// |
113 | 109 |
114 #if SK_SUPPORT_GPU | 110 #if SK_SUPPORT_GPU |
115 | 111 |
116 #include "GrCoordTransform.h" | 112 #include "GrCoordTransform.h" |
117 #include "GrFragmentProcessor.h" | 113 #include "GrFragmentProcessor.h" |
118 #include "GrInvariantOutput.h" | 114 #include "GrInvariantOutput.h" |
119 #include "GrTextureAccess.h" | 115 #include "GrTextureAccess.h" |
120 #include "glsl/GrGLSLFragmentProcessor.h" | 116 #include "glsl/GrGLSLFragmentProcessor.h" |
121 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 117 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
122 #include "glsl/GrGLSLProgramDataManager.h" | 118 #include "glsl/GrGLSLProgramDataManager.h" |
123 #include "glsl/GrGLSLUniformHandler.h" | 119 #include "glsl/GrGLSLUniformHandler.h" |
124 #include "SkGr.h" | 120 #include "SkGr.h" |
125 #include "SkGrPriv.h" | 121 #include "SkGrPriv.h" |
126 | 122 |
127 class LightingFP : public GrFragmentProcessor { | 123 class LightingFP : public GrFragmentProcessor { |
128 public: | 124 public: |
129 LightingFP(GrTexture* diffuse, const SkMatrix& diffMatrix, const GrTexturePa rams& diffParams, | 125 LightingFP(sk_sp<GrFragmentProcessor> diffuseFP, sk_sp<GrFragmentProcessor> normalFP, |
130 sk_sp<SkLights> lights, sk_sp<GrFragmentProcessor> normalFP) | 126 sk_sp<SkLights> lights) { |
131 : fDiffDeviceTransform(kLocal_GrCoordSet, diffMatrix, diffuse, diffParam s.filterMode()) | |
132 , fDiffuseTextureAccess(diffuse, diffParams) { | |
133 this->addCoordTransform(&fDiffDeviceTransform); | |
134 this->addTextureAccess(&fDiffuseTextureAccess); | |
135 | 127 |
136 // fuse all ambient lights into a single one | 128 // fuse all ambient lights into a single one |
137 fAmbientColor.set(0.0f, 0.0f, 0.0f); | 129 fAmbientColor.set(0.0f, 0.0f, 0.0f); |
138 for (int i = 0; i < lights->numLights(); ++i) { | 130 for (int i = 0; i < lights->numLights(); ++i) { |
139 if (SkLights::Light::kAmbient_LightType == lights->light(i).type()) { | 131 if (SkLights::Light::kAmbient_LightType == lights->light(i).type()) { |
140 fAmbientColor += lights->light(i).color(); | 132 fAmbientColor += lights->light(i).color(); |
141 } else { | 133 } else { |
142 // TODO: handle more than one of these | 134 // TODO: handle more than one of these |
143 fLightColor = lights->light(i).color(); | 135 fLightColor = lights->light(i).color(); |
144 fLightDir = lights->light(i).dir(); | 136 fLightDir = lights->light(i).dir(); |
145 } | 137 } |
146 } | 138 } |
147 | 139 |
140 this->registerChildProcessor(std::move(diffuseFP)); | |
148 this->registerChildProcessor(std::move(normalFP)); | 141 this->registerChildProcessor(std::move(normalFP)); |
149 this->initClassID<LightingFP>(); | 142 this->initClassID<LightingFP>(); |
150 } | 143 } |
151 | 144 |
152 class GLSLLightingFP : public GrGLSLFragmentProcessor { | 145 class GLSLLightingFP : public GrGLSLFragmentProcessor { |
153 public: | 146 public: |
154 GLSLLightingFP() { | 147 GLSLLightingFP() { |
155 fLightDir.fX = 10000.0f; | 148 fLightDir.fX = 10000.0f; |
156 fLightColor.fX = 0.0f; | 149 fLightColor.fX = 0.0f; |
157 fAmbientColor.fX = 0.0f; | 150 fAmbientColor.fX = 0.0f; |
(...skipping 13 matching lines...) Expand all Loading... | |
171 const char* lightColorUniName = nullptr; | 164 const char* lightColorUniName = nullptr; |
172 fLightColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, | 165 fLightColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, |
173 kVec3f_GrSLType, kDefaul t_GrSLPrecision, | 166 kVec3f_GrSLType, kDefaul t_GrSLPrecision, |
174 "LightColor", &lightColo rUniName); | 167 "LightColor", &lightColo rUniName); |
175 | 168 |
176 const char* ambientColorUniName = nullptr; | 169 const char* ambientColorUniName = nullptr; |
177 fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag , | 170 fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag , |
178 kVec3f_GrSLType, kDefa ult_GrSLPrecision, | 171 kVec3f_GrSLType, kDefa ult_GrSLPrecision, |
179 "AmbientColor", &ambie ntColorUniName); | 172 "AmbientColor", &ambie ntColorUniName); |
180 | 173 |
181 fragBuilder->codeAppend("vec4 diffuseColor = "); | 174 SkString dstDiffuseName("dstDiffuse"); |
182 fragBuilder->appendTextureLookupAndModulate(args.fInputColor, args.f TexSamplers[0], | 175 this->emitChild(0, args.fInputColor, &dstDiffuseName, args); |
183 args.fCoords[0].c_str(), | 176 fragBuilder->codeAppendf("vec4 diffuseColor = %s;", dstDiffuseName.c _str()); |
184 args.fCoords[0].getType()); | |
185 fragBuilder->codeAppend(";"); | |
186 | 177 |
187 SkString dstNormalName("dstNormal"); | 178 SkString dstNormalName("dstNormal"); |
188 this->emitChild(0, nullptr, &dstNormalName, args); | 179 this->emitChild(1, nullptr, &dstNormalName, args); |
189 | 180 |
190 fragBuilder->codeAppendf("vec3 normal = %s.xyz;", dstNormalName.c_st r()); | 181 fragBuilder->codeAppendf("vec3 normal = %s.xyz;", dstNormalName.c_st r()); |
191 fragBuilder->codeAppendf("float NdotL = clamp(dot(normal, %s), 0.0, 1.0);", | 182 fragBuilder->codeAppendf("float NdotL = clamp(dot(normal, %s), 0.0, 1.0);", |
192 lightDirUniName); | 183 lightDirUniName); |
193 // diffuse light | 184 // diffuse light |
194 fragBuilder->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;", lightColorUniName); | 185 fragBuilder->codeAppendf("vec3 result = %s*diffuseColor.rgb*NdotL;", lightColorUniName); |
195 // ambient light | 186 // ambient light |
196 fragBuilder->codeAppendf("result += %s;", ambientColorUniName); | 187 fragBuilder->codeAppendf("result += %s;", ambientColorUniName); |
197 fragBuilder->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", a rgs.fOutputColor); | 188 fragBuilder->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", a rgs.fOutputColor); |
198 } | 189 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 | 241 |
251 const SkVector3& lightDir() const { return fLightDir; } | 242 const SkVector3& lightDir() const { return fLightDir; } |
252 const SkColor3f& lightColor() const { return fLightColor; } | 243 const SkColor3f& lightColor() const { return fLightColor; } |
253 const SkColor3f& ambientColor() const { return fAmbientColor; } | 244 const SkColor3f& ambientColor() const { return fAmbientColor; } |
254 | 245 |
255 private: | 246 private: |
256 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLLightingFP; } | 247 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLLightingFP; } |
257 | 248 |
258 bool onIsEqual(const GrFragmentProcessor& proc) const override { | 249 bool onIsEqual(const GrFragmentProcessor& proc) const override { |
259 const LightingFP& lightingFP = proc.cast<LightingFP>(); | 250 const LightingFP& lightingFP = proc.cast<LightingFP>(); |
260 return fDiffDeviceTransform == lightingFP.fDiffDeviceTransform && | 251 return fLightDir == lightingFP.fLightDir && |
261 fDiffuseTextureAccess == lightingFP.fDiffuseTextureAccess && | |
262 fLightDir == lightingFP.fLightDir && | |
263 fLightColor == lightingFP.fLightColor && | 252 fLightColor == lightingFP.fLightColor && |
264 fAmbientColor == lightingFP.fAmbientColor; | 253 fAmbientColor == lightingFP.fAmbientColor; |
265 } | 254 } |
266 | 255 |
267 GrCoordTransform fDiffDeviceTransform; | |
268 GrTextureAccess fDiffuseTextureAccess; | |
269 SkVector3 fLightDir; | 256 SkVector3 fLightDir; |
270 SkColor3f fLightColor; | 257 SkColor3f fLightColor; |
271 SkColor3f fAmbientColor; | 258 SkColor3f fAmbientColor; |
272 }; | 259 }; |
273 | 260 |
274 //////////////////////////////////////////////////////////////////////////// | 261 //////////////////////////////////////////////////////////////////////////// |
275 | 262 |
276 static bool make_mat(const SkBitmap& bm, | |
277 const SkMatrix& localMatrix1, | |
278 const SkMatrix* localMatrix2, | |
279 SkMatrix* result) { | |
280 | |
281 result->setIDiv(bm.width(), bm.height()); | |
282 | |
283 SkMatrix lmInverse; | |
284 if (!localMatrix1.invert(&lmInverse)) { | |
285 return false; | |
286 } | |
287 if (localMatrix2) { | |
288 SkMatrix inv; | |
289 if (!localMatrix2->invert(&inv)) { | |
290 return false; | |
291 } | |
292 lmInverse.postConcat(inv); | |
293 } | |
294 result->preConcat(lmInverse); | |
295 | |
296 return true; | |
297 } | |
298 | |
299 sk_sp<GrFragmentProcessor> SkLightingShaderImpl::asFragmentProcessor( | 263 sk_sp<GrFragmentProcessor> SkLightingShaderImpl::asFragmentProcessor( |
300 GrContext* context, | 264 GrContext* context, |
301 const SkMatrix& viewM, | 265 const SkMatrix& viewM, |
302 const SkMatrix* localMatrix , | 266 const SkMatrix* localMatrix , |
303 SkFilterQuality filterQuali ty, | 267 SkFilterQuality filterQuali ty, |
304 SkSourceGammaTreatment gamm aTreatment) const { | 268 SkSourceGammaTreatment gamm aTreatment) const { |
305 // we assume diffuse and normal maps have same width and height | 269 sk_sp<GrFragmentProcessor> diffuseFP( |
306 // TODO: support different sizes, will be addressed when diffuse maps are fa ctored out of | 270 fDiffuseShader->asFragmentProcessor(context, viewM, localMatrix, fil terQuality, |
307 // SkLightingShader in a future CL | 271 gammaTreatment)); |
308 SkMatrix diffM; | |
309 | |
310 if (!make_mat(fDiffuseMap, this->getLocalMatrix(), localMatrix, &diffM)) { | |
311 return nullptr; | |
312 } | |
313 | |
314 bool doBicubic; | |
315 GrTextureParams::FilterMode diffFilterMode = GrSkFilterQualityToGrFilterMode ( | |
316 SkTMin(filterQuality, kMediu m_SkFilterQuality), | |
317 viewM, | |
318 this->getLocalMatrix(), | |
319 &doBicubic); | |
320 SkASSERT(!doBicubic); | |
321 | |
322 // TODO: support other tile modes | |
323 GrTextureParams diffParams(kClamp_TileMode, diffFilterMode); | |
324 SkAutoTUnref<GrTexture> diffuseTexture(GrRefCachedBitmapTexture(context, fDi ffuseMap, | |
325 diffParams, gammaTreatment)); | |
326 if (!diffuseTexture) { | |
327 SkErrorInternals::SetError(kInternalError_SkError, "Couldn't convert bit map to texture."); | |
328 return nullptr; | |
329 } | |
330 | |
331 sk_sp<GrFragmentProcessor> normalFP( | 272 sk_sp<GrFragmentProcessor> normalFP( |
332 fNormalSource->asFragmentProcessor(context, viewM, localMatrix, filt erQuality, | 273 fNormalSource->asFragmentProcessor(context, viewM, localMatrix, filt erQuality, |
333 gammaTreatment)); | 274 gammaTreatment)); |
334 sk_sp<GrFragmentProcessor> inner ( | 275 sk_sp<GrFragmentProcessor> inner ( |
335 new LightingFP(diffuseTexture, diffM, diffParams, fLights, std::move (normalFP))); | 276 new LightingFP(std::move(diffuseFP), std::move(normalFP), fLights)); |
egdaniel
2016/06/27 13:55:39
Should diffuseFP actually be a child of LightingFP
dvonbeck
2016/06/27 15:15:45
That makes a lot of sense. I'll refactor it that w
dvonbeck
2016/06/28 20:33:37
Done.
| |
336 | 277 |
337 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); | 278 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); |
338 } | 279 } |
339 | 280 |
340 #endif | 281 #endif |
341 | 282 |
342 //////////////////////////////////////////////////////////////////////////// | 283 //////////////////////////////////////////////////////////////////////////// |
343 | 284 |
344 bool SkLightingShaderImpl::isOpaque() const { | 285 bool SkLightingShaderImpl::isOpaque() const { |
345 return fDiffuseMap.isOpaque(); | 286 return fDiffuseShader->isOpaque(); |
346 } | 287 } |
347 | 288 |
348 SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( | 289 SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( |
349 const SkLightingShaderImpl& shader, const ContextRec& rec, SkBitmapProcS tate* diffuseState, | 290 const SkLightingShaderImpl& shader, const ContextRec& rec, |
350 SkNormalSource::Provider* normalProvider) | 291 SkShader::Context* diffuseContext, SkNormalSource::Provider* normalProvi der, |
292 void* heapAllocated) | |
351 : INHERITED(shader, rec) | 293 : INHERITED(shader, rec) |
352 , fDiffuseState(diffuseState) | 294 , fDiffuseContext(diffuseContext) |
353 , fNormalProvider(normalProvider) { | 295 , fNormalProvider(normalProvider) |
354 const SkPixmap& pixmap = fDiffuseState->fPixmap; | 296 , fHeapAllocated(heapAllocated) { |
355 bool isOpaque = pixmap.isOpaque(); | 297 bool isOpaque = shader.isOpaque(); |
356 | 298 |
357 // update fFlags | 299 // update fFlags |
358 uint32_t flags = 0; | 300 uint32_t flags = 0; |
359 if (isOpaque && (255 == this->getPaintAlpha())) { | 301 if (isOpaque && (255 == this->getPaintAlpha())) { |
360 flags |= kOpaqueAlpha_Flag; | 302 flags |= kOpaqueAlpha_Flag; |
361 } | 303 } |
362 | 304 |
363 fFlags = flags; | 305 fFlags = flags; |
364 } | 306 } |
365 | 307 |
366 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { | 308 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { |
367 // The bitmap proc states have been created outside of the context on memory that will be freed | 309 // The dependencies have been created outside of the context on memory that was allocated by |
368 // elsewhere. Call the destructors but leave the freeing of the memory to th e caller. | 310 // the onCreateContext() method. Call the destructors and free the memory. |
369 fDiffuseState->~SkBitmapProcState(); | 311 fDiffuseContext->~Context(); |
370 fNormalProvider->~Provider(); | 312 fNormalProvider->~Provider(); |
313 | |
314 free(fHeapAllocated); | |
371 } | 315 } |
372 | 316 |
373 static inline SkPMColor convert(SkColor3f color, U8CPU a) { | 317 static inline SkPMColor convert(SkColor3f color, U8CPU a) { |
374 if (color.fX <= 0.0f) { | 318 if (color.fX <= 0.0f) { |
375 color.fX = 0.0f; | 319 color.fX = 0.0f; |
376 } else if (color.fX >= 255.0f) { | 320 } else if (color.fX >= 255.0f) { |
377 color.fX = 255.0f; | 321 color.fX = 255.0f; |
378 } | 322 } |
379 | 323 |
380 if (color.fY <= 0.0f) { | 324 if (color.fY <= 0.0f) { |
381 color.fY = 0.0f; | 325 color.fY = 0.0f; |
382 } else if (color.fY >= 255.0f) { | 326 } else if (color.fY >= 255.0f) { |
383 color.fY = 255.0f; | 327 color.fY = 255.0f; |
384 } | 328 } |
385 | 329 |
386 if (color.fZ <= 0.0f) { | 330 if (color.fZ <= 0.0f) { |
387 color.fZ = 0.0f; | 331 color.fZ = 0.0f; |
388 } else if (color.fZ >= 255.0f) { | 332 } else if (color.fZ >= 255.0f) { |
389 color.fZ = 255.0f; | 333 color.fZ = 255.0f; |
390 } | 334 } |
391 | 335 |
392 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ) ; | 336 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ) ; |
393 } | 337 } |
394 | 338 |
395 // larger is better (fewer times we have to loop), but we shouldn't | 339 // larger is better (fewer times we have to loop), but we shouldn't |
396 // take up too much stack-space (each one here costs 16 bytes) | 340 // take up too much stack-space (each one here costs 16 bytes) |
397 #define TMP_COUNT 16 | 341 #define BUFFER_MAX 16 |
398 #define BUFFER_MAX ((int)(TMP_COUNT * sizeof(uint32_t))) | |
399 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, | 342 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, |
400 SkPMColor result[], int count) { | 343 SkPMColor result[], int count) { |
401 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader Impl&>(fShader); | 344 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader Impl&>(fShader); |
402 | 345 |
403 uint32_t tmpColor[TMP_COUNT]; | 346 SkPMColor diffuse[BUFFER_MAX]; |
404 SkPMColor tmpColor2[2*TMP_COUNT]; | |
405 | |
406 SkBitmapProcState::MatrixProc diffMProc = fDiffuseState->getMatrixProc(); | |
407 SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32() ; | |
408 | |
409 int max = fDiffuseState->maxCountForBufferSize(BUFFER_MAX); | |
410 | |
411 SkASSERT(fDiffuseState->fPixmap.addr()); | |
412 | |
413 SkASSERT(max <= BUFFER_MAX); | |
414 SkPoint3 normals[BUFFER_MAX]; | 347 SkPoint3 normals[BUFFER_MAX]; |
415 | 348 |
416 do { | 349 do { |
417 int n = count; | 350 int n = SkTMin(count, BUFFER_MAX); |
418 if (n > max) { | |
419 n = max; | |
420 } | |
421 | 351 |
422 diffMProc(*fDiffuseState, tmpColor, n, x, y); | 352 fDiffuseContext->shadeSpan(x, y, diffuse, n); |
423 diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); | |
424 | |
425 fNormalProvider->fillScanLine(x, y, normals, n); | 353 fNormalProvider->fillScanLine(x, y, normals, n); |
426 | 354 |
427 for (int i = 0; i < n; ++i) { | 355 for (int i = 0; i < n; ++i) { |
428 | 356 |
429 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | 357 SkColor diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]); |
430 | 358 |
431 SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); | 359 SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); |
432 // This is all done in linear unpremul color space (each component 0 ..255.0f though) | 360 // This is all done in linear unpremul color space (each component 0 ..255.0f though) |
433 for (int l = 0; l < lightShader.fLights->numLights(); ++l) { | 361 for (int l = 0; l < lightShader.fLights->numLights(); ++l) { |
434 const SkLights::Light& light = lightShader.fLights->light(l); | 362 const SkLights::Light& light = lightShader.fLights->light(l); |
435 | 363 |
436 if (SkLights::Light::kAmbient_LightType == light.type()) { | 364 if (SkLights::Light::kAmbient_LightType == light.type()) { |
437 accum += light.color().makeScale(255.0f); | 365 accum += light.color().makeScale(255.0f); |
438 } else { | 366 } else { |
439 SkScalar NdotL = normals[i].dot(light.dir()); | 367 SkScalar NdotL = normals[i].dot(light.dir()); |
(...skipping 18 matching lines...) Expand all Loading... | |
458 | 386 |
459 //////////////////////////////////////////////////////////////////////////// | 387 //////////////////////////////////////////////////////////////////////////// |
460 | 388 |
461 #ifndef SK_IGNORE_TO_STRING | 389 #ifndef SK_IGNORE_TO_STRING |
462 void SkLightingShaderImpl::toString(SkString* str) const { | 390 void SkLightingShaderImpl::toString(SkString* str) const { |
463 str->appendf("LightingShader: ()"); | 391 str->appendf("LightingShader: ()"); |
464 } | 392 } |
465 #endif | 393 #endif |
466 | 394 |
467 sk_sp<SkFlattenable> SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) { | 395 sk_sp<SkFlattenable> SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) { |
468 SkMatrix diffLocalM; | |
469 bool hasDiffLocalM = buf.readBool(); | |
470 if (hasDiffLocalM) { | |
471 buf.readMatrix(&diffLocalM); | |
472 } else { | |
473 diffLocalM.reset(); | |
474 } | |
475 | 396 |
476 SkBitmap diffuse; | 397 // Discarding SkShader flattenable params |
477 if (!buf.readBitmap(&diffuse)) { | 398 bool hasLocalMatrix = buf.readBool(); |
478 return nullptr; | 399 SkASSERT(!hasLocalMatrix); |
479 } | |
480 diffuse.setImmutable(); | |
481 | 400 |
482 int numLights = buf.readInt(); | 401 int numLights = buf.readInt(); |
483 | 402 |
484 SkLights::Builder builder; | 403 SkLights::Builder builder; |
485 | 404 |
486 for (int l = 0; l < numLights; ++l) { | 405 for (int l = 0; l < numLights; ++l) { |
487 bool isAmbient = buf.readBool(); | 406 bool isAmbient = buf.readBool(); |
488 | 407 |
489 SkColor3f color; | 408 SkColor3f color; |
490 if (!buf.readScalarArray(&color.fX, 3)) { | 409 if (!buf.readScalarArray(&color.fX, 3)) { |
491 return nullptr; | 410 return nullptr; |
492 } | 411 } |
493 | 412 |
494 if (isAmbient) { | 413 if (isAmbient) { |
495 builder.add(SkLights::Light(color)); | 414 builder.add(SkLights::Light(color)); |
496 } else { | 415 } else { |
497 SkVector3 dir; | 416 SkVector3 dir; |
498 if (!buf.readScalarArray(&dir.fX, 3)) { | 417 if (!buf.readScalarArray(&dir.fX, 3)) { |
499 return nullptr; | 418 return nullptr; |
500 } | 419 } |
501 builder.add(SkLights::Light(color, dir)); | 420 builder.add(SkLights::Light(color, dir)); |
502 } | 421 } |
503 } | 422 } |
504 | 423 |
505 sk_sp<SkLights> lights(builder.finish()); | 424 sk_sp<SkLights> lights(builder.finish()); |
506 | 425 |
507 sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>()); | 426 sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>()); |
427 sk_sp<SkShader> diffuseShader(buf.readFlattenable<SkShader>()); | |
508 | 428 |
509 return sk_make_sp<SkLightingShaderImpl>(diffuse, std::move(lights), &diffLoc alM, | 429 return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move( normalSource), |
510 std::move(normalSource)); | 430 std::move(lights)); |
511 } | 431 } |
512 | 432 |
513 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { | 433 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { |
514 this->INHERITED::flatten(buf); | 434 this->INHERITED::flatten(buf); |
515 | 435 |
516 buf.writeBitmap(fDiffuseMap); | |
517 | |
518 buf.writeInt(fLights->numLights()); | 436 buf.writeInt(fLights->numLights()); |
519 for (int l = 0; l < fLights->numLights(); ++l) { | 437 for (int l = 0; l < fLights->numLights(); ++l) { |
520 const SkLights::Light& light = fLights->light(l); | 438 const SkLights::Light& light = fLights->light(l); |
521 | 439 |
522 bool isAmbient = SkLights::Light::kAmbient_LightType == light.type(); | 440 bool isAmbient = SkLights::Light::kAmbient_LightType == light.type(); |
523 | 441 |
524 buf.writeBool(isAmbient); | 442 buf.writeBool(isAmbient); |
525 buf.writeScalarArray(&light.color().fX, 3); | 443 buf.writeScalarArray(&light.color().fX, 3); |
526 if (!isAmbient) { | 444 if (!isAmbient) { |
527 buf.writeScalarArray(&light.dir().fX, 3); | 445 buf.writeScalarArray(&light.dir().fX, 3); |
528 } | 446 } |
529 } | 447 } |
530 | 448 |
531 buf.writeFlattenable(fNormalSource.get()); | 449 buf.writeFlattenable(fNormalSource.get()); |
450 buf.writeFlattenable(fDiffuseShader.get()); | |
532 } | 451 } |
533 | 452 |
534 size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const { | 453 size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const { |
535 return sizeof(LightingShaderContext) + | 454 return sizeof(LightingShaderContext); |
536 sizeof(SkBitmapProcState) + | |
537 fNormalSource->providerSize(rec); | |
538 } | 455 } |
539 | 456 |
540 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, | 457 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, |
541 void* storage) const { | 458 void* storage) const { |
542 | 459 |
543 SkMatrix diffTotalInv; | 460 size_t heapRequired = fDiffuseShader->contextSize(rec) + fNormalSource->prov iderSize(rec); |
544 // computeTotalInverse was called in SkShader::createContext so we know it w ill succeed | 461 void* heapAllocated = malloc(heapRequired); // Freed on ~LightingShaderConte xt() |
545 SkAssertResult(this->computeTotalInverse(rec, &diffTotalInv)); | |
546 | 462 |
547 void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); | 463 void* diffuseContextStorage = (char*)heapAllocated; |
548 SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcStat e(fDiffuseMap, | |
549 SkShader::kClamp_TileMode, SkShade r::kClamp_TileMode, | |
550 SkMipMap::De duceTreatment(rec)); | |
551 SkASSERT(diffuseState); | |
552 if (!diffuseState->setup(diffTotalInv, *rec.fPaint)) { | |
553 diffuseState->~SkBitmapProcState(); | |
554 return nullptr; | |
555 } | |
556 void* normalProviderStorage = (char*)storage + | |
557 sizeof(LightingShaderContext) + | |
558 sizeof(SkBitmapProcState); | |
559 | 464 |
560 SkNormalSource::Provider* normalProvider = fNormalSource->asProvider(rec, | 465 SkShader::Context* diffuseContext = fDiffuseShader->createContext(rec, diffu seContextStorage); |
561 normalP roviderStorage); | 466 |
467 void* normalProviderStorage = (char*)heapAllocated + fDiffuseShader->context Size(rec); | |
468 SkNormalSource::Provider* normalProvider = | |
469 fNormalSource->asProvider(rec, normalProviderStorage); | |
562 if (!normalProvider) { | 470 if (!normalProvider) { |
563 diffuseState->~SkBitmapProcState(); | 471 diffuseContext->~Context(); |
472 free(heapAllocated); | |
564 return nullptr; | 473 return nullptr; |
565 } | 474 } |
566 | 475 |
567 return new (storage) LightingShaderContext(*this, rec, diffuseState, normalP rovider); | 476 return new (storage) LightingShaderContext(*this, rec, diffuseContext, norma lProvider, |
477 heapAllocated); | |
568 } | 478 } |
569 | 479 |
570 /////////////////////////////////////////////////////////////////////////////// | 480 /////////////////////////////////////////////////////////////////////////////// |
571 | 481 |
572 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, sk_sp<SkLights> lights, | 482 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, sk_sp<SkLights> lights, |
573 const SkMatrix* diffLocalM, sk_sp<SkNormalSource> normalSource) { | 483 const SkMatrix* diffLocalM, sk_sp<SkNormalSource> normalSource) { |
574 if (diffuse.isNull() || SkBitmapProcShader::BitmapIsTooBig(diffuse)) { | 484 if (diffuse.isNull() || SkBitmapProcShader::BitmapIsTooBig(diffuse)) { |
575 return nullptr; | 485 return nullptr; |
576 } | 486 } |
577 | 487 |
578 if (!normalSource) { | 488 if (!normalSource) { |
579 // TODO: Use a default implementation of normalSource instead | 489 // TODO: Use a default implementation of normalSource instead |
580 return nullptr; | 490 return nullptr; |
581 } | 491 } |
582 | 492 |
583 return sk_make_sp<SkLightingShaderImpl>(diffuse, std::move(lights), diffLoca lM, | 493 // TODO: support other tile modes |
584 std::move(normalSource)); | 494 sk_sp<SkShader> diffuseShader = SkBitmapProcShader::MakeBitmapShader(diffuse , |
495 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, diffLocalM); | |
496 | |
497 return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move( normalSource), | |
498 std::move(lights)); | |
585 } | 499 } |
586 | 500 |
587 /////////////////////////////////////////////////////////////////////////////// | 501 /////////////////////////////////////////////////////////////////////////////// |
588 | 502 |
589 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) | 503 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) |
590 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) | 504 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) |
591 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 505 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
592 | 506 |
593 /////////////////////////////////////////////////////////////////////////////// | 507 /////////////////////////////////////////////////////////////////////////////// |
OLD | NEW |