2 * Copyright © 2004 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
29 #include "pixman-private.h"
30 #include "pixman-accessor.h"
33 * Step across a small sample grid gap
35 #define RENDER_EDGE_STEP_SMALL(edge) \
37 edge->x += edge->stepx_small; \
38 edge->e += edge->dx_small; \
41 edge->e -= edge->dy; \
42 edge->x += edge->signdx; \
47 * Step across a large sample grid gap
49 #define RENDER_EDGE_STEP_BIG(edge) \
51 edge->x += edge->stepx_big; \
52 edge->e += edge->dx_big; \
55 edge->e -= edge->dy; \
56 edge->x += edge->signdx; \
60 #ifdef PIXMAN_FB_ACCESSORS
61 #define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
63 #define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
71 #define RASTERIZE_EDGES rasterize_edges_4
73 #ifndef WORDS_BIGENDIAN
74 #define SHIFT_4(o) ((o) << 2)
76 #define SHIFT_4(o) ((1 - (o)) << 2)
79 #define GET_4(x, o) (((x) >> SHIFT_4 (o)) & 0xf)
80 #define PUT_4(x, o, v) \
81 (((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
83 #define DEFINE_ALPHA(line, x) \
84 uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \
87 #define STEP_ALPHA ((__ap += __ao), (__ao ^= 1))
89 #define ADD_ALPHA(a) \
91 uint8_t __o = READ (image, __ap); \
92 uint8_t __a = (a) + GET_4 (__o, __ao); \
93 WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
96 #include "pixman-edge-imp.h"
101 #undef RASTERIZE_EDGES
110 #define RASTERIZE_EDGES rasterize_edges_1
112 #include "pixman-edge-imp.h"
114 #undef RASTERIZE_EDGES
121 static force_inline uint8_t
130 #define ADD_SATURATE_8(buf, val, length) \
133 int i__ = (length); \
134 uint8_t *buf__ = (buf); \
139 WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
145 * We want to detect the case where we add the same value to a long
146 * span of pixels. The triangles on the end are filled in while we
147 * count how many sub-pixel scanlines contribute to the middle section.
149 * +--------------------------+
151 * +------------------+
153 * fill_start fill_end
156 rasterize_edges_8 (pixman_image_t *image,
162 pixman_fixed_t y = t;
164 int fill_start = -1, fill_end = -1;
166 uint32_t *buf = (image)->bits.bits;
167 int stride = (image)->bits.rowstride;
168 int width = (image)->bits.width;
170 line = buf + pixman_fixed_to_int (y) * stride;
174 uint8_t *ap = (uint8_t *) line;
175 pixman_fixed_t lx, rx;
185 if (pixman_fixed_to_int (rx) >= width)
187 /* Use the last pixel of the scanline, covered 100%.
188 * We can't use the first pixel following the scanline,
189 * because accessing it could result in a buffer overrun.
191 rx = pixman_int_to_fixed (width) - 1;
194 /* Skip empty (or backwards) sections */
199 /* Find pixel bounds for span. */
200 lxi = pixman_fixed_to_int (lx);
201 rxi = pixman_fixed_to_int (rx);
203 /* Sample coverage for edge pixels */
204 lxs = RENDER_SAMPLES_X (lx, 8);
205 rxs = RENDER_SAMPLES_X (rx, 8);
207 /* Add coverage across row */
210 WRITE (image, ap + lxi,
211 clip255 (READ (image, ap + lxi) + rxs - lxs));
215 WRITE (image, ap + lxi,
216 clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
218 /* Move forward so that lxi/rxi is the pixel span */
221 /* Don't bother trying to optimize the fill unless
222 * the span is longer than 4 pixels. */
233 if (lxi >= fill_end || rxi < fill_start)
235 /* We're beyond what we saved, just fill it */
236 ADD_SATURATE_8 (ap + fill_start,
237 fill_size * N_X_FRAC (8),
238 fill_end - fill_start);
245 /* Update fill_start */
246 if (lxi > fill_start)
248 ADD_SATURATE_8 (ap + fill_start,
249 fill_size * N_X_FRAC (8),
253 else if (lxi < fill_start)
255 ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
259 /* Update fill_end */
262 ADD_SATURATE_8 (ap + rxi,
263 fill_size * N_X_FRAC (8),
267 else if (fill_end < rxi)
269 ADD_SATURATE_8 (ap + fill_end,
279 ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
282 WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
288 /* We're done, make sure we clean up any remaining fill. */
289 if (fill_start != fill_end)
291 if (fill_size == N_Y_FRAC (8))
293 MEMSET_WRAPPED (image, ap + fill_start,
294 0xff, fill_end - fill_start);
298 ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
299 fill_end - fill_start);
305 if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
307 RENDER_EDGE_STEP_SMALL (l);
308 RENDER_EDGE_STEP_SMALL (r);
309 y += STEP_Y_SMALL (8);
313 RENDER_EDGE_STEP_BIG (l);
314 RENDER_EDGE_STEP_BIG (r);
316 if (fill_start != fill_end)
318 if (fill_size == N_Y_FRAC (8))
320 MEMSET_WRAPPED (image, ap + fill_start,
321 0xff, fill_end - fill_start);
325 ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
326 fill_end - fill_start);
329 fill_start = fill_end = -1;
338 #ifndef PIXMAN_FB_ACCESSORS
342 PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
348 switch (PIXMAN_FORMAT_BPP (image->bits.format))
351 rasterize_edges_1 (image, l, r, t, b);
355 rasterize_edges_4 (image, l, r, t, b);
359 rasterize_edges_8 (image, l, r, t, b);
367 #ifndef PIXMAN_FB_ACCESSORS
370 pixman_rasterize_edges (pixman_image_t *image,
376 return_if_fail (image->type == BITS);
377 return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A);
379 if (image->bits.read_func || image->bits.write_func)
380 pixman_rasterize_edges_accessors (image, l, r, t, b);
382 pixman_rasterize_edges_no_accessors (image, l, r, t, b);