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