refactor lighting imagefilter to save codesize
Goal was to just remove template args and add virtuals where needed. Ended up having to also move a couple of classes/helpers earlier in the file, but nothing beyond that. Size savings (on Mac laptop) : 67896 Before: 8/8 MB 1 30.6ms 30.7ms 30.7ms 30.9ms 0% █▁▅▁▄▃▄▁▃▃ 8888 lightingspotlitspecular_large 8/8 MB 1 34.2ms 37.6ms 38.5ms 45.9ms 9% ▂▂▃▅▁▅█▂▅▂ 8888 lightingspotlitspecular_small 8/8 MB 1 31.3ms 35ms 34.6ms 38.4ms 7% ▁▄▅▆▆▁▇▃▂█ 8888 lightingdistantlitspecular_large 8/8 MB 1 29.9ms 33.5ms 34.3ms 39.2ms 8% ▁▅█▃▄▇▄▂▄▆ 8888 lightingdistantlitspecular_small 8/8 MB 1 30.4ms 34.1ms 34.5ms 40.7ms 11% ▂▄█▃▁▅▂▅▁▇ 8888 lightingpointlitspecular_large 8/8 MB 1 29.8ms 36.2ms 34.8ms 41.4ms 12% ▂▃▅▁▅▇▂▁▆█ 8888 lightingpointlitspecular_small 8/8 MB 1 16.3ms 19.5ms 20.5ms 26.6ms 17% ▁▆▃▃█▃▂▅▁▆ 8888 lightingspotlitdiffuse_large 8/8 MB 1 17.3ms 19.3ms 19.4ms 23.3ms 10% ▄▁▂▁▆▅▁▃▂█ 8888 lightingspotlitdiffuse_small 8/8 MB 1 12.7ms 14.9ms 17ms 27.9ms 30% ▂▁█▁▂▄▂▂▂▆ 8888 lightingdistantlitdiffuse_large 8/8 MB 1 12.4ms 14.5ms 15.8ms 24.7ms 23% ▁▂▅▂▁▃█▂▃▂ 8888 lightingdistantlitdiffuse_small 8/8 MB 1 13.6ms 14.9ms 16.6ms 22.5ms 22% ▁█▅▁▆▂▁▂▁█ 8888 lightingpointlitdiffuse_large 8/8 MB 1 13.8ms 17ms 16.5ms 19.2ms 11% ▆▆▁▁▆▅▅█▃▂ 8888 lightingpointlitdiffuse_small After: 8/8 MB 1 23.5ms 23.6ms 23.8ms 25.1ms 2% ▃▁█▁▁▂▁▂▁▁ 8888 lightingspotlitspecular_large 8/8 MB 1 23.5ms 23.6ms 23.9ms 24.9ms 2% █▅▂▁▁▁▁▁▆▃ 8888 lightingspotlitspecular_small 8/8 MB 1 21.6ms 21.8ms 21.9ms 22.3ms 1% █▆▃▁▄▄▃▂▄▂ 8888 lightingdistantlitspecular_large 8/8 MB 1 21.6ms 21.7ms 21.9ms 22.7ms 2% █▅▂▂▂▁▂▂▂▃ 8888 lightingdistantlitspecular_small 8/8 MB 1 22.3ms 22.9ms 22.8ms 23.2ms 1% ▇▆▁▄▆▄▃█▄▆ 8888 lightingpointlitspecular_large 8/8 MB 1 22.1ms 22.2ms 22.5ms 23.6ms 3% ██▁▁▂▂▁▁▂▂ 8888 lightingpointlitspecular_small 8/8 MB 1 12.8ms 13ms 13ms 13.3ms 2% ▃▇█▇▁▅▄▃▂▄ 8888 lightingspotlitdiffuse_large 8/8 MB 1 12.8ms 13ms 13ms 13.2ms 1% ▄▃██▄▁▃▅▂▇ 8888 lightingspotlitdiffuse_small 8/8 MB 1 10.6ms 10.7ms 10.8ms 11.1ms 2% ▂▄██▂▁▃▃▂▂ 8888 lightingdistantlitdiffuse_large 8/8 MB 1 10.6ms 10.7ms 10.8ms 11.3ms 2% ▂▂▇█▃▁▂▅▁▂ 8888 lightingdistantlitdiffuse_small 8/8 MB 1 10.9ms 11.1ms 11.2ms 11.6ms 2% ▁▂▇▁█▃▂▂▇▁ 8888 lightingpointlitdiffuse_large 8/8 MB 1 10.9ms 11.1ms 11.1ms 11.5ms 2% ▄▃█▅▃▃▁▃▂▁ 8888 lightingpointlitdiffuse_small Bug: skia: Change-Id: I7542a5ca1f209a732630f646b4ceb4fb08150ce4 Reviewed-on: https://skia-review.googlesource.com/20155 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
5f970fe6be
commit
0c182fc77e
@ -77,12 +77,83 @@ static inline void fast_normalize(SkPoint3* vector) {
|
||||
vector->fZ *= scale;
|
||||
}
|
||||
|
||||
class DiffuseLightingType {
|
||||
static SkPoint3 readPoint3(SkReadBuffer& buffer) {
|
||||
SkPoint3 point;
|
||||
point.fX = buffer.readScalar();
|
||||
point.fY = buffer.readScalar();
|
||||
point.fZ = buffer.readScalar();
|
||||
buffer.validate(SkScalarIsFinite(point.fX) &&
|
||||
SkScalarIsFinite(point.fY) &&
|
||||
SkScalarIsFinite(point.fZ));
|
||||
return point;
|
||||
};
|
||||
|
||||
static void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
|
||||
buffer.writeScalar(point.fX);
|
||||
buffer.writeScalar(point.fY);
|
||||
buffer.writeScalar(point.fZ);
|
||||
};
|
||||
|
||||
class GrGLLight;
|
||||
class SkImageFilterLight : public SkRefCnt {
|
||||
public:
|
||||
enum LightType {
|
||||
kDistant_LightType,
|
||||
kPoint_LightType,
|
||||
kSpot_LightType,
|
||||
};
|
||||
virtual LightType type() const = 0;
|
||||
const SkPoint3& color() const { return fColor; }
|
||||
virtual GrGLLight* createGLLight() const = 0;
|
||||
virtual bool isEqual(const SkImageFilterLight& other) const {
|
||||
return fColor == other.fColor;
|
||||
}
|
||||
virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
|
||||
|
||||
virtual sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer*) const = 0;
|
||||
|
||||
// Defined below SkLight's subclasses.
|
||||
void flattenLight(SkWriteBuffer& buffer) const;
|
||||
static SkImageFilterLight* UnflattenLight(SkReadBuffer& buffer);
|
||||
|
||||
virtual SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const = 0;
|
||||
virtual SkPoint3 lightColor(const SkPoint3& surfaceToLight) const = 0;
|
||||
|
||||
protected:
|
||||
SkImageFilterLight(SkColor color) {
|
||||
fColor = SkPoint3::Make(SkIntToScalar(SkColorGetR(color)),
|
||||
SkIntToScalar(SkColorGetG(color)),
|
||||
SkIntToScalar(SkColorGetB(color)));
|
||||
}
|
||||
SkImageFilterLight(const SkPoint3& color)
|
||||
: fColor(color) {}
|
||||
SkImageFilterLight(SkReadBuffer& buffer) {
|
||||
fColor = readPoint3(buffer);
|
||||
}
|
||||
|
||||
virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
|
||||
|
||||
|
||||
private:
|
||||
typedef SkRefCnt INHERITED;
|
||||
SkPoint3 fColor;
|
||||
};
|
||||
|
||||
class BaseLightingType {
|
||||
public:
|
||||
BaseLightingType() {}
|
||||
virtual ~BaseLightingType() {}
|
||||
|
||||
virtual SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
|
||||
const SkPoint3& lightColor) const= 0;
|
||||
};
|
||||
|
||||
class DiffuseLightingType : public BaseLightingType {
|
||||
public:
|
||||
DiffuseLightingType(SkScalar kd)
|
||||
: fKD(kd) {}
|
||||
SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
|
||||
const SkPoint3& lightColor) const {
|
||||
const SkPoint3& lightColor) const override {
|
||||
SkScalar colorScale = fKD * normal.dot(surfaceTolight);
|
||||
colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
|
||||
SkPoint3 color = lightColor.makeScale(colorScale);
|
||||
@ -99,12 +170,12 @@ static SkScalar max_component(const SkPoint3& p) {
|
||||
return p.x() > p.y() ? (p.x() > p.z() ? p.x() : p.z()) : (p.y() > p.z() ? p.y() : p.z());
|
||||
}
|
||||
|
||||
class SpecularLightingType {
|
||||
class SpecularLightingType : public BaseLightingType {
|
||||
public:
|
||||
SpecularLightingType(SkScalar ks, SkScalar shininess)
|
||||
: fKS(ks), fShininess(shininess) {}
|
||||
SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
|
||||
const SkPoint3& lightColor) const {
|
||||
const SkPoint3& lightColor) const override {
|
||||
SkPoint3 halfDir(surfaceTolight);
|
||||
halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1)
|
||||
fast_normalize(&halfDir);
|
||||
@ -206,15 +277,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <class LightingType, class LightType, class PixelFetcher>
|
||||
static void lightBitmap(const LightingType& lightingType,
|
||||
const SkImageFilterLight* light,
|
||||
template <class PixelFetcher>
|
||||
static void lightBitmap(const BaseLightingType& lightingType,
|
||||
const SkImageFilterLight* l,
|
||||
const SkBitmap& src,
|
||||
SkBitmap* dst,
|
||||
SkScalar surfaceScale,
|
||||
const SkIRect& bounds) {
|
||||
SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height());
|
||||
const LightType* l = static_cast<const LightType*>(light);
|
||||
int left = bounds.left(), right = bounds.right();
|
||||
int bottom = bounds.bottom();
|
||||
int y = bounds.top();
|
||||
@ -298,39 +368,21 @@ static void lightBitmap(const LightingType& lightingType,
|
||||
}
|
||||
}
|
||||
|
||||
template <class LightingType, class LightType>
|
||||
static void lightBitmap(const LightingType& lightingType,
|
||||
static void lightBitmap(const BaseLightingType& lightingType,
|
||||
const SkImageFilterLight* light,
|
||||
const SkBitmap& src,
|
||||
SkBitmap* dst,
|
||||
SkScalar surfaceScale,
|
||||
const SkIRect& bounds) {
|
||||
if (src.bounds().contains(bounds)) {
|
||||
lightBitmap<LightingType, LightType, UncheckedPixelFetcher>(
|
||||
lightBitmap<UncheckedPixelFetcher>(
|
||||
lightingType, light, src, dst, surfaceScale, bounds);
|
||||
} else {
|
||||
lightBitmap<LightingType, LightType, DecalPixelFetcher>(
|
||||
lightBitmap<DecalPixelFetcher>(
|
||||
lightingType, light, src, dst, surfaceScale, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
static SkPoint3 readPoint3(SkReadBuffer& buffer) {
|
||||
SkPoint3 point;
|
||||
point.fX = buffer.readScalar();
|
||||
point.fY = buffer.readScalar();
|
||||
point.fZ = buffer.readScalar();
|
||||
buffer.validate(SkScalarIsFinite(point.fX) &&
|
||||
SkScalarIsFinite(point.fY) &&
|
||||
SkScalarIsFinite(point.fZ));
|
||||
return point;
|
||||
};
|
||||
|
||||
static void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
|
||||
buffer.writeScalar(point.fX);
|
||||
buffer.writeScalar(point.fY);
|
||||
buffer.writeScalar(point.fZ);
|
||||
};
|
||||
|
||||
enum BoundaryMode {
|
||||
kTopLeft_BoundaryMode,
|
||||
kTop_BoundaryMode,
|
||||
@ -751,47 +803,6 @@ class GrGLLight;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SkImageFilterLight : public SkRefCnt {
|
||||
public:
|
||||
enum LightType {
|
||||
kDistant_LightType,
|
||||
kPoint_LightType,
|
||||
kSpot_LightType,
|
||||
};
|
||||
virtual LightType type() const = 0;
|
||||
const SkPoint3& color() const { return fColor; }
|
||||
virtual GrGLLight* createGLLight() const = 0;
|
||||
virtual bool isEqual(const SkImageFilterLight& other) const {
|
||||
return fColor == other.fColor;
|
||||
}
|
||||
virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
|
||||
|
||||
virtual sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer*) const = 0;
|
||||
|
||||
// Defined below SkLight's subclasses.
|
||||
void flattenLight(SkWriteBuffer& buffer) const;
|
||||
static SkImageFilterLight* UnflattenLight(SkReadBuffer& buffer);
|
||||
|
||||
protected:
|
||||
SkImageFilterLight(SkColor color) {
|
||||
fColor = SkPoint3::Make(SkIntToScalar(SkColorGetR(color)),
|
||||
SkIntToScalar(SkColorGetG(color)),
|
||||
SkIntToScalar(SkColorGetB(color)));
|
||||
}
|
||||
SkImageFilterLight(const SkPoint3& color)
|
||||
: fColor(color) {}
|
||||
SkImageFilterLight(SkReadBuffer& buffer) {
|
||||
fColor = readPoint3(buffer);
|
||||
}
|
||||
|
||||
virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
|
||||
|
||||
|
||||
private:
|
||||
typedef SkRefCnt INHERITED;
|
||||
SkPoint3 fColor;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static SkColor xform_color(const SkPoint3& color, SkColorSpaceXformer* xformer) {
|
||||
@ -808,10 +819,10 @@ public:
|
||||
: INHERITED(color), fDirection(direction) {
|
||||
}
|
||||
|
||||
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
|
||||
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
|
||||
return fDirection;
|
||||
}
|
||||
const SkPoint3& lightColor(const SkPoint3&) const { return this->color(); }
|
||||
SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
|
||||
LightType type() const override { return kDistant_LightType; }
|
||||
const SkPoint3& direction() const { return fDirection; }
|
||||
GrGLLight* createGLLight() const override {
|
||||
@ -865,14 +876,14 @@ public:
|
||||
SkPointLight(const SkPoint3& location, SkColor color)
|
||||
: INHERITED(color), fLocation(location) {}
|
||||
|
||||
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
|
||||
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
|
||||
SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
|
||||
fLocation.fY - SkIntToScalar(y),
|
||||
fLocation.fZ - SkIntToScalar(z) * surfaceScale);
|
||||
fast_normalize(&direction);
|
||||
return direction;
|
||||
}
|
||||
const SkPoint3& lightColor(const SkPoint3&) const { return this->color(); }
|
||||
SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
|
||||
LightType type() const override { return kPoint_LightType; }
|
||||
const SkPoint3& location() const { return fLocation; }
|
||||
GrGLLight* createGLLight() const override {
|
||||
@ -979,14 +990,14 @@ public:
|
||||
color());
|
||||
}
|
||||
|
||||
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
|
||||
SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
|
||||
SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
|
||||
fLocation.fY - SkIntToScalar(y),
|
||||
fLocation.fZ - SkIntToScalar(z) * surfaceScale);
|
||||
fast_normalize(&direction);
|
||||
return direction;
|
||||
}
|
||||
SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
|
||||
SkPoint3 lightColor(const SkPoint3& surfaceToLight) const override {
|
||||
SkScalar cosAngle = -surfaceToLight.dot(fS);
|
||||
SkScalar scale = 0;
|
||||
if (cosAngle >= fCosOuterConeAngle) {
|
||||
@ -1316,32 +1327,12 @@ sk_sp<SkSpecialImage> SkDiffuseLightingImageFilter::onFilterImage(SkSpecialImage
|
||||
sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
|
||||
|
||||
DiffuseLightingType lightingType(fKD);
|
||||
switch (transformedLight->type()) {
|
||||
case SkImageFilterLight::kDistant_LightType:
|
||||
lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType,
|
||||
lightBitmap(lightingType,
|
||||
transformedLight.get(),
|
||||
inputBM,
|
||||
&dst,
|
||||
surfaceScale(),
|
||||
bounds);
|
||||
break;
|
||||
case SkImageFilterLight::kPoint_LightType:
|
||||
lightBitmap<DiffuseLightingType, SkPointLight>(lightingType,
|
||||
transformedLight.get(),
|
||||
inputBM,
|
||||
&dst,
|
||||
surfaceScale(),
|
||||
bounds);
|
||||
break;
|
||||
case SkImageFilterLight::kSpot_LightType:
|
||||
lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType,
|
||||
transformedLight.get(),
|
||||
inputBM,
|
||||
&dst,
|
||||
surfaceScale(),
|
||||
bounds);
|
||||
break;
|
||||
}
|
||||
|
||||
return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
|
||||
dst);
|
||||
@ -1490,32 +1481,12 @@ sk_sp<SkSpecialImage> SkSpecularLightingImageFilter::onFilterImage(SkSpecialImag
|
||||
|
||||
sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
|
||||
|
||||
switch (transformedLight->type()) {
|
||||
case SkImageFilterLight::kDistant_LightType:
|
||||
lightBitmap<SpecularLightingType, SkDistantLight>(lightingType,
|
||||
lightBitmap(lightingType,
|
||||
transformedLight.get(),
|
||||
inputBM,
|
||||
&dst,
|
||||
surfaceScale(),
|
||||
bounds);
|
||||
break;
|
||||
case SkImageFilterLight::kPoint_LightType:
|
||||
lightBitmap<SpecularLightingType, SkPointLight>(lightingType,
|
||||
transformedLight.get(),
|
||||
inputBM,
|
||||
&dst,
|
||||
surfaceScale(),
|
||||
bounds);
|
||||
break;
|
||||
case SkImageFilterLight::kSpot_LightType:
|
||||
lightBitmap<SpecularLightingType, SkSpotLight>(lightingType,
|
||||
transformedLight.get(),
|
||||
inputBM,
|
||||
&dst,
|
||||
surfaceScale(),
|
||||
bounds);
|
||||
break;
|
||||
}
|
||||
|
||||
return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()), dst);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user