|
|
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.