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