304 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			304 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
/* $XFree86: xc/programs/Xserver/afb/afbimage.c,v 3.2 1998/03/20 21:04:55 hohndel Exp $ */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include <X11/X.h>
 | 
						|
#include "windowstr.h"
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "afb.h"
 | 
						|
#include "maskbits.h"
 | 
						|
#include "servermd.h"
 | 
						|
#include "mfb.h"
 | 
						|
 | 
						|
void
 | 
						|
afbPutImage(pDraw, pGC, depth, x, y, width, height, leftPad, format, pImage)
 | 
						|
	DrawablePtr pDraw;
 | 
						|
	GCPtr pGC;
 | 
						|
	int depth, x, y, width, height;
 | 
						|
	int leftPad;
 | 
						|
	int format;
 | 
						|
	char *pImage;
 | 
						|
{
 | 
						|
	PixmapPtr pPixmap;
 | 
						|
 | 
						|
	if ((width == 0) || (height == 0))
 | 
						|
		return;
 | 
						|
 | 
						|
	if (format != ZPixmap || depth == 1 || pDraw->depth == 1) {
 | 
						|
		pPixmap = GetScratchPixmapHeader(pDraw->pScreen, width+leftPad, height,
 | 
						|
													depth, depth,
 | 
						|
													BitmapBytePad(width+leftPad),
 | 
						|
													(pointer)pImage);
 | 
						|
		if (!pPixmap)
 | 
						|
			return;
 | 
						|
 | 
						|
		pGC->fExpose = FALSE;
 | 
						|
		if (format == XYBitmap)
 | 
						|
			(void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, pDraw, pGC, leftPad,
 | 
						|
												  0, width, height, x, y, 1);
 | 
						|
		else {
 | 
						|
#if 0
 | 
						|
			/* XXX: bit plane order wronge ! */
 | 
						|
			pPixmap->drawable.depth = 1;
 | 
						|
			pPixmap->drawable.bitsPerPixel = 1;
 | 
						|
 | 
						|
			switch (pGC->alu) {
 | 
						|
				case GXcopy:
 | 
						|
					doBitBlt = afbDoBitbltCopy;
 | 
						|
					break;
 | 
						|
				case GXxor:
 | 
						|
					doBitBlt = afbDoBitbltXor;
 | 
						|
					break;
 | 
						|
				case GXcopyInverted:
 | 
						|
					doBitBlt = afbDoBitbltCopyInverted;
 | 
						|
					break;
 | 
						|
				case GXor:
 | 
						|
					doBitBlt = afbDoBitbltOr;
 | 
						|
					break;
 | 
						|
				default:
 | 
						|
					doBitBlt = afbDoBitbltGeneral;
 | 
						|
					break;
 | 
						|
			}
 | 
						|
 | 
						|
			for (plane = (1L << (pPixmap->drawable.depth - 1)); plane;
 | 
						|
				  plane >>= 1) {
 | 
						|
				(void)afbBitBlt((DrawablePtr)pPixmap, pDraw, pGC, leftPad, 0,
 | 
						|
									  width, height, x, y, doBitBlt, plane);
 | 
						|
				/* pDraw->devKind += sizeDst; */
 | 
						|
			}
 | 
						|
#else
 | 
						|
			(void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, pDraw, pGC, leftPad,
 | 
						|
												 0, width, height, x, y);
 | 
						|
#endif
 | 
						|
		}
 | 
						|
 | 
						|
		pGC->fExpose = TRUE;
 | 
						|
		FreeScratchPixmapHeader(pPixmap);
 | 
						|
	} else {
 | 
						|
		/* Chunky to planar conversion required */
 | 
						|
 | 
						|
		PixmapPtr pPixmap;
 | 
						|
		ScreenPtr pScreen = pDraw->pScreen;
 | 
						|
		int widthSrc;
 | 
						|
		int start_srcshift;
 | 
						|
		register int b;
 | 
						|
		register int dstshift;
 | 
						|
		register int shift_step;
 | 
						|
		register PixelType dst;
 | 
						|
		register PixelType srcbits;
 | 
						|
		register PixelType *pdst;
 | 
						|
		register PixelType *psrc;
 | 
						|
		int start_bit;
 | 
						|
		register int nl;
 | 
						|
		register int h;
 | 
						|
		register int d;
 | 
						|
		int sizeDst;
 | 
						|
		PixelType *pdstBase;
 | 
						|
		int widthDst;
 | 
						|
		int depthDst;
 | 
						|
 | 
						|
		/* Create a tmp pixmap */
 | 
						|
		pPixmap = (pScreen->CreatePixmap)(pScreen, width, height, depth);
 | 
						|
		if (!pPixmap)
 | 
						|
			return;
 | 
						|
 | 
						|
		afbGetPixelWidthSizeDepthAndPointer((DrawablePtr)pPixmap, widthDst,
 | 
						|
														 sizeDst, depthDst, pdstBase);
 | 
						|
 | 
						|
		widthSrc = PixmapWidthInPadUnits(width, depth);
 | 
						|
		/* XXX: if depth == 8, use fast chunky to planar assembly function.*/
 | 
						|
		if (depth > 4) {
 | 
						|
			start_srcshift = 24;
 | 
						|
			shift_step = 8;
 | 
						|
		} else {
 | 
						|
			start_srcshift = 28;
 | 
						|
			shift_step = 4;
 | 
						|
		}
 | 
						|
 | 
						|
		for (d = 0; d < depth; d++, pdstBase += sizeDst) {	/* @@@ NEXT PLANE @@@ */
 | 
						|
			start_bit = start_srcshift + d;
 | 
						|
			psrc = (PixelType *)pImage;
 | 
						|
			pdst = pdstBase;
 | 
						|
			h = height;
 | 
						|
 | 
						|
			while (h--) {
 | 
						|
				dstshift = PPW - 1;
 | 
						|
				dst = 0;
 | 
						|
				nl = widthSrc;
 | 
						|
				while (nl--) {
 | 
						|
					srcbits = *psrc++;
 | 
						|
					for (b = start_bit; b >= 0; b -= shift_step) {
 | 
						|
						dst |= ((srcbits >> b) & 1) << dstshift;
 | 
						|
						if (--dstshift < 0) {
 | 
						|
							dstshift = PPW - 1;
 | 
						|
							*pdst++ = dst;
 | 
						|
							dst = 0;
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
				if (dstshift != PPW - 1)
 | 
						|
					*pdst++ = dst;
 | 
						|
			}
 | 
						|
		} /* for (d = ...) */
 | 
						|
 | 
						|
		pGC->fExpose = FALSE;
 | 
						|
		(void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, pDraw, pGC, leftPad, 0,
 | 
						|
											 width, height, x, y);
 | 
						|
		pGC->fExpose = TRUE;
 | 
						|
		(*pScreen->DestroyPixmap)(pPixmap);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
afbGetImage(pDrawable, sx, sy, width, height, format, planemask, pdstLine)
 | 
						|
	DrawablePtr pDrawable;
 | 
						|
	int sx, sy, width, height;
 | 
						|
	unsigned int format;
 | 
						|
	unsigned long planemask;
 | 
						|
	char *pdstLine;
 | 
						|
{
 | 
						|
	BoxRec box;
 | 
						|
	DDXPointRec ptSrc;
 | 
						|
	RegionRec rgnDst;
 | 
						|
	ScreenPtr pScreen;
 | 
						|
	PixmapPtr pPixmap;
 | 
						|
 | 
						|
	if ((width == 0) || (height == 0))
 | 
						|
		return;
 | 
						|
 | 
						|
	pScreen = pDrawable->pScreen;
 | 
						|
	sx += pDrawable->x;
 | 
						|
	sy += pDrawable->y;
 | 
						|
 | 
						|
	if (format == XYPixmap || pDrawable->depth == 1) {
 | 
						|
		pPixmap = GetScratchPixmapHeader(pScreen, width, height, 1, 1,
 | 
						|
													BitmapBytePad(width), (pointer)pdstLine);
 | 
						|
		if (!pPixmap)
 | 
						|
			return;
 | 
						|
 | 
						|
		ptSrc.x = sx;
 | 
						|
		ptSrc.y = sy;
 | 
						|
		box.x1 = 0;
 | 
						|
		box.y1 = 0;
 | 
						|
		box.x2 = width;
 | 
						|
		box.y2 = height;
 | 
						|
		REGION_INIT(pScreen, &rgnDst, &box, 1);
 | 
						|
 | 
						|
		pPixmap->drawable.depth = 1;
 | 
						|
		pPixmap->drawable.bitsPerPixel = 1;
 | 
						|
		/* dix layer only ever calls GetImage with 1 bit set in planemask
 | 
						|
		 * when format is XYPixmap.
 | 
						|
		 */
 | 
						|
		afbDoBitblt(pDrawable, (DrawablePtr)pPixmap, GXcopy, &rgnDst, &ptSrc,
 | 
						|
						 planemask);
 | 
						|
 | 
						|
		FreeScratchPixmapHeader(pPixmap);
 | 
						|
		REGION_UNINIT(pScreen, &rgnDst);
 | 
						|
	} else {
 | 
						|
		/* Planar to chunky conversion required */
 | 
						|
 | 
						|
		PixelType *psrcBits;
 | 
						|
		PixelType *psrcLine;
 | 
						|
		PixelType startmask, endmask;
 | 
						|
		int depthSrc;
 | 
						|
		int widthSrc;
 | 
						|
		int sizeSrc;
 | 
						|
		int sizeDst;
 | 
						|
		int widthDst;
 | 
						|
		register PixelType *psrc;
 | 
						|
		register PixelType *pdst;
 | 
						|
		register PixelType dst;
 | 
						|
		register PixelType srcbits;
 | 
						|
		register int d;
 | 
						|
		register int b;
 | 
						|
		register int dstshift;
 | 
						|
		register int shift_step;
 | 
						|
		register int start_endbit;
 | 
						|
		int start_startbit;
 | 
						|
		register int end_endbit = 0;
 | 
						|
		register int start_dstshift;
 | 
						|
		register int nl;
 | 
						|
		register int h;
 | 
						|
		int nlmiddle;
 | 
						|
 | 
						|
		widthDst = PixmapWidthInPadUnits(width, pDrawable->depth);
 | 
						|
		sizeDst = widthDst * height;
 | 
						|
 | 
						|
		/* Clear the dest image */
 | 
						|
		bzero(pdstLine, sizeDst << 2);
 | 
						|
 | 
						|
		afbGetPixelWidthSizeDepthAndPointer(pDrawable, widthSrc, sizeSrc,
 | 
						|
														 depthSrc, psrcBits);
 | 
						|
 | 
						|
		psrcBits = afbScanline(psrcBits, sx, sy, widthSrc);
 | 
						|
 | 
						|
		start_startbit = PPW - 1 - (sx & PIM);
 | 
						|
		if ((sx & PIM) + width < PPW) {
 | 
						|
			maskpartialbits(sx, width, startmask);
 | 
						|
			nlmiddle = 0;
 | 
						|
			endmask = 0;
 | 
						|
			start_endbit = PPW - ((sx + width) & PIM);
 | 
						|
		} else {
 | 
						|
			maskbits(sx, width, startmask, endmask, nlmiddle);
 | 
						|
			start_endbit = 0;
 | 
						|
			end_endbit = PPW - ((sx + width) & PIM);
 | 
						|
		}
 | 
						|
		/* ZPixmap images have either 4 or 8 bits per pixel dependent on
 | 
						|
		 * depth.
 | 
						|
		 */
 | 
						|
		if (depthSrc > 4) {
 | 
						|
			start_dstshift = 24;
 | 
						|
			shift_step = 8;
 | 
						|
		} else {
 | 
						|
			start_dstshift = 28;
 | 
						|
			shift_step = 4;
 | 
						|
		}
 | 
						|
#define SHIFT_BITS(start_bit,end_bit) \
 | 
						|
for (b = (start_bit); b >= (end_bit); b--) { \
 | 
						|
	dst |= ((srcbits >> b) & 1) << dstshift; \
 | 
						|
	if ((dstshift -= shift_step) < 0) { \
 | 
						|
		dstshift = start_dstshift + d; \
 | 
						|
		*pdst++ = dst; \
 | 
						|
		dst = *pdst; \
 | 
						|
	} \
 | 
						|
} \
 | 
						|
 | 
						|
		for (d = 0; d < depthSrc; d++, psrcBits += sizeSrc) {	/* @@@ NEXT PLANE @@@ */
 | 
						|
			psrcLine = psrcBits;
 | 
						|
			pdst = (PixelType *)pdstLine;
 | 
						|
			h = height;
 | 
						|
 | 
						|
			while (h--) {
 | 
						|
				psrc = psrcLine;
 | 
						|
				psrcLine += widthSrc;
 | 
						|
				dst = *pdst;
 | 
						|
				dstshift = start_dstshift + d;
 | 
						|
 | 
						|
				if (startmask) {
 | 
						|
					srcbits = *psrc++ & startmask;
 | 
						|
					SHIFT_BITS(start_startbit, start_endbit);
 | 
						|
				}
 | 
						|
 | 
						|
				nl = nlmiddle;
 | 
						|
				while (nl--) {
 | 
						|
					srcbits = *psrc++;
 | 
						|
					SHIFT_BITS(PPW - 1, 0);
 | 
						|
				}
 | 
						|
				if (endmask) {
 | 
						|
					srcbits = *psrc & endmask;
 | 
						|
					SHIFT_BITS(PPW - 1, end_endbit);
 | 
						|
				}
 | 
						|
 | 
						|
				if (dstshift != start_dstshift + d)
 | 
						|
					*pdst++ = dst;
 | 
						|
			} /* while (h--) */
 | 
						|
		} /* for (d = ...) */
 | 
						|
	}
 | 
						|
}
 |