|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 #include"liboil.h" |
|
18 |
|
19 //Arun's changes |
|
20 typedef struct _OilFunctionImpl OilFunctionImpl; |
|
21 typedef struct _OilFunctionClass OilFunctionClass; |
|
22 typedef void (*OilTestFunction) (OilFunctionClass *klass,OilFunctionImpl *impl); |
|
23 |
|
24 #define OIL_CHECK_PROTOTYPE(a) |
|
25 /** |
|
26 * OilFunctionClass: |
|
27 * |
|
28 * An opaque structure representing a function class. |
|
29 * |
|
30 */ |
|
31 struct _OilFunctionClass { |
|
32 /*< private >*/ |
|
33 void *func; |
|
34 const char *name; |
|
35 const char *desc; |
|
36 OilTestFunction test_func; |
|
37 |
|
38 OilFunctionImpl *first_impl; |
|
39 OilFunctionImpl *reference_impl; |
|
40 |
|
41 OilFunctionImpl *chosen_impl; |
|
42 |
|
43 const char *prototype; |
|
44 }; |
|
45 |
|
46 |
|
47 /** |
|
48 * OilFunctionImpl: |
|
49 * |
|
50 * An opaque structure representing a function implementation. |
|
51 * |
|
52 */ |
|
53 struct _OilFunctionImpl { |
|
54 /*< private >*/ |
|
55 void *next; |
|
56 OilFunctionClass *klass; |
|
57 void *func; |
|
58 unsigned int flags; |
|
59 const char *name; |
|
60 double profile_ave; |
|
61 double profile_std; |
|
62 }; |
|
63 |
|
64 #ifndef OIL_NO_CLASSES |
|
65 /** |
|
66 * OIL_DEFINE_CLASS_FULL: |
|
67 * @klass: name of class to declare (without oil_ prefix) |
|
68 * @string: prototype of class |
|
69 * @test: test function |
|
70 * |
|
71 * Defines a #OilFunctionClass structure for @klass. Classes |
|
72 * defined this way will be automatically at Liboil initialization |
|
73 * time. |
|
74 */ |
|
75 |
|
76 #define OIL_DEFINE_CLASS_FULL(klass, string, test) \ |
|
77 OilFunctionClass _oil_function_class_ ## klass = { \ |
|
78 NULL, \ |
|
79 #klass , \ |
|
80 NULL, \ |
|
81 test, \ |
|
82 NULL, \ |
|
83 NULL, \ |
|
84 NULL, \ |
|
85 string \ |
|
86 }; \ |
|
87 OilFunctionClass *oil_function_class_ptr_ ## klass = \ |
|
88 &_oil_function_class_ ## klass |
|
89 #else |
|
90 #define OIL_DEFINE_CLASS_FULL(klass, string, test) \ |
|
91 OIL_DECLARE_CLASS(klass) |
|
92 #endif |
|
93 |
|
94 /** |
|
95 * OIL_DEFINE_CLASS: |
|
96 * @klass: name of class to declare (without oil_ prefix) |
|
97 * @string: prototype of class |
|
98 * |
|
99 * Defines a #OilFunctionClass structure for @klass. Classes |
|
100 * defined this way will be automatically at Liboil initialization |
|
101 * time. |
|
102 */ |
|
103 #define OIL_DEFINE_CLASS(klass, string) \ |
|
104 OIL_DEFINE_CLASS_FULL (klass, string, NULL) |
|
105 |
|
106 |
|
107 OIL_DEFINE_CLASS (scalarmultiply_f32_ns, "float *d, float *s1, float *s2_1, int n"); |
|
108 |
|
109 OIL_DEFINE_CLASS_FULL (resample_linear_argb, |
|
110 "uint32_t *d_n, uint32_t *s_2xn, int n, uint32_t *i_2", |
|
111 NULL); |
|
112 |
|
113 OIL_DEFINE_CLASS_FULL (resample_linear_u8, |
|
114 "uint8_t *d_n, uint8_t *s_2xn, int n, uint32_t *i_2", |
|
115 NULL); |
|
116 |
|
117 OIL_DEFINE_CLASS_FULL (merge_linear_argb, |
|
118 "uint32_t *d_n, uint32_t *s_n, uint32_t *s2_n, uint32_t *s3_1, int n", |
|
119 NULL); |
|
120 OIL_DEFINE_CLASS_FULL (merge_linear_u8, |
|
121 "uint8_t *d_n, uint8_t *s_n, uint8_t *s2_n, uint32_t *s3_1, int n", |
|
122 NULL); |
|
123 |
|
124 OIL_DEFINE_CLASS(splat_u8_ns,"uint8_t *dest, uint8_t *s1_1, int n"); |
|
125 |
|
126 OIL_DEFINE_CLASS(splat_u8,"uint8_t *dest, int dstr, uint8_t *s1_1, int n"); |
|
127 |
|
128 typedef enum { |
|
129 OIL_IMPL_FLAG_REF = (1<<0), |
|
130 OIL_IMPL_FLAG_OPT = (1<<1), |
|
131 OIL_IMPL_FLAG_ASM = (1<<2), |
|
132 OIL_IMPL_FLAG_DISABLED = (1<<3), |
|
133 OIL_IMPL_FLAG_CMOV = (1<<16), |
|
134 OIL_IMPL_FLAG_MMX = (1<<17), |
|
135 OIL_IMPL_FLAG_SSE = (1<<18), |
|
136 OIL_IMPL_FLAG_MMXEXT = (1<<19), |
|
137 OIL_IMPL_FLAG_SSE2 = (1<<20), |
|
138 OIL_IMPL_FLAG_3DNOW = (1<<21), |
|
139 OIL_IMPL_FLAG_3DNOWEXT = (1<<22), |
|
140 OIL_IMPL_FLAG_SSE3 = (1<<23), |
|
141 OIL_IMPL_FLAG_ALTIVEC = (1<<24), |
|
142 OIL_IMPL_FLAG_EDSP = (1<<25), |
|
143 OIL_IMPL_FLAG_ARM6 = (1<<26), |
|
144 OIL_IMPL_FLAG_VFP = (1<<27), |
|
145 OIL_IMPL_FLAG_SSSE3 = (1<<28) |
|
146 } OilImplFlag; |
|
147 |
|
148 #ifndef OIL_OPT_MANGLE |
|
149 #define OIL_OPT_MANGLE(a) a |
|
150 #define OIL_OPT_FLAG_MANGLE(a) a |
|
151 #else |
|
152 #define OIL_NO_CLASSES |
|
153 #define OIL_OPT_FLAG_MANGLE(a) (((a)&(~OIL_IMPL_FLAG_REF)) | OIL_IMPL_FLAG_OPT) |
|
154 #endif |
|
155 #ifndef OIL_OPT_SUFFIX |
|
156 #define OIL_OPT_SUFFIX |
|
157 #endif |
|
158 |
|
159 /** |
|
160 * OIL_DEFINE_IMPL_FULL: |
|
161 * @function: name of function |
|
162 * @klass: name of class to declare (without oil_ prefix) |
|
163 * @flags: implementation flags and CPU requirements |
|
164 * |
|
165 * Defines a #OilFunctionImpl structure for the function @function |
|
166 * and class @klass. CPU-dependent flags in @flags will indicate |
|
167 * that this implementation requires the given CPU flags. |
|
168 */ |
|
169 #define OIL_DEFINE_IMPL_FULL(function,klass,flags) \ |
|
170 OilFunctionImpl OIL_OPT_MANGLE(_oil_function_impl_ ## function) = { \ |
|
171 NULL, \ |
|
172 &_oil_function_class_ ## klass , \ |
|
173 (void *)function, \ |
|
174 OIL_OPT_FLAG_MANGLE(flags), \ |
|
175 #function OIL_OPT_SUFFIX \ |
|
176 } \ |
|
177 OIL_CHECK_PROTOTYPE(;_oil_type_ ## klass _ignore_me_ ## function = function) |
|
178 |
|
179 /** |
|
180 * OIL_DEFINE_IMPL: |
|
181 * @function: name of function |
|
182 * @klass: name of class to declare (without oil_ prefix) |
|
183 * |
|
184 * Shorthand for defining a C implementation. See OIL_DEFINE_IMPL_FULL(). |
|
185 */ |
|
186 #define OIL_DEFINE_IMPL(function,klass) \ |
|
187 OIL_DEFINE_IMPL_FULL(function,klass,0) |
|
188 /** |
|
189 * OIL_DEFINE_IMPL_REF: |
|
190 * @function: name of function |
|
191 * @klass: name of class to declare (without oil_ prefix) |
|
192 * |
|
193 * Shorthand for defining a reference implementation. See OIL_DEFINE_IMPL_FULL(). |
|
194 */ |
|
195 #define OIL_DEFINE_IMPL_REF(function,klass) \ |
|
196 OIL_DEFINE_IMPL_FULL(function,klass,OIL_IMPL_FLAG_REF) |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 typedef void (*_oil_type_scalarmultiply_f32_ns)(float * d, const float * s1, const float * s2_1, int n); |
|
202 //#define oil_scalarmultiply_f32_ns ((_oil_type_scalarmultiply_f32_ns)(*(void **)oil_function_class_ptr_scalarmultiply_f32_ns)) |
|
203 |
|
204 |
|
205 |
|
206 #define OIL_GET(ptr, offset, type) (*(type *)((uint8_t *)(ptr) + (offset)) ) |
|
207 |
|
208 /**************'_oil_resample_linear_u8'****************************/ |
|
209 #ifdef __SYMBIAN32__ |
|
210 EXPORT_C |
|
211 #endif |
|
212 |
|
213 |
|
214 static void |
|
215 resample_linear_u8_ref (uint8_t *dest, uint8_t *src, int n, |
|
216 uint32_t *in) |
|
217 { |
|
218 int acc = in[0]; |
|
219 int increment = in[1]; |
|
220 int i; |
|
221 int j; |
|
222 int x; |
|
223 |
|
224 for(i=0;i<n;i++){ |
|
225 j = acc>>16; |
|
226 x = (acc&0xffff)>>8; |
|
227 dest[i] = (src[j]*(256-x) + src[j+1]*x) >> 8; |
|
228 |
|
229 acc += increment; |
|
230 } |
|
231 |
|
232 in[0] = acc; |
|
233 } |
|
234 |
|
235 /************************'_oil_resample_linear_argb'***************************/ |
|
236 static void |
|
237 resample_linear_argb_ref (uint32_t *d, uint32_t *s, int n, uint32_t *in) |
|
238 { |
|
239 uint8_t *src = (uint8_t *)s; |
|
240 uint8_t *dest = (uint8_t *)d; |
|
241 int acc = in[0]; |
|
242 int increment = in[1]; |
|
243 int i; |
|
244 int j; |
|
245 int x; |
|
246 |
|
247 for(i=0;i<n;i++){ |
|
248 j = acc>>16; |
|
249 x = (acc&0xffff)>>8; |
|
250 dest[4*i+0] = (src[4*j+0]*(256-x) + src[4*j+4]*x) >> 8; |
|
251 dest[4*i+1] = (src[4*j+1]*(256-x) + src[4*j+5]*x) >> 8; |
|
252 dest[4*i+2] = (src[4*j+2]*(256-x) + src[4*j+6]*x) >> 8; |
|
253 dest[4*i+3] = (src[4*j+3]*(256-x) + src[4*j+7]*x) >> 8; |
|
254 |
|
255 acc += increment; |
|
256 } |
|
257 |
|
258 in[0] = acc; |
|
259 } |
|
260 |
|
261 /****************** '_oil_merge_linear_argb'**************************/ |
|
262 static void |
|
263 merge_linear_argb_ref (uint32_t *d, uint32_t *s1, uint32_t *s2, |
|
264 uint32_t *src3, int n) |
|
265 { |
|
266 uint8_t *src1 = (uint8_t *)s1; |
|
267 uint8_t *src2 = (uint8_t *)s2; |
|
268 uint8_t *dest = (uint8_t *)d; |
|
269 int i; |
|
270 int x = src3[0]; |
|
271 |
|
272 for(i=0;i<n;i++){ |
|
273 dest[4*i+0] = (src1[4*i+0]*(256-x) + src2[4*i+0]*x) >> 8; |
|
274 dest[4*i+1] = (src1[4*i+1]*(256-x) + src2[4*i+1]*x) >> 8; |
|
275 dest[4*i+2] = (src1[4*i+2]*(256-x) + src2[4*i+2]*x) >> 8; |
|
276 dest[4*i+3] = (src1[4*i+3]*(256-x) + src2[4*i+3]*x) >> 8; |
|
277 } |
|
278 } |
|
279 |
|
280 static void |
|
281 merge_linear_u8_ref (uint8_t *dest, uint8_t *src1, uint8_t *src2, |
|
282 uint32_t *src3, int n) |
|
283 { |
|
284 int i; |
|
285 int x = src3[0]; |
|
286 |
|
287 for(i=0;i<n;i++){ |
|
288 dest[i] = (src1[i]*(256-x) + src2[i]*x) >> 8; |
|
289 } |
|
290 } |
|
291 |
|
292 static void splat_u8_ref (uint8_t *dest, int dstr, uint8_t *param, int n) |
|
293 { |
|
294 int i; |
|
295 for(i=0;i<n;i++){ |
|
296 OIL_GET(dest,i*dstr, uint8_t) = *param; |
|
297 } |
|
298 } |
|
299 |
|
300 static void splat_u8_ns_ref (uint8_t *dest, uint8_t *param, int n) |
|
301 { |
|
302 int i; |
|
303 for(i=0;i<n;i++){ |
|
304 dest[i] = *param; |
|
305 } |
|
306 } |
|
307 |
|
308 static void |
|
309 scalarmultiply_f32_ns_ref (float *dest, float *src1, float *src2, int n) |
|
310 { |
|
311 int i; |
|
312 |
|
313 for(i=0;i<n;i++){ |
|
314 dest[i] = src1[i] * src2[0]; |
|
315 } |
|
316 } |
|
317 |
|
318 /********oil_splat_u8*******/ |
|
319 /* |
|
320 EXPORT_C void splat_u8_ref (uint8_t *dest, int dstr, uint8_t *param, int n) |
|
321 { |
|
322 int i; |
|
323 for(i=0;i<n;i++){ |
|
324 OIL_GET(dest,i*dstr, uint8_t) = *param; |
|
325 } |
|
326 } |
|
327 */ |
|
328 |
|
329 unsigned long oil_cpu_flags; |
|
330 |
|
331 /** |
|
332 * oil_cpu_get_flags: |
|
333 * |
|
334 * Returns a bitmask containing the available CPU features. |
|
335 * |
|
336 * Returns: the CPU features. |
|
337 */ |
|
338 #ifdef __SYMBIAN32__ |
|
339 EXPORT_C |
|
340 #endif |
|
341 |
|
342 unsigned int |
|
343 oil_cpu_get_flags (void) |
|
344 { |
|
345 return oil_cpu_flags; |
|
346 } |
|
347 |
|
348 /** |
|
349 * OIL_CPU_FLAG_MASK: |
|
350 * |
|
351 * Mask describing which bits in #OilImplFlag depend on the current |
|
352 * CPU. |
|
353 */ |
|
354 #define OIL_CPU_FLAG_MASK 0xffff0000 |
|
355 |
|
356 /** |
|
357 * oil_impl_is_runnable: |
|
358 * @impl: an @OilFunctionImpl |
|
359 * |
|
360 * Determines whether the function implementation given by @impl |
|
361 * can be executed by the current CPU. |
|
362 * |
|
363 * Returns: 1 if the implementation can be executed, otherwise 0 |
|
364 */ |
|
365 #ifdef __SYMBIAN32__ |
|
366 EXPORT_C |
|
367 #endif |
|
368 |
|
369 int |
|
370 oil_impl_is_runnable (OilFunctionImpl *impl) |
|
371 { |
|
372 unsigned int oil_cpu_flags = oil_cpu_get_flags(); |
|
373 |
|
374 if ((impl->flags & OIL_CPU_FLAG_MASK) & (~oil_cpu_flags)) |
|
375 return 0; |
|
376 return 1; |
|
377 } |
|
378 |
|
379 /** |
|
380 * oil_class_optimize: |
|
381 * @klass: a function class |
|
382 * |
|
383 * Tests and profiles each implementation for the given function |
|
384 * class. Testing compares the output of running each implementation |
|
385 * on random input against the reference implementation for the |
|
386 * same input. |
|
387 */ |
|
388 #ifdef __SYMBIAN32__ |
|
389 EXPORT_C |
|
390 #endif |
|
391 |
|
392 void |
|
393 oil_class_optimize (OilFunctionClass * klass) |
|
394 { |
|
395 OilFunctionImpl *impl; |
|
396 OilFunctionImpl *min_impl; |
|
397 int ret; |
|
398 |
|
399 |
|
400 if (klass->reference_impl == NULL) { |
|
401 return; |
|
402 } |
|
403 if (klass->first_impl == NULL) { |
|
404 return; |
|
405 } |
|
406 |
|
407 min_impl = NULL; |
|
408 |
|
409 for (impl = klass->first_impl; impl; impl = impl->next) { |
|
410 if (!oil_impl_is_runnable (impl)) |
|
411 continue; |
|
412 } |
|
413 |
|
414 if (min_impl == NULL) { |
|
415 return; |
|
416 } |
|
417 |
|
418 klass->chosen_impl = min_impl; |
|
419 klass->func = min_impl->func; |
|
420 |
|
421 } |
|
422 |
|
423 |
|
424 #ifdef __SYMBIAN32__ |
|
425 EXPORT_C |
|
426 #endif |
|
427 void oil_scalarmultiply_f32_ns (float * d, const float * s1, const float * s2_1, int n) |
|
428 { |
|
429 /* |
|
430 if (_oil_function_class_scalarmultiply_f32_ns.func == NULL) { |
|
431 oil_class_optimize (&_oil_function_class_scalarmultiply_f32_ns); |
|
432 } |
|
433 */ |
|
434 scalarmultiply_f32_ns_ref(d,(float*) s1,(float*) s2_1, n); |
|
435 //((void (*)(float * d, const float * s1, const float * s2_1, int n))(_oil_function_class_scalarmultiply_f32_ns.func))(d, s1, s2_1, n); |
|
436 } |
|
437 #ifdef __SYMBIAN32__ |
|
438 EXPORT_C |
|
439 #endif |
|
440 |
|
441 void |
|
442 oil_merge_linear_argb (uint32_t * d_n, const uint32_t * s_n, const uint32_t * s2_n, const uint32_t * s3_1, int n) |
|
443 { |
|
444 if (_oil_function_class_merge_linear_argb.func == NULL) { |
|
445 oil_class_optimize (&_oil_function_class_merge_linear_argb); |
|
446 } |
|
447 ((void (*)(uint32_t * d_n, const uint32_t * s_n, const uint32_t * s2_n, const uint32_t * s3_1, int n))(_oil_function_class_merge_linear_argb.func))(d_n, s_n, s2_n, s3_1, n); |
|
448 } |
|
449 #ifdef __SYMBIAN32__ |
|
450 EXPORT_C |
|
451 #endif |
|
452 void |
|
453 oil_merge_linear_u8 (uint8_t * d_n, const uint8_t * s_n, const uint8_t * s2_n, const uint32_t * s3_1, int n) |
|
454 { |
|
455 if (_oil_function_class_merge_linear_u8.func == NULL) { |
|
456 oil_class_optimize (&_oil_function_class_merge_linear_u8); |
|
457 } |
|
458 ((void (*)(uint8_t * d_n, const uint8_t * s_n, const uint8_t * s2_n, const uint32_t * s3_1, int n))(_oil_function_class_merge_linear_u8.func))(d_n, s_n, s2_n, s3_1, n); |
|
459 } |
|
460 #ifdef __SYMBIAN32__ |
|
461 EXPORT_C |
|
462 #endif |
|
463 |
|
464 |
|
465 void |
|
466 oil_resample_linear_argb (uint32_t * d_n, const uint32_t * s_2xn, int n, uint32_t * i_2) |
|
467 { |
|
468 if (_oil_function_class_resample_linear_argb.func == NULL) { |
|
469 oil_class_optimize (&_oil_function_class_resample_linear_argb); |
|
470 } |
|
471 ((void (*)(uint32_t * d_n, const uint32_t * s_2xn, int n, uint32_t * i_2))(_oil_function_class_resample_linear_argb.func))(d_n, s_2xn, n, i_2); |
|
472 } |
|
473 #ifdef __SYMBIAN32__ |
|
474 EXPORT_C |
|
475 #endif |
|
476 void |
|
477 oil_resample_linear_u8 (uint8_t * d_n, const uint8_t * s_2xn, int n, uint32_t * i_2) |
|
478 { |
|
479 if (_oil_function_class_resample_linear_u8.func == NULL) { |
|
480 oil_class_optimize (&_oil_function_class_resample_linear_u8); |
|
481 } |
|
482 ((void (*)(uint8_t * d_n, const uint8_t * s_2xn, int n, uint32_t * i_2))(_oil_function_class_resample_linear_u8.func))(d_n, s_2xn, n, i_2); |
|
483 } |
|
484 #ifdef __SYMBIAN32__ |
|
485 EXPORT_C |
|
486 #endif |
|
487 |
|
488 |
|
489 void |
|
490 oil_splat_u8 (uint8_t * dest, int dstr, const uint8_t * s1_1, int n) |
|
491 { |
|
492 if (_oil_function_class_splat_u8.func == NULL) { |
|
493 oil_class_optimize (&_oil_function_class_splat_u8); |
|
494 } |
|
495 ((void (*)(uint8_t * dest, int dstr, const uint8_t * s1_1, int n))(_oil_function_class_splat_u8.func))(dest, dstr, s1_1, n); |
|
496 } |
|
497 #ifdef __SYMBIAN32__ |
|
498 EXPORT_C |
|
499 #endif |
|
500 |
|
501 void |
|
502 oil_splat_u8_ns (uint8_t * dest, const uint8_t * s1_1, int n) |
|
503 { |
|
504 if (_oil_function_class_splat_u8_ns.func == NULL) { |
|
505 oil_class_optimize (&_oil_function_class_splat_u8_ns); |
|
506 } |
|
507 ((void (*)(uint8_t * dest, const uint8_t * s1_1, int n))(_oil_function_class_splat_u8_ns.func))(dest, s1_1, n); |
|
508 } |
|
509 |
|
510 OIL_DEFINE_IMPL_REF (scalarmultiply_f32_ns_ref, scalarmultiply_f32_ns); |
|
511 OIL_DEFINE_IMPL_REF (resample_linear_u8_ref, resample_linear_u8); |
|
512 OIL_DEFINE_IMPL_REF (resample_linear_argb_ref, resample_linear_argb); |
|
513 OIL_DEFINE_IMPL_REF (merge_linear_argb_ref, merge_linear_argb); |
|
514 OIL_DEFINE_IMPL_REF (merge_linear_u8_ref, merge_linear_u8); |
|
515 OIL_DEFINE_IMPL_REF(splat_u8_ref, splat_u8); |
|
516 OIL_DEFINE_IMPL_REF(splat_u8_ns_ref, splat_u8_ns); |
|
517 |