text: /* $XFree86: xc/programs/Xserver/hw/xfree86/accel/mach8/mach8fc.c,v 3.7 1996/12/23 06:39:50 dawes Exp $ */
  /*
   * Copyright 1992 by Kevin E. Martin, Chapel Hill, North Carolina.
   * 
   * 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 Kevin E. Martin not be used in
   * advertising or publicity pertaining to distribution of the software
   * without specific, written prior permission.  Kevin E. Martin makes no
   * representations about the suitability of this software for any purpose. It
   * is provided "as is" without express or implied warranty.
   * 
   * KEVIN E. MARTIN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
   * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
   * EVENT SHALL KEVIN E. MARTIN 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.
   * 
   */
  
  /*
   * Extract from s3fcach.c
   * Adapted to Mach8, Hans Nasten. (nasten@everyware.se).
   */
  /* $XConsortium: mach8fc.c /main/6 1996/10/25 16:22:43 kaleb $ */
  
  #include	"X.h"
  #include	"Xmd.h"
  #include	"Xproto.h"
  #include	"cfb.h"
  #include	"misc.h"
  #include        "xf86.h"
  #include	"windowstr.h"
  #include	"gcstruct.h"
  #include	"fontstruct.h"
  #include	"dixfontstr.h"
  #include	"xf86bcache.h"
  #include	"xf86fcache.h"
  #include	"mach8.h"
  #include	"regmach8.h"
  
  
  static unsigned long FontAge;
  #define NEXT_FONT_AGE  ++FontAge
  
  /*
   * When using the 8514 compatible read mask, the read mask
   * is rotated right 1 bit compared to the write mask.
   */
  
  unsigned char mach8cachemask[ 8 ] = { 0x01, 0x02, 0x04, 0x08,
  				      0x10, 0x20, 0x40, 0x80
  };
  unsigned char mach8cachemaskswapped[ 8 ] = { 0x02, 0x04, 0x08, 0x10,
  				             0x20, 0x40, 0x80, 0x01
  };
  
  /*
   * Move the glyphs to the screen using the GE.
   */
  static void
  Domach8CPolyText8(x, y, count, chars, fentry, pGC, pBox)
       int   x, y, count;
       unsigned char *chars;
       CacheFont8Ptr fentry;
       GCPtr pGC;
       BoxPtr pBox;
  {
     int   gHeight, gWidth;
     int   w = fentry->w;
     int blocki = 255;
     unsigned short height = 0;	/* Cache for height, width and		 */
     unsigned short width = 0;	/* readmask registers.			 */
     unsigned short pmsk = 0;	/* ( Out instructions _are_ expensive ). */
  
     for (;count > 0; count--, chars++) {
        CharInfoPtr pci;
        short xoff;
  
        pci = fentry->pci[*chars];
        if (pci != NULL) {
  	 gHeight = GLYPHHEIGHTPIXELS(pci);
  	 gWidth = GLYPHWIDTHPIXELS(pci);
  	 if (gHeight
  	 && x + pci->metrics.leftSideBearing + gWidth-1 >= pBox->x1
  	 && x + pci->metrics.leftSideBearing            <  pBox->x2
  	 && y - pci->metrics.ascent         + gHeight-1 >= pBox->y1
  	 && y - pci->metrics.ascent                     <  pBox->y2 ) {
  	    if (*chars / 32 != blocki) {
  	       bitMapBlockPtr block;
  
  	       blocki = *chars / 32;
  	       if( ( block = fentry->fblock[blocki] ) == NULL) {
  		  /*
  		   * Reset the GE context to a known state before
  		   * calling the xf86loadfontblock function.
  		   */
  		  WaitQueue(8);
  		  outw(MULTIFUNC_CNTL, SCISSORS_T | 0);
  		  outw(MULTIFUNC_CNTL, SCISSORS_L | 0);
  		  outw(MULTIFUNC_CNTL, SCISSORS_R | 1023);
  		  outw(MULTIFUNC_CNTL, SCISSORS_B | 1023);
  		  outw(RD_MASK, 0xff);
  		  outw(MULTIFUNC_CNTL, PIX_CNTL | MIXSEL_FRGDMIX | COLCMPOP_F);
  		  outw(FRGD_MIX, FSS_FRGDCOL | MIX_SRC);
  		  outw(BKGD_MIX, BSS_BKGDCOL | MIX_SRC);
  		  xf86loadFontBlock(fentry, blocki);
  		  block = fentry->fblock[blocki];
  		  /*
  		   * Restore the GE context.
  		   */
  		  WaitQueue(9);
  		  outw(MULTIFUNC_CNTL, SCISSORS_L | (short)pBox->x1);
  		  outw(MULTIFUNC_CNTL, SCISSORS_T | (short)pBox->y1);
  		  outw(MULTIFUNC_CNTL, SCISSORS_R | (short)(pBox->x2 - 1));
  		  outw(MULTIFUNC_CNTL, SCISSORS_B | (short)(pBox->y2 - 1));
  		  outw(FRGD_COLOR, (short)pGC->fgPixel);
  		  outw(MULTIFUNC_CNTL, PIX_CNTL | MIXSEL_EXPBLT | COLCMPOP_F);
  		  outw(FRGD_MIX, FSS_FRGDCOL | mach8alu[pGC->alu]);
  		  outw(BKGD_MIX, BSS_BKGDCOL | MIX_DST);
  		  outw(WRT_MASK, (short)pGC->planemask);
  		  height = width = pmsk = 0; /* Invalidate register caches. */
  	       }
  	       WaitQueue(2);
  	       outw(CUR_Y, block->y);
  	       /*
  		* Is the readmask altered ?
  		*/
  	       if( mach8cachemaskswapped[block->id] != pmsk ) {
  		 pmsk = mach8cachemaskswapped[block->id];
  		 outw(RD_MASK, pmsk);
  	       }
  	       xoff = block->x;
  	       block->lru = NEXT_FONT_AGE;
     	    }
  
  	    WaitQueue(6);
  	    outw(CUR_X, (short) (xoff + (*chars & 0x1f) * w));
  	    outw(DESTX_DIASTP,
  		  (short)(x + pci->metrics.leftSideBearing));
  	    outw(DESTY_AXSTP, (short)(y - pci->metrics.ascent));
  	    /*
  	     * Need to update width register ?
  	     */
  	    if( (short)(GLYPHWIDTHPIXELS(pci)) != width) {
  	      width = (short)(GLYPHWIDTHPIXELS(pci));
  	      outw(MAJ_AXIS_PCNT, width - 1);
  	    }
  	    /*
  	     * How about the height register ?
  	     */
  	    if( (short)(gHeight) != height ) {
  	      height = (short)(gHeight);
  	      outw(MULTIFUNC_CNTL, MIN_AXIS_PCNT | height - 1);
  	    }
  	    outw(CMD, CMD_BITBLT | INC_X | INC_Y | DRAW | PLANAR | WRTDATA);
  	 }
  	 x += pci->metrics.characterWidth;
        }
     }
  
  }
  
  /*
   * Set the hardware scissors to match the clipping rectangles and
   * call the glyph output routine.
   */
  void mach8GlyphWrite( x, y, count, chars, fentry, pGC, pBox, numRects )
  int x, y, count, numRects;
  unsigned char *chars;
  CacheFont8Ptr fentry;
  GCPtr pGC;
  BoxPtr pBox;
  
  {
  int maxAscent, maxDescent;
  
     maxAscent = FONTMAXBOUNDS(pGC->font, ascent);
     maxDescent = FONTMAXBOUNDS(pGC->font, descent);
     WaitQueue(5);
     outw(FRGD_COLOR, (short)pGC->fgPixel);
     outw(MULTIFUNC_CNTL, PIX_CNTL | MIXSEL_EXPBLT | COLCMPOP_F);
     outw(FRGD_MIX, FSS_FRGDCOL | mach8alu[pGC->alu]);
     outw(BKGD_MIX, BSS_BKGDCOL | MIX_DST);
     outw(WRT_MASK, (short)pGC->planemask);
  
     for (; --numRects >= 0; ++pBox) {
       /*
        * Skip all boxes that are completely above or below the text string.
        */
       if( pBox->y2 >= y - maxAscent && pBox->y1 <= y + maxDescent ) {
         WaitQueue(4);
         outw(MULTIFUNC_CNTL, SCISSORS_L | (short)pBox->x1);
         outw(MULTIFUNC_CNTL, SCISSORS_T | (short)pBox->y1);
         outw(MULTIFUNC_CNTL, SCISSORS_R | (short)(pBox->x2 - 1));
         outw(MULTIFUNC_CNTL, SCISSORS_B | (short)(pBox->y2 - 1));
  
         Domach8CPolyText8(x, y, count, chars, fentry, pGC, pBox);
       }
     }
  
     WaitQueue(8);
     outw(MULTIFUNC_CNTL, SCISSORS_T | 0);
     outw(MULTIFUNC_CNTL, SCISSORS_L | 0);
     outw(MULTIFUNC_CNTL, SCISSORS_R | 1023);
     outw(MULTIFUNC_CNTL, SCISSORS_B | 1023);
     outw(RD_MASK, 0xff);
     outw(MULTIFUNC_CNTL, PIX_CNTL | MIXSEL_FRGDMIX | COLCMPOP_F);
     outw(FRGD_MIX, FSS_FRGDCOL | MIX_SRC);
     outw(BKGD_MIX, BSS_BKGDCOL | MIX_SRC);
  
  }
  