/*
 * $Workfile: amd_lx_accel.c $
 * $Revision: #4 $
 * $Author: billm $
 *
 * File Contents: This file is consists of main Xfree
 *                acceleration supported routines like solid fill used
 *                here.
 * Project:       Geode Xfree Frame buffer device driver.
 *
 *     
 */

/* <LIC_AMD_STD>
 * Copyright (c) 2003-2005 Advanced Micro Devices, Inc.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to 
 * deal in the Software without restriction, including without limitation the 
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
 * sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *  
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 *  
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
 * IN THE SOFTWARE.
 * 
 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 * </LIC_AMD_STD>  */
/* <CTL_AMD_STD>
 * </CTL_AMD_STD>  */
/* <DOC_AMD_STD>
 * </DOC_AMD_STD>  */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/* Xfree86 header files */

#include "vgaHW.h"
#include "xf86.h"
#include "xf86_ansic.h"
#include "xaalocal.h"
#include "xf86fbman.h"
#include "miline.h"
#include "xf86_libc.h"
#include "xaarop.h"
#include "nsc.h"

#define LX_FILL_RECT_SUPPORT 1
#define LX_BRES_LINE_SUPPORT 1
#define LX_DASH_LINE_SUPPORT 1
#define LX_MONO_8X8_PAT_SUPPORT 1
#define LX_CLREXP_8X8_PAT_SUPPORT 1
#define LX_SCR2SCREXP_SUPPORT 1
#define LX_SCR2SCRCPY_SUPPORT 1
#define LX_CPU2SCREXP_SUPPORT 1
#define LX_SCANLINE_SUPPORT 1
#define LX_USE_OFFSCRN_MEM 1
#define LX_WRITE_PIXMAP_SUPPORT 1

#undef ulong
typedef unsigned long ulong;
#undef uint
typedef unsigned int uint;
#undef ushort
typedef unsigned short ushort;
#undef uchar
typedef unsigned char uchar;

#if DEBUGLVL>0
extern FILE *zdfp;
#if DEBUGTIM>0
#ifndef USE_RDTSC
#define DBLOG(n,s...) do { if((DEBUGLVL)>=(n)) { long secs,usecs; \
  getsecs(&secs,&usecs); fprintf(zdfp,"%d,%d ",secs,usecs); \
  fprintf(zdfp,s); } } while(0)
#else
#define tsc(n) __asm__ __volatile__ ( \
   " rdtsc" \
 : "=a" (((int*)(&(n)))[0]), "=d" (((int*)(&(n)))[1]) \
 : )
#define DBLOG(n,s...) do { if((DEBUGLVL)>=(n)) { long long t; \
  tsc(t); fprintf(zdfp,"%lld ",t); \
  fprintf(zdfp,s); } } while(0)
#endif
#else
#define DBLOG(n,s...) do { if((DEBUGLVL)>=(n)) fprintf(zdfp,s); } while(0)
#endif
#else
#define DBLOG(n,s...) do {} while(0)
#endif

#define CALC_FBOFFSET(x, y) \
   (((ulong)(y) << gu3_yshift) | \
    ((ulong)(x) << gu3_xshift))

#define OS_UDELAY 0
#if OS_UDELAY > 0
#define OS_USLEEP(usec) usleep(usec);
#else
#define OS_USLEEP(usec)
#endif

#define HOOK(fn) localRecPtr->fn = LX##fn

static int lx0 = -1, ly0 = -1;
static int lx1 = -1, ly1 = -1;
static int ROP;

/* #define ENABLE_PREFETCH CIMGP_ENABLE_PREFETCH */
#define ENABLE_PREFETCH 0
#define BLTFLAGS_HAZARD CIMGP_BLTFLAGS_HAZARD

/* specify dst bounding box, upper left/lower right */
static int
lx_flags0(int x0,int y0, int x1,int y1)
{
   int n = ((ROP^(ROP>>1))&0x55) == 0 || /* no dst */
           x0 >= lx1 || y0 >= ly1 ||     /* rght/below */
           x1 <= lx0 || y1 <= ly0 ?      /* left/above */
              ENABLE_PREFETCH : BLTFLAGS_HAZARD ;
   lx0 = x0;  ly0 = y0;  lx1 = x1;  ly1 = y1;
   return n;
}

/* specify dst bounding box, upper left/WxH */
static int
lx_flags1(int x0,int y0, int w,int h)
{
   return lx_flags0(x0,y0, x0+w,y0+h);
}

/* specify dst bounding box, two points */
static int
lx_flags2(int x0,int y0, int x1,int y1)
{
   int n;
   if( x0 >= x1 ) { n = x0;  x0 = x1-1;  x1 = n+1; }
   if( y0 >= y1 ) { n = y0;  y0 = y1-1;  y1 = n+1; }
   return lx_flags0(x0,y0, x1,y1);
}

/* specify src/dst bounding box, upper left/WxH */
static int
lx_flags3(int x0,int y0, int x1,int y1, int w,int h)
{
   int x2 = x1+w, y2 = y1+h;
   /* dst not hazzard and src not hazzard */
   int n = ( ((ROP^(ROP>>1))&0x55) == 0 ||
              x1 >= lx1 || y1 >= ly1 ||
              x2 <= lx0 || y2 <= ly0 ) &&
           ( ((ROP^(ROP>>2))&0x33) == 0 ||
              x0 >= lx1 || y0 >= ly1 ||
              x0+w <= lx0 || y0+h <= ly0 ) ?
       ENABLE_PREFETCH : BLTFLAGS_HAZARD;
   lx0 = x1;  ly0 = y1;  lx1 = x2;  ly1 = y2;
   return n;
}

static void
lx_endpt(int x,int y,int len, int mag,int min,int err,int oct, int *px, int *py)
{
   int u = len-1;
   int v = (u*min-err)/mag;

   switch( oct ) {
   default:
   case 0:  x += u;  y += v;  break;
   case 1:  x += v;  y += u;  break;
   case 2:  x += u;  y -= v;  break;
   case 3:  x += v;  y -= u;  break;
   case 4:  x -= u;  y += v;  break;
   case 5:  x -= v;  y += u;  break;
   case 6:  x -= u;  y -= v;  break;
   case 7:  x -= v;  y -= u;  break;
   }
   *px = x;  *py = y;
}

/* static storage declarations */

typedef struct sGBltBox {
   ulong x, y;
   ulong w, h;
   ulong color;
   int bpp, transparent;
} GBltBox;

static GBltBox giwr;
static GBltBox gc2s;

typedef struct sGDashLine {
   ulong pat;
   int len;
   int fg;
   int bg;
} GDashLine;

static GDashLine gdln;

static uint gu3_xshift = 1;
static uint gu3_yshift = 1;
static uint gu3_img_fmt = 0;
#if !LX_USE_OFFSCRN_MEM
static uint ImgBufOffset;
#else
static uchar *ImgLnsBuffers;
#endif
static uchar *ClrLnsBuffers;
static XAAInfoRecPtr localRecPtr;

static int lx_src_fmt[4] = {
   CIMGP_SOURCE_FMT_8BPP_INDEXED,
   CIMGP_SOURCE_FMT_0_5_6_5,
   CIMGP_SOURCE_FMT_24BPP,
   CIMGP_SOURCE_FMT_8_8_8_8
};


/* pat  0xF0 */
/* src  0xCC */
/* dst  0xAA */

/* (src FUNC dst) */

static const int SDfn[16] = { 
   0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE,
   0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF
};

/* ((src FUNC dst) AND pat-mask) OR (dst AND (NOT pat-mask)) */

static const int SDfn_PM[16] = {
   0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
   0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA
};

/* (pat FUNC dst) */

static int PDfn[16] = {
   0x00, 0xA0, 0x50, 0xF0, 0x0A, 0xAA, 0x5A, 0xFA,
   0x05, 0xA5, 0x55, 0xF5, 0x0F, 0xAF, 0x5F, 0xFF
};

/* ((pat FUNC dst) AND src-mask) OR (dst AND (NOT src-mask)) */

static int PDfn_SM[16] = {
   0x22, 0xA2, 0x62, 0xE2, 0x2A, 0xAA, 0x6A, 0xEA,
   0x26, 0xA6, 0x66, 0xE6, 0x2E, 0xAE, 0x6E, 0xEE
};



/*----------------------------------------------------------------------------
 * LXAccelSync.
 *
 * Description  :This function is called to synchronize with the graphics
 *               engine and it waits the graphic engine is idle.  This is
 *               required before allowing direct access to the framebuffer.
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *
 * Returns              :none
 *---------------------------------------------------------------------------*/
void
LXAccelSync(ScrnInfoPtr pScrni)
{
   DBLOG(3,"LXAccelSync()\n");
   while( gp_test_blt_busy() != 0 ) { OS_USLEEP(OS_UDELAY) }
}

#if LX_FILL_RECT_SUPPORT
/*----------------------------------------------------------------------------
 * LXSetupForSolidFill.
 *
 * Description  :The SetupFor and Subsequent SolidFill(Rect) provide
 *               filling rectangular areas of the screen with a
 *               foreground color.
 *
 * Parameters.
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *   color        int     foreground fill color
 *    rop         int     unmapped raster op
 * planemask     uint     -1 (fill) or pattern data
 *
 * Returns              :none
 *--------------------------------------------------------------------------*/
static void
LXSetupForSolidFill(ScrnInfoPtr pScrni, int color, int rop, uint planemask)
{
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSetupForSolidFill(%#x,%#x,%#x)\n",color,rop,planemask);
   rop &= 0x0F;
   gp_declare_blt(0);
   if( planemask == ~0U ) { /* fill with color */
      gp_set_raster_operation(ROP=SDfn[rop]);
   }
   else { /* select rop that uses source data for planemask */
      gp_set_raster_operation(ROP=SDfn_PM[rop]);
      gp_set_solid_pattern(planemask);
   }
   gp_set_solid_source(color);
   gp_set_strides(pGeode->AccelPitch,pGeode->AccelPitch);
   gp_write_parameters();
}

 /*----------------------------------------------------------------------------
 * LXSubsequentSolidFillRect.
 *
 * Description  :see LXSetupForSolidFill.
 *
 * Parameters.
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     x          int     destination x offset
 *     y          int     destination y offset
 *     w          int     fill area width (pixels)
 *     h          int     fill area height (pixels)
 *
 * Returns      :none
 *
 * Sample application uses:
 *   - Window backgrounds. 
 *   - pull down highlighting.
 *   - x11perf: rectangle tests (-rect500).
 *   - x11perf: fill trapezoid tests (-trap100).
 *   - x11perf: horizontal line segments (-hseg500).
 *---------------------------------------------------------------------------*/
static void
LXSubsequentSolidFillRect(ScrnInfoPtr pScrni, int x, int y, int w, int h)
{
   int flags;
   DBLOG(2,"LXSubsequentSolidFillRect() at %d,%d %dx%d\n",x,y,w,h);
   flags = lx_flags1(x,y,w,h);
   gp_declare_blt(flags);
   gp_pattern_fill(CALC_FBOFFSET(x,y), w, h);
}

/* LX_FILL_RECT_SUPPORT */
#endif

#if LX_CLREXP_8X8_PAT_SUPPORT
/*----------------------------------------------------------------------------
 * LXSetupForColor8x8PatternFill
 *
 * Description  :8x8 color pattern data is 64 pixels of full color data
 *               stored linearly in offscreen video memory.  These patterns
 *               are useful as a substitute for 8x8 mono patterns when tiling,
 *               doing opaque stipples, or regular stipples. 
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *    patx        int     x offset to pattern data
 *    paty        int     y offset to pattern data
 *    rop         int     unmapped raster operation
 * planemask     uint     -1 (copy) or pattern data
 * trans_color    int     -1 (copy) or transparent color (not enabled)
 *                         trans color only supported on source channel
 *                         or in monochrome pattern channel
 * 
 * Returns      :none.
 *
 *---------------------------------------------------------------------------*/

static void
LXSetupForColor8x8PatternFill(ScrnInfoPtr pScrni, int patx, int paty, int rop,
                               uint planemask, int trans_color)
{
   unsigned long *pat_8x8;
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSetupForColor8x8PatternFill() pat %#x,%#x rop %#x %#x %#x\n"
           ,patx,paty,rop,planemask,trans_color);
   pat_8x8 = (unsigned long *)(pGeode->FBBase+CALC_FBOFFSET(patx,paty));
   /* since the cache may be loaded by blt, we must wait here */
   LXAccelSync(pScrni);
   gp_set_color_pattern(pat_8x8,gu3_img_fmt,0,0);
   rop &= 0x0F;
   gp_declare_blt(0);
   if( planemask == ~0U ) { /* fill with pattern */
      gp_set_raster_operation(ROP=PDfn[rop]);
   }
   else { /* select rop that uses source data for planemask */
      gp_set_raster_operation(ROP=PDfn_SM[rop]);
      gp_set_solid_source((ulong)planemask);
   }
   gp_set_strides(pGeode->AccelPitch,pGeode->AccelPitch);
   gp_write_parameters();
}

/*----------------------------------------------------------------------------
 * LXSubsequentColor8x8PatternFillRect
 *
 * Description  :see LXSetupForColor8x8PatternFill.
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *   patx         int     pattern phase x offset
 *   paty         int     pattern phase y offset
 *      x         int     destination x offset
 *      y         int     destination y offset
 *      w         int     fill area width (pixels)
 *      h         int     fill area height (pixels)
 *              
 * Returns      :none
 *
 * Sample application uses:
 *   - Patterned desktops
 *   - x11perf: stippled rectangle tests (-srect500).
 *   - x11perf: opaque stippled rectangle tests (-osrect500).
 *--------------------------------------------------------------------------*/
static void
LXSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrni, int patx, int paty,
                                     int x, int y, int w, int h)
{
   int flags;
   DBLOG(2,"LXSubsequentColor8x8PatternFillRect() patxy %d,%d at %d,%d %dsx%d\n",
           patx,paty,x,y,w,h);
   flags = lx_flags1(x,y,w,h);
   gp_declare_blt(flags);
   gp_set_pattern_origin(patx,paty);
   gp_pattern_fill(CALC_FBOFFSET(x,y), w, h);
}

/* LX_CLREXP_8X8_PAT_SUPPORT */
#endif

#if LX_MONO_8X8_PAT_SUPPORT
/*----------------------------------------------------------------------------
 * LXSetupForMono8x8PatternFill
 *
 * Description  :8x8 mono pattern data is 64 bits of color expansion data
 *               with ones indicating the foreground color and zeros
 *               indicating the background color.  These patterns are
 *               useful when tiling, doing opaque stipples, or regular
 *               stipples. 
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *    patx        int     x offset to pattern data
 *    paty        int     y offset to pattern data
 *     fg         int     foreground color
 *     bg         int     -1 (transparent) or background color
 *    rop         int     unmapped raster operation
 * planemask     uint     -1 (copy) or pattern data
 * 
 * Returns      :none.
 *
 * Comments     :none.
 *
 *--------------------------------------------------------------------------*/
static void
LXSetupForMono8x8PatternFill(ScrnInfoPtr pScrni, int patx, int paty,
                                int fg, int bg, int rop, uint planemask)
{
   int trans;
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSetupForMono8x8PatternFill() pat %#x,%#x fg %#x bg %#x %#x %#x\n",
            patx,paty,fg,bg,rop,planemask);
   rop &= 0x0F;
   gp_declare_blt(0);
   if( planemask == ~0U ) { /* fill with pattern */
      gp_set_raster_operation(ROP=PDfn[rop]);
   }
   else { /* select rop that uses source data for planemask */
      gp_set_raster_operation(ROP=PDfn_SM[rop]);
      gp_set_solid_source((ulong)planemask);
   }
   trans =  bg==-1 ? 1 : 0;
   gp_set_mono_pattern(bg,fg, patx,paty, trans, 0, 0);
   gp_set_strides(pGeode->AccelPitch,pGeode->AccelPitch);
   gp_write_parameters();
}

/*----------------------------------------------------------------------------
 * LXSubsequentMono8x8PatternFillRect
 *
 * Description  :see LXSetupForMono8x8PatternFill
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *   patx         int     pattern phase x offset
 *   paty         int     pattern phase y offset
 *      x         int     destination x offset
 *      y         int     destination y offset
 *      w         int     fill area width (pixels)
 *      h         int     fill area height (pixels)

 * Returns      :none
 *
 * Sample application uses:
 *   - Patterned desktops
 *   - x11perf: stippled rectangle tests (-srect500).
 *   - x11perf: opaque stippled rectangle tests (-osrect500).
 *--------------------------------------------------------------------------*/
static void
LXSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrni, int patx, int paty,
	     		          int x, int y, int w, int h)
{
   int flags;
   DBLOG(2,"LXSubsequentMono8x8PatternFillRect() pat %#x,%#x at %d,%d %dx%d\n",patx,paty,x,y,w,h);
   flags = lx_flags1(x,y,w,h);
   gp_declare_blt(flags);
   gp_set_pattern_origin(patx,paty);
   gp_pattern_fill(CALC_FBOFFSET(x,y), w,h);
}

/* LX_MONO_8X8_PAT_SUPPORT */
#endif

#if LX_SCR2SCRCPY_SUPPORT
/*----------------------------------------------------------------------------
 * LXSetupForScreenToScreenCopy
 *
 * Description  :SetupFor and Subsequent ScreenToScreenCopy functions
 *               provide an interface for copying rectangular areas from
 *               video memory to video memory.
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *   xdir         int     x copy direction (up/dn)
 *   ydir         int     y copy direction (up/dn)
 *    rop         int     unmapped raster operation
 * planemask     uint     -1 (copy) or pattern data
 * trans_color    int     -1 (copy) or transparent color
 *
 * Returns      :none
 *---------------------------------------------------------------------------*/
static void
LXSetupForScreenToScreenCopy(ScrnInfoPtr pScrni, int xdir, int ydir, int rop,
                              uint planemask, int trans_color)
{
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSetupForScreenToScreenCopy() xd%d yd%d rop %#x %#x %#x\n",
           xdir,ydir,rop,planemask,trans_color);
   rop &= 0x0F;
   gp_declare_blt(0);
   if( planemask == ~0U ) {
      gp_set_raster_operation(ROP=SDfn[rop]);
   }
   else {
      gp_set_raster_operation(ROP=SDfn_PM[rop]);
      gp_set_solid_pattern((ulong)planemask);
   }
   gp_set_strides(pGeode->AccelPitch, pGeode->AccelPitch);
   gp_write_parameters();
   gc2s.transparent = (trans_color == -1) ? 0 : 1;
   gc2s.color = trans_color;
}

/*----------------------------------------------------------------------------
 * LXSubsquentScreenToScreenCopy
 *
 * Description  :see LXSetupForScreenToScreenCopy.
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     x1         int     source x offset
 *     y1         int     source y offset
 *     x2         int     destination x offset
 *     y2         int     destination y offset
 *      w         int     copy area width (pixels)
 *      h         int     copy area height (pixels)
 * 
 * Returns      :none
 *
 * Sample application uses (non-transparent):
 *   - Moving windows.
 *   - x11perf: scroll tests (-scroll500).
 *   - x11perf: copy from window to window (-copywinwin500).
 *---------------------------------------------------------------------------*/
static void
LXSubsequentScreenToScreenCopy(ScrnInfoPtr pScrni,
                                int x1, int y1, int x2, int y2, int w, int h)
{
   int flags;
   DBLOG(2,"LXSubsequentScreenToScreenCopy() from %d,%d to %d,%d %dx%d\n",x1,y1,x2,y2,w,h);
   flags = lx_flags3(x1,y1,x2,y2,w,h);
   gp_declare_blt(flags);
   if( gc2s.transparent ) {
      gp_set_source_transparency(gc2s.color,~0);
   }
   flags = 0;
   if( x2 > x1 ) flags |= 1;
   if( y2 > y1 ) flags |= 2;
   gp_screen_to_screen_blt(CALC_FBOFFSET(x2,y2), CALC_FBOFFSET(x1,y1), w,h, flags);
}

/* LX_SCR2SCRCPY_SUPPORT */
#endif

#if LX_SCANLINE_SUPPORT
/*----------------------------------------------------------------------------
 * LXSetupForScanlineImageWrite
 *
 * Description  :SetupFor/Subsequent ScanlineImageWrite and ImageWriteScanline
 *               transfer full color pixel data from system memory to video
 *               memory.  This is useful for dealing with alignment issues and
 *               performing raster ops on the data.
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *    rop         int     unmapped raster operation
 * planemask     uint     -1 (copy) or pattern data
 *    bpp         int     bits per pixel (unused)
 *  depth         int     color depth (unused)
 *
 * Returns      :none
 *
 *  x11perf -putimage10  
 *  x11perf -putimage100 
 *  x11perf -putimage500 
*----------------------------------------------------------------------------
*/
static void
LXSetupForScanlineImageWrite(ScrnInfoPtr pScrni, int rop, uint planemask,
                              int trans_color, int bpp, int depth)
{
   int Bpp = (bpp+7) >> 3;
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSetupForScanlineImageWrite() rop %#x %#x %#x %d %d\n",
           rop,planemask,trans_color,bpp,depth);
   rop &= 0x0F;
   gp_set_source_format(lx_src_fmt[Bpp-1]);
   gp_declare_blt(0);
   if( planemask == ~0U ) {
      gp_set_raster_operation(ROP=SDfn[rop]);
   }
   else {
      gp_set_raster_operation(ROP=SDfn_PM[rop]);
      gp_set_solid_pattern(planemask);
   }
   gp_set_strides(pGeode->AccelPitch,pGeode->AccelPitch);
   gp_write_parameters();
   giwr.transparent = (trans_color == -1) ? 0 : 1;
   giwr.color = trans_color;
}

/*----------------------------------------------------------------------------
 * LXSubsequentScanlineImageWriteRect
 *
 * Description  : see LXSetupForScanlineImageWrite.
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *      x         int     destination x offset
 *      y         int     destination y offset
 *      w         int     copy area width (pixels)
 *      h         int     copy area height (pixels)
 * skipleft       int     x margin (pixels) to skip (not enabled)
 *      
 * Returns      :none
 *---------------------------------------------------------------------------*/
static void
LXSubsequentScanlineImageWriteRect(ScrnInfoPtr pScrni,
                                    int x, int y, int w, int h, int skipleft)
{
   DBLOG(2,"LXSubsequentScanlineImageWriteRect() rop %d,%d %dx%d %d\n",x,y,w,h,skipleft);
   giwr.x = x;  giwr.y = y;
   giwr.w = w;  giwr.h = h;
   /* since the image buffer must be not busy (it may be busy from
    * a previous ScanlineWriteImage), we must add a Sync here */
#if !LX_USE_OFFSCRN_MEM
   LXAccelSync(pScrni);
#endif
}

/*----------------------------------------------------------------------------
 * LXSubsquentImageWriteScanline
 *
 * Description  : see LXSetupForScanlineImageWrite.
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *  bufno         int     scanline number in write group
 *
 * Returns      :none
 *
 * Sample application uses (non-transparent):
 *   - Moving windows.
 *   - x11perf: scroll tests (-scroll500).
 *   - x11perf: copy from window to window (-copywinwin500).
 *
 *---------------------------------------------------------------------------*/
static void
LXSubsequentImageWriteScanline(ScrnInfoPtr pScrni, int bufno)
{
   GeodePtr pGeode;
   int blt_height = 0;
   DBLOG(3,"LXSubsequentImageWriteScanline() %d\n",bufno);
   pGeode = GEODEPTR(pScrni);

   if( (blt_height=pGeode->NoOfImgBuffers) > giwr.h )
      blt_height = giwr.h;
   if( ++bufno < blt_height ) return;

   gp_declare_blt(ENABLE_PREFETCH);
   if( giwr.transparent ) {
      gp_set_source_transparency(giwr.color,~0);
   }
#if !LX_USE_OFFSCRN_MEM
   gp_screen_to_screen_blt(CALC_FBOFFSET(giwr.x,giwr.y), ImgBufOffset,
                           giwr.w, blt_height, 0);
   LXAccelSync(pScrni);
#else
   gp_color_bitmap_to_screen_blt(CALC_FBOFFSET(giwr.x,giwr.y), 0,
                           giwr.w, blt_height, ImgLnsBuffers, pGeode->AccelPitch);
#endif
   giwr.h -= blt_height;
   giwr.y += blt_height;
}

/* LX_SCANLINE_SUPPORT */
#endif

#if LX_CPU2SCREXP_SUPPORT
/*----------------------------------------------------------------------------
 * LXSetupForScanlineCPUToScreenColorExpandFill
 *
 * Description  :SetupFor/Subsequent CPUToScreenColorExpandFill and
 *               ColorExpandScanline routines provide an interface for
 *               doing expansion blits from source patterns stored in
 *               system memory.
 *                              
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     fg         int     foreground color
 *     bg         int     -1 (transparent) or background color
 *    rop         int     unmapped raster operation
 * planemask     uint     -1 (copy) or pattern data
 *
 * Returns      :none.
 *---------------------------------------------------------------------------*/

static void
LXSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrni,
                                      int fg, int bg, int rop,
                                      uint planemask)
{
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSetupForScanlineCPUToScreenColorExpandFill() fg %#x bg %#x rop %#x %#x\n",
            fg,bg,rop,planemask);
   rop &= 0x0F;
   gp_declare_blt(0);
   if( planemask == ~0U ) {
      gp_set_raster_operation(ROP=SDfn[rop]);
   }
   else {
      gp_set_raster_operation(ROP=SDfn_PM[rop]);
      gp_set_solid_pattern(planemask);
   }
   gp_set_mono_source(bg, fg, (bg == -1));
   gp_set_strides(pGeode->AccelPitch, pGeode->AccelPitch);
   gp_write_parameters();
   gc2s.bpp = 1;
   gc2s.transparent = 0;
   gc2s.color = 0;
}

/*----------------------------------------------------------------------------
 * LXSubsequentScanlineCPUToScreenColorExpandFill
 *
 * Description  :see LXSetupForScanlineCPUToScreenColorExpandFill
 *
 * Parameters:
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     x          int     destination x offset
 *     y          int     destination y offset
 *     w          int     fill area width (pixels)
 *     h          int     fill area height (pixels)
 *      
 * Returns      :none
 *
 *---------------------------------------------------------------------------*/
static void
LXSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrni,
                                    int x, int y, int w, int h, int skipleft)
{
   DBLOG(2,"LXSubsequentScanlineCPUToScreenColorExpandFill() %d,%d %dx%d %d\n",
            x,y,w,h,skipleft);
   gc2s.x = x;  gc2s.y = y;  
   gc2s.w = w;  gc2s.h = h;  
}

/*----------------------------------------------------------------------------
 * LXSubsequentColorExpandScanline
 *
 * Description  :see LXSetupForScanlineCPUToScreenColorExpandFill
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *  bufno         int     scanline number in write group
 *
 * Returns      :none
*----------------------------------------------------------------------------
*/
static void
LXSubsequentColorExpandScanline(ScrnInfoPtr pScrni, int bufno)
{
   GeodePtr pGeode;
   ulong srcpitch;
   int blt_height = 0;
   DBLOG(3,"LXSubsequentColorExpandScanline() %d\n",bufno);
   pGeode = GEODEPTR(pScrni);

   if( (blt_height=pGeode->NoOfImgBuffers) > gc2s.h )
      blt_height = gc2s.h;
   if( ++bufno < blt_height ) return;

   gp_declare_blt(ENABLE_PREFETCH);
   /* convert from bits to dwords */
   srcpitch = ((pGeode->AccelPitch+31) >> 5) << 2;
   gp_mono_bitmap_to_screen_blt(CALC_FBOFFSET(gc2s.x,gc2s.y), 0, gc2s.w,blt_height,
                                ClrLnsBuffers,srcpitch);
   gc2s.h -= blt_height;
   gc2s.y += blt_height;
}

/* LX_CPU2SCREXP_SUPPORT */
#endif

#if LX_SCR2SCREXP_SUPPORT

/*----------------------------------------------------------------------------
 * LXSetupForScreenToScreenColorExpandFill
 *
 * Description  :SetupFor/Subsequent ScreenToScreenColorExpandFill and
 *               ColorExpandScanline routines provide an interface for
 *               doing expansion blits from source patterns stored in
 *               video memory.
 *                              
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     fg         int     foreground color
 *     bg         int     -1 (transparent) or background color
 *    rop         int     unmapped raster operation
 * planemask     uint     -1 (copy) or pattern data
 *
 * Returns      :none.
 *---------------------------------------------------------------------------*/

static void
LXSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrni, int fg, int bg,
                                         int rop, uint planemask)
{
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSetupForScreenToScreenColorExpandFill() fg %#x bg %#x rop %#x %#x\n",
	   fg,bg,rop,planemask);
   rop &= 0x0F;
   gp_declare_blt(0);
   if( planemask == ~0U ) {
      gp_set_raster_operation(ROP=SDfn[rop]);
   }
   else {
      gp_set_raster_operation(ROP=SDfn_PM[rop]);
      gp_set_solid_pattern(planemask);
   }
   gp_set_strides(pGeode->AccelPitch, pGeode->AccelPitch);
   gp_set_mono_source(bg, fg, (bg == -1));
   gp_write_parameters();
}

/*----------------------------------------------------------------------------
 * LXSubsequentScreenToScreenColorExpandFill
 *
 * Description  :see LXSetupForScreenToScreenColorExpandFill
 *
 * Parameters:
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     x          int     destination x offset
 *     y          int     destination y offset
 *     w          int     fill area width (pixels)
 *     h          int     fill area height (pixels)
 * offset         int     initial x offset
 *      
 * Returns      :none
 *
 *---------------------------------------------------------------------------*/
static void
LXSubsequentScreenToScreenColorExpandFill(ScrnInfoPtr pScrni,
                                           int x, int y, int w, int h,
                                           int srcx, int srcy, int offset)
{
   int flags;
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSubsequentScreenToScreenColorExpandFill() %d,%d %dx%d %d,%d %d\n",
	   x,y,w,h,srcx,srcy,offset);
   flags = lx_flags3(srcx,srcy,x,y,w,h);
   gp_declare_blt(flags);
   gp_set_strides(pGeode->AccelPitch, pGeode->AccelPitch);
   gp_mono_expand_blt(CALC_FBOFFSET(x,y), CALC_FBOFFSET(srcx,srcy), offset, w,h, 0);
}

/* LX_SCR2SCREXP_SUPPORT */
#endif

#define VM_X_MAJOR 0
#define VM_Y_MAJOR 1
#define VM_MAJOR_INC 2
#define VM_MAJOR_DEC 0
#define VM_MINOR_INC 4
#define VM_MINOR_DEC 0

static ushort vmode[] = {
   VM_X_MAJOR | VM_MAJOR_INC | VM_MINOR_INC,  /* !XDECREASING !YDECREASING !YMAJOR */
   VM_Y_MAJOR | VM_MAJOR_INC | VM_MINOR_INC,  /* !XDECREASING !YDECREASING  YMAJOR */
   VM_X_MAJOR | VM_MAJOR_INC | VM_MINOR_DEC,  /* !XDECREASING  YDECREASING !YMAJOR */
   VM_Y_MAJOR | VM_MAJOR_DEC | VM_MINOR_INC,  /* !XDECREASING  YDECREASING  YMAJOR */
   VM_X_MAJOR | VM_MAJOR_DEC | VM_MINOR_INC,  /*  XDECREASING !YDECREASING !YMAJOR */
   VM_Y_MAJOR | VM_MAJOR_INC | VM_MINOR_DEC,  /*  XDECREASING !YDECREASING  YMAJOR */
   VM_X_MAJOR | VM_MAJOR_DEC | VM_MINOR_DEC,  /*  XDECREASING  YDECREASING !YMAJOR */
   VM_Y_MAJOR | VM_MAJOR_DEC | VM_MINOR_DEC,  /*  XDECREASING  YDECREASING  YMAJOR */
};

#define ABS(_val1, _val2) (((_val1) > (_val2)) ? ((_val1)-(_val2)) : ((_val2) - (_val1)))

#if LX_BRES_LINE_SUPPORT
/*----------------------------------------------------------------------------
 * LXSetupForSolidLine
 *
 * Description  :SetupForSolidLine and Subsequent HorVertLine TwoPointLine
 *               BresenhamLine provides an interface for drawing thin
 *               solid lines.
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *   color        int     foreground fill color
 *    rop         int     unmapped raster op
 * planemask     uint     -1 (fill) or pattern data (not enabled)
 * 
 * Returns              :none
*---------------------------------------------------------------------------*/
static void
LXSetupForSolidLine(ScrnInfoPtr pScrni,
                     int color, int rop, uint planemask)
{
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSetupForSolidLine() %#x %#x %#x\n",color,rop,planemask);
   rop &= 0x0F;
   gp_declare_vector(CIMGP_BLTFLAGS_HAZARD);
   if( planemask == ~0U ) {
      gp_set_raster_operation(ROP=PDfn[rop]);
   }
   else {
      gp_set_raster_operation(ROP=PDfn_SM[rop]);
      gp_set_solid_source(planemask);
   }
   gp_set_solid_pattern((ulong)color);
   gp_set_strides(pGeode->AccelPitch, pGeode->AccelPitch);
   gp_write_parameters();
}

/*---------------------------------------------------------------------------
 * LXSubsequentSolidBresenhamLine
 *
 * Description  :see LXSetupForSolidLine
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     x1         int     destination x offset
 *     y1         int     destination y offset
 * absmaj         int     Bresenman absolute major
 * absmin         int     Bresenman absolute minor
 *    err         int     Bresenman initial error term
 *    len         int     length of the vector (pixels)
 * octant         int     specifies sign and magnitude relationships
 *                         used to determine axis of magor rendering
 *                         and direction of vector progress.
 *
 * Returns      :none
 *
 *   - Window outlines on window move.
 *   - x11perf: line segments (-line500).
 *   - x11perf: line segments (-seg500).
 *---------------------------------------------------------------------------*/
static void
LXSubsequentSolidBresenhamLine(ScrnInfoPtr pScrni, int x1, int y1,
                           int absmaj, int absmin, int err,
                           int len, int octant)
{
   int x2, y2, flags;
   long axial, diagn;
   DBLOG(2,"LXSubsequentSolidBresenhamLine() %d,%d %d %d, %d %d, %d\n",
           x1,y1,absmaj,absmin,err,len,octant);
   if( len <= 0 ) return;
   lx_endpt(x1,y1,len,absmaj,absmin,err,octant,&x2,&y2);
   flags = lx_flags2(x1,y1,x2+1,y2+1);
   gp_declare_vector(flags);
   axial = absmin;
   err += axial;
   diagn = absmin-absmaj;
   gp_bresenham_line(CALC_FBOFFSET(x1,y1), len, err, axial, diagn, vmode[octant]);
}

/*---------------------------------------------------------------------------
 * LXSubsequentSolidTwoPointLine
 *
 * Description  :see LXSetupForSolidLine
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     x0         int     destination x start offset
 *     y0         int     destination y start offset
 *     x1         int     destination x end offset
 *     y1         int     destination y end offset
 *  flags         int     OMIT_LAST, dont draw last pixel (not used)
 *
 * Returns      :none
 *---------------------------------------------------------------------------*/
static void
LXSubsequentSolidTwoPointLine(ScrnInfoPtr pScrni, int x0, int y0,
                               int x1, int y1, int flags)
{
   long dx, dy, dmaj, dmin, octant, bias;
   long axial, diagn, err, len;
   DBLOG(2,"LXSubsequentSolidTwoPointLine() %d,%d %d,%d, %#x\n",
           x0,y0,x1,y1,flags);

   if( (dx=x1-x0) < 0 ) dx = -dx;
   if( (dy=y1-y0) < 0 ) dy = -dy;
   if( dy >= dx ) {
      dmaj = dy;  dmin = dx;
      octant = YMAJOR;
   }
   else {
      dmaj = dx;  dmin = dy;
      octant = 0;
   }
   len = dmaj;
   if( (flags&OMIT_LAST) == 0 ) ++len;
   if( len <= 0 ) return;
   if (x1 < x0) octant |= XDECREASING;
   if (y1 < y0) octant |= YDECREASING;

   flags = lx_flags2(x0,y0,x1+1,y1+1);
   gp_declare_vector(flags);
   axial = dmin << 1;
   bias = miGetZeroLineBias(pScrni->pScreen);
   err = axial - dmaj - ((bias>>octant) & 1);
   diagn = (dmin-dmaj) << 1;
   gp_bresenham_line(CALC_FBOFFSET(x0,y0), len, err, axial, diagn, vmode[octant]);
}

/*---------------------------------------------------------------------------
 * LXSubsequentSolidHorVertLine
 *
 * Description  :see LXSetupForSolidLine
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     x          int     destination x offset
 *     y          int     destination y offset
 *    len         int     length of the vector (pixels)
 *    dir         int     DEGREES_270 or DEGREES_0 line direction
 *
 * Sample application uses:
 *   - Window outlines on window move.
 *   - x11perf: line segments (-hseg500).
 *   - x11perf: line segments (-vseg500).
 *---------------------------------------------------------------------------
 */
static void
LXSubsequentSolidHorVertLine(ScrnInfoPtr pScrni,
                         int x, int y, int len, int dir)
{
   int flags, w, h;
   DBLOG(2,"LXSubsequentHorVertLine() %d,%d %d %d\n",x,y,len,dir);
   gp_declare_blt(0);
   if( dir == DEGREES_0 ) {
      w = len;  h = 1;
   }
   else {
      w = 1;  h = len;
   }
   flags = lx_flags1(x,y,w,h);
   gp_declare_blt(flags);
   gp_pattern_fill(CALC_FBOFFSET(x,y),
                   ((dir == DEGREES_0) ? len : 1),
                   ((dir == DEGREES_0) ? 1 : len));
}

/* LX_BRES_LINE_SUPPORT */
#endif

#if LX_DASH_LINE_SUPPORT
/*----------------------------------------------------------------------------
 * LXSetupForDashedLine
 *
 * Description  :SetupForDashedLine and Subsequent TwoPointLine
 *               BresenhamLine provides an interface for drawing thin
 *               dashed lines.
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     fg         int     foreground fill color
 *     bg         int     -1 (transp) or background fill color
 *    rop         int     unmapped raster op
 * planemask     uint     -1 (fill) or pattern data (not enabled)
 *  length        int     pattern length (bits)
 * pattern     uchar*     dash pattern mask
 * 
 * Returns              :none
*---------------------------------------------------------------------------*/
static void
LXSetupForDashedLine(ScrnInfoPtr pScrni,
                      int fg, int bg, int rop, uint planemask,
                      int length, uchar *pattern)
{
   int n;
   GeodePtr pGeode = GEODEPTR(pScrni);
   DBLOG(2,"LXSetupForDashedLine() fg %#x bg %#x rop %#x pm %#x len %d, pat %#x\n",
	   fg,bg,rop,planemask,length,*(ulong*)pattern);
   gdln.fg = fg;
   gdln.bg = bg;
   gdln.len = length;
   n = (length+7)/8;
   if( n > sizeof(gdln.pat) )
      n = sizeof(gdln.pat);
   memcpy(&gdln.pat,pattern,n);
   rop &= 0x0F;
   gp_declare_vector(CIMGP_BLTFLAGS_HAZARD);
   if( planemask == ~0U ) {
      gp_set_raster_operation(ROP=PDfn[rop]);
   }
   else {
      gp_set_raster_operation(ROP=PDfn_SM[rop]);
      gp_set_solid_source(planemask);
   }
   gp_set_strides(pGeode->AccelPitch, pGeode->AccelPitch);
   gp_write_parameters();
}

/*---------------------------------------------------------------------------
 * LXSubsequentDashedBresenhamLine
 *
 * Description  :see LXSetupForDashedLine
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     x1         int     destination x offset
 *     y1         int     destination y offset
 * absmaj         int     Bresenman absolute major
 * absmin         int     Bresenman absolute minor
 *    err         int     Bresenman initial error term
 *    len         int     length of the vector (pixels)
 * octant         int     specifies sign and magnitude relationships
 *                         used to determine axis of magor rendering
 *                         and direction of vector progress.
 *  phase         int     initial pattern offset at x1,y1
 *
 * Returns      :none
 *---------------------------------------------------------------------------*/
static void
LXSubsequentDashedBresenhamLine(ScrnInfoPtr pScrni, int x1, int y1,
                           int absmaj, int absmin, int err,
                           int len, int octant, int phase)
{
   int x2, y2, flags;
   long axial, diagn;
   ulong pattern;
   DBLOG(2,"LXSubsequentDashedBresenhamLine() %d,%d %d %d, %d %d, %d %d\n",
           x1,y1,absmaj,absmin,err,len,octant,phase);
   if( len <= 0 ) return;
   pattern = gdln.pat;
   if( phase > 0 ) {
      int n = gdln.len-phase;
      pattern = ((pattern>>phase)&((1UL<<n)-1)) | (pattern<<n);
   }
   gp_set_vector_pattern(pattern,gdln.fg,gdln.len);
   lx_endpt(x1,y1,len,absmaj,absmin,err,octant,&x2,&y2);
   flags = lx_flags2(x1,y1,x2+1,y2+1);
   gp_declare_vector(flags);
   axial = absmin;
   err += axial;
   diagn = absmin-absmaj;
   gp_bresenham_line(CALC_FBOFFSET(x1,y1), len, err, axial, diagn, vmode[octant]);
}

/*---------------------------------------------------------------------------
 * LXSubsequentDashedTwoPointLine
 *
 * Description  :see LXSetupForDashedLine
 *
 *    Arg        Type     Comment
 *  pScrni   ScrnInfoPtr  pointer to Screeen info
 *     x0         int     destination x start offset
 *     y0         int     destination y start offset
 *     x1         int     destination x end offset
 *     y1         int     destination y end offset
 *  flags         int     OMIT_LAST, dont draw last pixel (not used)
 *  phase         int     initial pattern offset at x1,y1
 *
 * Returns      :none
 *---------------------------------------------------------------------------*/
static void
LXSubsequentDashedTwoPointLine(ScrnInfoPtr pScrni, int x0, int y0,
                               int x1, int y1, int flags, int phase)
{
   ulong pattern;
   long dx, dy, dmaj, dmin, octant, bias;
   long axial, diagn, err, len;
   DBLOG(2,"LXSubsequentDashedTwoPointLine() %d,%d %d,%d, %#x %d\n",
           x0,y0,x1,y1,flags,phase);

   if( (dx=x1-x0) < 0 ) dx = -dx;
   if( (dy=y1-y0) < 0 ) dy = -dy;
   if( dy >= dx ) {
      dmaj = dy;  dmin = dx;
      octant = YMAJOR;
   }
   else {
      dmaj = dx;  dmin = dy;
      octant = 0;
   }
   len = dmaj;
   if( (flags&OMIT_LAST) == 0 ) ++len;
   if( len <= 0 ) return;
   if (x1 < x0) octant |= XDECREASING;
   if (y1 < y0) octant |= YDECREASING;

   pattern = gdln.pat;
   if( phase > 0 ) {
      int n = gdln.len-phase;
      pattern = ((pattern>>phase)&((1UL<<n)-1)) | (pattern<<n);
   }
   gp_set_vector_pattern(pattern,gdln.fg,gdln.len);
   flags = lx_flags2(x0,y0,x1+1,y1+1);
   gp_declare_vector(flags);

   axial = dmin << 1;
   bias = miGetZeroLineBias(pScrni->pScreen);
   err = axial-dmaj - ((bias>>octant) & 1);
   diagn = (dmin-dmaj) << 1;
   gp_bresenham_line(CALC_FBOFFSET(x0,y0), len, err, axial, diagn, vmode[octant]);
}

/* LX_DASH_LINE_SUPPORT */
#endif

#if LX_WRITE_PIXMAP_SUPPORT
void
LXWritePixmap(ScrnInfoPtr pScrni, int x, int y, int w, int h, unsigned char *src, int srcwidth,
               int rop, unsigned int planemask, int trans, int bpp, int depth)
{
   int flags, dx, dy;
   int Bpp = (bpp+7) >> 3;
   unsigned long offset;
   GeodePtr pGeode = GEODEPTR(pScrni);

   DBLOG(2,"LXWritePixmap() %d,%d %dx%d, s%#x sp%d %#x %#x %#x %d %d\n",
           x,y, w,h, src, srcwidth, rop, planemask, trans,bpp,depth);

   rop &= 0x0F;
   gp_set_source_format(lx_src_fmt[Bpp-1]);
   /* must assign before lx_flags */
   ROP = planemask == ~0U ? SDfn[rop] : SDfn_PM[rop];

   if( src >= pGeode->FBBase && src < pGeode->FBBase+pGeode->FBSize ) {
      offset = src-pGeode->FBBase;
      dx = (offset & ((1<<gu3_yshift)-1)) >> Bpp;
      dy = offset >> gu3_yshift;
      flags = lx_flags3(x,y,dx,dy,w,h);
   }
   else
      flags = ENABLE_PREFETCH;

   gp_declare_blt(flags);
   gp_set_raster_operation(ROP);
   if( planemask != ~0U )
      gp_set_solid_pattern(planemask);
   gp_set_strides(pGeode->AccelPitch,pGeode->AccelPitch);
   if( trans != -1 ) {
      gp_set_source_transparency(trans,~0);
   }

   gp_color_bitmap_to_screen_blt(CALC_FBOFFSET(x,y), 0, w,h, src, srcwidth);
   SET_SYNC_FLAG(pGeode->AccelInfoRec);
}
#endif

/*----------------------------------------------------------------------------
 * LXAccelInit.
 *
 * Description  :Create and initialize XAAInfoRec structure.
 *               The XAAInfoRec structure contains many fields, most of
 *               which are primitive function pointers and flags.  Each
 *               primitive will have two or more functions and a set of
 *               associated associated flags.  These functions can be
 *               classified into two principle classes, the "SetupFor"
 *               and "Subsequent" functions.  The "SetupFor" function tells
 *               the driver that the hardware should be initialized for
 *               a particular type of graphics operation.  After the
 *               "SetupFor" function, one or more calls to the "Subsequent"
 *               function will be made to indicate that an instance of the
 *               particular primitive should be rendered by the hardware.
 *
 *    Arg        Type     Comment
 *  pScrn      ScreenPtr  pointer to active Screen data
 *
 * Returns              :TRUE on success and FALSE on Failure
 *
 * Comments             :This function is called in LXScreenInit in
 *                       amd_lx_driver.c to initialize acceleration.
 *---------------------------------------------------------------------------*/
Bool
LXAccelInit(ScreenPtr pScrn)
{
   GeodePtr pGeode;
   ScrnInfoPtr pScrni;
#if DEBUGLVL>0
   if( zdfp == NULL ) { zdfp = fopen("/tmp/xwin.log","w"); setbuf(zdfp,NULL); }
#endif
   DBLOG(2,"LXAccelInit()\n");

   pScrni = xf86Screens[pScrn->myNum];
   pGeode = GEODEPTR(pScrni);

   switch (pScrni->bitsPerPixel) {
   case 8:
      gu3_img_fmt = CIMGP_SOURCE_FMT_3_3_2;
      break;
   case 16:
      gu3_img_fmt = CIMGP_SOURCE_FMT_0_5_6_5;
      break;
   case 32:
      gu3_img_fmt = CIMGP_SOURCE_FMT_8_8_8_8;
      break;
   }

   gu3_xshift = pScrni->bitsPerPixel >> 4;

   switch (pGeode->AccelPitch) {
   case 1024:
      gu3_yshift = 10;
      break;
   case 2048:
      gu3_yshift = 11;
      break;
   case 4096:
      gu3_yshift = 12;
      break;
   case 8192:
      gu3_yshift = 13;
      break;
   }

   /* Getting the pointer for acceleration Inforecord */
   pGeode->AccelInfoRec = localRecPtr = XAACreateInfoRec();

   /* SET ACCELERATION FLAGS */
   localRecPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER;

   /* HOOK SYNCRONIZARION ROUTINE */
   localRecPtr->Sync = LXAccelSync;

#if LX_FILL_RECT_SUPPORT
   /* HOOK FILLED RECTANGLES */
   HOOK(SetupForSolidFill);
   HOOK(SubsequentSolidFillRect);
   localRecPtr->SolidFillFlags = 0;
#endif

#if LX_MONO_8X8_PAT_SUPPORT
   /* HOOK 8x8 Mono EXPAND PATTERNS */
   HOOK(SetupForMono8x8PatternFill);
   HOOK(SubsequentMono8x8PatternFillRect);
   localRecPtr->Mono8x8PatternFillFlags = 
         BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD |
         HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_PROGRAMMED_ORIGIN;
#endif

#if LX_CLREXP_8X8_PAT_SUPPORT
   /* Color expansion */
   HOOK(SetupForColor8x8PatternFill);
   HOOK(SubsequentColor8x8PatternFillRect);
   localRecPtr->Color8x8PatternFillFlags =
         BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD | NO_TRANSPARENCY |
         HARDWARE_PATTERN_PROGRAMMED_ORIGIN;
#endif

#if LX_SCR2SCRCPY_SUPPORT
   /* HOOK SCREEN TO SCREEN COPIES
    * Set flag to only allow copy if transparency is enabled.
    */
   HOOK(SetupForScreenToScreenCopy);
   HOOK(SubsequentScreenToScreenCopy);
   localRecPtr->ScreenToScreenCopyFlags =
         BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
#endif

#if LX_BRES_LINE_SUPPORT
   /* HOOK BRESENHAM SOLID LINES */
   localRecPtr->SolidLineFlags = NO_PLANEMASK;
   HOOK(SetupForSolidLine);
   HOOK(SubsequentSolidBresenhamLine);
   HOOK(SubsequentSolidHorVertLine);
   HOOK(SubsequentSolidTwoPointLine);
   localRecPtr->SolidBresenhamLineErrorTermBits = 15;
#endif

#if LX_DASH_LINE_SUPPORT
   /* HOOK BRESENHAM DASHED LINES */
   localRecPtr->DashedLineFlags = NO_PLANEMASK | TRANSPARENCY_ONLY |
	 LINE_PATTERN_LSBFIRST_LSBJUSTIFIED | SCANLINE_PAD_DWORD;
   HOOK(SetupForDashedLine);
   HOOK(SubsequentDashedBresenhamLine);
   HOOK(SubsequentDashedTwoPointLine);
   localRecPtr->DashedBresenhamLineErrorTermBits = 15;
   localRecPtr->DashPatternMaxLength = 32;
#endif

#if LX_SCR2SCREXP_SUPPORT
   /* Color expansion */
   HOOK(SetupForScreenToScreenColorExpandFill);
   HOOK(SubsequentScreenToScreenColorExpandFill);
   localRecPtr->ScreenToScreenColorExpandFillFlags =
         BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
#endif

   if (pGeode->AccelImageWriteBuffers) {
#if LX_SCANLINE_SUPPORT
      localRecPtr->ScanlineImageWriteBuffers = pGeode->AccelImageWriteBuffers;
      localRecPtr->NumScanlineImageWriteBuffers = pGeode->NoOfImgBuffers;
      HOOK(SetupForScanlineImageWrite);
      HOOK(SubsequentScanlineImageWriteRect);
      HOOK(SubsequentImageWriteScanline);
      localRecPtr->ScanlineImageWriteFlags = 
         BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
#endif
#if !LX_USE_OFFSCRN_MEM
      ImgBufOffset = pGeode->AccelImageWriteBuffers[0] - pGeode->FBBase;
#else
      ImgLnsBuffers = (uchar *)pGeode->AccelImageWriteBuffers[0];
#endif

   } else {
      localRecPtr->PixmapCacheFlags = DO_NOT_BLIT_STIPPLES;
   }

   if (pGeode->AccelColorExpandBuffers) {
#if LX_CPU2SCREXP_SUPPORT
      /* Color expansion */
      localRecPtr->ScanlineColorExpandBuffers = pGeode->AccelColorExpandBuffers;
      localRecPtr->NumScanlineColorExpandBuffers = pGeode->NoOfColorExpandLines;
      HOOK(SetupForScanlineCPUToScreenColorExpandFill);
      HOOK(SubsequentScanlineCPUToScreenColorExpandFill);
      HOOK(SubsequentColorExpandScanline);
      localRecPtr->ScanlineCPUToScreenColorExpandFillFlags = 
            BIT_ORDER_IN_BYTE_MSBFIRST | SCANLINE_PAD_DWORD;
#endif
      ClrLnsBuffers = (uchar *)pGeode->AccelColorExpandBuffers[0];
   }

#if LX_WRITE_PIXMAP_SUPPORT
   HOOK(WritePixmap);
#endif


   return (XAAInit(pScrn, localRecPtr));
}

/* END OF FILE */

