Edit

IABSD.fr/xenocara/xserver/fb/fb24_32.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/fb24_32.c
  • /*
     *
     * Copyright © 2000 SuSE, Inc.
     *
     * 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 SuSE not be used in advertising or
     * publicity pertaining to distribution of the software without specific,
     * written prior permission.  SuSE makes no representations about the
     * suitability of this software for any purpose.  It is provided "as is"
     * without express or implied warranty.
     *
     * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
     * 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.
     *
     * Author:  Keith Packard, SuSE, Inc.
     */
    
    #ifdef HAVE_DIX_CONFIG_H
    #include <dix-config.h>
    #endif
    
    #include <string.h>
    
    #include "fb.h"
    
    /* X apps don't like 24bpp images, this code exposes 32bpp images */
    
    /*
     * These two functions do a full CopyArea while reformatting
     * the data between 24 and 32bpp.  They try to go a bit faster
     * by reading/writing aligned CARD32s where it's easy
     */
    
    #define Get8(a)	((CARD32) *(a))
    
    #if BITMAP_BIT_ORDER == MSBFirst
    #define Get24(a)    ((Get8(a) << 16) | (Get8((a)+1) << 8) | Get8((a)+2))
    #define Put24(a,p)  (((a)[0] = (CARD8) ((p) >> 16)), \
    		     ((a)[1] = (CARD8) ((p) >> 8)), \
    		     ((a)[2] = (CARD8) (p)))
    #else
    #define Get24(a)    (Get8(a) | (Get8((a)+1) << 8) | (Get8((a)+2)<<16))
    #define Put24(a,p)  (((a)[0] = (CARD8) (p)), \
    		     ((a)[1] = (CARD8) ((p) >> 8)), \
    		     ((a)[2] = (CARD8) ((p) >> 16)))
    #endif
    
    typedef void (*fb24_32BltFunc) (CARD8	    *srcLine,
    				FbStride    srcStride,
    				int	    srcX,
    
    				CARD8	    *dstLine,
    				FbStride    dstStride,
    				int	    dstX,
    
    				int	    width, 
    				int	    height,
    
    				int	    alu,
    				FbBits	    pm);
    
    static void
    fb24_32BltDown (CARD8	    *srcLine,
    		FbStride    srcStride,
    		int	    srcX,
    
    		CARD8	    *dstLine,
    		FbStride    dstStride,
    		int	    dstX,
    
    		int	    width, 
    		int	    height,
    
    		int	    alu,
    		FbBits	    pm)
    {
        CARD32  *src;
        CARD8   *dst;
        int	    w;
        Bool    destInvarient;
        CARD32  pixel, dpixel;
        FbDeclareMergeRop ();
        
        srcLine += srcX * 4;
        dstLine += dstX * 3;
    
        FbInitializeMergeRop(alu, (pm | ~(FbBits) 0xffffff));
        destInvarient = FbDestInvarientMergeRop();
    
        while (height--)
        {
    	src = (CARD32 *) srcLine;
    	dst = dstLine;
    	srcLine += srcStride;
    	dstLine += dstStride;
    	w = width;
    	if (destInvarient)
    	{
    	    while (((long) dst & 3) && w)
    	    {
    		w--;
    		pixel = *src++;
    		pixel = FbDoDestInvarientMergeRop(pixel);
    		Put24 (dst, pixel);
    		dst += 3;
    	    }
    	    /* Do four aligned pixels at a time */
    	    while (w >= 4)
    	    {
    		CARD32  s0, s1;
    		s0 = *src++;
    		s0 = FbDoDestInvarientMergeRop(s0);
    		s1 = *src++;
    		s1 = FbDoDestInvarientMergeRop(s1);
    #if BITMAP_BIT_ORDER == LSBFirst
    		*(CARD32 *)(dst) = (s0 & 0xffffff) | (s1 << 24);
    #else
    		*(CARD32 *)(dst) = (s0 << 8) | ((s1 & 0xffffff) >> 16);
    #endif
    		s0 = *src++;
    		s0 = FbDoDestInvarientMergeRop(s0);
    #if BITMAP_BIT_ORDER == LSBFirst
    		*(CARD32 *)(dst+4) = ((s1 & 0xffffff) >> 8) | (s0 << 16);
    #else
    		*(CARD32 *)(dst+4) = (s1 << 16) | ((s0 & 0xffffff) >> 8);
    #endif
    		s1 = *src++;
    		s1 = FbDoDestInvarientMergeRop(s1);
    #if BITMAP_BIT_ORDER == LSBFirst
    		*(CARD32 *)(dst+8) = ((s0 & 0xffffff) >> 16) | (s1 << 8);
    #else
    		*(CARD32 *)(dst+8) = (s0 << 24) | (s1 & 0xffffff);
    #endif
    		dst += 12;
    		w -= 4;
    	    }
    	    while (w--)
    	    {
    		pixel = *src++;
    		pixel = FbDoDestInvarientMergeRop(pixel);
    		Put24 (dst, pixel);
    		dst += 3;
    	    }
    	}
    	else
    	{
    	    while (w--)
    	    {
    		pixel = *src++;
    		dpixel = Get24 (dst);
    		pixel = FbDoMergeRop(pixel, dpixel);
    		Put24 (dst, pixel);
    		dst += 3;
    	    }
    	}
        }
    }
    
    static void
    fb24_32BltUp (CARD8	    *srcLine,
    	      FbStride	    srcStride,
    	      int	    srcX,
    
    	      CARD8	    *dstLine,
    	      FbStride	    dstStride,
    	      int	    dstX,
    
    	      int	    width, 
    	      int	    height,
    
    	      int	    alu,
    	      FbBits	    pm)
    {
        CARD8   *src;
        CARD32  *dst;
        int	    w;
        Bool    destInvarient;
        CARD32  pixel;
        FbDeclareMergeRop ();
        
        FbInitializeMergeRop(alu, (pm | (~(FbBits) 0xffffff)));
        destInvarient = FbDestInvarientMergeRop();
    
        srcLine += srcX * 3;
        dstLine += dstX * 4;
    
        while (height--)
        {
    	w = width;
    	src = srcLine;
    	dst = (CARD32 *) dstLine;
    	srcLine += srcStride;
    	dstLine += dstStride;
    	if (destInvarient)
    	{
    	    while (((long) src & 3) && w)
    	    {
    		w--;
    		pixel = Get24(src);
    		src += 3;
    		*dst++ = FbDoDestInvarientMergeRop(pixel);
    	    }
    	    /* Do four aligned pixels at a time */
    	    while (w >= 4)
    	    {
    		CARD32  s0, s1;
    
    		s0 = *(CARD32 *)(src);
    #if BITMAP_BIT_ORDER == LSBFirst
    		pixel = s0 & 0xffffff;
    #else
    		pixel = s0 >> 8;
    #endif
    		*dst++ = FbDoDestInvarientMergeRop(pixel);
    		s1 = *(CARD32 *)(src+4);
    #if BITMAP_BIT_ORDER == LSBFirst
    		pixel = (s0 >> 24) | ((s1 << 8) & 0xffffff);
    #else
    		pixel = ((s0 << 16) & 0xffffff) | (s1 >> 16);
    #endif
    		*dst++ = FbDoDestInvarientMergeRop(pixel);
    		s0 = *(CARD32 *)(src+8);
    #if BITMAP_BIT_ORDER == LSBFirst
    		pixel = (s1 >> 16) | ((s0 << 16) & 0xffffff);
    #else
    		pixel = ((s1 << 8) & 0xffffff) | (s0 >> 24);
    #endif
    		*dst++ = FbDoDestInvarientMergeRop(pixel);
    #if BITMAP_BIT_ORDER == LSBFirst
    		pixel = s0 >> 8;
    #else
    		pixel = s0 & 0xffffff;
    #endif
    		*dst++ = FbDoDestInvarientMergeRop(pixel);
    		src += 12;
    		w -= 4;
    	    }
    	    while (w)
    	    {
    		w--;
    		pixel = Get24(src);
    		src += 3;
    		*dst++ = FbDoDestInvarientMergeRop(pixel);
    	    }
    	}
    	else
    	{
    	    while (w--)
    	    {
    		pixel = Get24(src);
    		src += 3;
    		*dst = FbDoMergeRop(pixel, *dst);
    		dst++;
    	    }
    	}
        }
    }
    
    /*
     * Spans functions; probably unused.
     */
    void
    fb24_32GetSpans(DrawablePtr	pDrawable, 
    		int		wMax, 
    		DDXPointPtr	ppt, 
    		int		*pwidth, 
    		int		nspans, 
    		char		*pchardstStart)
    {
        FbBits	    *srcBits;
        CARD8	    *src;
        FbStride	    srcStride;
        int		    srcBpp;
        int		    srcXoff, srcYoff;
        CARD8	    *dst;
        
        fbGetDrawable (pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff);
        src = (CARD8 *) srcBits;
        srcStride *= sizeof (FbBits);
        
        while (nspans--)
        {
    	dst = (CARD8 *) pchardstStart;
    	fb24_32BltUp (src + (ppt->y + srcYoff) * srcStride, srcStride,
    		      ppt->x + srcXoff,
    	       
    		      dst,
    		      1,
    		      0,
    
    		      *pwidth,
    		      1,
    
    		      GXcopy,
    		      FB_ALLONES);
    	
    	pchardstStart += PixmapBytePad(*pwidth, pDrawable->depth);
    	ppt++;
    	pwidth++;
        }
    }
    
    void
    fb24_32SetSpans (DrawablePtr	    pDrawable,
    		 GCPtr		    pGC,
    		 char		    *src,
    		 DDXPointPtr	    ppt,
    		 int		    *pwidth,
    		 int		    nspans,
    		 int		    fSorted)
    {
        FbGCPrivPtr	    pPriv = fbGetGCPrivate (pGC);
        RegionPtr	    pClip = fbGetCompositeClip(pGC);
        FbBits	    *dstBits;
        CARD8	    *dst, *d, *s;
        FbStride	    dstStride;
        int		    dstBpp;
        int		    dstXoff, dstYoff;
        BoxPtr	    pbox;
        int		    n;
        int		    x1, x2;
    
        fbGetDrawable (pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff);
        dst = (CARD8 *) dstBits;
        dstStride *= sizeof (FbBits);
        while (nspans--)
        {
    	d = dst + (ppt->y + dstYoff) * dstStride;
    	s = (CARD8 *) src;
    	n = REGION_NUM_RECTS(pClip);
    	pbox = REGION_RECTS (pClip);
    	while (n--)
    	{
    	    if (pbox->y1 > ppt->y)
    		break;
    	    if (pbox->y2 > ppt->y)
    	    {
    		x1 = ppt->x;
    		x2 = x1 + *pwidth;
    		if (pbox->x1 > x1)
    		    x1 = pbox->x1;
    		if (pbox->x2 < x2)
    		    x2 = pbox->x2;
    		if (x1 < x2)
    		    fb24_32BltDown (s,
    				    0,
    				    (x1 - ppt->x),
    				    d,
    				    dstStride,
    				    x1 + dstXoff,
    
    				    (x2 - x1),
    				    1,
    				    pGC->alu,
    				    pPriv->pm);
    	    }
    	}
    	src += PixmapBytePad (*pwidth, pDrawable->depth);
    	ppt++;
    	pwidth++;
        }
    }
    
    /*
     * Clip and put 32bpp Z-format images to a 24bpp drawable
     */
    void
    fb24_32PutZImage (DrawablePtr	pDrawable,
    		  RegionPtr	pClip,
    		  int		alu,
    		  FbBits	pm,
    		  int		x,
    		  int		y,
    		  int		width,
    		  int		height,
    		  CARD8		*src,
    		  FbStride	srcStride)
    {
        FbBits	*dstBits;
        CARD8	*dst;
        FbStride	dstStride;
        int		dstBpp;
        int		dstXoff, dstYoff;
        int		nbox;
        BoxPtr	pbox;
        int		x1, y1, x2, y2;
    
        fbGetDrawable (pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff);
        dstStride *= sizeof(FbBits);
        dst = (CARD8 *) dstBits;
    
        for (nbox = REGION_NUM_RECTS (pClip),
    	 pbox = REGION_RECTS(pClip);
    	 nbox--;
    	 pbox++)
        {
    	x1 = x;
    	y1 = y;
    	x2 = x + width;
    	y2 = y + height;
    	if (x1 < pbox->x1)
    	    x1 = pbox->x1;
    	if (y1 < pbox->y1)
    	    y1 = pbox->y1;
    	if (x2 > pbox->x2)
    	    x2 = pbox->x2;
    	if (y2 > pbox->y2)
    	    y2 = pbox->y2;
    	if (x1 >= x2 || y1 >= y2)
    	    continue;
    	fb24_32BltDown (src + (y1 - y) * srcStride,
    			srcStride,
    			(x1 - x),
    
    			dst + (y1 + dstYoff) * dstStride,
    			dstStride,
    			x1 + dstXoff,
    
    			(x2 - x1),
    			(y2 - y1),
    
    			alu,
    			pm);
        }
    }
    
    void
    fb24_32GetImage (DrawablePtr     pDrawable,
    		 int             x,
    		 int             y,
    		 int             w,
    		 int             h,
    		 unsigned int    format,
    		 unsigned long   planeMask,
    		 char            *d)
    {
        FbBits	    *srcBits;
        CARD8	    *src;
        FbStride	    srcStride;
        int		    srcBpp;
        int		    srcXoff, srcYoff;
        FbStride	    dstStride;
        FbBits	    pm;
    
        fbGetDrawable (pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff);
        src = (CARD8 *) srcBits;
        srcStride *= sizeof (FbBits);
    
        x += pDrawable->x;
        y += pDrawable->y;
        
        pm = fbReplicatePixel (planeMask, 32);
        dstStride = PixmapBytePad(w, pDrawable->depth);
        if (pm != FB_ALLONES)
    	memset (d, 0, dstStride * h);
        fb24_32BltUp (src + (y + srcYoff) * srcStride, srcStride, x + srcXoff,
    		  (CARD8 *) d, dstStride, 0,
    		  w, h, GXcopy, pm);
    }
    
    void
    fb24_32CopyMtoN (DrawablePtr pSrcDrawable,
    		 DrawablePtr pDstDrawable,
    		 GCPtr       pGC,
    		 BoxPtr      pbox,
    		 int         nbox,
    		 int         dx,
    		 int         dy,
    		 Bool        reverse,
    		 Bool        upsidedown,
    		 Pixel       bitplane,
    		 void        *closure)
    {
        FbGCPrivPtr	pPriv = fbGetGCPrivate(pGC);
        FbBits	*srcBits;
        CARD8	*src;
        FbStride	srcStride;
        int		srcBpp;
        FbBits	*dstBits;
        CARD8	*dst;
        FbStride	dstStride;
        int		dstBpp;
        fb24_32BltFunc  blt;
        int		srcXoff, srcYoff;
        int		dstXoff, dstYoff;
        
        fbGetDrawable (pSrcDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff);
        src = (CARD8 *) srcBits;
        srcStride *= sizeof (FbBits);
        fbGetDrawable (pDstDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff);
        dst = (CARD8 *) dstBits;
        dstStride *= sizeof (FbBits);
        if (srcBpp == 24)
    	blt = fb24_32BltUp;
        else
    	blt = fb24_32BltDown;
        
        while (nbox--)
        {
    	(*blt) (src + (pbox->y1 + dy + srcYoff) * srcStride,
    		srcStride,
    		(pbox->x1 + dx + srcXoff),
    
    		dst + (pbox->y1 + dstYoff) * dstStride,
    		dstStride,
    		(pbox->x1 + dstXoff),
    
    		(pbox->x2 - pbox->x1),
    		(pbox->y2 - pbox->y1),
    
    		pGC->alu,
    		pPriv->pm);
    	pbox++;
        }
    }
    
    PixmapPtr
    fb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel)
    {
        ScreenPtr	pScreen = pOldTile->drawable.pScreen;
        PixmapPtr	pNewTile;
        FbBits	*old, *new;
        FbStride	oldStride, newStride;
        int		oldBpp, newBpp;
        fb24_32BltFunc  blt;
        int		oldXoff, oldYoff;
        int		newXoff, newYoff;
    
        pNewTile = fbCreatePixmapBpp (pScreen,
    				  pOldTile->drawable.width,
    				  pOldTile->drawable.height,
    				  pOldTile->drawable.depth,
    				  bitsPerPixel);
        if (!pNewTile)
    	return 0;
        fbGetDrawable (&pOldTile->drawable, 
    		   old, oldStride, oldBpp, oldXoff, oldYoff);
        fbGetDrawable (&pNewTile->drawable, 
    		   new, newStride, newBpp, newXoff, newYoff);
        if (oldBpp == 24)
    	blt = fb24_32BltUp;
        else
    	blt = fb24_32BltDown;
    
        (*blt) ((CARD8 *) old,
    	    oldStride * sizeof (FbBits),
    	    0,
    
    	    (CARD8 *) new,
    	    newStride * sizeof (FbBits),
    	    0,
    
    	    pOldTile->drawable.width,
    	    pOldTile->drawable.height,
    
    	    GXcopy,
    	    FB_ALLONES);
    
        return pNewTile;
    }
    
    typedef struct {
        pointer pbits; 
        int width;   
    } miScreenInitParmsRec, *miScreenInitParmsPtr;
    
    Bool
    fb24_32CreateScreenResources(ScreenPtr pScreen)
    {
        miScreenInitParmsPtr pScrInitParms;
        int pitch;
        Bool retval;
    
        /* get the pitch before mi destroys it */
        pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate;
        pitch = BitmapBytePad(pScrInitParms->width * 24);
    
        if((retval = miCreateScreenResources(pScreen))) {
    	/* fix the screen pixmap */
    	PixmapPtr pPix = (PixmapPtr)pScreen->devPrivate;
    	pPix->drawable.bitsPerPixel = 24;
    	pPix->devKind = pitch;
        }
    
        return retval;
    }
    
    Bool
    fb24_32ModifyPixmapHeader (PixmapPtr   pPixmap,
    			   int         width,
    			   int         height,
    			   int         depth,
    			   int         bitsPerPixel,
    			   int         devKind,
    			   pointer     pPixData)
    {
        int	    bpp, w;
    
        if (!pPixmap)
    	return FALSE;
        bpp = bitsPerPixel;
        if (bpp <= 0)
    	bpp = pPixmap->drawable.bitsPerPixel;
        if (bpp == 24)
        {
    	if (devKind < 0)
    	{
    	    w = width;
    	    if (w <= 0)
    		w = pPixmap->drawable.width;
    	    devKind = BitmapBytePad(w * 24);
    	}
        }
        return miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel,
    				devKind, pPixData);	
    }