Edit

IABSD.fr/xenocara/xserver/fb/fbedge.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2006-11-26 18:13:41
    Hash : 889b8606
    Message : Importing xserver from X.Org 7.2RC2

  • xserver/fb/fbedge.c
  • /*
     * $Id: fbedge.c,v 1.1.1.1 2006/11/26 18:15:37 matthieu Exp $
     *
     * 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"
    
    #ifdef RENDER
    
    #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;
        }
    }
    
    #endif /* RENDER */