123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /*
- *
- * Copyright © 2004 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- #include <string.h>
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include "fb.h"
- #include "picturestr.h"
- #include "mipict.h"
- #include "renderedge.h"
- #include "fbpict.h"
- /*
- * 4 bit alpha
- */
- #define N_BITS 4
- #define rasterizeEdges fbRasterizeEdges4
- #if BITMAP_BIT_ORDER == LSBFirst
- #define Shift4(o) ((o) << 2)
- #else
- #define Shift4(o) ((1-(o)) << 2)
- #endif
- #define Get4(x,o) (((x) >> Shift4(o)) & 0xf)
- #define Put4(x,o,v) (((x) & ~(0xf << Shift4(o))) | (((v) & 0xf) << Shift4(o)))
- #define DefineAlpha(line,x) \
- CARD8 *__ap = (CARD8 *) line + ((x) >> 1); \
- int __ao = (x) & 1
- #define StepAlpha ((__ap += __ao), (__ao ^= 1))
- #define AddAlpha(a) { \
- CARD8 __o = *__ap; \
- CARD8 __a = (a) + Get4(__o, __ao); \
- *__ap = Put4 (__o, __ao, __a | (0 - ((__a) >> 4))); \
- }
- #include "fbedgeimp.h"
- #undef AddAlpha
- #undef StepAlpha
- #undef DefineAlpha
- #undef rasterizeEdges
- #undef N_BITS
- /*
- * 1 bit alpha
- */
- #define N_BITS 1
- #define rasterizeEdges fbRasterizeEdges1
- #include "fbedgeimp.h"
- #undef rasterizeEdges
- #undef N_BITS
- /*
- * 8 bit alpha
- */
- static INLINE CARD8
- clip255(int x)
- {
- if (x > 255)
- return 255;
- return x;
- }
- static INLINE void
- add_saturate_8(CARD8 *buf, int value, int length)
- {
- while (length--) {
- *buf = clip255(*buf + value);
- buf++;
- }
- }
- /*
- * We want to detect the case where we add the same value to a long
- * span of pixels. The triangles on the end are filled in while we
- * count how many sub-pixel scanlines contribute to the middle section.
- *
- * +--------------------------+
- * fill_height =| \ /
- * +------------------+
- * |================|
- * fill_start fill_end
- */
- static void
- fbRasterizeEdges8(FbBits * buf,
- int width,
- int stride,
- RenderEdge * l, RenderEdge * r, xFixed t, xFixed b)
- {
- xFixed y = t;
- FbBits *line;
- int fill_start = -1, fill_end = -1;
- int fill_size = 0;
- line = buf + xFixedToInt(y) * stride;
- for (;;) {
- CARD8 *ap = (CARD8 *) line;
- xFixed lx, rx;
- int lxi, rxi;
- /* clip X */
- lx = l->x;
- if (lx < 0)
- lx = 0;
- rx = r->x;
- if (xFixedToInt(rx) >= width)
- rx = IntToxFixed(width);
- /* Skip empty (or backwards) sections */
- if (rx > lx) {
- int lxs, rxs;
- /* Find pixel bounds for span. */
- lxi = xFixedToInt(lx);
- rxi = xFixedToInt(rx);
- /* Sample coverage for edge pixels */
- lxs = RenderSamplesX(lx, 8);
- rxs = RenderSamplesX(rx, 8);
- /* Add coverage across row */
- if (lxi == rxi) {
- ap[lxi] = clip255(ap[lxi] + rxs - lxs);
- }
- else {
- ap[lxi] = clip255(ap[lxi] + N_X_FRAC(8) - lxs);
- /* Move forward so that lxi/rxi is the pixel span */
- lxi++;
- /* Don't bother trying to optimize the fill unless
- * the span is longer than 4 pixels. */
- if (rxi - lxi > 4) {
- if (fill_start < 0) {
- fill_start = lxi;
- fill_end = rxi;
- fill_size++;
- }
- else {
- if (lxi >= fill_end || rxi < fill_start) {
- /* We're beyond what we saved, just fill it */
- add_saturate_8(ap + fill_start,
- fill_size * N_X_FRAC(8),
- fill_end - fill_start);
- fill_start = lxi;
- fill_end = rxi;
- fill_size = 1;
- }
- else {
- /* Update fill_start */
- if (lxi > fill_start) {
- add_saturate_8(ap + fill_start,
- fill_size * N_X_FRAC(8),
- lxi - fill_start);
- fill_start = lxi;
- }
- else if (lxi < fill_start) {
- add_saturate_8(ap + lxi, N_X_FRAC(8),
- fill_start - lxi);
- }
- /* Update fill_end */
- if (rxi < fill_end) {
- add_saturate_8(ap + rxi,
- fill_size * N_X_FRAC(8),
- fill_end - rxi);
- fill_end = rxi;
- }
- else if (fill_end < rxi) {
- add_saturate_8(ap + fill_end,
- N_X_FRAC(8), rxi - fill_end);
- }
- fill_size++;
- }
- }
- }
- else {
- add_saturate_8(ap + lxi, N_X_FRAC(8), rxi - lxi);
- }
- /* Do not add in a 0 alpha here. This check is
- * necessary to avoid a buffer overrun, (when rx
- * is exactly on a pixel boundary). */
- if (rxs)
- ap[rxi] = clip255(ap[rxi] + rxs);
- }
- }
- if (y == b) {
- /* We're done, make sure we clean up any remaining fill. */
- if (fill_start != fill_end) {
- if (fill_size == N_Y_FRAC(8)) {
- memset(ap + fill_start, 0xff, fill_end - fill_start);
- }
- else {
- add_saturate_8(ap + fill_start, fill_size * N_X_FRAC(8),
- fill_end - fill_start);
- }
- }
- break;
- }
- if (xFixedFrac(y) != Y_FRAC_LAST(8)) {
- RenderEdgeStepSmall(l);
- RenderEdgeStepSmall(r);
- y += STEP_Y_SMALL(8);
- }
- else {
- RenderEdgeStepBig(l);
- RenderEdgeStepBig(r);
- y += STEP_Y_BIG(8);
- if (fill_start != fill_end) {
- if (fill_size == N_Y_FRAC(8)) {
- memset(ap + fill_start, 0xff, fill_end - fill_start);
- }
- else {
- add_saturate_8(ap + fill_start, fill_size * N_X_FRAC(8),
- fill_end - fill_start);
- }
- fill_start = fill_end = -1;
- fill_size = 0;
- }
- line += stride;
- }
- }
- }
- void
- fbRasterizeEdges(FbBits * buf,
- int bpp,
- int width,
- int stride, RenderEdge * l, RenderEdge * r, xFixed t, xFixed b)
- {
- switch (bpp) {
- case 1:
- fbRasterizeEdges1(buf, width, stride, l, r, t, b);
- break;
- case 4:
- fbRasterizeEdges4(buf, width, stride, l, r, t, b);
- break;
- case 8:
- fbRasterizeEdges8(buf, width, stride, l, r, t, b);
- break;
- }
- }
|