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