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