Index: src/effects/SkLightingImageFilter.cpp |
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp |
index 72dcf64c5879faf45195ac58dd38cddaa5d0347c..972d9ac68ba5ae8a737b84896529c54525dfe669 100644 |
--- a/src/effects/SkLightingImageFilter.cpp |
+++ b/src/effects/SkLightingImageFilter.cpp |
@@ -277,7 +277,136 @@ void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) { |
buffer.writeScalar(point.fZ); |
}; |
-class SkDiffuseLightingImageFilter : public SkLightingImageFilter { |
+enum BoundaryMode { |
+ kTopLeft_BoundaryMode, |
+ kTop_BoundaryMode, |
+ kTopRight_BoundaryMode, |
+ kLeft_BoundaryMode, |
+ kInterior_BoundaryMode, |
+ kRight_BoundaryMode, |
+ kBottomLeft_BoundaryMode, |
+ kBottom_BoundaryMode, |
+ kBottomRight_BoundaryMode, |
+ |
+ kBoundaryModeCount, |
+}; |
+ |
+class SkLightingImageFilterInternal : public SkLightingImageFilter { |
+protected: |
+ SkLightingImageFilterInternal(SkLight* light, |
+ SkScalar surfaceScale, |
+ SkImageFilter* input, |
+ const CropRect* cropRect) |
+ : INHERITED(light, surfaceScale, input, cropRect) {} |
+ |
+#if SK_SUPPORT_GPU |
+ bool canFilterImageGPU() const override { return true; } |
+ bool filterImageGPU(Proxy*, const SkBitmap& src, const Context&, |
+ SkBitmap* result, SkIPoint* offset) const override; |
+ virtual GrFragmentProcessor* getFragmentProcessor(GrTexture*, |
+ const SkMatrix&, |
+ const SkIRect& bounds, |
+ BoundaryMode boundaryMode) const = 0; |
+#endif |
+private: |
+#if SK_SUPPORT_GPU |
+ void drawRect(GrContext* context, |
+ GrTexture* src, |
+ GrTexture* dst, |
+ const SkMatrix& matrix, |
+ const GrClip& clip, |
+ const SkRect& dstRect, |
+ BoundaryMode boundaryMode, |
+ const SkIRect& bounds) const; |
+#endif |
+ typedef SkLightingImageFilter INHERITED; |
+}; |
+ |
+#if SK_SUPPORT_GPU |
+void SkLightingImageFilterInternal::drawRect(GrContext* context, |
+ GrTexture* src, |
+ GrTexture* dst, |
+ const SkMatrix& matrix, |
+ const GrClip& clip, |
+ const SkRect& dstRect, |
+ BoundaryMode boundaryMode, |
+ const SkIRect& bounds) const { |
+ SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y())); |
+ GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, bounds, boundaryMode); |
+ GrPaint paint; |
+ paint.addColorProcessor(fp)->unref(); |
+ context->drawNonAARectToRect(dst->asRenderTarget(), clip, paint, SkMatrix::I(), |
+ dstRect, srcRect); |
+} |
+ |
+bool SkLightingImageFilterInternal::filterImageGPU(Proxy* proxy, |
+ const SkBitmap& src, |
+ const Context& ctx, |
+ SkBitmap* result, |
+ SkIPoint* offset) const { |
+ SkBitmap input = src; |
+ SkIPoint srcOffset = SkIPoint::Make(0, 0); |
+ if (this->getInput(0) && |
+ !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) { |
+ return false; |
+ } |
+ SkIRect bounds; |
+ if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) { |
+ return false; |
+ } |
+ SkRect dstRect = SkRect::MakeWH(SkIntToScalar(bounds.width()), |
+ SkIntToScalar(bounds.height())); |
+ GrTexture* srcTexture = input.getTexture(); |
+ GrContext* context = srcTexture->getContext(); |
+ |
+ GrSurfaceDesc desc; |
+ desc.fFlags = kRenderTarget_GrSurfaceFlag, |
+ desc.fWidth = bounds.width(); |
+ desc.fHeight = bounds.height(); |
+ desc.fConfig = kRGBA_8888_GrPixelConfig; |
+ |
+ SkAutoTUnref<GrTexture> dst( |
+ context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch)); |
+ if (!dst) { |
+ return false; |
+ } |
+ |
+ // setup new clip |
+ GrClip clip(dstRect); |
+ |
+ offset->fX = bounds.left(); |
+ offset->fY = bounds.top(); |
+ SkMatrix matrix(ctx.ctm()); |
+ matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top())); |
+ bounds.offset(-srcOffset); |
+ SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1); |
+ SkRect top = SkRect::MakeXYWH(1, 0, dstRect.width() - 2, 1); |
+ SkRect topRight = SkRect::MakeXYWH(dstRect.width() - 1, 0, 1, 1); |
+ SkRect left = SkRect::MakeXYWH(0, 1, 1, dstRect.height() - 2); |
+ SkRect interior = dstRect.makeInset(1, 1); |
+ SkRect right = SkRect::MakeXYWH(dstRect.width() - 1, 1, 1, dstRect.height() - 2); |
+ SkRect bottomLeft = SkRect::MakeXYWH(0, dstRect.height() - 1, 1, 1); |
+ SkRect bottom = SkRect::MakeXYWH(1, dstRect.height() - 1, dstRect.width() - 2, 1); |
+ SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1); |
+ this->drawRect(context, srcTexture, dst, matrix, clip, topLeft, kTopLeft_BoundaryMode, bounds); |
+ this->drawRect(context, srcTexture, dst, matrix, clip, top, kTop_BoundaryMode, bounds); |
+ this->drawRect(context, srcTexture, dst, matrix, clip, topRight, kTopRight_BoundaryMode, |
+ bounds); |
+ this->drawRect(context, srcTexture, dst, matrix, clip, left, kLeft_BoundaryMode, bounds); |
+ this->drawRect(context, srcTexture, dst, matrix, clip, interior, kInterior_BoundaryMode, |
+ bounds); |
+ this->drawRect(context, srcTexture, dst, matrix, clip, right, kRight_BoundaryMode, bounds); |
+ this->drawRect(context, srcTexture, dst, matrix, clip, bottomLeft, kBottomLeft_BoundaryMode, |
+ bounds); |
+ this->drawRect(context, srcTexture, dst, matrix, clip, bottom, kBottom_BoundaryMode, bounds); |
+ this->drawRect(context, srcTexture, dst, matrix, clip, bottomRight, kBottomRight_BoundaryMode, |
+ bounds); |
+ WrapTexture(dst, bounds.width(), bounds.height(), result); |
+ return true; |
+} |
+#endif |
+ |
+class SkDiffuseLightingImageFilter : public SkLightingImageFilterInternal { |
public: |
static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter*, |
const CropRect*); |
@@ -290,20 +419,20 @@ protected: |
SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, |
SkScalar kd, SkImageFilter* input, const CropRect* cropRect); |
void flatten(SkWriteBuffer& buffer) const override; |
- virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, |
- SkBitmap* result, SkIPoint* offset) const override; |
+ bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, |
+ SkBitmap* result, SkIPoint* offset) const override; |
#if SK_SUPPORT_GPU |
- virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, |
- const SkIRect& bounds) const override; |
+ GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, |
+ const SkIRect& bounds, BoundaryMode) const override; |
#endif |
private: |
friend class SkLightingImageFilter; |
- typedef SkLightingImageFilter INHERITED; |
+ typedef SkLightingImageFilterInternal INHERITED; |
SkScalar fKD; |
}; |
-class SkSpecularLightingImageFilter : public SkLightingImageFilter { |
+class SkSpecularLightingImageFilter : public SkLightingImageFilterInternal { |
public: |
static SkImageFilter* Create(SkLight* light, SkScalar surfaceScale, |
SkScalar ks, SkScalar shininess, SkImageFilter*, const CropRect*); |
@@ -318,30 +447,32 @@ protected: |
SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, |
SkScalar shininess, SkImageFilter* input, const CropRect*); |
void flatten(SkWriteBuffer& buffer) const override; |
- virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, |
- SkBitmap* result, SkIPoint* offset) const override; |
+ bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, |
+ SkBitmap* result, SkIPoint* offset) const override; |
#if SK_SUPPORT_GPU |
- virtual bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, |
- const SkIRect& bounds) const override; |
+ GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, |
+ const SkIRect& bounds, BoundaryMode) const override; |
#endif |
private: |
SkScalar fKS; |
SkScalar fShininess; |
friend class SkLightingImageFilter; |
- typedef SkLightingImageFilter INHERITED; |
+ typedef SkLightingImageFilterInternal INHERITED; |
}; |
#if SK_SUPPORT_GPU |
class GrLightingEffect : public GrSingleTextureEffect { |
public: |
- GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, const SkMatrix& matrix); |
+ GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, |
+ const SkMatrix& matrix, BoundaryMode boundaryMode); |
virtual ~GrLightingEffect(); |
const SkLight* light() const { return fLight; } |
SkScalar surfaceScale() const { return fSurfaceScale; } |
const SkMatrix& filterMatrix() const { return fFilterMatrix; } |
+ BoundaryMode boundaryMode() const { return fBoundaryMode; } |
protected: |
bool onIsEqual(const GrFragmentProcessor&) const override; |
@@ -356,6 +487,7 @@ private: |
const SkLight* fLight; |
SkScalar fSurfaceScale; |
SkMatrix fFilterMatrix; |
+ BoundaryMode fBoundaryMode; |
}; |
class GrDiffuseLightingEffect : public GrLightingEffect { |
@@ -364,12 +496,14 @@ public: |
const SkLight* light, |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
- SkScalar kd) { |
+ SkScalar kd, |
+ BoundaryMode boundaryMode) { |
return SkNEW_ARGS(GrDiffuseLightingEffect, (texture, |
light, |
surfaceScale, |
matrix, |
- kd)); |
+ kd, |
+ boundaryMode)); |
} |
const char* name() const override { return "DiffuseLighting"; } |
@@ -387,7 +521,8 @@ private: |
const SkLight* light, |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
- SkScalar kd); |
+ SkScalar kd, |
+ BoundaryMode boundaryMode); |
GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
typedef GrLightingEffect INHERITED; |
@@ -401,13 +536,15 @@ public: |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
SkScalar ks, |
- SkScalar shininess) { |
+ SkScalar shininess, |
+ BoundaryMode boundaryMode) { |
return SkNEW_ARGS(GrSpecularLightingEffect, (texture, |
light, |
surfaceScale, |
matrix, |
ks, |
- shininess)); |
+ shininess, |
+ boundaryMode)); |
} |
const char* name() const override { return "SpecularLighting"; } |
@@ -427,7 +564,8 @@ private: |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
SkScalar ks, |
- SkScalar shininess); |
+ SkScalar shininess, |
+ BoundaryMode boundaryMode); |
GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
typedef GrLightingEffect INHERITED; |
@@ -481,8 +619,7 @@ private: |
class GrGLDistantLight : public GrGLLight { |
public: |
virtual ~GrGLDistantLight() {} |
- virtual void setData(const GrGLProgramDataManager&, |
- const SkLight* light) const override; |
+ void setData(const GrGLProgramDataManager&, const SkLight* light) const override; |
void emitSurfaceToLight(GrGLFPBuilder*, const char* z) override; |
private: |
@@ -495,8 +632,7 @@ private: |
class GrGLPointLight : public GrGLLight { |
public: |
virtual ~GrGLPointLight() {} |
- virtual void setData(const GrGLProgramDataManager&, |
- const SkLight* light) const override; |
+ void setData(const GrGLProgramDataManager&, const SkLight* light) const override; |
void emitSurfaceToLight(GrGLFPBuilder*, const char* z) override; |
private: |
@@ -509,8 +645,7 @@ private: |
class GrGLSpotLight : public GrGLLight { |
public: |
virtual ~GrGLSpotLight() {} |
- virtual void setData(const GrGLProgramDataManager&, |
- const SkLight* light) const override; |
+ void setData(const GrGLProgramDataManager&, const SkLight* light) const override; |
void emitSurfaceToLight(GrGLFPBuilder*, const char* z) override; |
void emitLightColor(GrGLFPBuilder*, const char *surfaceToLight) override; |
@@ -695,7 +830,11 @@ private: |
class SkSpotLight : public SkLight { |
public: |
- SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color) |
+ SkSpotLight(const SkPoint3& location, |
+ const SkPoint3& target, |
+ SkScalar specularExponent, |
+ SkScalar cutoffAngle, |
+ SkColor color) |
: INHERITED(color), |
fLocation(location), |
fTarget(target), |
@@ -723,7 +862,14 @@ public: |
SkPoint3 target(target2.fX, target2.fY, SkScalarAve(targetZ.fX, targetZ.fY)); |
SkPoint3 s = target - location; |
s.normalize(); |
- return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, s, color()); |
+ return new SkSpotLight(location, |
+ target, |
+ fSpecularExponent, |
+ fCosOuterConeAngle, |
+ fCosInnerConeAngle, |
+ fConeScale, |
+ s, |
+ color()); |
} |
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const { |
@@ -777,7 +923,14 @@ public: |
SkScalarIsFinite(fConeScale)); |
} |
protected: |
- SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cosOuterConeAngle, SkScalar cosInnerConeAngle, SkScalar coneScale, const SkPoint3& s, const SkPoint3& color) |
+ SkSpotLight(const SkPoint3& location, |
+ const SkPoint3& target, |
+ SkScalar specularExponent, |
+ SkScalar cosOuterConeAngle, |
+ SkScalar cosInnerConeAngle, |
+ SkScalar coneScale, |
+ const SkPoint3& s, |
+ const SkPoint3& color) |
: INHERITED(color), |
fLocation(location), |
fTarget(target), |
@@ -960,8 +1113,12 @@ SkImageFilter* SkDiffuseLightingImageFilter::Create(SkLight* light, SkScalar sur |
return SkNEW_ARGS(SkDiffuseLightingImageFilter, (light, surfaceScale, kd, input, cropRect)); |
} |
-SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input, const CropRect* cropRect) |
- : SkLightingImageFilter(light, surfaceScale, input, cropRect), |
+SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, |
+ SkScalar surfaceScale, |
+ SkScalar kd, |
+ SkImageFilter* input, |
+ const CropRect* cropRect) |
+ : INHERITED(light, surfaceScale, input, cropRect), |
fKD(kd) |
{ |
} |
@@ -1020,13 +1177,28 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy, |
bounds.offset(-srcOffset); |
switch (transformedLight->type()) { |
case SkLight::kDistant_LightType: |
- lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); |
+ lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, |
+ transformedLight, |
+ src, |
+ dst, |
+ surfaceScale(), |
+ bounds); |
break; |
case SkLight::kPoint_LightType: |
- lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); |
+ lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, |
+ transformedLight, |
+ src, |
+ dst, |
+ surfaceScale(), |
+ bounds); |
break; |
case SkLight::kSpot_LightType: |
- lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); |
+ lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, |
+ transformedLight, |
+ src, |
+ dst, |
+ surfaceScale(), |
+ bounds); |
break; |
} |
@@ -1042,15 +1214,14 @@ void SkDiffuseLightingImageFilter::toString(SkString* str) const { |
#endif |
#if SK_SUPPORT_GPU |
-bool SkDiffuseLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, |
+GrFragmentProcessor* SkDiffuseLightingImageFilter::getFragmentProcessor( |
GrTexture* texture, |
const SkMatrix& matrix, |
- const SkIRect&) const { |
- if (fp) { |
- SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); |
- *fp = GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd()); |
- } |
- return true; |
+ const SkIRect&, |
+ BoundaryMode boundaryMode |
+) const { |
+ SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); |
+ return GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd(), boundaryMode); |
} |
#endif |
@@ -1073,8 +1244,13 @@ SkImageFilter* SkSpecularLightingImageFilter::Create(SkLight* light, SkScalar su |
(light, surfaceScale, ks, shininess, input, cropRect)); |
} |
-SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) |
- : SkLightingImageFilter(light, surfaceScale, input, cropRect), |
+SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, |
+ SkScalar surfaceScale, |
+ SkScalar ks, |
+ SkScalar shininess, |
+ SkImageFilter* input, |
+ const CropRect* cropRect) |
+ : INHERITED(light, surfaceScale, input, cropRect), |
fKS(ks), |
fShininess(shininess) |
{ |
@@ -1136,13 +1312,28 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy, |
SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm())); |
switch (transformedLight->type()) { |
case SkLight::kDistant_LightType: |
- lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); |
+ lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, |
+ transformedLight, |
+ src, |
+ dst, |
+ surfaceScale(), |
+ bounds); |
break; |
case SkLight::kPoint_LightType: |
- lightBitmap<SpecularLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); |
+ lightBitmap<SpecularLightingType, SkPointLight>(lightingType, |
+ transformedLight, |
+ src, |
+ dst, |
+ surfaceScale(), |
+ bounds); |
break; |
case SkLight::kSpot_LightType: |
- lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); |
+ lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, |
+ transformedLight, |
+ src, |
+ dst, |
+ surfaceScale(), |
+ bounds); |
break; |
} |
return true; |
@@ -1157,15 +1348,14 @@ void SkSpecularLightingImageFilter::toString(SkString* str) const { |
#endif |
#if SK_SUPPORT_GPU |
-bool SkSpecularLightingImageFilter::asFragmentProcessor(GrFragmentProcessor** fp, |
- GrTexture* texture, |
- const SkMatrix& matrix, |
- const SkIRect&) const { |
- if (fp) { |
- SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); |
- *fp = GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess()); |
- } |
- return true; |
+GrFragmentProcessor* SkSpecularLightingImageFilter::getFragmentProcessor( |
+ GrTexture* texture, |
+ const SkMatrix& matrix, |
+ const SkIRect&, |
+ BoundaryMode boundaryMode) const { |
+ SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); |
+ return GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess(), |
+ boundaryMode); |
} |
#endif |
@@ -1202,6 +1392,81 @@ SkLight* create_random_light(SkRandom* random) { |
} |
} |
+SkString emitNormalFunc(BoundaryMode mode, |
+ const char* pointToNormalName, |
+ const char* sobelFuncName) { |
+ SkString result; |
+ switch (mode) { |
+ case kTopLeft_BoundaryMode: |
+ result.printf("\treturn %s(%s(0.0, 0.0, m[4], m[5], m[7], m[8], %g),\n" |
+ "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n" |
+ "\t surfaceScale);\n", |
+ pointToNormalName, sobelFuncName, gTwoThirds, |
+ sobelFuncName, gTwoThirds); |
+ break; |
+ case kTop_BoundaryMode: |
+ result.printf("\treturn %s(%s(0.0, 0.0, m[3], m[5], m[6], m[8], %g),\n" |
+ "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n" |
+ "\t surfaceScale);\n", |
+ pointToNormalName, sobelFuncName, gOneThird, |
+ sobelFuncName, gOneHalf); |
+ break; |
+ case kTopRight_BoundaryMode: |
+ result.printf("\treturn %s(%s( 0.0, 0.0, m[3], m[4], m[6], m[7], %g),\n" |
+ "\t %s(m[3], m[6], m[4], m[7], 0.0, 0.0, %g),\n" |
+ "\t surfaceScale);\n", |
+ pointToNormalName, sobelFuncName, gTwoThirds, |
+ sobelFuncName, gTwoThirds); |
+ break; |
+ case kLeft_BoundaryMode: |
+ result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], m[7], m[8], %g),\n" |
+ "\t %s( 0.0, 0.0, m[1], m[7], m[2], m[8], %g),\n" |
+ "\t surfaceScale);\n", |
+ pointToNormalName, sobelFuncName, gOneHalf, |
+ sobelFuncName, gOneThird); |
+ break; |
+ case kInterior_BoundaryMode: |
+ result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], %g),\n" |
+ "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], %g),\n" |
+ "\t surfaceScale);\n", |
+ pointToNormalName, sobelFuncName, gOneQuarter, |
+ sobelFuncName, gOneQuarter); |
+ break; |
+ case kRight_BoundaryMode: |
+ result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], m[6], m[7], %g),\n" |
+ "\t %s(m[0], m[6], m[1], m[7], 0.0, 0.0, %g),\n" |
+ "\t surfaceScale);\n", |
+ pointToNormalName, sobelFuncName, gOneHalf, |
+ sobelFuncName, gOneThird); |
+ break; |
+ case kBottomLeft_BoundaryMode: |
+ result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], 0.0, 0.0, %g),\n" |
+ "\t %s( 0.0, 0.0, m[1], m[4], m[2], m[5], %g),\n" |
+ "\t surfaceScale);\n", |
+ pointToNormalName, sobelFuncName, gTwoThirds, |
+ sobelFuncName, gTwoThirds); |
+ break; |
+ case kBottom_BoundaryMode: |
+ result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], 0.0, 0.0, %g),\n" |
+ "\t %s(m[0], m[3], m[1], m[4], m[2], m[5], %g),\n" |
+ "\t surfaceScale);\n", |
+ pointToNormalName, sobelFuncName, gOneThird, |
+ sobelFuncName, gOneHalf); |
+ break; |
+ case kBottomRight_BoundaryMode: |
+ result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], 0.0, 0.0, %g),\n" |
+ "\t %s(m[0], m[3], m[1], m[4], 0.0, 0.0, %g),\n" |
+ "\t surfaceScale);\n", |
+ pointToNormalName, sobelFuncName, gTwoThirds, |
+ sobelFuncName, gTwoThirds); |
+ break; |
+ default: |
+ SkASSERT(false); |
+ break; |
+ } |
+ return result; |
+} |
+ |
} |
class GrGLLightingEffect : public GrGLFragmentProcessor { |
@@ -1209,12 +1474,12 @@ public: |
GrGLLightingEffect(const GrProcessor&); |
virtual ~GrGLLightingEffect(); |
- virtual void emitCode(GrGLFPBuilder*, |
- const GrFragmentProcessor&, |
- const char* outputColor, |
- const char* inputColor, |
- const TransformedCoordsArray&, |
- const TextureSamplerArray&) override; |
+ void emitCode(GrGLFPBuilder*, |
+ const GrFragmentProcessor&, |
+ const char* outputColor, |
+ const char* inputColor, |
+ const TransformedCoordsArray&, |
+ const TextureSamplerArray&) override; |
static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b); |
@@ -1232,6 +1497,7 @@ private: |
UniformHandle fImageIncrementUni; |
UniformHandle fSurfaceScaleUni; |
GrGLLight* fLight; |
+ BoundaryMode fBoundaryMode; |
}; |
/////////////////////////////////////////////////////////////////////////////// |
@@ -1268,11 +1534,13 @@ private: |
GrLightingEffect::GrLightingEffect(GrTexture* texture, |
const SkLight* light, |
SkScalar surfaceScale, |
- const SkMatrix& matrix) |
+ const SkMatrix& matrix, |
+ BoundaryMode boundaryMode) |
: INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)) |
, fLight(light) |
, fSurfaceScale(surfaceScale) |
- , fFilterMatrix(matrix) { |
+ , fFilterMatrix(matrix) |
+ , fBoundaryMode(boundaryMode) { |
fLight->ref(); |
if (light->requiresFragmentPosition()) { |
this->setWillReadFragmentPosition(); |
@@ -1286,7 +1554,8 @@ GrLightingEffect::~GrLightingEffect() { |
bool GrLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const { |
const GrLightingEffect& s = sBase.cast<GrLightingEffect>(); |
return fLight->isEqual(*s.fLight) && |
- fSurfaceScale == s.fSurfaceScale; |
+ fSurfaceScale == s.fSurfaceScale && |
+ fBoundaryMode == s.fBoundaryMode; |
} |
/////////////////////////////////////////////////////////////////////////////// |
@@ -1295,8 +1564,9 @@ GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, |
const SkLight* light, |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
- SkScalar kd) |
- : INHERITED(texture, light, surfaceScale, matrix), fKD(kd) { |
+ SkScalar kd, |
+ BoundaryMode boundaryMode) |
+ : INHERITED(texture, light, surfaceScale, matrix, boundaryMode), fKD(kd) { |
this->initClassID<GrDiffuseLightingEffect>(); |
} |
@@ -1328,8 +1598,9 @@ GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(SkRandom* random, |
for (int i = 0; i < 9; i++) { |
matrix[i] = random->nextUScalar1(); |
} |
+ BoundaryMode mode = static_cast<BoundaryMode>(random->nextU() % kBoundaryModeCount); |
return GrDiffuseLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx], |
- light, surfaceScale, matrix, kd); |
+ light, surfaceScale, matrix, kd, mode); |
} |
@@ -1338,6 +1609,7 @@ GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(SkRandom* random, |
GrGLLightingEffect::GrGLLightingEffect(const GrProcessor& fp) { |
const GrLightingEffect& m = fp.cast<GrLightingEffect>(); |
fLight = m.light()->createGLLight(); |
+ fBoundaryMode = m.boundaryMode(); |
} |
GrGLLightingEffect::~GrGLLightingEffect() { |
@@ -1388,27 +1660,23 @@ void GrGLLightingEffect::emitCode(GrGLFPBuilder* builder, |
"pointToNormal", |
SK_ARRAY_COUNT(gPointToNormalArgs), |
gPointToNormalArgs, |
- "\treturn normalize(vec3(-x * scale, y * scale, 1));\n", |
+ "\treturn normalize(vec3(-x * scale, -y * scale, 1));\n", |
&pointToNormalName); |
static const GrGLShaderVar gInteriorNormalArgs[] = { |
GrGLShaderVar("m", kFloat_GrSLType, 9), |
GrGLShaderVar("surfaceScale", kFloat_GrSLType), |
}; |
- SkString interiorNormalBody; |
- interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n" |
- "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n" |
- "\t surfaceScale);\n", |
- pointToNormalName.c_str(), |
- sobelFuncName.c_str(), |
- sobelFuncName.c_str()); |
- SkString interiorNormalName; |
+ SkString normalBody = emitNormalFunc(fBoundaryMode, |
+ pointToNormalName.c_str(), |
+ sobelFuncName.c_str()); |
+ SkString normalName; |
fsBuilder->emitFunction(kVec3f_GrSLType, |
- "interiorNormal", |
+ "normal", |
SK_ARRAY_COUNT(gInteriorNormalArgs), |
gInteriorNormalArgs, |
- interiorNormalBody.c_str(), |
- &interiorNormalName); |
+ normalBody.c_str(), |
+ &normalName); |
fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); |
fsBuilder->codeAppend("\t\tfloat m[9];\n"); |
@@ -1417,7 +1685,7 @@ void GrGLLightingEffect::emitCode(GrGLFPBuilder* builder, |
const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni); |
int index = 0; |
- for (int dy = -1; dy <= 1; dy++) { |
+ for (int dy = 1; dy >= -1; dy--) { |
for (int dx = -1; dx <= 1; dx++) { |
SkString texCoords; |
texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc); |
@@ -1432,7 +1700,7 @@ void GrGLLightingEffect::emitCode(GrGLFPBuilder* builder, |
fLight->emitSurfaceToLight(builder, arg.c_str()); |
fsBuilder->codeAppend(";\n"); |
fsBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ", |
- outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale); |
+ outputColor, lightFunc.c_str(), normalName.c_str(), surfScale); |
fLight->emitLightColor(builder, "surfaceToLight"); |
fsBuilder->codeAppend(");\n"); |
SkString modulate; |
@@ -1442,7 +1710,8 @@ void GrGLLightingEffect::emitCode(GrGLFPBuilder* builder, |
void GrGLLightingEffect::GenKey(const GrProcessor& proc, |
const GrGLCaps& caps, GrProcessorKeyBuilder* b) { |
- b->add32(proc.cast<GrLightingEffect>().light()->type()); |
+ const GrLightingEffect& lighting = proc.cast<GrLightingEffect>(); |
+ b->add32(lighting.boundaryMode() << 2 | lighting.light()->type()); |
} |
void GrGLLightingEffect::setData(const GrGLProgramDataManager& pdman, |
@@ -1500,8 +1769,9 @@ GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, |
SkScalar surfaceScale, |
const SkMatrix& matrix, |
SkScalar ks, |
- SkScalar shininess) |
- : INHERITED(texture, light, surfaceScale, matrix), |
+ SkScalar shininess, |
+ BoundaryMode boundaryMode) |
+ : INHERITED(texture, light, surfaceScale, matrix, boundaryMode), |
fKS(ks), |
fShininess(shininess) { |
this->initClassID<GrSpecularLightingEffect>(); |
@@ -1537,8 +1807,9 @@ GrFragmentProcessor* GrSpecularLightingEffect::TestCreate(SkRandom* random, |
for (int i = 0; i < 9; i++) { |
matrix[i] = random->nextUScalar1(); |
} |
+ BoundaryMode mode = static_cast<BoundaryMode>(random->nextU() % kBoundaryModeCount); |
return GrSpecularLightingEffect::Create(textures[GrProcessorUnitTest::kAlphaTextureIdx], |
- light, surfaceScale, matrix, ks, shininess); |
+ light, surfaceScale, matrix, ks, shininess, mode); |
} |
/////////////////////////////////////////////////////////////////////////////// |
@@ -1554,7 +1825,10 @@ void GrGLSpecularLightingEffect::emitLightFunc(GrGLFPBuilder* builder, SkString* |
fKSUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
kFloat_GrSLType, kDefault_GrSLPrecision, "KS", &ks); |
fShininessUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
- kFloat_GrSLType, kDefault_GrSLPrecision, "Shininess", &shininess); |
+ kFloat_GrSLType, |
+ kDefault_GrSLPrecision, |
+ "Shininess", |
+ &shininess); |
static const GrGLShaderVar gLightArgs[] = { |
GrGLShaderVar("normal", kVec3f_GrSLType), |