4.4BSD/usr/src/contrib/X11R5-hp300/mit/server/ddx/hpbsd/cfb/hpByteBlt.c

Compare this file to the similar file:
Show the results in this format:

/*

Copyright (c) 1986, 1987 by Hewlett-Packard Company
Copyright (c) 1986, 1987 by the Massachusetts Institute of Technology

Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, 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 M.I.T. not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

HEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD
TO THIS SOFWARE, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
PURPOSE.  Hewlett-Packard shall not be liable for errors 
contained herein or direct, indirect, special, incidental or 
consequential damages in connection with the furnishing, 
performance, or use of this material.

This software is not subject to any license of the American
Telephone and Telegraph Company or of the Regents of the
University of California.

*/
/***********************************************************************
 *  file: hpByteBlt.c
 *
 *  Byte-Per-Pixel 68000 (and hopefully Spectrum) bit/byte order
 *  image transfer routines. Specifically:
 *	hpGetByteImage
 *
 *		Hewlett Packard -- Corvallis Workstation Operation
 *		Project -- port of X11 to HP9000
 *		Harry Phinney -- MTS
 *
 *
 */

#include "X.h"
#include "Xprotostr.h"

#include "cfb.h"
#include "gcstruct.h"
#include "pixmapstr.h"
#include "windowstr.h"
#include "scrnintstr.h"
#include "mi.h"
#include "regionstr.h"
#include "Xmd.h"
#include "servermd.h"

static unsigned char masks[8] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
#if 0
static unsigned char trailMasks[8] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4,
				       0x2, 0x1 };

static unsigned long bmap[32] = {
	0x00000001, 0x00000002, 0x00000004, 0x00000008,
	0x00000010, 0x00000020, 0x00000040, 0x00000080,
	0x00000100, 0x00000200, 0x00000400, 0x00000800,
	0x00001000, 0x00002000, 0x00004000, 0x00008000,
	0x00010000, 0x00020000, 0x00040000, 0x00080000,
	0x00100000, 0x00200000, 0x00400000, 0x00800000,
	0x01000000, 0x02000000, 0x04000000, 0x08000000,
	0x10000000, 0x20000000, 0x40000000, 0x80000000 };
#endif

static unsigned long rbmap[32] = {
	0x80000000, 0x40000000, 0x20000000, 0x10000000,
	0x08000000, 0x04000000, 0x02000000, 0x01000000,
	0x00800000, 0x00400000, 0x00200000, 0x00100000,
	0x00080000, 0x00040000, 0x00020000, 0x00010000,
	0x00008000, 0x00004000, 0x00002000, 0x00001000,
	0x00000800, 0x00000400, 0x00000200, 0x00000100,
	0x00000080, 0x00000040, 0x00000020, 0x00000010,
	0x00000008, 0x00000004, 0x00000002, 0x00000001 };


/* hpGetPlane -- gets a bitmap representing one plane of pDraw
 * A helper used for XY format GetImage 
 * No clever strategy here, we grab a scanline at a time, pull out the
 * bits and then stuff them in a 1 bit deep map.
 * This is a significantly modified version of miGetPlane.  The arguments
 * are different, as here we pass in the start address within the source 
 * pixmap, instead of the sx and sy within the pixmap, and we pass in the
 * stride that will get us to the next line - either the pixmap width or
 * the screen width depending on whether the pixmap is in framebuffer or
 * main memory.
 */
unsigned long	*
hpGetPlane(pDraw, planeNum, startAddr, w, h, stride, result)
    DrawablePtr		pDraw;
    int			planeNum;	/* number of the bitPlane */
    unsigned char *	startAddr;
    int			w, h;
    int			stride; 	/* stride to get to next line */
    unsigned long	*result;
{
    register int 	i, j;
    int			k, widthInBytes;
    register CARD32	bits;
    CARD8		*pCharsOut;
    register unsigned char *pixAddr;
    register unsigned char pixel;

    if (pDraw->depth != 8)
	FatalError("hpGetPlane: invalid depth\n");
    widthInBytes = PixmapBytePad(w, 1);
    if (!result)
        result = (unsigned long *)xalloc(h * widthInBytes);

    for (i = 0; i < h; i++)
    {
    	pCharsOut = ((unsigned char *)result) + i * widthInBytes;
	pixAddr = startAddr + i * (stride);
	k = 0;
	bits = 0;
	for (j = 0; j < w; j++)
	{
	    pixel = *pixAddr++;
            if (BITMAP_BIT_ORDER == LSBFirst)
	        bits = (bits << 1) | ((pixel >> planeNum) & 1);
	    else
	    {
#ifdef notdef	/* more portable, but slower code */
		bits |= ((pixel >> planeNum) & 1) << ((BITMAP_SCANLINE_UNIT - 1)
			  - k);
#else		/* faster, but less portable code */
		if (pixel & masks[planeNum]) bits |= rbmap[k];
#endif
	    }
	    k++;
	    if (BITMAP_SCANLINE_UNIT == k)
	    {
		switch (BITMAP_SCANLINE_UNIT)
		{
		  case 8:
		    *pCharsOut++ = (CARD8)bits; break;
		  case 16:
		    *(CARD16 *)pCharsOut = (CARD16) bits;
		    pCharsOut += sizeof(CARD16);
		    break;
		  case 32:
		    *(CARD32 *)pCharsOut = bits;
		    pCharsOut += sizeof(CARD32);
		    break;
		}
		k = bits = 0;
	    }
	}

#define ORBITs(type,ptr,bits)   *(type *)ptr = (type)bits

	if (k)	/* trailing bits */
	{
	    switch (BITMAP_SCANLINE_UNIT)
	    {
	      case 8:
		ORBITs(CARD8, pCharsOut,bits);
		break;
	      case 16:
		ORBITs(CARD16,pCharsOut,bits);
		break;
	      case 32:
		ORBITs(CARD32,pCharsOut,bits); break;
	    }
	}
    }
    return(result);    
}

/* hpGetByteImage -- public entry for the GetImage Request
 * We're getting the image into a memory buffer.
 * Since we know what an hp byte-deep framebuffer looks like, we can do
 * this much faster than miGetImage.
 *
 * two different strategies are used, depending on whether we're getting the
 * image in Z format or XY format
 * Z format:
 *   For each row
 *	For each column
 *	  Read the pixel into pdst
 *   If planeMask is not all ones  (yech)
 *	For each row
 *	  For each column
 *	    Mask the unwanted bits 
 *
 * XY format:
 *   Call hpGetBytePlane (see above in this file)
 *   
 *
 */
void
hpGetByteImage(pDraw, sx, sy, w, h, format, planeMask, pdstLine)
    DrawablePtr 	pDraw;
    int			sx, sy, w, h;
    unsigned int 	format;
    unsigned long 	planeMask;
    pointer             pdstLine;
{
    int depth, i, linelength;

    unsigned char *pSrc;
    int widthSrc;
    unsigned int screenPlanes = getPlanesMask(pDraw->pScreen);

    if ((w == 0) || (h == 0))
        return;

    depth = pDraw->depth;
    switch (depth)
    {
      case 1:
        mfbGetImage(pDraw, sx, sy, w, h, format, planeMask, pdstLine);
        return;
      case 8:
	break;
      default:
	miGetImage(pDraw, sx, sy, w, h, format, planeMask, pdstLine);
	return;
    }
	
    if (!(planeMask &= screenPlanes))
	return;

    linelength = PixmapBytePad(w, depth);
    if (pDraw->type == DRAWABLE_WINDOW)
    {
	sx += pDraw->x;
	sy += pDraw->y;
        widthSrc = (int) getPrivScreenPtr(pDraw->pScreen)->stride;
        pSrc = (unsigned char *)
            getPrivScreenPtr(pDraw->pScreen)->bits + sx + sy * widthSrc;
    }
    else
    {				/* we're getting from a pixmap */
	hpPrivPixmapPtr pPrivPix =
	    (hpPrivPixmapPtr)((PixmapPtr) pDraw)->devPrivate.ptr;

	if (((PixmapPtr)pDraw)->devKind == PIXMAP_FRAME_BUFFER)
	{
	    sx += pPrivPix->pChunk->x;
	    sy += pPrivPix->pChunk->y;
	    widthSrc = (int) getPrivScreenPtr(pDraw->pScreen)->stride;
	    pSrc = (unsigned char *)
		getPrivScreenPtr(pDraw->pScreen)->bits + sx + sy * widthSrc;
        }
	else
	{			/* main memory pixmap */
	    widthSrc = (int) pPrivPix->stride;
	    pSrc = (unsigned char *) pPrivPix->bits + sx + sy * widthSrc;
	}
    }
    if (format == ZPixmap) 
    {
	WAIT_READY_TO_RENDER(pDraw->pScreen);

	for (i = 0; i < h; i++)
	{			/* for each row */
	    register int j;
	    register unsigned char *pByteDst;
	    register unsigned char *pSrcByte;

	    pSrcByte = pSrc + i * widthSrc;
	    pByteDst = ((unsigned char *)pdstLine) + i * linelength; 

	    for (j = 0; j < w; j++)
	    {			/* for each pixel in row */
		*pByteDst++ = *pSrcByte++ & planeMask;
	    }
	}
    }
    else
    {
	int planes = Ones(screenPlanes);
	int planeSize = PixmapBytePad(w, 1) * h;

	for (i = planes - 1; i >= 0; i--)
	    if (planeMask & (1 << i))
	    {
		(void) hpGetPlane(pDraw, i, pSrc, w, h, widthSrc, pdstLine);
		pdstLine += planeSize;
	    }
    }
}


/* hpPutByteImage -- public entry for the PutImage Request
 *  This is here to try to make XY pixmap puts work reasonably on
 *  our byte-deep framebuffers.
 */
void
hpPutByteImage(pDraw, pGC, depth, dstx, dsty, w, h, srcOffset, format, pImage)
    DrawablePtr         pDraw;
    GCPtr               pGC;
    int                 depth, dstx, dsty, w, h, srcOffset;
    unsigned int        format;
    unsigned char       *pImage;
{
    unsigned long planeMask = pGC->planemask;
    int i;
    unsigned int planeSize, srcStride, widthDst, garbageBits, bits;
    CARD8 *psrc, *psrcLine, *psrcBase, *pdstBase, *pdstLine, *pdst;
    RegionPtr pRegion;
    unsigned int alu;
    register BoxPtr pBox;
    unsigned int numBoxes;
    CARD8 srcByte;
    unsigned int rows;
    unsigned int pixels;
    
    if ((w == 0) || (h == 0))
        return;

    planeMask &= getPlanesMask(pDraw->pScreen);

    if ((format == ZPixmap) ||
	((pDraw->type == DRAWABLE_PIXMAP) &&
	 (((PixmapPtr)(pDraw))->devKind == PIXMAP_HOST_MEMORY)))
    {
	/*
	 * mi seems to work for ZPixmaps
	 * and my code doesn't work for main-memory pixmaps since
	 * I rely on the hardware plane-enable
	 */
	miPutImage(pDraw, pGC, depth, dstx, dsty, w, h, srcOffset, 
		   format, pImage);
	return;
    }

    alu = pGC->alu;
    pRegion = ((cfbPrivGC *)
	       (pGC->devPrivates[cfbGCPrivateIndex].ptr))->pCompositeClip;
    pBox = REGION_RECTS(pRegion);
    numBoxes = REGION_NUM_RECTS(pRegion);

    dstx += pDraw->x;
    dsty += pDraw->y;
    if (pDraw->type == DRAWABLE_WINDOW)
    {
	widthDst = (unsigned int)
	    getPrivScreenPtr(pDraw->pScreen)->stride;
	pdstBase = (CARD8 *)
	    getPrivScreenPtr(pDraw->pScreen)->bits; 
    }
    else
    {
        widthDst = (unsigned int)
            (((hpPrivPixmapPtr)(((PixmapPtr)pDraw)->devPrivate.ptr))->stride);
        pdstBase = (CARD8 *)
            (((hpPrivPixmapPtr)(((PixmapPtr)pDraw)->devPrivate.ptr))->bits); 
    }

    srcStride = PixmapBytePad(w, 1);
    planeSize = h * srcStride;

    while(numBoxes--)
    {
	int clippedWidth = w - srcOffset;
	int clippedHeight = h;
	int startx = dstx;
	int starty = dsty;
	int dx = 0, dy = 0;
	CARD8 *pdstBox = pdstBase;

	psrcBase = (CARD8 *)pImage;

	/*
	 * clip the height
	 */
	if (dsty < pBox->y1)
	{
	    dy = pBox->y1 - dsty;
	    clippedHeight -= dy;
	    if (clippedHeight <= 0)
	    {
		pBox++;
		continue;
	    }
	    starty = pBox->y1;
	}
	if (starty+clippedHeight > pBox->y2)
	{
	    clippedHeight = pBox->y2 - starty;
	    if (clippedHeight <= 0)
	    {
		pBox++;
		continue;
	    }
	}
	/*
	 * clip the width
	 */
	if (dstx < pBox->x1)
	{
	    dx = pBox->x1 - dstx;
	    clippedWidth -= dx;
	    if (clippedWidth <= 0)
	    {
		pBox++;
		continue;
	    }
	    startx = pBox->x1;
	}
	if (startx+clippedWidth > pBox->x2)
	{
	    clippedWidth = pBox->x2 - startx;
	    if (clippedWidth <= 0)
	    {
		pBox++;
		continue;
	    }
	}

	if (!clippedWidth || !clippedHeight)
	{
	    pBox++;
	    continue;
	}

	/*
	 * get address of the first destination pixel
	 */
	pdstBox += startx + starty * widthDst;
	/*
	 * get address of the first source bytes with useful bits
	 */
	psrcBase += srcStride * dy + (srcOffset + dx) / 8;
	garbageBits = (srcOffset + dx) % 8;

	if (depth == 1)
	{
	    /*
	     * XYBitmap code
	     */
	    unsigned int fore = pGC->fgPixel;
	    unsigned int back = pGC->bgPixel;

	    rows = clippedHeight;
	    pixels = clippedWidth;
	    /*
	     * write enable the one plane we want to alter
	     */
	    SET_REGISTERS_FOR_WRITING(pDraw->pScreen, planeMask, alu);

	    psrcLine = psrcBase;
	    pdstLine = pdstBox;
	    while (rows--)
	    {
		psrc = psrcLine;
		pdst = pdstLine;
		srcByte = *psrc++ << garbageBits;
		bits = 8 - garbageBits;

		while (pixels--)
		{
		    if (srcByte & 0x80)
			*pdst++ = fore;
		    else
			*pdst++ = back;
		    if (--bits)
			srcByte <<= 1;
		    else
		    {
			bits = 8;
			srcByte = *psrc++;
		    }
		}
		pixels = clippedWidth;
		psrcLine += srcStride;
		pdstLine += widthDst;
	    }
	}
	else
	{
	    for (i = 1 << (depth - 1); i > 0; i >>= 1, psrcBase += planeSize)
	    {
		if (i & planeMask)
		{
		    rows = clippedHeight;
		    pixels = clippedWidth;

		    /*
		     * write enable the one plane we want to alter
		     */
		    SET_REGISTERS_FOR_WRITING(pDraw->pScreen, i, alu);

		    psrcLine = psrcBase;
		    pdstLine = pdstBox;
		    while (rows--)
		    {
			psrc = psrcLine;
			pdst = pdstLine;
			srcByte = *psrc++ << garbageBits;
			bits = 8 - garbageBits;

			while (pixels--)
			{
			    if (srcByte & 0x80)
				*pdst++ = 0xff;
			    else
				*pdst++ = 0x00;
			    if (--bits)
				srcByte <<= 1;
			    else
			    {
				bits = 8;
				srcByte = *psrc++;
			    }
			}
			pixels = clippedWidth;
			psrcLine += srcStride;
			pdstLine += widthDst;
		    }
		}
	    }
	}
	pBox++;
    }
    SET_REGISTERS_FOR_WRITING(pDraw->pScreen, 0xff, alu);
}