1 /* 2 * Copyright (C) 2010 University of Szeged 3 * Copyright (C) 2010 Zoltan Herczeg 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 29 #if ENABLE(FILTERS) 30 #include "FELighting.h" 31 32 #include "LightSource.h" 33 #include "PointLightSource.h" 34 #include "SpotLightSource.h" 35 36 #if CPU(ARM_NEON) && COMPILER(GCC) 37 #include "FELightingNEON.h" 38 #include <wtf/Vector.h> 39 #endif 40 41 namespace WebCore { 42 43 FELighting::FELighting(Filter* filter, LightingType lightingType, const Color& lightingColor, float surfaceScale, 44 float diffuseConstant, float specularConstant, float specularExponent, 45 float kernelUnitLengthX, float kernelUnitLengthY, PassRefPtr<LightSource> lightSource) 46 : FilterEffect(filter) 47 , m_lightingType(lightingType) 48 , m_lightSource(lightSource) 49 , m_lightingColor(lightingColor) 50 , m_surfaceScale(surfaceScale) 51 , m_diffuseConstant(diffuseConstant) 52 , m_specularConstant(specularConstant) 53 , m_specularExponent(specularExponent) 54 , m_kernelUnitLengthX(kernelUnitLengthX) 55 , m_kernelUnitLengthY(kernelUnitLengthY) 56 { 57 } 58 59 const static int cPixelSize = 4; 60 const static int cAlphaChannelOffset = 3; 61 const static unsigned char cOpaqueAlpha = static_cast<unsigned char>(0xff); 62 const static float cFactor1div2 = -1 / 2.f; 63 const static float cFactor1div3 = -1 / 3.f; 64 const static float cFactor1div4 = -1 / 4.f; 65 const static float cFactor2div3 = -2 / 3.f; 66 67 // << 1 is signed multiply by 2 68 inline void FELighting::LightingData::topLeft(int offset, IntPoint& normalVector) 69 { 70 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 71 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 72 offset += widthMultipliedByPixelSize; 73 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 74 int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 75 normalVector.setX(-(center << 1) + (right << 1) - bottom + bottomRight); 76 normalVector.setY(-(center << 1) - right + (bottom << 1) + bottomRight); 77 } 78 79 inline void FELighting::LightingData::topRow(int offset, IntPoint& normalVector) 80 { 81 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 82 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 83 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 84 offset += widthMultipliedByPixelSize; 85 int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 86 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 87 int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 88 normalVector.setX(-(left << 1) + (right << 1) - bottomLeft + bottomRight); 89 normalVector.setY(-left - (center << 1) - right + bottomLeft + (bottom << 1) + bottomRight); 90 } 91 92 inline void FELighting::LightingData::topRight(int offset, IntPoint& normalVector) 93 { 94 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 95 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 96 offset += widthMultipliedByPixelSize; 97 int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 98 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 99 normalVector.setX(-(left << 1) + (center << 1) - bottomLeft + bottom); 100 normalVector.setY(-left - (center << 1) + bottomLeft + (bottom << 1)); 101 } 102 103 inline void FELighting::LightingData::leftColumn(int offset, IntPoint& normalVector) 104 { 105 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 106 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 107 offset -= widthMultipliedByPixelSize; 108 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 109 int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 110 offset += widthMultipliedByPixelSize << 1; 111 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 112 int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 113 normalVector.setX(-top + topRight - (center << 1) + (right << 1) - bottom + bottomRight); 114 normalVector.setY(-(top << 1) - topRight + (bottom << 1) + bottomRight); 115 } 116 117 inline void FELighting::LightingData::interior(int offset, IntPoint& normalVector) 118 { 119 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 120 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 121 offset -= widthMultipliedByPixelSize; 122 int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 123 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 124 int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 125 offset += widthMultipliedByPixelSize << 1; 126 int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 127 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 128 int bottomRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 129 normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1) - bottomLeft + bottomRight); 130 normalVector.setY(-topLeft - (top << 1) - topRight + bottomLeft + (bottom << 1) + bottomRight); 131 } 132 133 inline void FELighting::LightingData::rightColumn(int offset, IntPoint& normalVector) 134 { 135 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 136 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 137 offset -= widthMultipliedByPixelSize; 138 int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 139 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 140 offset += widthMultipliedByPixelSize << 1; 141 int bottomLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 142 int bottom = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 143 normalVector.setX(-topLeft + top - (left << 1) + (center << 1) - bottomLeft + bottom); 144 normalVector.setY(-topLeft - (top << 1) + bottomLeft + (bottom << 1)); 145 } 146 147 inline void FELighting::LightingData::bottomLeft(int offset, IntPoint& normalVector) 148 { 149 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 150 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 151 offset -= widthMultipliedByPixelSize; 152 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 153 int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 154 normalVector.setX(-top + topRight - (center << 1) + (right << 1)); 155 normalVector.setY(-(top << 1) - topRight + (center << 1) + right); 156 } 157 158 inline void FELighting::LightingData::bottomRow(int offset, IntPoint& normalVector) 159 { 160 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 161 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 162 int right = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 163 offset -= widthMultipliedByPixelSize; 164 int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 165 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 166 int topRight = static_cast<int>(pixels->get(offset + cPixelSize + cAlphaChannelOffset)); 167 normalVector.setX(-topLeft + topRight - (left << 1) + (right << 1)); 168 normalVector.setY(-topLeft - (top << 1) - topRight + left + (center << 1) + right); 169 } 170 171 inline void FELighting::LightingData::bottomRight(int offset, IntPoint& normalVector) 172 { 173 int left = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 174 int center = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 175 offset -= widthMultipliedByPixelSize; 176 int topLeft = static_cast<int>(pixels->get(offset - cPixelSize + cAlphaChannelOffset)); 177 int top = static_cast<int>(pixels->get(offset + cAlphaChannelOffset)); 178 normalVector.setX(-topLeft + top - (left << 1) + (center << 1)); 179 normalVector.setY(-topLeft - (top << 1) + left + (center << 1)); 180 } 181 182 inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, 183 int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector) 184 { 185 m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->get(offset + cAlphaChannelOffset)) * data.surfaceScale); 186 187 float lightStrength; 188 if (!normal2DVector.x() && !normal2DVector.y()) { 189 // Normal vector is (0, 0, 1). This is a quite frequent case. 190 if (m_lightingType == FELighting::DiffuseLighting) 191 lightStrength = m_diffuseConstant * paintingData.lightVector.z() / paintingData.lightVectorLength; 192 else { 193 FloatPoint3D halfwayVector = paintingData.lightVector; 194 halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); 195 float halfwayVectorLength = halfwayVector.length(); 196 if (m_specularExponent == 1) 197 lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength; 198 else 199 lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent); 200 } 201 } else { 202 FloatPoint3D normalVector; 203 normalVector.setX(factorX * static_cast<float>(normal2DVector.x()) * data.surfaceScale); 204 normalVector.setY(factorY * static_cast<float>(normal2DVector.y()) * data.surfaceScale); 205 normalVector.setZ(1); 206 float normalVectorLength = normalVector.length(); 207 208 if (m_lightingType == FELighting::DiffuseLighting) 209 lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength); 210 else { 211 FloatPoint3D halfwayVector = paintingData.lightVector; 212 halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); 213 float halfwayVectorLength = halfwayVector.length(); 214 if (m_specularExponent == 1) 215 lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength); 216 else 217 lightStrength = m_specularConstant * powf((normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength), m_specularExponent); 218 } 219 } 220 221 if (lightStrength > 1) 222 lightStrength = 1; 223 if (lightStrength < 0) 224 lightStrength = 0; 225 226 data.pixels->set(offset, static_cast<unsigned char>(lightStrength * paintingData.colorVector.x())); 227 data.pixels->set(offset + 1, static_cast<unsigned char>(lightStrength * paintingData.colorVector.y())); 228 data.pixels->set(offset + 2, static_cast<unsigned char>(lightStrength * paintingData.colorVector.z())); 229 } 230 231 void FELighting::setPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, 232 int lightX, int lightY, float factorX, float factorY, IntPoint& normalVector) 233 { 234 inlineSetPixel(offset, data, paintingData, lightX, lightY, factorX, factorY, normalVector); 235 } 236 237 bool FELighting::drawLighting(ByteArray* pixels, int width, int height) 238 { 239 LightSource::PaintingData paintingData; 240 LightingData data; 241 242 if (!m_lightSource) 243 return false; 244 245 // FIXME: do something if width or height (or both) is 1 pixel. 246 // The W3 spec does not define this case. Now the filter just returns. 247 if (width <= 2 || height <= 2) 248 return false; 249 250 data.pixels = pixels; 251 data.surfaceScale = m_surfaceScale / 255.0f; 252 data.widthMultipliedByPixelSize = width * cPixelSize; 253 data.widthDecreasedByOne = width - 1; 254 data.heightDecreasedByOne = height - 1; 255 paintingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue()); 256 m_lightSource->initPaintingData(paintingData); 257 258 // Top/Left corner 259 IntPoint normalVector; 260 int offset = 0; 261 data.topLeft(offset, normalVector); 262 setPixel(offset, data, paintingData, 0, 0, cFactor2div3, cFactor2div3, normalVector); 263 264 // Top/Right pixel 265 offset = data.widthMultipliedByPixelSize - cPixelSize; 266 data.topRight(offset, normalVector); 267 setPixel(offset, data, paintingData, data.widthDecreasedByOne, 0, cFactor2div3, cFactor2div3, normalVector); 268 269 // Bottom/Left pixel 270 offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize; 271 data.bottomLeft(offset, normalVector); 272 setPixel(offset, data, paintingData, 0, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector); 273 274 // Bottom/Right pixel 275 offset = height * data.widthMultipliedByPixelSize - cPixelSize; 276 data.bottomRight(offset, normalVector); 277 setPixel(offset, data, paintingData, data.widthDecreasedByOne, data.heightDecreasedByOne, cFactor2div3, cFactor2div3, normalVector); 278 279 if (width >= 3) { 280 // Top row 281 offset = cPixelSize; 282 for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) { 283 data.topRow(offset, normalVector); 284 inlineSetPixel(offset, data, paintingData, x, 0, cFactor1div3, cFactor1div2, normalVector); 285 } 286 // Bottom row 287 offset = data.heightDecreasedByOne * data.widthMultipliedByPixelSize + cPixelSize; 288 for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) { 289 data.bottomRow(offset, normalVector); 290 inlineSetPixel(offset, data, paintingData, x, data.heightDecreasedByOne, cFactor1div3, cFactor1div2, normalVector); 291 } 292 } 293 294 if (height >= 3) { 295 // Left column 296 offset = data.widthMultipliedByPixelSize; 297 for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) { 298 data.leftColumn(offset, normalVector); 299 inlineSetPixel(offset, data, paintingData, 0, y, cFactor1div2, cFactor1div3, normalVector); 300 } 301 // Right column 302 offset = (data.widthMultipliedByPixelSize << 1) - cPixelSize; 303 for (int y = 1; y < data.heightDecreasedByOne; ++y, offset += data.widthMultipliedByPixelSize) { 304 data.rightColumn(offset, normalVector); 305 inlineSetPixel(offset, data, paintingData, data.widthDecreasedByOne, y, cFactor1div2, cFactor1div3, normalVector); 306 } 307 } 308 309 if (width >= 3 && height >= 3) { 310 // Interior pixels 311 #if CPU(ARM_NEON) && COMPILER(GCC) 312 drawInteriorPixels(data, paintingData); 313 #else 314 for (int y = 1; y < data.heightDecreasedByOne; ++y) { 315 offset = y * data.widthMultipliedByPixelSize + cPixelSize; 316 for (int x = 1; x < data.widthDecreasedByOne; ++x, offset += cPixelSize) { 317 data.interior(offset, normalVector); 318 inlineSetPixel(offset, data, paintingData, x, y, cFactor1div4, cFactor1div4, normalVector); 319 } 320 } 321 #endif 322 } 323 324 int lastPixel = data.widthMultipliedByPixelSize * height; 325 if (m_lightingType == DiffuseLighting) { 326 for (int i = cAlphaChannelOffset; i < lastPixel; i += cPixelSize) 327 data.pixels->set(i, cOpaqueAlpha); 328 } else { 329 for (int i = 0; i < lastPixel; i += cPixelSize) { 330 unsigned char a1 = data.pixels->get(i); 331 unsigned char a2 = data.pixels->get(i + 1); 332 unsigned char a3 = data.pixels->get(i + 2); 333 // alpha set to set to max(a1, a2, a3) 334 data.pixels->set(i + 3, a1 >= a2 ? (a1 >= a3 ? a1 : a3) : (a2 >= a3 ? a2 : a3)); 335 } 336 } 337 338 return true; 339 } 340 341 void FELighting::apply() 342 { 343 if (hasResult()) 344 return; 345 FilterEffect* in = inputEffect(0); 346 in->apply(); 347 if (!in->hasResult()) 348 return; 349 350 ByteArray* srcPixelArray = createUnmultipliedImageResult(); 351 if (!srcPixelArray) 352 return; 353 354 setIsAlphaImage(false); 355 356 IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); 357 in->copyUnmultipliedImage(srcPixelArray, effectDrawingRect); 358 359 // FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3 360 // standard has no test case for them, and other browsers (like Firefox) has strange 361 // output for various kernelUnitLengths, and I am not sure they are reliable. 362 // Anyway, feConvolveMatrix should also use the implementation 363 364 IntSize absolutePaintSize = absolutePaintRect().size(); 365 drawLighting(srcPixelArray, absolutePaintSize.width(), absolutePaintSize.height()); 366 } 367 368 #if CPU(ARM_NEON) && COMPILER(GCC) 369 370 static int getPowerCoefficients(float exponent) 371 { 372 // Calling a powf function from the assembly code would require to save 373 // and reload a lot of NEON registers. Since the base is in range [0..1] 374 // and only 8 bit precision is required, we use our own powf function. 375 // This is probably not the best, but it uses only a few registers and 376 // gives us enough precision (modifying the exponent field directly would 377 // also be possible). 378 379 // First, we limit the exponent to maximum of 64, which gives us enough 380 // precision. We split the exponent to an integer and fraction part, 381 // since a^x = (a^y)*(a^z) where x = y+z. The integer exponent of the 382 // power is estimated by square, and the fraction exponent of the power 383 // is estimated by square root assembly instructions. 384 int i, result; 385 386 if (exponent < 0) 387 exponent = 1 / (-exponent); 388 389 if (exponent > 63.99) 390 exponent = 63.99; 391 392 exponent /= 64; 393 result = 0; 394 for (i = 11; i >= 0; --i) { 395 exponent *= 2; 396 if (exponent >= 1) { 397 result |= 1 << i; 398 exponent -= 1; 399 } 400 } 401 return result; 402 } 403 404 void FELighting::drawInteriorPixels(LightingData& data, LightSource::PaintingData& paintingData) 405 { 406 WTF_ALIGNED(FELightingFloatArgumentsForNeon, floatArguments, 16); 407 408 FELightingPaintingDataForNeon neonData = { 409 data.pixels->data(), 410 data.widthDecreasedByOne - 1, 411 data.heightDecreasedByOne - 1, 412 0, 413 0, 414 0, 415 &floatArguments, 416 feLightingConstantsForNeon() 417 }; 418 419 // Set light source arguments. 420 floatArguments.constOne = 1; 421 422 floatArguments.colorRed = m_lightingColor.red(); 423 floatArguments.colorGreen = m_lightingColor.green(); 424 floatArguments.colorBlue = m_lightingColor.blue(); 425 floatArguments.padding4 = 0; 426 427 if (m_lightSource->type() == LS_POINT) { 428 neonData.flags |= FLAG_POINT_LIGHT; 429 PointLightSource* pointLightSource = static_cast<PointLightSource*>(m_lightSource.get()); 430 floatArguments.lightX = pointLightSource->position().x(); 431 floatArguments.lightY = pointLightSource->position().y(); 432 floatArguments.lightZ = pointLightSource->position().z(); 433 floatArguments.padding2 = 0; 434 } else if (m_lightSource->type() == LS_SPOT) { 435 neonData.flags |= FLAG_SPOT_LIGHT; 436 SpotLightSource* spotLightSource = static_cast<SpotLightSource*>(m_lightSource.get()); 437 floatArguments.lightX = spotLightSource->position().x(); 438 floatArguments.lightY = spotLightSource->position().y(); 439 floatArguments.lightZ = spotLightSource->position().z(); 440 floatArguments.padding2 = 0; 441 442 floatArguments.directionX = paintingData.directionVector.x(); 443 floatArguments.directionY = paintingData.directionVector.y(); 444 floatArguments.directionZ = paintingData.directionVector.z(); 445 floatArguments.padding3 = 0; 446 447 floatArguments.coneCutOffLimit = paintingData.coneCutOffLimit; 448 floatArguments.coneFullLight = paintingData.coneFullLight; 449 floatArguments.coneCutOffRange = paintingData.coneCutOffLimit - paintingData.coneFullLight; 450 neonData.coneExponent = getPowerCoefficients(spotLightSource->specularExponent()); 451 if (spotLightSource->specularExponent() == 1) 452 neonData.flags |= FLAG_CONE_EXPONENT_IS_1; 453 } else { 454 ASSERT(m_lightSource.type == LS_DISTANT); 455 floatArguments.lightX = paintingData.lightVector.x(); 456 floatArguments.lightY = paintingData.lightVector.y(); 457 floatArguments.lightZ = paintingData.lightVector.z(); 458 floatArguments.padding2 = 1; 459 } 460 461 // Set lighting arguments. 462 floatArguments.surfaceScale = data.surfaceScale; 463 floatArguments.minusSurfaceScaleDividedByFour = -data.surfaceScale / 4; 464 if (m_lightingType == FELighting::DiffuseLighting) 465 floatArguments.diffuseConstant = m_diffuseConstant; 466 else { 467 neonData.flags |= FLAG_SPECULAR_LIGHT; 468 floatArguments.diffuseConstant = m_specularConstant; 469 neonData.specularExponent = getPowerCoefficients(m_specularExponent); 470 if (m_specularExponent == 1) 471 neonData.flags |= FLAG_SPECULAR_EXPONENT_IS_1; 472 } 473 if (floatArguments.diffuseConstant == 1) 474 neonData.flags |= FLAG_DIFFUSE_CONST_IS_1; 475 476 neonDrawLighting(&neonData); 477 } 478 #endif // CPU(ARM_NEON) && COMPILER(GCC) 479 480 } // namespace WebCore 481 482 #endif // ENABLE(FILTERS) 483