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