Diff
Modified: trunk/Source/WebCore/ChangeLog (225121 => 225122)
--- trunk/Source/WebCore/ChangeLog 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/ChangeLog 2017-11-23 22:20:09 UTC (rev 225122)
@@ -1,5 +1,65 @@
2017-11-23 Simon Fraser <simon.fra...@apple.com>
+ FELighting cleanup and optimization
+ https://bugs.webkit.org/show_bug.cgi?id=179933
+
+ Reviewed by Darin Adler.
+
+ Make FELighting about 25% faster by maintaining an "alpha" window of the alpha
+ values of the 9 pixels surrounding the current pixel, and sliding this window over
+ when moving to the next pixel. This avoids reading the same alpha values from the original
+ buffer multiple times.
+
+ Clean up LightSource and subclasses, adding SPECIALIZE_TYPE_TRAITS macros,
+ and turning updatePaintingData() into a function with no side effects that returns
+ the required data.
+
+ Remove explicit 'inline' keywords, allowing the compiler to make inlining decisions.
+
+ * platform/graphics/cpu/arm/filters/FELightingNEON.h:
+ (WebCore::FELighting::platformApplyNeon):
+ * platform/graphics/filters/DistantLightSource.cpp:
+ (WebCore::DistantLightSource::initPaintingData):
+ (WebCore::DistantLightSource::computePixelLightingData const):
+ (WebCore::DistantLightSource::updatePaintingData): Deleted.
+ * platform/graphics/filters/DistantLightSource.h:
+ * platform/graphics/filters/FELighting.cpp:
+ (WebCore::FELighting::LightingData::interiorNormal const):
+ (WebCore::FELighting::setPixel):
+ (WebCore::FELighting::setPixelInternal):
+ (WebCore::FELighting::platformApplyGenericPaint):
+ (WebCore::FELighting::platformApplyGeneric):
+ (WebCore::FELighting::platformApply):
+ (WebCore::FELighting::drawLighting):
+ (WebCore::FELighting::inlineSetPixel): Deleted.
+ * platform/graphics/filters/FELighting.h:
+ (WebCore::FELighting::AlphaWindow::topLeft const):
+ (WebCore::FELighting::AlphaWindow::left const):
+ (WebCore::FELighting::AlphaWindow::bottomLeft const):
+ (WebCore::FELighting::AlphaWindow::top const):
+ (WebCore::FELighting::AlphaWindow::center const):
+ (WebCore::FELighting::AlphaWindow::bottom const):
+ (WebCore::FELighting::AlphaWindow::setTop):
+ (WebCore::FELighting::AlphaWindow::setCenter):
+ (WebCore::FELighting::AlphaWindow::setBottom):
+ (WebCore::FELighting::AlphaWindow::setTopRight):
+ (WebCore::FELighting::AlphaWindow::setRight):
+ (WebCore::FELighting::AlphaWindow::setBottomRight):
+ (WebCore::FELighting::AlphaWindow::shiftRow):
+ (WebCore::FELighting::AlphaWindow::shift):
+ * platform/graphics/filters/LightSource.h:
+ * platform/graphics/filters/PointLightSource.cpp:
+ (WebCore::PointLightSource::computePixelLightingData const):
+ (WebCore::PointLightSource::updatePaintingData): Deleted.
+ * platform/graphics/filters/PointLightSource.h:
+ * platform/graphics/filters/SpotLightSource.cpp:
+ (WebCore::SpotLightSource::initPaintingData):
+ (WebCore::SpotLightSource::computePixelLightingData const):
+ (WebCore::SpotLightSource::updatePaintingData): Deleted.
+ * platform/graphics/filters/SpotLightSource.h:
+
+2017-11-23 Simon Fraser <simon.fra...@apple.com>
+
Add support for CanvasPattern.setTransform()
https://bugs.webkit.org/show_bug.cgi?id=179935
Modified: trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.h (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.h 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/cpu/arm/filters/FELightingNEON.h 2017-11-23 22:20:09 UTC (rev 225122)
@@ -93,7 +93,7 @@
void neonDrawLighting(FELightingPaintingDataForNeon*);
}
-inline void FELighting::platformApplyNeon(LightingData& data, LightSource::PaintingData& paintingData)
+inline void FELighting::platformApplyNeon(const LightingData& data, const LightSource::PaintingData& paintingData)
{
FELightingFloatArgumentsForNeon floatArguments __attribute__((__aligned__(16)));
FELightingPaintingDataForNeon neonData = {
Modified: trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.cpp 2017-11-23 22:20:09 UTC (rev 225122)
@@ -39,14 +39,17 @@
{
float azimuth = deg2rad(m_azimuth);
float elevation = deg2rad(m_elevation);
- paintingData.lightVector.setX(cosf(azimuth) * cosf(elevation));
- paintingData.lightVector.setY(sinf(azimuth) * cosf(elevation));
- paintingData.lightVector.setZ(sinf(elevation));
- paintingData.lightVectorLength = 1;
+ paintingData.intialLightingData.lightVector = {
+ std::cos(azimuth) * std::cos(elevation),
+ std::sin(azimuth) * std::cos(elevation),
+ std::sin(elevation)
+ };
+ paintingData.intialLightingData.lightVectorLength = 1;
}
-void DistantLightSource::updatePaintingData(PaintingData&, int, int, float)
+LightSource::ComputedLightingData DistantLightSource::computePixelLightingData(const PaintingData& paintingData, int, int, float) const
{
+ return paintingData.intialLightingData;
}
bool DistantLightSource::setAzimuth(float azimuth)
Modified: trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.h (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.h 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/DistantLightSource.h 2017-11-23 22:20:09 UTC (rev 225122)
@@ -20,8 +20,7 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef DistantLightSource_h
-#define DistantLightSource_h
+#pragma once
#include "LightSource.h"
#include <wtf/Ref.h>
@@ -35,6 +34,7 @@
return adoptRef(*new DistantLightSource(azimuth, elevation));
}
+ // These are in degrees.
float azimuth() const { return m_azimuth; }
float elevation() const { return m_elevation; }
@@ -42,7 +42,7 @@
bool setElevation(float) override;
void initPaintingData(PaintingData&) override;
- void updatePaintingData(PaintingData&, int x, int y, float z) override;
+ ComputedLightingData computePixelLightingData(const PaintingData&, int x, int y, float z) const final;
WTF::TextStream& externalRepresentation(WTF::TextStream&) const override;
@@ -60,4 +60,4 @@
} // namespace WebCore
-#endif // DistantLightSource_h
+SPECIALIZE_TYPE_TRAITS_LIGHTSOURCE(DistantLightSource, LS_DISTANT)
Modified: trunk/Source/WebCore/platform/graphics/filters/FELighting.cpp (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/filters/FELighting.cpp 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/FELighting.cpp 2017-11-23 22:20:09 UTC (rev 225122)
@@ -84,7 +84,7 @@
const static int cPixelSize = 4;
const static int cAlphaChannelOffset = 3;
-const static unsigned char cOpaqueAlpha = static_cast<unsigned char>(0xff);
+const static uint8_t cOpaqueAlpha = static_cast<uint8_t>(0xFF);
// These factors and the normal coefficients come from the table under https://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement.
const static float cFactor1div2 = -1 / 2.f;
@@ -149,18 +149,30 @@
};
}
-inline IntSize FELighting::LightingData::interiorNormal(int offset) const
+inline IntSize FELighting::LightingData::interiorNormal(int offset, AlphaWindow& alphaWindow) const
{
- int left = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
- int right = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
- offset -= widthMultipliedByPixelSize;
- int topLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
- int top = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
- int topRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
- offset += 2 * widthMultipliedByPixelSize;
- int bottomLeft = static_cast<int>(pixels->item(offset - cPixelSize + cAlphaChannelOffset));
- int bottom = static_cast<int>(pixels->item(offset + cAlphaChannelOffset));
- int bottomRight = static_cast<int>(pixels->item(offset + cPixelSize + cAlphaChannelOffset));
+ int rightAlphaOffset = offset + cPixelSize + cAlphaChannelOffset;
+
+ int right = static_cast<int>(pixels->item(rightAlphaOffset));
+ int topRight = static_cast<int>(pixels->item(rightAlphaOffset - widthMultipliedByPixelSize));
+ int bottomRight = static_cast<int>(pixels->item(rightAlphaOffset + widthMultipliedByPixelSize));
+
+ int left = alphaWindow.left();
+ int topLeft = alphaWindow.topLeft();
+ int top = alphaWindow.top();
+
+ int bottomLeft = alphaWindow.bottomLeft();
+ int bottom = alphaWindow.bottom();
+
+ // The alphaWindow has been shifted, and here we fill in the right column.
+ alphaWindow.alpha[0][2] = topRight;
+ alphaWindow.alpha[1][2] = right;
+ alphaWindow.alpha[2][2] = bottomRight;
+
+ // Check that the alphaWindow is working with some spot-checks.
+ ASSERT(alphaWindow.topLeft() == pixels->item(offset - cPixelSize - widthMultipliedByPixelSize + cAlphaChannelOffset)); // topLeft
+ ASSERT(alphaWindow.top() == pixels->item(offset - widthMultipliedByPixelSize + cAlphaChannelOffset)); // top
+
return {
-topLeft + topRight - 2 * left + 2 * right - bottomLeft + bottomRight,
-topLeft - 2 * top - topRight + bottomLeft + 2 * bottom + bottomRight
@@ -224,18 +236,27 @@
};
}
-inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, int lightX, int lightY, float factorX, float factorY, IntSize normal2DVector)
+void FELighting::setPixel(int offset, const LightingData& data, const LightSource::PaintingData& paintingData, int x, int y, float factorX, float factorY, IntSize normal2DVector)
{
- m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->item(offset + cAlphaChannelOffset)) * data.surfaceScale);
+ setPixelInternal(offset, data, paintingData, x, y, factorX, factorY, normal2DVector, data.pixels->item(offset + cAlphaChannelOffset));
+}
+void FELighting::setPixelInternal(int offset, const LightingData& data, const LightSource::PaintingData& paintingData, int x, int y, float factorX, float factorY, IntSize normal2DVector, float alpha)
+{
+ float z = alpha * data.surfaceScale;
+ LightSource::ComputedLightingData lightingData = m_lightSource->computePixelLightingData(paintingData, x, y, z);
+
float lightStrength;
if (normal2DVector.isZero()) {
// Normal vector is (0, 0, 1). This is a quite frequent case.
if (m_lightingType == FELighting::DiffuseLighting)
- lightStrength = m_diffuseConstant * paintingData.lightVector.z() / paintingData.lightVectorLength;
+ lightStrength = m_diffuseConstant * lightingData.lightVector.z() / lightingData.lightVectorLength;
else {
- FloatPoint3D halfwayVector = paintingData.lightVector;
- halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
+ FloatPoint3D halfwayVector = {
+ lightingData.lightVector.x(),
+ lightingData.lightVector.y(),
+ lightingData.lightVector.z() + lightingData.lightVectorLength
+ };
float halfwayVectorLength = halfwayVector.length();
if (m_specularExponent == 1)
lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength;
@@ -243,17 +264,21 @@
lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent);
}
} else {
- FloatPoint3D normalVector;
- normalVector.setX(factorX * static_cast<float>(normal2DVector.width()) * data.surfaceScale);
- normalVector.setY(factorY * static_cast<float>(normal2DVector.height()) * data.surfaceScale);
- normalVector.setZ(1);
+ FloatPoint3D normalVector = {
+ factorX * normal2DVector.width() * data.surfaceScale,
+ factorY * normal2DVector.height() * data.surfaceScale,
+ 1.0f
+ };
float normalVectorLength = normalVector.length();
if (m_lightingType == FELighting::DiffuseLighting)
- lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength);
+ lightStrength = m_diffuseConstant * (normalVector * lightingData.lightVector) / (normalVectorLength * lightingData.lightVectorLength);
else {
- FloatPoint3D halfwayVector = paintingData.lightVector;
- halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength);
+ FloatPoint3D halfwayVector = {
+ lightingData.lightVector.x(),
+ lightingData.lightVector.y(),
+ lightingData.lightVector.z() + lightingData.lightVectorLength
+ };
float halfwayVectorLength = halfwayVector.length();
if (m_specularExponent == 1)
lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength);
@@ -267,22 +292,43 @@
if (lightStrength < 0)
lightStrength = 0;
- data.pixels->set(offset, static_cast<unsigned char>(lightStrength * paintingData.colorVector.x()));
- data.pixels->set(offset + 1, static_cast<unsigned char>(lightStrength * paintingData.colorVector.y()));
- data.pixels->set(offset + 2, static_cast<unsigned char>(lightStrength * paintingData.colorVector.z()));
+ uint8_t pixelValue[3] = {
+ static_cast<uint8_t>(lightStrength * lightingData.colorVector.x()),
+ static_cast<uint8_t>(lightStrength * lightingData.colorVector.y()),
+ static_cast<uint8_t>(lightStrength * lightingData.colorVector.z())
+ };
+
+ data.pixels->setRange(pixelValue, 3, offset);
}
-void FELighting::setPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, int lightX, int lightY, float factorX, float factorY, IntSize normalVector)
+// This appears to read from and write to the same pixel buffer, but it only reads the alpha channel, and writes the non-alpha channels.
+void FELighting::platformApplyGenericPaint(const LightingData& data, const LightSource::PaintingData& paintingData, int startY, int endY)
{
- inlineSetPixel(offset, data, paintingData, lightX, lightY, factorX, factorY, normalVector);
-}
+ // Make sure startY is > 0 since we read from the previous row in the loop.
+ ASSERT(startY);
-inline void FELighting::platformApplyGenericPaint(LightingData& data, LightSource::PaintingData& paintingData, int startY, int endY)
-{
for (int y = startY; y < endY; ++y) {
- int offset = y * data.widthMultipliedByPixelSize + cPixelSize;
+ int rowStartOffset = y * data.widthMultipliedByPixelSize;
+ int previousRowStart = rowStartOffset - data.widthMultipliedByPixelSize;
+ int nextRowStart = rowStartOffset + data.widthMultipliedByPixelSize;
+
+ // alphaWindow is a local cache of alpha values.
+ // Fill the two right columns putting the left edge value in the center column.
+ // For each pixel, we shift each row left then fill the right column.
+ AlphaWindow alphaWindow;
+ alphaWindow.setTop(data.pixels->item(previousRowStart + cAlphaChannelOffset));
+ alphaWindow.setTopRight(data.pixels->item(previousRowStart + cPixelSize + cAlphaChannelOffset));
+
+ alphaWindow.setCenter(data.pixels->item(rowStartOffset + cAlphaChannelOffset));
+ alphaWindow.setRight(data.pixels->item(rowStartOffset + cPixelSize + cAlphaChannelOffset));
+
+ alphaWindow.setBottom(data.pixels->item(nextRowStart + cAlphaChannelOffset));
+ alphaWindow.setBottomRight(data.pixels->item(nextRowStart + cPixelSize + cAlphaChannelOffset));
+
+ int offset = rowStartOffset + cPixelSize;
for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) {
- inlineSetPixel(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, data.interiorNormal(offset));
+ alphaWindow.shift();
+ setPixelInternal(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, data.interiorNormal(offset, alphaWindow), alphaWindow.center());
}
}
}
@@ -292,7 +338,7 @@
parameters->filter->platformApplyGenericPaint(parameters->data, parameters->paintingData, parameters->yStart, parameters->yEnd);
}
-inline void FELighting::platformApplyGeneric(LightingData& data, LightSource::PaintingData& paintingData)
+void FELighting::platformApplyGeneric(const LightingData& data, const LightSource::PaintingData& paintingData)
{
int optimalThreadNumber = ((data.widthDecreasedByOne - 1) * (data.heightDecreasedByOne - 1)) / s_minimalRectDimension;
if (optimalThreadNumber > 1) {
@@ -326,7 +372,7 @@
platformApplyGenericPaint(data, paintingData, 1, data.heightDecreasedByOne);
}
-inline void FELighting::platformApply(LightingData& data, LightSource::PaintingData& paintingData)
+inline void FELighting::platformApply(const LightingData& data, const LightSource::PaintingData& paintingData)
{
// The selection here eventually should happen dynamically on some platforms.
#if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC_OR_CLANG)
@@ -351,7 +397,7 @@
data.widthMultipliedByPixelSize = width * cPixelSize;
data.widthDecreasedByOne = width - 1;
data.heightDecreasedByOne = height - 1;
- paintingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue());
+ paintingData.intialLightingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue());
m_lightSource->initPaintingData(paintingData);
// Top left.
@@ -374,12 +420,12 @@
// Top row.
offset = cPixelSize;
for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize)
- inlineSetPixel(offset, data, paintingData, x, 0, cFactor1div3, cFactor1div2, data.topRowNormal(offset));
+ setPixel(offset, data, paintingData, x, 0, cFactor1div3, cFactor1div2, data.topRowNormal(offset));
// Bottom row.
offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize;
for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize)
- inlineSetPixel(offset, data, paintingData, x, data.heightDecreasedByOne, cFactor1div3, cFactor1div2, data.bottomRowNormal(offset));
+ setPixel(offset, data, paintingData, x, data.heightDecreasedByOne, cFactor1div3, cFactor1div2, data.bottomRowNormal(offset));
}
if (height >= 3) {
@@ -386,12 +432,12 @@
// Left column.
offset = data.widthMultipliedByPixelSize;
for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize)
- inlineSetPixel(offset, data, paintingData, 0, y, cFactor1div2, cFactor1div3, data.leftColumnNormal(offset));
+ setPixel(offset, data, paintingData, 0, y, cFactor1div2, cFactor1div3, data.leftColumnNormal(offset));
// Right column.
offset = 2 * data.widthMultipliedByPixelSize - cPixelSize;
for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize)
- inlineSetPixel(offset, data, paintingData, data.widthDecreasedByOne, y, cFactor1div2, cFactor1div3, data.rightColumnNormal(offset));
+ setPixel(offset, data, paintingData, data.widthDecreasedByOne, y, cFactor1div2, cFactor1div3, data.rightColumnNormal(offset));
}
if (width >= 3 && height >= 3) {
@@ -405,9 +451,9 @@
data.pixels->set(i, cOpaqueAlpha);
} else {
for (int i = 0; i < lastPixel; i += cPixelSize) {
- unsigned char a1 = data.pixels->item(i);
- unsigned char a2 = data.pixels->item(i + 1);
- unsigned char a3 = data.pixels->item(i + 2);
+ uint8_t a1 = data.pixels->item(i);
+ uint8_t a2 = data.pixels->item(i + 1);
+ uint8_t a3 = data.pixels->item(i + 2);
// alpha set to set to max(a1, a2, a3)
data.pixels->set(i + 3, a1 >= a2 ? (a1 >= a3 ? a1 : a3) : (a2 >= a3 ? a2 : a3));
}
Modified: trunk/Source/WebCore/platform/graphics/filters/FELighting.h (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/filters/FELighting.h 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/FELighting.h 2017-11-23 22:20:09 UTC (rev 225122)
@@ -63,7 +63,41 @@
DiffuseLighting,
SpecularLighting
};
+
+ struct AlphaWindow {
+ uint8_t alpha[3][3] { };
+
+ // The implementations are lined up to make comparing indices easier.
+ uint8_t topLeft() const { return alpha[0][0]; }
+ uint8_t left() const { return alpha[1][0]; }
+ uint8_t bottomLeft() const { return alpha[2][0]; }
+ uint8_t top() const { return alpha[0][1]; }
+ uint8_t center() const { return alpha[1][1]; }
+ uint8_t bottom() const { return alpha[2][1]; }
+
+ void setTop(uint8_t value) { alpha[0][1] = value; }
+ void setCenter(uint8_t value) { alpha[1][1] = value; }
+ void setBottom(uint8_t value) { alpha[2][1] = value; }
+
+ void setTopRight(uint8_t value) { alpha[0][2] = value; }
+ void setRight(uint8_t value) { alpha[1][2] = value; }
+ void setBottomRight(uint8_t value) { alpha[2][2] = value; }
+
+ static void shiftRow(uint8_t alpha[3])
+ {
+ alpha[0] = alpha[1];
+ alpha[1] = alpha[2];
+ }
+
+ void shift()
+ {
+ shiftRow(alpha[0]);
+ shiftRow(alpha[1]);
+ shiftRow(alpha[2]);
+ }
+ };
+
struct LightingData {
// This structure contains only read-only (SMP safe) data
Uint8ClampedArray* pixels;
@@ -76,7 +110,7 @@
inline IntSize topRowNormal(int offset) const;
inline IntSize topRightNormal(int offset) const;
inline IntSize leftColumnNormal(int offset) const;
- inline IntSize interiorNormal(int offset) const;
+ inline IntSize interiorNormal(int offset, AlphaWindow&) const;
inline IntSize rightColumnNormal(int offset) const;
inline IntSize bottomLeftNormal(int offset) const;
inline IntSize bottomRowNormal(int offset) const;
@@ -100,23 +134,20 @@
FELighting(Filter&, LightingType, const Color&, float, float, float, float, float, float, Ref<LightSource>&&);
bool drawLighting(Uint8ClampedArray*, int, int);
- inline void inlineSetPixel(int offset, LightingData&, LightSource::PaintingData&,
- int lightX, int lightY, float factorX, float factorY, IntSize normalVector);
- // Not worth to inline every occurence of setPixel.
- void setPixel(int offset, LightingData&, LightSource::PaintingData&,
- int lightX, int lightY, float factorX, float factorY, IntSize normalVector);
+ void setPixel(int offset, const LightingData&, const LightSource::PaintingData&, int x, int y, float factorX, float factorY, IntSize normalVector);
+ void setPixelInternal(int offset, const LightingData&, const LightSource::PaintingData&, int x, int y, float factorX, float factorY, IntSize normalVector, float alpha);
void platformApplySoftware() override;
- inline void platformApply(LightingData&, LightSource::PaintingData&);
+ void platformApply(const LightingData&, const LightSource::PaintingData&);
- inline void platformApplyGenericPaint(LightingData&, LightSource::PaintingData&, int startX, int startY);
- inline void platformApplyGeneric(LightingData&, LightSource::PaintingData&);
+ void platformApplyGenericPaint(const LightingData&, const LightSource::PaintingData&, int startX, int startY);
+ void platformApplyGeneric(const LightingData&, const LightSource::PaintingData&);
#if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC_OR_CLANG)
static int getPowerCoefficients(float exponent);
- inline void platformApplyNeon(LightingData&, LightSource::PaintingData&);
+ inline void platformApplyNeon(const LightingData&, const LightSource::PaintingData&);
#endif
LightingType m_lightingType;
Modified: trunk/Source/WebCore/platform/graphics/filters/LightSource.h (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/filters/LightSource.h 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/LightSource.h 2017-11-23 22:20:09 UTC (rev 225122)
@@ -21,8 +21,7 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef LightSource_h
-#define LightSource_h
+#pragma once
#include "FloatPoint3D.h"
#include <wtf/RefCounted.h>
@@ -41,20 +40,15 @@
class LightSource : public RefCounted<LightSource> {
public:
-
- // Light vectors must be calculated for every pixel during
- // painting. It is expensive to pass all these arguments to
- // a frequently called function, especially because not all
- // light sources require all of them. Instead, we just pass
- // a reference to the following structure
- struct PaintingData {
- // SVGFELighting also use them
+ struct ComputedLightingData {
FloatPoint3D lightVector;
FloatPoint3D colorVector;
float lightVectorLength;
- // Private members
+ };
+
+ struct PaintingData {
+ ComputedLightingData intialLightingData;
FloatPoint3D directionVector;
- FloatPoint3D privateColorVector;
float coneCutOffLimit;
float coneFullLight;
int specularExponent;
@@ -72,7 +66,7 @@
virtual void initPaintingData(PaintingData&) = 0;
// z is a float number, since it is the alpha value scaled by a user
// specified "surfaceScale" constant, which type is <number> in the SVG standard
- virtual void updatePaintingData(PaintingData&, int x, int y, float z) = 0;
+ virtual ComputedLightingData computePixelLightingData(const PaintingData&, int x, int y, float z) const = 0;
virtual bool setAzimuth(float) { return false; }
virtual bool setElevation(float) { return false; }
@@ -91,4 +85,7 @@
} // namespace WebCore
-#endif // LightSource_h
+#define SPECIALIZE_TYPE_TRAITS_LIGHTSOURCE(ClassName, Type) \
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ClassName) \
+ static bool isType(const WebCore::LightSource& source) { return source.type() == WebCore::Type; } \
+SPECIALIZE_TYPE_TRAITS_END()
Modified: trunk/Source/WebCore/platform/graphics/filters/PointLightSource.cpp (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/filters/PointLightSource.cpp 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/PointLightSource.cpp 2017-11-23 22:20:09 UTC (rev 225122)
@@ -39,12 +39,15 @@
{
}
-void PointLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+LightSource::ComputedLightingData PointLightSource::computePixelLightingData(const PaintingData&, int x, int y, float z) const
{
- paintingData.lightVector.setX(m_position.x() - x);
- paintingData.lightVector.setY(m_position.y() - y);
- paintingData.lightVector.setZ(m_position.z() - z);
- paintingData.lightVectorLength = paintingData.lightVector.length();
+ FloatPoint3D lightVector = {
+ m_position.x() - x,
+ m_position.y() - y,
+ m_position.z() - z
+ };
+
+ return { lightVector, { }, lightVector.length() };
}
bool PointLightSource::setX(float x)
Modified: trunk/Source/WebCore/platform/graphics/filters/PointLightSource.h (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/filters/PointLightSource.h 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/PointLightSource.h 2017-11-23 22:20:09 UTC (rev 225122)
@@ -20,8 +20,7 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef PointLightSource_h
-#define PointLightSource_h
+#pragma once
#include "LightSource.h"
#include <wtf/Ref.h>
@@ -41,7 +40,7 @@
bool setZ(float) override;
void initPaintingData(PaintingData&) override;
- void updatePaintingData(PaintingData&, int x, int y, float z) override;
+ ComputedLightingData computePixelLightingData(const PaintingData&, int x, int y, float z) const final;
WTF::TextStream& externalRepresentation(WTF::TextStream&) const override;
@@ -57,4 +56,4 @@
} // namespace WebCore
-#endif // PointLightSource_h
+SPECIALIZE_TYPE_TRAITS_LIGHTSOURCE(PointLightSource, LS_POINT)
Modified: trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.cpp 2017-11-23 22:20:09 UTC (rev 225122)
@@ -42,10 +42,7 @@
void SpotLightSource::initPaintingData(PaintingData& paintingData)
{
- paintingData.privateColorVector = paintingData.colorVector;
- paintingData.directionVector.setX(m_direction.x() - m_position.x());
- paintingData.directionVector.setY(m_direction.y() - m_position.y());
- paintingData.directionVector.setZ(m_direction.z() - m_position.z());
+ paintingData.directionVector = m_direction - m_position;
paintingData.directionVector.normalize();
if (!m_limitingConeAngle) {
@@ -70,20 +67,19 @@
paintingData.specularExponent = 2;
}
-void SpotLightSource::updatePaintingData(PaintingData& paintingData, int x, int y, float z)
+LightSource::ComputedLightingData SpotLightSource::computePixelLightingData(const PaintingData& paintingData, int x, int y, float z) const
{
- paintingData.lightVector.setX(m_position.x() - x);
- paintingData.lightVector.setY(m_position.y() - y);
- paintingData.lightVector.setZ(m_position.z() - z);
- paintingData.lightVectorLength = paintingData.lightVector.length();
+ FloatPoint3D lightVector = {
+ m_position.x() - x,
+ m_position.y() - y,
+ m_position.z() - z
+ };
+ float lightVectorLength = lightVector.length();
- float cosineOfAngle = (paintingData.lightVector * paintingData.directionVector) / paintingData.lightVectorLength;
+ float cosineOfAngle = (lightVector * paintingData.directionVector) / lightVectorLength;
if (cosineOfAngle > paintingData.coneCutOffLimit) {
// No light is produced, scanlines are not updated
- paintingData.colorVector.setX(0.0f);
- paintingData.colorVector.setY(0.0f);
- paintingData.colorVector.setZ(0.0f);
- return;
+ return { lightVector, { }, lightVectorLength };
}
// Set the color of the pixel
@@ -106,9 +102,11 @@
if (lightStrength > 1.0f)
lightStrength = 1.0f;
- paintingData.colorVector.setX(paintingData.privateColorVector.x() * lightStrength);
- paintingData.colorVector.setY(paintingData.privateColorVector.y() * lightStrength);
- paintingData.colorVector.setZ(paintingData.privateColorVector.z() * lightStrength);
+ return {
+ lightVector,
+ paintingData.intialLightingData.colorVector * lightStrength,
+ lightVectorLength
+ };
}
bool SpotLightSource::setX(float x)
Modified: trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.h (225121 => 225122)
--- trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.h 2017-11-23 21:33:44 UTC (rev 225121)
+++ trunk/Source/WebCore/platform/graphics/filters/SpotLightSource.h 2017-11-23 22:20:09 UTC (rev 225122)
@@ -20,8 +20,7 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef SpotLightSource_h
-#define SpotLightSource_h
+#pragma once
#include "LightSource.h"
#include <wtf/Ref.h>
@@ -52,7 +51,7 @@
bool setLimitingConeAngle(float) override;
void initPaintingData(PaintingData&) override;
- void updatePaintingData(PaintingData&, int x, int y, float z) override;
+ ComputedLightingData computePixelLightingData(const PaintingData&, int x, int y, float z) const final;
WTF::TextStream& externalRepresentation(WTF::TextStream&) const override;
@@ -76,4 +75,4 @@
} // namespace WebCore
-#endif // SpotLightSource_h
+SPECIALIZE_TYPE_TRAITS_LIGHTSOURCE(SpotLightSource, LS_SPOT)