#include "fb.h"
#include "micmap.h"
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "xf86cmap.h"
#include "mipointer.h"
#include "mibstore.h"
#include "miline.h"
#include "tga_regs.h"
#include "BT.h"
#include "tga.h"
#define BLIT_FORWARDS 0
#define BLIT_BACKWARDS 1
#define USE_BLOCK_FILL 2
#define USE_OPAQUE_FILL 3
#define MIX_SRC 0x03
#define CE_BUFSIZE 256
#define FB_OFFSET(x, y) (((long)(y) * pScrn->displayWidth * (pTga->Bpp)) + (long)(x) * pTga->Bpp)
static void TGACopyLineForwards(ScrnInfoPtr pScrn, int x1, int y1, int x2,
int y2, int w);
static void TGACopyLineBackwards(ScrnInfoPtr pScrn, int x1, int y1, int x2,
int y2, int w);
extern void TGASync(ScrnInfoPtr pScrn);
static void TGASetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
unsigned int planemask);
static void TGASubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h);
static void TGASetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
int rop, unsigned int planemask,
int transparency_color);
static void TGASubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
int x2, int y2, int w, int h);
static void TGASetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
int fg, int bg, int rop,
unsigned int planemask);
static void TGASubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx,
int paty, int x, int y, int w,
int h);
static void TGASetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
int fg, int bg,
int rop,
unsigned int planemask);
static void
TGASubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
int x, int y, int w,
int h, int skipleft);
static void
TGASubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
Bool
DEC21030AccelInit(ScreenPtr pScreen)
{
XAAInfoRecPtr TGA_AccelInfoRec;
BoxRec AvailFBArea;
ScrnInfoPtr pScrn;
TGAPtr pTga;
pScrn = xf86Screens[pScreen->myNum];
pTga = TGAPTR(pScrn);
TGA_AccelInfoRec = XAACreateInfoRec();
if(pScrn->depth == 8) {
pTga->depthflag = BPP8PACKED;
pTga->Bpp = 1;
} else {
pTga->depthflag = BPP24;
pTga->Bpp = 4;
}
TGA_AccelInfoRec->Flags = PIXMAP_CACHE | LINEAR_FRAMEBUFFER |
OFFSCREEN_PIXMAPS;
TGA_AccelInfoRec->Sync = TGASync;
TGA_AccelInfoRec->SolidFillFlags = 0;
TGA_AccelInfoRec->SetupForSolidFill = TGASetupForSolidFill;
TGA_AccelInfoRec->SubsequentSolidFillRect = TGASubsequentSolidFillRect;
TGA_AccelInfoRec->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
TGA_AccelInfoRec->SetupForScreenToScreenCopy =
TGASetupForScreenToScreenCopy;
TGA_AccelInfoRec->SubsequentScreenToScreenCopy =
TGASubsequentScreenToScreenCopy;
TGA_AccelInfoRec->Mono8x8PatternFillFlags =
HARDWARE_PATTERN_PROGRAMMED_BITS | BIT_ORDER_IN_BYTE_LSBFIRST;
TGA_AccelInfoRec->SetupForMono8x8PatternFill =
TGASetupForMono8x8PatternFill;
TGA_AccelInfoRec->SubsequentMono8x8PatternFillRect =
TGASubsequentMono8x8PatternFillRect;
TGA_AccelInfoRec->ScanlineCPUToScreenColorExpandFillFlags =
BIT_ORDER_IN_BYTE_LSBFIRST;
TGA_AccelInfoRec->NumScanlineColorExpandBuffers = 1;
pTga->buffers[0] = (CARD32 *)xnfalloc(CE_BUFSIZE);
TGA_AccelInfoRec->ScanlineColorExpandBuffers =
(unsigned char **)pTga->buffers;
TGA_AccelInfoRec->SetupForScanlineCPUToScreenColorExpandFill =
TGASetupForScanlineCPUToScreenColorExpandFill;
TGA_AccelInfoRec->SubsequentScanlineCPUToScreenColorExpandFill =
TGASubsequentScanlineCPUToScreenColorExpandFill;
TGA_AccelInfoRec->SubsequentColorExpandScanline =
TGASubsequentColorExpandScanline;
TGA_AccelInfoRec->PolylinesThinSolid = TGAPolyLines;
if(pTga->NoXaaPolySegment == FALSE)
TGA_AccelInfoRec->PolySegmentThinSolid = TGAPolySegment;
TGA_AccelInfoRec->PolylinesThinSolidFlags = 0x0;
TGA_AccelInfoRec->PolySegmentThinSolidFlags = 0x0;
TGA_AccelInfoRec->PolylinesThinDashed = TGAPolyLinesDashed;
if(pTga->NoXaaPolySegment == FALSE)
TGA_AccelInfoRec->PolySegmentThinDashed = TGAPolySegmentDashed;
TGA_AccelInfoRec->PolylinesThinDashedFlags = 0x0;
TGA_AccelInfoRec->PolySegmentThinDashedFlags = 0x0;
TGA_AccelInfoRec->DashedLineFlags = LINE_PATTERN_LSBFIRST_LSBJUSTIFIED;
TGA_AccelInfoRec->DashPatternMaxLength = 16;
AvailFBArea.x1 = 0;
AvailFBArea.y1 = 0;
AvailFBArea.x2 = pScrn->displayWidth;
AvailFBArea.y2 = (pScrn->videoRam * 1024) / (pScrn->displayWidth *
pTga->Bpp);
xf86InitFBManager(pScreen, &AvailFBArea);
TGA_AccelInfoRec->PixmapCacheFlags = 0;
return(XAAInit(pScreen, TGA_AccelInfoRec));
}
static void
TGASetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
int fg, int bg, int rop,
unsigned int planemask)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga = NULL;
unsigned int fgcolor = 0, bgcolor = 0, pmask = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
if(pTga->depthflag == BPP8PACKED) {
fgcolor = (fg | (fg << 8) | (fg << 16) | (fg << 24));
bgcolor = bg | (bg << 8) | (bg << 16) | (bg << 24);
pmask = planemask | (planemask << 8) | (planemask << 16)
| (planemask << 24);
}
else {
bgcolor = bg;
fgcolor = fg;
pmask = planemask;
}
pTga->current_rop = rop | pTga->depthflag;
if(bg == -1) {
pTga->transparent_pattern_p = 1;
if(rop == MIX_SRC) {
pTga->block_or_opaque_p = USE_BLOCK_FILL;
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR0_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR1_REG);
if(pTga->depthflag == BPP24) {
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR2_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR3_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR4_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR5_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR6_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR7_REG);
}
}
else {
pTga->block_or_opaque_p = USE_OPAQUE_FILL;
TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
}
}
else {
pTga->transparent_pattern_p = 0;
TGA_FAST_WRITE_REG(bgcolor, TGA_BACKGROUND_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
}
TGA_FAST_WRITE_REG(pmask, TGA_PLANEMASK_REG);
TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
TGA_SAVE_OFFSET();
return;
}
static void
TGASubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
int x, int y, int w,
int h, int skipleft)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
pTga->ce_height = h;
pTga->ce_width = w;
pTga->ce_x = x;
pTga->ce_y = y;
pTga->ce_skipleft = skipleft;
if(pTga->transparent_pattern_p) {
if(pTga->block_or_opaque_p == USE_BLOCK_FILL)
TGA_FAST_WRITE_REG(BLOCKSTIPPLE | X11 | pTga->depthflag,
TGA_MODE_REG);
else
TGA_FAST_WRITE_REG(TRANSPARENTSTIPPLE | X11 | pTga->depthflag,
TGA_MODE_REG);
}
else
TGA_FAST_WRITE_REG(OPAQUESTIPPLE | X11 | pTga->depthflag,
TGA_MODE_REG);
TGA_SAVE_OFFSET();
return;
}
static void
TGASubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga;
unsigned char *p = NULL;
int width = 0;
unsigned int addr;
unsigned int pixelmask = 0;
unsigned int stipple;
unsigned int align_mask;
int align = 0;
int skipleft;
CARD32 c = 0, d = 0;
CARD32 *e = NULL;
int i = 0, num_dwords = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
align_mask = (pTga->depthflag == BPP24) ? 0x0f : 0x03;
#if 0
ErrorF("TGASubsequentColorExpandScanline called\n");
if(pTga->transparent_pattern_p)
ErrorF("transparent color expand\n");
#endif
p = (unsigned char *)pTga->buffers[0];
addr = FB_OFFSET(pTga->ce_x, pTga->ce_y);
width = pTga->ce_width;
skipleft = pTga->ce_skipleft;
while(width > 0) {
if(!pTga->transparent_pattern_p)
pixelmask = 0xFFFFFFFF;
align = (addr & align_mask) / pTga->Bpp;
if (align) {
if (!pTga->transparent_pattern_p)
pixelmask <<= align;
addr -= align * pTga->Bpp;
width += align;
e = (CARD32 *)p;
num_dwords = (width / 32) + 1;
if(num_dwords > (CE_BUFSIZE / 4)) {
ErrorF("TGASubsequentColorExpandScanline passed scanline %d bytes long, truncating\n", num_dwords * 4);
num_dwords = CE_BUFSIZE / 4;
}
for(i = 0; i < num_dwords; i++) {
c = e[i];
if(i == 0)
e[i] = c << align;
else
e[i] = (d >> (32 - align)) | (c << align);
d = c;
}
}
if (!pTga->transparent_pattern_p) {
if (skipleft) {
pixelmask <<= skipleft;
skipleft = 0;
}
if (width < 32) {
pixelmask &= (0xFFFFFFFF >> (32 - width));
}
TGA_FAST_WRITE_REG(pixelmask, TGA_PIXELMASK_REG);
}
else {
unsigned int *i = NULL;
if (skipleft) {
i = (unsigned int *)p;
*i &= (0xFFFFFFFF << skipleft);
skipleft = 0;
}
if (width < 32) {
i = (unsigned int *)p;
*i &= (0xFFFFFFFF >> (32 - width));
}
}
stipple = *((unsigned int *)p);
switch (pTga->Chipset) {
case PCI_CHIP_TGA2:
*(unsigned int *)(pTga->FbBase + addr) = stipple; WMB;
break;
case PCI_CHIP_DEC21030:
TGA_FAST_WRITE_REG(addr, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(stipple, TGA_CONTINUE_REG);
}
addr += 32 * pTga->Bpp;
p += 4;
width -= 32;
}
pTga->ce_height--;
if(pTga->ce_height == 0) {
TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag,
TGA_MODE_REG);
TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
}
else
pTga->ce_y += 1;
TGA_SAVE_OFFSET();
return;
}
void
TGASetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
unsigned int planemask)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga;
unsigned int fgcolor = 0, pmask = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
if(pTga->depthflag == BPP8PACKED) {
fgcolor = color | (color << 8) | (color << 16) | (color << 24);
pmask = planemask | (planemask << 8) | (planemask << 16) |
(planemask << 24);
}
else {
fgcolor = color;
pmask = planemask;
}
if(rop == MIX_SRC) {
pTga->block_or_opaque_p = USE_BLOCK_FILL;
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR0_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR1_REG);
if(pTga->depthflag == BPP24) {
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR2_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR3_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR4_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR5_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR6_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR7_REG);
}
}
else {
pTga->block_or_opaque_p = USE_OPAQUE_FILL;
pTga->current_rop = rop | pTga->depthflag;
TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
}
pTga->current_planemask = pmask;
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_DATA_REG);
TGA_SAVE_OFFSET();
return;
}
void
TGASubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
{
unsigned int mode_reg = 0;
int i = 0;
unsigned int pixel_count = 0;
unsigned int write_data = 0;
int a1 = 0;
#ifdef PROFILE
unsigned int stop, start;
#endif
TGAPtr pTga;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
if(pTga->block_or_opaque_p == USE_OPAQUE_FILL) {
mode_reg = OPAQUEFILL | X11 | pTga->depthflag;
TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
}
else
mode_reg = BLOCKFILL | X11 | pTga->depthflag;
TGA_FAST_WRITE_REG(mode_reg, TGA_MODE_REG);
TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
if(w > 2048) {
ErrorF("TGASubsequentSolidFillRect called with w = %d, truncating.\n", w);
w = 2048;
}
pixel_count = w - 1;
for(i = 0; i < h; i++) {
a1 = FB_OFFSET(x, y + i);
if(pTga->block_or_opaque_p == USE_OPAQUE_FILL)
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PIXELMASK_REG);
write_data = pixel_count;
TGA_FAST_WRITE_REG(a1, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(write_data, TGA_CONTINUE_REG);
}
mode_reg = SIMPLE | X11 | pTga->depthflag;
TGA_FAST_WRITE_REG(mode_reg, TGA_MODE_REG);
if(pTga->block_or_opaque_p == USE_OPAQUE_FILL)
TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag,
TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
TGA_SAVE_OFFSET();
return;
}
void
TGASetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
int rop, unsigned int planemask,
int transparency_color)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga;
unsigned int pmask = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
if (pTga->depthflag == BPP8PACKED) {
pmask = planemask | (planemask << 8) | (planemask << 16) |
(planemask << 24);
}
else
pmask = planemask;
pTga->current_planemask = pmask;
TGA_FAST_WRITE_REG(pmask, TGA_PLANEMASK_REG);
pTga->current_rop = rop | pTga->depthflag;
if (ydir == -1) {
pTga->blitdir = BLIT_FORWARDS;
}
else {
pTga->blitdir = BLIT_BACKWARDS;
}
TGA_SAVE_OFFSET();
return;
}
void
TGASubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2,
int y2, int w, int h)
{
int i = 0;
void (*copy_func)(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w);
#ifdef PROFILE
unsigned int stop, start;
#endif
TGAPtr pTga;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
#if 0
ErrorF("TGASubsequentScreenToScreenCopy(,%d,%d,%d,%d,%d,%d):"
" COPY %s BLIT %s\n",
x1, y1, x2, y2, w, h, (x2 > x1 && (x1 + w) > x2)?"BWD":"FWD",
(pTga->blitdir == BLIT_FORWARDS)?"FWD":"BWD");
#endif
TGASync(pScrn);
TGA_FAST_WRITE_REG(COPY | X11 | pTga->depthflag, TGA_MODE_REG);
TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
if(x2 > x1 && (x1 + w) > x2)
copy_func = TGACopyLineBackwards;
else
copy_func = TGACopyLineForwards;
TGA_SAVE_OFFSET();
if(pTga->blitdir == BLIT_FORWARDS) {
for(i = h - 1; i >= 0; i--) {
(*copy_func)(pScrn, x1, y1 + i, x2, y2 + i, w);
}
}
else {
for(i = 0; i < h; i++) {
(*copy_func)(pScrn, x1, y1 + i, x2, y2 + i, w);
}
}
TGASync(pScrn);
TGA_GET_OFFSET();
TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
TGA_SAVE_OFFSET();
return;
}
void
TGACopyLineForwards(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w)
{
int read;
unsigned long source_address, destination_address;
unsigned int mask_source, mask_destination;
int cando;
unsigned int cando_mask;
int source_align, destination_align;
int pixel_shift;
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
cando = 32;
cando_mask = 0xFFFFFFFFU;
if (pTga->Chipset == PCI_CHIP_DEC21030 && pTga->depthflag == BPP24) {
cando = 16;
cando_mask = 0x0000FFFFU;
}
source_address = FB_OFFSET(x1, y1);
destination_address = FB_OFFSET(x2, y2);
#if 0
ErrorF("CPY-FWD(,%d,%d,%d,%d,%d): sadr = 0x%lx, dadr = 0x%lx\n",
x1, y1, x2, y2, w, source_address, destination_address);
#endif
read = 0;
while (read < w) {
mask_source = cando_mask;
if ((w - read) >= cando)
mask_destination = cando_mask;
else
mask_destination = cando_mask >> (cando - (w - read));
source_align = source_address & 0x07;
source_address -= source_align;
mask_source <<= source_align / pTga->Bpp;
destination_align = destination_address & 0x07;
destination_address -= destination_align;
mask_destination <<= destination_align / pTga->Bpp;
if (destination_align >= source_align)
pixel_shift = destination_align - source_align;
else {
pixel_shift = 8 - (source_align - destination_align);
destination_address -= 8;
mask_destination <<= 8 / pTga->Bpp;
mask_destination &= cando_mask;
}
TGA_FAST_WRITE_REG(pixel_shift, TGA_PIXELSHIFT_REG);
switch (pTga->Chipset) {
case PCI_CHIP_TGA2:
*(unsigned int *)(pTga->FbBase + source_address) = mask_source; WMB;
*(unsigned int *)(pTga->FbBase + destination_address) = mask_destination; WMB;
break;
case PCI_CHIP_DEC21030:
TGA_FAST_WRITE_REG(source_address, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(mask_source, TGA_CONTINUE_REG);
TGA_FAST_WRITE_REG(destination_address, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(mask_destination, TGA_CONTINUE_REG);
break;
}
source_address += (cando - (pixel_shift / pTga->Bpp)) * pTga->Bpp;
destination_address += cando * pTga->Bpp;
read += cando;
read -= destination_align / pTga->Bpp;
if (destination_align < source_align) {
read -= 8 / pTga->Bpp;
}
}
TGA_SAVE_OFFSET();
return;
}
void
TGACopyLineBackwards(ScrnInfoPtr pScrn, int x1, int y1, int x2,
int y2, int w)
{
unsigned long a1, a2;
unsigned long source_address, destination_address;
unsigned int mask_source, mask_destination;
int cando;
unsigned int cando_mask;
int source_align, destination_align;
int pixel_shift;
int read;
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
cando = 32;
cando_mask = 0xFFFFFFFFU;
if (pTga->Chipset == PCI_CHIP_DEC21030 && pTga->depthflag == BPP24) {
cando = 16;
cando_mask = 0x0000FFFFU;
}
a1 = FB_OFFSET(x1, y1);
a2 = FB_OFFSET(x2, y2);
source_address = FB_OFFSET((x1 + w) - cando, y1);
destination_address = FB_OFFSET((x2 + w) - cando, y2);
#if 0
ErrorF("CPY-BWD(,%d,%d,%d,%d,%d): sadr = 0x%lx, dadr = 0x%lx"
" a1 0x%lx a2 0x%lx\n",
x1, y1, x2, y2, w, source_address, destination_address, a1, a2);
#endif
read = 0;
while (read < w) {
mask_source = cando_mask;
if ((w - read) >= cando)
mask_destination = cando_mask;
else {
mask_destination = ((unsigned int)cando_mask) << (cando - (w - read));
mask_destination &= cando_mask;
}
source_align = source_address & 0x07;
destination_align = destination_address & 0x07;
if (read == 0 && destination_align &&
(source_align > destination_align)) {
unsigned long tmp_src, tmp_dest;
unsigned int tmp_src_mask, tmp_dest_mask;
tmp_src = a1 + (w - (source_align / pTga->Bpp)) * pTga->Bpp;
tmp_dest = a2 + (w - (destination_align / pTga->Bpp) - (8 / pTga->Bpp)) * pTga->Bpp;
tmp_src_mask = cando_mask;
tmp_dest_mask = ((unsigned int)0x000000FF) >> (8 - destination_align) / pTga->Bpp;
tmp_dest_mask <<= 8 / pTga->Bpp;
pixel_shift = (8 - source_align) + destination_align;
#if 0
ErrorF("CPY-BWD - preliminary copy: sa = %d, da = %d, ps =%d\n",
source_align, destination_align, pixel_shift);
#endif
TGA_FAST_WRITE_REG(pixel_shift, TGA_PIXELSHIFT_REG);
switch (pTga->Chipset)
{
case PCI_CHIP_TGA2:
*(unsigned int *)(pTga->FbBase + tmp_src) = tmp_src_mask; WMB;
*(unsigned int *)(pTga->FbBase + tmp_dest) = tmp_dest_mask; WMB;
break;
case PCI_CHIP_DEC21030:
TGA_FAST_WRITE_REG(tmp_src, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(tmp_src_mask, TGA_CONTINUE_REG);
TGA_FAST_WRITE_REG(tmp_dest, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(tmp_dest_mask, TGA_CONTINUE_REG);
break;
}
source_address += (8 - source_align);
mask_source >>= (8 - source_align) / pTga->Bpp;
mask_source >>= destination_align / pTga->Bpp;
mask_destination >>= destination_align / pTga->Bpp;
}
else if (read == 0 && (source_align != destination_align)) {
source_address += (8 - source_align);
}
else if (source_align) {
source_address += (8 - source_align);
mask_source >>= (8 - source_align) / pTga->Bpp;
}
if (destination_align) {
destination_address += (8 - destination_align);
mask_destination >>= (8 - destination_align) / pTga->Bpp;
}
if (destination_align >= source_align)
pixel_shift = destination_align - source_align;
else {
pixel_shift = (8 - source_align) + destination_align;
if (destination_align) {
source_address += 8;
mask_source >>= 8 / pTga->Bpp;
}
}
#if 0
ErrorF("CPY-BWD - normal: sadr 0x%lx sm 0x%x dadr 0x%lx dm 0x%x"
" sa %d da %d ps %d read %d\n",
source_address, mask_source,
destination_address, mask_destination,
source_align, destination_align, pixel_shift, read);
#endif
TGA_FAST_WRITE_REG(pixel_shift, TGA_PIXELSHIFT_REG);
switch (pTga->Chipset) {
case PCI_CHIP_TGA2:
*(unsigned int *)(pTga->FbBase + source_address) = mask_source; WMB;
*(unsigned int *)(pTga->FbBase + destination_address) = mask_destination; WMB;
break;
case PCI_CHIP_DEC21030:
TGA_FAST_WRITE_REG(source_address, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(mask_source, TGA_CONTINUE_REG);
TGA_FAST_WRITE_REG(destination_address, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(mask_destination, TGA_CONTINUE_REG);
break;
}
if (destination_align > source_align) {
source_address -= cando * pTga->Bpp - 8;
destination_address -= (cando - (pixel_shift / pTga->Bpp)) * pTga->Bpp;
if (read == 0)
read += (cando - 8 / pTga->Bpp) + source_align / pTga->Bpp;
else
read += cando - 8 / pTga->Bpp;
}
else if (destination_align == source_align) {
source_address -= cando * pTga->Bpp;
destination_address -= cando * pTga->Bpp;
if (read == 0 && destination_align)
read += (cando - (8 - destination_align) / pTga->Bpp);
else
read += cando;
}
else if (source_align > destination_align) {
source_address -= cando * pTga->Bpp - 8;
destination_address -= (cando - (pixel_shift / pTga->Bpp)) * pTga->Bpp;
if (destination_align)
read += (cando - 16 / pTga->Bpp) + source_align / pTga->Bpp;
else
read += cando - pixel_shift / pTga->Bpp;
}
}
TGA_SAVE_OFFSET();
return;
}
void
TGASetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
int fg, int bg, int rop, unsigned int planemask)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga;
unsigned int fgcolor = 0, bgcolor = 0, pmask = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
if(bg == -1)
pTga->transparent_pattern_p = 1;
else
pTga->transparent_pattern_p = 0;
if(rop == MIX_SRC)
pTga->block_or_opaque_p = USE_BLOCK_FILL;
else
pTga->block_or_opaque_p = USE_OPAQUE_FILL;
if(pTga->depthflag == BPP8PACKED) {
fgcolor = fg | (fg << 8) | (fg << 16) | (fg << 24);
bgcolor = bg | (bg << 8) | (bg << 16) | (bg << 24);
pmask = planemask | (planemask << 8) | (planemask << 16) |
(planemask << 24);
}
else {
fgcolor = fg;
bgcolor = bg;
pmask = planemask;
}
if(pTga->transparent_pattern_p &&
pTga->block_or_opaque_p == USE_BLOCK_FILL) {
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR0_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR1_REG);
if(pTga->depthflag == BPP24) {
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR2_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR3_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR4_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR5_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR6_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR7_REG);
}
}
else if(pTga->transparent_pattern_p) {
TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
}
else {
TGA_FAST_WRITE_REG(bgcolor, TGA_BACKGROUND_REG);
TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PIXELMASK_REG);
}
pTga->current_rop = rop;
pTga->current_planemask = pmask;
TGA_SAVE_OFFSET();
return;
}
void
TGASubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
int x, int y, int w, int h)
{
TGAPtr pTga;
int i, j;
unsigned int stipple_mask[8], align, tmp;
#ifdef PROFILE
register unsigned int stop, start;
#endif
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
if(w > 2048)
ErrorF("TGASubsequentMono8x8PatternFillRect called with w > 2048, truncating\n");
if(pTga->block_or_opaque_p == USE_OPAQUE_FILL)
TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
if(pTga->depthflag == BPP8PACKED)
align = FB_OFFSET(x, y) % 4;
else
align = x % 4;
for(i = 0; i < 4; i++) {
tmp = (patx >> (i * 8)) & 0xFF;
stipple_mask[i] = (tmp | (tmp << 8) | (tmp << 16) | (tmp << 24));
}
for(i = 4; i < 8; i++) {
tmp = (paty >> ((i - 4) * 8)) & 0xFF;
stipple_mask[i] = (tmp | (tmp << 8) | (tmp << 16) | (tmp << 24));
}
if(align) {
for(i = 0; i < 8; i++) {
stipple_mask[i] = (stipple_mask[i] << align) |
((stipple_mask[i] & 0xFF000000) >> (32 - align));
}
}
if((pTga->block_or_opaque_p == USE_BLOCK_FILL) && pTga->transparent_pattern_p) {
TGA_FAST_WRITE_REG(BLOCKFILL | X11 | pTga->depthflag, TGA_MODE_REG);
for(i = 0, j = 0; i < h; i++, (j == 7) ? (j = 0) : (j++)) {
TGA_FAST_WRITE_REG(stipple_mask[j], TGA_DATA_REG);
TGA_FAST_WRITE_REG(FB_OFFSET(x, y + i), TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(w - 1, TGA_CONTINUE_REG);
}
}
else if(pTga->transparent_pattern_p) {
TGA_FAST_WRITE_REG(TRANSPARENTFILL | X11 | pTga->depthflag, TGA_MODE_REG);
for(i = 0, j = 0; i < h; i++, (j == 7) ? (j = 0) : (j++)) {
TGA_FAST_WRITE_REG(stipple_mask[j], TGA_DATA_REG);
TGA_FAST_WRITE_REG(FB_OFFSET(x, y + i), TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(w - 1, TGA_CONTINUE_REG);
}
}
else {
TGA_FAST_WRITE_REG(OPAQUEFILL | X11 | pTga->depthflag, TGA_MODE_REG);
for(i = 0, j = 0; i < h; i++, (j == 7) ? (j = 0) : (j++)) {
TGA_FAST_WRITE_REG(stipple_mask[j], TGA_DATA_REG);
TGA_FAST_WRITE_REG(FB_OFFSET(x, y + i), TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(w - 1, TGA_CONTINUE_REG);
}
}
TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
TGA_SAVE_OFFSET();
return;
}
void
TGASetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
unsigned int planemask)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga = NULL;
unsigned int fgcolor = 0, pmask = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
if(pTga->depthflag == BPP8PACKED) {
fgcolor = color | (color << 8) | (color << 16) | (color << 24);
pmask = planemask | (planemask << 8) | (planemask << 16) |
(planemask << 24);
}
else {
fgcolor = color;
pmask = planemask;
}
pTga->current_rop = rop | pTga->depthflag;
TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
pTga->current_planemask = pmask;
TGA_FAST_WRITE_REG(0xFFFF, TGA_DATA_REG);
TGA_FAST_WRITE_REG(pScrn->displayWidth, TGA_WIDTH_REG);
TGA_SAVE_OFFSET();
return;
}
void
TGASubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len,
int dir)
{
if(dir == DEGREES_0)
TGASubsequentSolidLine(pScrn, x, y, x + len, y, 0x0, OMIT_LAST);
else if(dir == DEGREES_270)
TGASubsequentSolidLine(pScrn, x, y, x, y + len, YMAJOR, OMIT_LAST);
else
ErrorF("TGASubsequentSolidHorVertLine passed dir %d!\n", dir);
return;
}
void
TGASubsequentSolidLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
int octant, int flags)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga = NULL;
CARD32 abs_dx = 0, abs_dy = 0, address = 0, octant_reg = 0;
int length = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag |
((flags & OMIT_LAST) ? 0x0 : CAP_ENDS), TGA_MODE_REG);
TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
address = FB_OFFSET(x1, y1);
TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
abs_dx = abs(x2 - x1);
abs_dy = abs(y2 - y1);
if(octant & YMAJOR)
length = abs_dy;
else
length = abs_dx;
if(octant & YMAJOR) {
if(octant & YDECREASING) {
if(octant & XDECREASING)
octant_reg = TGA_SLOPE0_REG;
else
octant_reg = TGA_SLOPE2_REG;
}
else {
if(octant & XDECREASING)
octant_reg = TGA_SLOPE1_REG;
else
octant_reg = TGA_SLOPE3_REG;
}
}
else {
if(octant & YDECREASING) {
if(octant & XDECREASING)
octant_reg = TGA_SLOPE4_REG;
else
octant_reg = TGA_SLOPE6_REG;
}
else {
if(octant & XDECREASING)
octant_reg = TGA_SLOPE5_REG;
else
octant_reg = TGA_SLOPE7_REG;
}
}
TGA_FAST_WRITE_REG(abs_dx | (abs_dy << 16), octant_reg);
if(length > 16 && length % 16)
length -= length % 16;
else
length -= 16;
while(length > 0) {
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_CONTINUE_REG);
length -= 16;
}
TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
TGA_SAVE_OFFSET();
return;
}
void
TGASetupForClippedLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
int octant)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga = NULL;
CARD32 abs_dx = 0, abs_dy = 0, octant_reg = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
abs_dx = abs(x2 - x1);
abs_dy = abs(y2 - y1);
if(octant & YMAJOR) {
if(octant & YDECREASING) {
if(octant & XDECREASING)
octant_reg = TGA_NOSLOPE0_REG;
else
octant_reg = TGA_NOSLOPE2_REG;
}
else {
if(octant & XDECREASING)
octant_reg = TGA_NOSLOPE1_REG;
else
octant_reg = TGA_NOSLOPE3_REG;
}
}
else {
if(octant & YDECREASING) {
if(octant & XDECREASING)
octant_reg = TGA_NOSLOPE4_REG;
else
octant_reg = TGA_NOSLOPE6_REG;
}
else {
if(octant & XDECREASING)
octant_reg = TGA_NOSLOPE5_REG;
else
octant_reg = TGA_NOSLOPE7_REG;
}
}
TGA_FAST_WRITE_REG(abs_dx | (abs_dy << 16), octant_reg);
TGA_SAVE_OFFSET();
return;
}
void
TGASubsequentClippedSolidLine(ScrnInfoPtr pScrn, int x1, int y1, int len,
int err)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga = NULL;
CARD32 address = 0;
int length = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
address = FB_OFFSET(x1, y1);
TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(pTga->current_rop | pTga->depthflag, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag, TGA_MODE_REG);
TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
length = len;
TGA_FAST_WRITE_REG((err << 15) | (length & 0xF), TGA_BRES3_REG);
while(length > 0) {
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_CONTINUE_REG);
if(length > 16 && length % 16)
length -= length % 16;
else
length -= 16;
}
TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
TGA_SAVE_OFFSET();
return;
}
void
TGASetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
unsigned int planemask, int length,
unsigned char *pattern)
{
#ifdef PROFILE
unsigned int start = 0, stop = 0;
#endif
TGAPtr pTga = NULL;
unsigned int color1 = 0, color2 = 0, pmask = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
if(pTga->depthflag == BPP8PACKED) {
color1 = fg | (fg << 8) | (fg << 16) | (fg << 24);
color2 = bg | (bg << 8) | (bg << 16) | (bg << 24);
pmask = planemask | (planemask << 8) | (planemask << 16)
| (planemask << 24);
}
else {
color1 = fg;
color2 = fg;
pmask = planemask;
}
pTga->current_rop = rop | pTga->depthflag;
TGA_FAST_WRITE_REG(color1, TGA_FOREGROUND_REG);
pTga->current_planemask = pmask;
if(bg == -1)
pTga->transparent_pattern_p = 1;
else {
pTga->transparent_pattern_p = 0;
TGA_FAST_WRITE_REG(color2, TGA_BACKGROUND_REG);
}
pTga->line_pattern = pattern[0] | (pattern[1] << 8);
pTga->line_pattern_length = length;
TGA_FAST_WRITE_REG(pScrn->displayWidth, TGA_WIDTH_REG);
TGA_SAVE_OFFSET();
return;
}
void
TGASubsequentDashedLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
int y2, int octant, int flags, int phase)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga = NULL;
CARD32 abs_dx = 0, abs_dy = 0, address = 0, octant_reg = 0;
int length = 0;
CARD16 line_mask = 0;
int pattern_overflow = 0;
int l = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
if(pTga->transparent_pattern_p)
TGA_FAST_WRITE_REG(TRANSPARENTLINE | X11 | pTga->depthflag |
((flags & OMIT_LAST) ? 0x0 : CAP_ENDS),
TGA_MODE_REG);
else
TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag |
((flags & OMIT_LAST) ? 0x0 : CAP_ENDS),
TGA_MODE_REG);
address = FB_OFFSET(x1, y1);
TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
abs_dx = abs(x2 - x1);
abs_dy = abs(y2 - y1);
if(abs_dx > abs_dy)
length = abs_dx;
else
length = abs_dy;
if(octant & YMAJOR) {
if(octant & YDECREASING) {
if(octant & XDECREASING)
octant_reg = TGA_SLOPE0_REG;
else
octant_reg = TGA_SLOPE2_REG;
}
else {
if(octant & XDECREASING)
octant_reg = TGA_SLOPE1_REG;
else
octant_reg = TGA_SLOPE3_REG;
}
}
else {
if(octant & YDECREASING) {
if(octant & XDECREASING)
octant_reg = TGA_SLOPE4_REG;
else
octant_reg = TGA_SLOPE6_REG;
}
else {
if(octant & XDECREASING)
octant_reg = TGA_SLOPE5_REG;
else
octant_reg = TGA_SLOPE7_REG;
}
}
if(phase) {
line_mask = pTga->line_pattern >> phase;
l = (pTga->line_pattern_length - phase);
}
else {
line_mask = pTga->line_pattern;
l = pTga->line_pattern_length;
}
while(l < 16) {
line_mask |= pTga->line_pattern << l;
l += pTga->line_pattern_length;
}
pattern_overflow = l - 16;
TGA_FAST_WRITE_REG(line_mask, TGA_DATA_REG);
TGA_FAST_WRITE_REG(abs_dx | (abs_dy << 16), octant_reg);
if(length > 16 && length % 16)
length -= length % 16;
else
length -= 16;
while(length > 0) {
if(pattern_overflow) {
line_mask = pTga->line_pattern >> (pTga->line_pattern_length -
pattern_overflow);
l = pattern_overflow;
}
else {
line_mask = pTga->line_pattern;
l = pTga->line_pattern_length;
}
while(l < 16) {
line_mask |= (pTga->line_pattern << l);
l += pTga->line_pattern_length;
}
pattern_overflow = l - 16;
TGA_FAST_WRITE_REG(line_mask, TGA_CONTINUE_REG);
length -= 16;
}
TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
TGA_SAVE_OFFSET();
return;
}
void
TGASubsequentClippedDashedLine(ScrnInfoPtr pScrn, int x1, int y1, int len,
int err, int phase)
{
#ifdef PROFILE
unsigned int start, stop;
#endif
TGAPtr pTga = NULL;
CARD32 address = 0;
int length = 0;
CARD16 line_mask = 0;
int pattern_overflow = 0;
int l = 0;
TGA_DECL();
pTga = TGAPTR(pScrn);
TGA_GET_IOBASE();
TGA_GET_OFFSET();
address = FB_OFFSET(x1, y1);
TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
if(pTga->transparent_pattern_p)
TGA_FAST_WRITE_REG(TRANSPARENTLINE | X11 | pTga->depthflag, TGA_MODE_REG);
else
TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag, TGA_MODE_REG);
length = len;
TGA_FAST_WRITE_REG((err << 15) | (length & 0xF), TGA_BRES3_REG);
if(phase) {
line_mask = pTga->line_pattern >> phase;
l = (pTga->line_pattern_length - phase);
}
else {
line_mask = pTga->line_pattern;
l = pTga->line_pattern_length;
}
while(l < 16) {
line_mask |= pTga->line_pattern << l;
l += pTga->line_pattern_length;
}
pattern_overflow = l - 16;
while(length > 0) {
TGA_FAST_WRITE_REG(line_mask, TGA_CONTINUE_REG);
if(pattern_overflow) {
line_mask = pTga->line_pattern >> (pTga->line_pattern_length -
pattern_overflow);
l = pattern_overflow;
}
else {
line_mask = pTga->line_pattern;
l = pTga->line_pattern_length;
}
while(l < 16) {
line_mask |= (pTga->line_pattern << l);
l += pTga->line_pattern_length;
}
pattern_overflow = l - 16;
if(length > 16 && length % 16)
length -= length % 16;
else
length -= 16;
}
TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
TGA_SAVE_OFFSET();
return;
}