1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #include "rsCpuIntrinsic.h"
19 #include "rsCpuIntrinsicInlines.h"
20 
21 using namespace android;
22 using namespace android::renderscript;
23 
24 namespace android {
25 namespace renderscript {
26 
27 
28 class RsdCpuScriptIntrinsicConvolve5x5 : public RsdCpuScriptIntrinsic {
29 public:
30     void populateScript(Script *) override;
31     void invokeFreeChildren() override;
32 
33     void setGlobalVar(uint32_t slot, const void *data, size_t dataLength) override;
34     void setGlobalObj(uint32_t slot, ObjectBase *data) override;
35 
36     ~RsdCpuScriptIntrinsicConvolve5x5() override;
37     RsdCpuScriptIntrinsicConvolve5x5(RsdCpuReferenceImpl *ctx, const Script *s, const Element *e);
38 
39 protected:
40     float mFp[28];
41     short mIp[28];
42     ObjectBaseRef<Allocation> alloc;
43 
44 
45     static void kernelU1(const RsExpandKernelDriverInfo *info,
46                          uint32_t xstart, uint32_t xend,
47                          uint32_t outstep);
48     static void kernelU2(const RsExpandKernelDriverInfo *info,
49                          uint32_t xstart, uint32_t xend,
50                          uint32_t outstep);
51     static void kernelU4(const RsExpandKernelDriverInfo *info,
52                          uint32_t xstart, uint32_t xend,
53                          uint32_t outstep);
54     static void kernelF1(const RsExpandKernelDriverInfo *info,
55                          uint32_t xstart, uint32_t xend,
56                          uint32_t outstep);
57     static void kernelF2(const RsExpandKernelDriverInfo *info,
58                          uint32_t xstart, uint32_t xend,
59                          uint32_t outstep);
60     static void kernelF4(const RsExpandKernelDriverInfo *info,
61                          uint32_t xstart, uint32_t xend,
62                          uint32_t outstep);
63 
64 
65 };
66 
67 }
68 }
69 
setGlobalObj(uint32_t slot,ObjectBase * data)70 void RsdCpuScriptIntrinsicConvolve5x5::setGlobalObj(uint32_t slot, ObjectBase *data) {
71     rsAssert(slot == 1);
72     alloc.set(static_cast<Allocation *>(data));
73 }
74 
setGlobalVar(uint32_t slot,const void * data,size_t dataLength)75 void RsdCpuScriptIntrinsicConvolve5x5::setGlobalVar(uint32_t slot,
76                                                     const void *data, size_t dataLength) {
77     rsAssert(slot == 0);
78     memcpy (&mFp, data, dataLength);
79     for(int ct=0; ct < 25; ct++) {
80         if (mFp[ct] >= 0) {
81             mIp[ct] = (short)(mFp[ct] * 256.f + 0.5f);
82         } else {
83             mIp[ct] = (short)(mFp[ct] * 256.f - 0.5f);
84         }
85     }
86 }
87 
88 
OneU4(const RsExpandKernelDriverInfo * info,uint32_t x,uchar4 * out,const uchar4 * py0,const uchar4 * py1,const uchar4 * py2,const uchar4 * py3,const uchar4 * py4,const float * coeff)89 static void OneU4(const RsExpandKernelDriverInfo *info, uint32_t x, uchar4 *out,
90                   const uchar4 *py0, const uchar4 *py1, const uchar4 *py2, const uchar4 *py3, const uchar4 *py4,
91                   const float* coeff) {
92 
93     uint32_t x0 = rsMax((int32_t)x-2, 0);
94     uint32_t x1 = rsMax((int32_t)x-1, 0);
95     uint32_t x2 = x;
96     uint32_t x3 = rsMin((int32_t)x+1, (int32_t)(info->dim.x-1));
97     uint32_t x4 = rsMin((int32_t)x+2, (int32_t)(info->dim.x-1));
98 
99     float4 px = convert_float4(py0[x0]) * coeff[0] +
100                 convert_float4(py0[x1]) * coeff[1] +
101                 convert_float4(py0[x2]) * coeff[2] +
102                 convert_float4(py0[x3]) * coeff[3] +
103                 convert_float4(py0[x4]) * coeff[4] +
104 
105                 convert_float4(py1[x0]) * coeff[5] +
106                 convert_float4(py1[x1]) * coeff[6] +
107                 convert_float4(py1[x2]) * coeff[7] +
108                 convert_float4(py1[x3]) * coeff[8] +
109                 convert_float4(py1[x4]) * coeff[9] +
110 
111                 convert_float4(py2[x0]) * coeff[10] +
112                 convert_float4(py2[x1]) * coeff[11] +
113                 convert_float4(py2[x2]) * coeff[12] +
114                 convert_float4(py2[x3]) * coeff[13] +
115                 convert_float4(py2[x4]) * coeff[14] +
116 
117                 convert_float4(py3[x0]) * coeff[15] +
118                 convert_float4(py3[x1]) * coeff[16] +
119                 convert_float4(py3[x2]) * coeff[17] +
120                 convert_float4(py3[x3]) * coeff[18] +
121                 convert_float4(py3[x4]) * coeff[19] +
122 
123                 convert_float4(py4[x0]) * coeff[20] +
124                 convert_float4(py4[x1]) * coeff[21] +
125                 convert_float4(py4[x2]) * coeff[22] +
126                 convert_float4(py4[x3]) * coeff[23] +
127                 convert_float4(py4[x4]) * coeff[24];
128     px = clamp(px + 0.5f, 0.f, 255.f);
129     *out = convert_uchar4(px);
130 }
131 
OneU2(const RsExpandKernelDriverInfo * info,uint32_t x,uchar2 * out,const uchar2 * py0,const uchar2 * py1,const uchar2 * py2,const uchar2 * py3,const uchar2 * py4,const float * coeff)132 static void OneU2(const RsExpandKernelDriverInfo *info, uint32_t x, uchar2 *out,
133                   const uchar2 *py0, const uchar2 *py1, const uchar2 *py2, const uchar2 *py3, const uchar2 *py4,
134                   const float* coeff) {
135 
136     uint32_t x0 = rsMax((int32_t)x-2, 0);
137     uint32_t x1 = rsMax((int32_t)x-1, 0);
138     uint32_t x2 = x;
139     uint32_t x3 = rsMin((int32_t)x+1, (int32_t)(info->dim.x-1));
140     uint32_t x4 = rsMin((int32_t)x+2, (int32_t)(info->dim.x-1));
141 
142     float2 px = convert_float2(py0[x0]) * coeff[0] +
143                 convert_float2(py0[x1]) * coeff[1] +
144                 convert_float2(py0[x2]) * coeff[2] +
145                 convert_float2(py0[x3]) * coeff[3] +
146                 convert_float2(py0[x4]) * coeff[4] +
147 
148                 convert_float2(py1[x0]) * coeff[5] +
149                 convert_float2(py1[x1]) * coeff[6] +
150                 convert_float2(py1[x2]) * coeff[7] +
151                 convert_float2(py1[x3]) * coeff[8] +
152                 convert_float2(py1[x4]) * coeff[9] +
153 
154                 convert_float2(py2[x0]) * coeff[10] +
155                 convert_float2(py2[x1]) * coeff[11] +
156                 convert_float2(py2[x2]) * coeff[12] +
157                 convert_float2(py2[x3]) * coeff[13] +
158                 convert_float2(py2[x4]) * coeff[14] +
159 
160                 convert_float2(py3[x0]) * coeff[15] +
161                 convert_float2(py3[x1]) * coeff[16] +
162                 convert_float2(py3[x2]) * coeff[17] +
163                 convert_float2(py3[x3]) * coeff[18] +
164                 convert_float2(py3[x4]) * coeff[19] +
165 
166                 convert_float2(py4[x0]) * coeff[20] +
167                 convert_float2(py4[x1]) * coeff[21] +
168                 convert_float2(py4[x2]) * coeff[22] +
169                 convert_float2(py4[x3]) * coeff[23] +
170                 convert_float2(py4[x4]) * coeff[24];
171     px = clamp(px + 0.5f, 0.f, 255.f);
172     *out = convert_uchar2(px);
173 }
174 
OneU1(const RsExpandKernelDriverInfo * info,uint32_t x,uchar * out,const uchar * py0,const uchar * py1,const uchar * py2,const uchar * py3,const uchar * py4,const float * coeff)175 static void OneU1(const RsExpandKernelDriverInfo *info, uint32_t x, uchar *out,
176                   const uchar *py0, const uchar *py1, const uchar *py2, const uchar *py3, const uchar *py4,
177                   const float* coeff) {
178 
179     uint32_t x0 = rsMax((int32_t)x-2, 0);
180     uint32_t x1 = rsMax((int32_t)x-1, 0);
181     uint32_t x2 = x;
182     uint32_t x3 = rsMin((int32_t)x+1, (int32_t)(info->dim.x-1));
183     uint32_t x4 = rsMin((int32_t)x+2, (int32_t)(info->dim.x-1));
184 
185     float px = (float)(py0[x0]) * coeff[0] +
186                (float)(py0[x1]) * coeff[1] +
187                (float)(py0[x2]) * coeff[2] +
188                (float)(py0[x3]) * coeff[3] +
189                (float)(py0[x4]) * coeff[4] +
190 
191                (float)(py1[x0]) * coeff[5] +
192                (float)(py1[x1]) * coeff[6] +
193                (float)(py1[x2]) * coeff[7] +
194                (float)(py1[x3]) * coeff[8] +
195                (float)(py1[x4]) * coeff[9] +
196 
197                (float)(py2[x0]) * coeff[10] +
198                (float)(py2[x1]) * coeff[11] +
199                (float)(py2[x2]) * coeff[12] +
200                (float)(py2[x3]) * coeff[13] +
201                (float)(py2[x4]) * coeff[14] +
202 
203                (float)(py3[x0]) * coeff[15] +
204                (float)(py3[x1]) * coeff[16] +
205                (float)(py3[x2]) * coeff[17] +
206                (float)(py3[x3]) * coeff[18] +
207                (float)(py3[x4]) * coeff[19] +
208 
209                (float)(py4[x0]) * coeff[20] +
210                (float)(py4[x1]) * coeff[21] +
211                (float)(py4[x2]) * coeff[22] +
212                (float)(py4[x3]) * coeff[23] +
213                (float)(py4[x4]) * coeff[24];
214     px = clamp(px + 0.5f, 0.f, 255.f);
215     *out = px;
216 }
217 
OneF4(const RsExpandKernelDriverInfo * info,uint32_t x,float4 * out,const float4 * py0,const float4 * py1,const float4 * py2,const float4 * py3,const float4 * py4,const float * coeff)218 static void OneF4(const RsExpandKernelDriverInfo *info, uint32_t x, float4 *out,
219                   const float4 *py0, const float4 *py1, const float4 *py2, const float4 *py3, const float4 *py4,
220                   const float* coeff) {
221 
222     uint32_t x0 = rsMax((int32_t)x-2, 0);
223     uint32_t x1 = rsMax((int32_t)x-1, 0);
224     uint32_t x2 = x;
225     uint32_t x3 = rsMin((int32_t)x+1, (int32_t)(info->dim.x-1));
226     uint32_t x4 = rsMin((int32_t)x+2, (int32_t)(info->dim.x-1));
227 
228     float4 px = py0[x0] * coeff[0] +
229                 py0[x1] * coeff[1] +
230                 py0[x2] * coeff[2] +
231                 py0[x3] * coeff[3] +
232                 py0[x4] * coeff[4] +
233 
234                 py1[x0] * coeff[5] +
235                 py1[x1] * coeff[6] +
236                 py1[x2] * coeff[7] +
237                 py1[x3] * coeff[8] +
238                 py1[x4] * coeff[9] +
239 
240                 py2[x0] * coeff[10] +
241                 py2[x1] * coeff[11] +
242                 py2[x2] * coeff[12] +
243                 py2[x3] * coeff[13] +
244                 py2[x4] * coeff[14] +
245 
246                 py3[x0] * coeff[15] +
247                 py3[x1] * coeff[16] +
248                 py3[x2] * coeff[17] +
249                 py3[x3] * coeff[18] +
250                 py3[x4] * coeff[19] +
251 
252                 py4[x0] * coeff[20] +
253                 py4[x1] * coeff[21] +
254                 py4[x2] * coeff[22] +
255                 py4[x3] * coeff[23] +
256                 py4[x4] * coeff[24];
257     *out = px;
258 }
259 
OneF2(const RsExpandKernelDriverInfo * info,uint32_t x,float2 * out,const float2 * py0,const float2 * py1,const float2 * py2,const float2 * py3,const float2 * py4,const float * coeff)260 static void OneF2(const RsExpandKernelDriverInfo *info, uint32_t x, float2 *out,
261                   const float2 *py0, const float2 *py1, const float2 *py2, const float2 *py3, const float2 *py4,
262                   const float* coeff) {
263 
264     uint32_t x0 = rsMax((int32_t)x-2, 0);
265     uint32_t x1 = rsMax((int32_t)x-1, 0);
266     uint32_t x2 = x;
267     uint32_t x3 = rsMin((int32_t)x+1, (int32_t)(info->dim.x-1));
268     uint32_t x4 = rsMin((int32_t)x+2, (int32_t)(info->dim.x-1));
269 
270     float2 px = py0[x0] * coeff[0] +
271                 py0[x1] * coeff[1] +
272                 py0[x2] * coeff[2] +
273                 py0[x3] * coeff[3] +
274                 py0[x4] * coeff[4] +
275 
276                 py1[x0] * coeff[5] +
277                 py1[x1] * coeff[6] +
278                 py1[x2] * coeff[7] +
279                 py1[x3] * coeff[8] +
280                 py1[x4] * coeff[9] +
281 
282                 py2[x0] * coeff[10] +
283                 py2[x1] * coeff[11] +
284                 py2[x2] * coeff[12] +
285                 py2[x3] * coeff[13] +
286                 py2[x4] * coeff[14] +
287 
288                 py3[x0] * coeff[15] +
289                 py3[x1] * coeff[16] +
290                 py3[x2] * coeff[17] +
291                 py3[x3] * coeff[18] +
292                 py3[x4] * coeff[19] +
293 
294                 py4[x0] * coeff[20] +
295                 py4[x1] * coeff[21] +
296                 py4[x2] * coeff[22] +
297                 py4[x3] * coeff[23] +
298                 py4[x4] * coeff[24];
299     *out = px;
300 }
301 
OneF1(const RsExpandKernelDriverInfo * info,uint32_t x,float * out,const float * py0,const float * py1,const float * py2,const float * py3,const float * py4,const float * coeff)302 static void OneF1(const RsExpandKernelDriverInfo *info, uint32_t x, float *out,
303                   const float *py0, const float *py1, const float *py2, const float *py3, const float *py4,
304                   const float* coeff) {
305 
306     uint32_t x0 = rsMax((int32_t)x-2, 0);
307     uint32_t x1 = rsMax((int32_t)x-1, 0);
308     uint32_t x2 = x;
309     uint32_t x3 = rsMin((int32_t)x+1, (int32_t)(info->dim.x-1));
310     uint32_t x4 = rsMin((int32_t)x+2, (int32_t)(info->dim.x-1));
311 
312     float px = py0[x0] * coeff[0] +
313                py0[x1] * coeff[1] +
314                py0[x2] * coeff[2] +
315                py0[x3] * coeff[3] +
316                py0[x4] * coeff[4] +
317 
318                py1[x0] * coeff[5] +
319                py1[x1] * coeff[6] +
320                py1[x2] * coeff[7] +
321                py1[x3] * coeff[8] +
322                py1[x4] * coeff[9] +
323 
324                py2[x0] * coeff[10] +
325                py2[x1] * coeff[11] +
326                py2[x2] * coeff[12] +
327                py2[x3] * coeff[13] +
328                py2[x4] * coeff[14] +
329 
330                py3[x0] * coeff[15] +
331                py3[x1] * coeff[16] +
332                py3[x2] * coeff[17] +
333                py3[x3] * coeff[18] +
334                py3[x4] * coeff[19] +
335 
336                py4[x0] * coeff[20] +
337                py4[x1] * coeff[21] +
338                py4[x2] * coeff[22] +
339                py4[x3] * coeff[23] +
340                py4[x4] * coeff[24];
341     *out = px;
342 }
343 
344 
345 extern "C" void rsdIntrinsicConvolve5x5_K(void *dst, const void *y0, const void *y1,
346                                           const void *y2, const void *y3, const void *y4,
347                                           const short *coef, uint32_t count);
348 
kernelU4(const RsExpandKernelDriverInfo * info,uint32_t xstart,uint32_t xend,uint32_t outstep)349 void RsdCpuScriptIntrinsicConvolve5x5::kernelU4(const RsExpandKernelDriverInfo *info,
350                                                 uint32_t xstart, uint32_t xend,
351                                                 uint32_t outstep) {
352     RsdCpuScriptIntrinsicConvolve5x5 *cp = (RsdCpuScriptIntrinsicConvolve5x5 *)info->usr;
353     if (!cp->alloc.get()) {
354         ALOGE("Convolve5x5 executed without input, skipping");
355         return;
356     }
357     const uchar *pin = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
358     const size_t stride = cp->alloc->mHal.drvState.lod[0].stride;
359 
360     uint32_t y0 = rsMax((int32_t)info->current.y-2, 0);
361     uint32_t y1 = rsMax((int32_t)info->current.y-1, 0);
362     uint32_t y2 = info->current.y;
363     uint32_t y3 = rsMin((int32_t)info->current.y+1, (int32_t)(info->dim.y-1));
364     uint32_t y4 = rsMin((int32_t)info->current.y+2, (int32_t)(info->dim.y-1));
365 
366     const uchar4 *py0 = (const uchar4 *)(pin + stride * y0);
367     const uchar4 *py1 = (const uchar4 *)(pin + stride * y1);
368     const uchar4 *py2 = (const uchar4 *)(pin + stride * y2);
369     const uchar4 *py3 = (const uchar4 *)(pin + stride * y3);
370     const uchar4 *py4 = (const uchar4 *)(pin + stride * y4);
371 
372     uchar4 *out = (uchar4 *)info->outPtr[0];
373     uint32_t x1 = xstart;
374     uint32_t x2 = xend;
375 
376     while((x1 < x2) && (x1 < 2)) {
377         OneU4(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
378         out++;
379         x1++;
380     }
381 #if defined(ARCH_X86_HAVE_SSSE3)
382     // for x86 SIMD, require minimum of 7 elements (4 for SIMD,
383     // 3 for end boundary where x may hit the end boundary)
384     if (gArchUseSIMD &&((x1 + 6) < x2)) {
385         // subtract 3 for end boundary
386         uint32_t len = (x2 - x1 - 3) >> 2;
387         rsdIntrinsicConvolve5x5_K(out, py0 + x1 - 2, py1 + x1 - 2, py2 + x1 - 2, py3 + x1 - 2, py4 + x1 - 2, cp->mIp, len);
388         out += len << 2;
389         x1 += len << 2;
390     }
391 #endif
392 
393 #if defined(ARCH_ARM_USE_INTRINSICS)
394     if(gArchUseSIMD && ((x1 + 3) < x2)) {
395         uint32_t len = (x2 - x1 - 3) >> 1;
396         rsdIntrinsicConvolve5x5_K(out, py0 + x1 - 2, py1 + x1 - 2, py2 + x1 - 2, py3 + x1 - 2, py4 + x1 - 2, cp->mIp, len);
397         out += len << 1;
398         x1 += len << 1;
399     }
400 #endif
401 
402     while(x1 < x2) {
403         OneU4(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
404         out++;
405         x1++;
406     }
407 }
408 
kernelU2(const RsExpandKernelDriverInfo * info,uint32_t xstart,uint32_t xend,uint32_t outstep)409 void RsdCpuScriptIntrinsicConvolve5x5::kernelU2(const RsExpandKernelDriverInfo *info,
410                                                 uint32_t xstart, uint32_t xend,
411                                                 uint32_t outstep) {
412     RsdCpuScriptIntrinsicConvolve5x5 *cp = (RsdCpuScriptIntrinsicConvolve5x5 *)info->usr;
413     if (!cp->alloc.get()) {
414         ALOGE("Convolve5x5 executed without input, skipping");
415         return;
416     }
417     const uchar *pin = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
418     const size_t stride = cp->alloc->mHal.drvState.lod[0].stride;
419 
420     uint32_t y0 = rsMax((int32_t)info->current.y-2, 0);
421     uint32_t y1 = rsMax((int32_t)info->current.y-1, 0);
422     uint32_t y2 = info->current.y;
423     uint32_t y3 = rsMin((int32_t)info->current.y+1, (int32_t)(info->dim.y-1));
424     uint32_t y4 = rsMin((int32_t)info->current.y+2, (int32_t)(info->dim.y-1));
425 
426     const uchar2 *py0 = (const uchar2 *)(pin + stride * y0);
427     const uchar2 *py1 = (const uchar2 *)(pin + stride * y1);
428     const uchar2 *py2 = (const uchar2 *)(pin + stride * y2);
429     const uchar2 *py3 = (const uchar2 *)(pin + stride * y3);
430     const uchar2 *py4 = (const uchar2 *)(pin + stride * y4);
431 
432     uchar2 *out = (uchar2 *)info->outPtr[0];
433     uint32_t x1 = xstart;
434     uint32_t x2 = xend;
435 
436     while((x1 < x2) && (x1 < 2)) {
437         OneU2(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
438         out++;
439         x1++;
440     }
441 
442 #if 0//defined(ARCH_ARM_HAVE_NEON)
443     if((x1 + 3) < x2) {
444         uint32_t len = (x2 - x1 - 3) >> 1;
445         rsdIntrinsicConvolve5x5_K(out, py0, py1, py2, py3, py4, cp->ip, len);
446         out += len << 1;
447         x1 += len << 1;
448     }
449 #endif
450 
451     while(x1 < x2) {
452         OneU2(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
453         out++;
454         x1++;
455     }
456 }
457 
kernelU1(const RsExpandKernelDriverInfo * info,uint32_t xstart,uint32_t xend,uint32_t outstep)458 void RsdCpuScriptIntrinsicConvolve5x5::kernelU1(const RsExpandKernelDriverInfo *info,
459                                                 uint32_t xstart, uint32_t xend,
460                                                 uint32_t outstep) {
461     RsdCpuScriptIntrinsicConvolve5x5 *cp = (RsdCpuScriptIntrinsicConvolve5x5 *)info->usr;
462     if (!cp->alloc.get()) {
463         ALOGE("Convolve5x5 executed without input, skipping");
464         return;
465     }
466     const uchar *pin = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
467     const size_t stride = cp->alloc->mHal.drvState.lod[0].stride;
468 
469     uint32_t y0 = rsMax((int32_t)info->current.y-2, 0);
470     uint32_t y1 = rsMax((int32_t)info->current.y-1, 0);
471     uint32_t y2 = info->current.y;
472     uint32_t y3 = rsMin((int32_t)info->current.y+1, (int32_t)(info->dim.y-1));
473     uint32_t y4 = rsMin((int32_t)info->current.y+2, (int32_t)(info->dim.y-1));
474 
475     const uchar *py0 = (const uchar *)(pin + stride * y0);
476     const uchar *py1 = (const uchar *)(pin + stride * y1);
477     const uchar *py2 = (const uchar *)(pin + stride * y2);
478     const uchar *py3 = (const uchar *)(pin + stride * y3);
479     const uchar *py4 = (const uchar *)(pin + stride * y4);
480 
481     uchar *out = (uchar *)info->outPtr[0];
482     uint32_t x1 = xstart;
483     uint32_t x2 = xend;
484 
485     while((x1 < x2) && (x1 < 2)) {
486         OneU1(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
487         out++;
488         x1++;
489     }
490 
491 #if 0//defined(ARCH_ARM_HAVE_NEON)
492     if((x1 + 3) < x2) {
493         uint32_t len = (x2 - x1 - 3) >> 1;
494         rsdIntrinsicConvolve5x5_K(out, py0, py1, py2, py3, py4, cp->ip, len);
495         out += len << 1;
496         x1 += len << 1;
497     }
498 #endif
499 
500     while(x1 < x2) {
501         OneU1(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
502         out++;
503         x1++;
504     }
505 }
506 
kernelF4(const RsExpandKernelDriverInfo * info,uint32_t xstart,uint32_t xend,uint32_t outstep)507 void RsdCpuScriptIntrinsicConvolve5x5::kernelF4(const RsExpandKernelDriverInfo *info,
508                                                 uint32_t xstart, uint32_t xend,
509                                                 uint32_t outstep) {
510     RsdCpuScriptIntrinsicConvolve5x5 *cp = (RsdCpuScriptIntrinsicConvolve5x5 *)info->usr;
511     if (!cp->alloc.get()) {
512         ALOGE("Convolve5x5 executed without input, skipping");
513         return;
514     }
515     const uchar *pin = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
516     const size_t stride = cp->alloc->mHal.drvState.lod[0].stride;
517 
518     uint32_t y0 = rsMax((int32_t)info->current.y-2, 0);
519     uint32_t y1 = rsMax((int32_t)info->current.y-1, 0);
520     uint32_t y2 = info->current.y;
521     uint32_t y3 = rsMin((int32_t)info->current.y+1, (int32_t)(info->dim.y-1));
522     uint32_t y4 = rsMin((int32_t)info->current.y+2, (int32_t)(info->dim.y-1));
523 
524     const float4 *py0 = (const float4 *)(pin + stride * y0);
525     const float4 *py1 = (const float4 *)(pin + stride * y1);
526     const float4 *py2 = (const float4 *)(pin + stride * y2);
527     const float4 *py3 = (const float4 *)(pin + stride * y3);
528     const float4 *py4 = (const float4 *)(pin + stride * y4);
529 
530     float4 *out = (float4 *)info->outPtr[0];
531     uint32_t x1 = xstart;
532     uint32_t x2 = xend;
533 
534     while((x1 < x2) && (x1 < 2)) {
535         OneF4(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
536         out++;
537         x1++;
538     }
539 
540 #if 0//defined(ARCH_ARM_HAVE_NEON)
541     if((x1 + 3) < x2) {
542         uint32_t len = (x2 - x1 - 3) >> 1;
543         rsdIntrinsicConvolve5x5_K(out, py0, py1, py2, py3, py4, cp->ip, len);
544         out += len << 1;
545         x1 += len << 1;
546     }
547 #endif
548 
549     while(x1 < x2) {
550         OneF4(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
551         out++;
552         x1++;
553     }
554 }
555 
kernelF2(const RsExpandKernelDriverInfo * info,uint32_t xstart,uint32_t xend,uint32_t outstep)556 void RsdCpuScriptIntrinsicConvolve5x5::kernelF2(const RsExpandKernelDriverInfo *info,
557                                                 uint32_t xstart, uint32_t xend,
558                                                 uint32_t outstep) {
559     RsdCpuScriptIntrinsicConvolve5x5 *cp = (RsdCpuScriptIntrinsicConvolve5x5 *)info->usr;
560     if (!cp->alloc.get()) {
561         ALOGE("Convolve5x5 executed without input, skipping");
562         return;
563     }
564     const uchar *pin = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
565     const size_t stride = cp->alloc->mHal.drvState.lod[0].stride;
566 
567     uint32_t y0 = rsMax((int32_t)info->current.y-2, 0);
568     uint32_t y1 = rsMax((int32_t)info->current.y-1, 0);
569     uint32_t y2 = info->current.y;
570     uint32_t y3 = rsMin((int32_t)info->current.y+1, (int32_t)(info->dim.y-1));
571     uint32_t y4 = rsMin((int32_t)info->current.y+2, (int32_t)(info->dim.y-1));
572 
573     const float2 *py0 = (const float2 *)(pin + stride * y0);
574     const float2 *py1 = (const float2 *)(pin + stride * y1);
575     const float2 *py2 = (const float2 *)(pin + stride * y2);
576     const float2 *py3 = (const float2 *)(pin + stride * y3);
577     const float2 *py4 = (const float2 *)(pin + stride * y4);
578 
579     float2 *out = (float2 *)info->outPtr[0];
580     uint32_t x1 = xstart;
581     uint32_t x2 = xend;
582 
583     while((x1 < x2) && (x1 < 2)) {
584         OneF2(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
585         out++;
586         x1++;
587     }
588 
589 #if 0//defined(ARCH_ARM_HAVE_NEON)
590     if((x1 + 3) < x2) {
591         uint32_t len = (x2 - x1 - 3) >> 1;
592         rsdIntrinsicConvolve5x5_K(out, py0, py1, py2, py3, py4, cp->ip, len);
593         out += len << 1;
594         x1 += len << 1;
595     }
596 #endif
597 
598     while(x1 < x2) {
599         OneF2(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
600         out++;
601         x1++;
602     }
603 }
604 
kernelF1(const RsExpandKernelDriverInfo * info,uint32_t xstart,uint32_t xend,uint32_t outstep)605 void RsdCpuScriptIntrinsicConvolve5x5::kernelF1(const RsExpandKernelDriverInfo *info,
606                                                 uint32_t xstart, uint32_t xend,
607                                                 uint32_t outstep) {
608     RsdCpuScriptIntrinsicConvolve5x5 *cp = (RsdCpuScriptIntrinsicConvolve5x5 *)info->usr;
609     if (!cp->alloc.get()) {
610         ALOGE("Convolve5x5 executed without input, skipping");
611         return;
612     }
613     const uchar *pin = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
614     const size_t stride = cp->alloc->mHal.drvState.lod[0].stride;
615 
616     uint32_t y0 = rsMax((int32_t)info->current.y-2, 0);
617     uint32_t y1 = rsMax((int32_t)info->current.y-1, 0);
618     uint32_t y2 = info->current.y;
619     uint32_t y3 = rsMin((int32_t)info->current.y+1, (int32_t)(info->dim.y-1));
620     uint32_t y4 = rsMin((int32_t)info->current.y+2, (int32_t)(info->dim.y-1));
621 
622     const float *py0 = (const float *)(pin + stride * y0);
623     const float *py1 = (const float *)(pin + stride * y1);
624     const float *py2 = (const float *)(pin + stride * y2);
625     const float *py3 = (const float *)(pin + stride * y3);
626     const float *py4 = (const float *)(pin + stride * y4);
627 
628     float *out = (float *)info->outPtr[0];
629     uint32_t x1 = xstart;
630     uint32_t x2 = xend;
631 
632     while((x1 < x2) && (x1 < 2)) {
633         OneF1(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
634         out++;
635         x1++;
636     }
637 
638 #if 0//defined(ARCH_ARM_HAVE_NEON)
639     if((x1 + 3) < x2) {
640         uint32_t len = (x2 - x1 - 3) >> 1;
641         rsdIntrinsicConvolve5x5_K(out, py0, py1, py2, py3, py4, cp->ip, len);
642         out += len << 1;
643         x1 += len << 1;
644     }
645 #endif
646 
647     while(x1 < x2) {
648         OneF1(info, x1, out, py0, py1, py2, py3, py4, cp->mFp);
649         out++;
650         x1++;
651     }
652 }
653 
RsdCpuScriptIntrinsicConvolve5x5(RsdCpuReferenceImpl * ctx,const Script * s,const Element * e)654 RsdCpuScriptIntrinsicConvolve5x5::RsdCpuScriptIntrinsicConvolve5x5(
655             RsdCpuReferenceImpl *ctx, const Script *s, const Element *e)
656             : RsdCpuScriptIntrinsic(ctx, s, e, RS_SCRIPT_INTRINSIC_ID_CONVOLVE_5x5) {
657 
658     if (e->getType() == RS_TYPE_FLOAT_32) {
659         switch(e->getVectorSize()) {
660         case 1:
661             mRootPtr = &kernelF1;
662             break;
663         case 2:
664             mRootPtr = &kernelF2;
665             break;
666         case 3:
667         case 4:
668             mRootPtr = &kernelF4;
669             break;
670         }
671     } else {
672         switch(e->getVectorSize()) {
673         case 1:
674             mRootPtr = &kernelU1;
675             break;
676         case 2:
677             mRootPtr = &kernelU2;
678             break;
679         case 3:
680         case 4:
681             mRootPtr = &kernelU4;
682             break;
683         }
684     }
685     for(int ct=0; ct < 25; ct++) {
686         mFp[ct] = 1.f / 25.f;
687         mIp[ct] = (short)(mFp[ct] * 256.f);
688     }
689 }
690 
~RsdCpuScriptIntrinsicConvolve5x5()691 RsdCpuScriptIntrinsicConvolve5x5::~RsdCpuScriptIntrinsicConvolve5x5() {
692 }
693 
populateScript(Script * s)694 void RsdCpuScriptIntrinsicConvolve5x5::populateScript(Script *s) {
695     s->mHal.info.exportedVariableCount = 2;
696 }
697 
invokeFreeChildren()698 void RsdCpuScriptIntrinsicConvolve5x5::invokeFreeChildren() {
699     alloc.clear();
700 }
701 
702 
rsdIntrinsic_Convolve5x5(RsdCpuReferenceImpl * ctx,const Script * s,const Element * e)703 RsdCpuScriptImpl * rsdIntrinsic_Convolve5x5(RsdCpuReferenceImpl *ctx,
704                                             const Script *s, const Element *e) {
705 
706     return new RsdCpuScriptIntrinsicConvolve5x5(ctx, s, e);
707 }
708