mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
9.5 KiB
306 lines
9.5 KiB
/*
|
|
*
|
|
* Copyright (C) 1993-1995 by
|
|
* DIGITAL EQUIPMENT CORPORATION, Maynard, MA.
|
|
*
|
|
* This software is furnished under a license and may be used and copied
|
|
* only in accordance with the terms of such license and with the inclusion
|
|
* of the above copyright notice. This software or any other copies there-
|
|
* of may not be provided or otherwise made available to any other person.
|
|
* No title to and ownership of the software is hereby transferred.
|
|
*
|
|
* The information in this software is subject to change without notice
|
|
* and should not be construed as a commitment by DIGITAL EQUIPMENT COR-
|
|
* PORATION.
|
|
*
|
|
* DIGITAL assumes no responsibility for the use or reliability of its
|
|
* software on equipment which is not supplied by DIGITAL.
|
|
*
|
|
*******************************************************************************
|
|
*
|
|
* Module: bltss_.c
|
|
*
|
|
* Abstract: Contains the 'code' for the screen->screen blit routine.
|
|
*
|
|
* HISTORY
|
|
*
|
|
* 25-Aug-1994 Bob Seitsinger
|
|
* Original version.
|
|
*
|
|
* 2-Mar-1995 Barry Tannenbaum
|
|
* EV5 changes
|
|
*/
|
|
|
|
{
|
|
|
|
/*
|
|
* Many of these variables come in editions of 2, as we need 1 set for
|
|
* even numbered scanlines, one set for odd.
|
|
*/
|
|
int dstAlign[2]; /* Last few bits of destination ptr */
|
|
int srcAlign[2]; /* last few bits of source ptr */
|
|
int shift[2]; /* Mostly dstAlign-srcAlign */
|
|
int width[2]; /* width to blt */
|
|
register int height; /* height to blt */
|
|
Pixel8 *psrcBase, *pdstBase; /* start of src, dst */
|
|
int widthSrc, widthDst; /* add to get to same position
|
|
in next line */
|
|
int wS, wD; /* for next even/odd line */
|
|
Pixel8 *psrcLine[2]; /* Current source scanline */
|
|
Pixel8 *pdstLine[2]; /* Current dest scanline */
|
|
CommandWord ones = TGACOPYALL1;
|
|
CommandWord mask[2], leftMask[2], rightMask[2];
|
|
int i = 0; /* even/odd scanline index */
|
|
ULONG mode;
|
|
|
|
DISPDBG ((1, "TGA.DLL!%s - Entry\n", ROUTINE_NAME));
|
|
|
|
// Cycle to the next register alias
|
|
|
|
CYCLE_REGS (ppdev);
|
|
|
|
// Force source to be 8-bpp packed
|
|
|
|
mode = TGA_MODE_COPY | ppdev->ulModeTemplate;
|
|
TGAMODE (ppdev, mode);
|
|
|
|
// Get the base addresses for the source and destination.
|
|
//
|
|
// NOTE: These could be different, e.g. when off-screen
|
|
// memory is involved.
|
|
|
|
psrcBase = SURFOBJ_base_address(psoSrc);
|
|
|
|
// Put destination in a different frame buffer alias,
|
|
// because this routine may have been called multiple
|
|
// times due to multiple clip objects.
|
|
//
|
|
// Cycle 'after' we get the base address, in the event
|
|
// we're dealing with an offscreen memory object, which
|
|
// will 'always' be first-alias based.
|
|
|
|
pdstBase = SURFOBJ_base_address(psoTrg);
|
|
pdstBase = cycle_fb_address(ppdev, pdstBase);
|
|
|
|
// Get the scan line stride, i.e. bytes to next scan line.
|
|
|
|
widthSrc = SURFOBJ_stride(psoSrc);
|
|
widthDst = SURFOBJ_stride(psoTrg);
|
|
|
|
/* Number of rows to affect */
|
|
height = prclTrg->bottom - prclTrg->top;
|
|
|
|
/* Number of pixels in each row to affect */
|
|
width[0] = width[1] = prclTrg->right - prclTrg->left;
|
|
|
|
/* Decide what direction to do copies in, so as not to lose data if the
|
|
source and destination overlap. */
|
|
|
|
if (CD_RIGHTDOWN == flDir)
|
|
{
|
|
/* multiply scan line stride by 2. we need this in order to
|
|
calculate the next address for an even/odd scan line */
|
|
wS = widthSrc << 1;
|
|
wD = widthDst << 1;
|
|
|
|
psrcLine[0] = psrcBase + (pptlSrc->y * widthSrc);
|
|
pdstLine[0] = pdstBase + (prclTrg->top * widthDst);
|
|
|
|
/*
|
|
* It's possible that the src or dst ending mask address on one line
|
|
* is very close to the src or dst starting mask address on the next
|
|
* line, so put 'odd' scan line in a different alias
|
|
*/
|
|
|
|
psrcBase = cycle_fb_address(ppdev, psrcBase);
|
|
pdstBase = cycle_fb_address(ppdev, pdstBase);
|
|
|
|
psrcLine[1] = (psrcBase + (pptlSrc->y * widthSrc)) + widthSrc;
|
|
pdstLine[1] = (pdstBase + (prclTrg->top * widthDst)) + widthDst;
|
|
|
|
/* first scan line of pair */
|
|
CONJUGATE_FORWARD_ARGUMENTS(psrcLine[0], pdstLine[0],
|
|
srcAlign[0], dstAlign[0], shift[0], width[0],
|
|
leftMask[0], rightMask[0], pptlSrc->x, prclTrg->left,
|
|
TGACOPYALL1_SCRSCR, TGAMASKEDCOPYPIXELSMASK_SCRSCR);
|
|
|
|
/* second scan line of pair */
|
|
CONJUGATE_FORWARD_ARGUMENTS(psrcLine[1], pdstLine[1],
|
|
srcAlign[1], dstAlign[1], shift[1], width[1],
|
|
leftMask[1], rightMask[1], pptlSrc->x, prclTrg->left,
|
|
TGACOPYALL1_SCRSCR, TGAMASKEDCOPYPIXELSMASK_SCRSCR);
|
|
|
|
/* Error if scan line 1 shift value != scan line 2 shift value */
|
|
Assert((shift[0] == shift[1]), "TGAbBitbltScrScr, shift[0] != shift[1]");
|
|
|
|
/* Cycle to the next set of alias'd registers */
|
|
CYCLE_REGS(ppdev);
|
|
|
|
/* Update the shift register */
|
|
TGASHIFT(ppdev, shift[0]);
|
|
|
|
if ((width[0] <= TGACOPYPIXELS_SCRSCR) &&
|
|
(width[1] <= TGACOPYPIXELS_SCRSCR))
|
|
{
|
|
/* Copy fits into a single word; combine masks. */
|
|
mask[0] = leftMask[0] & rightMask[0];
|
|
mask[1] = leftMask[1] & rightMask[1];
|
|
do {
|
|
/* Copy mode needs a strict Src/Dst write ordering */
|
|
TGAWRITE (ppdev, psrcLine[i], rightMask[i]);
|
|
FORCE_ORDER;
|
|
TGAWRITE (ppdev, pdstLine[i], mask[i]);
|
|
FORCE_ORDER;
|
|
psrcLine[i] += wS;
|
|
pdstLine[i] += wD;
|
|
height--;
|
|
i ^= 1;
|
|
} while (height != 0);
|
|
|
|
}
|
|
else
|
|
{
|
|
/* At least even or odd rows require multiple words/row */
|
|
do {
|
|
if (width[i] <= TGACOPYPIXELS_SCRSCR)
|
|
{
|
|
TGAWRITE (ppdev, psrcLine[i], rightMask[i]);
|
|
FORCE_ORDER;
|
|
TGAWRITE (ppdev, pdstLine[i], rightMask[i] & leftMask[i]);
|
|
FORCE_ORDER;
|
|
}
|
|
else
|
|
{
|
|
#if TGAPIXELBITS==8
|
|
vSSCopy8to8 (ppdev, psrcLine[i],
|
|
pdstLine[i], width[i],
|
|
leftMask[i], rightMask[i],
|
|
TGACOPYBYTESDONE_SCRSCR, TGASRCCOPYBYTESDONE_SCRSCR,
|
|
TGACOPYBYTESDONEUNMASKED,
|
|
TGASRCCOPYBYTESDONEUNMASKED);
|
|
#else
|
|
vSSCopy32to32 (ppdev, psrcLine[i],
|
|
pdstLine[i], width[i],
|
|
leftMask[i], rightMask[i],
|
|
TGACOPYBYTESDONE_SCRSCR, TGASRCCOPYBYTESDONE_SCRSCR,
|
|
TGACOPYBYTESDONEUNMASKED,
|
|
TGASRCCOPYBYTESDONEUNMASKED);
|
|
#endif
|
|
}
|
|
/* point to 'next' odd or even scan line */
|
|
psrcLine[i] += wS;
|
|
pdstLine[i] += wD;
|
|
/* flip/flop between 'odd'/'even' scan lines */
|
|
i ^= 1;
|
|
height--;
|
|
} while (height != 0);
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Negate the scan line stride for backward copies, */
|
|
/* so we don't have to change the base algorithm. */
|
|
widthSrc = -widthSrc;
|
|
widthDst = -widthDst;
|
|
|
|
/* multiply scan line stride by 2. we need this in order to
|
|
calculate the next address for an even/odd scan line */
|
|
wS = widthSrc << 1;
|
|
wD = widthDst << 1;
|
|
|
|
/* we negated widthSrc and widthDst earlier */
|
|
psrcLine[0] = psrcBase - ((pptlSrc->y + height - 1) * widthSrc);
|
|
pdstLine[0] = pdstBase - ((prclTrg->bottom - 1) * widthDst);
|
|
|
|
/*
|
|
* It's possible that the src or dst ending mask address on one line
|
|
* is very close to the src or dst starting mask address on the next
|
|
* line, so put 'odd' scan line in a different alias
|
|
*/
|
|
|
|
psrcBase = cycle_fb_address(ppdev, psrcBase);
|
|
pdstBase = cycle_fb_address(ppdev, pdstBase);
|
|
|
|
/* we negated widthSrc and widthDst earlier */
|
|
psrcLine[1] = (psrcBase - ((pptlSrc->y + height - 1) * widthSrc)) + widthSrc;
|
|
pdstLine[1] = (pdstBase - ((prclTrg->bottom - 1) * widthDst)) + widthDst;
|
|
|
|
CONJUGATE_BACKWARD_ARGUMENTS(psrcLine[0], pdstLine[0],
|
|
srcAlign[0], dstAlign[0], shift[0], width[0],
|
|
leftMask[0], rightMask[0], pptlSrc->x, prclTrg->right,
|
|
TGACOPYALL1_SCRSCR, TGAMASKEDCOPYPIXELSMASK_SCRSCR);
|
|
|
|
CONJUGATE_BACKWARD_ARGUMENTS(psrcLine[1], pdstLine[1],
|
|
srcAlign[1], dstAlign[1], shift[1], width[1],
|
|
leftMask[1], rightMask[1], pptlSrc->x, prclTrg->right,
|
|
TGACOPYALL1_SCRSCR, TGAMASKEDCOPYPIXELSMASK_SCRSCR);
|
|
|
|
Assert((shift[0] == shift[1]), "TGAbBitbltScrScr, shift[0] != shift[1]");
|
|
CYCLE_REGS(ppdev);
|
|
TGASHIFT(ppdev, shift[0]);
|
|
|
|
if ((width[0] <= TGACOPYPIXELS_SCRSCR) &&
|
|
(width[1] <= TGACOPYPIXELS_SCRSCR))
|
|
{
|
|
/*
|
|
* Copy fits into a single word; combine masks.
|
|
*/
|
|
mask[0] = leftMask[0] & rightMask[0];
|
|
mask[1] = leftMask[1] & rightMask[1];
|
|
do {
|
|
TGAWRITE (ppdev, psrcLine[i], leftMask[i]);
|
|
FORCE_ORDER;
|
|
TGAWRITE (ppdev, pdstLine[i], mask[i]);
|
|
FORCE_ORDER;
|
|
psrcLine[i] += wS;
|
|
pdstLine[i] += wD;
|
|
height--;
|
|
i ^= 1;
|
|
} while (height != 0);
|
|
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* At least even or odd rows require multiple words/row
|
|
*/
|
|
do {
|
|
if (width[i] <= TGACOPYPIXELS_SCRSCR)
|
|
{
|
|
TGAWRITE (ppdev, psrcLine[i], leftMask[i]);
|
|
FORCE_ORDER;
|
|
TGAWRITE (ppdev, pdstLine[i], rightMask[i] & leftMask[i]);
|
|
FORCE_ORDER;
|
|
}
|
|
else
|
|
{
|
|
#if TGAPIXELBITS==8
|
|
vSSCopy8to8 (ppdev, psrcLine[i],
|
|
pdstLine[i], width[i],
|
|
rightMask[i], leftMask[i],
|
|
-TGACOPYBYTESDONE_SCRSCR,
|
|
-TGASRCCOPYBYTESDONE_SCRSCR,
|
|
-TGACOPYBYTESDONEUNMASKED,
|
|
-TGASRCCOPYBYTESDONEUNMASKED);
|
|
#else
|
|
vSSCopy32to32 (ppdev, psrcLine[i],
|
|
pdstLine[i], width[i],
|
|
rightMask[i], leftMask[i],
|
|
-TGACOPYBYTESDONE_SCRSCR,
|
|
-TGASRCCOPYBYTESDONE_SCRSCR,
|
|
-TGACOPYBYTESDONEUNMASKED,
|
|
-TGASRCCOPYBYTESDONEUNMASKED);
|
|
#endif
|
|
}
|
|
psrcLine[i] += wS;
|
|
pdstLine[i] += wD;
|
|
i ^= 1;
|
|
height--;
|
|
} while (height != 0);
|
|
}
|
|
}
|
|
|
|
}
|