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