Annotation of 43BSDTahoe/new/X/libibm/bitblt/bitblt_subr.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char *rcsid_bitblt_subr_c = "$Header: bitblt_subr.c,v 10.1 86/11/19 10:51:21 jg Exp $";
                      3: #endif lint
                      4: /*
                      5:  *             Copyright (c) 1986 Brown University
                      6:  *
                      7:  * Permission to use, copy, modify and distribute this software and its
                      8:  * documentation for any purpose and without fee is hereby granted, provided
                      9:  * that the above copyright notice appear in all copies, and that both
                     10:  * that copyright notice and this permission notice appear in supporting
                     11:  * documentation, and that the name of Brown University not be used in
                     12:  * advertising or publicity pertaining to distribution of the software without
                     13:  * specific, written prior permission. Brown University makes no
                     14:  * representations about the suitability of this software for any purpose.
                     15:  * It is provided "as-is" without express or implied warranty.
                     16:  *
                     17:  * Written by Daniel Stone, Brown University/IRIS  (des@iris)
                     18:  */
                     19: 
                     20: /*
                     21:  * CURRENT HISTORY:
                     22:  *
                     23:  * $Log:       bitblt_subr.c,v $
                     24:  * Revision 10.1  86/11/19  10:51:21  jg
                     25:  * Device dependent code for IBM displays.  General blitter...
                     26:  * 
                     27:  * Revision 4.0  86/09/25  10:03:10  des
                     28:  * Version 4.0. Works with all IBM screens.
                     29:  * 
                     30:  * Revision 3.6  86/09/22  16:47:44  des
                     31:  * Added a third argument to blt_init.
                     32:  * 
                     33:  * Revision 3.5  86/09/22  13:37:29  des
                     34:  * Version 3.5. Removed all ifdef's that did not pertain to X.
                     35:  * 
                     36:  * Revision 3.0  86/09/17  10:29:59  des
                     37:  * Version 3.0.  Works but has ifdef's for all systems.
                     38:  * 
                     39:  * Revision 7.0  86/07/03  10:40:03  des
                     40:  * Release 7.0.
                     41:  * 
                     42:  * Revision 6.1  86/07/03  10:29:10  des
                     43:  * Replaced certain mask rules.
                     44:  * 
                     45:  * Revision 6.0  86/06/18  11:19:59  des
                     46:  * Changed unsigned short pointers to unsigned char pointers for efficiency
                     47:  * reasons.  This change ment multiplying by 2 every variable added to
                     48:  * these pointers.
                     49:  * 
                     50:  * Revision 5.0  86/05/21  14:26:02  des
                     51:  * Revision 5.0.  No longer uses unsigned short pointers.
                     52:  * 
                     53:  * Revision 4.7  86/05/15  16:03:45  des
                     54:  * Latest and faster version of the new copyBitPos loop.  Runs 5% to 7% faster
                     55:  * than the old loop.
                     56:  * 
                     57:  * Revision 4.6  86/05/14  10:54:46  des
                     58:  * Changed smallcopyBitPos_LOOP so that it checks for 1 or 2 words changed
                     59:  * and branches to that loop.
                     60:  * 
                     61:  * Revision 4.5  86/05/14  10:31:57  des
                     62:  * bitblt with NEW_LOOP (needs work.)
                     63:  * 
                     64:  * Revision 4.0  86/05/09  13:52:25  des
                     65:  * Revision 4.0.  Apa-16 hardware enhancements Version 0.6.
                     66:  * 
                     67:  * Revision 3.2  86/04/30  15:34:16  des
                     68:  * This version has smallcopyBitPos and the old copyBitPos.  The new copyBitPos
                     69:  * took off .1 second on a 111 second blt. (new: 111.1 old:111.2) so what right?
                     70:  * The old copyBitPos did not need smallcopyBitPos around so I figured it was
                     71:  * better.
                     72:  * 
                     73:  * Revision 2.2  86/04/29  16:31:53  des
                     74:  * Added the smallcopyBitPos routine for speeding up small blts.
                     75:  * 
                     76:  * Revision 3.0  86/04/28  16:59:20  des
                     77:  * Runs with X. Version 0.5.
                     78:  * 
                     79:  * Revision 2.2  86/04/09  09:36:41  des
                     80:  * Fixed APA-8 and APA-8C software locator problem.
                     81:  * 
                     82:  * Revision 2.1  86/04/04  12:19:38  des
                     83:  * Moved copyBitNeg,copyBitPos,copyTile,maskBitNeg,maskBitPos,maskTile,
                     84:  * clip_and_maskBitNeg,clip_and_maskBitPos and clip_and_maskTile to
                     85:  * bitblt_subr.c.
                     86:  */
                     87: 
                     88: #ifndef lint
                     89: static char rcsid[] =
                     90: "$Header: bitblt_subr.c,v 10.1 86/11/19 10:51:21 jg Exp $ (Brown/IRIS)";
                     91: #endif
                     92: 
                     93: #include "bitblt_int.h"
                     94: 
                     95: /*
                     96:  * Keep track of the first and one beyond the last address of the screen,
                     97:  * so that current_screen.firstaddr <= some_base < current_screen.lastaddr
                     98:  * is true if some_base is a pointer to a section of the screen.
                     99:  */
                    100: Blt_screen_info blt_cur_screen;
                    101:  
                    102: static Blt_Tile blt_black = {
                    103:        0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
                    104:        0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff
                    105: };
                    106: 
                    107: extern Blt_Rectangle changed_rect;/* describes the area changed by the bltter */
                    108: 
                    109: /*
                    110:  * Set 'ans' to the largest value and set 'diff' equal to the difference
                    111:  * between 'ans' and 'a'.
                    112:  */
                    113: #define max_a(a,b,c,ans,diff) {                \
                    114:        if (a >= b) {                   \
                    115:                if (a >= c) {           \
                    116:                        diff = 0;       \
                    117:                        ans = a;        \
                    118:                }                       \
                    119:                else {                  \
                    120:                        diff = c - a;   \
                    121:                        ans = c;        \
                    122:                }                       \
                    123:        }                               \
                    124:        else if (b > c) {               \
                    125:                diff = b - a;           \
                    126:                ans = b;                \
                    127:        }                               \
                    128:        else {                          \
                    129:                diff = c - a;           \
                    130:                ans = c;                \
                    131:        }                               \
                    132: }
                    133: 
                    134: /*
                    135:  * Set 'ans' to the smallest value and set 'diff' equal to the difference
                    136:  * between 'ans' and 'a'.
                    137:  */
                    138: #define min_a(a,b,c,ans,diff) {                \
                    139:        if (a <= b) {                   \
                    140:                if (a <= c) {           \
                    141:                        diff = 0;       \
                    142:                        ans = a;        \
                    143:                }                       \
                    144:                else {                  \
                    145:                        diff = a - c;   \
                    146:                        ans = c;        \
                    147:                }                       \
                    148:        }                               \
                    149:        else if (b < c) {               \
                    150:                diff = a - b;           \
                    151:                ans = b;                \
                    152:        }                               \
                    153:        else {                          \
                    154:                diff = a - c;           \
                    155:                ans = c;                \
                    156:        }                               \
                    157: }
                    158: 
                    159: /* 
                    160:  * Initialize the bitblt so that it knows where in the address space the 
                    161:  * screen is and whether or not it uses a hardware or software cursor. 
                    162:  */
                    163: bitblt_init(screen_base,screen_wd,screen_ht,flags)
                    164: unsigned short *screen_base;   /* The first address of the bitmap */
                    165: long screen_wd;                        /* Screen width in BITS (will round up) */
                    166: long screen_ht;                        /* Screen height in scan lines */
                    167: unsigned long flags;           /* Indicates the type of cursor on the screen.*/
                    168: {
                    169:        blt_cur_screen.firstaddr = screen_base;
                    170:        blt_cur_screen.lastaddr = (unsigned short *)((long)screen_base +
                    171:                                  (((screen_wd+7)/8) * screen_ht));
                    172:        blt_cur_screen.cursortype = flags;
                    173: }
                    174: 
                    175: /*
                    176:  * Blt_setup takes information from the user data and creates data
                    177:  * to be used internally.  Specificly it creates clipped source rectangle
                    178:  * if a source combination rule is given, a clipped destination rectangle
                    179:  * the number of destination words to be changed across a scanline
                    180:  * (nshorts) and masking bitmap rectangle masking is to be done.
                    181:  * Finally the width and height and rule are filled in as width,
                    182:  * height and rule.
                    183:  * 
                    184:  * If a bad pointer was encountered  (or something else is wrong) then
                    185:  * blt_setup returns -1. Returns 0 if combination rule was a no-op and
                    186:  * 1 if blt_setup finished ok.
                    187:  */
                    188: blt_setup(u_info,s_info)
                    189: register Blt_userdata *u_info; /* User bitblt data */
                    190: register Blt_sysdata *s_info;  /* bitblt internal data (This is modified
                    191:                                   bitblt user data depending on the clipping
                    192:                                   to be done. */
                    193: {
                    194:        register int x_orig,y_orig;/* because the destination x,y origin
                    195:                                      is used so much, it will be put in
                    196:                                      registers. */
                    197:        register int Oxdiff,Cxdiff;/* If the destination rectangle is clipped
                    198:                                      then these variables contain the
                    199:                                      difference between the destination
                    200:                                      rectangle and the rectangle used
                    201:                                      to clip. */
                    202:        register int Oydiff,Cydiff;/* If the destination rectangle is clipped
                    203:                                      then these variables contain the
                    204:                                      difference between the destination
                    205:                                      rectangle and the rectangle used
                    206:                                      to clip. */
                    207: 
                    208:        DEBUGF((blt_debug > 1),
                    209:               printf("Enter blt_setup.0x%x\r\n",u_info->blt_flags));
                    210: 
                    211:        /*
                    212:         * Set up the internal bltters combination rule.
                    213:         */
                    214:        s_info->rule = u_info->comb_rule;
                    215: 
                    216:        /*
                    217:         * Set a flag indicating that the rule uses the source.
                    218:         */
                    219:        s_info->is_src = IS_SRC(s_info->rule);
                    220: 
                    221:        /*
                    222:         * Make sure s_info->tile_ptr = 0. 
                    223:         */
                    224:        s_info->tile_ptr = (unsigned short *)0;
                    225: 
                    226:        /*
                    227:         * Check the bltstruct to make sure every pointer is valid.
                    228:         */
                    229:        if (u_info == (Blt_userdata *)0) {
                    230:                printf("Error: NULL bltstruct given!\n");
                    231:                return(-1);
                    232:        }
                    233: 
                    234:        if (u_info->dst_bitmap.base == (unsigned short *)0) {
                    235:                printf("Error: NULL destination bitmap!\n");
                    236:                return(-1);
                    237:        }
                    238: 
                    239:        /*
                    240:         * If a source combination rule was given and no bitmap was given then
                    241:         * we assume the user wants US to assume that the source is infinitely
                    242:         * large and is set to all one's.  This is the same thing as using
                    243:         * the coorisponding tile rule and an all black tile.
                    244:         */
                    245:        if (s_info->is_src && u_info->src_bitmap.base == (unsigned short *)0) {
                    246:                s_info->is_src = 0;
                    247:                s_info->rule += SRC_TO_TILE;
                    248:                s_info->tile_ptr = &blt_black.tile[0];
                    249:        }
                    250: 
                    251:        /*
                    252:         * Check the rule and if its a no-op then return immediately.
                    253:         */
                    254:        if (s_info->rule == DstCopy || s_info->rule == TileDstCopy) {
                    255:                return(0);
                    256:        }
                    257: 
                    258:        if (u_info->blt_flags & BLT_CLIPON) {
                    259:                /* DEBUGF(blt_debug,printf("Clip.\r\n")); */
                    260:                /*
                    261:                 * Do some clipping.  We clip to the clipping rectangle,
                    262:                 * the destination bitmap's rect and the destination
                    263:                 * rectangle.  NOTE that if the destination rectangle
                    264:                 * is clipped in any way then the source rectangle must
                    265:                 * also be changed, thats why we keep track of the difference
                    266:                 * in Oxdiff.
                    267:                 *
                    268:                 * Set the origin to be a zero based coorinate system.
                    269:                 */
                    270:                max_a(u_info->dst_rect.origin_x,
                    271:                      u_info->clp_rect.origin_x,
                    272:                      u_info->dst_bitmap.rect.origin_x,
                    273:                      x_orig,Oxdiff);
                    274: 
                    275:                x_orig -= u_info->dst_bitmap.rect.origin_x;
                    276: 
                    277:                /*
                    278:                 * Take the min value of the clipping rectangle X corner
                    279:                 * coord, bitmap rectangle X corner coord. and the
                    280:                 * destination rectangle X corner coord.. Cxdiff
                    281:                 * contains the difference between dst_rect.corner_x and
                    282:                 * the value returned.  Then convert to a zero based
                    283:                 * coordinate system.
                    284:                 */
                    285:                min_a(u_info->dst_rect.corner_x,
                    286:                      u_info->clp_rect.corner_x,
                    287:                      u_info->dst_bitmap.rect.corner_x,
                    288:                      s_info->dst.rect.corner_x,Cxdiff);
                    289: 
                    290:                s_info->dst.rect.corner_x -= u_info->dst_bitmap.rect.origin_x;
                    291: 
                    292:                /*
                    293:                 * Take the max value of the clipping rectangle Y origin
                    294:                 * coord, bitmap rectangle Y origin coord. and the
                    295:                 * destination rectangle Y origin coord..  Oydiff
                    296:                 * contains the difference between dst_rect.origin_y and
                    297:                 * the value returned.  Then convert to a zero based
                    298:                 * coordinate system.
                    299:                 */
                    300:                max_a(u_info->dst_rect.origin_y,
                    301:                      u_info->clp_rect.origin_y,
                    302:                      u_info->dst_bitmap.rect.origin_y,
                    303:                      y_orig,Oydiff);
                    304: 
                    305:                y_orig -= u_info->dst_bitmap.rect.origin_y;
                    306: 
                    307:                /*
                    308:                 * Take the min value of the clipping rectangle Y corner
                    309:                 * coord, bitmap rectangle Y corner coord. and the
                    310:                 * destination rectangle Y corner coord..  Cydiff
                    311:                 * contains the difference between dst_rect.corner_y and
                    312:                 * the value returned.  Then convert to a zero based
                    313:                 * coordinate system.
                    314:                 */
                    315:                min_a(u_info->dst_rect.corner_y,
                    316:                      u_info->clp_rect.corner_y,
                    317:                      u_info->dst_bitmap.rect.corner_y,
                    318:                      s_info->dst.rect.corner_y,Cydiff);
                    319: 
                    320:                s_info->dst.rect.corner_y -= u_info->dst_bitmap.rect.origin_y;
                    321: /*
                    322:  *             printf("dst:\t%4d,%4d,%4d,%4d\n",x_orig,
                    323:  *                     y_orig,s_info->dst.rect.corner_x,
                    324:  *                     s_info->dst.rect.corner_y);
                    325:  *             printf("diffs:\t%4d,%4d,%4d,%4d\n",Oxdiff,Oydiff,Cxdiff,Cydiff);
                    326:  */
                    327: 
                    328:                /*
                    329:                 * Adjust source if necessary. (May only be using a tile.)
                    330:                 */
                    331:                if (s_info->is_src) {
                    332:                        /*
                    333:                         * We may have done some clipping. If X was clipped
                    334:                         * then the section of the source that would have
                    335:                         * been mapped to the clipped section of the
                    336:                         * destination must also be clipped.
                    337:                         *      In other words if one clips the destination one
                    338:                         * must also clip the source.  Anyways 'Oxdiff' is set
                    339:                         * to the difference.  Then we subtract the rect
                    340:                         * of the source bitmap so as to get the source into
                    341:                         * the same coordinate system as the destination,
                    342:                         * a zero based system.
                    343:                         */ 
                    344:                        s_info->src.rect.origin_x = u_info->src_rect.origin_x +
                    345:                                                    Oxdiff -
                    346:                                               u_info->src_bitmap.rect.origin_x;
                    347: 
                    348:                        /*
                    349:                         * If Y was clipped then the section of source
                    350:                         * that would have mapped to the clipped section
                    351:                         * of the destination must also be clipped.
                    352:                         */
                    353:                        s_info->src.rect.origin_y = u_info->src_rect.origin_y +
                    354:                                                    Oydiff -
                    355:                                               u_info->src_bitmap.rect.origin_y;
                    356: 
                    357:                        /*
                    358:                         * Now clip to the source bitmap's origin which is
                    359:                         * now 0,0 because we subtracted its origin above.
                    360:                         */
                    361:                        if (s_info->src.rect.origin_x < 0) {
                    362:                                /*
                    363:                                 * The source rectangle has been clipped so
                    364:                                 * the destination rectangle must also be
                    365:                                 * clipped.
                    366:                                 */
                    367:                                x_orig -= s_info->src.rect.origin_x;
                    368:                                s_info->src.rect.origin_x = 0;
                    369:                        }
                    370:                        if (s_info->src.rect.origin_y < 0) {
                    371:                                /*
                    372:                                 * The source rectangle has been clipped so
                    373:                                 * the destination rectangle must also be
                    374:                                 * clipped.
                    375:                                 */
                    376:                                y_orig -= s_info->src.rect.origin_y;
                    377:                                s_info->src.rect.origin_y = 0;
                    378:                        }
                    379: 
                    380:                        /*
                    381:                         * Calculate the source rectangle's corner rect.
                    382:                         * NOTE: We are not setting these rect to a zero
                    383:                         *       based system yet.
                    384:                         */
                    385:                        s_info->src.rect.corner_x = u_info->src_rect.corner_x -
                    386:                                                    Cxdiff;
                    387:                        s_info->src.rect.corner_y = u_info->src_rect.corner_y -
                    388:                                                    Cydiff;
                    389: 
                    390:                        /*
                    391:                         * Clip these rect to the corner of the source
                    392:                         * bitmap corner rect.
                    393:                         */
                    394:                        if (s_info->src.rect.corner_x >
                    395:                                             u_info->src_bitmap.rect.corner_x) {
                    396:                                s_info->src.rect.corner_x =
                    397:                                               u_info->src_bitmap.rect.corner_x;
                    398:                        }
                    399:                        if (s_info->src.rect.corner_y >
                    400:                                             u_info->src_bitmap.rect.corner_y) {
                    401:                                s_info->src.rect.corner_y =
                    402:                                               u_info->src_bitmap.rect.corner_y;
                    403:                        }
                    404: 
                    405:                        /*
                    406:                         * Now set these rect to a zero based coordinate
                    407:                         * system.
                    408:                         */
                    409:                        s_info->src.rect.corner_x -=
                    410:                                               u_info->src_bitmap.rect.origin_x;
                    411:                        s_info->src.rect.corner_y -=
                    412:                                               u_info->src_bitmap.rect.origin_y;
                    413: 
                    414:                        /*
                    415:                         * Calculate the width in pixels of the blt area
                    416:                         * using the smaller of the two widths found in
                    417:                         * the source and destination rectangles.
                    418:                         */
                    419:                        if ((s_info->src.rect.corner_x -
                    420:                             s_info->src.rect.origin_x) >
                    421:                            (s_info->dst.rect.corner_x - x_orig)) {
                    422:                                s_info->width = s_info->dst.rect.corner_x -
                    423:                                                x_orig;
                    424:                        }
                    425:                        else {
                    426:                                s_info->width = s_info->src.rect.corner_x -
                    427:                                                s_info->src.rect.origin_x;
                    428: 
                    429:                                /*
                    430:                                 * Must change the destination corner.
                    431:                                 */
                    432:                                s_info->dst.rect.corner_x = x_orig +
                    433:                                                            s_info->width;
                    434:                        }
                    435: 
                    436:                        /*
                    437:                         * Calculate the height in scanlines of the blt area
                    438:                         * using the smaller of the two heights found in 
                    439:                         * the source and destination rectangles.
                    440:                         */
                    441:                        if ((s_info->src.rect.corner_y -
                    442:                             s_info->src.rect.origin_y) >
                    443:                            (s_info->dst.rect.corner_y - y_orig)) {
                    444:                                s_info->height = s_info->dst.rect.corner_y -
                    445:                                                 y_orig;
                    446:                        }
                    447:                        else {
                    448:                                s_info->height = s_info->src.rect.corner_y -
                    449:                                                 s_info->src.rect.origin_y;
                    450: 
                    451:                                /*
                    452:                                 * Must change the destination corner.
                    453:                                 */
                    454:                                s_info->dst.rect.corner_y = y_orig +
                    455:                                                            s_info->height;
                    456:                        }
                    457: 
                    458:                        /*
                    459:                         * Set up source corners to BE CLOSED CORNERS.
                    460:                         * This is done because alot of -1's are being used in
                    461:                         * calculations of pointers when copying bitmaps from
                    462:                         * corner_y to origin_y, corner_x to origin_x.
                    463:                         * (for copyBitNeg(), see calculateOffsets())
                    464:                         */
                    465:                        s_info->src.rect.origin_x = s_info->src.rect.origin_x;
                    466:                        s_info->src.rect.origin_y = s_info->src.rect.origin_y;
                    467:                        s_info->src.rect.corner_x = s_info->src.rect.origin_x +
                    468:                                                    s_info->width - 1;
                    469:                        s_info->src.rect.corner_y = s_info->src.rect.origin_y +
                    470:                                                    s_info->height - 1;
                    471:                }
                    472:                else {
                    473:                        /*
                    474:                         * Calculate the width in pixels and the height in
                    475:                         * scanlines.
                    476:                         */
                    477:                        s_info->width = s_info->dst.rect.corner_x - x_orig;
                    478:                        s_info->height = s_info->dst.rect.corner_y - y_orig;
                    479:                }
                    480:        }
                    481:        else {
                    482:                /*
                    483:                 * Assume that the user has set everything up legally and
                    484:                 * all we have to do is set up our bltter (internal)
                    485:                 * coordinates.
                    486:                 *
                    487:                 * Set up the x origin and width.
                    488:                 */
                    489:                x_orig = u_info->dst_rect.origin_x;
                    490:                s_info->width = u_info->dst_rect.corner_x - x_orig;
                    491: 
                    492:                /*
                    493:                 * Set up y origin and height.
                    494:                 */
                    495:                y_orig = u_info->dst_rect.origin_y;
                    496:                s_info->height = u_info->dst_rect.corner_y - y_orig;
                    497: 
                    498:                /*
                    499:                 * Convert to zero based coordinate system.
                    500:                 */
                    501:                x_orig -= u_info->dst_bitmap.rect.origin_x;
                    502:                y_orig -= u_info->dst_bitmap.rect.origin_y;
                    503: 
                    504:                /*
                    505:                 * Set up the destination corners.
                    506:                 */
                    507:                s_info->dst.rect.corner_x = x_orig + s_info->width;
                    508:                s_info->dst.rect.corner_y = y_orig + s_info->height;
                    509: 
                    510: 
                    511:                /*
                    512:                 * Adjust source if necessary. (May only be using a tile.)
                    513:                 */
                    514:                if (s_info->is_src) {
                    515:                        /*
                    516:                         * We must have source and destination coordinates
                    517:                         * which are in the same coordinate system, a
                    518:                         * zero-based coordinate system in this case.
                    519:                         */
                    520:                        s_info->src.rect.origin_x = u_info->src_rect.origin_x -
                    521:                                               u_info->src_bitmap.rect.origin_x;
                    522:                        s_info->src.rect.origin_y = u_info->src_rect.origin_y -
                    523:                                               u_info->src_bitmap.rect.origin_y;
                    524: 
                    525:                        /*
                    526:                         * Set up source corners to BE CLOSED CORNERS.
                    527:                         * This is done because alot of -1's are being used in
                    528:                         * calculations of pointers when copying bitmaps from
                    529:                         * corner_y to origin_y, corner_x to origin_x.
                    530:                         * (for copyBitNeg(), see calculateOffsets())
                    531:                         */
                    532:                        s_info->src.rect.corner_x = s_info->src.rect.origin_x +
                    533:                                                    s_info->width - 1;
                    534:                        s_info->src.rect.corner_y = s_info->src.rect.origin_y +
                    535:                                                    s_info->height - 1;
                    536:                }
                    537:        }
                    538: 
                    539:        /*
                    540:         * Keep the final rectangle for outside use.  (Others can extern
                    541:         * changed_rect.)
                    542:         */
                    543:        changed_rect.origin_x = x_orig;
                    544:        changed_rect.origin_y = y_orig;
                    545:        changed_rect.corner_x = s_info->dst.rect.corner_x;
                    546:        changed_rect.corner_y = s_info->dst.rect.corner_y;
                    547: 
                    548:        /*
                    549:         * Set up destination corners to BE CLOSED CORNERS.  This is done
                    550:         * because alot of -1's are being used in calculations of pointers when 
                    551:         * copying bitmaps from corner_y to origin_y, corner_x to
                    552:         * origin_x. (for copyBitNeg(), see calculateOffsets())
                    553:         */
                    554:        s_info->dst.rect.corner_x -= 1;
                    555:        s_info->dst.rect.corner_y -= 1;
                    556: 
                    557:        /*
                    558:         * Set up the number of words across the destination that will be
                    559:         * affected. (Because we subracted one we don't have to subtract one
                    560:         * from dst.rect.corner_x.)
                    561:         */
                    562:        if ((s_info->nshorts = (DIV_BPW(s_info->dst.rect.corner_x) -
                    563:            DIV_BPW(x_orig)) + 1) < 1) {
                    564:                /*
                    565:                 * nshorts should always be positive.
                    566:                 */
                    567:                DEBUGF((blt_debug),
                    568:                        printf("dst cx,ox: %d,%d nshorts = %d - %d\n",
                    569:                                s_info->dst.rect.corner_x,x_orig,
                    570:                                DIV_BPW(s_info->dst.rect.corner_x),
                    571:                                DIV_BPW(x_orig)));
                    572:                return(0);
                    573:        }
                    574:        DEBUGF((blt_debug),
                    575:                        printf("dst cx,ox: %d,%d nshorts = %d - %d, (IS %d)\n",
                    576:                                s_info->dst.rect.corner_x,x_orig,
                    577:                                DIV_BPW(s_info->dst.rect.corner_x),
                    578:                                DIV_BPW(x_orig),s_info->nshorts));
                    579: 
                    580:        /*
                    581:         * NOTE: This program ASSUMES that msk_bitmap's bounds are within
                    582:         *       the bounds of the msk_bitmap.  If not, bummer.
                    583:         *
                    584:         * Mask bitmap specified?? Set up mask corners.
                    585:         */
                    586:        if (u_info->blt_flags & BLT_MASKON) {
                    587:                /*
                    588:                 * Currently, the msk_bitmap's rect is in destination
                    589:                 * coordinates and msk_bitmap.rect picks out the area of the
                    590:                 * mask to be used.
                    591:                 * 
                    592:                 * Align the mask bitmap with the destination rectangle.
                    593:                 * Because the x_orig is zero based and the
                    594:                 * msk_bitmap box is not we add back the dst_bitmap.rect.
                    595:                 * This has the effect of putting the mask corners into
                    596:                 * a zero based coordinate system.
                    597:                 */
                    598:                s_info->msk.rect.origin_x = x_orig +
                    599:                                            u_info->dst_bitmap.rect.origin_x -
                    600:                                            u_info->msk_bitmap.rect.origin_x;
                    601:                s_info->msk.rect.corner_x = s_info->msk.rect.origin_x +
                    602:                                            s_info->width - 1;
                    603:                s_info->msk.rect.origin_y = y_orig +
                    604:                                            u_info->dst_bitmap.rect.origin_y -
                    605:                                            u_info->msk_bitmap.rect.origin_y;
                    606:                s_info->msk.rect.corner_y = s_info->msk.rect.origin_y +
                    607:                                            s_info->height - 1;
                    608: 
                    609:                /*
                    610:                 * At some point it may be smart to check the clip flag and
                    611:                 * clip this also.
                    612:                 *
                    613:                 * if (u_info->blt_flags & BLT_CLIPON) {
                    614:                 * }
                    615:                 */
                    616:        }
                    617: 
                    618:        /*
                    619:         * Set the temp varibles into the system data structure.
                    620:         */
                    621:        s_info->dst.rect.origin_x = x_orig;
                    622:        s_info->dst.rect.origin_y = y_orig;
                    623: 
                    624:        return(1);
                    625: }
                    626: 
                    627: /*
                    628:  * This part of this file should be moved to another file someday.
                    629:  */
                    630: 
                    631: #define MSK_SKEW 0x01
                    632: #define SRC_SKEW 0x02
                    633: 
                    634: /*
                    635:  * Macros for the operations.
                    636:  */
                    637: 
                    638: #define SrcCopy_MASK(src,dst,mask)    dst = ((dst) & ~(mask)) |  \
                    639:                                            ((src) & mask)
                    640: 
                    641: /*
                    642:  * Old SrcOr rule.
                    643:  * #define SrcOr_MASK(src,dst,mask)      dst = ((dst) & ~(mask)) |  \
                    644:  *                                         (((dst) | (src)) & mask)
                    645:  */
                    646: #define SrcOr_MASK(src,dst,mask)      dst = ((dst) | ((src) & mask))
                    647: 
                    648: /*
                    649:  * Old SrcXor rule.
                    650:  * #define SrcXor_MASK(src,dst,mask)     dst = ((dst) & ~(mask)) |  \
                    651:  *                                         (((dst) ^ (src)) & mask)
                    652:  */
                    653: #define SrcXor_MASK(src,dst,mask)     dst = ((dst) ^ ((src) & mask))
                    654: 
                    655: #define SrcAnd_MASK(src,dst,mask)      dst = ((dst) & ~(mask)) |  \
                    656:                                            (((dst) & (src)) & mask)
                    657: 
                    658: #define NotSrcCopy_MASK(src,dst,mask) dst = ((dst) & ~(mask)) |  \
                    659:                                            (~(src) & mask)
                    660: 
                    661: /*
                    662:  * Old NotSrcOr rule.
                    663:  * #define NotSrcOr_MASK(src,dst,mask)   dst = ((dst) & ~(mask)) |  \
                    664:  *                                         (((dst) | ~(src)) & mask)
                    665:  */
                    666: #define NotSrcOr_MASK(src,dst,mask)   dst = ((dst) | (~(src) & mask))
                    667: 
                    668: /*
                    669:  * Old NotSrcXor rule.
                    670:  * #define NotSrcXor_MASK(src,dst,mask)  dst = ((dst) & ~(mask)) |  \
                    671:  *                                         (((dst) ^ ~(src)) & mask)
                    672:  */
                    673: #define NotSrcXor_MASK(src,dst,mask)  dst = ((dst) ^ (~(src) & mask))
                    674: 
                    675: #define NotSrcAnd_MASK(src,dst,mask)  dst = ((dst) & ~(mask)) |  \
                    676:                                            (((dst) & ~(src)) & mask)
                    677: /*
                    678:  * DstCopy is a no-op.
                    679:  */
                    680: 
                    681: #define SrcAndNotDst_MASK(src,dst,mask) dst = ((dst) & ~(mask)) |  \
                    682:                                              ((~(dst) & (src)) & mask)
                    683: 
                    684: #define SrcOrNotDst_MASK(src,dst,mask)     dst = ((dst) & ~(mask)) |  \
                    685:                                                 ((~(dst) | (src)) & mask)
                    686: 
                    687: #define NotDstCopy_MASK(src,dst,mask)      dst = ((dst) & ~(mask)) | \
                    688:                                                 (~(dst) & (mask))
                    689: 
                    690: #define NotSrcAndNotDst_MASK(src,dst,mask) dst = ((dst) & ~(mask)) |  \
                    691:                                                 ((~(dst) & ~(src)) & mask)
                    692: 
                    693: #define NotSrcOrNotDst_MASK(src,dst,mask)  dst = ((dst) & ~(mask)) |  \
                    694:                                                 ((~(dst) | ~(src)) & mask)
                    695: 
                    696: #define SrcCopy_OP(src,dst)    dst = (src)
                    697: #define SrcOr_OP(src,dst)      dst = (dst) | (src)
                    698: #define SrcXor_OP(src,dst)     dst = (dst) ^ (src)
                    699: #define SrcAnd_OP(src,dst)     dst = (dst) & (src)
                    700: #define NotSrcCopy_OP(src,dst) dst = ~(src)
                    701: #define NotSrcOr_OP(src,dst)   dst = (dst) | ~(src)
                    702: #define NotSrcXor_OP(src,dst)  dst = (dst) ^ ~(src)
                    703: #define NotSrcAnd_OP(src,dst)  dst = (dst) & ~(src)
                    704: /*
                    705:  * DstCopy is a no-op (dst = (dst)).
                    706:  */
                    707: #define SrcOrNotDst_OP(src,dst)     dst = (~(dst) | (src))
                    708: #define SrcAndNotDst_OP(src,dst)    dst = (~(dst) & (src))
                    709: #define NotDstCopy_OP(src,dst)      dst = ~(dst)
                    710: #define NotSrcOrNotDst_OP(src,dst)  dst = (~(dst) | ~(src))
                    711: #define NotSrcAndNotDst_OP(src,dst) dst = (~(dst) & ~(src))
                    712: 
                    713: /*
                    714:  * Make the mask and operation macros for tiles.
                    715:  */
                    716: #define TileCopy_MASK(tile,dst,mask)    dst = ((dst) & ~(mask)) |  \
                    717:                                              ((tile) & mask)
                    718: 
                    719: #define TileOr_MASK(tile,dst,mask)      dst = ((dst) & ~(mask)) |  \
                    720:                                              (((dst) | (tile)) & mask)
                    721: 
                    722: #define TileXor_MASK(tile,dst,mask)     dst = ((dst) & ~(mask)) |  \
                    723:                                              (((dst) ^ (tile)) & mask)
                    724: 
                    725: #define NotTileAnd_MASK(tile,dst,mask)  dst = ((dst) & ~(mask)) |  \
                    726:                                              (((dst) & ~(tile)) & mask)
                    727: 
                    728: #define NotTileCopy_MASK(tile,dst,mask) dst = ((dst) & ~(mask)) |  \
                    729:                                              (~(tile) & mask)
                    730: 
                    731: #define NotTileOr_MASK(tile,dst,mask)   dst = ((dst) & ~(mask)) |  \
                    732:                                              (((dst) | ~(tile)) & mask)
                    733: 
                    734: #define NotTileXor_MASK(tile,dst,mask)  dst = ((dst) & ~(mask)) |  \
                    735:                                              (((dst) ^ ~(tile)) & mask)
                    736: 
                    737: #define TileAnd_MASK(tile,dst,mask)     dst = ((dst) & ~(mask)) |  \
                    738:                                              (((dst) & (tile)) & mask)
                    739: 
                    740: #define TileOrNotDst_MASK(tile,dst,mask)      dst = ((dst) & ~(mask)) |  \
                    741:                                                    ((~(dst) | (tile)) & mask)
                    742: 
                    743: #define NotTileAndNotDst_MASK(tile,dst,mask)  dst = ((dst) & ~(mask)) |  \
                    744:                                                    ((~(dst) & ~(tile)) & mask)
                    745: 
                    746: #define NotTileOrNotDst_MASK(tile,dst,mask)   dst = ((dst) & ~(mask)) |  \
                    747:                                                    ((~(dst) | ~(tile)) & mask)
                    748: 
                    749: #define TileAndNotDst_MASK(tile,dst,mask)     dst = ((dst) & ~(mask)) |  \
                    750:                                                    ((~(dst) & (tile)) & mask)
                    751: 
                    752: #define TileCopy_OP(tile,dst)   dst = (tile)
                    753: #define TileOr_OP(tile,dst)     dst = (dst) | (tile)
                    754: #define TileXor_OP(tile,dst)    dst = (dst) ^ (tile)
                    755: #define NotTileAnd_OP(tile,dst)         dst = (dst) & ~(tile)
                    756: #define NotTileCopy_OP(tile,dst) dst = ~(tile)
                    757: #define NotTileOr_OP(tile,dst)  dst = (dst) | ~(tile)
                    758: #define NotTileXor_OP(tile,dst)         dst = (dst) ^ ~(tile)
                    759: #define TileAnd_OP(tile,dst)    dst = (dst) & (tile)
                    760: 
                    761: #define TileOrNotDst_OP(tile,dst)      dst = ~(dst) | (tile)
                    762: #define NotTileAndNotDst_OP(tile,dst)  dst = ~(dst) & ~(tile)
                    763: #define NotTileOrNotDst_OP(tile,dst)   dst = ~(dst) | ~(tile)
                    764: #define TileAndNotDst_OP(tile,dst)     dst = ~(dst) & (tile)
                    765: 
                    766: #if (APA8 || APA8C)
                    767: /*
                    768:  * Defines for how a pointer is incremented.  This is needed because one must
                    769:  * increment a pointer to the APA-8 bitmap by 2.
                    770:  */
                    771: #define DECR_SRC(src)  src -= src_plus
                    772: #define DECR_DST(dst)  dst -= dst_plus
                    773: #define INCR_SRC(src)  src += src_plus
                    774: #define INCR_DST(dst)  dst += dst_plus
                    775: #define MINUS_SRC(src) ((unsigned short *)(src - src_plus))
                    776: #define PLUS_SRC(src)  ((unsigned short *)(src + src_plus))
                    777: #else no APA8 stuff
                    778: /*
                    779:  * Defines for how normal pointers are incremented.
                    780:  */
                    781: #define DECR_SRC(src)  (src -= 2)
                    782: #define DECR_DST(dst)  (dst -= 2)
                    783: #define INCR_SRC(src)  (src += 2)
                    784: #define INCR_DST(dst)  (dst += 2)
                    785: #define MINUS_SRC(src) ((unsigned short *)(src - 2))
                    786: #define PLUS_SRC(src)  ((unsigned short *)(src + 2))
                    787: #endif
                    788: 
                    789: #define SRC    ((unsigned short *)src)
                    790: #define DST    ((unsigned short *)dst)
                    791: #define TILE   ((unsigned short *)tile)
                    792: #define MSK    ((unsigned short *)msk)
                    793: #define CLP    ((unsigned short *)clp)
                    794: 
                    795: #define DECR_MSK(msk)  (msk -= 2)
                    796: #define INCR_MSK(msk)  (msk += 2)
                    797: #define MINUS_MSK(msk) ((unsigned short *)(msk - 2))
                    798: #define PLUS_MSK(msk)  ((unsigned short *)(msk + 2))
                    799: 
                    800: #define DECR_CLP(clp)  (clp -= 2)
                    801: #define INCR_CLP(clp)  (clp += 2)
                    802: #define MINUS_CLP(clp) ((unsigned short *)(clp - 2))
                    803: #define PLUS_CLP(clp)  ((unsigned short *)(clp + 2))
                    804: 
                    805: /*
                    806:  * Macro to increment the tile pointer.  If last_ptr is reached then the
                    807:  * pointer is decremented back to the beginning of the tile struct.
                    808:  */
                    809: #define INCR_TILE_PTR(ptr,last_ptr) ((ptr==last_ptr) ? (ptr -= 30) : (ptr += 2))
                    810: 
                    811: /*
                    812:  * This loop copies bits from right to left, bottom to top.  It takes as
                    813:  * arguments 1 of 8 masking macros and the coorisponding generic macro.
                    814:  * The general scheme is this:
                    815:  *     Foreach row do
                    816:  *             Take care of the first word priming if necessary. (Done because
                    817:  *                     the first word uses the RIGHT edge mask.)
                    818:  *
                    819:  *             If there is a skew then (Means parts of 2 source words make one
                    820:  *                     destination word.)
                    821:  *                     For each word between the first and last word do
                    822:  *                             Shift the source word and source word -1 and
                    823:  *                                     write the word to the destination.
                    824:  *                     endfor
                    825:  *
                    826:  *                     Take care of the last word. (Done here and not in 
                    827:  *                             the loop because the last word uses the 
                    828:  *                             LEFT edge mask.)
                    829:  * 
                    830:  *             else  The skew is zero meaning 1 source word per destination
                    831:  *                   word.
                    832:  * 
                    833:  *                     For each word between the first and last word do
                    834:  *                             Write the source word into the destination word.
                    835:  *                     endfor
                    836:  *
                    837:  *                     Take care of the last word. (Done here and not in 
                    838:  *                             the loop because the last word uses the 
                    839:  *                             LEFT edge mask.)
                    840:  *             endif
                    841:  *
                    842:  *             DECREMENT the source and destination pointers to point to the
                    843:  *                     next row.
                    844:  *     endfor
                    845:  *
                    846:  */
                    847: #define copyBitNeg_LOOP(EDGE_OP,OP) {                                  \
                    848:        while (--s_info->height) {                                      \
                    849:                wordnum = s_info->nshorts;                              \
                    850:                if (s_info->preload_src) {                              \
                    851:                        EDGE_OP((*SRC >> skew_src) |                    \
                    852:                                (*(MINUS_SRC(src)) << (inv_skew_src)),  \
                    853:                                *DST,s_info->right_mask);               \
                    854:                        DECR_SRC(src);                                  \
                    855:                }                                                       \
                    856:                else {                                                  \
                    857:                        EDGE_OP((*SRC << (inv_skew_src)),*DST,          \
                    858:                                s_info->right_mask);                    \
                    859:                }                                                       \
                    860:                if (--wordnum != 0) {                                   \
                    861:                        DECR_DST(dst);                                  \
                    862:                        if (skew_src & 0xf) {                           \
                    863:                                while (wordnum > 1) {                   \
                    864:                                        OP((*SRC >> skew_src) |         \
                    865:                                           (*(MINUS_SRC(src))<<(inv_skew_src)),\
                    866:                                           *DST);                       \
                    867:                                        DECR_SRC(src);                  \
                    868:                                        DECR_DST(dst);                  \
                    869:                                        wordnum--;                      \
                    870:                                }                                       \
                    871:                                EDGE_OP((*SRC >> skew_src) |            \
                    872:                                        (*(MINUS_SRC(src)) << (inv_skew_src)),\
                    873:                                        *DST,s_info->left_mask);        \
                    874:                                DECR_SRC(src);                          \
                    875:                        }                                               \
                    876:                        else {                                          \
                    877:                                while (wordnum > 1) {                   \
                    878:                                        DECR_SRC(src);                  \
                    879:                                        OP(*SRC,*DST);                  \
                    880:                                        DECR_DST(dst);                  \
                    881:                                        wordnum--;                      \
                    882:                                }                                       \
                    883:                                DECR_SRC(src);                          \
                    884:                                EDGE_OP(*SRC,*DST,s_info->left_mask);   \
                    885:                        }                                               \
                    886:                }                                                       \
                    887:        src -= s_info->src.nextline;                                    \
                    888:        dst -= s_info->dst.nextline;                                    \
                    889:        }                                                               \
                    890: }
                    891: 
                    892: /*
                    893:  * Do setup and dereferencing of 5 of the most important Blt_sysdata variables.
                    894:  * Then do a switch on the combination rule to do the correct loop.  Each loop
                    895:  * copies from right to left, bottom to top.
                    896:  */
                    897: copyBitNeg(s_info)
                    898: register Blt_sysdata *s_info;
                    899: {
                    900:        register unsigned char *src; /* Register pointers are declared as  */
                    901:                                     /* unsigned char pointers. This is an */
                    902:        register unsigned char *dst; /* optimization to get around extra   */
                    903:                                     /* addressing in the assembler.       */
                    904: #if (APA8 || APA8C)
                    905:        register int src_plus;
                    906:        register int dst_plus;
                    907: #endif
                    908:        register int wordnum;
                    909:        register int skew_src;
                    910:        register int inv_skew_src;
                    911: 
                    912: #if (APA8 || APA8C)
                    913:        src_plus = s_info->src_plus;
                    914:        dst_plus = s_info->dst_plus;
                    915: #endif
                    916: 
                    917:        src = (unsigned char *)s_info->src.data;
                    918:        dst = (unsigned char *)s_info->dst.data;
                    919: 
                    920:        /*
                    921:         * Set up the inverted skew number which is used to shift stuff the
                    922:         * other direction.
                    923:         */
                    924:        skew_src = s_info->skew_src;
                    925:        inv_skew_src = BPW - skew_src;
                    926: 
                    927:        DEBUGF(blt_debug,
                    928:                printf("Enter copyBitNeg s:%d,p:%d,ws:%d r:%d\r\n",
                    929:                        s_info->skew_src,s_info->preload_src,
                    930:                        s_info->nshorts,s_info->rule));
                    931: 
                    932:        /*
                    933:         * Compiler optimization: a pre-decrement in a while loop saves a test
                    934:         * in assembly language for every iteration.
                    935:         */
                    936:        s_info->height += 1;
                    937:        switch (s_info->rule) {
                    938:                case SrcCopy:
                    939:                     copyBitNeg_LOOP(SrcCopy_MASK,SrcCopy_OP);
                    940:                     break;
                    941: 
                    942:                case SrcOr:
                    943:                     copyBitNeg_LOOP(SrcOr_MASK,SrcOr_OP);
                    944:                     break;
                    945: 
                    946:                case SrcXor:
                    947:                     copyBitNeg_LOOP(SrcXor_MASK,SrcXor_OP);
                    948:                     break;
                    949: 
                    950:                case NotSrcAnd:   
                    951:                     copyBitNeg_LOOP(NotSrcAnd_MASK,NotSrcAnd_OP);
                    952:                     break;
                    953: 
                    954:                case NotSrcCopy:
                    955:                     copyBitNeg_LOOP(NotSrcCopy_MASK,NotSrcCopy_OP);
                    956:                     break;
                    957: 
                    958:                case NotSrcOr:
                    959:                     copyBitNeg_LOOP(NotSrcOr_MASK,NotSrcOr_OP);
                    960:                     break;
                    961: 
                    962:                case NotSrcXor:
                    963:                     copyBitNeg_LOOP(NotSrcXor_MASK,NotSrcXor_OP);
                    964:                     break;
                    965: 
                    966:                case SrcAnd:
                    967:                     copyBitNeg_LOOP(SrcAnd_MASK,SrcAnd_OP);
                    968:                     break;
                    969: 
                    970:                case SrcAndNotDst:
                    971:                     copyBitNeg_LOOP(SrcAndNotDst_MASK,SrcAndNotDst_OP);
                    972:                     break;
                    973: 
                    974:                case NotSrcAndNotDst:
                    975:                     copyBitNeg_LOOP(NotSrcAndNotDst_MASK,NotSrcAndNotDst_OP);
                    976:                     break;
                    977: 
                    978:                case SrcOrNotDst:
                    979:                     copyBitNeg_LOOP(SrcOrNotDst_MASK,SrcOrNotDst_OP);
                    980:                     break;
                    981: 
                    982:                case NotSrcOrNotDst:
                    983:                     copyBitNeg_LOOP(NotSrcOrNotDst_MASK,NotSrcOrNotDst_OP);
                    984:                     break;
                    985: 
                    986:                default:
                    987:                     break;
                    988:        }
                    989: }
                    990: 
                    991: #if (APA8 || APA8C)
                    992: #define I_SRC          src_plus
                    993: #define I_DST          dst_plus
                    994: #else no APA8 stuff
                    995: #define I_SRC          2
                    996: #define I_DST          2
                    997: #endif
                    998: 
                    999: /*
                   1000:  * This loop copies bits from left to right, top to bottom.  It takes as
                   1001:  * arguments 1 of 8 masking macros and the coorisponding generic macro.
                   1002:  * The general scheme is this:
                   1003:  *     Foreach row do
                   1004:  *             Take care of the first word priming if necessary. (Done because
                   1005:  *                     the first word uses the LEFT edge mask.)
                   1006:  *
                   1007:  *             If there is a skew then (Means parts of 2 source words make one
                   1008:  *                     destination word.)
                   1009:  *                     For each word between the first and last word do
                   1010:  *                             Shift the source word and source word +1 and
                   1011:  *                                     write the word to the destination.
                   1012:  *                     endfor
                   1013:  *
                   1014:  *                     Take care of the last word. (Done here and not in 
                   1015:  *                             the loop because the last word uses the 
                   1016:  *                             RIGHT edge mask.)
                   1017:  * 
                   1018:  *             else  The skew is zero meaning 1 source word per destination
                   1019:  *                   word.
                   1020:  * 
                   1021:  *                     For each word between the first and last word do
                   1022:  *                             Write the source word into the destination word
                   1023:  *                     endfor
                   1024:  *
                   1025:  *                     Take care of the last word. (Done here and not in 
                   1026:  *                             the loop because the last word uses the 
                   1027:  *                             RIGHT edge mask.)
                   1028:  *             endif
                   1029:  *
                   1030:  *             INCREMENT the source and destination pointers to point to the
                   1031:  *                     next row.
                   1032:  *     endfor
                   1033:  *
                   1034:  */
                   1035: #define copyBitPos_LOOP(EDGE_OP,OP) {                                  \
                   1036:        while (--s_info->height) {                                      \
                   1037:                wordnum = s_info->nshorts;                              \
                   1038:                if (s_info->preload_src) {                              \
                   1039:                        EDGE_OP((*SRC << skew_src) |                    \
                   1040:                                (*(PLUS_SRC(src)) >> (inv_skew_src)),*DST,\
                   1041:                                s_info->left_mask);                     \
                   1042:                        INCR_SRC(src);                                  \
                   1043:                }                                                       \
                   1044:                else {                                                  \
                   1045:                        EDGE_OP((*SRC>>(inv_skew_src)),*DST,s_info->left_mask);\
                   1046:                }                                                       \
                   1047:                if (--wordnum != 0) {                                   \
                   1048:                        INCR_DST(dst);                                  \
                   1049:                        if (skew_src & 0xf) {                           \
                   1050:                                while (wordnum-- > 1) {                 \
                   1051:                                        OP((*SRC << skew_src) |         \
                   1052:                                          (*(PLUS_SRC(src)) >> (inv_skew_src)),\
                   1053:                                           *DST);                       \
                   1054:                                        INCR_DST(dst);                  \
                   1055:                                        INCR_SRC(src);                  \
                   1056:                                }                                       \
                   1057:                                EDGE_OP((*SRC << skew_src) |            \
                   1058:                                        (*(PLUS_SRC(src)) >> (inv_skew_src)),\
                   1059:                                        *DST,s_info->right_mask);          \
                   1060:                                INCR_SRC(src);                             \
                   1061:                        }                                                  \
                   1062:                        else {                                             \
                   1063:                                while (wordnum-- > 1) {                    \
                   1064:                                        INCR_SRC(src);                     \
                   1065:                                        OP(*SRC,*DST);                     \
                   1066:                                        INCR_DST(dst);                     \
                   1067:                                }                                          \
                   1068:                                INCR_SRC(src);                             \
                   1069:                                EDGE_OP(*SRC,*DST,s_info->right_mask);     \
                   1070:                        }                                                  \
                   1071:                }                                                          \
                   1072:                src += s_info->src.nextline;                               \
                   1073:                dst += s_info->dst.nextline;                               \
                   1074:        }                                                                  \
                   1075: }
                   1076: 
                   1077: /*
                   1078:  * Do setup and dereferencing of 5 of the most important Blt_sysdata variables.
                   1079:  * Then do a switch on the combination rule to do the correct loop.  Each loop
                   1080:  * copies from left to right, top to bottom .
                   1081:  */
                   1082: copyBitPos(s_info)
                   1083: register Blt_sysdata *s_info;
                   1084: {
                   1085:        register unsigned char *src; /* Register pointers are declared as  */
                   1086:                                     /* unsigned char pointers. This is an */
                   1087:        register unsigned char *dst; /* optimization to get around extra   */
                   1088:                                     /* addressing in the assembler.       */
                   1089: #if (APA8 || APA8C)
                   1090:        register int src_plus;
                   1091:        register int dst_plus;
                   1092: #endif
                   1093:        register int wordnum;
                   1094:        register int skew_src;
                   1095:        register int inv_skew_src;
                   1096: 
                   1097: #if (APA8 || APA8C)
                   1098:        src_plus = s_info->src_plus;
                   1099:        dst_plus = s_info->dst_plus;
                   1100: #endif
                   1101:        src = (unsigned char *)s_info->src.data;
                   1102:        dst = (unsigned char *)s_info->dst.data;
                   1103: 
                   1104:        skew_src = s_info->skew_src;
                   1105:        inv_skew_src = BPW - skew_src;
                   1106: 
                   1107:        DEBUGF(blt_debug,
                   1108:                printf("Enter copyBitPos:%d,%d,%d,%d\r\n",s_info->skew_src,
                   1109:                        inv_skew_src,s_info->preload_src,s_info->rule));
                   1110: 
                   1111:        /*
                   1112:         * foreach row do.
                   1113:         *
                   1114:         * Compiler optimization: a pre-decrement in a while loop saves a test
                   1115:         * in assembly language for every iteration.
                   1116:         */
                   1117:        s_info->height += 1;
                   1118:        switch (s_info->rule) {
                   1119:                case SrcCopy:
                   1120:                     copyBitPos_LOOP(SrcCopy_MASK,SrcCopy_OP);
                   1121:                     break;
                   1122: 
                   1123:                case SrcOr:
                   1124:                     copyBitPos_LOOP(SrcOr_MASK,SrcOr_OP);
                   1125:                     break;
                   1126: 
                   1127:                case SrcXor:
                   1128:                     copyBitPos_LOOP(SrcXor_MASK,SrcXor_OP);
                   1129:                     break;
                   1130: 
                   1131:                case NotSrcAnd:   
                   1132:                     copyBitPos_LOOP(NotSrcAnd_MASK,NotSrcAnd_OP);
                   1133:                     break;
                   1134: 
                   1135:                case NotSrcCopy:
                   1136:                     copyBitPos_LOOP(NotSrcCopy_MASK,NotSrcCopy_OP);
                   1137:                     break;
                   1138: 
                   1139:                case NotSrcOr:
                   1140:                     copyBitPos_LOOP(NotSrcOr_MASK,NotSrcOr_OP);
                   1141:                     break;
                   1142: 
                   1143:                case NotSrcXor:
                   1144:                     copyBitPos_LOOP(NotSrcXor_MASK,NotSrcXor_OP);
                   1145:                     break;
                   1146: 
                   1147:                case SrcAnd:
                   1148:                     copyBitPos_LOOP(SrcAnd_MASK,SrcAnd_OP);
                   1149:                     break;
                   1150: 
                   1151:                case SrcAndNotDst:
                   1152:                     copyBitPos_LOOP(SrcAndNotDst_MASK,SrcAndNotDst_OP);
                   1153:                     break;
                   1154: 
                   1155:                case NotSrcAndNotDst:
                   1156:                     copyBitPos_LOOP(NotSrcAndNotDst_MASK,NotSrcAndNotDst_OP);
                   1157:                     break;
                   1158: 
                   1159:                case SrcOrNotDst:
                   1160:                     copyBitPos_LOOP(SrcOrNotDst_MASK,SrcOrNotDst_OP);
                   1161:                     break;
                   1162: 
                   1163:                case NotSrcOrNotDst:
                   1164:                     copyBitPos_LOOP(NotSrcOrNotDst_MASK,NotSrcOrNotDst_OP);
                   1165:                     break;
                   1166: 
                   1167:                default:
                   1168:                     break;
                   1169:        }
                   1170: }
                   1171: 
                   1172: #define MYDEBUG_PR(n,s)
                   1173: #define smallcopyBitPos_LOOP(EDGE_OP,OP) {                             \
                   1174:        if (s_info->preload_src) {                                      \
                   1175:                if (s_info->nshorts == 2) {                             \
                   1176:                        MYDEBUG_PR(blt_debug,printf("preload 2\r\n"));  \
                   1177:                        while (--height) {                              \
                   1178:                                EDGE_OP((*SRC << skew_src) |            \
                   1179:                                        (*(PLUS_SRC(src)) >> (inv_skew_src)),\
                   1180:                                         *DST,s_info->left_mask);       \
                   1181:                                INCR_SRC(src);                          \
                   1182:                                INCR_DST(dst);                          \
                   1183:                                EDGE_OP((*SRC << skew_src) |            \
                   1184:                                        (*(PLUS_SRC(src)) >> (inv_skew_src)),\
                   1185:                                        *DST,s_info->right_mask);       \
                   1186:                                src += (s_info->src.nextline + I_SRC);  \
                   1187:                                dst += s_info->dst.nextline;            \
                   1188:                        }                                               \
                   1189:                }                                                       \
                   1190:                else {                                                  \
                   1191:                        MYDEBUG_PR(blt_debug,printf("preload 1\r\n"));  \
                   1192:                        while (--height) {                              \
                   1193:                                EDGE_OP((*SRC << skew_src) |            \
                   1194:                                        (*(PLUS_SRC(src)) >> (inv_skew_src)),\
                   1195:                                         *DST,s_info->left_mask);       \
                   1196:                                src += (s_info->src.nextline + I_SRC);  \
                   1197:                                dst += s_info->dst.nextline;            \
                   1198:                        }                                               \
                   1199:                }                                                       \
                   1200:        }                                                               \
                   1201:        else if (skew_src & 0xf) {                                      \
                   1202:                if (s_info->nshorts == 2) {                             \
                   1203:                        MYDEBUG_PR(blt_debug,printf("skew_src 2\r\n")); \
                   1204:                        while (--height) {                              \
                   1205:                                EDGE_OP((*SRC>>(inv_skew_src)),         \
                   1206:                                        *DST,s_info->left_mask);        \
                   1207:                                INCR_DST(dst);                          \
                   1208:                                EDGE_OP((*SRC << skew_src) |            \
                   1209:                                        (*(PLUS_SRC(src)) >> (inv_skew_src)),\
                   1210:                                        *DST,s_info->right_mask);       \
                   1211:                                src += (s_info->src.nextline + I_SRC);  \
                   1212:                                dst += s_info->dst.nextline;            \
                   1213:                        }                                               \
                   1214:                }                                                       \
                   1215:                else {                                                  \
                   1216:                        MYDEBUG_PR(blt_debug,printf("skew_src 1\r\n")); \
                   1217:                        while (--height) {                              \
                   1218:                                EDGE_OP((*SRC>>(inv_skew_src)),         \
                   1219:                                        *DST,s_info->left_mask);        \
                   1220:                                src += s_info->src.nextline;            \
                   1221:                                dst += s_info->dst.nextline;            \
                   1222:                        }                                               \
                   1223:                }                                                       \
                   1224:        }                                                               \
                   1225:        else if (s_info->nshorts == 2) {                                \
                   1226:                MYDEBUG_PR(blt_debug,printf("lines up 2\r\n"));         \
                   1227:                while (--height) {                                      \
                   1228:                        EDGE_OP(*SRC,*DST,s_info->left_mask);           \
                   1229:                        INCR_DST(dst);                                  \
                   1230:                        INCR_SRC(src);                                  \
                   1231:                        EDGE_OP(*SRC,*DST,s_info->right_mask);          \
                   1232:                        src += s_info->src.nextline;                    \
                   1233:                        dst += s_info->dst.nextline;                    \
                   1234:                }                                                       \
                   1235:        }                                                               \
                   1236:        else {                                                          \
                   1237:                MYDEBUG_PR(blt_debug,printf("lines up 1\r\n"));         \
                   1238:                while (--height) {                                      \
                   1239:                        EDGE_OP(*SRC,*DST,s_info->left_mask);           \
                   1240:                        src += s_info->src.nextline;                    \
                   1241:                        dst += s_info->dst.nextline;                    \
                   1242:                }                                                       \
                   1243:        }                                                               \
                   1244: }
                   1245: 
                   1246: /*
                   1247:  * Do setup and dereferencing of 5 of the most important Blt_sysdata variables.
                   1248:  * Then do a switch on the combination rule to do the correct loop.  Each loop
                   1249:  * copies from left to right, top to bottom .
                   1250:  */
                   1251: smallcopyBitPos(s_info)
                   1252: register Blt_sysdata *s_info;
                   1253: {
                   1254:        register unsigned char *src; /* Register pointers are declared as  */
                   1255:                                     /* unsigned char pointers. This is an */
                   1256:        register unsigned char *dst; /* optimization to get around extra   */
                   1257:                                     /* addressing in the assembler.       */
                   1258: #if (APA8 || APA8C)
                   1259:        register int src_plus;
                   1260:        register int dst_plus;
                   1261: #endif
                   1262:        register long height;
                   1263:        register int skew_src;
                   1264:        register int inv_skew_src;
                   1265: 
                   1266: #if (APA8 || APA8C)
                   1267:        src_plus = s_info->src_plus;
                   1268:        dst_plus = s_info->dst_plus;
                   1269: #endif
                   1270:        src = (unsigned char *)s_info->src.data;
                   1271:        dst = (unsigned char *)s_info->dst.data;
                   1272: 
                   1273:        height = s_info->height;
                   1274:        skew_src = s_info->skew_src;
                   1275:        inv_skew_src = BPW - skew_src;
                   1276: 
                   1277:        DEBUGF(blt_debug,
                   1278:                printf("Enter smallcopyBitPos:%d,%d,%d,%d\r\n",skew_src,
                   1279:                        inv_skew_src,s_info->preload_src,s_info->rule));
                   1280: 
                   1281:        /*
                   1282:         * foreach row do.
                   1283:         *
                   1284:         * Compiler optimization: a pre-decrement in a while loop saves a test
                   1285:         * in assembly language for every iteration.
                   1286:         */
                   1287:        height += 1;
                   1288:        switch (s_info->rule) {
                   1289:                case SrcCopy:
                   1290:                     smallcopyBitPos_LOOP(SrcCopy_MASK,SrcCopy_OP);
                   1291:                     break;
                   1292: 
                   1293:                case SrcOr:
                   1294:                     smallcopyBitPos_LOOP(SrcOr_MASK,SrcOr_OP);
                   1295:                     break;
                   1296: 
                   1297:                case SrcXor:
                   1298:                     smallcopyBitPos_LOOP(SrcXor_MASK,SrcXor_OP);
                   1299:                     break;
                   1300: 
                   1301:                case NotSrcAnd:   
                   1302:                     smallcopyBitPos_LOOP(NotSrcAnd_MASK,NotSrcAnd_OP);
                   1303:                     break;
                   1304: 
                   1305:                case NotSrcCopy:
                   1306:                     smallcopyBitPos_LOOP(NotSrcCopy_MASK,NotSrcCopy_OP);
                   1307:                     break;
                   1308: 
                   1309:                case NotSrcOr:
                   1310:                     smallcopyBitPos_LOOP(NotSrcOr_MASK,NotSrcOr_OP);
                   1311:                     break;
                   1312: 
                   1313:                case NotSrcXor:
                   1314:                     smallcopyBitPos_LOOP(NotSrcXor_MASK,NotSrcXor_OP);
                   1315:                     break;
                   1316: 
                   1317:                case SrcAnd:
                   1318:                     smallcopyBitPos_LOOP(SrcAnd_MASK,SrcAnd_OP);
                   1319:                     break;
                   1320: 
                   1321:                case SrcAndNotDst:
                   1322:                     smallcopyBitPos_LOOP(SrcAndNotDst_MASK,SrcAndNotDst_OP);
                   1323:                     break;
                   1324: 
                   1325:                case NotSrcAndNotDst:
                   1326:                     smallcopyBitPos_LOOP(NotSrcAndNotDst_MASK,NotSrcAndNotDst_OP);
                   1327:                     break;
                   1328: 
                   1329:                case SrcOrNotDst:
                   1330:                     smallcopyBitPos_LOOP(SrcOrNotDst_MASK,SrcOrNotDst_OP);
                   1331:                     break;
                   1332: 
                   1333:                case NotSrcOrNotDst:
                   1334:                     smallcopyBitPos_LOOP(NotSrcOrNotDst_MASK,NotSrcOrNotDst_OP);
                   1335:                     break;
                   1336: 
                   1337:                default:
                   1338:                     break;
                   1339:        }
                   1340: }
                   1341: 
                   1342: /*
                   1343:  * This loop copies the tile to the destination. It takes as
                   1344:  * arguments 1 of 8 masking tile macros and the coorisponding generic
                   1345:  * tile  macro. The general scheme is this:
                   1346:  *     Foreach row do
                   1347:  *             Copy the tile to the first word using the left edge mask.
                   1348:  *
                   1349:  *             For each word between the first and last word do
                   1350:  *                     Copy the tile to the destination word.
                   1351:  *             endfor
                   1352:  *
                   1353:  *             Copy the tile to the first word using the right edge mask.
                   1354:  *
                   1355:  *             INCREMENT the tile and destination pointers to point to the
                   1356:  *                     next row.
                   1357:  *     endfor
                   1358:  *
                   1359:  */
                   1360: #define copyTile_LOOP(EDGE_OP,OP) {                    \
                   1361:        while (--height) {                              \
                   1362:                wordnum = s_info->nshorts;              \
                   1363:                EDGE_OP(*TILE,*DST,s_info->left_mask);  \
                   1364:                if (--wordnum != 0) {                   \
                   1365:                        INCR_DST(dst);                  \
                   1366:                        while (wordnum > 1) {           \
                   1367:                                OP(*TILE,*DST);         \
                   1368:                                INCR_DST(dst);          \
                   1369:                                wordnum--;              \
                   1370:                        }                               \
                   1371:                        EDGE_OP(*TILE,*DST,s_info->right_mask);\
                   1372:                }                                       \
                   1373:                INCR_TILE_PTR(tile,last_tile);          \
                   1374:                dst += s_info->dst.nextline;            \
                   1375:        }                                               \
                   1376: }
                   1377: 
                   1378: /*
                   1379:  * Tiles the destination.
                   1380:  */
                   1381: copyTile(s_info)
                   1382: register Blt_sysdata *s_info;
                   1383: {
                   1384:        /*
                   1385:         * For optimization, these registers are placed in order of importance.
                   1386:         */
                   1387:        register unsigned char *dst; /* All register pointers are declared as */
                   1388:                                     /* unsigned char pointers. This is an    */
                   1389:                                     /* optimization to get around extra      */
                   1390:                                     /* addressing in the assembler.          */
                   1391:        register unsigned char *tile;
                   1392: #if (APA8 || APA8C)
                   1393:        register int dst_plus;
                   1394: #endif
                   1395:        register int wordnum;
                   1396:        register unsigned char *last_tile;
                   1397:        register long height;
                   1398: 
                   1399: #if (APA8 || APA8C)
                   1400:        DEBUGF(blt_debug,
                   1401:                printf("Enter copyTile r:%d p:%d, i:%d dw:%d\r\n",s_info->rule,
                   1402:                        s_info->dst_plus,s_info->dst.nextline,s_info->nshorts));
                   1403: #else
                   1404:        DEBUGF(blt_debug,
                   1405:                printf("Enter copyTile r:%d i:%d dw:%d\r\n",s_info->rule,
                   1406:                        s_info->dst.nextline,s_info->nshorts));
                   1407: #endif
                   1408: 
                   1409:        dst = (unsigned char *)s_info->dst.data;
                   1410:        tile = (unsigned char *)&s_info->tile_ptr[
                   1411:                                            MOD_BPW(s_info->dst.rect.origin_y)];
                   1412:        last_tile = (unsigned char *)&s_info->tile_ptr[15];
                   1413: 
                   1414: #if (APA8 || APA8C)
                   1415:        dst_plus = s_info->dst_plus;
                   1416: #endif
                   1417: 
                   1418:        /*
                   1419:         * Compiler optimization: a pre-decrement in a while loop saves a test
                   1420:         * in assembly language for every iteration.
                   1421:         */
                   1422:        height = s_info->height + 1;
                   1423:        switch (s_info->rule) {
                   1424:                case DstClear:
                   1425:                case DstSet:
                   1426:                case TileDstClear:
                   1427:                case TileDstSet:
                   1428:                case TileCopy:
                   1429:                     copyTile_LOOP(TileCopy_MASK,TileCopy_OP);
                   1430:                     break;
                   1431: 
                   1432:                case TileOr:
                   1433:                     copyTile_LOOP(TileOr_MASK,TileOr_OP);
                   1434:                     break;
                   1435: 
                   1436:                case TileXor:
                   1437:                     copyTile_LOOP(TileXor_MASK,TileXor_OP);
                   1438:                     break;
                   1439: 
                   1440:                case NotTileAnd:
                   1441:                     copyTile_LOOP(NotTileAnd_MASK,NotTileAnd_OP);
                   1442:                     break;
                   1443: 
                   1444:                case NotTileCopy:
                   1445:                     copyTile_LOOP(NotTileCopy_MASK,NotTileCopy_OP);
                   1446:                     break;
                   1447: 
                   1448:                case NotTileOr:
                   1449:                     copyTile_LOOP(NotTileOr_MASK,NotTileOr_OP);
                   1450:                     break;
                   1451: 
                   1452:                case NotTileXor:
                   1453:                     copyTile_LOOP(NotTileXor_MASK,NotTileXor_OP);
                   1454:                     break;
                   1455: 
                   1456:                case TileAnd:
                   1457:                     copyTile_LOOP(TileAnd_MASK,TileAnd_OP);
                   1458:                     break;
                   1459: 
                   1460:                case TileNotDstCopy:
                   1461:                case NotDstCopy:
                   1462:                     copyTile_LOOP(NotDstCopy_MASK,NotDstCopy_OP);
                   1463:                     break;
                   1464: 
                   1465:                case TileAndNotDst:
                   1466:                     copyTile_LOOP(TileAndNotDst_MASK,TileAndNotDst_OP);
                   1467:                     break;
                   1468: 
                   1469:                case NotTileAndNotDst:
                   1470:                     copyTile_LOOP(NotTileAndNotDst_MASK,NotTileAndNotDst_OP);
                   1471:                     break;
                   1472: 
                   1473:                case TileOrNotDst:
                   1474:                     copyTile_LOOP(TileOrNotDst_MASK,TileOrNotDst_OP);
                   1475:                     break;
                   1476: 
                   1477:                case NotTileOrNotDst:
                   1478:                     copyTile_LOOP(NotTileOrNotDst_MASK,NotTileOrNotDst_OP);
                   1479:                     break;
                   1480: 
                   1481:                default:
                   1482:                     break;
                   1483:        }
                   1484: }
                   1485: 
                   1486: /*
                   1487:  * This loop copies bits from right to left, bottom to top.  It takes as
                   1488:  * arguments 1 of 8 masking macros.  This loop has the same general structure
                   1489:  * as copyBitNeg_LOOP except that work must be done on the mask bitmap.
                   1490:  * This adds complexity because for optimization purposes, there are 4 loops
                   1491:  * instead of 2.
                   1492:  * The general scheme is this:
                   1493:  *     Foreach row do
                   1494:  *             Calculate the first MASK word priming if necessary.
                   1495:  *
                   1496:  *             Take care of the first word priming if necessary and using
                   1497:  *                     the mask just calculated. (Done because
                   1498:  *                     the first word uses the RIGHT edge mask.)
                   1499:  *
                   1500:  *             If the source and the MASK is skewed then
                   1501:  *                     (Means parts of 2 source words make one
                   1502:  *                     destination word and parts of 2 mask words are used
                   1503:  *                     to mask this one destination word.)
                   1504:  *
                   1505:  *                     For each word between the first and last word do
                   1506:  *                             Calculate the MASK word.
                   1507:  *                             Shift the source word and source word -1 and
                   1508:  *                                     write the word to the destination using
                   1509:  *                                     the mask just calculated.
                   1510:  *                     endfor
                   1511:  *
                   1512:  *                     Calculate the MASK word.
                   1513:  *                     Take care of the last word using the mask and left
                   1514:  *                             edge mask. (Done here and not in 
                   1515:  *                             the loop because the last word uses the 
                   1516:  *                             LEFT edge mask.)
                   1517:  * 
                   1518:  *             else if the MASK is skewed then
                   1519:  *                     For each word between the first and last word do
                   1520:  *                             Calculate the MASK word.
                   1521:  *                             Write the source word to the destination using
                   1522:  *                                     the mask just calculated.
                   1523:  *                     endfor
                   1524:  *
                   1525:  *                     Calculate the MASK word.
                   1526:  *                     Take care of the last word using the mask and left
                   1527:  *                             edge mask.
                   1528:  *                     
                   1529:  *             else if the source is skewed then
                   1530:  *
                   1531:  *                     For each word between the first and last word do
                   1532:  *                             Shift the source word and source word -1 and
                   1533:  *                                     write the word to the destination using
                   1534:  *                                     the mask.
                   1535:  *                     endfor
                   1536:  *
                   1537:  *                     Take care of the last word using the mask and left
                   1538:  *                             edge mask.
                   1539:  *
                   1540:  *             else  The source and mask skew are zero meaning 1 source word,
                   1541:  *                   one mask word are used per destination word.
                   1542:  * 
                   1543:  *                     For each word between the first and last word do
                   1544:  *                             Write the source word into the destination
                   1545:  *                                     using the mask word.
                   1546:  *                     endfor
                   1547:  *
                   1548:  *                     Take care of the last word using the mask word and
                   1549:  *                             the left edge mask.
                   1550:  *             endif
                   1551:  *
                   1552:  *             DECREMENT the source,destination and mask pointers to point
                   1553:  *                     to the next row in their respective bitmaps.
                   1554:  *     endfor
                   1555:  *
                   1556:  */
                   1557: #define maskBitNeg_LOOP(MASK_OP) {                                     \
                   1558:        while (--s_info->height) {                                      \
                   1559:                wordnum = s_info->nshorts;                              \
                   1560:                if (s_info->preload_msk) {                              \
                   1561:                        mask = (*MSK >> s_info->skew_msk) |             \
                   1562:                               (*MINUS_MSK(msk) << inv_skew_msk);       \
                   1563:                        DECR_MSK(msk);                                  \
                   1564:                }                                                       \
                   1565:                else {                                                  \
                   1566:                        mask = (*MSK << inv_skew_msk);                  \
                   1567:                }                                                       \
                   1568:                if (s_info->preload_src) {                              \
                   1569:                        MASK_OP((*SRC >> s_info->skew_src) |            \
                   1570:                                (*(MINUS_SRC(src)) << (inv_skew_src)),  \
                   1571:                                *DST,s_info->right_mask & mask);        \
                   1572:                        DECR_SRC(src);                                  \
                   1573:                }                                                       \
                   1574:                else {                                                  \
                   1575:                        MASK_OP((*SRC << (inv_skew_src)),*DST,          \
                   1576:                                s_info->right_mask & mask);             \
                   1577:                }                                                       \
                   1578:                if (--wordnum != 0) {                                   \
                   1579:                        DECR_DST(dst);                                  \
                   1580:                        if (write_mode == (MSK_SKEW | SRC_SKEW)) {      \
                   1581:                                while (wordnum-- > 1) {                 \
                   1582:                                        mask = (*MSK >> s_info->skew_msk) |\
                   1583:                                               (*MINUS_MSK(msk)<<inv_skew_msk);\
                   1584:                                        MASK_OP((*SRC >> s_info->skew_src) |\
                   1585:                                                (*(MINUS_SRC(src)) <<   \
                   1586:                                                inv_skew_src),          \
                   1587:                                                *DST,mask);             \
                   1588:                                        DECR_SRC(src); DECR_MSK(msk);   \
                   1589:                                        DECR_DST(dst);                  \
                   1590:                                }                                       \
                   1591:                                mask = (*MSK >> s_info->skew_msk) |     \
                   1592:                                       (*MINUS_MSK(msk)<<inv_skew_msk); \
                   1593:                                MASK_OP((*SRC >> s_info->skew_src) |    \
                   1594:                                        (*(MINUS_SRC(src))<<inv_skew_src),\
                   1595:                                        *DST,s_info->left_mask & mask);  \
                   1596:                                DECR_SRC(src); DECR_MSK(msk);           \
                   1597:                        }                                               \
                   1598:                        else if (write_mode & MSK_SKEW) {               \
                   1599:                                while (wordnum-- > 1) {                 \
                   1600:                                        mask = (*MSK >> s_info->skew_msk) |\
                   1601:                                               (*MINUS_MSK(msk)<<inv_skew_msk);\
                   1602:                                        DECR_SRC(src); DECR_MSK(msk);   \
                   1603:                                        MASK_OP(*SRC,*DST,mask);        \
                   1604:                                        DECR_DST(dst);                  \
                   1605:                                }                                       \
                   1606:                                mask = (*MSK >> s_info->skew_msk) |     \
                   1607:                                       (*MINUS_MSK(msk)<<inv_skew_msk); \
                   1608:                                DECR_SRC(src); DECR_MSK(msk);           \
                   1609:                                MASK_OP(*SRC,*DST,s_info->left_mask&mask);\
                   1610:                        }                                               \
                   1611:                        else if (write_mode & SRC_SKEW) {               \
                   1612:                                while (wordnum-- > 1) {                 \
                   1613:                                        DECR_MSK(msk);                  \
                   1614:                                        MASK_OP((*SRC >> s_info->skew_src) |\
                   1615:                                                (*(MINUS_SRC(src)) <<   \
                   1616:                                                inv_skew_src),          \
                   1617:                                                *DST,*MSK);             \
                   1618:                                        DECR_SRC(src);                  \
                   1619:                                        DECR_DST(dst);                  \
                   1620:                                }                                       \
                   1621:                                DECR_MSK(msk);                          \
                   1622:                                MASK_OP((*SRC >> s_info->skew_src) |    \
                   1623:                                        (*(MINUS_SRC(src))<<inv_skew_src),\
                   1624:                                        *DST,s_info->left_mask & *MSK); \
                   1625:                                DECR_SRC(src);                          \
                   1626:                        }                                               \
                   1627:                        else {                                          \
                   1628:                                while (wordnum-- > 1) {                 \
                   1629:                                        DECR_SRC(src); DECR_MSK(msk);   \
                   1630:                                        MASK_OP(*SRC,*DST,*MSK);        \
                   1631:                                        DECR_DST(dst);                  \
                   1632:                                }                                       \
                   1633:                                DECR_SRC(src); DECR_MSK(msk);           \
                   1634:                                MASK_OP(*SRC,*DST,s_info->left_mask & *MSK);\
                   1635:                        }                                               \
                   1636:                }                                                       \
                   1637:                src -= s_info->src.nextline;                            \
                   1638:                dst -= s_info->dst.nextline;                            \
                   1639:                msk -= s_info->msk.nextline;                            \
                   1640:        }                                                               \
                   1641: }
                   1642: 
                   1643: /*
                   1644:  * Copies bits from bottom to top, right to left but only changes those bits
                   1645:  * that have corrisponding ones in the mask bitmap.
                   1646:  */
                   1647: maskBitNeg(s_info)
                   1648: register Blt_sysdata *s_info;
                   1649: {
                   1650:        register unsigned char *src; /* Register pointers are declared as  */
                   1651:                                     /* unsigned char pointers. This is an */
                   1652:        register unsigned char *dst; /* optimization to get around extra   */
                   1653:                                     /* addressing in the assembler.       */
                   1654:        register unsigned char *msk; /* register pointer to the mask */
                   1655: #if (APA8 || APA8C)
                   1656:        register int src_plus;
                   1657:        register int dst_plus;
                   1658: #endif
                   1659:        register int wordnum;        /* number of shorts per scanline */
                   1660:        register int inv_skew_src;   /* BPW - skew_src */
                   1661:        register int inv_skew_msk;   /* BPW - skew_msk */
                   1662:        register int write_mode;     /* One of 4 modes: 0. no skew.
                   1663:                                                        1. skew just the msk.
                   1664:                                                        2. skew just the src.
                   1665:                                                        3. skew both. */
                   1666:        register unsigned short mask;/* The local mask produced by shifting
                   1667:                                        *MSK and *MINUS_MASK() */
                   1668: 
                   1669: #if (APA8 || APA8C)
                   1670:        src_plus = s_info->src_plus;
                   1671:        dst_plus = s_info->dst_plus;
                   1672: #endif
                   1673: 
                   1674:        DEBUGF(blt_debug,
                   1675:                printf("Enter maskBitNeg. rule:%d\r\n",s_info->rule));
                   1676: 
                   1677:        src = (unsigned char *)s_info->src.data;
                   1678:        dst = (unsigned char *)s_info->dst.data;
                   1679:        msk = (unsigned char *)s_info->msk.data;
                   1680: 
                   1681:        inv_skew_src = BPW - s_info->skew_src;
                   1682:        inv_skew_msk = BPW - s_info->skew_msk;
                   1683: 
                   1684:        /*
                   1685:         * Set the write mode so that the correct inner loop is picked.
                   1686:         */
                   1687:        write_mode = 0;
                   1688:        if (s_info->skew_src & 0xf)
                   1689:                write_mode |= SRC_SKEW;
                   1690:        if (s_info->skew_msk & 0xf)
                   1691:                write_mode |= MSK_SKEW;
                   1692: 
                   1693:        /*
                   1694:         * Compiler optimization: a pre-decrement in a while loop saves a test
                   1695:         * in assembly language for every iteration.
                   1696:         */
                   1697:        s_info->height += 1;
                   1698:        switch (s_info->rule) {
                   1699:                case SrcCopy:
                   1700:                     maskBitNeg_LOOP(SrcCopy_MASK);
                   1701:                     break;
                   1702: 
                   1703:                case SrcOr:
                   1704:                     maskBitNeg_LOOP(SrcOr_MASK);
                   1705:                     break;
                   1706: 
                   1707:                case SrcXor:
                   1708:                     maskBitNeg_LOOP(SrcXor_MASK);
                   1709:                     break;
                   1710: 
                   1711:                case NotSrcAnd:   
                   1712:                     maskBitNeg_LOOP(NotSrcAnd_MASK);
                   1713:                     break;
                   1714: 
                   1715:                case NotSrcCopy:
                   1716:                     maskBitNeg_LOOP(NotSrcCopy_MASK);
                   1717:                     break;
                   1718: 
                   1719:                case NotSrcOr:
                   1720:                     maskBitNeg_LOOP(NotSrcOr_MASK);
                   1721:                     break;
                   1722: 
                   1723:                case NotSrcXor:
                   1724:                     maskBitNeg_LOOP(NotSrcXor_MASK);
                   1725:                     break;
                   1726: 
                   1727:                case SrcAnd:
                   1728:                     maskBitNeg_LOOP(SrcAnd_MASK);
                   1729:                     break;
                   1730: 
                   1731:                case SrcAndNotDst:
                   1732:                     maskBitNeg_LOOP(SrcAndNotDst_MASK);
                   1733:                     break;
                   1734: 
                   1735:                case NotSrcAndNotDst:
                   1736:                     maskBitNeg_LOOP(NotSrcAndNotDst_MASK);
                   1737:                     break;
                   1738: 
                   1739:                case SrcOrNotDst:
                   1740:                     maskBitNeg_LOOP(SrcOrNotDst_MASK);
                   1741:                     break;
                   1742: 
                   1743:                case NotSrcOrNotDst:
                   1744:                     maskBitNeg_LOOP(NotSrcOrNotDst_MASK);
                   1745:                     break;
                   1746: 
                   1747:                default:
                   1748:                     break;
                   1749:        }
                   1750: }
                   1751: 
                   1752: /*
                   1753:  * This loop copies bits from left to right, top to bottom.  It takes as
                   1754:  * arguments 1 of 8 masking macros.  This loop has the same general structure
                   1755:  * as copyBitPos_LOOP except that work must be done on the mask bitmap.
                   1756:  * This adds complexity because, for optimization purposes, there are 4 loops
                   1757:  * instead of 2.
                   1758:  * The general scheme is this:
                   1759:  *     Foreach row do
                   1760:  *             Calculate the first MASK word priming if necessary.
                   1761:  *
                   1762:  *             Take care of the first word priming if necessary and using
                   1763:  *                     the mask just calculated. (Done because
                   1764:  *                     the first word uses the RIGHT edge mask.)
                   1765:  *
                   1766:  *             If the source and the MASK is skewed then
                   1767:  *                     (Means parts of 2 source words make one
                   1768:  *                     destination word and parts of 2 mask words are used
                   1769:  *                     to mask this one destination word.)
                   1770:  *
                   1771:  *                     For each word between the first and last word do
                   1772:  *                             Calculate the MASK word.
                   1773:  *                             Shift the source word and source word -1 and
                   1774:  *                                     write the word to the destination using
                   1775:  *                                     the mask just calculated.
                   1776:  *                     endfor
                   1777:  *
                   1778:  *                     Calculate the MASK word.
                   1779:  *                     Take care of the last word using the mask and left
                   1780:  *                             edge mask. (Done here and not in 
                   1781:  *                             the loop because the last word uses the 
                   1782:  *                             LEFT edge mask.)
                   1783:  * 
                   1784:  *             else if the MASK is skewed then
                   1785:  *                     For each word between the first and last word do
                   1786:  *                             Calculate the MASK word.
                   1787:  *                             Write the source word to the destination using
                   1788:  *                                     the mask just calculated.
                   1789:  *                     endfor
                   1790:  *
                   1791:  *                     Calculate the MASK word.
                   1792:  *                     Take care of the last word using the mask and left
                   1793:  *                             edge mask.
                   1794:  *                     
                   1795:  *             else if the source is skewed then
                   1796:  *
                   1797:  *                     For each word between the first and last word do
                   1798:  *                             Shift the source word and source word -1 and
                   1799:  *                                     write the word to the destination using
                   1800:  *                                     the mask.
                   1801:  *                     endfor
                   1802:  *
                   1803:  *                     Take care of the last word using the mask and left
                   1804:  *                             edge mask.
                   1805:  *
                   1806:  *             else  The source and mask skew are zero meaning 1 source word,
                   1807:  *                   one mask word are used per destination word.
                   1808:  * 
                   1809:  *                     For each word between the first and last word do
                   1810:  *                             Write the source word into the destination
                   1811:  *                                     using the mask word.
                   1812:  *                     endfor
                   1813:  *
                   1814:  *                     Take care of the last word using the mask word and
                   1815:  *                             the left edge mask.
                   1816:  *             endif
                   1817:  *
                   1818:  *             INCREMENT the source,destination and mask pointers to point
                   1819:  *                     to the next row in their respective bitmaps.
                   1820:  *     endfor
                   1821:  *
                   1822:  */
                   1823: #define maskBitPos_LOOP(MASK_OP) {                                     \
                   1824:        while (--s_info->height) {                                      \
                   1825:                wordnum = s_info->nshorts;                              \
                   1826:                if (s_info->preload_msk) {                              \
                   1827:                        mask = (*MSK << s_info->skew_msk) |             \
                   1828:                               (*PLUS_MSK(msk) >> inv_skew_msk);        \
                   1829:                        INCR_MSK(msk);                                  \
                   1830:                }                                                       \
                   1831:                else {                                                  \
                   1832:                        mask = (*MSK >> inv_skew_msk);                  \
                   1833:                }                                                       \
                   1834:                if (s_info->preload_src) {                              \
                   1835:                        MASK_OP((*SRC << s_info->skew_src) |            \
                   1836:                                (*(PLUS_SRC(src)) >> (inv_skew_src)),*DST,\
                   1837:                                s_info->left_mask & mask);              \
                   1838:                        INCR_SRC(src);                                  \
                   1839:                }                                                       \
                   1840:                else {                                                  \
                   1841:                         MASK_OP((*SRC >> (inv_skew_src)),*DST,         \
                   1842:                                s_info->left_mask & mask);              \
                   1843:                }                                                       \
                   1844:                if (--wordnum != 0) {                                   \
                   1845:                        INCR_DST(dst);                                  \
                   1846:                        if (write_mode == (MSK_SKEW | SRC_SKEW)) {      \
                   1847:                                while (wordnum-- > 1) {                 \
                   1848:                                        mask = (*MSK << s_info->skew_msk) |\
                   1849:                                               (*PLUS_MSK(msk)>>inv_skew_msk);\
                   1850:                                        MASK_OP((*SRC << s_info->skew_src) |\
                   1851:                                                (*(PLUS_SRC(src)) >>    \
                   1852:                                                (inv_skew_src)),        \
                   1853:                                                *DST,mask);             \
                   1854:                                        INCR_SRC(src); INCR_MSK(msk);   \
                   1855:                                        INCR_DST(dst);                  \
                   1856:                                }                                       \
                   1857:                                mask = (*MSK << s_info->skew_msk) |     \
                   1858:                                       (*PLUS_MSK(msk) >> inv_skew_msk);\
                   1859:                                MASK_OP((*SRC << s_info->skew_src) |    \
                   1860:                                        (*(PLUS_SRC(src))>>(inv_skew_src)),\
                   1861:                                        *DST, s_info->right_mask & mask);\
                   1862:                                INCR_SRC(src); INCR_MSK(msk);           \
                   1863:                        }                                               \
                   1864:                        else if (write_mode & MSK_SKEW) {               \
                   1865:                                while (wordnum-- > 1) {                 \
                   1866:                                        mask = (*MSK << s_info->skew_msk) |\
                   1867:                                               (*PLUS_MSK(msk) >>       \
                   1868:                                                   inv_skew_msk);       \
                   1869:                                        INCR_SRC(src); INCR_MSK(msk);   \
                   1870:                                        MASK_OP(*SRC,*DST,mask);        \
                   1871:                                        INCR_DST(dst);                  \
                   1872:                                }                                       \
                   1873:                                mask = (*MSK << s_info->skew_msk) |     \
                   1874:                                          (*PLUS_MSK(msk) >> inv_skew_msk);\
                   1875:                                INCR_SRC(src); INCR_MSK(msk);           \
                   1876:                                MASK_OP(*SRC,*DST, s_info->right_mask & mask);\
                   1877:                        }                                               \
                   1878:                        else if (write_mode & SRC_SKEW) {               \
                   1879:                                while (wordnum-- > 1) {                 \
                   1880:                                        INCR_MSK(msk);                  \
                   1881:                                        MASK_OP((*SRC << s_info->skew_src) |\
                   1882:                                                (*(PLUS_SRC(src)) >>    \
                   1883:                                                (inv_skew_src)),        \
                   1884:                                                *DST,*MSK);             \
                   1885:                                        INCR_SRC(src);                  \
                   1886:                                        INCR_DST(dst);                  \
                   1887:                                }                                       \
                   1888:                                INCR_MSK(msk);                          \
                   1889:                                MASK_OP((*SRC << s_info->skew_src) |    \
                   1890:                                        (*(PLUS_SRC(src))>>(inv_skew_src)),\
                   1891:                                        *DST, s_info->right_mask & *MSK);\
                   1892:                                        INCR_SRC(src);                  \
                   1893:                        }                                               \
                   1894:                        else {                                          \
                   1895:                                while (wordnum-- > 1) {                 \
                   1896:                                        INCR_SRC(src); INCR_MSK(msk);   \
                   1897:                                        MASK_OP(*SRC,*DST,*MSK);        \
                   1898:                                        INCR_DST(dst);                  \
                   1899:                                }                                       \
                   1900:                                INCR_SRC(src); INCR_MSK(msk);           \
                   1901:                                MASK_OP(*SRC,*DST,s_info->right_mask & *MSK);\
                   1902:                        }                                               \
                   1903:                }                                                       \
                   1904:                src += s_info->src.nextline;                            \
                   1905:                dst += s_info->dst.nextline;                            \
                   1906:                msk += s_info->msk.nextline;                            \
                   1907:        }                                                               \
                   1908: }
                   1909: 
                   1910: /*
                   1911:  * Copies bits from top to bottom , left to right but only changes those bits
                   1912:  * that have corrisponding ones in mask bitmap given.
                   1913:  */
                   1914: maskBitPos(s_info)
                   1915: register Blt_sysdata *s_info;
                   1916: {
                   1917:        register unsigned char *src; /* Register pointers are declared as  */
                   1918:                                     /* unsigned char pointers. This is an */
                   1919:        register unsigned char *dst; /* optimization to get around extra   */
                   1920:                                     /* addressing in the assembler.       */
                   1921:        register unsigned char *msk; /* register pointer to the mask */
                   1922: #if (APA8 || APA8C)
                   1923:        register int src_plus;
                   1924:        register int dst_plus;
                   1925: #endif
                   1926:        register int wordnum;        /* number of shorts per scanline */
                   1927:        register int inv_skew_src;   /* BPW - skew_src */
                   1928:        register int inv_skew_msk;   /* BPW - skew_msk */
                   1929:        register int write_mode;     /* One of 4 modes: 0. no skew.
                   1930:                                                        1. skew just the msk.
                   1931:                                                        2. skew just the src.
                   1932:                                                        3. skew both. */
                   1933:        register unsigned short mask;/* The local mask produced by shifting
                   1934:                                        *MSK and *PLUS_MASK() */
                   1935: 
                   1936: #if (APA8 || APA8C)
                   1937:        src_plus = s_info->src_plus;
                   1938:        dst_plus = s_info->dst_plus;
                   1939: #endif
                   1940: 
                   1941:        DEBUGF(blt_debug,printf("Enter maskBitPos. rule:%d\r\n",s_info->rule));
                   1942: 
                   1943:        src = (unsigned char *)s_info->src.data;
                   1944:        dst = (unsigned char *)s_info->dst.data;
                   1945:        msk = (unsigned char *)s_info->msk.data;
                   1946: 
                   1947:        inv_skew_msk = BPW - s_info->skew_msk;
                   1948:        inv_skew_src = BPW - s_info->skew_src;
                   1949: 
                   1950:        /*
                   1951:         * Set the write mode so that the correct inner loop is picked.
                   1952:         */
                   1953:        write_mode = 0;
                   1954:        if (s_info->skew_src & 0xf)
                   1955:                write_mode |=  SRC_SKEW;
                   1956:        if (s_info->skew_msk & 0xf)
                   1957:                write_mode |= MSK_SKEW;
                   1958: 
                   1959:        /*
                   1960:         * Compiler optimization: a pre-decrement in a while loop saves a test
                   1961:         * in assembly language for every iteration.
                   1962:         */
                   1963:        s_info->height += 1;
                   1964:        switch (s_info->rule) {
                   1965:                case SrcCopy:
                   1966:                     maskBitPos_LOOP(SrcCopy_MASK);
                   1967:                     break;
                   1968: 
                   1969:                case SrcOr:
                   1970:                     maskBitPos_LOOP(SrcOr_MASK);
                   1971:                     break;
                   1972: 
                   1973:                case SrcXor:
                   1974:                     maskBitPos_LOOP(SrcXor_MASK);
                   1975:                     break;
                   1976: 
                   1977:                case NotSrcAnd:   
                   1978:                     maskBitPos_LOOP(NotSrcAnd_MASK);
                   1979:                     break;
                   1980: 
                   1981:                case NotSrcCopy:
                   1982:                     maskBitPos_LOOP(NotSrcCopy_MASK);
                   1983:                     break;
                   1984: 
                   1985:                case NotSrcOr:
                   1986:                     maskBitPos_LOOP(NotSrcOr_MASK);
                   1987:                     break;
                   1988: 
                   1989:                case NotSrcXor:
                   1990:                     maskBitPos_LOOP(NotSrcXor_MASK);
                   1991:                     break;
                   1992: 
                   1993:                case SrcAnd:
                   1994:                     maskBitPos_LOOP(SrcAnd_MASK);
                   1995:                     break;
                   1996: 
                   1997:                case SrcAndNotDst:
                   1998:                     maskBitPos_LOOP(SrcAndNotDst_MASK);
                   1999:                     break;
                   2000: 
                   2001:                case NotSrcAndNotDst:
                   2002:                     maskBitPos_LOOP(NotSrcAndNotDst_MASK);
                   2003:                     break;
                   2004: 
                   2005:                case SrcOrNotDst:
                   2006:                     maskBitPos_LOOP(SrcOrNotDst_MASK);
                   2007:                     break;
                   2008: 
                   2009:                case NotSrcOrNotDst:
                   2010:                     maskBitPos_LOOP(NotSrcOrNotDst_MASK);
                   2011:                     break;
                   2012: 
                   2013:                default:
                   2014:                     break;
                   2015:        }
                   2016: }
                   2017: 
                   2018: /*
                   2019:  * This loop copies the tile to the destination only changing those bits
                   2020:  * in the destination that have coorisponding one's in the mask bitmap.
                   2021:  * It takes as arguments 1 of 8 masking tile macros. The general scheme
                   2022:  * is this:
                   2023:  *     Foreach row do
                   2024:  *             Calculate the MASK shifting if necessary.
                   2025:  *             Copy the tile to the first word using the left edge mask and
                   2026:  *             MASK.
                   2027:  *
                   2028:  *             if the MASK is skewed then (2 mask words are needed for one
                   2029:  *                     destination word.)
                   2030:  *                     For each word between the first and last word do
                   2031:  *                             Calculate the MASK.
                   2032:  *                             Copy the tile to the destination word using
                   2033:  *                                     the mask calculated.
                   2034:  *                     endfor
                   2035:  *
                   2036:  *             Calculate the MASK.
                   2037:  *             Copy the tile to the first word using the right edge mask and
                   2038:  *                     the mask calculated.
                   2039:  *
                   2040:  *             else
                   2041:  *                     For each word between the first and last word do
                   2042:  *                             Copy the tile to the destination word using
                   2043:  *                                     the mask.
                   2044:  *                     endfor
                   2045:  *
                   2046:  *                     Copy the tile to the first word using the
                   2047:  *                             right edge mask and the mask.
                   2048:  *             endif
                   2049:  *
                   2050:  *             INCREMENT the tile and destination pointers to point to the
                   2051:  *                     next row.
                   2052:  *     endfor
                   2053:  */
                   2054: #define maskTile_LOOP(MASK_OP) {                                       \
                   2055:        while (--s_info->height) {                                      \
                   2056:                wordnum = s_info->nshorts;                              \
                   2057:                if (s_info->preload_msk) {                              \
                   2058:                        mask = (*MSK << s_info->skew_msk) |             \
                   2059:                               (*PLUS_MSK(msk) >> inv_skew_msk);        \
                   2060:                        INCR_MSK(msk);                                  \
                   2061:                }                                                       \
                   2062:                else {                                                  \
                   2063:                        mask = (*MSK >> inv_skew_msk);                  \
                   2064:                }                                                       \
                   2065:                MASK_OP(*TILE,*DST,s_info->left_mask & mask);           \
                   2066:                if (--wordnum != 0) {                                   \
                   2067:                        INCR_DST(dst);                                  \
                   2068:                        if (s_info->skew_msk & 0xf) {                   \
                   2069:                                while (wordnum-- > 1) {                 \
                   2070:                                        mask = (*MSK << s_info->skew_msk) |\
                   2071:                                               (*PLUS_MSK(msk)>>inv_skew_msk);\
                   2072:                                        MASK_OP(*TILE,*DST,mask);       \
                   2073:                                        INCR_DST(dst); INCR_MSK(msk);   \
                   2074:                                }                                       \
                   2075:                                mask = (*MSK << s_info->skew_msk) |     \
                   2076:                                       (*PLUS_MSK(msk) >> inv_skew_msk);\
                   2077:                                MASK_OP(*TILE,*DST,                     \
                   2078:                                        s_info->right_mask & mask);     \
                   2079:                                INCR_MSK(msk);                          \
                   2080:                        }                                               \
                   2081:                        else {                                          \
                   2082:                                while (wordnum-- > 1) {                 \
                   2083:                                        INCR_MSK(msk);                  \
                   2084:                                        MASK_OP(*TILE,*DST,*MSK);       \
                   2085:                                        INCR_DST(dst);                  \
                   2086:                                }                                       \
                   2087:                                INCR_MSK(msk);                          \
                   2088:                                MASK_OP(*TILE,*DST,s_info->right_mask & *MSK);\
                   2089:                        }                                               \
                   2090:                }                                                       \
                   2091:                INCR_TILE_PTR(tile,last_tile);                          \
                   2092:                dst += s_info->dst.nextline;                            \
                   2093:                msk += s_info->msk.nextline;                            \
                   2094:        }                                                               \
                   2095: }
                   2096: 
                   2097: /*
                   2098:  * Copies a tile to the destination but only changes those bits
                   2099:  * that have corrisponding ones in the mask bitmap given.
                   2100:  */
                   2101: maskTile(s_info)
                   2102: register Blt_sysdata *s_info;
                   2103: {
                   2104:        register unsigned char *dst; /* Register pointers are declared as  */
                   2105:                                     /* unsigned char pointers. This is an */
                   2106:        register unsigned char *msk; /* optimization to get around extra   */
                   2107:                                     /* addressing in the assembler.       */
                   2108:        register unsigned char *tile;/* register pointer to the tile */
                   2109: #if (APA8 || APA8C)
                   2110:        register int src_plus;
                   2111:        register int dst_plus;
                   2112: #endif
                   2113:        register unsigned char *last_tile;/* points to the last word in a tile*/
                   2114:        register int wordnum;        /* number of shorts per scanline */
                   2115:        register int inv_skew_msk;   /* BPW - skew_msk */
                   2116:        register unsigned short mask;/* The local mask produced by shifting
                   2117:                                        *MSK and *PLUS_MASK() */
                   2118: #if (APA8 || APA8C)
                   2119:        src_plus = s_info->src_plus;
                   2120:        dst_plus = s_info->dst_plus;
                   2121: #endif
                   2122:        dst = (unsigned char *)s_info->dst.data;
                   2123:        msk = (unsigned char *)s_info->msk.data;
                   2124:        tile = (unsigned char *)&s_info->tile_ptr[
                   2125:                                            MOD_BPW(s_info->dst.rect.origin_y)];
                   2126:        last_tile = (unsigned char *)(&s_info->tile_ptr[15]);
                   2127: 
                   2128: 
                   2129:        inv_skew_msk = BPW - s_info->skew_msk;
                   2130: 
                   2131:        DEBUGF(blt_debug,
                   2132:                printf("Enter maskTile%d,%d %d %s %d\r\n",s_info->skew_msk,
                   2133:                        inv_skew_msk,s_info->preload_msk,
                   2134:                        ((s_info->tile_ptr[0] == 0xffff &&
                   2135:                         s_info->tile_ptr[5] == 0xffff) ?
                   2136:                        "black" : "not black"),s_info->rule));
                   2137: 
                   2138:        /*
                   2139:         * Compiler optimization: a pre-decrement in a while loop saves a test
                   2140:         * in assembly language for every iteration.
                   2141:         */
                   2142:        s_info->height += 1;
                   2143:        switch (s_info->rule) {
                   2144:                case DstClear:
                   2145:                case DstSet:
                   2146:                case TileDstClear:
                   2147:                case TileDstSet:
                   2148:                case TileCopy:
                   2149:                     maskTile_LOOP(TileCopy_MASK);
                   2150:                     break;
                   2151: 
                   2152:                case TileOr:
                   2153:                     maskTile_LOOP(TileOr_MASK);
                   2154:                     break;
                   2155: 
                   2156:                case TileXor:
                   2157:                     maskTile_LOOP(TileXor_MASK);
                   2158:                     break;
                   2159: 
                   2160:                case NotTileAnd:
                   2161:                     maskTile_LOOP(NotTileAnd_MASK);
                   2162:                     break;
                   2163: 
                   2164:                case NotTileCopy:
                   2165:                     maskTile_LOOP(NotTileCopy_MASK);
                   2166:                     break;
                   2167: 
                   2168:                case NotTileOr:
                   2169:                     maskTile_LOOP(NotTileOr_MASK);
                   2170:                     break;
                   2171: 
                   2172:                case NotTileXor:
                   2173:                     maskTile_LOOP(NotTileXor_MASK);
                   2174:                     break;
                   2175: 
                   2176:                case TileAnd:
                   2177:                     maskTile_LOOP(TileAnd_MASK);
                   2178:                     break;
                   2179: 
                   2180:                case TileNotDstCopy:
                   2181:                case NotDstCopy:
                   2182:                     maskTile_LOOP(NotDstCopy_MASK);
                   2183:                     break;
                   2184: 
                   2185:                case TileAndNotDst:
                   2186:                     maskTile_LOOP(TileAndNotDst_MASK);
                   2187:                     break;
                   2188: 
                   2189:                case NotTileAndNotDst:
                   2190:                     maskTile_LOOP(NotTileAndNotDst_MASK);
                   2191:                     break;
                   2192: 
                   2193:                case TileOrNotDst:
                   2194:                     maskTile_LOOP(TileOrNotDst_MASK);
                   2195:                     break;
                   2196: 
                   2197:                case NotTileOrNotDst:
                   2198:                     maskTile_LOOP(NotTileOrNotDst_MASK);
                   2199:                     break;
                   2200: 
                   2201:                default:
                   2202:                     break;
                   2203:        }
                   2204: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.