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