Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(946)

Side by Side Diff: src/core/SkShadowShader.cpp

Issue 2118553002: adding new GM to demostrate new shadows (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: Lines too long Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkShadowShader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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
9 #include "SkLights.h"
10 #include "SkReadBuffer.h"
11 #include "SkShadowShader.h"
12 #include "SkPoint3.h"
13
14 ////////////////////////////////////////////////////////////////////////////
15 #ifdef SK_EXPERIMENTAL_SHADOWING
16
17 #define SK_MAX_NON_AMBIENT_LIGHTS 4
18
19 /** \class SkShadowShaderImpl
20 This subclass of shader applies shadowing
21 */
22 class SkShadowShaderImpl : public SkShader {
23 public:
24 /** Create a new shadowing shader that shadows
25 @param to do to do
26 */
27 SkShadowShaderImpl(sk_sp<SkShader> povDepthShader,
28 sk_sp<SkShader> diffuseShader,
29 sk_sp<SkLights> lights,
30 int diffuseWidth, int diffuseHeight)
31 : fPovDepthShader(std::move(povDepthShader))
32 , fDiffuseShader(std::move(diffuseShader))
33 , fLights(std::move(lights))
34 , fDiffuseWidth(diffuseWidth)
35 , fDiffuseHeight(diffuseHeight) { }
36
37 bool isOpaque() const override;
38
39 #if SK_SUPPORT_GPU
40 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const overri de;
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* fPovDepthContext;
60 SkShader::Context* fDiffuseContext;
61 uint32_t fFlags;
62
63 void* fHeapAllocated;
64
65 typedef SkShader::Context INHERITED;
66 };
67
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> fPovDepthShader;
78 sk_sp<SkShader> fDiffuseShader;
79 sk_sp<SkLights> fLights;
80
81 int fDiffuseWidth;
82 int fDiffuseHeight;
83
84 friend class SkShadowShader;
85
86 typedef SkShader INHERITED;
87 };
88
89 ////////////////////////////////////////////////////////////////////////////
90
91 #if SK_SUPPORT_GPU
92
93 #include "GrCoordTransform.h"
94 #include "GrFragmentProcessor.h"
95 #include "GrInvariantOutput.h"
96 #include "glsl/GrGLSLFragmentProcessor.h"
97 #include "glsl/GrGLSLFragmentShaderBuilder.h"
98 #include "SkGr.h"
99 #include "SkGrPriv.h"
100 #include "SkSpecialImage.h"
101 #include "SkImage_Base.h"
102 #include "GrContext.h"
103
104 class ShadowFP : public GrFragmentProcessor {
105 public:
106 ShadowFP(sk_sp<GrFragmentProcessor> povDepth,
107 sk_sp<GrFragmentProcessor> diffuse,
108 sk_sp<SkLights> lights,
109 int diffuseWidth, int diffuseHeight,
110 GrContext* context) {
111
112 // fuse all ambient lights into a single one
113 fAmbientColor.set(0.0f, 0.0f, 0.0f);
114
115 fNumDirLights = 0; // refers to directional lights.
116 for (int i = 0; i < lights->numLights(); ++i) {
117 if (SkLights::Light::kAmbient_LightType == lights->light(i).type()) {
118 fAmbientColor += lights->light(i).color();
119 } else if (fNumDirLights < SK_MAX_NON_AMBIENT_LIGHTS){
120 fLightColor[fNumDirLights] = lights->light(i).color();
121 fLightDir[fNumDirLights] = lights->light(i).dir();
122 SkImage_Base* shadowMap = ((SkImage_Base*)lights->light(i).getSh adowMap().get());
123
124 // this sk_sp gets deleted when the ShadowFP is destroyed, and f rees the GrTexture*
125 fTexture[fNumDirLights] = sk_sp<GrTexture>(shadowMap->asTextureR ef(context,
126 GrTextureParams::Clam pNoFilter(),
127 SkSourceGammaTreatmen t::kIgnore));
128 fDepthMapAccess[fNumDirLights].reset(fTexture[fNumDirLights].get ());
129 this->addTextureAccess(&fDepthMapAccess[fNumDirLights]);
130
131 fDepthMapHeight[fNumDirLights] = shadowMap->height();
132 fDepthMapWidth[fNumDirLights] = shadowMap->width();
133
134 fNumDirLights++;
135 }
136 }
137
138 fWidth = diffuseWidth;
139 fHeight = diffuseHeight;
140
141 this->registerChildProcessor(std::move(povDepth));
142 this->registerChildProcessor(std::move(diffuse));
143 this->initClassID<ShadowFP>();
144 }
145
146 class GLSLShadowFP : public GrGLSLFragmentProcessor {
147 public:
148 GLSLShadowFP() { }
149
150 void emitCode(EmitArgs& args) override {
151
152 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
153 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
154
155 // add uniforms
156 int32_t numLights = args.fFp.cast<ShadowFP>().fNumDirLights;
157 SkASSERT(numLights <= SK_MAX_NON_AMBIENT_LIGHTS);
158
159 const char* lightDirUniName[SK_MAX_NON_AMBIENT_LIGHTS] = {nullptr};
160 const char* lightColorUniName[SK_MAX_NON_AMBIENT_LIGHTS] = {nullptr} ;
161
162 const char* depthMapWidthUniName[SK_MAX_NON_AMBIENT_LIGHTS] = {nullp tr};
163 const char* depthMapHeightUniName[SK_MAX_NON_AMBIENT_LIGHTS] = {null ptr};
164
165 SkString lightDirUniNameBase("lightDir");
166 SkString lightColorUniNameBase("lightColor");
167
168 SkString depthMapWidthUniNameBase("dmapWidth");
169 SkString depthMapHeightUniNameBase("dmapHeight");
170
171 for (int i = 0; i < numLights; i++) {
172 SkString lightDirUniNameStr(lightDirUniNameBase);
173 lightDirUniNameStr.appendf("%d", i);
174 SkString lightColorUniNameStr(lightColorUniNameBase);
175 lightColorUniNameStr.appendf("%d", i);
176
177 SkString depthMapWidthUniNameStr(depthMapWidthUniNameBase);
178 depthMapWidthUniNameStr.appendf("%d", i);
179 SkString depthMapHeightUniNameStr(depthMapHeightUniNameBase);
180 depthMapHeightUniNameStr.appendf("%d", i);
181
182 fLightDirUni[i] = uniformHandler->addUniform(kFragment_GrShaderF lag,
183 kVec3f_GrSLType,
184 kDefault_GrSLPrecis ion,
185 lightDirUniNameStr. c_str(),
186 &lightDirUniName[i] );
187 fLightColorUni[i] = uniformHandler->addUniform(kFragment_GrShade rFlag,
188 kVec3f_GrSLType,
189 kDefault_GrSLPrec ision,
190 lightColorUniName Str.c_str(),
191 &lightColorUniNam e[i]);
192
193 fDepthMapWidthUni[i] = uniformHandler->addUniform(kFragment_GrS haderFlag,
194 kInt_GrSLType,
195 kDefault_GrSLPrecision,
196 depthMapWidthUniNameStr.c_str (),
197 &depthMapWidthUniName[i]);
198 fDepthMapHeightUni[i] = uniformHandler->addUniform(kFragment_GrS haderFlag,
199 kInt_GrSLType,
200 kDefault_GrSLPrecision,
201 depthMapHeightUniNameStr.c_st r(),
202 &depthMapHeightUniName[i]);
203 }
204
205
206 const char* widthUniName = nullptr;
207 const char* heightUniName = nullptr;
208
209 fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
210 kInt_GrSLType,
211 kDefault_GrSLPrecision,
212 "width", &widthUniName);
213 fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
214 kInt_GrSLType,
215 kDefault_GrSLPrecision,
216 "height", &heightUniName);
217
218
219 SkString povDepth("povDepth");
220 this->emitChild(0, nullptr, &povDepth, args);
221
222 SkString diffuseColor("inDiffuseColor");
223 this->emitChild(1, nullptr, &diffuseColor, args);
224
225 SkString depthMaps[SK_MAX_NON_AMBIENT_LIGHTS];
226
227 for (int i = 0; i < numLights; i++) {
228 SkString povCoord("povCoord");
229 povCoord.appendf("%d", i);
230
231 // vMatrixCoord_0_1_Stage0 is the texture sampler coordinates.
232 // povDepth.b * 255 scales it to 0 - 255, bringing it to world s pace,
233 // and the / 400 brings it back to a sampler coordinate, 0 - 1
234 // The 400 comes from the shadowmaps GM.
235 // TODO use real shadowmaps size
236 SkString offset("offset");
237 offset.appendf("%d", i);
238
239 SkString scaleVec("scaleVec");
240 scaleVec.appendf("%d", i);
241
242 SkString scaleOffsetVec("scaleOffsetVec");
243 scaleOffsetVec.appendf("%d", i);
244
245 fragBuilder->codeAppendf("vec2 %s = vec2(%s) * povDepth.b * 255 / 400;\n",
246 offset.c_str(), lightDirUniName[i]);
247
248 fragBuilder->codeAppendf("vec2 %s = (vec2(%s, %s) / vec2(%s, %s) );\n",
249 scaleVec.c_str(),
250 widthUniName, heightUniName,
251 depthMapWidthUniName[i], depthMapHeight UniName[i]);
252
253 fragBuilder->codeAppendf("vec2 %s = 1 - %s;\n",
254 scaleOffsetVec.c_str(), scaleVec.c_str( ));
255
256
257 fragBuilder->codeAppendf("vec2 %s = (vMatrixCoord_0_1_Stage0 + "
258 "vec2(%s.x, 0 - %s.y)) "
259 " * %s + vec2(0,1) * %s;\n",
260
261 povCoord.c_str(), offset.c_str(), offse t.c_str(),
262 scaleVec.c_str(), scaleOffsetVec.c_str( ));
263
264 fragBuilder->appendTextureLookup(&depthMaps[i], args.fTexSampler s[i],
265 povCoord.c_str(),
266 kVec2f_GrSLType);
267 }
268
269 const char* ambientColorUniName = nullptr;
270 fAmbientColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag ,
271 kVec3f_GrSLType, kDefa ult_GrSLPrecision,
272 "AmbientColor", &ambie ntColorUniName);
273
274 fragBuilder->codeAppendf("vec4 resultDiffuseColor = %s;", diffuseCol or.c_str());
275
276 // Essentially,
277 // diffColor * (ambientLightTot + foreachDirLight(lightColor * (N . L)))
278 SkString totalLightColor("totalLightColor");
279 fragBuilder->codeAppendf("vec3 %s = vec3(0);", totalLightColor.c_str ());
280
281 for (int i = 0; i < numLights; i++) {
282 fragBuilder->codeAppendf("if (%s.b >= %s.b) {",
283 povDepth.c_str(), depthMaps[i].c_str()) ;
284 // Note that dot(vec3(0,0,1), %s) == %s.z * %s
285 fragBuilder->codeAppendf("%s += %s.z * %s;",
286 totalLightColor.c_str(),
287 lightDirUniName[i],
288 lightColorUniName[i]);
289 fragBuilder->codeAppendf("}");
290 }
291
292 fragBuilder->codeAppendf("%s += %s;",
293 totalLightColor.c_str(),
294 ambientColorUniName);
295
296 fragBuilder->codeAppendf("resultDiffuseColor *= vec4(%s, 1);",
297 totalLightColor.c_str());
298
299 fragBuilder->codeAppendf("%s = resultDiffuseColor;", args.fOutputCol or);
300 }
301
302 static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
303 GrProcessorKeyBuilder* b) {
304 const ShadowFP& shadowFP = proc.cast<ShadowFP>();
305 b->add32(shadowFP.fNumDirLights);
306 }
307
308 protected:
309 void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
310 const ShadowFP &shadowFP = proc.cast<ShadowFP>();
311
312 fNumDirLights = shadowFP.numLights();
313
314 for (int i = 0; i < fNumDirLights; i++) {
315 const SkVector3& lightDir = shadowFP.lightDir(i);
316 if (lightDir != fLightDir[i]) {
317 pdman.set3fv(fLightDirUni[i], 1, &lightDir.fX);
318 fLightDir[i] = lightDir;
319 }
320 const SkColor3f& lightColor = shadowFP.lightColor(i);
321 if (lightColor != fLightColor[i]) {
322 pdman.set3fv(fLightColorUni[i], 1, &lightColor.fX);
323 fLightColor[i] = lightColor;
324 }
325
326 int depthMapWidth = shadowFP.depthMapWidth(i);
327 if (depthMapWidth != fDepthMapWidth[i]) {
328 pdman.set1i(fDepthMapWidthUni[i], depthMapWidth);
329 fDepthMapWidth[i] = depthMapWidth;
330 }
331 int depthMapHeight = shadowFP.depthMapHeight(i);
332 if (depthMapHeight != fDepthMapHeight[i]) {
333 pdman.set1i(fDepthMapHeightUni[i], depthMapHeight);
334 fDepthMapHeight[i] = depthMapHeight;
335 }
336 }
337
338 int width = shadowFP.width();
339 if (width != fWidth) {
340 pdman.set1i(fWidthUni, width);
341 fWidth = width;
342 }
343 int height = shadowFP.height();
344 if (height != fHeight) {
345 pdman.set1i(fHeightUni, height);
346 fHeight = height;
347 }
348
349 const SkColor3f& ambientColor = shadowFP.ambientColor();
350 if (ambientColor != fAmbientColor) {
351 pdman.set3fv(fAmbientColorUni, 1, &ambientColor.fX);
352 fAmbientColor = ambientColor;
353 }
354 }
355
356 private:
357 SkVector3 fLightDir[SK_MAX_NON_AMBIENT_LIGHTS];
358 GrGLSLProgramDataManager::UniformHandle fLightDirUni[SK_MAX_NON_AMBIENT_ LIGHTS];
359 SkColor3f fLightColor[SK_MAX_NON_AMBIENT_LIGHTS];
360 GrGLSLProgramDataManager::UniformHandle fLightColorUni[SK_MAX_NON_AMBIEN T_LIGHTS];
361
362 int fDepthMapWidth[SK_MAX_NON_AMBIENT_LIGHTS];
363 GrGLSLProgramDataManager::UniformHandle fDepthMapWidthUni[SK_MAX_NON_AMB IENT_LIGHTS];
364 int fDepthMapHeight[SK_MAX_NON_AMBIENT_LIGHTS];
365 GrGLSLProgramDataManager::UniformHandle fDepthMapHeightUni[SK_MAX_NON_AM BIENT_LIGHTS];
366
367 int fWidth;
368 GrGLSLProgramDataManager::UniformHandle fWidthUni;
369 int fHeight;
370 GrGLSLProgramDataManager::UniformHandle fHeightUni;
371
372 SkColor3f fAmbientColor;
373 GrGLSLProgramDataManager::UniformHandle fAmbientColorUni;
374
375 int fNumDirLights;
376 };
377
378 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
379 GLSLShadowFP::GenKey(*this, caps, b);
380 }
381
382 const char* name() const override { return "shadowFP"; }
383
384 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
385 inout->mulByUnknownFourComponents();
386 }
387 int32_t numLights() const { return fNumDirLights; }
388 const SkColor3f& ambientColor() const { return fAmbientColor; }
389 const SkVector3& lightDir(int i) const {
390 SkASSERT(i < fNumDirLights);
391 return fLightDir[i];
392 }
393 const SkVector3& lightColor(int i) const {
394 SkASSERT(i < fNumDirLights);
395 return fLightColor[i];
396 }
397
398 int depthMapWidth(int i) const {
399 SkASSERT(i < fNumDirLights);
400 return fDepthMapWidth[i];
401 }
402 int depthMapHeight(int i) const {
403 SkASSERT(i < fNumDirLights);
404 return fDepthMapHeight[i];
405 }
406 int width() const {return fWidth; }
407 int height() const {return fHeight; }
408
409 private:
410 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLShadowFP; }
411
412 bool onIsEqual(const GrFragmentProcessor& proc) const override {
413 const ShadowFP& shadowFP = proc.cast<ShadowFP>();
414 if (fAmbientColor != shadowFP.fAmbientColor || fNumDirLights != shadowFP .fNumDirLights) {
415 return false;
416 }
417
418 if (fWidth != shadowFP.fWidth || fHeight != shadowFP.fHeight) {
419 return false;
420 }
421
422 for (int i = 0; i < fNumDirLights; i++) {
423 if (fLightDir[i] != shadowFP.fLightDir[i] ||
424 fLightColor[i] != shadowFP.fLightColor[i]) {
425 return false;
426 }
427
428 if (fDepthMapWidth[i] != shadowFP.fDepthMapWidth[i] ||
429 fDepthMapHeight[i] != shadowFP.fDepthMapHeight[i]) {
430 return false;
431 }
432 }
433
434 return true;
435 }
436
437 int fNumDirLights;
438
439 SkVector3 fLightDir[SK_MAX_NON_AMBIENT_LIGHTS];
440 SkColor3f fLightColor[SK_MAX_NON_AMBIENT_LIGHTS];
441 GrTextureAccess fDepthMapAccess[SK_MAX_NON_AMBIENT_LIGHTS];
442 sk_sp<GrTexture> fTexture[SK_MAX_NON_AMBIENT_LIGHTS];
443
444 int fDepthMapWidth[SK_MAX_NON_AMBIENT_LIGHTS];
445 int fDepthMapHeight[SK_MAX_NON_AMBIENT_LIGHTS];
446
447 int fHeight;
448 int fWidth;
449
450 SkColor3f fAmbientColor;
451 };
452
453 ////////////////////////////////////////////////////////////////////////////
454
455 sk_sp<GrFragmentProcessor> SkShadowShaderImpl::asFragmentProcessor(const AsFPArg s& fpargs) const {
456
457 sk_sp<GrFragmentProcessor> povDepthFP = fPovDepthShader->asFragmentProcessor (fpargs);
458
459 sk_sp<GrFragmentProcessor> diffuseFP = fDiffuseShader->asFragmentProcessor(f pargs);
460
461 sk_sp<GrFragmentProcessor> shadowfp = sk_make_sp<ShadowFP>(std::move(povDept hFP),
462 std::move(diffuse FP),
463 std::move(fLights ),
464 fDiffuseWidth, fD iffuseHeight,
465 fpargs.fContext);
466 return shadowfp;
467 }
468
469
470 #endif
471
472 ////////////////////////////////////////////////////////////////////////////
473
474 bool SkShadowShaderImpl::isOpaque() const {
475 return fDiffuseShader->isOpaque();
476 }
477
478 SkShadowShaderImpl::ShadowShaderContext::ShadowShaderContext(
479 const SkShadowShaderImpl& shader, const ContextRec& rec,
480 SkShader::Context* povDepthContext,
481 SkShader::Context* diffuseContext,
482 void* heapAllocated)
483 : INHERITED(shader, rec)
484 , fPovDepthContext(povDepthContext)
485 , fDiffuseContext(diffuseContext)
486 , fHeapAllocated(heapAllocated) {
487 bool isOpaque = shader.isOpaque();
488
489 // update fFlags
490 uint32_t flags = 0;
491 if (isOpaque && (255 == this->getPaintAlpha())) {
492 flags |= kOpaqueAlpha_Flag;
493 }
494
495 fFlags = flags;
496 }
497
498 SkShadowShaderImpl::ShadowShaderContext::~ShadowShaderContext() {
499 // The dependencies have been created outside of the context on memory that was allocated by
500 // the onCreateContext() method. Call the destructors and free the memory.
501 fPovDepthContext->~Context();
502 fDiffuseContext->~Context();
503
504 sk_free(fHeapAllocated);
505 }
506
507 static inline SkPMColor convert(SkColor3f color, U8CPU a) {
508 if (color.fX <= 0.0f) {
509 color.fX = 0.0f;
510 } else if (color.fX >= 255.0f) {
511 color.fX = 255.0f;
512 }
513
514 if (color.fY <= 0.0f) {
515 color.fY = 0.0f;
516 } else if (color.fY >= 255.0f) {
517 color.fY = 255.0f;
518 }
519
520 if (color.fZ <= 0.0f) {
521 color.fZ = 0.0f;
522 } else if (color.fZ >= 255.0f) {
523 color.fZ = 255.0f;
524 }
525
526 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ) ;
527 }
528
529 // larger is better (fewer times we have to loop), but we shouldn't
530 // take up too much stack-space (each one here costs 16 bytes)
531 #define BUFFER_MAX 16
532 void SkShadowShaderImpl::ShadowShaderContext::shadeSpan(int x, int y,
533 SkPMColor result[], int count) {
534 const SkShadowShaderImpl& lightShader = static_cast<const SkShadowShaderImpl &>(fShader);
535
536 SkPMColor diffuse[BUFFER_MAX];
537
538 do {
539 int n = SkTMin(count, BUFFER_MAX);
540
541 fPovDepthContext->shadeSpan(x, y, diffuse, n);
542 fDiffuseContext->shadeSpan(x, y, diffuse, n);
543
544 for (int i = 0; i < n; ++i) {
545
546 SkColor diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]);
547
548 SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f);
549 // This is all done in linear unpremul color space (each component 0 ..255.0f though)
550 for (int l = 0; l < lightShader.fLights->numLights(); ++l) {
551 const SkLights::Light& light = lightShader.fLights->light(l);
552
553 if (SkLights::Light::kAmbient_LightType == light.type()) {
554 accum.fX += light.color().fX * SkColorGetR(diffColor);
555 accum.fY += light.color().fY * SkColorGetG(diffColor);
556 accum.fZ += light.color().fZ * SkColorGetB(diffColor);
557 } else {
558 // scaling by fZ accounts for lighting direction
559 accum.fX += light.color().makeScale(light.dir().fZ).fX * SkC olorGetR(diffColor);
560 accum.fY += light.color().makeScale(light.dir().fZ).fY * SkC olorGetG(diffColor);
561 accum.fZ += light.color().makeScale(light.dir().fZ).fZ * SkC olorGetB(diffColor);
562 }
563 }
564
565 result[i] = convert(accum, SkColorGetA(diffColor));
566 }
567
568 result += n;
569 x += n;
570 count -= n;
571 } while (count > 0);
572 }
573
574 ////////////////////////////////////////////////////////////////////////////
575
576 #ifndef SK_IGNORE_TO_STRING
577 void SkShadowShaderImpl::toString(SkString* str) const {
578 str->appendf("ShadowShader: ()");
579 }
580 #endif
581
582 sk_sp<SkFlattenable> SkShadowShaderImpl::CreateProc(SkReadBuffer& buf) {
583
584 // Discarding SkShader flattenable params
585 bool hasLocalMatrix = buf.readBool();
586 SkAssertResult(!hasLocalMatrix);
587
588 int numLights = buf.readInt();
589
590 SkLights::Builder builder;
591
592 for (int l = 0; l < numLights; ++l) {
593 bool isAmbient = buf.readBool();
594
595 SkColor3f color;
596 if (!buf.readScalarArray(&color.fX, 3)) {
597 return nullptr;
598 }
599
600 if (isAmbient) {
601 builder.add(SkLights::Light(color));
602 } else {
603 SkVector3 dir;
604 if (!buf.readScalarArray(&dir.fX, 3)) {
605 return nullptr;
606 }
607
608 sk_sp<SkImage> depthMap;
609 if (!(depthMap = sk_ref_sp<SkImage>(buf.readImage()))) {
610 return nullptr;
611 }
612
613 SkLights::Light light = SkLights::Light(color, dir);
614 light.setShadowMap(depthMap);
615
616 builder.add(light);
617 }
618 }
619
620 sk_sp<SkLights> lights(builder.finish());
621
622 int diffuseWidth = buf.readInt();
623 int diffuseHeight = buf.readInt();
624
625 sk_sp<SkShader> povDepthShader(buf.readFlattenable<SkShader>());
626 sk_sp<SkShader> diffuseShader(buf.readFlattenable<SkShader>());
627
628 return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader),
629 std::move(diffuseShader),
630 std::move(lights),
631 diffuseWidth, diffuseHeight);
632 }
633
634 void SkShadowShaderImpl::flatten(SkWriteBuffer& buf) const {
635 this->INHERITED::flatten(buf);
636
637 buf.writeInt(fLights->numLights());
638
639 for (int l = 0; l < fLights->numLights(); ++l) {
640 const SkLights::Light& light = fLights->light(l);
641
642 bool isAmbient = SkLights::Light::kAmbient_LightType == light.type();
643
644 buf.writeBool(isAmbient);
645 buf.writeScalarArray(&light.color().fX, 3);
646 if (!isAmbient) {
647 buf.writeScalarArray(&light.dir().fX, 3);
648 }
649
650 buf.writeImage(light.getShadowMap().get());
651 }
652
653 buf.writeInt(fDiffuseWidth);
654 buf.writeInt(fDiffuseHeight);
655
656 buf.writeFlattenable(fPovDepthShader.get());
657 buf.writeFlattenable(fDiffuseShader.get());
658 }
659
660 size_t SkShadowShaderImpl::onContextSize(const ContextRec& rec) const {
661 return sizeof(ShadowShaderContext);
662 }
663
664 SkShader::Context* SkShadowShaderImpl::onCreateContext(const ContextRec& rec,
665 void* storage) const {
666 size_t heapRequired = fPovDepthShader->contextSize(rec) +
667 fDiffuseShader->contextSize(rec);
668
669 void* heapAllocated = sk_malloc_throw(heapRequired);
670
671 void* povDepthContextStorage = heapAllocated;
672
673 SkShader::Context* povDepthContext =
674 fPovDepthShader->createContext(rec, povDepthContextStorage);
675
676 if (!povDepthContext) {
677 sk_free(heapAllocated);
678 return nullptr;
679 }
680
681 void* diffuseContextStorage = (char*)heapAllocated + fPovDepthShader->contex tSize(rec);
682
683 SkShader::Context* diffuseContext = fDiffuseShader->createContext(rec, diffu seContextStorage);
684 if (!diffuseContext) {
685 sk_free(heapAllocated);
686 return nullptr;
687 }
688
689 return new (storage) ShadowShaderContext(*this, rec, povDepthContext, diffus eContext,
690 heapAllocated);
691 }
692
693 ///////////////////////////////////////////////////////////////////////////////
694
695 sk_sp<SkShader> SkShadowShader::Make(sk_sp<SkShader> povDepthShader,
696 sk_sp<SkShader> diffuseShader,
697 sk_sp<SkLights> lights,
698 int diffuseWidth, int diffuseHeight) {
699 if (!povDepthShader || !diffuseShader) {
700 // TODO: Use paint's color in absence of a diffuseShader
701 // TODO: Use a default implementation of normalSource instead
702 return nullptr;
703 }
704
705 return sk_make_sp<SkShadowShaderImpl>(std::move(povDepthShader),
706 std::move(diffuseShader),
707 std::move(lights),
708 diffuseWidth, diffuseHeight);
709 }
710
711 ///////////////////////////////////////////////////////////////////////////////
712
713 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkShadowShader)
714 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkShadowShaderImpl)
715 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
716
717 ///////////////////////////////////////////////////////////////////////////////
718
719 #endif
OLDNEW
« no previous file with comments | « src/core/SkShadowShader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698