| 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 |