OLD | NEW |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2015 Google Inc. | 3 * Copyright 2015 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "SampleCode.h" | |
9 #include "Resources.h" | |
10 | 8 |
11 #include "SkCanvas.h" | 9 #include "SkBitmapProcState.h" |
10 #include "SkColor.h" | |
11 #include "SkEmptyShader.h" | |
12 #include "SkErrorInternals.h" | 12 #include "SkErrorInternals.h" |
13 #include "SkGr.h" | 13 #include "SkLightingShader.h" |
14 #include "SkPoint3.h" | 14 #include "SkMathPriv.h" |
15 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" |
16 #include "SkShader.h" | |
17 #include "SkWriteBuffer.h" | 16 #include "SkWriteBuffer.h" |
18 #include "GrFragmentProcessor.h" | |
19 #include "GrCoordTransform.h" | |
20 #include "gl/GrGLProcessor.h" | |
21 #include "gl/builders/GrGLProgramBuilder.h" | |
22 | |
23 /////////////////////////////////////////////////////////////////////////////// | |
24 | |
25 class LightingShader : public SkShader { | |
26 public: | |
27 struct Light { | |
28 SkVector3 fDirection; | |
29 SkColor fColor; // assumed to be linear color | |
30 }; | |
31 | |
32 LightingShader(const SkBitmap& diffuse, const SkBitmap& normal, const Light& light, | |
33 const SkColor ambient) | |
34 : fDiffuseMap(diffuse) | |
35 , fNormalMap(normal) | |
36 , fLight(light) | |
37 , fAmbientColor(ambient) {} | |
38 | |
39 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(LightingShader); | |
40 | |
41 void flatten(SkWriteBuffer& buf) const override { | |
42 buf.writeBitmap(fDiffuseMap); | |
43 buf.writeBitmap(fNormalMap); | |
44 buf.writeScalarArray(&fLight.fDirection.fX, 3); | |
45 buf.writeColor(fLight.fColor); | |
46 buf.writeColor(fAmbientColor); | |
47 } | |
48 | |
49 bool asFragmentProcessor(GrContext*, const SkPaint& paint, const SkMatrix& v iewM, | |
50 const SkMatrix* localMatrix, GrColor* color, | |
51 GrProcessorDataManager*, GrFragmentProcessor** fp) const override; | |
52 | |
53 SkShader::BitmapType asABitmap(SkBitmap* bitmap, SkMatrix* matrix, | |
54 SkShader::TileMode* xy) const override { | |
55 if (bitmap) { | |
56 *bitmap = fDiffuseMap; | |
57 } | |
58 if (matrix) { | |
59 matrix->reset(); | |
60 } | |
61 if (xy) { | |
62 xy[0] = kClamp_TileMode; | |
63 xy[1] = kClamp_TileMode; | |
64 } | |
65 return kDefault_BitmapType; | |
66 } | |
67 | |
68 #ifndef SK_IGNORE_TO_STRING | |
69 void toString(SkString* str) const override { | |
70 str->appendf("LightingShader: ()"); | |
71 } | |
72 #endif | |
73 | |
74 void setLight(const Light& light) { fLight = light; } | |
75 | |
76 private: | |
77 SkBitmap fDiffuseMap; | |
78 SkBitmap fNormalMap; | |
79 Light fLight; | |
80 SkColor fAmbientColor; | |
81 }; | |
82 | |
83 SkFlattenable* LightingShader::CreateProc(SkReadBuffer& buf) { | |
84 SkBitmap diffuse; | |
85 if (!buf.readBitmap(&diffuse)) { | |
86 return NULL; | |
87 } | |
88 diffuse.setImmutable(); | |
89 | |
90 SkBitmap normal; | |
91 if (!buf.readBitmap(&normal)) { | |
92 return NULL; | |
93 } | |
94 normal.setImmutable(); | |
95 | |
96 Light light; | |
97 if (!buf.readScalarArray(&light.fDirection.fX, 3)) { | |
98 return NULL; | |
99 } | |
100 light.fColor = buf.readColor(); | |
101 | |
102 SkColor ambient = buf.readColor(); | |
103 | |
104 return SkNEW_ARGS(LightingShader, (diffuse, normal, light, ambient)); | |
105 } | |
106 | 17 |
107 //////////////////////////////////////////////////////////////////////////// | 18 //////////////////////////////////////////////////////////////////////////// |
108 | 19 |
20 #if SK_SUPPORT_GPU | |
21 | |
22 #include "GrCoordTransform.h" | |
23 #include "GrFragmentProcessor.h" | |
24 #include "GrTextureAccess.h" | |
25 #include "gl/GrGLProcessor.h" | |
26 #include "gl/builders/GrGLProgramBuilder.h" | |
27 #include "SkGr.h" | |
28 | |
109 class LightingFP : public GrFragmentProcessor { | 29 class LightingFP : public GrFragmentProcessor { |
110 public: | 30 public: |
111 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix, | 31 LightingFP(GrTexture* diffuse, GrTexture* normal, const SkMatrix& matrix, |
112 SkVector3 lightDir, GrColor lightColor, GrColor ambientColor) | 32 SkVector3 lightDir, GrColor lightColor, GrColor ambientColor) |
113 : fDeviceTransform(kDevice_GrCoordSet, matrix) | 33 : fDeviceTransform(kDevice_GrCoordSet, matrix) |
114 , fDiffuseTextureAccess(diffuse) | 34 , fDiffuseTextureAccess(diffuse) |
115 , fNormalTextureAccess(normal) | 35 , fNormalTextureAccess(normal) |
116 , fLightDir(lightDir) | 36 , fLightDir(lightDir) |
117 , fLightColor(lightColor) | 37 , fLightColor(lightColor) |
118 , fAmbientColor(ambientColor) { | 38 , fAmbientColor(ambientColor) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 | 76 |
157 fpb->codeAppend("vec4 diffuseColor = "); | 77 fpb->codeAppend("vec4 diffuseColor = "); |
158 fpb->appendTextureLookupAndModulate(inputColor, samplers[0], | 78 fpb->appendTextureLookupAndModulate(inputColor, samplers[0], |
159 coords[0].c_str(), coords[0].get Type()); | 79 coords[0].c_str(), coords[0].get Type()); |
160 fpb->codeAppend(";"); | 80 fpb->codeAppend(";"); |
161 | 81 |
162 fpb->codeAppend("vec4 normalColor = "); | 82 fpb->codeAppend("vec4 normalColor = "); |
163 fpb->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].g etType()); | 83 fpb->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].g etType()); |
164 fpb->codeAppend(";"); | 84 fpb->codeAppend(";"); |
165 | 85 |
166 fpb->codeAppend("vec3 normal = normalize(2.0*(normalColor.rgb - vec3 (0.5)));"); | 86 fpb->codeAppend("vec3 normal = normalize(normalColor.rgb - vec3(0.5) );"); |
167 fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName); | 87 fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName); |
jvanverth1
2015/07/23 17:40:14
From external discussion, and for a future change:
| |
168 fpb->codeAppend("float NdotL = dot(normal, lightDir);"); | 88 fpb->codeAppend("float NdotL = dot(normal, lightDir);"); |
169 // diffuse light | 89 // diffuse light |
170 fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lig htColorUniName); | 90 fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lig htColorUniName); |
171 // ambient light | 91 // ambient light |
172 fpb->codeAppendf("result += %s.rgb;", ambientColorUniName); | 92 fpb->codeAppendf("result += %s.rgb;", ambientColorUniName); |
173 fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", outputCol or); | 93 fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", outputCol or); |
174 } | 94 } |
175 | 95 |
176 void setData(const GrGLProgramDataManager& pdman, const GrProcessor& pro c) override { | 96 void setData(const GrGLProgramDataManager& pdman, const GrProcessor& pro c) override { |
177 const LightingFP& lightingFP = proc.cast<LightingFP>(); | 97 const LightingFP& lightingFP = proc.cast<LightingFP>(); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 } | 165 } |
246 | 166 |
247 GrCoordTransform fDeviceTransform; | 167 GrCoordTransform fDeviceTransform; |
248 GrTextureAccess fDiffuseTextureAccess; | 168 GrTextureAccess fDiffuseTextureAccess; |
249 GrTextureAccess fNormalTextureAccess; | 169 GrTextureAccess fNormalTextureAccess; |
250 SkVector3 fLightDir; | 170 SkVector3 fLightDir; |
251 GrColor fLightColor; | 171 GrColor fLightColor; |
252 GrColor fAmbientColor; | 172 GrColor fAmbientColor; |
253 }; | 173 }; |
254 | 174 |
255 bool LightingShader::asFragmentProcessor(GrContext* context, const SkPaint& pain t, | 175 //////////////////////////////////////////////////////////////////////////// |
256 const SkMatrix& viewM, const SkMatrix* localMatrix, | 176 |
257 GrColor* color, GrProcessorDataManager* , | 177 bool SkLightingShader::asFragmentProcessor(GrContext* context, const SkPaint& pa int, |
258 GrFragmentProcessor** fp) const { | 178 const SkMatrix& viewM, const SkMatrix * localMatrix, |
179 GrColor* color, GrProcessorDataManage r*, | |
180 GrFragmentProcessor** fp) const { | |
259 // we assume diffuse and normal maps have same width and height | 181 // we assume diffuse and normal maps have same width and height |
260 // TODO: support different sizes | 182 // TODO: support different sizes |
261 SkASSERT(fDiffuseMap.width() == fNormalMap.width() && | 183 SkASSERT(fDiffuseMap.width() == fNormalMap.width() && |
262 fDiffuseMap.height() == fNormalMap.height()); | 184 fDiffuseMap.height() == fNormalMap.height()); |
263 SkMatrix matrix; | 185 SkMatrix matrix; |
264 matrix.setIDiv(fDiffuseMap.width(), fDiffuseMap.height()); | 186 matrix.setIDiv(fDiffuseMap.width(), fDiffuseMap.height()); |
265 | 187 |
266 SkMatrix lmInverse; | 188 SkMatrix lmInverse; |
267 if (!this->getLocalMatrix().invert(&lmInverse)) { | 189 if (!this->getLocalMatrix().invert(&lmInverse)) { |
268 return false; | 190 return false; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
329 GrColor lightColor = GrColorPackRGBA(SkColorGetR(fLight.fColor), SkColorGetG (fLight.fColor), | 251 GrColor lightColor = GrColorPackRGBA(SkColorGetR(fLight.fColor), SkColorGetG (fLight.fColor), |
330 SkColorGetB(fLight.fColor), SkColorGetA (fLight.fColor)); | 252 SkColorGetB(fLight.fColor), SkColorGetA (fLight.fColor)); |
331 GrColor ambientColor = GrColorPackRGBA(SkColorGetR(fAmbientColor), SkColorGe tG(fAmbientColor), | 253 GrColor ambientColor = GrColorPackRGBA(SkColorGetR(fAmbientColor), SkColorGe tG(fAmbientColor), |
332 SkColorGetB(fAmbientColor), SkColorGe tA(fAmbientColor)); | 254 SkColorGetB(fAmbientColor), SkColorGe tA(fAmbientColor)); |
333 | 255 |
334 *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix, | 256 *fp = SkNEW_ARGS(LightingFP, (diffuseTexture, normalTexture, matrix, |
335 fLight.fDirection, lightColor, ambientColor)); | 257 fLight.fDirection, lightColor, ambientColor)); |
336 *color = GrColorPackA4(paint.getAlpha()); | 258 *color = GrColorPackA4(paint.getAlpha()); |
337 return true; | 259 return true; |
338 } | 260 } |
261 #else | |
262 | |
263 bool SkLightingShader::asFragmentProcessor(GrContext* context, const SkPaint& pa int, | |
264 const SkMatrix& viewM, const SkMatrix * localMatrix, | |
265 GrColor* color, GrProcessorDataManage r*, | |
266 GrFragmentProcessor** fp) const { | |
267 SkDEBUGFAIL("Should not call in GPU-less build"); | |
268 return false; | |
269 } | |
270 | |
271 #endif | |
339 | 272 |
340 //////////////////////////////////////////////////////////////////////////// | 273 //////////////////////////////////////////////////////////////////////////// |
341 | 274 |
342 class LightingView : public SampleView { | 275 bool SkLightingShader::isOpaque() const { |
343 public: | 276 return fDiffuseMap.isOpaque(); |
344 SkAutoTUnref<LightingShader> fShader; | 277 } |
345 SkBitmap fDiffuseBitmap; | 278 |
346 SkBitmap fNormalBitmap; | 279 size_t SkLightingShader::contextSize() const { |
347 SkScalar fLightAngle; | 280 return 2 * sizeof(SkBitmapProcState) + sizeof(LightingShaderContext); |
348 int fColorFactor; | 281 } |
349 | 282 |
350 LightingView() { | 283 SkLightingShader::LightingShaderContext::LightingShaderContext(const SkLightingS hader& shader, |
351 SkString diffusePath = GetResourcePath("brickwork-texture.jpg"); | 284 const ContextRec& rec, |
352 SkImageDecoder::DecodeFile(diffusePath.c_str(), &fDiffuseBitmap); | 285 SkBitmapProcState * diffuseState, |
353 SkString normalPath = GetResourcePath("brickwork_normal-map.jpg"); | 286 SkBitmapProcState * normalState) |
354 SkImageDecoder::DecodeFile(normalPath.c_str(), &fNormalBitmap); | 287 : INHERITED(shader, rec) |
355 | 288 , fDiffuseState(diffuseState) |
356 fLightAngle = 0.0f; | 289 , fNormalState(normalState) |
357 fColorFactor = 0; | 290 { |
358 | 291 const SkPixmap& pixmap = fDiffuseState->fPixmap; |
359 LightingShader::Light light; | 292 bool isOpaque = pixmap.isOpaque(); |
360 light.fColor = SkColorSetRGB(0xff, 0xff, 0xff); | 293 |
361 light.fDirection.fX = SkScalarSin(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f); | 294 // update fFlags |
362 light.fDirection.fY = SkScalarCos(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f); | 295 uint32_t flags = 0; |
363 light.fDirection.fZ = SkScalarCos(SK_ScalarPI*0.25f); | 296 if (isOpaque && (255 == this->getPaintAlpha())) { |
364 | 297 flags |= kOpaqueAlpha_Flag; |
365 SkColor ambient = SkColorSetRGB(0x1f, 0x1f, 0x1f); | 298 } |
366 | 299 |
367 fShader.reset(SkNEW_ARGS(LightingShader, (fDiffuseBitmap, fNormalBitmap, light, ambient))); | 300 fFlags = flags; |
368 } | 301 } |
369 | 302 |
370 virtual ~LightingView() {} | 303 SkLightingShader::LightingShaderContext::~LightingShaderContext() { |
371 | 304 // The bitmap proc states have been created outside of the context on memory that will be freed |
372 protected: | 305 // elsewhere. Call the destructors but leave the freeing of the memory to th e caller. |
373 // overrides from SkEventSink | 306 fDiffuseState->~SkBitmapProcState(); |
374 bool onQuery(SkEvent* evt) override { | 307 fNormalState->~SkBitmapProcState(); |
375 if (SampleCode::TitleQ(*evt)) { | 308 } |
376 SampleCode::TitleR(evt, "Lighting"); | 309 |
377 return true; | 310 static inline int light(int light, int diff, SkScalar NdotL, int ambient) { |
378 } | 311 int color = int(light * diff * NdotL + 255 * ambient); |
379 return this->INHERITED::onQuery(evt); | 312 if (color <= 0) { |
380 } | 313 return 0; |
381 | 314 } else if (color >= 255*255) { |
382 void onDrawContent(SkCanvas* canvas) override { | 315 return 255; |
383 fLightAngle += 0.015f; | 316 } else { |
384 fColorFactor++; | 317 return SkDiv255Round(color); |
385 | 318 } |
386 LightingShader::Light light; | 319 } |
387 light.fColor = SkColorSetRGB(0xff, 0xff, (fColorFactor >> 1) & 0xff); | 320 |
388 light.fDirection.fX = SkScalarSin(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f); | 321 // larger is better (fewer times we have to loop), but we shouldn't |
389 light.fDirection.fY = SkScalarCos(fLightAngle)*SkScalarSin(SK_ScalarPI*0 .25f); | 322 // take up too much stack-space (each could here costs 16 bytes) |
390 light.fDirection.fZ = SkScalarCos(SK_ScalarPI*0.25f); | 323 #define TMP_COUNT 16 |
391 | 324 |
392 fShader.get()->setLight(light); | 325 void SkLightingShader::LightingShaderContext::shadeSpan(int x, int y, |
393 | 326 SkPMColor result[], int count) { |
394 SkPaint paint; | 327 const SkLightingShader& lightShader = static_cast<const SkLightingShader&>(f Shader); |
395 paint.setShader(fShader); | 328 |
396 paint.setColor(SK_ColorBLACK); | 329 SkPMColor tmpColor[TMP_COUNT], tmpColor2[TMP_COUNT]; |
397 | 330 SkPMColor tmpNormal[TMP_COUNT], tmpNormal2[TMP_COUNT]; |
398 SkRect r = SkRect::MakeWH((SkScalar)fDiffuseBitmap.width(), | 331 |
399 (SkScalar)fDiffuseBitmap.height()); | 332 SkBitmapProcState::MatrixProc diffMProc = fDiffuseState->getMatrixProc(); |
400 canvas->drawRect(r, paint); | 333 SkBitmapProcState::SampleProc32 diffSProc = fDiffuseState->getSampleProc32() ; |
401 | 334 |
402 // so we're constantly updating | 335 SkBitmapProcState::MatrixProc normalMProc = fNormalState->getMatrixProc(); |
403 this->inval(NULL); | 336 SkBitmapProcState::SampleProc32 normalSProc = fNormalState->getSampleProc32( ); |
404 } | 337 |
405 | 338 SkASSERT(fDiffuseState->fPixmap.addr()); |
406 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride { | 339 SkASSERT(fNormalState->fPixmap.addr()); |
407 this->inval(NULL); | 340 |
408 return this->INHERITED::onFindClickHandler(x, y, modi); | 341 SkPoint3 norm; |
409 } | 342 SkScalar NdotL; |
410 | 343 int r, g, b; |
411 private: | 344 |
412 typedef SampleView INHERITED; | 345 do { |
413 }; | 346 int n = count; |
414 | 347 if (n > TMP_COUNT) { |
415 ////////////////////////////////////////////////////////////////////////////// | 348 n = TMP_COUNT; |
416 | 349 } |
417 static SkView* MyFactory() { return new LightingView; } | 350 |
418 static SkViewRegister reg(MyFactory); | 351 diffMProc(*fDiffuseState, tmpColor, n, x, y); |
352 diffSProc(*fDiffuseState, tmpColor, n, tmpColor2); | |
353 | |
354 normalMProc(*fNormalState, tmpNormal, n, x, y); | |
355 normalSProc(*fNormalState, tmpNormal, n, tmpNormal2); | |
356 | |
357 for (int i = 0; i < n; ++i) { | |
358 SkASSERT(0xFF == SkColorGetA(tmpNormal2[i])); // opaque -> unpremul | |
359 norm.set(SkIntToScalar(SkColorGetR(tmpNormal2[i]))-127.0f, | |
360 SkIntToScalar(SkColorGetG(tmpNormal2[i]))-127.0f, | |
361 SkIntToScalar(SkColorGetB(tmpNormal2[i]))-127.0f); | |
362 norm.normalize(); | |
363 | |
364 SkColor diffColor = SkUnPreMultiply::PMColorToColor(tmpColor2[i]); | |
365 NdotL = norm.dot(lightShader.fLight.fDirection); | |
366 | |
367 // This is all done in linear unpremul color space | |
368 r = light(SkColorGetR(lightShader.fLight.fColor), SkColorGetR(diffCo lor), NdotL, | |
369 SkColorGetR(lightShader.fAmbientColor)); | |
370 g = light(SkColorGetG(lightShader.fLight.fColor), SkColorGetG(diffCo lor), NdotL, | |
371 SkColorGetG(lightShader.fAmbientColor)); | |
372 b = light(SkColorGetB(lightShader.fLight.fColor), SkColorGetB(diffCo lor), NdotL, | |
373 SkColorGetB(lightShader.fAmbientColor)); | |
374 | |
375 result[i] = SkPreMultiplyARGB(SkColorGetA(diffColor), r, g, b); | |
376 } | |
377 | |
378 result += n; | |
379 x += n; | |
380 count -= n; | |
381 } while (count > 0); | |
382 } | |
383 | |
384 //////////////////////////////////////////////////////////////////////////// | |
385 | |
386 #ifndef SK_IGNORE_TO_STRING | |
387 void SkLightingShader::toString(SkString* str) const { | |
388 str->appendf("LightingShader: ()"); | |
389 } | |
390 #endif | |
391 | |
392 SkFlattenable* SkLightingShader::CreateProc(SkReadBuffer& buf) { | |
393 SkBitmap diffuse; | |
394 if (!buf.readBitmap(&diffuse)) { | |
395 return NULL; | |
396 } | |
397 diffuse.setImmutable(); | |
398 | |
399 SkBitmap normal; | |
400 if (!buf.readBitmap(&normal)) { | |
401 return NULL; | |
402 } | |
403 normal.setImmutable(); | |
404 | |
405 Light light; | |
406 if (!buf.readScalarArray(&light.fDirection.fX, 3)) { | |
407 return NULL; | |
408 } | |
409 light.fColor = buf.readColor(); | |
410 | |
411 SkColor ambient = buf.readColor(); | |
412 | |
413 // TODO: this would be nice to enable | |
414 // return SkCreateLightingShader(diffuse, normal, light, ambient, NULL); | |
415 return SkNEW_ARGS(SkLightingShader, (diffuse, normal, light, ambient)); | |
416 } | |
417 | |
418 void SkLightingShader::flatten(SkWriteBuffer& buf) const { | |
419 buf.writeBitmap(fDiffuseMap); | |
420 buf.writeBitmap(fNormalMap); | |
421 buf.writeScalarArray(&fLight.fDirection.fX, 3); | |
422 buf.writeColor(fLight.fColor); | |
423 buf.writeColor(fAmbientColor); | |
424 } | |
425 | |
426 SkShader::Context* SkLightingShader::onCreateContext(const ContextRec& rec, void * storage) const { | |
427 | |
428 SkMatrix totalInverse; | |
429 // Do this first, so we know the matrix can be inverted. | |
430 if (!this->computeTotalInverse(rec, &totalInverse)) { | |
431 return NULL; | |
432 } | |
433 | |
434 void* diffuseStateStorage = (char*)storage + sizeof(LightingShaderContext); | |
435 SkBitmapProcState* diffuseState = SkNEW_PLACEMENT(diffuseStateStorage, SkBit mapProcState); | |
436 SkASSERT(diffuseState); | |
437 | |
438 diffuseState->fTileModeX = SkShader::kClamp_TileMode; | |
439 diffuseState->fTileModeY = SkShader::kClamp_TileMode; | |
440 diffuseState->fOrigBitmap = fDiffuseMap; | |
441 if (!diffuseState->chooseProcs(totalInverse, *rec.fPaint)) { | |
442 diffuseState->~SkBitmapProcState(); | |
443 return NULL; | |
444 } | |
445 | |
446 void* normalStateStorage = (char*)storage + sizeof(LightingShaderContext) + sizeof(SkBitmapProcState); | |
447 SkBitmapProcState* normalState = SkNEW_PLACEMENT(normalStateStorage, SkBitma pProcState); | |
448 SkASSERT(normalState); | |
449 | |
450 normalState->fTileModeX = SkShader::kClamp_TileMode; | |
451 normalState->fTileModeY = SkShader::kClamp_TileMode; | |
452 normalState->fOrigBitmap = fNormalMap; | |
453 if (!normalState->chooseProcs(totalInverse, *rec.fPaint)) { | |
454 diffuseState->~SkBitmapProcState(); | |
455 normalState->~SkBitmapProcState(); | |
456 return NULL; | |
457 } | |
458 | |
459 return SkNEW_PLACEMENT_ARGS(storage, LightingShaderContext, (*this, rec, | |
460 diffuseState, n ormalState)); | |
461 } | |
462 | |
463 /////////////////////////////////////////////////////////////////////////////// | |
464 | |
465 // TODO: it would be nice to be able to call this from SkShader but this | |
466 // would need to reside in core. | |
467 #if 0 | |
468 static bool bitmap_is_too_big(const SkBitmap& bm) { | |
469 // SkBitmapProcShader stores bitmap coordinates in a 16bit buffer, as it | |
470 // communicates between its matrix-proc and its sampler-proc. Until we can | |
471 // widen that, we have to reject bitmaps that are larger. | |
472 // | |
473 static const int kMaxSize = 65535; | |
474 | |
475 return bm.width() > kMaxSize || bm.height() > kMaxSize; | |
476 } | |
477 | |
478 SkShader* SkCreateLightingShader(const SkBitmap& diffuse, const SkBitmap& normal , | |
479 const SkLightingShader::Light& light, const SkC olor ambient, | |
480 SkTBlitterAllocator* allocator) { | |
481 SkShader* shader; | |
482 | |
483 if (diffuse.isNull() || bitmap_is_too_big(diffuse) || | |
484 normal.isNull() || bitmap_is_too_big(normal) || | |
485 diffuse.width() != normal.width() || | |
486 diffuse.height() != normal.height()) { | |
487 if (!allocator) { | |
488 shader = SkNEW(SkEmptyShader); | |
489 } else { | |
490 shader = allocator->createT<SkEmptyShader>(); | |
491 } | |
492 } else { | |
493 if (!allocator) { | |
494 shader = SkNEW_ARGS(SkLightingShader, (diffuse, normal, light, ambie nt)); | |
495 } else { | |
496 shader = allocator->createT<SkLightingShader>(diffuse, normal, light , ambient); | |
497 } | |
498 } | |
499 return shader; | |
500 } | |
501 #endif | |
502 | |
503 /////////////////////////////////////////////////////////////////////////////// | |
OLD | NEW |