500 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			500 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Id: tridentdraw.c,v 1.1 1999/11/02 03:54:47 keithp Exp $
 | |
|  *
 | |
|  * Copyright © 1999 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.
 | |
|  */
 | |
| /* $RCSId: xc/programs/Xserver/hw/kdrive/trident/tridentdraw.c,v 1.10 2001/06/03 18:48:19 keithp Exp $ */
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include <kdrive-config.h>
 | |
| #endif
 | |
| #include "trident.h"
 | |
| #include "tridentdraw.h"
 | |
| 
 | |
| #include	"Xmd.h"
 | |
| #include	"gcstruct.h"
 | |
| #include	"scrnintstr.h"
 | |
| #include	"pixmapstr.h"
 | |
| #include	"regionstr.h"
 | |
| #include	"mistruct.h"
 | |
| #include	"fontstruct.h"
 | |
| #include	"dixfontstr.h"
 | |
| #include	"fb.h"
 | |
| #include	"migc.h"
 | |
| #include	"miline.h"
 | |
| #include	"picturestr.h"
 | |
| 
 | |
| CARD8 tridentRop[16] = {
 | |
|     /* GXclear      */      0x00,         /* 0 */
 | |
|     /* GXand        */      0x88,         /* src AND dst */
 | |
|     /* GXandReverse */      0x44,         /* src AND NOT dst */
 | |
|     /* GXcopy       */      0xcc,         /* src */
 | |
|     /* GXandInverted*/      0x22,         /* NOT src AND dst */
 | |
|     /* GXnoop       */      0xaa,         /* dst */
 | |
|     /* GXxor        */      0x66,         /* src XOR dst */
 | |
|     /* GXor         */      0xee,         /* src OR dst */
 | |
|     /* GXnor        */      0x11,         /* NOT src AND NOT dst */
 | |
|     /* GXequiv      */      0x99,         /* NOT src XOR dst */
 | |
|     /* GXinvert     */      0x55,         /* NOT dst */
 | |
|     /* GXorReverse  */      0xdd,         /* src OR NOT dst */
 | |
|     /* GXcopyInverted*/     0x33,         /* NOT src */
 | |
|     /* GXorInverted */      0xbb,         /* NOT src OR dst */
 | |
|     /* GXnand       */      0x77,         /* NOT src OR NOT dst */
 | |
|     /* GXset        */      0xff,         /* 1 */
 | |
| };
 | |
| 
 | |
| #define tridentFillPix(bpp,pixel) {\
 | |
|     if (bpp == 8) \
 | |
|     { \
 | |
| 	pixel = pixel & 0xff; \
 | |
| 	pixel = pixel | pixel << 8; \
 | |
|     } \
 | |
|     if (bpp <= 16) \
 | |
|     { \
 | |
| 	pixel = pixel & 0xffff; \
 | |
| 	pixel = pixel | pixel << 16; \
 | |
|     } \
 | |
| }
 | |
| 
 | |
| static Cop	*cop;
 | |
| static CARD32	cmd;
 | |
| 
 | |
| Bool
 | |
| tridentPrepareSolid (DrawablePtr    pDrawable,
 | |
| 		     int	    alu,
 | |
| 		     Pixel	    pm,
 | |
| 		     Pixel	    fg)
 | |
| {
 | |
|     FbBits  depthMask = FbFullMask(pDrawable->depth);
 | |
|     
 | |
|     if ((pm & depthMask) != depthMask)
 | |
| 	return FALSE;
 | |
|     else
 | |
|     {
 | |
| 	KdScreenPriv(pDrawable->pScreen);
 | |
| 	tridentCardInfo(pScreenPriv);
 | |
| 	cop = tridentc->cop;
 | |
| 	
 | |
| 	tridentFillPix(pDrawable->bitsPerPixel,fg);
 | |
| 	_tridentInit(cop,tridentc);
 | |
| 	_tridentSetSolidRect(cop,fg,alu,cmd);
 | |
| 	return TRUE;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| tridentSolid (int x1, int y1, int x2, int y2)
 | |
| {
 | |
|     _tridentRect (cop, x1, y1, x2 - 1, y2 - 1, cmd);
 | |
| }
 | |
| 
 | |
| void
 | |
| tridentDoneSolid (void)
 | |
| {
 | |
| }
 | |
| 
 | |
| Bool
 | |
| tridentPrepareCopy (DrawablePtr	pSrcDrawable,
 | |
| 		    DrawablePtr	pDstDrawable,
 | |
| 		    int		dx,
 | |
| 		    int		dy,
 | |
| 		    int		alu,
 | |
| 		    Pixel	pm)
 | |
| {
 | |
|     FbBits  depthMask = FbFullMask(pDstDrawable->depth);
 | |
|     
 | |
|     if ((pm & depthMask) == depthMask)
 | |
|     {
 | |
| 	KdScreenPriv(pDstDrawable->pScreen);
 | |
| 	tridentCardInfo(pScreenPriv);
 | |
| 	cop = tridentc->cop;
 | |
| 	_tridentInit(cop,tridentc);
 | |
| 	cop->multi = COP_MULTI_PATTERN;
 | |
| 	cop->multi = COP_MULTI_ROP | tridentRop[alu];
 | |
| 	cmd = COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_OP_FB;
 | |
| 	if (dx < 0 || dy < 0)
 | |
| 	    cmd |= COP_X_REVERSE;
 | |
| 	return TRUE;
 | |
|     }
 | |
|     else
 | |
| 	return FALSE;
 | |
| }
 | |
| 
 | |
| void
 | |
| tridentCopy (int srcX,
 | |
| 	     int srcY,
 | |
| 	     int dstX,
 | |
| 	     int dstY,
 | |
| 	     int w,
 | |
| 	     int h)
 | |
| {
 | |
|     if (cmd & COP_X_REVERSE)
 | |
|     {
 | |
| 	cop->src_start_xy = TRI_XY (srcX + w - 1, srcY + h - 1);
 | |
| 	cop->src_end_xy   = TRI_XY (srcX, srcY);
 | |
| 	cop->dst_start_xy = TRI_XY (dstX + w - 1, dstY + h - 1);
 | |
| 	cop->dst_end_xy   = TRI_XY (dstX, dstY);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	cop->src_start_xy   = TRI_XY (srcX, srcY);
 | |
| 	cop->src_end_xy	    = TRI_XY (srcX + w - 1, srcY + h - 1);
 | |
| 	cop->dst_start_xy   = TRI_XY (dstX, dstY);
 | |
| 	cop->dst_end_xy	    = TRI_XY (dstX + w - 1, dstY + h - 1);
 | |
|     }
 | |
|     _tridentWaitDone (cop);
 | |
|     cop->command = cmd;
 | |
| }
 | |
| 
 | |
| void
 | |
| tridentDoneCopy (void)
 | |
| {
 | |
| }
 | |
| 
 | |
| void
 | |
| tridentComposite (CARD8      op,
 | |
| 		  PicturePtr pSrc,
 | |
| 		  PicturePtr pMask,
 | |
| 		  PicturePtr pDst,
 | |
| 		  INT16      xSrc,
 | |
| 		  INT16      ySrc,
 | |
| 		  INT16      xMask,
 | |
| 		  INT16      yMask,
 | |
| 		  INT16      xDst,
 | |
| 		  INT16      yDst,
 | |
| 		  CARD16     width,
 | |
| 		  CARD16     height)
 | |
| {
 | |
|     SetupTrident (pDst->pDrawable->pScreen);
 | |
|     tridentScreenInfo(pScreenPriv);
 | |
|     RegionRec	region;
 | |
|     int		n;
 | |
|     BoxPtr	pbox;
 | |
|     CARD32	rgb;
 | |
|     CARD8	*msk, *mskLine;
 | |
|     FbBits	*mskBits;
 | |
|     FbStride	mskStride;
 | |
|     int		mskBpp;
 | |
|     int		mskXoff, mskYoff;
 | |
|     CARD32	*src, *srcLine;
 | |
|     CARD32	*off, *offLine;
 | |
|     FbBits	*srcBits;
 | |
|     FbStride	srcStride;
 | |
|     int		srcXoff, srcYoff;
 | |
|     FbStride	offStride;
 | |
|     int		srcBpp;
 | |
|     int		x_msk, y_msk, x_src, y_src, x_dst, y_dst;
 | |
|     int		x2;
 | |
|     int		w, h, w_this, h_this, w_remain;
 | |
|     CARD32	*off_screen;
 | |
|     int		off_size = tridents->off_screen_size >> 2;
 | |
|     int		off_width, off_height;
 | |
|     int		stride = pScreenPriv->screen->fb[0].pixelStride;
 | |
|     int		mskExtra;
 | |
|     CARD32	off_screen_offset = tridents->off_screen - tridents->screen;
 | |
|     int		mode;
 | |
|     
 | |
| #define MODE_NONE   0
 | |
| #define MODE_IMAGE  1
 | |
| #define MODE_MASK   2
 | |
|     
 | |
|     rgb = *((CARD32 *) ((PixmapPtr) (pSrc->pDrawable))->devPrivate.ptr);
 | |
|     if (pMask && 
 | |
| 	!pMask->repeat &&
 | |
| 	pMask->format == PICT_a8 &&
 | |
|         op == PictOpOver &&
 | |
| 	pSrc->repeat &&
 | |
| 	pSrc->pDrawable->width == 1 &&
 | |
| 	pSrc->pDrawable->height == 1 &&
 | |
| 	PICT_FORMAT_BPP(pSrc->format) == 32 &&
 | |
| 	(PICT_FORMAT_A(pSrc->format) == 0 ||
 | |
| 	 (rgb & 0xff000000) == 0xff000000) &&
 | |
| 	pDst->pDrawable->bitsPerPixel == 32 &&
 | |
| 	pDst->pDrawable->type == DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	mode = MODE_MASK;
 | |
|     }
 | |
|     else if (!pMask &&
 | |
| 	     op == PictOpOver &&
 | |
| 	     !pSrc->repeat &&
 | |
| 	     PICT_FORMAT_A(pSrc->format) == 8 &&
 | |
| 	     PICT_FORMAT_BPP(pSrc->format) == 32 &&
 | |
| 	     pDst->pDrawable->bitsPerPixel == 32 &&
 | |
| 	     pDst->pDrawable->type == DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	mode = MODE_IMAGE;
 | |
|     }
 | |
|     else
 | |
| 	mode = MODE_NONE;
 | |
|     
 | |
|     if (mode != MODE_NONE)
 | |
|     {
 | |
| 	xDst += pDst->pDrawable->x;
 | |
| 	yDst += pDst->pDrawable->y;
 | |
| 	xSrc += pSrc->pDrawable->x;
 | |
| 	ySrc += pSrc->pDrawable->y;
 | |
| 	
 | |
| 	fbGetDrawable (pSrc->pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff);
 | |
| 	
 | |
| 	if (pMask)
 | |
| 	{
 | |
| 	    xMask += pMask->pDrawable->x;
 | |
| 	    yMask += pMask->pDrawable->y;
 | |
| 	    fbGetDrawable (pMask->pDrawable, mskBits, mskStride, mskBpp, mskXoff, mskYoff);
 | |
| 	    mskStride = mskStride * sizeof (FbBits) / sizeof (CARD8);
 | |
| 	}
 | |
| 	
 | |
| 	if (!miComputeCompositeRegion (®ion,
 | |
| 				       pSrc,
 | |
| 				       pMask,
 | |
| 				       pDst,
 | |
| 				       xSrc,
 | |
| 				       ySrc,
 | |
| 				       xMask,
 | |
| 				       yMask,
 | |
| 				       xDst,
 | |
| 				       yDst,
 | |
| 				       width,
 | |
| 				       height))
 | |
| 	    return;
 | |
| 	
 | |
| 	_tridentInit(cop,tridentc);
 | |
| 	
 | |
| 	cop->multi = COP_MULTI_PATTERN;
 | |
| 	cop->src_offset = off_screen_offset;
 | |
| 	
 | |
| 	if (mode == MODE_IMAGE)
 | |
| 	{
 | |
| 	    cop->multi = (COP_MULTI_ALPHA |
 | |
| 			  COP_ALPHA_BLEND_ENABLE |
 | |
| 			  COP_ALPHA_WRITE_ENABLE |
 | |
| 			  0x7 << 16 |
 | |
| 			  COP_ALPHA_DST_BLEND_1_SRC_A |
 | |
| 			  COP_ALPHA_SRC_BLEND_1);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    rgb &= 0xffffff;
 | |
| 	    cop->multi = (COP_MULTI_ALPHA |
 | |
| 			  COP_ALPHA_BLEND_ENABLE |
 | |
| 			  COP_ALPHA_WRITE_ENABLE |
 | |
| 			  0x7 << 16 |
 | |
| 			  COP_ALPHA_DST_BLEND_1_SRC_A |
 | |
| 			  COP_ALPHA_SRC_BLEND_SRC_A);
 | |
| 	}
 | |
| 	
 | |
| 	n = REGION_NUM_RECTS (®ion);
 | |
| 	pbox = REGION_RECTS (®ion);
 | |
| 	
 | |
| 	while (n--)
 | |
| 	{
 | |
| 	    h = pbox->y2 - pbox->y1;
 | |
| 	    w = pbox->x2 - pbox->x1;
 | |
| 	    
 | |
| 	    offStride = (w + 7) & ~7;
 | |
| 	    off_height = off_size / offStride;
 | |
| 	    if (off_height > h)
 | |
| 		off_height = h;
 | |
| 	    
 | |
| 	    cop->multi = COP_MULTI_STRIDE | (stride << 16) | offStride;
 | |
| 	    
 | |
| 	    y_dst = pbox->y1;
 | |
| 	    y_src = y_dst - yDst + ySrc;
 | |
| 	    y_msk = y_dst - yDst + yMask;
 | |
| 	    
 | |
| 	    x_dst = pbox->x1;
 | |
| 	    x_src = x_dst - xDst + xSrc;
 | |
| 	    x_msk = x_dst - xDst + xMask;
 | |
| 	
 | |
| 	    if (mode == MODE_IMAGE)
 | |
| 		srcLine = (CARD32 *) srcBits + (y_src - srcYoff) * srcStride + (x_src - srcXoff);
 | |
| 	    else
 | |
| 		mskLine = (CARD8 *) mskBits + (y_msk - mskYoff) * mskStride + (x_msk - mskXoff);
 | |
| 
 | |
| 	    while (h)
 | |
| 	    {
 | |
| 		h_this = h;
 | |
| 		if (h_this > off_height)
 | |
| 		    h_this = off_height;
 | |
| 		h -= h_this;
 | |
| 		
 | |
| 		offLine = (CARD32 *) tridents->off_screen;
 | |
| 		
 | |
| 		_tridentWaitDone(cop);
 | |
| 		
 | |
| 		cop->dst_start_xy = TRI_XY(x_dst, y_dst);
 | |
| 		cop->dst_end_xy = TRI_XY(x_dst + w - 1, y_dst + h_this - 1);
 | |
| 		cop->src_start_xy = TRI_XY(0,0);
 | |
| 		cop->src_end_xy = TRI_XY(w - 1, h_this - 1);
 | |
| 					 
 | |
| 		if (mode == MODE_IMAGE)
 | |
| 		{
 | |
| 		    while (h_this--)
 | |
| 		    {
 | |
| 			w_remain = w;
 | |
| 			src = srcLine;
 | |
| 			srcLine += srcStride;
 | |
| 			off = offLine;
 | |
| 			offLine += offStride;
 | |
| 			while (w_remain--)
 | |
| 			    *off++ = *src++;
 | |
| 		    }
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 		    while (h_this--)
 | |
| 		    {
 | |
| 			w_remain = w;
 | |
| 			msk = mskLine;
 | |
| 			mskLine += mskStride;
 | |
| 			off = offLine;
 | |
| 			offLine += offStride;
 | |
| 			while (w_remain--)
 | |
| 			    *off++ = rgb | (*msk++ << 24);
 | |
| 		    }
 | |
| 		}
 | |
| 		
 | |
| 		cop->command = (COP_OP_BLT |
 | |
| 				COP_SCL_OPAQUE |
 | |
| 				COP_OP_FB);
 | |
| 	    }
 | |
| 	    pbox++;
 | |
| 	}
 | |
| 	cop->src_offset = 0;
 | |
| 	
 | |
| 	KdMarkSync (pDst->pDrawable->pScreen);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	KdCheckComposite (op,
 | |
| 			  pSrc,
 | |
| 			  pMask,
 | |
| 			  pDst,
 | |
| 			  xSrc,
 | |
| 			  ySrc,
 | |
| 			  xMask,
 | |
| 			  yMask,
 | |
| 			  xDst,
 | |
| 			  yDst,
 | |
| 			  width,
 | |
| 			  height);
 | |
|     }
 | |
| }
 | |
| 
 | |
| KaaScreenPrivRec    tridentKaa = {
 | |
|     tridentPrepareSolid,
 | |
|     tridentSolid,
 | |
|     tridentDoneSolid,
 | |
| 
 | |
|     tridentPrepareCopy,
 | |
|     tridentCopy,
 | |
|     tridentDoneCopy,
 | |
| };
 | |
| 
 | |
| Bool
 | |
| tridentDrawInit (ScreenPtr pScreen)
 | |
| {
 | |
|     SetupTrident(pScreen);
 | |
|     tridentScreenInfo(pScreenPriv);
 | |
|     PictureScreenPtr    ps = GetPictureScreen(pScreen);
 | |
|     
 | |
|     if (!kaaDrawInit (pScreen, &tridentKaa))
 | |
| 	return FALSE;
 | |
| 
 | |
|     if (ps && tridents->off_screen)
 | |
| 	ps->Composite = tridentComposite;
 | |
|     
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| void
 | |
| tridentDrawEnable (ScreenPtr pScreen)
 | |
| {
 | |
|     SetupTrident(pScreen);
 | |
|     CARD32  cmd;
 | |
|     CARD32  base;
 | |
|     CARD16  stride;
 | |
|     CARD32  format;
 | |
|     CARD32  alpha;
 | |
|     int	    tries;
 | |
|     int	    nwrite;
 | |
|     
 | |
|     stride = pScreenPriv->screen->fb[0].pixelStride;
 | |
|     switch (pScreenPriv->screen->fb[0].bitsPerPixel) {
 | |
|     case 8:
 | |
| 	format = COP_DEPTH_8;
 | |
| 	break;
 | |
|     case 16:
 | |
| 	format = COP_DEPTH_16;
 | |
| 	break;
 | |
|     case 24:
 | |
| 	format = COP_DEPTH_24_32;
 | |
| 	break;
 | |
|     case 32:
 | |
| 	format = COP_DEPTH_24_32;
 | |
| 	break;
 | |
|     }
 | |
|     /* 
 | |
|      * compute a few things which will be set every time the
 | |
|      * accelerator is used; this avoids problems with APM
 | |
|      */
 | |
|     tridentc->cop_depth = COP_MULTI_DEPTH | format;
 | |
|     tridentc->cop_stride = COP_MULTI_STRIDE | (stride << 16) | (stride);
 | |
|     
 | |
| #define NUM_TRIES   100000
 | |
|     for (tries = 0; tries < NUM_TRIES; tries++)
 | |
| 	if (!(cop->status & COP_STATUS_BUSY))
 | |
| 	    break;
 | |
|     if (cop->status & COP_STATUS_BUSY)
 | |
| 	FatalError ("Can't initialize graphics coprocessor");
 | |
|     cop->multi = COP_MULTI_CLIP_TOP_LEFT;
 | |
|     cop->multi = COP_MULTI_MASK | 0;
 | |
|     cop->src_offset = 0;
 | |
|     cop->dst_offset = 0;
 | |
|     cop->z_offset = 0;
 | |
|     cop->clip_bottom_right = 0x0fff0fff;
 | |
|     
 | |
|     _tridentInit(cop,tridentc);
 | |
|     _tridentSetSolidRect(cop, pScreen->blackPixel, GXcopy, cmd);
 | |
|     _tridentRect (cop, 0, 0, 
 | |
| 		  pScreenPriv->screen->width, pScreenPriv->screen->height,
 | |
| 		  cmd);
 | |
|     KdMarkSync (pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| tridentDrawDisable (ScreenPtr pScreen)
 | |
| {
 | |
| }
 | |
| 
 | |
| void
 | |
| tridentDrawFini (ScreenPtr pScreen)
 | |
| {
 | |
| }
 | |
| 
 | |
| void
 | |
| tridentDrawSync (ScreenPtr pScreen)
 | |
| {
 | |
|     SetupTrident(pScreen);
 | |
|     
 | |
|     _tridentWaitIdleEmpty(cop);
 | |
| }
 |