Chromium Code Reviews| 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 | |
| 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 | |
| 332 sk_sp<GrFragmentProcessor> normalFP( | 266 sk_sp<GrFragmentProcessor> normalFP( |
| 333 fNormalSource->asFragmentProcessor(context, viewM, localMatrix, filt erQuality, | 267 fNormalSource->asFragmentProcessor(context, viewM, localMatrix, filt erQuality, |
| 334 gammaTreatment)); | 268 gammaTreatment)); |
| 335 sk_sp<GrFragmentProcessor> inner ( | 269 sk_sp<GrFragmentProcessor> fpPipeline[] = { |
| 336 new LightingFP(diffuseTexture, diffM, diffParams, fLights, std::move (normalFP))); | 270 fDiffuseShader->asFragmentProcessor(context, viewM, localMatrix, fil terQuality, |
| 271 gammaTreatment), | |
| 272 sk_make_sp<LightingFP>(std::move(normalFP), fLights) | |
| 273 }; | |
| 274 sk_sp<GrFragmentProcessor> inner(GrFragmentProcessor::RunInSeries(fpPipeline , 2)); | |
| 337 | 275 |
| 338 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); | 276 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); |
| 339 } | 277 } |
| 340 | 278 |
| 341 #endif | 279 #endif |
| 342 | 280 |
| 343 //////////////////////////////////////////////////////////////////////////// | 281 //////////////////////////////////////////////////////////////////////////// |
| 344 | 282 |
| 345 bool SkLightingShaderImpl::isOpaque() const { | 283 bool SkLightingShaderImpl::isOpaque() const { |
| 346 return fDiffuseMap.isOpaque(); | 284 return fDiffuseShader->isOpaque(); |
| 347 } | 285 } |
| 348 | 286 |
| 349 SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( | 287 SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( |
| 350 const SkLightingShaderImpl& shader, const ContextRec& rec, SkBitmapProcS tate* diffuseState, | 288 const SkLightingShaderImpl& shader, const ContextRec& rec, |
| 351 SkNormalSource::Provider* normalProvider, void* heapAllocated) | 289 SkShader::Context* diffuseContext, SkNormalSource::Provider* normalProvi der, |
| 290 void* heapAllocated) | |
| 352 : INHERITED(shader, rec) | 291 : INHERITED(shader, rec) |
| 353 , fDiffuseState(diffuseState) | 292 , fDiffuseContext(diffuseContext) |
| 354 , fNormalProvider(normalProvider) | 293 , fNormalProvider(normalProvider) |
| 355 , fHeapAllocated(heapAllocated) { | 294 , fHeapAllocated(heapAllocated) { |
| 356 const SkPixmap& pixmap = fDiffuseState->fPixmap; | 295 bool isOpaque = shader.isOpaque(); |
| 357 bool isOpaque = pixmap.isOpaque(); | |
| 358 | 296 |
| 359 // update fFlags | 297 // update fFlags |
| 360 uint32_t flags = 0; | 298 uint32_t flags = 0; |
| 361 if (isOpaque && (255 == this->getPaintAlpha())) { | 299 if (isOpaque && (255 == this->getPaintAlpha())) { |
| 362 flags |= kOpaqueAlpha_Flag; | 300 flags |= kOpaqueAlpha_Flag; |
| 363 } | 301 } |
| 364 | 302 |
| 365 fFlags = flags; | 303 fFlags = flags; |
| 366 } | 304 } |
| 367 | 305 |
| 368 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { | 306 SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { |
| 369 // The bitmap proc states have been created outside of the context on memory that will be freed | 307 // 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. | 308 // the onCreateContext() method. Call the destructors and free the memory. |
| 371 fDiffuseState->~SkBitmapProcState(); | 309 fDiffuseContext->~Context(); |
| 372 fNormalProvider->~Provider(); | 310 fNormalProvider->~Provider(); |
| 373 | 311 |
| 374 sk_free(fHeapAllocated); | 312 sk_free(fHeapAllocated); |
| 375 } | 313 } |
| 376 | 314 |
| 377 static inline SkPMColor convert(SkColor3f color, U8CPU a) { | 315 static inline SkPMColor convert(SkColor3f color, U8CPU a) { |
| 378 if (color.fX <= 0.0f) { | 316 if (color.fX <= 0.0f) { |
| 379 color.fX = 0.0f; | 317 color.fX = 0.0f; |
| 380 } else if (color.fX >= 255.0f) { | 318 } else if (color.fX >= 255.0f) { |
| 381 color.fX = 255.0f; | 319 color.fX = 255.0f; |
| 382 } | 320 } |
| 383 | 321 |
| 384 if (color.fY <= 0.0f) { | 322 if (color.fY <= 0.0f) { |
| 385 color.fY = 0.0f; | 323 color.fY = 0.0f; |
| 386 } else if (color.fY >= 255.0f) { | 324 } else if (color.fY >= 255.0f) { |
| 387 color.fY = 255.0f; | 325 color.fY = 255.0f; |
| 388 } | 326 } |
| 389 | 327 |
| 390 if (color.fZ <= 0.0f) { | 328 if (color.fZ <= 0.0f) { |
| 391 color.fZ = 0.0f; | 329 color.fZ = 0.0f; |
| 392 } else if (color.fZ >= 255.0f) { | 330 } else if (color.fZ >= 255.0f) { |
| 393 color.fZ = 255.0f; | 331 color.fZ = 255.0f; |
| 394 } | 332 } |
| 395 | 333 |
| 396 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ) ; | 334 return SkPreMultiplyARGB(a, (int) color.fX, (int) color.fY, (int) color.fZ) ; |
| 397 } | 335 } |
| 398 | 336 |
| 399 // larger is better (fewer times we have to loop), but we shouldn't | 337 // 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) | 338 // take up too much stack-space (each one here costs 16 bytes) |
| 401 #define TMP_COUNT 16 | 339 #define BUFFER_MAX 16 |
| 402 #define BUFFER_MAX ((int)(TMP_COUNT * sizeof(uint32_t))) | |
| 403 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, | 340 void SkLightingShaderImpl::LightingShaderContext::shadeSpan(int x, int y, |
| 404 SkPMColor result[], int count) { | 341 SkPMColor result[], int count) { |
| 405 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader Impl&>(fShader); | 342 const SkLightingShaderImpl& lightShader = static_cast<const SkLightingShader Impl&>(fShader); |
| 406 | 343 |
| 407 uint32_t tmpColor[TMP_COUNT]; | 344 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]; | 345 SkPoint3 normals[BUFFER_MAX]; |
| 419 | 346 |
| 420 do { | 347 do { |
| 421 int n = count; | 348 int n = SkTMin(count, BUFFER_MAX); |
| 422 if (n > max) { | |
| 423 n = max; | |
| 424 } | |
| 425 | 349 |
| 426 diffMProc(*fDiffuseState, tmpColor, n, x, y); | 350 fDiffuseContext->shadeSpan(x, y, diffuse, n); |
| 427 diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); | |
| 428 | |
| 429 fNormalProvider->fillScanLine(x, y, normals, n); | 351 fNormalProvider->fillScanLine(x, y, normals, n); |
| 430 | 352 |
| 431 for (int i = 0; i < n; ++i) { | 353 for (int i = 0; i < n; ++i) { |
| 432 | 354 |
| 433 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | 355 SkColor diffColor = SkUnPreMultiply::PMColorToColor(diffuse[i]); |
| 434 | 356 |
| 435 SkColor3f accum = SkColor3f::Make(0.0f, 0.0f, 0.0f); | 357 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) | 358 // 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) { | 359 for (int l = 0; l < lightShader.fLights->numLights(); ++l) { |
| 438 const SkLights::Light& light = lightShader.fLights->light(l); | 360 const SkLights::Light& light = lightShader.fLights->light(l); |
| 439 | 361 |
| 440 if (SkLights::Light::kAmbient_LightType == light.type()) { | 362 if (SkLights::Light::kAmbient_LightType == light.type()) { |
| 441 accum += light.color().makeScale(255.0f); | 363 accum += light.color().makeScale(255.0f); |
| 442 } else { | 364 } else { |
| 443 SkScalar NdotL = normals[i].dot(light.dir()); | 365 SkScalar NdotL = normals[i].dot(light.dir()); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 462 | 384 |
| 463 //////////////////////////////////////////////////////////////////////////// | 385 //////////////////////////////////////////////////////////////////////////// |
| 464 | 386 |
| 465 #ifndef SK_IGNORE_TO_STRING | 387 #ifndef SK_IGNORE_TO_STRING |
| 466 void SkLightingShaderImpl::toString(SkString* str) const { | 388 void SkLightingShaderImpl::toString(SkString* str) const { |
| 467 str->appendf("LightingShader: ()"); | 389 str->appendf("LightingShader: ()"); |
| 468 } | 390 } |
| 469 #endif | 391 #endif |
| 470 | 392 |
| 471 sk_sp<SkFlattenable> SkLightingShaderImpl::CreateProc(SkReadBuffer& buf) { | 393 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 | 394 |
| 480 SkBitmap diffuse; | 395 // Discarding SkShader flattenable params |
| 481 if (!buf.readBitmap(&diffuse)) { | 396 bool hasLocalMatrix = buf.readBool(); |
| 482 return nullptr; | 397 SkASSERT(!hasLocalMatrix); |
|
dvonbeck
2016/07/06 21:21:02
CQ's release bots are failing to compile here beca
dvonbeck
2016/07/06 21:22:35
P.S.: Just realized SkASSERT(buf.readBool()) would
robertphillips
2016/07/06 21:56:43
SkAssertResult ?
dvonbeck
2016/07/06 22:19:10
Done.
| |
| 483 } | |
| 484 diffuse.setImmutable(); | |
| 485 | 398 |
| 486 int numLights = buf.readInt(); | 399 int numLights = buf.readInt(); |
| 487 | 400 |
| 488 SkLights::Builder builder; | 401 SkLights::Builder builder; |
| 489 | 402 |
| 490 for (int l = 0; l < numLights; ++l) { | 403 for (int l = 0; l < numLights; ++l) { |
| 491 bool isAmbient = buf.readBool(); | 404 bool isAmbient = buf.readBool(); |
| 492 | 405 |
| 493 SkColor3f color; | 406 SkColor3f color; |
| 494 if (!buf.readScalarArray(&color.fX, 3)) { | 407 if (!buf.readScalarArray(&color.fX, 3)) { |
| 495 return nullptr; | 408 return nullptr; |
| 496 } | 409 } |
| 497 | 410 |
| 498 if (isAmbient) { | 411 if (isAmbient) { |
| 499 builder.add(SkLights::Light(color)); | 412 builder.add(SkLights::Light(color)); |
| 500 } else { | 413 } else { |
| 501 SkVector3 dir; | 414 SkVector3 dir; |
| 502 if (!buf.readScalarArray(&dir.fX, 3)) { | 415 if (!buf.readScalarArray(&dir.fX, 3)) { |
| 503 return nullptr; | 416 return nullptr; |
| 504 } | 417 } |
| 505 builder.add(SkLights::Light(color, dir)); | 418 builder.add(SkLights::Light(color, dir)); |
| 506 } | 419 } |
| 507 } | 420 } |
| 508 | 421 |
| 509 sk_sp<SkLights> lights(builder.finish()); | 422 sk_sp<SkLights> lights(builder.finish()); |
| 510 | 423 |
| 511 sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>()); | 424 sk_sp<SkNormalSource> normalSource(buf.readFlattenable<SkNormalSource>()); |
| 425 sk_sp<SkShader> diffuseShader(buf.readFlattenable<SkShader>()); | |
| 512 | 426 |
| 513 return sk_make_sp<SkLightingShaderImpl>(diffuse, std::move(lights), &diffLoc alM, | 427 return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move( normalSource), |
| 514 std::move(normalSource)); | 428 std::move(lights)); |
| 515 } | 429 } |
| 516 | 430 |
| 517 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { | 431 void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { |
| 518 this->INHERITED::flatten(buf); | 432 this->INHERITED::flatten(buf); |
| 519 | 433 |
| 520 buf.writeBitmap(fDiffuseMap); | |
| 521 | |
| 522 buf.writeInt(fLights->numLights()); | 434 buf.writeInt(fLights->numLights()); |
| 523 for (int l = 0; l < fLights->numLights(); ++l) { | 435 for (int l = 0; l < fLights->numLights(); ++l) { |
| 524 const SkLights::Light& light = fLights->light(l); | 436 const SkLights::Light& light = fLights->light(l); |
| 525 | 437 |
| 526 bool isAmbient = SkLights::Light::kAmbient_LightType == light.type(); | 438 bool isAmbient = SkLights::Light::kAmbient_LightType == light.type(); |
| 527 | 439 |
| 528 buf.writeBool(isAmbient); | 440 buf.writeBool(isAmbient); |
| 529 buf.writeScalarArray(&light.color().fX, 3); | 441 buf.writeScalarArray(&light.color().fX, 3); |
| 530 if (!isAmbient) { | 442 if (!isAmbient) { |
| 531 buf.writeScalarArray(&light.dir().fX, 3); | 443 buf.writeScalarArray(&light.dir().fX, 3); |
| 532 } | 444 } |
| 533 } | 445 } |
| 534 | 446 |
| 535 buf.writeFlattenable(fNormalSource.get()); | 447 buf.writeFlattenable(fNormalSource.get()); |
| 448 buf.writeFlattenable(fDiffuseShader.get()); | |
| 536 } | 449 } |
| 537 | 450 |
| 538 size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const { | 451 size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const { |
| 539 return sizeof(LightingShaderContext); | 452 return sizeof(LightingShaderContext); |
| 540 } | 453 } |
| 541 | 454 |
| 542 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, | 455 SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, |
| 543 void* storage) const { | 456 void* storage) const { |
| 544 | 457 size_t heapRequired = fDiffuseShader->contextSize(rec) + |
| 545 SkMatrix diffTotalInv; | 458 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); | 459 void* heapAllocated = sk_malloc_throw(heapRequired); |
| 551 | 460 |
| 552 void* diffuseStateStorage = heapAllocated; | 461 void* diffuseContextStorage = heapAllocated; |
| 553 SkBitmapProcState* diffuseState = new (diffuseStateStorage) SkBitmapProcStat e(fDiffuseMap, | 462 SkShader::Context* diffuseContext = fDiffuseShader->createContext(rec, diffu seContextStorage); |
| 554 SkShader::kClamp_TileMode, SkShade r::kClamp_TileMode, | 463 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); | 464 sk_free(heapAllocated); |
| 569 return nullptr; | 465 return nullptr; |
| 570 } | 466 } |
| 571 | 467 |
| 572 return new (storage) LightingShaderContext(*this, rec, diffuseState, normalP rovider, | 468 void* normalProviderStorage = (char*)heapAllocated + fDiffuseShader->context Size(rec); |
| 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, | |
| 573 heapAllocated); | 478 heapAllocated); |
| 574 } | 479 } |
| 575 | 480 |
| 576 /////////////////////////////////////////////////////////////////////////////// | 481 /////////////////////////////////////////////////////////////////////////////// |
| 577 | 482 |
| 578 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, sk_sp<SkLights> lights, | 483 sk_sp<SkShader> SkLightingShader::Make(const SkBitmap& diffuse, sk_sp<SkLights> lights, |
| 579 const SkMatrix* diffLocalM, sk_sp<SkNormalSource> normalSource) { | 484 const SkMatrix* diffLocalM, sk_sp<SkNormalSource> normalSource) { |
| 580 if (diffuse.isNull() || SkBitmapProcShader::BitmapIsTooBig(diffuse)) { | 485 if (diffuse.isNull() || SkBitmapProcShader::BitmapIsTooBig(diffuse)) { |
| 581 return nullptr; | 486 return nullptr; |
| 582 } | 487 } |
| 583 | 488 |
| 584 if (!normalSource) { | 489 if (!normalSource) { |
| 585 // TODO: Use a default implementation of normalSource instead | 490 // TODO: Use a default implementation of normalSource instead |
| 586 return nullptr; | 491 return nullptr; |
| 587 } | 492 } |
| 588 | 493 |
| 589 return sk_make_sp<SkLightingShaderImpl>(diffuse, std::move(lights), diffLoca lM, | 494 // TODO: support other tile modes |
| 590 std::move(normalSource)); | 495 sk_sp<SkShader> diffuseShader = SkBitmapProcShader::MakeBitmapShader(diffuse , |
| 496 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, diffLocalM); | |
| 497 | |
| 498 return sk_make_sp<SkLightingShaderImpl>(std::move(diffuseShader), std::move( normalSource), | |
| 499 std::move(lights)); | |
| 591 } | 500 } |
| 592 | 501 |
| 593 /////////////////////////////////////////////////////////////////////////////// | 502 /////////////////////////////////////////////////////////////////////////////// |
| 594 | 503 |
| 595 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) | 504 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingShader) |
| 596 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) | 505 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingShaderImpl) |
| 597 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 506 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| 598 | 507 |
| 599 /////////////////////////////////////////////////////////////////////////////// | 508 /////////////////////////////////////////////////////////////////////////////// |
| OLD | NEW |