Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) 2011 University of Szeged
      3  * Copyright (C) 2011 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 #ifndef FELightingNEON_h
     28 #define FELightingNEON_h
     29 
     30 #if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC)
     31 
     32 #include "core/platform/graphics/filters/FELighting.h"
     33 #include "wtf/Alignment.h"
     34 #include "wtf/CPU.h"
     35 #include "wtf/ParallelJobs.h"
     36 
     37 namespace WebCore {
     38 
     39 // Otherwise: Distant Light.
     40 #define FLAG_POINT_LIGHT                 0x01
     41 #define FLAG_SPOT_LIGHT                  0x02
     42 #define FLAG_CONE_EXPONENT_IS_1          0x04
     43 
     44 // Otherwise: Diffuse light.
     45 #define FLAG_SPECULAR_LIGHT              0x10
     46 #define FLAG_DIFFUSE_CONST_IS_1          0x20
     47 #define FLAG_SPECULAR_EXPONENT_IS_1      0x40
     48 
     49 // Must be aligned to 16 bytes.
     50 struct FELightingFloatArgumentsForNeon {
     51     float surfaceScale;
     52     float minusSurfaceScaleDividedByFour;
     53     float diffuseConstant;
     54     float padding1;
     55 
     56     float coneCutOffLimit;
     57     float coneFullLight;
     58     float coneCutOffRange;
     59     float constOne;
     60 
     61     float lightX;
     62     float lightY;
     63     float lightZ;
     64     float padding2;
     65 
     66     float directionX;
     67     float directionY;
     68     float directionZ;
     69     float padding3;
     70 
     71     float colorRed;
     72     float colorGreen;
     73     float colorBlue;
     74     float padding4;
     75 };
     76 
     77 struct FELightingPaintingDataForNeon {
     78     unsigned char* pixels;
     79     float yStart;
     80     int widthDecreasedByTwo;
     81     int absoluteHeight;
     82     // Combination of FLAG constants above.
     83     int flags;
     84     int specularExponent;
     85     int coneExponent;
     86     FELightingFloatArgumentsForNeon* floatArguments;
     87     short* paintingConstants;
     88 };
     89 
     90 short* feLightingConstantsForNeon();
     91 
     92 extern "C" {
     93 void neonDrawLighting(FELightingPaintingDataForNeon*);
     94 }
     95 
     96 inline void FELighting::platformApplyNeon(LightingData& data, LightSource::PaintingData& paintingData)
     97 {
     98     WTF_ALIGNED(FELightingFloatArgumentsForNeon, floatArguments, 16);
     99 
    100     FELightingPaintingDataForNeon neonData = {
    101         data.pixels->data(),
    102         1,
    103         data.widthDecreasedByOne - 1,
    104         data.heightDecreasedByOne - 1,
    105         0,
    106         0,
    107         0,
    108         &floatArguments,
    109         feLightingConstantsForNeon()
    110     };
    111 
    112     // Set light source arguments.
    113     floatArguments.constOne = 1;
    114 
    115     floatArguments.colorRed = m_lightingColor.red();
    116     floatArguments.colorGreen = m_lightingColor.green();
    117     floatArguments.colorBlue = m_lightingColor.blue();
    118     floatArguments.padding4 = 0;
    119 
    120     if (m_lightSource->type() == LS_POINT) {
    121         neonData.flags |= FLAG_POINT_LIGHT;
    122         PointLightSource* pointLightSource = static_cast<PointLightSource*>(m_lightSource.get());
    123         floatArguments.lightX = pointLightSource->position().x();
    124         floatArguments.lightY = pointLightSource->position().y();
    125         floatArguments.lightZ = pointLightSource->position().z();
    126         floatArguments.padding2 = 0;
    127     } else if (m_lightSource->type() == LS_SPOT) {
    128         neonData.flags |= FLAG_SPOT_LIGHT;
    129         SpotLightSource* spotLightSource = static_cast<SpotLightSource*>(m_lightSource.get());
    130         floatArguments.lightX = spotLightSource->position().x();
    131         floatArguments.lightY = spotLightSource->position().y();
    132         floatArguments.lightZ = spotLightSource->position().z();
    133         floatArguments.padding2 = 0;
    134 
    135         floatArguments.directionX = paintingData.directionVector.x();
    136         floatArguments.directionY = paintingData.directionVector.y();
    137         floatArguments.directionZ = paintingData.directionVector.z();
    138         floatArguments.padding3 = 0;
    139 
    140         floatArguments.coneCutOffLimit = paintingData.coneCutOffLimit;
    141         floatArguments.coneFullLight = paintingData.coneFullLight;
    142         floatArguments.coneCutOffRange = paintingData.coneCutOffLimit - paintingData.coneFullLight;
    143         neonData.coneExponent = getPowerCoefficients(spotLightSource->specularExponent());
    144         if (spotLightSource->specularExponent() == 1)
    145             neonData.flags |= FLAG_CONE_EXPONENT_IS_1;
    146     } else {
    147         ASSERT(m_lightSource->type() == LS_DISTANT);
    148         floatArguments.lightX = paintingData.lightVector.x();
    149         floatArguments.lightY = paintingData.lightVector.y();
    150         floatArguments.lightZ = paintingData.lightVector.z();
    151         floatArguments.padding2 = 1;
    152     }
    153 
    154     // Set lighting arguments.
    155     floatArguments.surfaceScale = data.surfaceScale;
    156     floatArguments.minusSurfaceScaleDividedByFour = -data.surfaceScale / 4;
    157     if (m_lightingType == FELighting::DiffuseLighting)
    158         floatArguments.diffuseConstant = m_diffuseConstant;
    159     else {
    160         neonData.flags |= FLAG_SPECULAR_LIGHT;
    161         floatArguments.diffuseConstant = m_specularConstant;
    162         neonData.specularExponent = getPowerCoefficients(m_specularExponent);
    163         if (m_specularExponent == 1)
    164             neonData.flags |= FLAG_SPECULAR_EXPONENT_IS_1;
    165     }
    166     if (floatArguments.diffuseConstant == 1)
    167         neonData.flags |= FLAG_DIFFUSE_CONST_IS_1;
    168 
    169     int optimalThreadNumber = ((data.widthDecreasedByOne - 1) * (data.heightDecreasedByOne - 1)) / s_minimalRectDimension;
    170     if (optimalThreadNumber > 1) {
    171         // Initialize parallel jobs
    172         ParallelJobs<FELightingPaintingDataForNeon> parallelJobs(&WebCore::FELighting::platformApplyNeonWorker, optimalThreadNumber);
    173 
    174         // Fill the parameter array
    175         int job = parallelJobs.numberOfJobs();
    176         if (job > 1) {
    177             int yStart = 1;
    178             int yStep = (data.heightDecreasedByOne - 1) / job;
    179             for (--job; job >= 0; --job) {
    180                 FELightingPaintingDataForNeon& params = parallelJobs.parameter(job);
    181                 params = neonData;
    182                 params.yStart = yStart;
    183                 params.pixels += (yStart - 1) * (data.widthDecreasedByOne + 1) * 4;
    184                 if (job > 0) {
    185                     params.absoluteHeight = yStep;
    186                     yStart += yStep;
    187                 } else
    188                     params.absoluteHeight = data.heightDecreasedByOne - yStart;
    189             }
    190             parallelJobs.execute();
    191             return;
    192         }
    193     }
    194 
    195     neonDrawLighting(&neonData);
    196 }
    197 
    198 } // namespace WebCore
    199 
    200 #endif // CPU(ARM_NEON) && COMPILER(GCC)
    201 
    202 #endif // FELightingNEON_h
    203