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

1.1       root        1: #ifndef lint
                      2: static char *rcsid_bitblt_c = "$Header: bitblt.c,v 10.1 86/11/19 10:50:19 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 November 21, 1985 and
                     18:  * "enhanced" a number of times since.
                     19:  *
                     20:  * ABOUT BITBLT.C:  This program and related 'C' files (bitblt_int.h,
                     21:  * bitblt_subr.c, bitblt_apa16.c, bitblt_apa16.h) were originally written to go
                     22:  * into the Unix 4.2 kernel as a "bitblt" driver.  Later we were able
                     23:  * to put in some ifdef's and use it for Smalltalk and X.  Whatever
                     24:  * version you have, there may be some strange ifdef's that may not
                     25:  * make any sense at all.  We tried to remove all ifdef's not relevant
                     26:  * to the system being compiled but then no one's perfect.
                     27:  * Also some strange things are done to support the APA8, APA8C and the AED
                     28:  * (viking).  You will encounter ifdef's for all these things.  if you define
                     29:  * all the screens (-DAED -DAPA8 -DAPA16 ... on the compile line) the bitblt
                     30:  * routine will work on every screen.
                     31:  */
                     32: 
                     33: #include "bitblt_int.h"
                     34: 
                     35: #ifdef USE_APA16_HDWR
                     36: #include "bitblt_apa16.h"
                     37: #endif
                     38: 
                     39: #ifdef BLT_DEBUG
                     40: int blt_debug = 0;
                     41: #endif
                     42: 
                     43: #define MSK_SKEW 0x01
                     44: #define SRC_SKEW 0x02
                     45: 
                     46: Blt_sysdata blt_info;          /* internal variables used by bitblt() */
                     47: Blt_Rectangle changed_rect;    /* describes the area changed by the bltter */
                     48: 
                     49: /*
                     50:  * Array of short masks used to compute the masks to mask out the edges
                     51:  * of the destination that should not be affected.  A one means that bit
                     52:  * in the destination can be changed.  The values in leftMasks are set up 
                     53:  * to be used with the left edge and the values in rightMasks are to be used
                     54:  * in right edge. 
                     55:  */
                     56: static unsigned short leftMasks[] = {
                     57:        0xffff,0x7fff,0x3fff,0x1fff,0x0fff,0x07ff,0x03ff,0x01ff,
                     58:        0x00ff,0x007f,0x003f,0x001f,0x000f,0x0007,0x0003,0x0001,
                     59:        0x0000
                     60: };
                     61: 
                     62: static unsigned short rightMasks[] = {
                     63:        0xffff,0x8000,0xc000,0xe000,0xf000,0xf800,0xfc00,0xfe00,
                     64:        0xff00,0xff80,0xffc0,0xffe0,0xfff0,0xfff8,0xfffc,0xfffe,
                     65:        0x0000
                     66: };
                     67: 
                     68: static Blt_Tile white = {
                     69:        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
                     70:        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
                     71: };
                     72: static Blt_Tile black = {
                     73:        0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
                     74:        0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
                     75: };
                     76:  
                     77: /*
                     78:  * Defines used to indicate whether 1 or 2 source words are needed to make
                     79:  * the first destination word.
                     80:  * NOTE: Changing the value of MUST_PRIME may have bad side effects because
                     81:  *      the variable "preload_src" is added to something in calculateOffsets.
                     82:  *      THIS IS SEMI-HOOKY BUT IT WORKS.
                     83:  */
                     84: #define MUST_PRIME 1
                     85: #define DONT_PRIME 0
                     86: 
                     87: #define SAVE_LOCATOR() {                                               \
                     88:        if (blt_cur_screen.cursortype & SOFT_CURSOR) {                  \
                     89:                saved_loc = 0;                                          \
                     90:                if (IS_SCREEN(u_info->dst_bitmap)) {                    \
                     91:                        if (sys_info->is_src && IS_SCREEN(u_info->src_bitmap)){\
                     92:                                saved_loc = 1;                          \
                     93:                                save_cursor(MIN(sys_info->dst.rect.origin_x,  \
                     94:                                               sys_info->src.rect.origin_x),  \
                     95:                                            MIN(sys_info->dst.rect.origin_y,  \
                     96:                                               sys_info->src.rect.origin_y),  \
                     97:                                            MAX(sys_info->dst.rect.corner_x,  \
                     98:                                               sys_info->src.rect.corner_x)+1,\
                     99:                                            MAX(sys_info->dst.rect.corner_y,  \
                    100:                                               sys_info->src.rect.corner_y)+1);\
                    101:                        }                                               \
                    102:                        else {                                          \
                    103:                                saved_loc = 1;                          \
                    104:                                save_cursor(sys_info->dst.rect.origin_x,     \
                    105:                                            sys_info->dst.rect.origin_y,     \
                    106:                                            sys_info->dst.rect.corner_x + 1, \
                    107:                                            sys_info->dst.rect.corner_y + 1);\
                    108:                        }                                               \
                    109:                }                                                       \
                    110:                else if (sys_info->is_src && IS_SCREEN(u_info->src_bitmap)) { \
                    111:                        saved_loc = 1;                                  \
                    112:                        save_cursor(sys_info->src.rect.origin_x,        \
                    113:                                    sys_info->src.rect.origin_y,        \
                    114:                                    sys_info->src.rect.corner_x + 1,    \
                    115:                                    sys_info->src.rect.corner_y + 1);   \
                    116:                }                                                       \
                    117:        }                                                               \
                    118: }
                    119: 
                    120: #define RESTORE_LOCATOR() {                                            \
                    121:        if ((blt_cur_screen.cursortype & SOFT_CURSOR) && saved_loc) {   \
                    122:                restore_cursor();                                       \
                    123:        }                                                               \
                    124: }
                    125: 
                    126: /*
                    127:  * Macros to calculate the skew and preload flag depending on the direction
                    128:  * of the blt.
                    129:  */
                    130: #define computeSkewPos(SI) {                                   \
                    131:        if ((MOD_BPW(SI->dst.rect.origin_x))<(MOD_BPW(SI->src.rect.origin_x))){\
                    132:                SI->skew_src = MOD_BPW(SI->src.rect.origin_x) - \
                    133:                               MOD_BPW(SI->dst.rect.origin_x);  \
                    134:                SI->preload_src = MUST_PRIME;                   \
                    135:        }                                                       \
                    136:        else {                                                  \
                    137:                SI->skew_src = BPW - (MOD_BPW(SI->dst.rect.origin_x) -  \
                    138:                               MOD_BPW(SI->src.rect.origin_x));         \
                    139:                 SI->preload_src = DONT_PRIME;                  \
                    140:        }                                                       \
                    141: }
                    142: 
                    143: #define computeSkewMskPos(SI) {                                                \
                    144:        if ((MOD_BPW(SI->dst.rect.origin_x))<(MOD_BPW(SI->msk.rect.origin_x))){\
                    145:                SI->skew_msk = MOD_BPW(SI->msk.rect.origin_x) -         \
                    146:                               MOD_BPW(SI->dst.rect.origin_x);          \
                    147:                SI->preload_msk = MUST_PRIME;                           \
                    148:        }                                                               \
                    149:        else {                                                          \
                    150:                SI->skew_msk = BPW - (MOD_BPW(SI->dst.rect.origin_x) -  \
                    151:                               MOD_BPW(SI->msk.rect.origin_x));         \
                    152:                 SI->preload_msk = DONT_PRIME;                          \
                    153:        }                                                               \
                    154: }
                    155: 
                    156: #define computeSkewNeg(SI) {                                           \
                    157:        if ((MOD_BPW(SI->dst.rect.corner_x))>(MOD_BPW(SI->src.rect.corner_x))){\
                    158:                SI->skew_src = MOD_BPW(SI->dst.rect.corner_x) -         \
                    159:                               MOD_BPW(SI->src.rect.corner_x);          \
                    160:                    SI->preload_src = MUST_PRIME;                       \
                    161:        }                                                               \
                    162:        else {                                                          \
                    163:                SI->skew_src = BPW - (MOD_BPW(SI->src.rect.corner_x) -  \
                    164:                               MOD_BPW(SI->dst.rect.corner_x));         \
                    165:                SI->preload_src = DONT_PRIME;                           \
                    166:        }                                                               \
                    167: }
                    168: 
                    169: #define computeSkewMskNeg(SI) {                                                \
                    170:        if ((MOD_BPW(SI->dst.rect.corner_x))>(MOD_BPW(SI->msk.rect.corner_x))){\
                    171:                SI->skew_msk = MOD_BPW(SI->dst.rect.corner_x) -         \
                    172:                               MOD_BPW(SI->msk.rect.corner_x);          \
                    173:                SI->preload_msk = MUST_PRIME;                           \
                    174:        }                                                               \
                    175:        else {                                                          \
                    176:                SI->skew_msk = BPW - (MOD_BPW(SI->msk.rect.corner_x) -  \
                    177:                               MOD_BPW(SI->dst.rect.corner_x));         \
                    178:                SI->preload_msk = DONT_PRIME;                           \
                    179:        }                                                               \
                    180: }
                    181: 
                    182: /*
                    183:  * Make a mask for the first and last destination word in each scanline.
                    184:  * 1's mean those bits can be changed in the destination.
                    185:  * Combine the masks if only one destination word is effected and set
                    186:  * BOTH masks equal to it so as not to screw up copyBitNeg. 
                    187:  *
                    188:  * NOTE: The +1 with dst.rect.corner_x. This is because dst.rect.corner_x was
                    189:  *       set to the rectangle size -1. (see blt_setup())
                    190:  */
                    191: #define computeMasks(SI) {                                             \
                    192:        if (SI->nshorts == 1) {                                         \
                    193:                SI->right_mask = SI->left_mask =                        \
                    194:                                 leftMasks[MOD_BPW(SI->dst.rect.origin_x)] &\
                    195:                                 rightMasks[MOD_BPW(SI->dst.rect.corner_x+1)];\
                    196:        }                                                               \
                    197:        else {                                                          \
                    198:                SI->left_mask = leftMasks[MOD_BPW(SI->dst.rect.origin_x)];\
                    199:                SI->right_mask = rightMasks[MOD_BPW(SI->dst.rect.corner_x+1)];\
                    200:        }                                                               \
                    201: }
                    202: 
                    203: /*
                    204:  * CheckOverlap checks for overlapping source and destination. 
                    205:  * (See checkOverlap in Smalltalk-80)  It set SI->top_to_bot to
                    206:  * non-zero if we must copy from bottom to top, right to left
                    207:  * instead of top to bottom, left to right.
                    208:  *
                    209:  * NOTE: The +1 for both src.rect.corner_y and src.rect.corner_x this is because
                    210:  *       these local variables have "closed" corners. (See blt_setup())
                    211:  *
                    212:  * IF the destination and source have the same bitmap
                    213:  *                        AND 
                    214:  *           TEST AREA 1  OR  TEST AREA 2
                    215:  * THEN
                    216:  *             (We must copy from right to left bottom to top)
                    217:  *
                    218:  *    TEST AREA 1:  The destination top is GREATER than or EQUAL to the
                    219:  *                  source top and its less than the source bottom
                    220:  *            (src.rect.origin_y <= dst.rect.origin_y < src.rect.corner_y+1) AND
                    221:  *                 the destination left is greater than or equal to
                    222:  *                  the source left and its less than the source right.
                    223:  *           (src.rect.origin_x <= dst.rect.origin_x < src.rect.corner_x+1)
                    224:  *                 IN OTHER WORDS, the top left corner of the destination
                    225:  *                 is in the source area.
                    226:  *
                    227:  *    TEST AREA 2:  The destination top is GREATER than the source top 
                    228:  *                  and its less than the source bottom:
                    229:  *                 (src.rect.origin_y < dst.rect.origin_y < src.rect.corner_y+1)
                    230:  *                  AND the source left is greater than the destination left
                    231:  *                  and its less than the destination right.
                    232:  *                 (dst.rect.origin_x < src.rect.origin_x < dst.rect.corner_x+1)
                    233:  *                 IN OTHER WORDS, the top horizontal line of the destination
                    234:  *                 intersects the left vertical line of the source, causing
                    235:  *                 the right top corner of the destination to be in the
                    236:  *                 source.
                    237:  *
                    238:  *                              src.rect.origin_x
                    239:  *                              src.rect.origin_y +----------------------------
                    240:  *   src.rect.origin_y - 1  -----------------------|
                    241:  *                                                 |
                    242:  *                           TEST AREA 2          |    TEST AREA 1
                    243:  *                                                 |
                    244:  *                                                 |
                    245:  *    src.rect.corner_y+1   ------------------------------------------------
                    246:  */
                    247: #define checkOverlap(UI,SI) \
                    248:        SI->top_to_bot = ((UI->src_bitmap.base == UI->dst_bitmap.base)  \
                    249:                  && (((SI->src.rect.origin_y <= SI->dst.rect.origin_y &&\
                    250:                        SI->dst.rect.origin_y < (SI->src.rect.corner_y+1))\
                    251:                  && (SI->src.rect.origin_x <= SI->dst.rect.origin_x && \
                    252:                        SI->dst.rect.origin_x < (SI->src.rect.corner_x+1)))\
                    253:                  || ((SI->src.rect.origin_y < SI->dst.rect.origin_y && \
                    254:                        SI->dst.rect.origin_y < (SI->src.rect.corner_y+1))\
                    255:                  && (SI->dst.rect.origin_x < SI->src.rect.origin_x &&  \
                    256:                        SI->src.rect.origin_x < (SI->dst.rect.corner_x+1)))))
                    257: 
                    258: /*
                    259:  * CalculateOffsetDst sets up pointers to a word in the destination and
                    260:  * possibly to the mask bitmap using the dst_x,dst_y points given.
                    261:  * It calculates the increment for each pointer from the end of one 
                    262:  * rectangle scanline to the beginning of the next.
                    263:  */
                    264: calculateOffsetDst(u_info,s_info,dst_x,dst_y)
                    265: register Blt_userdata *u_info;
                    266: register Blt_sysdata *s_info;
                    267: short  dst_x,dst_y; /* top,left or bottom,right */
                    268: {
                    269:        /*
                    270:         * Set up the destination pointer and increment.
                    271:         * NOTE that (dst_y * u_info->dst_bitmap.nshorts) + DIV_BPW(dst_x)
                    272:         * gives the WORD offset to base.  Since we need the byte address
                    273:         * this quantity must be multiplied by 2 (MUL_2).
                    274:         *
                    275:         * Set up destination to point to a word offset from the base address.
                    276:         */
                    277: #if (APA8 || APA8C)
                    278:        if (IS_APA8orAPA8C(u_info->dst_bitmap)) {
                    279:                s_info->dst_plus = 4;
                    280:                s_info->dst.data = (unsigned short *)(
                    281:                                   (long)u_info->dst_bitmap.base +
                    282:                                   MUL_4((dst_y *
                    283:                                        u_info->dst_bitmap.nshorts) +
                    284:                                        DIV_BPW(dst_x)));
                    285:                s_info->dst.nextline = MUL_4(u_info->dst_bitmap.nshorts -
                    286:                                             s_info->nshorts + 1);
                    287:        }
                    288:        else {
                    289:                s_info->dst_plus = 2;
                    290:                s_info->dst.data = (unsigned short *)(
                    291:                                   (long)u_info->dst_bitmap.base +
                    292:                                   MUL_2((dst_y * u_info->dst_bitmap.nshorts) +
                    293:                                         DIV_BPW(dst_x)));
                    294:                s_info->dst.nextline = MUL_2(u_info->dst_bitmap.nshorts -
                    295:                                             s_info->nshorts + 1);
                    296:        }
                    297: #else no APA8 stuff
                    298:        s_info->dst.data = (unsigned short *)((long)u_info->dst_bitmap.base +
                    299:                            MUL_2((dst_y * u_info->dst_bitmap.nshorts) +
                    300:                                  DIV_BPW(dst_x)));
                    301: 
                    302:        /*
                    303:         * NOTE: This increment shows the increment for the number of BYTES.
                    304:         */
                    305:        s_info->dst.nextline = MUL_2(u_info->dst_bitmap.nshorts -
                    306:                                     s_info->nshorts + 1);
                    307: #endif APA8
                    308: 
                    309:        /*
                    310:         * Set up the masking bitmap (if given) to point to a word
                    311:         * offset from the base address.
                    312:         */
                    313:        if (u_info->blt_flags & BLT_MASKON) {
                    314:                /*
                    315:                 * Calculate the shift amount (skew) that is needed
                    316:                 * to align a word in the mask bitmap with a word
                    317:                 * in the destination.
                    318:                 */
                    319:                if (s_info->top_to_bot) {
                    320:                        computeSkewMskNeg(s_info);
                    321: 
                    322:                        /*
                    323:                         * Calculate the mask pointer.
                    324:                         */
                    325:                        s_info->msk.data = (unsigned short *)(
                    326:                                           (long)(u_info->msk_bitmap.base) +
                    327:                                           MUL_2((s_info->msk.rect.corner_y *
                    328:                                                 u_info->msk_bitmap.nshorts) +
                    329:                                           DIV_BPW(s_info->msk.rect.corner_x)));
                    330:                }
                    331:                else {
                    332:                        computeSkewMskPos(s_info);
                    333: 
                    334:                        /*
                    335:                         * Calculate the mask pointer.
                    336:                         */
                    337:                        s_info->msk.data = (unsigned short *)(
                    338:                                           (long)(u_info->msk_bitmap.base) + 
                    339:                                           MUL_2((s_info->msk.rect.origin_y *
                    340:                                                  u_info->msk_bitmap.nshorts) +
                    341:                                           DIV_BPW(s_info->msk.rect.origin_x)));
                    342:                }
                    343: 
                    344:                /*
                    345:                 * Calculate the mask increment.
                    346:                 */
                    347:                s_info->msk.nextline = MUL_2( u_info->msk_bitmap.nshorts -
                    348:                                             (s_info->nshorts +
                    349:                                              s_info->preload_msk) + 1);
                    350:        }
                    351:        else {
                    352:                s_info->msk.data = (unsigned short *)0;
                    353:                s_info->msk.nextline = 0;
                    354:        }
                    355: }
                    356: 
                    357: /*
                    358:  * CalculateOffsetSrcNeg sets up pointers to the last word in the
                    359:  * source.  It also determines if "priming" must be done.
                    360:  * (i.e. 2 words of source are needed for the first word of the destination.)
                    361:  * When going from right to left this happens when for example you have 
                    362:  * 3 bits in the source (at the end of the line) (0-2) and 5 bits to fill
                    363:  * in the destination (0-4).  One must take those 3 bits from the source
                    364:  * and put them in 2-4 in the destination and increment the source.
                    365:  *
                    366:  * It then calculates the increment for the source.
                    367:  */
                    368: 
                    369: #if (APA8 || APA8C)
                    370: #define calculateOffsetSrcNeg(UI,SI) {                                 \
                    371:        if (IS_APA8orAPA8C(UI->src_bitmap)) {                           \
                    372:                SI->src_plus = 4;                                       \
                    373:                SI->src.data = (unsigned short *)((long)(UI->src_bitmap.base) +\
                    374:                             MUL_4((SI->src.rect.corner_y *     \
                    375:                                          UI->src_bitmap.nshorts) +     \
                    376:                                         DIV_BPW(SI->src.rect.corner_x)));\
                    377:                SI->src.nextline = MUL_4(UI->src_bitmap.nshorts -       \
                    378:                                         (SI->nshorts+SI->preload_src) + 1);\
                    379:        }                                                               \
                    380:        else {                                                          \
                    381:                SI->src_plus = 2;                                       \
                    382:                SI->src.data = (unsigned short *)((long)(UI->src_bitmap.base) +\
                    383:                            MUL_2((SI->src.rect.corner_y *              \
                    384:                                   UI->src_bitmap.nshorts) +            \
                    385:                                   DIV_BPW(SI->src.rect.corner_x)));    \
                    386:                SI->src.nextline = MUL_2(UI->src_bitmap.nshorts -       \
                    387:                                   (SI->nshorts + SI->preload_src) + 1);\
                    388:        }                                                               \
                    389: }
                    390: #else no APA8 stuff
                    391: #define calculateOffsetSrcNeg(UI,SI) {                                 \
                    392:        SI->src.data = (unsigned short *)((long)(UI->src_bitmap.base) + \
                    393:                     MUL_2((SI->src.rect.corner_y * UI->src_bitmap.nshorts) +\
                    394:                           DIV_BPW(SI->src.rect.corner_x)));            \
                    395:        SI->src.nextline = MUL_2(UI->src_bitmap.nshorts -               \
                    396:                           (SI->nshorts+SI->preload_src) + 1);          \
                    397: }
                    398: #endif
                    399: 
                    400: /*
                    401:  * CalculateOffsetSrcPos sets up pointers to the first word in the
                    402:  * source.  It also determines if "priming" must be done. (i.e. 2 words 
                    403:  * of source are needed for the first word of the destination.)
                    404:  * When going from left to right this happens when for example you have 
                    405:  * 3 bits in the source (13-15) and 5 bits to fill in the destination (11-15).
                    406:  * One must take those 3 bits from the source and put them in 11-13
                    407:  * and then increment the source.
                    408:  *
                    409:  * It then calculates the increment for the source.
                    410:  */
                    411: #if (APA8 || APA8C)
                    412: #define calculateOffsetSrcPos(UI,SI) {                                 \
                    413:        if (IS_APA8orAPA8C(UI->src_bitmap)) {                           \
                    414:                SI->src_plus = 4;                                       \
                    415:                SI->src.data = (unsigned short *)((long)UI->src_bitmap.base +  \
                    416:                               MUL_4((SI->src.rect.origin_y *           \
                    417:                                      UI->src_bitmap.nshorts) + \
                    418:                                      DIV_BPW(SI->src.rect.origin_x)));\
                    419:                SI->src.nextline = MUL_4(UI->src_bitmap.nshorts -       \
                    420:                                         (SI->nshorts + SI->preload_src) + 1);\
                    421:        }                                                               \
                    422:        else {                                                          \
                    423:                SI->src_plus = 2;                                       \
                    424:                SI->src.data = (unsigned short *)((long)UI->src_bitmap.base +\
                    425:                                MUL_2((SI->src.rect.origin_y *          \
                    426:                                      UI->src_bitmap.nshorts) +         \
                    427:                                      DIV_BPW(SI->src.rect.origin_x))); \
                    428:                SI->src.nextline = MUL_2(UI->src_bitmap.nshorts -       \
                    429:                                   (SI->nshorts+SI->preload_src) + 1);  \
                    430:        }                                                               \
                    431: }
                    432: #else no APA8 stuff
                    433: #define calculateOffsetSrcPos(UI,SI) {                                 \
                    434:        SI->src.data = (unsigned short *)((long)UI->src_bitmap.base +   \
                    435:                     MUL_2((SI->src.rect.origin_y * UI->src_bitmap.nshorts) +\
                    436:                           DIV_BPW(SI->src.rect.origin_x)));            \
                    437:        SI->src.nextline = MUL_2(UI->src_bitmap.nshorts -               \
                    438:                           (SI->nshorts+SI->preload_src) + 1);          \
                    439: }
                    440: #endif
                    441: 
                    442: /*
                    443:  * Set up destination offsets.
                    444:  */
                    445: #define calculateOffsetDstNeg(UI,SI) calculateOffsetDst(UI,SI,         \
                    446:                                                        SI->dst.rect.corner_x,\
                    447:                                                        SI->dst.rect.corner_y)
                    448: #define calculateOffsetDstPos(UI,SI) calculateOffsetDst(UI,SI,         \
                    449:                                                        SI->dst.rect.origin_x, \
                    450:                                                        SI->dst.rect.origin_y)
                    451: 
                    452: /*
                    453:  * If a rule specifies the type of tile to be used then set tile_ptr.
                    454:  * If tile_ptr has already been set then don't change it.
                    455:  */
                    456: #define calculateOffsetTile(UI,SI) {                           \
                    457:        if (SI->rule == DstClear || SI->rule == TileDstClear) { \
                    458:                SI->tile_ptr = &white.tile[0];                  \
                    459:        }                                                       \
                    460:        else if (SI->rule == DstSet || SI->rule == TileDstSet   \
                    461:                || SI->rule == NotDstCopy) {                    \
                    462:                SI->tile_ptr = &black.tile[0];                  \
                    463:        }                                                       \
                    464:        else if (SI->tile_ptr == (unsigned short *)0){          \
                    465:                SI->tile_ptr = (unsigned short *)UI->tile_ptr;  \
                    466:        }                                                       \
                    467: }
                    468: 
                    469: /*
                    470:  * Do the bit block transfer using the information in u_info. Return -1 if
                    471:  * bad pointers are given, 0 if the area clipped down to a null blt and 1 if
                    472:  * the "bitblt" was done.
                    473:  */
                    474: bitblt(u_info)
                    475: register Blt_userdata *u_info;
                    476: {
                    477:        register Blt_sysdata *sys_info = &blt_info;
                    478:        register tmp;
                    479:        register saved_loc;
                    480:        int blt_status;
                    481: 
                    482:        DEBUGF((blt_debug > 1),printf("Enter bitblt.\r\n"));
                    483: 
                    484:        /*
                    485:         * Set up to do this blt.  blt_setup does clipping if necessary, sets
                    486:         * up either the source or tile (depending on the combination rule
                    487:         * being used) and sets the width and height of the blt.  It returns
                    488:         * zero if the blt is to be done.
                    489:         */
                    490:        if ((blt_status = blt_setup(u_info,sys_info)) != 1) {
                    491:                /*
                    492:                 * Bad pointers or the combination rule was such that nothing
                    493:                 * has to be done.
                    494:                 */
                    495:                return(blt_status);
                    496:        }
                    497:        else if (sys_info->width <= 0 || sys_info->height <= 0) {
                    498:                /*
                    499:                 * Nothing to do.
                    500:                 */
                    501:                return(0);
                    502:        }
                    503: 
                    504: #ifdef USE_APA16_HDWR
                    505:        /*
                    506:         * Are we using hardware??  This is for debugging purposes, we
                    507:         * know the software works so to test the hardware stuff we have this
                    508:         * flag in blt_flags.  However if we are using a mask bitmap then
                    509:         * the hardware can not be used.
                    510:         */
                    511:        if ((u_info->blt_flags & BLT_MASKON) == 0) {
                    512:                register int ret_flag;  /* Hardware return flag */
                    513: 
                    514:                /*
                    515:                 * One can only use the hardware assist if the destination
                    516:                 * bitmap is the screen.
                    517:                 */
                    518:                ret_flag = 1;
                    519:                if (IS_APA16(u_info->dst_bitmap)) {
                    520:                        extern unsigned short execute_cmd[];
                    521: 
                    522:                        /*
                    523:                         * Check and see if there is a hardware function
                    524:                         * (execute command) for this rule.
                    525:                         */
                    526:                        if (execute_cmd[sys_info->rule]) {
                    527:                                if (sys_info->is_src) {
                    528:                                        if (IS_APA16(u_info->src_bitmap)) {
                    529:                                                /*
                    530:                                                 * Pass in the pointers to
                    531:                                                 * the screen because if they
                    532:                                                 * are greater than the first
                    533:                                                 * byte address in the APA16
                    534:                                                 * buffer things will not
                    535:                                                 * work.
                    536:                                                 */
                    537:                                                sys_info->dst.data =
                    538:                                                        u_info->dst_bitmap.base;
                    539:                                                sys_info->src.data =
                    540:                                                        u_info->src_bitmap.base;
                    541:                                                ret_flag = apa16_StoS(sys_info);
                    542:                                        }
                    543:                                        else {
                    544:                                                /*
                    545:                                                 * The APA-16 does memory to
                    546:                                                 * screen stuff.  But first
                    547:                                                 * The source address and
                    548:                                                 * and the source "nextline"
                    549:                                                 * field must also be
                    550:                                                 * calculated.
                    551:                                                 *
                    552:                                                 * NOT IMPLEMENTED YET.
                    553:                                                 *
                    554:                                                 * computeSkewPos(sys_info);
                    555:                                                 * calculateOffsetSrcPos(u_info,
                    556:                                                 *                    sys_info);
                    557:                                                 * ret_flag =
                    558:                                                 *         apa16_MtoS(sys_info);
                    559:                                                 */
                    560:                                        }
                    561:                                }
                    562:                                else {
                    563:                                        /*
                    564:                                         * The tile ptr has not been set up yet.
                    565:                                         */
                    566:                                        sys_info->tile_ptr = (unsigned short *)
                    567:                                                             u_info->tile_ptr;
                    568:                                        ret_flag = apa16_copyTile(sys_info);
                    569:                                }
                    570: 
                    571:                                /*
                    572:                                 * Check the status of the hardware blt, if
                    573:                                 * its 0 then everything was done successfully.
                    574:                                 */
                    575:                                if (ret_flag == 0) {
                    576: 
                    577:                                        /*
                    578:                                         * Indicate that a blt was done.
                    579:                                         */
                    580:                                        return(1);
                    581:                                }
                    582:                        }
                    583:                }
                    584:        }
                    585: 
                    586:        /*
                    587:         * Regardless of the hardware flag, if we get here it means
                    588:         * that we are going to use the software to blt.  If the screen
                    589:         * is to be changed then we must wait for the rasterop engine to finish
                    590:         * with the screen if it is still using the screen.
                    591:         */
                    592:        if (*QUE_COUNT_R != 0) {
                    593:                if (IS_APA16(u_info->dst_bitmap) || 
                    594:                    (IS_APA16(u_info->src_bitmap))) {
                    595:                        WAIT_QUE(tmp,0);
                    596:                }
                    597:        }
                    598: 
                    599: #endif USE_APA16_HDWR
                    600: 
                    601: #ifdef AED
                    602:        /*  
                    603:         * If this is a screen to screen blt on the AED have the microcode
                    604:         * make the screen changes while the bltter alters the 
                    605:         * offscreen bitmap.
                    606:         */ 
                    607: 
                    608:        if (IS_AED(u_info->src_bitmap) && IS_AED(u_info->dst_bitmap) &&
                    609:            (u_info->blt_flags & BLT_ECHO)) {
                    610:                aed_screen_copy(sys_info->src.rect.origin_x,
                    611:                                 sys_info->src.rect.origin_y,
                    612:                                 sys_info->dst.rect.origin_x,
                    613:                                 sys_info->dst.rect.origin_y,
                    614:                                 (short) sys_info->width,
                    615:                                 (short) sys_info->height,
                    616:                                 sys_info->rule);
                    617:                blt_status = 0;
                    618:        }
                    619: #endif AED
                    620: 
                    621:        /*
                    622:         * Remove the locator from the screen if it is a software locator that
                    623:         * is actually in (on) the source or destination bitmap.  Hardware
                    624:         * locators (as in the APA-16) are not removed.
                    625:         */
                    626:        SAVE_LOCATOR();
                    627: 
                    628:        /*
                    629:         * Calculate the edge masks for the destination. (See computeMasks
                    630:         * in Smalltalk-80)
                    631:         */
                    632:        computeMasks(sys_info);
                    633: 
                    634:        /*
                    635:         * If the source is to be used then things will be done differently
                    636:         * than if a tile is used.
                    637:         */
                    638:        if (sys_info->is_src) {
                    639:                /*
                    640:                 * Check for overlapping source and destination. (See
                    641:                 * checkOverlap in Smalltalk-80)  Sets sys_info->top_to_bot
                    642:                 * non-zero if we must copy from bottom to top, right to
                    643:                 * left instead of top to bottom, left to right.
                    644:                 */
                    645:                checkOverlap(u_info,sys_info);
                    646: 
                    647:                if (sys_info->top_to_bot) {
                    648:                        /*
                    649:                         * Calculate the shift amount (skew) that is needed
                    650:                         * to align a word in the source with a word in the
                    651:                         * destination.
                    652:                         */
                    653:                        computeSkewNeg(sys_info);
                    654: 
                    655:                        /*
                    656:                         * Set up pointers to the source, destination 
                    657:                         * and possibly to the mask bitmap. Also set up
                    658:                         * shift amounts (skews) for the mask bitmap if needed.
                    659:                         * Calculate the increment for each pointer from
                    660:                         * the end of one rectangle scanline to the beginning
                    661:                         * of the next.
                    662:                         */
                    663:                        calculateOffsetSrcNeg(u_info,sys_info);
                    664:                        calculateOffsetDstNeg(u_info,sys_info);
                    665: 
                    666:                        /*
                    667:                         * Do the blt from bottom to top, right to left!!
                    668:                         */
                    669:                        if (u_info->blt_flags & BLT_MASKON) {
                    670:                                maskBitNeg(sys_info);
                    671:                        }
                    672:                        else {
                    673:                                /*
                    674:                                 * Just copy from source to destination
                    675:                                 * going bottom to top, right to left.
                    676:                                 * No mask bitmap to worry about.
                    677:                                 */
                    678:                                copyBitNeg(sys_info);
                    679:                        }
                    680:                }
                    681:                else {
                    682:                        /*
                    683:                         * Calculate the shift amount (skew) that is needed
                    684:                         * to align a word in the source with a word in the
                    685:                         * destination.
                    686:                         */
                    687:                        computeSkewPos(sys_info);
                    688: 
                    689:                        /*
                    690:                         * Set up pointers to the source, destination 
                    691:                         * and possibly to the mask bitmap.
                    692:                         * Also set up shift amounts (skews) for the mask
                    693:                         * bitmap if needed.  Calculate the increment for
                    694:                         * each pointer from the end of one rectangle
                    695:                         * scanline to the beginning of the next.
                    696:                         */
                    697:                        calculateOffsetSrcPos(u_info,sys_info);
                    698:                        calculateOffsetDstPos(u_info,sys_info);
                    699: 
                    700:                        /*
                    701:                         * Do the blt from top to bottom, left to right!!
                    702:                         */
                    703:                        if (u_info->blt_flags & BLT_MASKON) {
                    704:                                /*
                    705:                                 * Copy from source to destination going
                    706:                                 * top to bottom, left to right. Use the
                    707:                                 * mask bitmap.
                    708:                                 */
                    709:                                maskBitPos(sys_info);
                    710:                        }
                    711:                        else {
                    712:                                /*
                    713:                                 * Just copy from source to destination
                    714:                                 * going top to bottom, left to right.
                    715:                                 */
                    716:                                if (sys_info->nshorts < 3) {
                    717:                                        /*
                    718:                                         * Optimize this very important routine
                    719:                                         * for one and two shorts in the dst
                    720:                                         * changed.
                    721:                                         */
                    722:                                        smallcopyBitPos(sys_info);
                    723:                                }
                    724:                                else {
                    725:                                        copyBitPos(sys_info);
                    726:                                }
                    727:                        }
                    728:                }
                    729:        }
                    730:        else { 
                    731:                /*
                    732:                 * We have a TILE rule.
                    733:                 */
                    734:                sys_info->top_to_bot = 0;
                    735: 
                    736:                /*
                    737:                 * Set up pointers to the tile and destination and possibly
                    738:                 * to the mask bitmap.  Calculate the increment for
                    739:                 * each pointer from the end of one rectangle scanline to
                    740:                 * the beginning of the next.
                    741:                 * NOTE: The pointer to the tile may have been set in
                    742:                 *       blt_setup.
                    743:                 */
                    744:                calculateOffsetTile(u_info,sys_info);
                    745:                calculateOffsetDstPos(u_info,sys_info);
                    746: 
                    747:                /*
                    748:                 * Do the tile blt!
                    749:                 */
                    750:                if (u_info->blt_flags & BLT_MASKON) {
                    751:                        maskTile(sys_info);
                    752:                }
                    753:                else {
                    754:                        copyTile(sys_info);
                    755:                }
                    756:        }
                    757: 
                    758:        /*
                    759:         * Restore the locator if the screen was dealt with.
                    760:         */
                    761:        RESTORE_LOCATOR();
                    762: 
                    763: #ifdef AED
                    764:        /*  
                    765:         * If we are echoing to AED, keep track of bounding
                    766:         * rectangle of the updated screen area.
                    767:         */ 
                    768: 
                    769:        if (IS_AED(u_info->dst_bitmap) && blt_status &&
                    770:            (u_info->blt_flags & BLT_ECHO)) {
                    771:                aed_echo_rect(&changed_rect);
                    772:        }
                    773: #endif AED
                    774: 
                    775:        /*
                    776:         * Indicate that a blt was done.
                    777:         */
                    778:        return(1);
                    779: }

unix.superglobalmegacorp.com

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