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