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