OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SkBitmapProcShader.h" | |
9 #include "SkBitmapProcState.h" | |
10 #include "SkShadowShader.h" | |
11 #include "SkPoint3.h" | |
12 #include "SkReadBuffer.h" | |
13 #include "SkLights.h" | |
14 | |
15 //////////////////////////////////////////////////////////////////////////// | |
16 #define SK_MAX_NON_AMBIENT_LIGHTS 4 | |
17 | |
18 /** \class SkShadowShaderImpl | |
19 This subclass of shader applies shadowing | |
20 */ | |
21 class SkShadowShaderImpl : public SkShader { | |
22 public: | |
23 /** Create a new shadowing shader that shadows | |
24 @param to do to do | |
25 */ | |
26 SkShadowShaderImpl(sk_sp<SkShader> povDepthShader, | |
27 sk_sp<SkShader> diffuseShader, | |
28 sk_sp<SkLights> lights) | |
29 : povDepthShader(std::move(povDepthShader)) | |
30 , diffuseShader(std::move(diffuseShader)) | |
31 , fLights(std::move(lights)) { } | |
32 | |
33 bool isOpaque() const override; | |
34 | |
35 #if SK_SUPPORT_GPU | |
36 sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, | |
37 const SkMatrix& viewM, | |
38 const SkMatrix* localMatrix, | |
39 SkFilterQuality, | |
40 SkSourceGammaTreatment) const override; | |
41 #endif | |
42 | |
43 class ShadowShaderContext : public SkShader::Context { | |
44 public: | |
45 // The context takes ownership of the states. It will call their destruc tors | |
46 // but will NOT free the memory. | |
47 ShadowShaderContext(const SkShadowShaderImpl&, const ContextRec&, | |
48 SkShader::Context* povDepthContext, | |
49 SkShader::Context* diffuseContext, | |
50 void* heapAllocated); | |
51 | |
52 ~ShadowShaderContext() override; | |
53 | |
54 void shadeSpan(int x, int y, SkPMColor[], int count) override; | |
55 | |
56 uint32_t getFlags() const override { return fFlags; } | |
57 | |
58 private: | |
59 SkShader::Context* fDiffuseContext1; | |
60 SkShader::Context* fDiffuseContext2; | |
61 uint32_t fFlags; | |
62 | |
63 void* fHeapAllocated; | |
64 | |
65 typedef SkShader::Context INHERITED; | |
66 }; | |
67 | |
robertphillips
2016/07/27 18:52:59
I think these two lines are supposed to be tabbed
vjiaoblack
2016/07/28 17:17:51
Done.
| |
68 SK_TO_STRING_OVERRIDE() | |
69 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkShadowShaderImpl) | |
70 | |
71 protected: | |
72 void flatten(SkWriteBuffer&) const override; | |
73 size_t onContextSize(const ContextRec&) const override; | |
74 Context* onCreateContext(const ContextRec&, void*) const override; | |
75 | |
76 private: | |
77 sk_sp<SkShader> povDepthShader; | |
78 sk_sp<SkShader> diffuseShader; | |
79 sk_sp<SkLights> fLights; | |
80 | |
81 friend class SkShadowShader; | |
82 | |
83 typedef SkShader INHERITED; | |
84 }; | |
85 | |
86 //////////////////////////////////////////////////////////////////////////// | |
87 | |
88 #if SK_SUPPORT_GPU | |
89 | |
90 #include "GrCoordTransform.h" | |
91 #include "GrFragmentProcessor.h" | |
92 #include "GrInvariantOutput.h" | |
93 #include "GrTextureAccess.h" | |
94 #include "glsl/GrGLSLFragmentProcessor.h" | |
95 #include "glsl/GrGLSLFragmentShaderBuilder.h" | |
96 #include "glsl/GrGLSLProgramDataManager.h" | |
97 #include "glsl/GrGLSLUniformHandler.h" | |
98 #include "SkGr.h" | |
99 #include "SkGrPriv.h" | |
100 #include "SkSpecialImage.h" | |
101 #include "SkImage_Base.h" | |
102 #include "SkImageInfo.h" | |
103 #include "GrContext.h" | |
104 #include "GrContextOptions.h" | |
105 | |
106 class ShadowFP : public GrFragmentProcessor { | |
107 public: | |
108 ShadowFP(sk_sp<GrFragmentProcessor> povDepth, | |
109 sk_sp<GrFragmentProcessor> diffuse, | |
110 sk_sp<SkLights> lights, | |
111 GrContext* context) { | |
112 | |
113 // fuse all ambient lights into a single one | |
114 fAmbientColor.set(0.0f, 0.0f, 0.0f); | |
115 | |
116 fGrContext = context; | |
jvanverth1
2016/07/27 17:46:04
Do you use this anywhere else? If not, you don't n
vjiaoblack
2016/07/28 17:17:51
Done.
| |
117 | |
118 fNumDirLights = 0; // refers to directional lights. | |
119 for (int i = 0; i < lights->numLights(); ++i) { | |
120 if (SkLights::Light::kAmbient_LightType == lights->light(i).type()) { | |
121 fAmbientColor += lights->light(i).color(); | |
122 } else if (fNumDirLights < SK_MAX_NON_AMBIENT_LIGHTS){ | |
123 fNumDirLights++; | |
robertphillips
2016/07/27 18:52:59
I think you need to index by fNumDirLights (in the
vjiaoblack
2016/07/28 17:17:52
Done.
| |
124 fLightColor[i] = lights->light(i).color(); | |
125 fLightDir[i] = lights->light(i).dir(); | |
126 SkImage_Base* shadowMap = ((SkImage_Base*)lights->light(i).getSh adowMap().get()); | |
127 | |
128 // this sk_sp gets deleted when the ShadowFP is destroyed, and f rees the GrTexture* | |
robertphillips
2016/07/27 18:52:59
IIUC, asTextureRef returns a "GrTexture*" so I thi
vjiaoblack
2016/07/28 17:17:52
Done.
| |
129 fTexture[i] = sk_sp<GrTexture>(std::move(shadowMap->asTextureRef (fGrContext, | |
130 GrTextur eParams::ClampNoFilter(), | |
jvanverth1
2016/07/27 17:46:04
Still over 100 chars.
vjiaoblack
2016/07/28 17:17:51
Done.
| |
131 SkSource GammaTreatment::kIgnore))); | |
132 fDepthMapAccess[i].reset(fTexture[i].get()); | |
133 this->addTextureAccess(&fDepthMapAccess[i]); | |
134 } | |
135 } | |
136 | |
137 this->registerChildProcessor(std::move(povDepth)); | |
138 this->registerChildProcessor(std::move(diffuse)); | |
139 this->initClassID<ShadowFP>(); | |
140 } | |
141 | |
142 class GLSLShadowFP : public GrGLSLFragmentProcessor { | |
143 public: | |
144 GLSLShadowFP() { } | |
145 | |
146 void emitCode(EmitArgs& args) override { | |
147 | |
148 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; | |
149 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; | |
150 | |
151 // add uniforms | |
152 int32_t numLights = args.fFp.cast<ShadowFP>().fNumDirLights; | |
153 | |
154 const char* lightDirUniName[SK_MAX_NON_AMBIENT_LIGHTS] = {nullptr}; | |
155 const char* lightColorUniName[SK_MAX_NON_AMBIENT_LIGHTS] = {nullptr} ; | |
156 | |
157 for (int i = 0; i < numLights; i++) { | |
158 lightDirUniName[i] = nullptr; | |
159 fLightDirUni[i] = uniformHandler->addUniform(kFragment_GrShaderF lag, | |
160 kVec3f_GrSLType, kD efault_GrSLPrecision, | |
jvanverth1
2016/07/27 17:46:04
Over 100 chars?
vjiaoblack
2016/07/28 17:17:51
Done.
| |
161 "LightDir" + (i+1), &lightDirUniName[i]); | |
162 | |
163 lightColorUniName[i] = nullptr; | |
164 fLightColorUni[i] = uniformHandler->addUniform(kFragment_GrShade rFlag, | |
165 kVec3f_GrSLType, kDefault_GrSLPrecision, | |
jvanverth1
2016/07/27 17:46:04
Over 100 chars?
vjiaoblack
2016/07/28 17:17:51
Done.
| |
166 "LightColor" + (i +1), &lightColorUniName[i]); | |
167 } | |
168 | |
169 SkString povDepth("povDepth"); | |
170 this->emitChild(0, nullptr, &povDepth, args); | |
171 | |
172 SkString diffuseColor("inDiffuseColor"); | |
173 this->emitChild(1, nullptr, &diffuseColor, args); | |
174 | |
175 SkString depthMaps[SK_MAX_NON_AMBIENT_LIGHTS]; | |
176 | |
177 for (int i = 0; i < numLights; i++) { | |
178 const char* povCoord = "povCoord" + i; | |
179 | |
180 // vMatrixCoord_0_1_Stage0 is the texture sampler coordinates. | |
181 // povDepth.b * 255 scales it to 0 - 255, bringing it to world s pace, | |
robertphillips
2016/07/27 18:52:59
Is the 400 coming from the fact that the GM has a
vjiaoblack
2016/07/28 17:17:51
Yes. I'll pass this stuff in when I migrate to a S
robertphillips
2016/07/28 19:47:25
Well, isn't the 400 value going to have to vary wi
| |
182 // and the / 400 brings it back to a sampler coordinate, 0 - 1 | |
183 fragBuilder->codeAppendf("vec2 %s = vMatrixCoord_0_1_Stage0 + " | |
184 "(vec2(%s) * povDepth.b * 255 / 400);", | |
185 povCoord, lightDirUniName[i]); | |
186 | |
187 fragBuilder->appendTextureLookup(&depthMaps[i], args.fTexSampler s[i], | |
188 povCoord, | |
189 kVec2f_GrSLType); | |
190 } | |
191 | |
192 const char* ambientColorUniName = nullptr; | |
193 fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag , | |
194 kVec3f_GrSLType, kDefa ult_GrSLPrecision, | |
195 "AmbientColor", &ambie ntColorUniName); | |
196 | |
197 fragBuilder->codeAppendf("vec4 resultDiffuseColor = %s;", diffuseCol or.c_str()); | |
198 | |
199 // all the normal vectors point straight up | |
200 SkString totalLightColor("totalLightColor"); | |
201 fragBuilder->codeAppendf("vec3 %s = vec3(0,0,0);", | |
202 totalLightColor.c_str()); | |
203 | |
204 for (int i = 0; i < numLights; i++) { | |
205 fragBuilder->codeAppendf("if (%s.b >= %s.b) {", | |
206 povDepth.c_str(), depthMaps[i].c_str()) ; | |
207 fragBuilder->codeAppendf("%s += dot(vec3(0,0,1), %s) * %s;", | |
208 totalLightColor.c_str(), | |
209 lightDirUniName[i], | |
210 lightColorUniName[i]); | |
211 fragBuilder->codeAppendf("}"); | |
212 } | |
213 | |
214 fragBuilder->codeAppendf("%s += %s;", | |
215 totalLightColor.c_str(), | |
216 ambientColorUniName); | |
217 | |
218 fragBuilder->codeAppendf("resultDiffuseColor *= vec4(%s, 1);", | |
219 totalLightColor.c_str()); | |
220 | |
221 fragBuilder->codeAppendf("%s = resultDiffuseColor;", args.fOutputCol or); | |
222 } | |
223 | |
224 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&, | |
225 GrProcessorKeyBuilder* b) { | |
226 const ShadowFP& shadowFP = proc.cast<ShadowFP>(); | |
227 b->add32(shadowFP.fNumDirLights); | |
228 } | |
229 | |
230 protected: | |
231 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override { | |
232 const ShadowFP &shadowFP = proc.cast<ShadowFP>(); | |
233 | |
234 fNumDirLights = shadowFP.numLights(); | |
235 | |
236 for (int i = 0; i < fNumDirLights; i++) { | |
237 const SkVector3 &lightDir = shadowFP.lightDir(i); | |
238 if (lightDir != fLightDir[i]) { | |
239 pdman.set3fv(fLightDirUni[i], 1, &lightDir.fX); | |
240 fLightDir[i] = lightDir; | |
241 } | |
242 const SkColor3f &lightColor = shadowFP.lightColor(i); | |
243 if (lightColor != fLightColor[i]) { | |
244 pdman.set3fv(fLightColorUni[i], 1, &lightColor.fX); | |
245 fLightColor[i] = lightColor; | |
246 } | |
247 } | |
248 | |
249 const SkColor3f& ambientColor = shadowFP.ambientColor(); | |
250 if (ambientColor != fAmbientColor) { | |
251 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX); | |
252 fAmbientColor = ambientColor; | |
253 } | |
254 } | |
255 | |
256 private: | |
257 SkVector3 fLightDir[SK_MAX_NON_AMBIENT_LIGHTS]; | |
robertphillips
2016/07/27 18:52:59
Shouldn't these other 4s be SK_MAX_NON_AMBIENT_LIG
vjiaoblack
2016/07/28 17:17:51
Done.
| |
258 GrGLSLProgramDataManager::UniformHandle fLightDirUni[4]; | |
259 SkColor3f fLightColor[SK_MAX_NON_AMBIENT_LIGHTS]; | |
260 GrGLSLProgramDataManager::UniformHandle fLightColorUni[4]; | |
261 | |
262 SkColor3f fAmbientColor; | |
263 GrGLSLProgramDataManager::UniformHandle fAmbientColorUni; | |
264 | |
265 int fNumDirLights; | |
266 }; | |
267 | |
268 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { | |
269 GLSLShadowFP::GenKey(*this, caps, b); | |
270 } | |
271 | |
272 const char* name() const override { return "shadowFP"; } | |
273 | |
274 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | |
275 inout->mulByUnknownFourComponents(); | |
276 } | |
277 int32_t numLights() const { return fNumDirLights; } | |
278 const SkColor3f& ambientColor() const { return fAmbientColor; } | |
279 const SkVector3& lightDir(int i) const { | |
280 SkASSERT(i < fNumDirLights); | |
281 return fLightDir[i]; | |
282 } | |
283 const SkVector3& lightColor(int i) const { | |
284 SkASSERT(i < fNumDirLights); | |
285 return fLightColor[i]; | |
286 } | |
287 | |
288 private: | |
289 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLShadowFP; } | |
290 | |
291 bool onIsEqual(const GrFragmentProcessor& proc) const override { | |
292 const ShadowFP& shadowFP = proc.cast<ShadowFP>(); | |
robertphillips
2016/07/27 18:52:59
You could just say:
if (fAmbientColor != shadowFP
vjiaoblack
2016/07/28 17:17:51
Done.
| |
293 bool isEqual = fAmbientColor == shadowFP.fAmbientColor && | |
294 fNumDirLights == shadowFP.fNumDirLights; | |
295 | |
296 for (int i = 0; i < fNumDirLights && isEqual; i++) { | |
robertphillips
2016/07/27 18:52:59
Similarly, in here you can just return false if an
vjiaoblack
2016/07/28 17:17:51
Done.
| |
297 isEqual = isEqual && fLightDir[i] == shadowFP.fLightDir[i] && | |
298 fLightColor[i] == shadowFP.fLightColor[i]; | |
299 } | |
300 | |
301 return isEqual; | |
302 } | |
303 | |
304 int fNumDirLights; | |
305 | |
robertphillips
2016/07/27 18:52:59
SK_MAX_NON_AMBIENT_LIGHTS ?
vjiaoblack
2016/07/28 17:17:51
Done.
| |
306 SkVector3 fLightDir[4]; | |
307 SkColor3f fLightColor[4]; | |
308 GrTextureAccess fDepthMapAccess[4]; | |
309 sk_sp<GrTexture> fTexture[4]; | |
310 GrContext* fGrContext; | |
311 | |
312 SkColor3f fAmbientColor; | |
313 }; | |
314 | |
315 //////////////////////////////////////////////////////////////////////////// | |
316 | |
317 sk_sp<GrFragmentProcessor> SkShadowShaderImpl::asFragmentProcessor( | |
318 GrContext* context, | |
319 const SkMatrix& viewM, | |
320 const SkMatrix* localMatrix, | |
321 SkFilterQuality filterQuality, | |
322 SkSourceGammaTreatment gammaTreatment) const { | |
323 | |
robertphillips
2016/07/27 18:52:59
Can you keep the method name next to the '->' and
vjiaoblack
2016/07/28 17:17:51
Done.
| |
324 sk_sp<GrFragmentProcessor> povDepthFP = povDepthShader-> | |
325 asFragmentProcessor(context, viewM, localMatrix, filterQuality, gamm aTreatment); | |
326 | |
327 sk_sp<GrFragmentProcessor> diffuseFP = diffuseShader-> | |
328 asFragmentProcessor(context, viewM, localMatrix, filterQuality, gamm aTreatment); | |
329 | |
robertphillips
2016/07/27 18:52:59
Seems like you want some std::moves for diffuseFP
vjiaoblack
2016/07/28 17:17:52
Done.
| |
330 sk_sp<GrFragmentProcessor> shadowfp = sk_make_sp<ShadowFP>(povDepthFP, diffu seFP, fLights, context); | |
jvanverth1
2016/07/27 17:46:04
100 chars
vjiaoblack
2016/07/28 17:17:51
Done.
| |
331 return shadowfp; | |
332 } | |
333 | |
334 | |
335 #endif | |
336 | |
337 //////////////////////////////////////////////////////////////////////////// | |
338 | |
339 bool SkShadowShaderImpl::isOpaque() const { | |
340 return povDepthShader->isOpaque() || diffuseShader->isOpaque(); | |
341 } | |
342 | |
343 SkShadowShaderImpl::ShadowShaderContext::ShadowShaderContext( | |
344 const SkShadowShaderImpl& shader, const ContextRec& rec, | |
345 SkShader::Context* povDepthContext, | |
346 SkShader::Context* diffuseContext, | |
347 void* heapAllocated) | |
348 : INHERITED(shader, rec) | |
349 , fDiffuseContext1(povDepthContext) | |
350 , fDiffuseContext2(diffuseContext) | |
351 , fHeapAllocated(heapAllocated) { | |
352 bool isOpaque = shader.isOpaque(); | |
353 | |
354 // update fFlags | |
355 uint32_t flags = 0; | |
356 if (isOpaque && (255 == this->getPaintAlpha())) { | |
357 flags |= kOpaqueAlpha_Flag; | |
358 } | |
359 | |
360 fFlags = flags; | |
361 } | |
362 | |
363 SkShadowShaderImpl::ShadowShaderContext::~ShadowShaderContext() { | |
364 // The dependencies have been created outside of the context on memory that was allocated by | |
365 // the onCreateContext() method. Call the destructors and free the memory. | |
366 fDiffuseContext1->~Context(); | |
367 fDiffuseContext2->~Context(); | |
368 | |
369 sk_free(fHeapAllocated); | |
370 } | |
371 | |
372 static inline SkPMColor convert(SkColor3f color, U8CPU a) { | |
373 if (color.fX <= 0.0f) { | |
374 color.fX = 0.0f; | |
375 } else if (color.fX >= 255.0f) { | |
376 color.fX = 255.0f; | |
377 } | |
378 | |
379 if (color.fY <= 0.0f) { | |
380 color.fY = 0.0f; | |
381 } else if (color.fY >= 255.0f) { | |
382 color.fY = 255.0f; | |
383 } | |
384 | |
385 if (color.fZ <= 0.0f) { | |
386 color.fZ = 0.0f; | |
387 } else if (color.fZ >= 255.0f) { | |
388 color.fZ = 255.0f; | |
389 } | |
robertphillips
2016/07/27 18:52:59
rm the printf
vjiaoblack
2016/07/28 17:17:51
Done.
| |
390 // printf(); | |
391 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ) ; | |
392 } | |
393 | |
394 // larger is better (fewer times we have to loop), but we shouldn't | |
395 // take up too much stack-space (each one here costs 16 bytes) | |
396 #define BUFFER_MAX 16 | |
397 void SkShadowShaderImpl::ShadowShaderContext::shadeSpan(int x, int y, | |
398 SkPMColor result[], int count) { | |
399 const SkShadowShaderImpl& lightShader = static_cast<const SkShadowShaderImpl &>(fShader); | |
400 | |
401 SkPMColor diffuse[BUFFER_MAX]; | |
402 SkPoint3 normals[BUFFER_MAX]; | |
403 | |
404 do { | |
405 int n = SkTMin(count, BUFFER_MAX); | |
406 | |
407 fDiffuseContext1->shadeSpan(x, y, diffuse, n); | |
408 fDiffuseContext2->shadeSpan(x, y, diffuse, n); | |
409 | |
410 for (int i = 0; i < n; ++i) { | |
411 | |
412 SkColor diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]); | |
413 | |
414 SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); | |
415 // This is all done in linear unpremul color space (each component 0 ..255.0f though) | |
416 for (int l = 0; l < lightShader.fLights->numLights(); ++l) { | |
417 const SkLights::Light& light = lightShader.fLights->light(l); | |
418 | |
419 if (SkLights::Light::kAmbient_LightType == light.type()) { | |
420 accum += light.color().makeScale(255.0f); | |
421 } else { | |
422 SkScalar NdotL = normals[i].dot(light.dir()); | |
423 if (NdotL < 0.0f) { | |
424 NdotL = 0.0f; | |
425 } | |
426 | |
robertphillips
2016/07/27 18:52:59
It seems like pegging NdotL is going to short circ
vjiaoblack
2016/07/28 17:17:51
Done.
| |
427 NdotL = 1.0f; | |
428 | |
429 accum.fX += light.color().fX * SkColorGetR(diffColor) * Ndot L; | |
430 accum.fY += light.color().fY * SkColorGetG(diffColor) * Ndot L; | |
431 accum.fZ += light.color().fZ * SkColorGetB(diffColor) * Ndot L; | |
432 } | |
433 } | |
434 | |
435 result[i] = convert(accum, SkColorGetA(diffColor)); | |
436 } | |
437 | |
438 result += n; | |
439 x += n; | |
440 count -= n; | |
441 } while (count > 0); | |
442 } | |
443 | |
444 //////////////////////////////////////////////////////////////////////////// | |
445 | |
446 #ifndef SK_IGNORE_TO_STRING | |
447 void SkShadowShaderImpl::toString(SkString* str) const { | |
448 str->appendf("ShadowShader: ()"); | |
449 } | |
450 #endif | |
451 | |
452 sk_sp<SkFlattenable> SkShadowShaderImpl::CreateProc(SkReadBuffer& buf) { | |
453 | |
454 // Discarding SkShader flattenable params | |
455 bool hasLocalMatrix = buf.readBool(); | |
456 SkAssertResult(!hasLocalMatrix); | |
457 | |
458 int numLights = buf.readInt(); | |
459 | |
460 SkLights::Builder builder; | |
461 | |
462 for (int l = 0; l < numLights; ++l) { | |
463 bool isAmbient = buf.readBool(); | |
464 | |
465 SkColor3f color; | |
466 if (!buf.readScalarArray(&color.fX, 3)) { | |
467 return nullptr; | |
468 } | |
469 | |
470 if (isAmbient) { | |
471 builder.add(SkLights::Light(color)); | |
472 } else { | |
473 SkVector3 dir; | |
474 if (!buf.readScalarArray(&dir.fX, 3)) { | |
475 return nullptr; | |
476 } | |
477 builder.add(SkLights::Light(color, dir)); | |
478 } | |
479 } | |
480 | |
481 sk_sp<SkLights> lights(builder.finish()); | |
482 | |
483 sk_sp<SkShader> povDepthShader(buf.readFlattenable<SkShader>()); | |
484 sk_sp<SkShader> diffuseShader(buf.readFlattenable<SkShader>()); | |
485 | |
486 return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader), | |
487 std::move(diffuseShader), | |
488 std::move(lights)); | |
489 } | |
490 | |
491 void SkShadowShaderImpl::flatten(SkWriteBuffer& buf) const { | |
492 this->INHERITED::flatten(buf); | |
493 | |
494 buf.writeInt(fLights->numLights()); | |
495 for (int l = 0; l < fLights->numLights(); ++l) { | |
496 const SkLights::Light& light = fLights->light(l); | |
497 | |
498 bool isAmbient = SkLights::Light::kAmbient_LightType == light.type(); | |
499 | |
500 buf.writeBool(isAmbient); | |
501 buf.writeScalarArray(&light.color().fX, 3); | |
502 if (!isAmbient) { | |
503 buf.writeScalarArray(&light.dir().fX, 3); | |
504 } | |
505 } | |
506 | |
507 buf.writeFlattenable(povDepthShader.get()); | |
508 buf.writeFlattenable(diffuseShader.get()); | |
509 } | |
510 | |
511 size_t SkShadowShaderImpl::onContextSize(const ContextRec& rec) const { | |
512 return sizeof(ShadowShaderContext); | |
513 } | |
514 | |
515 SkShader::Context* SkShadowShaderImpl::onCreateContext(const ContextRec& rec, | |
516 void* storage) const { | |
517 size_t heapRequired = povDepthShader->contextSize(rec) + | |
robertphillips
2016/07/27 18:52:59
extra space ?
vjiaoblack
2016/07/28 17:17:52
Done.
| |
518 diffuseShader->contextSize(rec); | |
519 | |
520 void* heapAllocated = sk_malloc_throw(heapRequired); | |
521 | |
522 void* povDepthContextStorage = heapAllocated; | |
523 | |
524 SkShader::Context* povDepthContext = povDepthShader->createContext(rec, povD epthContextStorage); | |
525 if (!povDepthContext) { | |
526 sk_free(heapAllocated); | |
527 return nullptr; | |
528 } | |
529 | |
530 void* diffuseContextStorage = (char*)heapAllocated + povDepthShader->context Size(rec); | |
531 | |
robertphillips
2016/07/27 18:52:59
I don't think we need the '2' suffix here
vjiaoblack
2016/07/28 17:17:51
Done.
| |
532 SkShader::Context* diffuseContext2 = diffuseShader->createContext(rec, diffu seContextStorage); | |
533 if (!diffuseContext2) { | |
534 sk_free(heapAllocated); | |
535 return nullptr; | |
536 } | |
537 | |
robertphillips
2016/07/27 18:52:59
extra '\n' here ?
vjiaoblack
2016/07/28 17:17:51
Done.
| |
538 | |
539 return new (storage) ShadowShaderContext(*this, rec, povDepthContext, diffus eContext2, | |
540 heapAllocated); | |
541 } | |
542 | |
543 /////////////////////////////////////////////////////////////////////////////// | |
544 | |
545 sk_sp<SkShader> SkShadowShader::Make(sk_sp<SkShader> povDepthShader, | |
546 sk_sp<SkShader> diffuseShader, | |
547 sk_sp<SkLights> lights) { | |
548 if (!povDepthShader || !diffuseShader) { | |
549 // TODO: Use paint's color in absence of a diffuseShader | |
550 // TODO: Use a default implementation of normalSource instead | |
551 return nullptr; | |
552 } | |
553 | |
554 return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader), | |
555 std::move(diffuseShader), | |
556 std::move(lights)); | |
557 } | |
558 | |
559 /////////////////////////////////////////////////////////////////////////////// | |
560 | |
561 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShadowShader) | |
562 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkShadowShaderImpl) | |
563 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | |
564 | |
565 /////////////////////////////////////////////////////////////////////////////// | |
OLD | NEW |