|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T b
Length: 63414 (0xf7b6)
Types: TextFile
Names: »bitblt_subr.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z«
└─⟦2109abc41⟧
└─⟦this⟧ »./X.V10R4/libibm/bitblt/bitblt_subr.c«
#ifndef lint
static char *rcsid_bitblt_subr_c = "$Header: bitblt_subr.c,v 10.1 86/11/19 10:51:21 jg Exp $";
#endif lint
/*
* Copyright (c) 1986 Brown University
*
* Permission to use, copy, modify and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies, and that both
* that copyright notice and this permission notice appear in supporting
* documentation, and that the name of Brown University not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Brown University makes no
* representations about the suitability of this software for any purpose.
* It is provided "as-is" without express or implied warranty.
*
* Written by Daniel Stone, Brown University/IRIS (des@iris)
*/
/*
* CURRENT HISTORY:
*
* $Log: bitblt_subr.c,v $
* Revision 10.1 86/11/19 10:51:21 jg
* Device dependent code for IBM displays. General blitter...
*
* Revision 4.0 86/09/25 10:03:10 des
* Version 4.0. Works with all IBM screens.
*
* Revision 3.6 86/09/22 16:47:44 des
* Added a third argument to blt_init.
*
* Revision 3.5 86/09/22 13:37:29 des
* Version 3.5. Removed all ifdef's that did not pertain to X.
*
* Revision 3.0 86/09/17 10:29:59 des
* Version 3.0. Works but has ifdef's for all systems.
*
* Revision 7.0 86/07/03 10:40:03 des
* Release 7.0.
*
* Revision 6.1 86/07/03 10:29:10 des
* Replaced certain mask rules.
*
* Revision 6.0 86/06/18 11:19:59 des
* Changed unsigned short pointers to unsigned char pointers for efficiency
* reasons. This change ment multiplying by 2 every variable added to
* these pointers.
*
* Revision 5.0 86/05/21 14:26:02 des
* Revision 5.0. No longer uses unsigned short pointers.
*
* Revision 4.7 86/05/15 16:03:45 des
* Latest and faster version of the new copyBitPos loop. Runs 5% to 7% faster
* than the old loop.
*
* Revision 4.6 86/05/14 10:54:46 des
* Changed smallcopyBitPos_LOOP so that it checks for 1 or 2 words changed
* and branches to that loop.
*
* Revision 4.5 86/05/14 10:31:57 des
* bitblt with NEW_LOOP (needs work.)
*
* Revision 4.0 86/05/09 13:52:25 des
* Revision 4.0. Apa-16 hardware enhancements Version 0.6.
*
* Revision 3.2 86/04/30 15:34:16 des
* This version has smallcopyBitPos and the old copyBitPos. The new copyBitPos
* took off .1 second on a 111 second blt. (new: 111.1 old:111.2) so what right?
* The old copyBitPos did not need smallcopyBitPos around so I figured it was
* better.
*
* Revision 2.2 86/04/29 16:31:53 des
* Added the smallcopyBitPos routine for speeding up small blts.
*
* Revision 3.0 86/04/28 16:59:20 des
* Runs with X. Version 0.5.
*
* Revision 2.2 86/04/09 09:36:41 des
* Fixed APA-8 and APA-8C software locator problem.
*
* Revision 2.1 86/04/04 12:19:38 des
* Moved copyBitNeg,copyBitPos,copyTile,maskBitNeg,maskBitPos,maskTile,
* clip_and_maskBitNeg,clip_and_maskBitPos and clip_and_maskTile to
* bitblt_subr.c.
*/
#ifndef lint
static char rcsid[] =
"$Header: bitblt_subr.c,v 10.1 86/11/19 10:51:21 jg Exp $ (Brown/IRIS)";
#endif
#include "bitblt_int.h"
/*
* Keep track of the first and one beyond the last address of the screen,
* so that current_screen.firstaddr <= some_base < current_screen.lastaddr
* is true if some_base is a pointer to a section of the screen.
*/
Blt_screen_info blt_cur_screen;
static Blt_Tile blt_black = {
0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff
};
extern Blt_Rectangle changed_rect;/* describes the area changed by the bltter */
/*
* Set 'ans' to the largest value and set 'diff' equal to the difference
* between 'ans' and 'a'.
*/
#define max_a(a,b,c,ans,diff) { \
if (a >= b) { \
if (a >= c) { \
diff = 0; \
ans = a; \
} \
else { \
diff = c - a; \
ans = c; \
} \
} \
else if (b > c) { \
diff = b - a; \
ans = b; \
} \
else { \
diff = c - a; \
ans = c; \
} \
}
/*
* Set 'ans' to the smallest value and set 'diff' equal to the difference
* between 'ans' and 'a'.
*/
#define min_a(a,b,c,ans,diff) { \
if (a <= b) { \
if (a <= c) { \
diff = 0; \
ans = a; \
} \
else { \
diff = a - c; \
ans = c; \
} \
} \
else if (b < c) { \
diff = a - b; \
ans = b; \
} \
else { \
diff = a - c; \
ans = c; \
} \
}
/*
* Initialize the bitblt so that it knows where in the address space the
* screen is and whether or not it uses a hardware or software cursor.
*/
bitblt_init(screen_base,screen_wd,screen_ht,flags)
unsigned short *screen_base; /* The first address of the bitmap */
long screen_wd; /* Screen width in BITS (will round up) */
long screen_ht; /* Screen height in scan lines */
unsigned long flags; /* Indicates the type of cursor on the screen.*/
{
blt_cur_screen.firstaddr = screen_base;
blt_cur_screen.lastaddr = (unsigned short *)((long)screen_base +
(((screen_wd+7)/8) * screen_ht));
blt_cur_screen.cursortype = flags;
}
/*
* Blt_setup takes information from the user data and creates data
* to be used internally. Specificly it creates clipped source rectangle
* if a source combination rule is given, a clipped destination rectangle
* the number of destination words to be changed across a scanline
* (nshorts) and masking bitmap rectangle masking is to be done.
* Finally the width and height and rule are filled in as width,
* height and rule.
*
* If a bad pointer was encountered (or something else is wrong) then
* blt_setup returns -1. Returns 0 if combination rule was a no-op and
* 1 if blt_setup finished ok.
*/
blt_setup(u_info,s_info)
register Blt_userdata *u_info; /* User bitblt data */
register Blt_sysdata *s_info; /* bitblt internal data (This is modified
bitblt user data depending on the clipping
to be done. */
{
register int x_orig,y_orig;/* because the destination x,y origin
is used so much, it will be put in
registers. */
register int Oxdiff,Cxdiff;/* If the destination rectangle is clipped
then these variables contain the
difference between the destination
rectangle and the rectangle used
to clip. */
register int Oydiff,Cydiff;/* If the destination rectangle is clipped
then these variables contain the
difference between the destination
rectangle and the rectangle used
to clip. */
DEBUGF((blt_debug > 1),
printf("Enter blt_setup.0x%x\r\n",u_info->blt_flags));
/*
* Set up the internal bltters combination rule.
*/
s_info->rule = u_info->comb_rule;
/*
* Set a flag indicating that the rule uses the source.
*/
s_info->is_src = IS_SRC(s_info->rule);
/*
* Make sure s_info->tile_ptr = 0.
*/
s_info->tile_ptr = (unsigned short *)0;
/*
* Check the bltstruct to make sure every pointer is valid.
*/
if (u_info == (Blt_userdata *)0) {
printf("Error: NULL bltstruct given!\n");
return(-1);
}
if (u_info->dst_bitmap.base == (unsigned short *)0) {
printf("Error: NULL destination bitmap!\n");
return(-1);
}
/*
* If a source combination rule was given and no bitmap was given then
* we assume the user wants US to assume that the source is infinitely
* large and is set to all one's. This is the same thing as using
* the coorisponding tile rule and an all black tile.
*/
if (s_info->is_src && u_info->src_bitmap.base == (unsigned short *)0) {
s_info->is_src = 0;
s_info->rule += SRC_TO_TILE;
s_info->tile_ptr = &blt_black.tile[0];
}
/*
* Check the rule and if its a no-op then return immediately.
*/
if (s_info->rule == DstCopy || s_info->rule == TileDstCopy) {
return(0);
}
if (u_info->blt_flags & BLT_CLIPON) {
/* DEBUGF(blt_debug,printf("Clip.\r\n")); */
/*
* Do some clipping. We clip to the clipping rectangle,
* the destination bitmap's rect and the destination
* rectangle. NOTE that if the destination rectangle
* is clipped in any way then the source rectangle must
* also be changed, thats why we keep track of the difference
* in Oxdiff.
*
* Set the origin to be a zero based coorinate system.
*/
max_a(u_info->dst_rect.origin_x,
u_info->clp_rect.origin_x,
u_info->dst_bitmap.rect.origin_x,
x_orig,Oxdiff);
x_orig -= u_info->dst_bitmap.rect.origin_x;
/*
* Take the min value of the clipping rectangle X corner
* coord, bitmap rectangle X corner coord. and the
* destination rectangle X corner coord.. Cxdiff
* contains the difference between dst_rect.corner_x and
* the value returned. Then convert to a zero based
* coordinate system.
*/
min_a(u_info->dst_rect.corner_x,
u_info->clp_rect.corner_x,
u_info->dst_bitmap.rect.corner_x,
s_info->dst.rect.corner_x,Cxdiff);
s_info->dst.rect.corner_x -= u_info->dst_bitmap.rect.origin_x;
/*
* Take the max value of the clipping rectangle Y origin
* coord, bitmap rectangle Y origin coord. and the
* destination rectangle Y origin coord.. Oydiff
* contains the difference between dst_rect.origin_y and
* the value returned. Then convert to a zero based
* coordinate system.
*/
max_a(u_info->dst_rect.origin_y,
u_info->clp_rect.origin_y,
u_info->dst_bitmap.rect.origin_y,
y_orig,Oydiff);
y_orig -= u_info->dst_bitmap.rect.origin_y;
/*
* Take the min value of the clipping rectangle Y corner
* coord, bitmap rectangle Y corner coord. and the
* destination rectangle Y corner coord.. Cydiff
* contains the difference between dst_rect.corner_y and
* the value returned. Then convert to a zero based
* coordinate system.
*/
min_a(u_info->dst_rect.corner_y,
u_info->clp_rect.corner_y,
u_info->dst_bitmap.rect.corner_y,
s_info->dst.rect.corner_y,Cydiff);
s_info->dst.rect.corner_y -= u_info->dst_bitmap.rect.origin_y;
/*
* printf("dst:\t%4d,%4d,%4d,%4d\n",x_orig,
* y_orig,s_info->dst.rect.corner_x,
* s_info->dst.rect.corner_y);
* printf("diffs:\t%4d,%4d,%4d,%4d\n",Oxdiff,Oydiff,Cxdiff,Cydiff);
*/
/*
* Adjust source if necessary. (May only be using a tile.)
*/
if (s_info->is_src) {
/*
* We may have done some clipping. If X was clipped
* then the section of the source that would have
* been mapped to the clipped section of the
* destination must also be clipped.
* In other words if one clips the destination one
* must also clip the source. Anyways 'Oxdiff' is set
* to the difference. Then we subtract the rect
* of the source bitmap so as to get the source into
* the same coordinate system as the destination,
* a zero based system.
*/
s_info->src.rect.origin_x = u_info->src_rect.origin_x +
Oxdiff -
u_info->src_bitmap.rect.origin_x;
/*
* If Y was clipped then the section of source
* that would have mapped to the clipped section
* of the destination must also be clipped.
*/
s_info->src.rect.origin_y = u_info->src_rect.origin_y +
Oydiff -
u_info->src_bitmap.rect.origin_y;
/*
* Now clip to the source bitmap's origin which is
* now 0,0 because we subtracted its origin above.
*/
if (s_info->src.rect.origin_x < 0) {
/*
* The source rectangle has been clipped so
* the destination rectangle must also be
* clipped.
*/
x_orig -= s_info->src.rect.origin_x;
s_info->src.rect.origin_x = 0;
}
if (s_info->src.rect.origin_y < 0) {
/*
* The source rectangle has been clipped so
* the destination rectangle must also be
* clipped.
*/
y_orig -= s_info->src.rect.origin_y;
s_info->src.rect.origin_y = 0;
}
/*
* Calculate the source rectangle's corner rect.
* NOTE: We are not setting these rect to a zero
* based system yet.
*/
s_info->src.rect.corner_x = u_info->src_rect.corner_x -
Cxdiff;
s_info->src.rect.corner_y = u_info->src_rect.corner_y -
Cydiff;
/*
* Clip these rect to the corner of the source
* bitmap corner rect.
*/
if (s_info->src.rect.corner_x >
u_info->src_bitmap.rect.corner_x) {
s_info->src.rect.corner_x =
u_info->src_bitmap.rect.corner_x;
}
if (s_info->src.rect.corner_y >
u_info->src_bitmap.rect.corner_y) {
s_info->src.rect.corner_y =
u_info->src_bitmap.rect.corner_y;
}
/*
* Now set these rect to a zero based coordinate
* system.
*/
s_info->src.rect.corner_x -=
u_info->src_bitmap.rect.origin_x;
s_info->src.rect.corner_y -=
u_info->src_bitmap.rect.origin_y;
/*
* Calculate the width in pixels of the blt area
* using the smaller of the two widths found in
* the source and destination rectangles.
*/
if ((s_info->src.rect.corner_x -
s_info->src.rect.origin_x) >
(s_info->dst.rect.corner_x - x_orig)) {
s_info->width = s_info->dst.rect.corner_x -
x_orig;
}
else {
s_info->width = s_info->src.rect.corner_x -
s_info->src.rect.origin_x;
/*
* Must change the destination corner.
*/
s_info->dst.rect.corner_x = x_orig +
s_info->width;
}
/*
* Calculate the height in scanlines of the blt area
* using the smaller of the two heights found in
* the source and destination rectangles.
*/
if ((s_info->src.rect.corner_y -
s_info->src.rect.origin_y) >
(s_info->dst.rect.corner_y - y_orig)) {
s_info->height = s_info->dst.rect.corner_y -
y_orig;
}
else {
s_info->height = s_info->src.rect.corner_y -
s_info->src.rect.origin_y;
/*
* Must change the destination corner.
*/
s_info->dst.rect.corner_y = y_orig +
s_info->height;
}
/*
* Set up source corners to BE CLOSED CORNERS.
* This is done because alot of -1's are being used in
* calculations of pointers when copying bitmaps from
* corner_y to origin_y, corner_x to origin_x.
* (for copyBitNeg(), see calculateOffsets())
*/
s_info->src.rect.origin_x = s_info->src.rect.origin_x;
s_info->src.rect.origin_y = s_info->src.rect.origin_y;
s_info->src.rect.corner_x = s_info->src.rect.origin_x +
s_info->width - 1;
s_info->src.rect.corner_y = s_info->src.rect.origin_y +
s_info->height - 1;
}
else {
/*
* Calculate the width in pixels and the height in
* scanlines.
*/
s_info->width = s_info->dst.rect.corner_x - x_orig;
s_info->height = s_info->dst.rect.corner_y - y_orig;
}
}
else {
/*
* Assume that the user has set everything up legally and
* all we have to do is set up our bltter (internal)
* coordinates.
*
* Set up the x origin and width.
*/
x_orig = u_info->dst_rect.origin_x;
s_info->width = u_info->dst_rect.corner_x - x_orig;
/*
* Set up y origin and height.
*/
y_orig = u_info->dst_rect.origin_y;
s_info->height = u_info->dst_rect.corner_y - y_orig;
/*
* Convert to zero based coordinate system.
*/
x_orig -= u_info->dst_bitmap.rect.origin_x;
y_orig -= u_info->dst_bitmap.rect.origin_y;
/*
* Set up the destination corners.
*/
s_info->dst.rect.corner_x = x_orig + s_info->width;
s_info->dst.rect.corner_y = y_orig + s_info->height;
/*
* Adjust source if necessary. (May only be using a tile.)
*/
if (s_info->is_src) {
/*
* We must have source and destination coordinates
* which are in the same coordinate system, a
* zero-based coordinate system in this case.
*/
s_info->src.rect.origin_x = u_info->src_rect.origin_x -
u_info->src_bitmap.rect.origin_x;
s_info->src.rect.origin_y = u_info->src_rect.origin_y -
u_info->src_bitmap.rect.origin_y;
/*
* Set up source corners to BE CLOSED CORNERS.
* This is done because alot of -1's are being used in
* calculations of pointers when copying bitmaps from
* corner_y to origin_y, corner_x to origin_x.
* (for copyBitNeg(), see calculateOffsets())
*/
s_info->src.rect.corner_x = s_info->src.rect.origin_x +
s_info->width - 1;
s_info->src.rect.corner_y = s_info->src.rect.origin_y +
s_info->height - 1;
}
}
/*
* Keep the final rectangle for outside use. (Others can extern
* changed_rect.)
*/
changed_rect.origin_x = x_orig;
changed_rect.origin_y = y_orig;
changed_rect.corner_x = s_info->dst.rect.corner_x;
changed_rect.corner_y = s_info->dst.rect.corner_y;
/*
* Set up destination corners to BE CLOSED CORNERS. This is done
* because alot of -1's are being used in calculations of pointers when
* copying bitmaps from corner_y to origin_y, corner_x to
* origin_x. (for copyBitNeg(), see calculateOffsets())
*/
s_info->dst.rect.corner_x -= 1;
s_info->dst.rect.corner_y -= 1;
/*
* Set up the number of words across the destination that will be
* affected. (Because we subracted one we don't have to subtract one
* from dst.rect.corner_x.)
*/
if ((s_info->nshorts = (DIV_BPW(s_info->dst.rect.corner_x) -
DIV_BPW(x_orig)) + 1) < 1) {
/*
* nshorts should always be positive.
*/
DEBUGF((blt_debug),
printf("dst cx,ox: %d,%d nshorts = %d - %d\n",
s_info->dst.rect.corner_x,x_orig,
DIV_BPW(s_info->dst.rect.corner_x),
DIV_BPW(x_orig)));
return(0);
}
DEBUGF((blt_debug),
printf("dst cx,ox: %d,%d nshorts = %d - %d, (IS %d)\n",
s_info->dst.rect.corner_x,x_orig,
DIV_BPW(s_info->dst.rect.corner_x),
DIV_BPW(x_orig),s_info->nshorts));
/*
* NOTE: This program ASSUMES that msk_bitmap's bounds are within
* the bounds of the msk_bitmap. If not, bummer.
*
* Mask bitmap specified?? Set up mask corners.
*/
if (u_info->blt_flags & BLT_MASKON) {
/*
* Currently, the msk_bitmap's rect is in destination
* coordinates and msk_bitmap.rect picks out the area of the
* mask to be used.
*
* Align the mask bitmap with the destination rectangle.
* Because the x_orig is zero based and the
* msk_bitmap box is not we add back the dst_bitmap.rect.
* This has the effect of putting the mask corners into
* a zero based coordinate system.
*/
s_info->msk.rect.origin_x = x_orig +
u_info->dst_bitmap.rect.origin_x -
u_info->msk_bitmap.rect.origin_x;
s_info->msk.rect.corner_x = s_info->msk.rect.origin_x +
s_info->width - 1;
s_info->msk.rect.origin_y = y_orig +
u_info->dst_bitmap.rect.origin_y -
u_info->msk_bitmap.rect.origin_y;
s_info->msk.rect.corner_y = s_info->msk.rect.origin_y +
s_info->height - 1;
/*
* At some point it may be smart to check the clip flag and
* clip this also.
*
* if (u_info->blt_flags & BLT_CLIPON) {
* }
*/
}
/*
* Set the temp varibles into the system data structure.
*/
s_info->dst.rect.origin_x = x_orig;
s_info->dst.rect.origin_y = y_orig;
return(1);
}
/*
* This part of this file should be moved to another file someday.
*/
#define MSK_SKEW 0x01
#define SRC_SKEW 0x02
/*
* Macros for the operations.
*/
#define SrcCopy_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
((src) & mask)
/*
* Old SrcOr rule.
* #define SrcOr_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
* (((dst) | (src)) & mask)
*/
#define SrcOr_MASK(src,dst,mask) dst = ((dst) | ((src) & mask))
/*
* Old SrcXor rule.
* #define SrcXor_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
* (((dst) ^ (src)) & mask)
*/
#define SrcXor_MASK(src,dst,mask) dst = ((dst) ^ ((src) & mask))
#define SrcAnd_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
(((dst) & (src)) & mask)
#define NotSrcCopy_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
(~(src) & mask)
/*
* Old NotSrcOr rule.
* #define NotSrcOr_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
* (((dst) | ~(src)) & mask)
*/
#define NotSrcOr_MASK(src,dst,mask) dst = ((dst) | (~(src) & mask))
/*
* Old NotSrcXor rule.
* #define NotSrcXor_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
* (((dst) ^ ~(src)) & mask)
*/
#define NotSrcXor_MASK(src,dst,mask) dst = ((dst) ^ (~(src) & mask))
#define NotSrcAnd_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
(((dst) & ~(src)) & mask)
/*
* DstCopy is a no-op.
*/
#define SrcAndNotDst_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
((~(dst) & (src)) & mask)
#define SrcOrNotDst_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
((~(dst) | (src)) & mask)
#define NotDstCopy_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
(~(dst) & (mask))
#define NotSrcAndNotDst_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
((~(dst) & ~(src)) & mask)
#define NotSrcOrNotDst_MASK(src,dst,mask) dst = ((dst) & ~(mask)) | \
((~(dst) | ~(src)) & mask)
#define SrcCopy_OP(src,dst) dst = (src)
#define SrcOr_OP(src,dst) dst = (dst) | (src)
#define SrcXor_OP(src,dst) dst = (dst) ^ (src)
#define SrcAnd_OP(src,dst) dst = (dst) & (src)
#define NotSrcCopy_OP(src,dst) dst = ~(src)
#define NotSrcOr_OP(src,dst) dst = (dst) | ~(src)
#define NotSrcXor_OP(src,dst) dst = (dst) ^ ~(src)
#define NotSrcAnd_OP(src,dst) dst = (dst) & ~(src)
/*
* DstCopy is a no-op (dst = (dst)).
*/
#define SrcOrNotDst_OP(src,dst) dst = (~(dst) | (src))
#define SrcAndNotDst_OP(src,dst) dst = (~(dst) & (src))
#define NotDstCopy_OP(src,dst) dst = ~(dst)
#define NotSrcOrNotDst_OP(src,dst) dst = (~(dst) | ~(src))
#define NotSrcAndNotDst_OP(src,dst) dst = (~(dst) & ~(src))
/*
* Make the mask and operation macros for tiles.
*/
#define TileCopy_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
((tile) & mask)
#define TileOr_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
(((dst) | (tile)) & mask)
#define TileXor_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
(((dst) ^ (tile)) & mask)
#define NotTileAnd_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
(((dst) & ~(tile)) & mask)
#define NotTileCopy_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
(~(tile) & mask)
#define NotTileOr_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
(((dst) | ~(tile)) & mask)
#define NotTileXor_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
(((dst) ^ ~(tile)) & mask)
#define TileAnd_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
(((dst) & (tile)) & mask)
#define TileOrNotDst_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
((~(dst) | (tile)) & mask)
#define NotTileAndNotDst_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
((~(dst) & ~(tile)) & mask)
#define NotTileOrNotDst_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
((~(dst) | ~(tile)) & mask)
#define TileAndNotDst_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) | \
((~(dst) & (tile)) & mask)
#define TileCopy_OP(tile,dst) dst = (tile)
#define TileOr_OP(tile,dst) dst = (dst) | (tile)
#define TileXor_OP(tile,dst) dst = (dst) ^ (tile)
#define NotTileAnd_OP(tile,dst) dst = (dst) & ~(tile)
#define NotTileCopy_OP(tile,dst) dst = ~(tile)
#define NotTileOr_OP(tile,dst) dst = (dst) | ~(tile)
#define NotTileXor_OP(tile,dst) dst = (dst) ^ ~(tile)
#define TileAnd_OP(tile,dst) dst = (dst) & (tile)
#define TileOrNotDst_OP(tile,dst) dst = ~(dst) | (tile)
#define NotTileAndNotDst_OP(tile,dst) dst = ~(dst) & ~(tile)
#define NotTileOrNotDst_OP(tile,dst) dst = ~(dst) | ~(tile)
#define TileAndNotDst_OP(tile,dst) dst = ~(dst) & (tile)
#if (APA8 || APA8C)
/*
* Defines for how a pointer is incremented. This is needed because one must
* increment a pointer to the APA-8 bitmap by 2.
*/
#define DECR_SRC(src) src -= src_plus
#define DECR_DST(dst) dst -= dst_plus
#define INCR_SRC(src) src += src_plus
#define INCR_DST(dst) dst += dst_plus
#define MINUS_SRC(src) ((unsigned short *)(src - src_plus))
#define PLUS_SRC(src) ((unsigned short *)(src + src_plus))
#else no APA8 stuff
/*
* Defines for how normal pointers are incremented.
*/
#define DECR_SRC(src) (src -= 2)
#define DECR_DST(dst) (dst -= 2)
#define INCR_SRC(src) (src += 2)
#define INCR_DST(dst) (dst += 2)
#define MINUS_SRC(src) ((unsigned short *)(src - 2))
#define PLUS_SRC(src) ((unsigned short *)(src + 2))
#endif
#define SRC ((unsigned short *)src)
#define DST ((unsigned short *)dst)
#define TILE ((unsigned short *)tile)
#define MSK ((unsigned short *)msk)
#define CLP ((unsigned short *)clp)
#define DECR_MSK(msk) (msk -= 2)
#define INCR_MSK(msk) (msk += 2)
#define MINUS_MSK(msk) ((unsigned short *)(msk - 2))
#define PLUS_MSK(msk) ((unsigned short *)(msk + 2))
#define DECR_CLP(clp) (clp -= 2)
#define INCR_CLP(clp) (clp += 2)
#define MINUS_CLP(clp) ((unsigned short *)(clp - 2))
#define PLUS_CLP(clp) ((unsigned short *)(clp + 2))
/*
* Macro to increment the tile pointer. If last_ptr is reached then the
* pointer is decremented back to the beginning of the tile struct.
*/
#define INCR_TILE_PTR(ptr,last_ptr) ((ptr==last_ptr) ? (ptr -= 30) : (ptr += 2))
/*
* This loop copies bits from right to left, bottom to top. It takes as
* arguments 1 of 8 masking macros and the coorisponding generic macro.
* The general scheme is this:
* Foreach row do
* Take care of the first word priming if necessary. (Done because
* the first word uses the RIGHT edge mask.)
*
* If there is a skew then (Means parts of 2 source words make one
* destination word.)
* For each word between the first and last word do
* Shift the source word and source word -1 and
* write the word to the destination.
* endfor
*
* Take care of the last word. (Done here and not in
* the loop because the last word uses the
* LEFT edge mask.)
*
* else The skew is zero meaning 1 source word per destination
* word.
*
* For each word between the first and last word do
* Write the source word into the destination word.
* endfor
*
* Take care of the last word. (Done here and not in
* the loop because the last word uses the
* LEFT edge mask.)
* endif
*
* DECREMENT the source and destination pointers to point to the
* next row.
* endfor
*
*/
#define copyBitNeg_LOOP(EDGE_OP,OP) { \
while (--s_info->height) { \
wordnum = s_info->nshorts; \
if (s_info->preload_src) { \
EDGE_OP((*SRC >> skew_src) | \
(*(MINUS_SRC(src)) << (inv_skew_src)), \
*DST,s_info->right_mask); \
DECR_SRC(src); \
} \
else { \
EDGE_OP((*SRC << (inv_skew_src)),*DST, \
s_info->right_mask); \
} \
if (--wordnum != 0) { \
DECR_DST(dst); \
if (skew_src & 0xf) { \
while (wordnum > 1) { \
OP((*SRC >> skew_src) | \
(*(MINUS_SRC(src))<<(inv_skew_src)),\
*DST); \
DECR_SRC(src); \
DECR_DST(dst); \
wordnum--; \
} \
EDGE_OP((*SRC >> skew_src) | \
(*(MINUS_SRC(src)) << (inv_skew_src)),\
*DST,s_info->left_mask); \
DECR_SRC(src); \
} \
else { \
while (wordnum > 1) { \
DECR_SRC(src); \
OP(*SRC,*DST); \
DECR_DST(dst); \
wordnum--; \
} \
DECR_SRC(src); \
EDGE_OP(*SRC,*DST,s_info->left_mask); \
} \
} \
src -= s_info->src.nextline; \
dst -= s_info->dst.nextline; \
} \
}
/*
* Do setup and dereferencing of 5 of the most important Blt_sysdata variables.
* Then do a switch on the combination rule to do the correct loop. Each loop
* copies from right to left, bottom to top.
*/
copyBitNeg(s_info)
register Blt_sysdata *s_info;
{
register unsigned char *src; /* Register pointers are declared as */
/* unsigned char pointers. This is an */
register unsigned char *dst; /* optimization to get around extra */
/* addressing in the assembler. */
#if (APA8 || APA8C)
register int src_plus;
register int dst_plus;
#endif
register int wordnum;
register int skew_src;
register int inv_skew_src;
#if (APA8 || APA8C)
src_plus = s_info->src_plus;
dst_plus = s_info->dst_plus;
#endif
src = (unsigned char *)s_info->src.data;
dst = (unsigned char *)s_info->dst.data;
/*
* Set up the inverted skew number which is used to shift stuff the
* other direction.
*/
skew_src = s_info->skew_src;
inv_skew_src = BPW - skew_src;
DEBUGF(blt_debug,
printf("Enter copyBitNeg s:%d,p:%d,ws:%d r:%d\r\n",
s_info->skew_src,s_info->preload_src,
s_info->nshorts,s_info->rule));
/*
* Compiler optimization: a pre-decrement in a while loop saves a test
* in assembly language for every iteration.
*/
s_info->height += 1;
switch (s_info->rule) {
case SrcCopy:
copyBitNeg_LOOP(SrcCopy_MASK,SrcCopy_OP);
break;
case SrcOr:
copyBitNeg_LOOP(SrcOr_MASK,SrcOr_OP);
break;
case SrcXor:
copyBitNeg_LOOP(SrcXor_MASK,SrcXor_OP);
break;
case NotSrcAnd:
copyBitNeg_LOOP(NotSrcAnd_MASK,NotSrcAnd_OP);
break;
case NotSrcCopy:
copyBitNeg_LOOP(NotSrcCopy_MASK,NotSrcCopy_OP);
break;
case NotSrcOr:
copyBitNeg_LOOP(NotSrcOr_MASK,NotSrcOr_OP);
break;
case NotSrcXor:
copyBitNeg_LOOP(NotSrcXor_MASK,NotSrcXor_OP);
break;
case SrcAnd:
copyBitNeg_LOOP(SrcAnd_MASK,SrcAnd_OP);
break;
case SrcAndNotDst:
copyBitNeg_LOOP(SrcAndNotDst_MASK,SrcAndNotDst_OP);
break;
case NotSrcAndNotDst:
copyBitNeg_LOOP(NotSrcAndNotDst_MASK,NotSrcAndNotDst_OP);
break;
case SrcOrNotDst:
copyBitNeg_LOOP(SrcOrNotDst_MASK,SrcOrNotDst_OP);
break;
case NotSrcOrNotDst:
copyBitNeg_LOOP(NotSrcOrNotDst_MASK,NotSrcOrNotDst_OP);
break;
default:
break;
}
}
#if (APA8 || APA8C)
#define I_SRC src_plus
#define I_DST dst_plus
#else no APA8 stuff
#define I_SRC 2
#define I_DST 2
#endif
/*
* This loop copies bits from left to right, top to bottom. It takes as
* arguments 1 of 8 masking macros and the coorisponding generic macro.
* The general scheme is this:
* Foreach row do
* Take care of the first word priming if necessary. (Done because
* the first word uses the LEFT edge mask.)
*
* If there is a skew then (Means parts of 2 source words make one
* destination word.)
* For each word between the first and last word do
* Shift the source word and source word +1 and
* write the word to the destination.
* endfor
*
* Take care of the last word. (Done here and not in
* the loop because the last word uses the
* RIGHT edge mask.)
*
* else The skew is zero meaning 1 source word per destination
* word.
*
* For each word between the first and last word do
* Write the source word into the destination word
* endfor
*
* Take care of the last word. (Done here and not in
* the loop because the last word uses the
* RIGHT edge mask.)
* endif
*
* INCREMENT the source and destination pointers to point to the
* next row.
* endfor
*
*/
#define copyBitPos_LOOP(EDGE_OP,OP) { \
while (--s_info->height) { \
wordnum = s_info->nshorts; \
if (s_info->preload_src) { \
EDGE_OP((*SRC << skew_src) | \
(*(PLUS_SRC(src)) >> (inv_skew_src)),*DST,\
s_info->left_mask); \
INCR_SRC(src); \
} \
else { \
EDGE_OP((*SRC>>(inv_skew_src)),*DST,s_info->left_mask);\
} \
if (--wordnum != 0) { \
INCR_DST(dst); \
if (skew_src & 0xf) { \
while (wordnum-- > 1) { \
OP((*SRC << skew_src) | \
(*(PLUS_SRC(src)) >> (inv_skew_src)),\
*DST); \
INCR_DST(dst); \
INCR_SRC(src); \
} \
EDGE_OP((*SRC << skew_src) | \
(*(PLUS_SRC(src)) >> (inv_skew_src)),\
*DST,s_info->right_mask); \
INCR_SRC(src); \
} \
else { \
while (wordnum-- > 1) { \
INCR_SRC(src); \
OP(*SRC,*DST); \
INCR_DST(dst); \
} \
INCR_SRC(src); \
EDGE_OP(*SRC,*DST,s_info->right_mask); \
} \
} \
src += s_info->src.nextline; \
dst += s_info->dst.nextline; \
} \
}
/*
* Do setup and dereferencing of 5 of the most important Blt_sysdata variables.
* Then do a switch on the combination rule to do the correct loop. Each loop
* copies from left to right, top to bottom .
*/
copyBitPos(s_info)
register Blt_sysdata *s_info;
{
register unsigned char *src; /* Register pointers are declared as */
/* unsigned char pointers. This is an */
register unsigned char *dst; /* optimization to get around extra */
/* addressing in the assembler. */
#if (APA8 || APA8C)
register int src_plus;
register int dst_plus;
#endif
register int wordnum;
register int skew_src;
register int inv_skew_src;
#if (APA8 || APA8C)
src_plus = s_info->src_plus;
dst_plus = s_info->dst_plus;
#endif
src = (unsigned char *)s_info->src.data;
dst = (unsigned char *)s_info->dst.data;
skew_src = s_info->skew_src;
inv_skew_src = BPW - skew_src;
DEBUGF(blt_debug,
printf("Enter copyBitPos:%d,%d,%d,%d\r\n",s_info->skew_src,
inv_skew_src,s_info->preload_src,s_info->rule));
/*
* foreach row do.
*
* Compiler optimization: a pre-decrement in a while loop saves a test
* in assembly language for every iteration.
*/
s_info->height += 1;
switch (s_info->rule) {
case SrcCopy:
copyBitPos_LOOP(SrcCopy_MASK,SrcCopy_OP);
break;
case SrcOr:
copyBitPos_LOOP(SrcOr_MASK,SrcOr_OP);
break;
case SrcXor:
copyBitPos_LOOP(SrcXor_MASK,SrcXor_OP);
break;
case NotSrcAnd:
copyBitPos_LOOP(NotSrcAnd_MASK,NotSrcAnd_OP);
break;
case NotSrcCopy:
copyBitPos_LOOP(NotSrcCopy_MASK,NotSrcCopy_OP);
break;
case NotSrcOr:
copyBitPos_LOOP(NotSrcOr_MASK,NotSrcOr_OP);
break;
case NotSrcXor:
copyBitPos_LOOP(NotSrcXor_MASK,NotSrcXor_OP);
break;
case SrcAnd:
copyBitPos_LOOP(SrcAnd_MASK,SrcAnd_OP);
break;
case SrcAndNotDst:
copyBitPos_LOOP(SrcAndNotDst_MASK,SrcAndNotDst_OP);
break;
case NotSrcAndNotDst:
copyBitPos_LOOP(NotSrcAndNotDst_MASK,NotSrcAndNotDst_OP);
break;
case SrcOrNotDst:
copyBitPos_LOOP(SrcOrNotDst_MASK,SrcOrNotDst_OP);
break;
case NotSrcOrNotDst:
copyBitPos_LOOP(NotSrcOrNotDst_MASK,NotSrcOrNotDst_OP);
break;
default:
break;
}
}
#define MYDEBUG_PR(n,s)
#define smallcopyBitPos_LOOP(EDGE_OP,OP) { \
if (s_info->preload_src) { \
if (s_info->nshorts == 2) { \
MYDEBUG_PR(blt_debug,printf("preload 2\r\n")); \
while (--height) { \
EDGE_OP((*SRC << skew_src) | \
(*(PLUS_SRC(src)) >> (inv_skew_src)),\
*DST,s_info->left_mask); \
INCR_SRC(src); \
INCR_DST(dst); \
EDGE_OP((*SRC << skew_src) | \
(*(PLUS_SRC(src)) >> (inv_skew_src)),\
*DST,s_info->right_mask); \
src += (s_info->src.nextline + I_SRC); \
dst += s_info->dst.nextline; \
} \
} \
else { \
MYDEBUG_PR(blt_debug,printf("preload 1\r\n")); \
while (--height) { \
EDGE_OP((*SRC << skew_src) | \
(*(PLUS_SRC(src)) >> (inv_skew_src)),\
*DST,s_info->left_mask); \
src += (s_info->src.nextline + I_SRC); \
dst += s_info->dst.nextline; \
} \
} \
} \
else if (skew_src & 0xf) { \
if (s_info->nshorts == 2) { \
MYDEBUG_PR(blt_debug,printf("skew_src 2\r\n")); \
while (--height) { \
EDGE_OP((*SRC>>(inv_skew_src)), \
*DST,s_info->left_mask); \
INCR_DST(dst); \
EDGE_OP((*SRC << skew_src) | \
(*(PLUS_SRC(src)) >> (inv_skew_src)),\
*DST,s_info->right_mask); \
src += (s_info->src.nextline + I_SRC); \
dst += s_info->dst.nextline; \
} \
} \
else { \
MYDEBUG_PR(blt_debug,printf("skew_src 1\r\n")); \
while (--height) { \
EDGE_OP((*SRC>>(inv_skew_src)), \
*DST,s_info->left_mask); \
src += s_info->src.nextline; \
dst += s_info->dst.nextline; \
} \
} \
} \
else if (s_info->nshorts == 2) { \
MYDEBUG_PR(blt_debug,printf("lines up 2\r\n")); \
while (--height) { \
EDGE_OP(*SRC,*DST,s_info->left_mask); \
INCR_DST(dst); \
INCR_SRC(src); \
EDGE_OP(*SRC,*DST,s_info->right_mask); \
src += s_info->src.nextline; \
dst += s_info->dst.nextline; \
} \
} \
else { \
MYDEBUG_PR(blt_debug,printf("lines up 1\r\n")); \
while (--height) { \
EDGE_OP(*SRC,*DST,s_info->left_mask); \
src += s_info->src.nextline; \
dst += s_info->dst.nextline; \
} \
} \
}
/*
* Do setup and dereferencing of 5 of the most important Blt_sysdata variables.
* Then do a switch on the combination rule to do the correct loop. Each loop
* copies from left to right, top to bottom .
*/
smallcopyBitPos(s_info)
register Blt_sysdata *s_info;
{
register unsigned char *src; /* Register pointers are declared as */
/* unsigned char pointers. This is an */
register unsigned char *dst; /* optimization to get around extra */
/* addressing in the assembler. */
#if (APA8 || APA8C)
register int src_plus;
register int dst_plus;
#endif
register long height;
register int skew_src;
register int inv_skew_src;
#if (APA8 || APA8C)
src_plus = s_info->src_plus;
dst_plus = s_info->dst_plus;
#endif
src = (unsigned char *)s_info->src.data;
dst = (unsigned char *)s_info->dst.data;
height = s_info->height;
skew_src = s_info->skew_src;
inv_skew_src = BPW - skew_src;
DEBUGF(blt_debug,
printf("Enter smallcopyBitPos:%d,%d,%d,%d\r\n",skew_src,
inv_skew_src,s_info->preload_src,s_info->rule));
/*
* foreach row do.
*
* Compiler optimization: a pre-decrement in a while loop saves a test
* in assembly language for every iteration.
*/
height += 1;
switch (s_info->rule) {
case SrcCopy:
smallcopyBitPos_LOOP(SrcCopy_MASK,SrcCopy_OP);
break;
case SrcOr:
smallcopyBitPos_LOOP(SrcOr_MASK,SrcOr_OP);
break;
case SrcXor:
smallcopyBitPos_LOOP(SrcXor_MASK,SrcXor_OP);
break;
case NotSrcAnd:
smallcopyBitPos_LOOP(NotSrcAnd_MASK,NotSrcAnd_OP);
break;
case NotSrcCopy:
smallcopyBitPos_LOOP(NotSrcCopy_MASK,NotSrcCopy_OP);
break;
case NotSrcOr:
smallcopyBitPos_LOOP(NotSrcOr_MASK,NotSrcOr_OP);
break;
case NotSrcXor:
smallcopyBitPos_LOOP(NotSrcXor_MASK,NotSrcXor_OP);
break;
case SrcAnd:
smallcopyBitPos_LOOP(SrcAnd_MASK,SrcAnd_OP);
break;
case SrcAndNotDst:
smallcopyBitPos_LOOP(SrcAndNotDst_MASK,SrcAndNotDst_OP);
break;
case NotSrcAndNotDst:
smallcopyBitPos_LOOP(NotSrcAndNotDst_MASK,NotSrcAndNotDst_OP);
break;
case SrcOrNotDst:
smallcopyBitPos_LOOP(SrcOrNotDst_MASK,SrcOrNotDst_OP);
break;
case NotSrcOrNotDst:
smallcopyBitPos_LOOP(NotSrcOrNotDst_MASK,NotSrcOrNotDst_OP);
break;
default:
break;
}
}
/*
* This loop copies the tile to the destination. It takes as
* arguments 1 of 8 masking tile macros and the coorisponding generic
* tile macro. The general scheme is this:
* Foreach row do
* Copy the tile to the first word using the left edge mask.
*
* For each word between the first and last word do
* Copy the tile to the destination word.
* endfor
*
* Copy the tile to the first word using the right edge mask.
*
* INCREMENT the tile and destination pointers to point to the
* next row.
* endfor
*
*/
#define copyTile_LOOP(EDGE_OP,OP) { \
while (--height) { \
wordnum = s_info->nshorts; \
EDGE_OP(*TILE,*DST,s_info->left_mask); \
if (--wordnum != 0) { \
INCR_DST(dst); \
while (wordnum > 1) { \
OP(*TILE,*DST); \
INCR_DST(dst); \
wordnum--; \
} \
EDGE_OP(*TILE,*DST,s_info->right_mask);\
} \
INCR_TILE_PTR(tile,last_tile); \
dst += s_info->dst.nextline; \
} \
}
/*
* Tiles the destination.
*/
copyTile(s_info)
register Blt_sysdata *s_info;
{
/*
* For optimization, these registers are placed in order of importance.
*/
register unsigned char *dst; /* All register pointers are declared as */
/* unsigned char pointers. This is an */
/* optimization to get around extra */
/* addressing in the assembler. */
register unsigned char *tile;
#if (APA8 || APA8C)
register int dst_plus;
#endif
register int wordnum;
register unsigned char *last_tile;
register long height;
#if (APA8 || APA8C)
DEBUGF(blt_debug,
printf("Enter copyTile r:%d p:%d, i:%d dw:%d\r\n",s_info->rule,
s_info->dst_plus,s_info->dst.nextline,s_info->nshorts));
#else
DEBUGF(blt_debug,
printf("Enter copyTile r:%d i:%d dw:%d\r\n",s_info->rule,
s_info->dst.nextline,s_info->nshorts));
#endif
dst = (unsigned char *)s_info->dst.data;
tile = (unsigned char *)&s_info->tile_ptr[
MOD_BPW(s_info->dst.rect.origin_y)];
last_tile = (unsigned char *)&s_info->tile_ptr[15];
#if (APA8 || APA8C)
dst_plus = s_info->dst_plus;
#endif
/*
* Compiler optimization: a pre-decrement in a while loop saves a test
* in assembly language for every iteration.
*/
height = s_info->height + 1;
switch (s_info->rule) {
case DstClear:
case DstSet:
case TileDstClear:
case TileDstSet:
case TileCopy:
copyTile_LOOP(TileCopy_MASK,TileCopy_OP);
break;
case TileOr:
copyTile_LOOP(TileOr_MASK,TileOr_OP);
break;
case TileXor:
copyTile_LOOP(TileXor_MASK,TileXor_OP);
break;
case NotTileAnd:
copyTile_LOOP(NotTileAnd_MASK,NotTileAnd_OP);
break;
case NotTileCopy:
copyTile_LOOP(NotTileCopy_MASK,NotTileCopy_OP);
break;
case NotTileOr:
copyTile_LOOP(NotTileOr_MASK,NotTileOr_OP);
break;
case NotTileXor:
copyTile_LOOP(NotTileXor_MASK,NotTileXor_OP);
break;
case TileAnd:
copyTile_LOOP(TileAnd_MASK,TileAnd_OP);
break;
case TileNotDstCopy:
case NotDstCopy:
copyTile_LOOP(NotDstCopy_MASK,NotDstCopy_OP);
break;
case TileAndNotDst:
copyTile_LOOP(TileAndNotDst_MASK,TileAndNotDst_OP);
break;
case NotTileAndNotDst:
copyTile_LOOP(NotTileAndNotDst_MASK,NotTileAndNotDst_OP);
break;
case TileOrNotDst:
copyTile_LOOP(TileOrNotDst_MASK,TileOrNotDst_OP);
break;
case NotTileOrNotDst:
copyTile_LOOP(NotTileOrNotDst_MASK,NotTileOrNotDst_OP);
break;
default:
break;
}
}
/*
* This loop copies bits from right to left, bottom to top. It takes as
* arguments 1 of 8 masking macros. This loop has the same general structure
* as copyBitNeg_LOOP except that work must be done on the mask bitmap.
* This adds complexity because for optimization purposes, there are 4 loops
* instead of 2.
* The general scheme is this:
* Foreach row do
* Calculate the first MASK word priming if necessary.
*
* Take care of the first word priming if necessary and using
* the mask just calculated. (Done because
* the first word uses the RIGHT edge mask.)
*
* If the source and the MASK is skewed then
* (Means parts of 2 source words make one
* destination word and parts of 2 mask words are used
* to mask this one destination word.)
*
* For each word between the first and last word do
* Calculate the MASK word.
* Shift the source word and source word -1 and
* write the word to the destination using
* the mask just calculated.
* endfor
*
* Calculate the MASK word.
* Take care of the last word using the mask and left
* edge mask. (Done here and not in
* the loop because the last word uses the
* LEFT edge mask.)
*
* else if the MASK is skewed then
* For each word between the first and last word do
* Calculate the MASK word.
* Write the source word to the destination using
* the mask just calculated.
* endfor
*
* Calculate the MASK word.
* Take care of the last word using the mask and left
* edge mask.
*
* else if the source is skewed then
*
* For each word between the first and last word do
* Shift the source word and source word -1 and
* write the word to the destination using
* the mask.
* endfor
*
* Take care of the last word using the mask and left
* edge mask.
*
* else The source and mask skew are zero meaning 1 source word,
* one mask word are used per destination word.
*
* For each word between the first and last word do
* Write the source word into the destination
* using the mask word.
* endfor
*
* Take care of the last word using the mask word and
* the left edge mask.
* endif
*
* DECREMENT the source,destination and mask pointers to point
* to the next row in their respective bitmaps.
* endfor
*
*/
#define maskBitNeg_LOOP(MASK_OP) { \
while (--s_info->height) { \
wordnum = s_info->nshorts; \
if (s_info->preload_msk) { \
mask = (*MSK >> s_info->skew_msk) | \
(*MINUS_MSK(msk) << inv_skew_msk); \
DECR_MSK(msk); \
} \
else { \
mask = (*MSK << inv_skew_msk); \
} \
if (s_info->preload_src) { \
MASK_OP((*SRC >> s_info->skew_src) | \
(*(MINUS_SRC(src)) << (inv_skew_src)), \
*DST,s_info->right_mask & mask); \
DECR_SRC(src); \
} \
else { \
MASK_OP((*SRC << (inv_skew_src)),*DST, \
s_info->right_mask & mask); \
} \
if (--wordnum != 0) { \
DECR_DST(dst); \
if (write_mode == (MSK_SKEW | SRC_SKEW)) { \
while (wordnum-- > 1) { \
mask = (*MSK >> s_info->skew_msk) |\
(*MINUS_MSK(msk)<<inv_skew_msk);\
MASK_OP((*SRC >> s_info->skew_src) |\
(*(MINUS_SRC(src)) << \
inv_skew_src), \
*DST,mask); \
DECR_SRC(src); DECR_MSK(msk); \
DECR_DST(dst); \
} \
mask = (*MSK >> s_info->skew_msk) | \
(*MINUS_MSK(msk)<<inv_skew_msk); \
MASK_OP((*SRC >> s_info->skew_src) | \
(*(MINUS_SRC(src))<<inv_skew_src),\
*DST,s_info->left_mask & mask); \
DECR_SRC(src); DECR_MSK(msk); \
} \
else if (write_mode & MSK_SKEW) { \
while (wordnum-- > 1) { \
mask = (*MSK >> s_info->skew_msk) |\
(*MINUS_MSK(msk)<<inv_skew_msk);\
DECR_SRC(src); DECR_MSK(msk); \
MASK_OP(*SRC,*DST,mask); \
DECR_DST(dst); \
} \
mask = (*MSK >> s_info->skew_msk) | \
(*MINUS_MSK(msk)<<inv_skew_msk); \
DECR_SRC(src); DECR_MSK(msk); \
MASK_OP(*SRC,*DST,s_info->left_mask&mask);\
} \
else if (write_mode & SRC_SKEW) { \
while (wordnum-- > 1) { \
DECR_MSK(msk); \
MASK_OP((*SRC >> s_info->skew_src) |\
(*(MINUS_SRC(src)) << \
inv_skew_src), \
*DST,*MSK); \
DECR_SRC(src); \
DECR_DST(dst); \
} \
DECR_MSK(msk); \
MASK_OP((*SRC >> s_info->skew_src) | \
(*(MINUS_SRC(src))<<inv_skew_src),\
*DST,s_info->left_mask & *MSK); \
DECR_SRC(src); \
} \
else { \
while (wordnum-- > 1) { \
DECR_SRC(src); DECR_MSK(msk); \
MASK_OP(*SRC,*DST,*MSK); \
DECR_DST(dst); \
} \
DECR_SRC(src); DECR_MSK(msk); \
MASK_OP(*SRC,*DST,s_info->left_mask & *MSK);\
} \
} \
src -= s_info->src.nextline; \
dst -= s_info->dst.nextline; \
msk -= s_info->msk.nextline; \
} \
}
/*
* Copies bits from bottom to top, right to left but only changes those bits
* that have corrisponding ones in the mask bitmap.
*/
maskBitNeg(s_info)
register Blt_sysdata *s_info;
{
register unsigned char *src; /* Register pointers are declared as */
/* unsigned char pointers. This is an */
register unsigned char *dst; /* optimization to get around extra */
/* addressing in the assembler. */
register unsigned char *msk; /* register pointer to the mask */
#if (APA8 || APA8C)
register int src_plus;
register int dst_plus;
#endif
register int wordnum; /* number of shorts per scanline */
register int inv_skew_src; /* BPW - skew_src */
register int inv_skew_msk; /* BPW - skew_msk */
register int write_mode; /* One of 4 modes: 0. no skew.
1. skew just the msk.
2. skew just the src.
3. skew both. */
register unsigned short mask;/* The local mask produced by shifting
*MSK and *MINUS_MASK() */
#if (APA8 || APA8C)
src_plus = s_info->src_plus;
dst_plus = s_info->dst_plus;
#endif
DEBUGF(blt_debug,
printf("Enter maskBitNeg. rule:%d\r\n",s_info->rule));
src = (unsigned char *)s_info->src.data;
dst = (unsigned char *)s_info->dst.data;
msk = (unsigned char *)s_info->msk.data;
inv_skew_src = BPW - s_info->skew_src;
inv_skew_msk = BPW - s_info->skew_msk;
/*
* Set the write mode so that the correct inner loop is picked.
*/
write_mode = 0;
if (s_info->skew_src & 0xf)
write_mode |= SRC_SKEW;
if (s_info->skew_msk & 0xf)
write_mode |= MSK_SKEW;
/*
* Compiler optimization: a pre-decrement in a while loop saves a test
* in assembly language for every iteration.
*/
s_info->height += 1;
switch (s_info->rule) {
case SrcCopy:
maskBitNeg_LOOP(SrcCopy_MASK);
break;
case SrcOr:
maskBitNeg_LOOP(SrcOr_MASK);
break;
case SrcXor:
maskBitNeg_LOOP(SrcXor_MASK);
break;
case NotSrcAnd:
maskBitNeg_LOOP(NotSrcAnd_MASK);
break;
case NotSrcCopy:
maskBitNeg_LOOP(NotSrcCopy_MASK);
break;
case NotSrcOr:
maskBitNeg_LOOP(NotSrcOr_MASK);
break;
case NotSrcXor:
maskBitNeg_LOOP(NotSrcXor_MASK);
break;
case SrcAnd:
maskBitNeg_LOOP(SrcAnd_MASK);
break;
case SrcAndNotDst:
maskBitNeg_LOOP(SrcAndNotDst_MASK);
break;
case NotSrcAndNotDst:
maskBitNeg_LOOP(NotSrcAndNotDst_MASK);
break;
case SrcOrNotDst:
maskBitNeg_LOOP(SrcOrNotDst_MASK);
break;
case NotSrcOrNotDst:
maskBitNeg_LOOP(NotSrcOrNotDst_MASK);
break;
default:
break;
}
}
/*
* This loop copies bits from left to right, top to bottom. It takes as
* arguments 1 of 8 masking macros. This loop has the same general structure
* as copyBitPos_LOOP except that work must be done on the mask bitmap.
* This adds complexity because, for optimization purposes, there are 4 loops
* instead of 2.
* The general scheme is this:
* Foreach row do
* Calculate the first MASK word priming if necessary.
*
* Take care of the first word priming if necessary and using
* the mask just calculated. (Done because
* the first word uses the RIGHT edge mask.)
*
* If the source and the MASK is skewed then
* (Means parts of 2 source words make one
* destination word and parts of 2 mask words are used
* to mask this one destination word.)
*
* For each word between the first and last word do
* Calculate the MASK word.
* Shift the source word and source word -1 and
* write the word to the destination using
* the mask just calculated.
* endfor
*
* Calculate the MASK word.
* Take care of the last word using the mask and left
* edge mask. (Done here and not in
* the loop because the last word uses the
* LEFT edge mask.)
*
* else if the MASK is skewed then
* For each word between the first and last word do
* Calculate the MASK word.
* Write the source word to the destination using
* the mask just calculated.
* endfor
*
* Calculate the MASK word.
* Take care of the last word using the mask and left
* edge mask.
*
* else if the source is skewed then
*
* For each word between the first and last word do
* Shift the source word and source word -1 and
* write the word to the destination using
* the mask.
* endfor
*
* Take care of the last word using the mask and left
* edge mask.
*
* else The source and mask skew are zero meaning 1 source word,
* one mask word are used per destination word.
*
* For each word between the first and last word do
* Write the source word into the destination
* using the mask word.
* endfor
*
* Take care of the last word using the mask word and
* the left edge mask.
* endif
*
* INCREMENT the source,destination and mask pointers to point
* to the next row in their respective bitmaps.
* endfor
*
*/
#define maskBitPos_LOOP(MASK_OP) { \
while (--s_info->height) { \
wordnum = s_info->nshorts; \
if (s_info->preload_msk) { \
mask = (*MSK << s_info->skew_msk) | \
(*PLUS_MSK(msk) >> inv_skew_msk); \
INCR_MSK(msk); \
} \
else { \
mask = (*MSK >> inv_skew_msk); \
} \
if (s_info->preload_src) { \
MASK_OP((*SRC << s_info->skew_src) | \
(*(PLUS_SRC(src)) >> (inv_skew_src)),*DST,\
s_info->left_mask & mask); \
INCR_SRC(src); \
} \
else { \
MASK_OP((*SRC >> (inv_skew_src)),*DST, \
s_info->left_mask & mask); \
} \
if (--wordnum != 0) { \
INCR_DST(dst); \
if (write_mode == (MSK_SKEW | SRC_SKEW)) { \
while (wordnum-- > 1) { \
mask = (*MSK << s_info->skew_msk) |\
(*PLUS_MSK(msk)>>inv_skew_msk);\
MASK_OP((*SRC << s_info->skew_src) |\
(*(PLUS_SRC(src)) >> \
(inv_skew_src)), \
*DST,mask); \
INCR_SRC(src); INCR_MSK(msk); \
INCR_DST(dst); \
} \
mask = (*MSK << s_info->skew_msk) | \
(*PLUS_MSK(msk) >> inv_skew_msk);\
MASK_OP((*SRC << s_info->skew_src) | \
(*(PLUS_SRC(src))>>(inv_skew_src)),\
*DST, s_info->right_mask & mask);\
INCR_SRC(src); INCR_MSK(msk); \
} \
else if (write_mode & MSK_SKEW) { \
while (wordnum-- > 1) { \
mask = (*MSK << s_info->skew_msk) |\
(*PLUS_MSK(msk) >> \
inv_skew_msk); \
INCR_SRC(src); INCR_MSK(msk); \
MASK_OP(*SRC,*DST,mask); \
INCR_DST(dst); \
} \
mask = (*MSK << s_info->skew_msk) | \
(*PLUS_MSK(msk) >> inv_skew_msk);\
INCR_SRC(src); INCR_MSK(msk); \
MASK_OP(*SRC,*DST, s_info->right_mask & mask);\
} \
else if (write_mode & SRC_SKEW) { \
while (wordnum-- > 1) { \
INCR_MSK(msk); \
MASK_OP((*SRC << s_info->skew_src) |\
(*(PLUS_SRC(src)) >> \
(inv_skew_src)), \
*DST,*MSK); \
INCR_SRC(src); \
INCR_DST(dst); \
} \
INCR_MSK(msk); \
MASK_OP((*SRC << s_info->skew_src) | \
(*(PLUS_SRC(src))>>(inv_skew_src)),\
*DST, s_info->right_mask & *MSK);\
INCR_SRC(src); \
} \
else { \
while (wordnum-- > 1) { \
INCR_SRC(src); INCR_MSK(msk); \
MASK_OP(*SRC,*DST,*MSK); \
INCR_DST(dst); \
} \
INCR_SRC(src); INCR_MSK(msk); \
MASK_OP(*SRC,*DST,s_info->right_mask & *MSK);\
} \
} \
src += s_info->src.nextline; \
dst += s_info->dst.nextline; \
msk += s_info->msk.nextline; \
} \
}
/*
* Copies bits from top to bottom , left to right but only changes those bits
* that have corrisponding ones in mask bitmap given.
*/
maskBitPos(s_info)
register Blt_sysdata *s_info;
{
register unsigned char *src; /* Register pointers are declared as */
/* unsigned char pointers. This is an */
register unsigned char *dst; /* optimization to get around extra */
/* addressing in the assembler. */
register unsigned char *msk; /* register pointer to the mask */
#if (APA8 || APA8C)
register int src_plus;
register int dst_plus;
#endif
register int wordnum; /* number of shorts per scanline */
register int inv_skew_src; /* BPW - skew_src */
register int inv_skew_msk; /* BPW - skew_msk */
register int write_mode; /* One of 4 modes: 0. no skew.
1. skew just the msk.
2. skew just the src.
3. skew both. */
register unsigned short mask;/* The local mask produced by shifting
*MSK and *PLUS_MASK() */
#if (APA8 || APA8C)
src_plus = s_info->src_plus;
dst_plus = s_info->dst_plus;
#endif
DEBUGF(blt_debug,printf("Enter maskBitPos. rule:%d\r\n",s_info->rule));
src = (unsigned char *)s_info->src.data;
dst = (unsigned char *)s_info->dst.data;
msk = (unsigned char *)s_info->msk.data;
inv_skew_msk = BPW - s_info->skew_msk;
inv_skew_src = BPW - s_info->skew_src;
/*
* Set the write mode so that the correct inner loop is picked.
*/
write_mode = 0;
if (s_info->skew_src & 0xf)
write_mode |= SRC_SKEW;
if (s_info->skew_msk & 0xf)
write_mode |= MSK_SKEW;
/*
* Compiler optimization: a pre-decrement in a while loop saves a test
* in assembly language for every iteration.
*/
s_info->height += 1;
switch (s_info->rule) {
case SrcCopy:
maskBitPos_LOOP(SrcCopy_MASK);
break;
case SrcOr:
maskBitPos_LOOP(SrcOr_MASK);
break;
case SrcXor:
maskBitPos_LOOP(SrcXor_MASK);
break;
case NotSrcAnd:
maskBitPos_LOOP(NotSrcAnd_MASK);
break;
case NotSrcCopy:
maskBitPos_LOOP(NotSrcCopy_MASK);
break;
case NotSrcOr:
maskBitPos_LOOP(NotSrcOr_MASK);
break;
case NotSrcXor:
maskBitPos_LOOP(NotSrcXor_MASK);
break;
case SrcAnd:
maskBitPos_LOOP(SrcAnd_MASK);
break;
case SrcAndNotDst:
maskBitPos_LOOP(SrcAndNotDst_MASK);
break;
case NotSrcAndNotDst:
maskBitPos_LOOP(NotSrcAndNotDst_MASK);
break;
case SrcOrNotDst:
maskBitPos_LOOP(SrcOrNotDst_MASK);
break;
case NotSrcOrNotDst:
maskBitPos_LOOP(NotSrcOrNotDst_MASK);
break;
default:
break;
}
}
/*
* This loop copies the tile to the destination only changing those bits
* in the destination that have coorisponding one's in the mask bitmap.
* It takes as arguments 1 of 8 masking tile macros. The general scheme
* is this:
* Foreach row do
* Calculate the MASK shifting if necessary.
* Copy the tile to the first word using the left edge mask and
* MASK.
*
* if the MASK is skewed then (2 mask words are needed for one
* destination word.)
* For each word between the first and last word do
* Calculate the MASK.
* Copy the tile to the destination word using
* the mask calculated.
* endfor
*
* Calculate the MASK.
* Copy the tile to the first word using the right edge mask and
* the mask calculated.
*
* else
* For each word between the first and last word do
* Copy the tile to the destination word using
* the mask.
* endfor
*
* Copy the tile to the first word using the
* right edge mask and the mask.
* endif
*
* INCREMENT the tile and destination pointers to point to the
* next row.
* endfor
*/
#define maskTile_LOOP(MASK_OP) { \
while (--s_info->height) { \
wordnum = s_info->nshorts; \
if (s_info->preload_msk) { \
mask = (*MSK << s_info->skew_msk) | \
(*PLUS_MSK(msk) >> inv_skew_msk); \
INCR_MSK(msk); \
} \
else { \
mask = (*MSK >> inv_skew_msk); \
} \
MASK_OP(*TILE,*DST,s_info->left_mask & mask); \
if (--wordnum != 0) { \
INCR_DST(dst); \
if (s_info->skew_msk & 0xf) { \
while (wordnum-- > 1) { \
mask = (*MSK << s_info->skew_msk) |\
(*PLUS_MSK(msk)>>inv_skew_msk);\
MASK_OP(*TILE,*DST,mask); \
INCR_DST(dst); INCR_MSK(msk); \
} \
mask = (*MSK << s_info->skew_msk) | \
(*PLUS_MSK(msk) >> inv_skew_msk);\
MASK_OP(*TILE,*DST, \
s_info->right_mask & mask); \
INCR_MSK(msk); \
} \
else { \
while (wordnum-- > 1) { \
INCR_MSK(msk); \
MASK_OP(*TILE,*DST,*MSK); \
INCR_DST(dst); \
} \
INCR_MSK(msk); \
MASK_OP(*TILE,*DST,s_info->right_mask & *MSK);\
} \
} \
INCR_TILE_PTR(tile,last_tile); \
dst += s_info->dst.nextline; \
msk += s_info->msk.nextline; \
} \
}
/*
* Copies a tile to the destination but only changes those bits
* that have corrisponding ones in the mask bitmap given.
*/
maskTile(s_info)
register Blt_sysdata *s_info;
{
register unsigned char *dst; /* Register pointers are declared as */
/* unsigned char pointers. This is an */
register unsigned char *msk; /* optimization to get around extra */
/* addressing in the assembler. */
register unsigned char *tile;/* register pointer to the tile */
#if (APA8 || APA8C)
register int src_plus;
register int dst_plus;
#endif
register unsigned char *last_tile;/* points to the last word in a tile*/
register int wordnum; /* number of shorts per scanline */
register int inv_skew_msk; /* BPW - skew_msk */
register unsigned short mask;/* The local mask produced by shifting
*MSK and *PLUS_MASK() */
#if (APA8 || APA8C)
src_plus = s_info->src_plus;
dst_plus = s_info->dst_plus;
#endif
dst = (unsigned char *)s_info->dst.data;
msk = (unsigned char *)s_info->msk.data;
tile = (unsigned char *)&s_info->tile_ptr[
MOD_BPW(s_info->dst.rect.origin_y)];
last_tile = (unsigned char *)(&s_info->tile_ptr[15]);
inv_skew_msk = BPW - s_info->skew_msk;
DEBUGF(blt_debug,
printf("Enter maskTile%d,%d %d %s %d\r\n",s_info->skew_msk,
inv_skew_msk,s_info->preload_msk,
((s_info->tile_ptr[0] == 0xffff &&
s_info->tile_ptr[5] == 0xffff) ?
"black" : "not black"),s_info->rule));
/*
* Compiler optimization: a pre-decrement in a while loop saves a test
* in assembly language for every iteration.
*/
s_info->height += 1;
switch (s_info->rule) {
case DstClear:
case DstSet:
case TileDstClear:
case TileDstSet:
case TileCopy:
maskTile_LOOP(TileCopy_MASK);
break;
case TileOr:
maskTile_LOOP(TileOr_MASK);
break;
case TileXor:
maskTile_LOOP(TileXor_MASK);
break;
case NotTileAnd:
maskTile_LOOP(NotTileAnd_MASK);
break;
case NotTileCopy:
maskTile_LOOP(NotTileCopy_MASK);
break;
case NotTileOr:
maskTile_LOOP(NotTileOr_MASK);
break;
case NotTileXor:
maskTile_LOOP(NotTileXor_MASK);
break;
case TileAnd:
maskTile_LOOP(TileAnd_MASK);
break;
case TileNotDstCopy:
case NotDstCopy:
maskTile_LOOP(NotDstCopy_MASK);
break;
case TileAndNotDst:
maskTile_LOOP(TileAndNotDst_MASK);
break;
case NotTileAndNotDst:
maskTile_LOOP(NotTileAndNotDst_MASK);
break;
case TileOrNotDst:
maskTile_LOOP(TileOrNotDst_MASK);
break;
case NotTileOrNotDst:
maskTile_LOOP(NotTileOrNotDst_MASK);
break;
default:
break;
}
}