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