1/*
2 * Copyright © 2010 Nokia Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Author:  Siarhei Siamashka (siarhei.siamashka@nokia.com)
24 */
25
26#ifndef PIXMAN_ARM_COMMON_H
27#define PIXMAN_ARM_COMMON_H
28
29#include "pixman-inlines.h"
30
31/* Define some macros which can expand into proxy functions between
32 * ARM assembly optimized functions and the rest of pixman fast path API.
33 *
34 * All the low level ARM assembly functions have to use ARM EABI
35 * calling convention and take up to 8 arguments:
36 *    width, height, dst, dst_stride, src, src_stride, mask, mask_stride
37 *
38 * The arguments are ordered with the most important coming first (the
39 * first 4 arguments are passed to function in registers, the rest are
40 * on stack). The last arguments are optional, for example if the
41 * function is not using mask, then 'mask' and 'mask_stride' can be
42 * omitted when doing a function call.
43 *
44 * Arguments 'src' and 'mask' contain either a pointer to the top left
45 * pixel of the composited rectangle or a pixel color value depending
46 * on the function type. In the case of just a color value (solid source
47 * or mask), the corresponding stride argument is unused.
48 */
49
50#define SKIP_ZERO_SRC  1
51#define SKIP_ZERO_MASK 2
52
53#define PIXMAN_ARM_BIND_FAST_PATH_SRC_DST(cputype, name,                \
54                                          src_type, src_cnt,            \
55                                          dst_type, dst_cnt)            \
56void                                                                    \
57pixman_composite_##name##_asm_##cputype (int32_t   w,                   \
58                                         int32_t   h,                   \
59                                         dst_type *dst,                 \
60                                         int32_t   dst_stride,          \
61                                         src_type *src,                 \
62                                         int32_t   src_stride);         \
63                                                                        \
64static void                                                             \
65cputype##_composite_##name (pixman_implementation_t *imp,               \
66                            pixman_composite_info_t *info)              \
67{                                                                       \
68    PIXMAN_COMPOSITE_ARGS (info);                                       \
69    dst_type *dst_line;							\
70    src_type *src_line;                                                 \
71    int32_t dst_stride, src_stride;                                     \
72                                                                        \
73    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type,           \
74                           src_stride, src_line, src_cnt);              \
75    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type,        \
76                           dst_stride, dst_line, dst_cnt);              \
77                                                                        \
78    pixman_composite_##name##_asm_##cputype (width, height,             \
79                                             dst_line, dst_stride,      \
80                                             src_line, src_stride);     \
81}
82
83#define PIXMAN_ARM_BIND_FAST_PATH_N_DST(flags, cputype, name,           \
84                                        dst_type, dst_cnt)              \
85void                                                                    \
86pixman_composite_##name##_asm_##cputype (int32_t    w,                  \
87                                         int32_t    h,                  \
88                                         dst_type  *dst,                \
89                                         int32_t    dst_stride,         \
90                                         uint32_t   src);               \
91                                                                        \
92static void                                                             \
93cputype##_composite_##name (pixman_implementation_t *imp,               \
94			    pixman_composite_info_t *info)              \
95{                                                                       \
96    PIXMAN_COMPOSITE_ARGS (info);					\
97    dst_type  *dst_line;                                                \
98    int32_t    dst_stride;                                              \
99    uint32_t   src;                                                     \
100                                                                        \
101    src = _pixman_image_get_solid (					\
102	imp, src_image, dest_image->bits.format);			\
103                                                                        \
104    if ((flags & SKIP_ZERO_SRC) && src == 0)                            \
105	return;                                                         \
106                                                                        \
107    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type,        \
108                           dst_stride, dst_line, dst_cnt);              \
109                                                                        \
110    pixman_composite_##name##_asm_##cputype (width, height,             \
111                                             dst_line, dst_stride,      \
112                                             src);                      \
113}
114
115#define PIXMAN_ARM_BIND_FAST_PATH_N_MASK_DST(flags, cputype, name,      \
116                                             mask_type, mask_cnt,       \
117                                             dst_type, dst_cnt)         \
118void                                                                    \
119pixman_composite_##name##_asm_##cputype (int32_t    w,                  \
120                                         int32_t    h,                  \
121                                         dst_type  *dst,                \
122                                         int32_t    dst_stride,         \
123                                         uint32_t   src,                \
124                                         int32_t    unused,             \
125                                         mask_type *mask,               \
126                                         int32_t    mask_stride);       \
127                                                                        \
128static void                                                             \
129cputype##_composite_##name (pixman_implementation_t *imp,               \
130                            pixman_composite_info_t *info)              \
131{                                                                       \
132    PIXMAN_COMPOSITE_ARGS (info);                                       \
133    dst_type  *dst_line;						\
134    mask_type *mask_line;                                               \
135    int32_t    dst_stride, mask_stride;                                 \
136    uint32_t   src;                                                     \
137                                                                        \
138    src = _pixman_image_get_solid (					\
139	imp, src_image, dest_image->bits.format);			\
140                                                                        \
141    if ((flags & SKIP_ZERO_SRC) && src == 0)                            \
142	return;                                                         \
143                                                                        \
144    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type,        \
145                           dst_stride, dst_line, dst_cnt);              \
146    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type,       \
147                           mask_stride, mask_line, mask_cnt);           \
148                                                                        \
149    pixman_composite_##name##_asm_##cputype (width, height,             \
150                                             dst_line, dst_stride,      \
151                                             src, 0,                    \
152                                             mask_line, mask_stride);   \
153}
154
155#define PIXMAN_ARM_BIND_FAST_PATH_SRC_N_DST(flags, cputype, name,       \
156                                            src_type, src_cnt,          \
157                                            dst_type, dst_cnt)          \
158void                                                                    \
159pixman_composite_##name##_asm_##cputype (int32_t    w,                  \
160                                         int32_t    h,                  \
161                                         dst_type  *dst,                \
162                                         int32_t    dst_stride,         \
163                                         src_type  *src,                \
164                                         int32_t    src_stride,         \
165                                         uint32_t   mask);              \
166                                                                        \
167static void                                                             \
168cputype##_composite_##name (pixman_implementation_t *imp,               \
169                            pixman_composite_info_t *info)              \
170{                                                                       \
171    PIXMAN_COMPOSITE_ARGS (info);                                       \
172    dst_type  *dst_line;						\
173    src_type  *src_line;                                                \
174    int32_t    dst_stride, src_stride;                                  \
175    uint32_t   mask;                                                    \
176                                                                        \
177    mask = _pixman_image_get_solid (					\
178	imp, mask_image, dest_image->bits.format);			\
179                                                                        \
180    if ((flags & SKIP_ZERO_MASK) && mask == 0)                          \
181	return;                                                         \
182                                                                        \
183    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type,        \
184                           dst_stride, dst_line, dst_cnt);              \
185    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type,           \
186                           src_stride, src_line, src_cnt);              \
187                                                                        \
188    pixman_composite_##name##_asm_##cputype (width, height,             \
189                                             dst_line, dst_stride,      \
190                                             src_line, src_stride,      \
191                                             mask);                     \
192}
193
194#define PIXMAN_ARM_BIND_FAST_PATH_SRC_MASK_DST(cputype, name,           \
195                                               src_type, src_cnt,       \
196                                               mask_type, mask_cnt,     \
197                                               dst_type, dst_cnt)       \
198void                                                                    \
199pixman_composite_##name##_asm_##cputype (int32_t    w,                  \
200                                         int32_t    h,                  \
201                                         dst_type  *dst,                \
202                                         int32_t    dst_stride,         \
203                                         src_type  *src,                \
204                                         int32_t    src_stride,         \
205                                         mask_type *mask,               \
206                                         int32_t    mask_stride);       \
207                                                                        \
208static void                                                             \
209cputype##_composite_##name (pixman_implementation_t *imp,               \
210                            pixman_composite_info_t *info)              \
211{                                                                       \
212    PIXMAN_COMPOSITE_ARGS (info);                                       \
213    dst_type  *dst_line;						\
214    src_type  *src_line;                                                \
215    mask_type *mask_line;                                               \
216    int32_t    dst_stride, src_stride, mask_stride;                     \
217                                                                        \
218    PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type,        \
219                           dst_stride, dst_line, dst_cnt);              \
220    PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, src_type,           \
221                           src_stride, src_line, src_cnt);              \
222    PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type,       \
223                           mask_stride, mask_line, mask_cnt);           \
224                                                                        \
225    pixman_composite_##name##_asm_##cputype (width, height,             \
226                                             dst_line, dst_stride,      \
227                                             src_line, src_stride,      \
228                                             mask_line, mask_stride);   \
229}
230
231#define PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_DST(cputype, name, op,             \
232                                               src_type, dst_type)            \
233void                                                                          \
234pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (                \
235                                                   int32_t          w,        \
236                                                   dst_type *       dst,      \
237                                                   const src_type * src,      \
238                                                   pixman_fixed_t   vx,       \
239                                                   pixman_fixed_t   unit_x,   \
240                                                   pixman_fixed_t   max_vx);  \
241                                                                              \
242static force_inline void                                                      \
243scaled_nearest_scanline_##cputype##_##name##_##op (dst_type *       pd,       \
244                                                   const src_type * ps,       \
245                                                   int32_t          w,        \
246                                                   pixman_fixed_t   vx,       \
247                                                   pixman_fixed_t   unit_x,   \
248                                                   pixman_fixed_t   max_vx,   \
249                                                   pixman_bool_t    zero_src) \
250{                                                                             \
251    pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (w, pd, ps,  \
252                                                                  vx, unit_x, \
253                                                                  max_vx);    \
254}                                                                             \
255                                                                              \
256FAST_NEAREST_MAINLOOP (cputype##_##name##_cover_##op,                         \
257                       scaled_nearest_scanline_##cputype##_##name##_##op,     \
258                       src_type, dst_type, COVER)                             \
259FAST_NEAREST_MAINLOOP (cputype##_##name##_none_##op,                          \
260                       scaled_nearest_scanline_##cputype##_##name##_##op,     \
261                       src_type, dst_type, NONE)                              \
262FAST_NEAREST_MAINLOOP (cputype##_##name##_pad_##op,                           \
263                       scaled_nearest_scanline_##cputype##_##name##_##op,     \
264                       src_type, dst_type, PAD)                               \
265FAST_NEAREST_MAINLOOP (cputype##_##name##_normal_##op,                        \
266                       scaled_nearest_scanline_##cputype##_##name##_##op,     \
267                       src_type, dst_type, NORMAL)
268
269/* Provide entries for the fast path table */
270#define PIXMAN_ARM_SIMPLE_NEAREST_FAST_PATH(op,s,d,func)                      \
271    SIMPLE_NEAREST_FAST_PATH_COVER (op,s,d,func),                             \
272    SIMPLE_NEAREST_FAST_PATH_NONE (op,s,d,func),                              \
273    SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func),                               \
274    SIMPLE_NEAREST_FAST_PATH_NORMAL (op,s,d,func)
275
276#define PIXMAN_ARM_BIND_SCALED_NEAREST_SRC_A8_DST(flags, cputype, name, op,   \
277                                                  src_type, dst_type)         \
278void                                                                          \
279pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (                \
280                                                   int32_t          w,        \
281                                                   dst_type *       dst,      \
282                                                   const src_type * src,      \
283                                                   pixman_fixed_t   vx,       \
284                                                   pixman_fixed_t   unit_x,   \
285                                                   pixman_fixed_t   max_vx,   \
286                                                   const uint8_t *  mask);    \
287                                                                              \
288static force_inline void                                                      \
289scaled_nearest_scanline_##cputype##_##name##_##op (const uint8_t *  mask,     \
290                                                   dst_type *       pd,       \
291                                                   const src_type * ps,       \
292                                                   int32_t          w,        \
293                                                   pixman_fixed_t   vx,       \
294                                                   pixman_fixed_t   unit_x,   \
295                                                   pixman_fixed_t   max_vx,   \
296                                                   pixman_bool_t    zero_src) \
297{                                                                             \
298    if ((flags & SKIP_ZERO_SRC) && zero_src)                                  \
299	return;                                                               \
300    pixman_scaled_nearest_scanline_##name##_##op##_asm_##cputype (w, pd, ps,  \
301                                                                  vx, unit_x, \
302                                                                  max_vx,     \
303                                                                  mask);      \
304}                                                                             \
305                                                                              \
306FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_cover_##op,                  \
307                              scaled_nearest_scanline_##cputype##_##name##_##op,\
308                              src_type, uint8_t, dst_type, COVER, TRUE, FALSE)\
309FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_none_##op,                   \
310                              scaled_nearest_scanline_##cputype##_##name##_##op,\
311                              src_type, uint8_t, dst_type, NONE, TRUE, FALSE) \
312FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_pad_##op,                    \
313                              scaled_nearest_scanline_##cputype##_##name##_##op,\
314                              src_type, uint8_t, dst_type, PAD, TRUE, FALSE)  \
315FAST_NEAREST_MAINLOOP_COMMON (cputype##_##name##_normal_##op,                 \
316                              scaled_nearest_scanline_##cputype##_##name##_##op,\
317                              src_type, uint8_t, dst_type, NORMAL, TRUE, FALSE)
318
319/* Provide entries for the fast path table */
320#define PIXMAN_ARM_SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func)              \
321    SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER (op,s,d,func),                     \
322    SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE (op,s,d,func),                      \
323    SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func),                       \
324    SIMPLE_NEAREST_A8_MASK_FAST_PATH_NORMAL (op,s,d,func)
325
326/*****************************************************************************/
327
328#define PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_DST(flags, cputype, name, op,     \
329                                                src_type, dst_type)           \
330void                                                                          \
331pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype (               \
332                                                dst_type *       dst,         \
333                                                const src_type * top,         \
334                                                const src_type * bottom,      \
335                                                int              wt,          \
336                                                int              wb,          \
337                                                pixman_fixed_t   x,           \
338                                                pixman_fixed_t   ux,          \
339                                                int              width);      \
340                                                                              \
341static force_inline void                                                      \
342scaled_bilinear_scanline_##cputype##_##name##_##op (                          \
343                                                dst_type *       dst,         \
344                                                const uint32_t * mask,        \
345                                                const src_type * src_top,     \
346                                                const src_type * src_bottom,  \
347                                                int32_t          w,           \
348                                                int              wt,          \
349                                                int              wb,          \
350                                                pixman_fixed_t   vx,          \
351                                                pixman_fixed_t   unit_x,      \
352                                                pixman_fixed_t   max_vx,      \
353                                                pixman_bool_t    zero_src)    \
354{                                                                             \
355    if ((flags & SKIP_ZERO_SRC) && zero_src)                                  \
356	return;                                                               \
357    pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype (           \
358                            dst, src_top, src_bottom, wt, wb, vx, unit_x, w); \
359}                                                                             \
360                                                                              \
361FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op,                 \
362                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
363                       src_type, uint32_t, dst_type, COVER, FLAG_NONE)        \
364FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op,                  \
365                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
366                       src_type, uint32_t, dst_type, NONE, FLAG_NONE)         \
367FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op,                   \
368                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
369                       src_type, uint32_t, dst_type, PAD, FLAG_NONE)          \
370FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op,                \
371                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
372                       src_type, uint32_t, dst_type, NORMAL,                  \
373                       FLAG_NONE)
374
375
376#define PIXMAN_ARM_BIND_SCALED_BILINEAR_SRC_A8_DST(flags, cputype, name, op,  \
377                                                src_type, dst_type)           \
378void                                                                          \
379pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype (               \
380                                                dst_type *       dst,         \
381                                                const uint8_t *  mask,        \
382                                                const src_type * top,         \
383                                                const src_type * bottom,      \
384                                                int              wt,          \
385                                                int              wb,          \
386                                                pixman_fixed_t   x,           \
387                                                pixman_fixed_t   ux,          \
388                                                int              width);      \
389                                                                              \
390static force_inline void                                                      \
391scaled_bilinear_scanline_##cputype##_##name##_##op (                          \
392                                                dst_type *       dst,         \
393                                                const uint8_t *  mask,        \
394                                                const src_type * src_top,     \
395                                                const src_type * src_bottom,  \
396                                                int32_t          w,           \
397                                                int              wt,          \
398                                                int              wb,          \
399                                                pixman_fixed_t   vx,          \
400                                                pixman_fixed_t   unit_x,      \
401                                                pixman_fixed_t   max_vx,      \
402                                                pixman_bool_t    zero_src)    \
403{                                                                             \
404    if ((flags & SKIP_ZERO_SRC) && zero_src)                                  \
405	return;                                                                   \
406    pixman_scaled_bilinear_scanline_##name##_##op##_asm_##cputype (           \
407                      dst, mask, src_top, src_bottom, wt, wb, vx, unit_x, w); \
408}                                                                             \
409                                                                              \
410FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_cover_##op,                 \
411                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
412                       src_type, uint8_t, dst_type, COVER,                    \
413                       FLAG_HAVE_NON_SOLID_MASK)                              \
414FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_none_##op,                  \
415                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
416                       src_type, uint8_t, dst_type, NONE,                     \
417                       FLAG_HAVE_NON_SOLID_MASK)                              \
418FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_pad_##op,                   \
419                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
420                       src_type, uint8_t, dst_type, PAD,                      \
421                       FLAG_HAVE_NON_SOLID_MASK)                              \
422FAST_BILINEAR_MAINLOOP_COMMON (cputype##_##name##_normal_##op,                \
423                       scaled_bilinear_scanline_##cputype##_##name##_##op,    \
424                       src_type, uint8_t, dst_type, NORMAL,                   \
425                       FLAG_HAVE_NON_SOLID_MASK)
426
427
428#endif
429