|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.