19aa5da4cStorek /*-
2*c32d685fSbostic * Copyright (c) 1991, 1993
3*c32d685fSbostic * The Regents of the University of California. All rights reserved.
49aa5da4cStorek *
59aa5da4cStorek * This code is derived from software contributed to the Computer Systems
69aa5da4cStorek * Engineering Group at Lawrence Berkeley Laboratory and to the University
79aa5da4cStorek * of California at Berkeley by Jef Poskanzer.
89aa5da4cStorek *
99aa5da4cStorek * %sccs.include.redist.c%
109aa5da4cStorek *
11*c32d685fSbostic * @(#)raster_op.c 8.1 (Berkeley) 06/11/93
129aa5da4cStorek *
139aa5da4cStorek * from: $Header: raster_op.c,v 1.22 92/06/17 08:14:44 torek Exp $
149aa5da4cStorek */
159aa5da4cStorek
169aa5da4cStorek /*
179aa5da4cStorek * Bitblit routine for raster library.
189aa5da4cStorek *
199aa5da4cStorek * This raster-op is machined to exacting tolerances by skilled native
209aa5da4cStorek * craftsmen with pride in their work.
219aa5da4cStorek *
229aa5da4cStorek * The various cases are broken down like this:
239aa5da4cStorek *
249aa5da4cStorek * src required
259aa5da4cStorek * 1-bit to 1-bit
269aa5da4cStorek * 1-bit to 8-bits
279aa5da4cStorek * 8-bits to 8-bits
289aa5da4cStorek * no src required
299aa5da4cStorek * 1-bit no-src
309aa5da4cStorek * 8-bits no-src
319aa5da4cStorek */
329aa5da4cStorek
339aa5da4cStorek #include <sys/types.h>
34ef65d49cSbostic #include <sparc/rcons/raster.h>
359aa5da4cStorek
369aa5da4cStorek /* CONFIGURE: To save on executable size, you can configure out the seldom-used
379aa5da4cStorek ** logical operations. With this variable set, the only operations implemented
389aa5da4cStorek ** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC.
399aa5da4cStorek */
409aa5da4cStorek #ifdef KERNEL
419aa5da4cStorek #define PARTIAL_LOGICAL_OPS
429aa5da4cStorek #endif
439aa5da4cStorek
449aa5da4cStorek /* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move
459aa5da4cStorek ** bytes, overlapping or not, ignoring the startup cost. Unfortunately
469aa5da4cStorek ** this is not true on some systems. For example, on a Sun 3 running
479aa5da4cStorek ** SunOS 3.5, bcopy() is about five times slower than a simple for loop
489aa5da4cStorek ** on overlapping copies. And on a 4.1.1 SPARC, bcopy() is about 2/3rds
499aa5da4cStorek ** as fast on backwards overlaps. So, only define this if your bcopy is ok.
509aa5da4cStorek */
519aa5da4cStorek #undef BCOPY_FASTER
529aa5da4cStorek
539aa5da4cStorek /* End of configurable definitions. */
549aa5da4cStorek
559aa5da4cStorek
569aa5da4cStorek /* Definitions. */
579aa5da4cStorek
589aa5da4cStorek /* Raster-op macros. These encapsulate the switch statements and so make
599aa5da4cStorek ** the source code 16 times smaller. The pre and pst args are code
609aa5da4cStorek ** fragments to put before and after the assignment in each case. They
619aa5da4cStorek ** can be the beginning and end of a loop. If the pst fragment includes a
629aa5da4cStorek ** masked assignment, for example to handle the left or right edge cases,
639aa5da4cStorek ** a good optimizing compiler will simplify the boolean expressions very
649aa5da4cStorek ** nicely - both cc and gcc on the SPARC will do this.
659aa5da4cStorek */
669aa5da4cStorek
679aa5da4cStorek #ifndef PARTIAL_LOGICAL_OPS
689aa5da4cStorek
699aa5da4cStorek #define ROP_DST(op,pre,d,pst) \
709aa5da4cStorek switch ( op ) \
719aa5da4cStorek { \
729aa5da4cStorek case RAS_CLEAR: \
739aa5da4cStorek pre \
749aa5da4cStorek (d) = 0; \
759aa5da4cStorek pst \
769aa5da4cStorek break; \
779aa5da4cStorek case RAS_INVERT: \
789aa5da4cStorek pre \
799aa5da4cStorek (d) = ~(d); \
809aa5da4cStorek pst \
819aa5da4cStorek break; \
829aa5da4cStorek case RAS_DST: \
839aa5da4cStorek /* noop */ \
849aa5da4cStorek break; \
859aa5da4cStorek case RAS_SET: \
869aa5da4cStorek pre \
879aa5da4cStorek (d) = ~0; \
889aa5da4cStorek pst \
899aa5da4cStorek break; \
909aa5da4cStorek default: \
919aa5da4cStorek return -1; \
929aa5da4cStorek }
939aa5da4cStorek
949aa5da4cStorek #define ROP_DSTCOLOR(op,pre,d,c,pst) \
959aa5da4cStorek switch ( op ) \
969aa5da4cStorek { \
979aa5da4cStorek case RAS_CLEAR: \
989aa5da4cStorek pre \
999aa5da4cStorek (d) = 0; \
1009aa5da4cStorek pst \
1019aa5da4cStorek break; \
1029aa5da4cStorek case RAS_INVERT: \
1039aa5da4cStorek pre \
1049aa5da4cStorek (d) = ~(d); \
1059aa5da4cStorek pst \
1069aa5da4cStorek break; \
1079aa5da4cStorek case RAS_DST: \
1089aa5da4cStorek /* noop */ \
1099aa5da4cStorek break; \
1109aa5da4cStorek case RAS_SET: \
1119aa5da4cStorek pre \
1129aa5da4cStorek (d) = (c); \
1139aa5da4cStorek pst \
1149aa5da4cStorek break; \
1159aa5da4cStorek default: \
1169aa5da4cStorek return -1; \
1179aa5da4cStorek }
1189aa5da4cStorek
1199aa5da4cStorek #define ROP_SRCDST(op,pre,s,d,pst) \
1209aa5da4cStorek switch ( op ) \
1219aa5da4cStorek { \
1229aa5da4cStorek case RAS_NOTOR: \
1239aa5da4cStorek pre \
1249aa5da4cStorek (d) = ~( (s) | (d) ); \
1259aa5da4cStorek pst \
1269aa5da4cStorek break; \
1279aa5da4cStorek case RAS_NOTSRC_AND_DST: \
1289aa5da4cStorek pre \
1299aa5da4cStorek (d) = ~(s) & (d); \
1309aa5da4cStorek pst \
1319aa5da4cStorek break; \
1329aa5da4cStorek case RAS_INVERTSRC: \
1339aa5da4cStorek pre \
1349aa5da4cStorek (d) = ~(s); \
1359aa5da4cStorek pst \
1369aa5da4cStorek break; \
1379aa5da4cStorek case RAS_SRC_AND_NOTDST: \
1389aa5da4cStorek pre \
1399aa5da4cStorek (d) = (s) & ~(d); \
1409aa5da4cStorek pst \
1419aa5da4cStorek break; \
1429aa5da4cStorek case RAS_XOR: \
1439aa5da4cStorek pre \
1449aa5da4cStorek (d) = (s) ^ (d); \
1459aa5da4cStorek pst \
1469aa5da4cStorek break; \
1479aa5da4cStorek case RAS_NOTAND: \
1489aa5da4cStorek pre \
1499aa5da4cStorek (d) = ~( (s) & (d) ); \
1509aa5da4cStorek pst \
1519aa5da4cStorek break; \
1529aa5da4cStorek case RAS_AND: \
1539aa5da4cStorek pre \
1549aa5da4cStorek (d) = (s) & (d); \
1559aa5da4cStorek pst \
1569aa5da4cStorek break; \
1579aa5da4cStorek case RAS_NOTXOR: \
1589aa5da4cStorek pre \
1599aa5da4cStorek (d) = ~( (s) ^ (d) ); \
1609aa5da4cStorek pst \
1619aa5da4cStorek break; \
1629aa5da4cStorek case RAS_NOTSRC_OR_DST: \
1639aa5da4cStorek pre \
1649aa5da4cStorek (d) = ~(s) | (d); \
1659aa5da4cStorek pst \
1669aa5da4cStorek break; \
1679aa5da4cStorek case RAS_SRC: \
1689aa5da4cStorek pre \
1699aa5da4cStorek (d) = (s); \
1709aa5da4cStorek pst \
1719aa5da4cStorek break; \
1729aa5da4cStorek case RAS_SRC_OR_NOTDST: \
1739aa5da4cStorek pre \
1749aa5da4cStorek (d) = (s) | ~(d); \
1759aa5da4cStorek pst \
1769aa5da4cStorek break; \
1779aa5da4cStorek case RAS_OR: \
1789aa5da4cStorek pre \
1799aa5da4cStorek (d) = (s) | (d); \
1809aa5da4cStorek pst \
1819aa5da4cStorek break; \
1829aa5da4cStorek default: \
1839aa5da4cStorek return -1; \
1849aa5da4cStorek }
1859aa5da4cStorek
1869aa5da4cStorek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
1879aa5da4cStorek switch ( op ) \
1889aa5da4cStorek { \
1899aa5da4cStorek case RAS_NOTOR: \
1909aa5da4cStorek pre \
1919aa5da4cStorek if ( s ) \
1929aa5da4cStorek (d) = ~( (c) | (d) ); \
1939aa5da4cStorek else \
1949aa5da4cStorek (d) = ~(d); \
1959aa5da4cStorek pst \
1969aa5da4cStorek break; \
1979aa5da4cStorek case RAS_NOTSRC_AND_DST: \
1989aa5da4cStorek pre \
1999aa5da4cStorek if ( s ) \
2009aa5da4cStorek (d) = ~(c) & (d); \
2019aa5da4cStorek pst \
2029aa5da4cStorek break; \
2039aa5da4cStorek case RAS_INVERTSRC: \
2049aa5da4cStorek pre \
2059aa5da4cStorek if ( s ) \
2069aa5da4cStorek (d) = ~(c); \
2079aa5da4cStorek else \
2089aa5da4cStorek (d) = ~0; \
2099aa5da4cStorek pst \
2109aa5da4cStorek break; \
2119aa5da4cStorek case RAS_SRC_AND_NOTDST: \
2129aa5da4cStorek pre \
2139aa5da4cStorek if ( s ) \
2149aa5da4cStorek (d) = (c) & ~(d); \
2159aa5da4cStorek else \
2169aa5da4cStorek (d) = 0; \
2179aa5da4cStorek pst \
2189aa5da4cStorek break; \
2199aa5da4cStorek case RAS_XOR: \
2209aa5da4cStorek pre \
2219aa5da4cStorek if ( s ) \
2229aa5da4cStorek (d) = (c) ^ (d); \
2239aa5da4cStorek pst \
2249aa5da4cStorek break; \
2259aa5da4cStorek case RAS_NOTAND: \
2269aa5da4cStorek pre \
2279aa5da4cStorek if ( s ) \
2289aa5da4cStorek (d) = ~( (c) & (d) ); \
2299aa5da4cStorek else \
2309aa5da4cStorek (d) = ~0; \
2319aa5da4cStorek pst \
2329aa5da4cStorek break; \
2339aa5da4cStorek case RAS_AND: \
2349aa5da4cStorek pre \
2359aa5da4cStorek if ( s ) \
2369aa5da4cStorek (d) = (c) & (d); \
2379aa5da4cStorek else \
2389aa5da4cStorek (d) = 0; \
2399aa5da4cStorek pst \
2409aa5da4cStorek break; \
2419aa5da4cStorek case RAS_NOTXOR: \
2429aa5da4cStorek pre \
2439aa5da4cStorek if ( s ) \
2449aa5da4cStorek (d) = ~( (c) ^ (d) ); \
2459aa5da4cStorek else \
2469aa5da4cStorek (d) = ~(d); \
2479aa5da4cStorek pst \
2489aa5da4cStorek break; \
2499aa5da4cStorek case RAS_NOTSRC_OR_DST: \
2509aa5da4cStorek pre \
2519aa5da4cStorek if ( s ) \
2529aa5da4cStorek (d) = ~(c) | (d); \
2539aa5da4cStorek else \
2549aa5da4cStorek (d) = ~0; \
2559aa5da4cStorek pst \
2569aa5da4cStorek break; \
2579aa5da4cStorek case RAS_SRC: \
2589aa5da4cStorek pre \
2599aa5da4cStorek if ( s ) \
2609aa5da4cStorek (d) = (c); \
2619aa5da4cStorek else \
2629aa5da4cStorek (d) = 0; \
2639aa5da4cStorek pst \
2649aa5da4cStorek break; \
2659aa5da4cStorek case RAS_SRC_OR_NOTDST: \
2669aa5da4cStorek pre \
2679aa5da4cStorek if ( s ) \
2689aa5da4cStorek (d) = (c) | ~(d); \
2699aa5da4cStorek else \
2709aa5da4cStorek (d) = ~(d); \
2719aa5da4cStorek pst \
2729aa5da4cStorek break; \
2739aa5da4cStorek case RAS_OR: \
2749aa5da4cStorek pre \
2759aa5da4cStorek if ( s ) \
2769aa5da4cStorek (d) = (c) | (d); \
2779aa5da4cStorek pst \
2789aa5da4cStorek break; \
2799aa5da4cStorek default: \
2809aa5da4cStorek return -1; \
2819aa5da4cStorek }
2829aa5da4cStorek
2839aa5da4cStorek #else /*PARTIAL_LOGICAL_OPS*/
2849aa5da4cStorek
2859aa5da4cStorek #define ROP_DST(op,pre,d,pst) \
2869aa5da4cStorek switch ( op ) \
2879aa5da4cStorek { \
2889aa5da4cStorek case RAS_CLEAR: \
2899aa5da4cStorek pre \
2909aa5da4cStorek (d) = 0; \
2919aa5da4cStorek pst \
2929aa5da4cStorek break; \
2939aa5da4cStorek case RAS_INVERT: \
2949aa5da4cStorek pre \
2959aa5da4cStorek (d) = ~(d); \
2969aa5da4cStorek pst \
2979aa5da4cStorek break; \
2989aa5da4cStorek case RAS_SET: \
2999aa5da4cStorek pre \
3009aa5da4cStorek (d) = ~0; \
3019aa5da4cStorek pst \
3029aa5da4cStorek break; \
3039aa5da4cStorek default: \
3049aa5da4cStorek return -1; \
3059aa5da4cStorek }
3069aa5da4cStorek
3079aa5da4cStorek #define ROP_DSTCOLOR(op,pre,d,c,pst) \
3089aa5da4cStorek switch ( op ) \
3099aa5da4cStorek { \
3109aa5da4cStorek case RAS_CLEAR: \
3119aa5da4cStorek pre \
3129aa5da4cStorek (d) = 0; \
3139aa5da4cStorek pst \
3149aa5da4cStorek break; \
3159aa5da4cStorek case RAS_INVERT: \
3169aa5da4cStorek pre \
3179aa5da4cStorek (d) = ~(d); \
3189aa5da4cStorek pst \
3199aa5da4cStorek break; \
3209aa5da4cStorek case RAS_SET: \
3219aa5da4cStorek pre \
3229aa5da4cStorek (d) = (c); \
3239aa5da4cStorek pst \
3249aa5da4cStorek break; \
3259aa5da4cStorek default: \
3269aa5da4cStorek return -1; \
3279aa5da4cStorek }
3289aa5da4cStorek
3299aa5da4cStorek #define ROP_SRCDST(op,pre,s,d,pst) \
3309aa5da4cStorek switch ( op ) \
3319aa5da4cStorek { \
3329aa5da4cStorek case RAS_INVERTSRC: \
3339aa5da4cStorek pre \
3349aa5da4cStorek (d) = ~(s); \
3359aa5da4cStorek pst \
3369aa5da4cStorek break; \
3379aa5da4cStorek case RAS_XOR: \
3389aa5da4cStorek pre \
3399aa5da4cStorek (d) = (s) ^ (d); \
3409aa5da4cStorek pst \
3419aa5da4cStorek break; \
3429aa5da4cStorek case RAS_SRC: \
3439aa5da4cStorek pre \
3449aa5da4cStorek (d) = (s); \
3459aa5da4cStorek pst \
3469aa5da4cStorek break; \
3479aa5da4cStorek default: \
3489aa5da4cStorek return -1; \
3499aa5da4cStorek }
3509aa5da4cStorek
3519aa5da4cStorek #define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
3529aa5da4cStorek switch ( op ) \
3539aa5da4cStorek { \
3549aa5da4cStorek case RAS_INVERTSRC: \
3559aa5da4cStorek pre \
3569aa5da4cStorek if ( s ) \
3579aa5da4cStorek (d) = ~(c); \
3589aa5da4cStorek else \
3599aa5da4cStorek (d) = ~0; \
3609aa5da4cStorek pst \
3619aa5da4cStorek break; \
3629aa5da4cStorek case RAS_XOR: \
3639aa5da4cStorek pre \
3649aa5da4cStorek if ( s ) \
3659aa5da4cStorek (d) = (c) ^ (d); \
3669aa5da4cStorek pst \
3679aa5da4cStorek break; \
3689aa5da4cStorek case RAS_SRC: \
3699aa5da4cStorek pre \
3709aa5da4cStorek if ( s ) \
3719aa5da4cStorek (d) = (c); \
3729aa5da4cStorek else \
3739aa5da4cStorek (d) = 0; \
3749aa5da4cStorek pst \
3759aa5da4cStorek break; \
3769aa5da4cStorek default: \
3779aa5da4cStorek return -1; \
3789aa5da4cStorek }
3799aa5da4cStorek
3809aa5da4cStorek #endif /*PARTIAL_LOGICAL_OPS*/
3819aa5da4cStorek
3829aa5da4cStorek
3839aa5da4cStorek /* Variables. */
3849aa5da4cStorek
3859aa5da4cStorek static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
3869aa5da4cStorek /* CLEAR INVERT DST SET */
3879aa5da4cStorek
3889aa5da4cStorek #ifdef MSBIT_FIRST
3899aa5da4cStorek
3909aa5da4cStorek u_long raster_bitmask[32] = {
3919aa5da4cStorek 0x80000000, 0x40000000, 0x20000000, 0x10000000,
3929aa5da4cStorek 0x08000000, 0x04000000, 0x02000000, 0x01000000,
3939aa5da4cStorek 0x00800000, 0x00400000, 0x00200000, 0x00100000,
3949aa5da4cStorek 0x00080000, 0x00040000, 0x00020000, 0x00010000,
3959aa5da4cStorek 0x00008000, 0x00004000, 0x00002000, 0x00001000,
3969aa5da4cStorek 0x00000800, 0x00000400, 0x00000200, 0x00000100,
3979aa5da4cStorek 0x00000080, 0x00000040, 0x00000020, 0x00000010,
3989aa5da4cStorek 0x00000008, 0x00000004, 0x00000002, 0x00000001 };
3999aa5da4cStorek
4009aa5da4cStorek #ifdef MSBYTE_FIRST
4019aa5da4cStorek static u_long leftmask[32] = {
4029aa5da4cStorek 0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
4039aa5da4cStorek 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
4049aa5da4cStorek 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
4059aa5da4cStorek 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
4069aa5da4cStorek 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
4079aa5da4cStorek 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
4089aa5da4cStorek 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
4099aa5da4cStorek 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
4109aa5da4cStorek static u_long rightmask[32] = {
4119aa5da4cStorek 0x00000000, 0x00000001, 0x00000003, 0x00000007,
4129aa5da4cStorek 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
4139aa5da4cStorek 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
4149aa5da4cStorek 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
4159aa5da4cStorek 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
4169aa5da4cStorek 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
4179aa5da4cStorek 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
4189aa5da4cStorek 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
4199aa5da4cStorek #endif /*MSBYTE_FIRST*/
4209aa5da4cStorek
4219aa5da4cStorek #else /*MSBIT_FIRST*/
4229aa5da4cStorek
4239aa5da4cStorek u_long raster_bitmask[32] = {
4249aa5da4cStorek 0x00000001, 0x00000002, 0x00000004, 0x00000008,
4259aa5da4cStorek 0x00000010, 0x00000020, 0x00000040, 0x00000080,
4269aa5da4cStorek 0x00000100, 0x00000200, 0x00000400, 0x00000800,
4279aa5da4cStorek 0x00001000, 0x00002000, 0x00004000, 0x00008000,
4289aa5da4cStorek 0x00010000, 0x00020000, 0x00040000, 0x00080000,
4299aa5da4cStorek 0x00100000, 0x00200000, 0x00400000, 0x00800000,
4309aa5da4cStorek 0x01000000, 0x02000000, 0x04000000, 0x08000000,
4319aa5da4cStorek 0x10000000, 0x20000000, 0x40000000, 0x80000000 };
4329aa5da4cStorek
4339aa5da4cStorek #ifndef MSBYTE_FIRST
4349aa5da4cStorek static u_long leftmask[32] = {
4359aa5da4cStorek 0x00000000, 0x00000001, 0x00000003, 0x00000007,
4369aa5da4cStorek 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
4379aa5da4cStorek 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
4389aa5da4cStorek 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
4399aa5da4cStorek 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
4409aa5da4cStorek 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
4419aa5da4cStorek 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
4429aa5da4cStorek 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
4439aa5da4cStorek static u_long rightmask[32] = {
4449aa5da4cStorek 0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
4459aa5da4cStorek 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
4469aa5da4cStorek 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
4479aa5da4cStorek 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
4489aa5da4cStorek 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
4499aa5da4cStorek 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
4509aa5da4cStorek 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
4519aa5da4cStorek 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
4529aa5da4cStorek #endif /*not MSBYTE_FIRST*/
4539aa5da4cStorek
4549aa5da4cStorek #endif /*MSBIT_FIRST*/
4559aa5da4cStorek
4569aa5da4cStorek /* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */
4579aa5da4cStorek
4589aa5da4cStorek #ifdef MSBYTE_FIRST
4599aa5da4cStorek static u_long bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
4609aa5da4cStorek #else /*MSBYTE_FIRST*/
4619aa5da4cStorek static u_long bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
4629aa5da4cStorek #endif /*MSBYTE_FIRST*/
4639aa5da4cStorek
4649aa5da4cStorek
4659aa5da4cStorek /* Forward routines. */
4669aa5da4cStorek
4679aa5da4cStorek static int raster_blit();
4689aa5da4cStorek
4699aa5da4cStorek
4709aa5da4cStorek /* Raster operations. */
4719aa5da4cStorek
4729aa5da4cStorek /* Performs a bitblit. Returns 0 on success, -1 on failure. */
4739aa5da4cStorek int
raster_op(dst,dx,dy,w,h,rop,src,sx,sy)4749aa5da4cStorek raster_op( dst, dx, dy, w, h, rop, src, sx, sy )
4759aa5da4cStorek struct raster* dst;
4769aa5da4cStorek int dx, dy, w, h, rop;
4779aa5da4cStorek struct raster* src;
4789aa5da4cStorek int sx, sy;
4799aa5da4cStorek {
4809aa5da4cStorek if ( dst == (struct raster*) 0 )
4819aa5da4cStorek return -1; /* no destination */
4829aa5da4cStorek
4839aa5da4cStorek if ( needsrc[RAS_GETOP( rop )] )
4849aa5da4cStorek {
4859aa5da4cStorek /* Two-operand blit. */
4869aa5da4cStorek if ( src == (struct raster*) 0 )
4879aa5da4cStorek return -1; /* no source */
4889aa5da4cStorek
4899aa5da4cStorek /* Clip against source. */
4909aa5da4cStorek if ( sx < 0 )
4919aa5da4cStorek {
4929aa5da4cStorek w += sx;
4939aa5da4cStorek sx = 0;
4949aa5da4cStorek }
4959aa5da4cStorek if ( sy < 0 )
4969aa5da4cStorek {
4979aa5da4cStorek h += sy;
4989aa5da4cStorek sy = 0;
4999aa5da4cStorek }
5009aa5da4cStorek if ( sx + w > src->width )
5019aa5da4cStorek w = src->width - sx;
5029aa5da4cStorek if ( sy + h > src->height )
5039aa5da4cStorek h = src->height - sy;
5049aa5da4cStorek
5059aa5da4cStorek /* Clip against dest. */
5069aa5da4cStorek if ( dx < 0 )
5079aa5da4cStorek {
5089aa5da4cStorek w += dx;
5099aa5da4cStorek sx -= dx;
5109aa5da4cStorek dx = 0;
5119aa5da4cStorek }
5129aa5da4cStorek if ( dy < 0 )
5139aa5da4cStorek {
5149aa5da4cStorek h += dy;
5159aa5da4cStorek sy -= dy;
5169aa5da4cStorek dy = 0;
5179aa5da4cStorek }
5189aa5da4cStorek if ( dx + w > dst->width )
5199aa5da4cStorek w = dst->width - dx;
5209aa5da4cStorek if ( dy + h > dst->height )
5219aa5da4cStorek h = dst->height - dy;
5229aa5da4cStorek
5239aa5da4cStorek if ( w <= 0 || h <= 0 )
5249aa5da4cStorek return 0; /* nothing to do */
5259aa5da4cStorek
5269aa5da4cStorek return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy );
5279aa5da4cStorek }
5289aa5da4cStorek
5299aa5da4cStorek /* No source necessary - one-operand blit. */
5309aa5da4cStorek if ( src != (struct raster*) 0 )
5319aa5da4cStorek return -1; /* unwanted source */
5329aa5da4cStorek
5339aa5da4cStorek /* Clip against dest. */
5349aa5da4cStorek if ( dx < 0 )
5359aa5da4cStorek {
5369aa5da4cStorek w += dx;
5379aa5da4cStorek dx = 0;
5389aa5da4cStorek }
5399aa5da4cStorek if ( dy < 0 )
5409aa5da4cStorek {
5419aa5da4cStorek h += dy;
5429aa5da4cStorek dy = 0;
5439aa5da4cStorek }
5449aa5da4cStorek if ( dx + w > dst->width )
5459aa5da4cStorek w = dst->width - dx;
5469aa5da4cStorek if ( dy + h > dst->height )
5479aa5da4cStorek h = dst->height - dy;
5489aa5da4cStorek
5499aa5da4cStorek if ( w <= 0 || h <= 0 )
5509aa5da4cStorek return 0; /* nothing to do */
5519aa5da4cStorek
5529aa5da4cStorek return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop );
5539aa5da4cStorek }
5549aa5da4cStorek
5559aa5da4cStorek /* Semi-public routine to do a bitblit without clipping. Returns 0 on
5569aa5da4cStorek ** success, -1 on failure.
5579aa5da4cStorek */
5589aa5da4cStorek int
raster_op_noclip(dst,dx,dy,w,h,rop,src,sx,sy)5599aa5da4cStorek raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy )
5609aa5da4cStorek struct raster* dst;
5619aa5da4cStorek int dx, dy, w, h, rop;
5629aa5da4cStorek struct raster* src;
5639aa5da4cStorek int sx, sy;
5649aa5da4cStorek {
5659aa5da4cStorek int op;
5669aa5da4cStorek
5679aa5da4cStorek op = RAS_GETOP( rop );
5689aa5da4cStorek
5699aa5da4cStorek if ( src->depth == 1 )
5709aa5da4cStorek {
5719aa5da4cStorek /* One-bit to ? blit. */
5729aa5da4cStorek if ( dst->depth == 1 )
5739aa5da4cStorek {
5749aa5da4cStorek /* One to one blit. */
5759aa5da4cStorek u_long* srclin1;
5769aa5da4cStorek u_long* dstlin1;
5779aa5da4cStorek int srcleftignore, srcrightignore, srclongs;
5789aa5da4cStorek int dstleftignore, dstrightignore, dstlongs;
5799aa5da4cStorek
5809aa5da4cStorek srclin1 = RAS_ADDR( src, sx, sy );
5819aa5da4cStorek dstlin1 = RAS_ADDR( dst, dx, dy );
5829aa5da4cStorek
5839aa5da4cStorek #ifdef BCOPY_FASTER
5849aa5da4cStorek /* Special-case full-width to full-width copies. */
5859aa5da4cStorek if ( op == RAS_SRC && src->width == w && dst->width == w &&
5869aa5da4cStorek src->linelongs == dst->linelongs && src->linelongs == w >> 5 )
5879aa5da4cStorek {
5889aa5da4cStorek bcopy(
5899aa5da4cStorek (char*) srclin1, (char*) dstlin1,
5909aa5da4cStorek h * src->linelongs * sizeof(u_long) );
5919aa5da4cStorek return 0;
5929aa5da4cStorek }
5939aa5da4cStorek #endif /*BCOPY_FASTER*/
5949aa5da4cStorek
5959aa5da4cStorek srcleftignore = ( sx & 31 );
5969aa5da4cStorek srclongs = ( srcleftignore + w + 31 ) >> 5;
5979aa5da4cStorek srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31;
5989aa5da4cStorek dstleftignore = ( dx & 31 );
5999aa5da4cStorek dstlongs = ( dstleftignore + w + 31 ) >> 5;
6009aa5da4cStorek dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
6019aa5da4cStorek
6029aa5da4cStorek return raster_blit(
6039aa5da4cStorek src, srclin1, srcleftignore, srcrightignore, srclongs,
6049aa5da4cStorek dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
6059aa5da4cStorek }
6069aa5da4cStorek
6079aa5da4cStorek else
6089aa5da4cStorek {
6099aa5da4cStorek /* One to eight, using the color in the rop. This could
6109aa5da4cStorek ** probably be sped up by handling each four-bit source nybble
6119aa5da4cStorek ** as a group, indexing into a 16-element runtime-constructed
6129aa5da4cStorek ** table of longwords.
6139aa5da4cStorek */
6149aa5da4cStorek u_long* srclin1;
6159aa5da4cStorek u_long* dstlin1;
6169aa5da4cStorek u_long* srclin2;
6179aa5da4cStorek u_long* srclin;
6189aa5da4cStorek u_long* dstlin;
6199aa5da4cStorek register u_long* srclong;
6209aa5da4cStorek register u_long* dstlong;
6219aa5da4cStorek register u_long color, dl;
6229aa5da4cStorek register int srcbit, dstbyte, i;
6239aa5da4cStorek
6249aa5da4cStorek color = RAS_GETCOLOR( rop );
6259aa5da4cStorek if ( color == 0 )
6269aa5da4cStorek color = 255;
6279aa5da4cStorek
6289aa5da4cStorek /* Make 32 bits of color so we can do the ROP without shifting. */
6299aa5da4cStorek color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
6309aa5da4cStorek
6319aa5da4cStorek /* Don't have to worry about overlapping blits here. */
6329aa5da4cStorek srclin1 = RAS_ADDR( src, sx, sy );
6339aa5da4cStorek srclin2 = srclin1 + h * src->linelongs;
6349aa5da4cStorek dstlin1 = RAS_ADDR( dst, dx, dy );
6359aa5da4cStorek srclin = srclin1;
6369aa5da4cStorek dstlin = dstlin1;
6379aa5da4cStorek while ( srclin != srclin2 )
6389aa5da4cStorek {
6399aa5da4cStorek srclong = srclin;
6409aa5da4cStorek srcbit = sx & 31;
6419aa5da4cStorek dstlong = dstlin;
6429aa5da4cStorek dstbyte = dx & 3;
6439aa5da4cStorek i = w;
6449aa5da4cStorek
6459aa5da4cStorek /* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
6469aa5da4cStorek ROP_SRCDSTCOLOR(
6479aa5da4cStorek /*op*/ op,
6489aa5da4cStorek /*pre*/ while ( i > 0 )
6499aa5da4cStorek {
6509aa5da4cStorek dl = *dstlong;,
6519aa5da4cStorek /*s*/ *srclong & raster_bitmask[srcbit],
6529aa5da4cStorek /*d*/ dl,
6539aa5da4cStorek /*c*/ color,
6549aa5da4cStorek /*pst*/ *dstlong = ( *dstlong & ~bytemask[dstbyte] ) |
6559aa5da4cStorek ( dl & bytemask[dstbyte] );
6569aa5da4cStorek if ( srcbit == 31 )
6579aa5da4cStorek {
6589aa5da4cStorek srcbit = 0;
6599aa5da4cStorek ++srclong;
6609aa5da4cStorek }
6619aa5da4cStorek else
6629aa5da4cStorek ++srcbit;
6639aa5da4cStorek if ( dstbyte == 3 )
6649aa5da4cStorek {
6659aa5da4cStorek dstbyte = 0;
6669aa5da4cStorek ++dstlong;
6679aa5da4cStorek }
6689aa5da4cStorek else
6699aa5da4cStorek ++dstbyte;
6709aa5da4cStorek --i;
6719aa5da4cStorek } )
6729aa5da4cStorek
6739aa5da4cStorek srclin += src->linelongs;
6749aa5da4cStorek dstlin += dst->linelongs;
6759aa5da4cStorek }
6769aa5da4cStorek }
6779aa5da4cStorek }
6789aa5da4cStorek
6799aa5da4cStorek else
6809aa5da4cStorek {
6819aa5da4cStorek /* Eight to eight blit. */
6829aa5da4cStorek u_long* srclin1;
6839aa5da4cStorek u_long* dstlin1;
6849aa5da4cStorek int srcleftignore, srcrightignore, srclongs;
6859aa5da4cStorek int dstleftignore, dstrightignore, dstlongs;
6869aa5da4cStorek
6879aa5da4cStorek if ( dst->depth != 8 )
6889aa5da4cStorek return -1; /* depth mismatch */
6899aa5da4cStorek
6909aa5da4cStorek srclin1 = RAS_ADDR( src, sx, sy );
6919aa5da4cStorek dstlin1 = RAS_ADDR( dst, dx, dy );
6929aa5da4cStorek
6939aa5da4cStorek #ifdef BCOPY_FASTER
6949aa5da4cStorek /* Special-case full-width to full-width copies. */
6959aa5da4cStorek if ( op == RAS_SRC && src->width == w && dst->width == w &&
6969aa5da4cStorek src->linelongs == dst->linelongs && src->linelongs == w >> 2 )
6979aa5da4cStorek {
6989aa5da4cStorek bcopy( (char*) srclin1, (char*) dstlin1,
6999aa5da4cStorek h * src->linelongs * sizeof(u_long) );
7009aa5da4cStorek return 0;
7019aa5da4cStorek }
7029aa5da4cStorek #endif /*BCOPY_FASTER*/
7039aa5da4cStorek
7049aa5da4cStorek srcleftignore = ( sx & 3 ) * 8;
7059aa5da4cStorek srclongs = ( srcleftignore + w * 8 + 31 ) >> 5;
7069aa5da4cStorek srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31;
7079aa5da4cStorek dstleftignore = ( dx & 3 ) * 8;
7089aa5da4cStorek dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
7099aa5da4cStorek dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
7109aa5da4cStorek
7119aa5da4cStorek return raster_blit(
7129aa5da4cStorek src, srclin1, srcleftignore, srcrightignore, srclongs,
7139aa5da4cStorek dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
7149aa5da4cStorek }
7159aa5da4cStorek
7169aa5da4cStorek return 0;
7179aa5da4cStorek }
7189aa5da4cStorek
7199aa5da4cStorek /* Semi-public routine to do a no-src bitblit without clipping. Returns 0
7209aa5da4cStorek ** on success, -1 on failure.
7219aa5da4cStorek */
7229aa5da4cStorek int
raster_op_nosrc_noclip(dst,dx,dy,w,h,rop)7239aa5da4cStorek raster_op_nosrc_noclip( dst, dx, dy, w, h, rop )
7249aa5da4cStorek struct raster* dst;
7259aa5da4cStorek int dx, dy, w, h, rop;
7269aa5da4cStorek {
7279aa5da4cStorek int op;
7289aa5da4cStorek
7299aa5da4cStorek op = RAS_GETOP( rop );
7309aa5da4cStorek
7319aa5da4cStorek if ( dst->depth == 1 )
7329aa5da4cStorek {
7339aa5da4cStorek /* One-bit no-src blit. */
7349aa5da4cStorek u_long* dstlin1;
7359aa5da4cStorek u_long* dstlin2;
7369aa5da4cStorek u_long* dstlin;
7379aa5da4cStorek int dstleftignore, dstrightignore, dstlongs;
7389aa5da4cStorek u_long dl, lm, nlm, rm, nrm;
7399aa5da4cStorek register u_long* dstlong2;
7409aa5da4cStorek register u_long* dstlong;
7419aa5da4cStorek
7429aa5da4cStorek dstlin1 = RAS_ADDR( dst, dx, dy );
7439aa5da4cStorek
7449aa5da4cStorek #ifdef BCOPY_FASTER
7459aa5da4cStorek /* Special-case full-width clears. */
7469aa5da4cStorek if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
7479aa5da4cStorek {
7489aa5da4cStorek bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
7499aa5da4cStorek return 0;
7509aa5da4cStorek }
7519aa5da4cStorek #endif /*BCOPY_FASTER*/
7529aa5da4cStorek
7539aa5da4cStorek dstleftignore = ( dx & 31 );
7549aa5da4cStorek dstlongs = ( dstleftignore + w + 31 ) >> 5;
7559aa5da4cStorek dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
7569aa5da4cStorek
7579aa5da4cStorek dstlin2 = dstlin1 + h * dst->linelongs;
7589aa5da4cStorek dstlin = dstlin1;
7599aa5da4cStorek
7609aa5da4cStorek if ( dstlongs == 1 )
7619aa5da4cStorek {
7629aa5da4cStorek /* It fits into a single longword. */
7639aa5da4cStorek lm = leftmask[dstleftignore] | rightmask[dstrightignore];
7649aa5da4cStorek nlm = ~lm;
7659aa5da4cStorek while ( dstlin != dstlin2 )
7669aa5da4cStorek {
7679aa5da4cStorek ROP_DST(
7689aa5da4cStorek /*op*/ op,
7699aa5da4cStorek /*pre*/ dl = *dstlin;,
7709aa5da4cStorek /*d*/ dl,
7719aa5da4cStorek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
7729aa5da4cStorek
7739aa5da4cStorek dstlin += dst->linelongs;
7749aa5da4cStorek }
7759aa5da4cStorek }
7769aa5da4cStorek else
7779aa5da4cStorek {
7789aa5da4cStorek lm = leftmask[dstleftignore];
7799aa5da4cStorek rm = rightmask[dstrightignore];
7809aa5da4cStorek nrm = ~rm;
7819aa5da4cStorek nlm = ~lm;
7829aa5da4cStorek
7839aa5da4cStorek while ( dstlin != dstlin2 )
7849aa5da4cStorek {
7859aa5da4cStorek dstlong = dstlin;
7869aa5da4cStorek dstlong2 = dstlong + dstlongs;
7879aa5da4cStorek if ( dstrightignore != 0 )
7889aa5da4cStorek --dstlong2;
7899aa5da4cStorek
7909aa5da4cStorek /* Leading edge. */
7919aa5da4cStorek if ( dstleftignore != 0 )
7929aa5da4cStorek {
7939aa5da4cStorek ROP_DST(
7949aa5da4cStorek /*op*/ op,
7959aa5da4cStorek /*pre*/ dl = *dstlong;,
7969aa5da4cStorek /*d*/ dl,
7979aa5da4cStorek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
7989aa5da4cStorek ++dstlong;
7999aa5da4cStorek }
8009aa5da4cStorek
8019aa5da4cStorek /* Main rop. */
8029aa5da4cStorek ROP_DST(
8039aa5da4cStorek /*op*/ op,
8049aa5da4cStorek /*pre*/ while ( dstlong != dstlong2 )
8059aa5da4cStorek {,
8069aa5da4cStorek /*d*/ *dstlong,
8079aa5da4cStorek /*pst*/ ++dstlong;
8089aa5da4cStorek } )
8099aa5da4cStorek
8109aa5da4cStorek /* Trailing edge. */
8119aa5da4cStorek if ( dstrightignore != 0 )
8129aa5da4cStorek {
8139aa5da4cStorek ROP_DST(
8149aa5da4cStorek /*op*/ op,
8159aa5da4cStorek /*pre*/ dl = *dstlong;,
8169aa5da4cStorek /*d*/ dl,
8179aa5da4cStorek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
8189aa5da4cStorek }
8199aa5da4cStorek
8209aa5da4cStorek dstlin += dst->linelongs;
8219aa5da4cStorek }
8229aa5da4cStorek }
8239aa5da4cStorek }
8249aa5da4cStorek
8259aa5da4cStorek else
8269aa5da4cStorek {
8279aa5da4cStorek /* Eight-bit no-src blit. */
8289aa5da4cStorek register u_long color;
8299aa5da4cStorek u_long* dstlin1;
8309aa5da4cStorek u_long* dstlin2;
8319aa5da4cStorek u_long* dstlin;
8329aa5da4cStorek int dstleftignore, dstrightignore, dstlongs;
8339aa5da4cStorek u_long dl, lm, nlm, rm, nrm;
8349aa5da4cStorek register u_long* dstlong2;
8359aa5da4cStorek register u_long* dstlong;
8369aa5da4cStorek
8379aa5da4cStorek dstlin1 = RAS_ADDR( dst, dx, dy );
8389aa5da4cStorek
8399aa5da4cStorek #ifdef BCOPY_FASTER
8409aa5da4cStorek /* Special-case full-width clears. */
8419aa5da4cStorek if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 )
8429aa5da4cStorek {
8439aa5da4cStorek bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_long) );
8449aa5da4cStorek return 0;
8459aa5da4cStorek }
8469aa5da4cStorek #endif /*BCOPY_FASTER*/
8479aa5da4cStorek
8489aa5da4cStorek color = RAS_GETCOLOR( rop );
8499aa5da4cStorek if ( color == 0 )
8509aa5da4cStorek color = 255;
8519aa5da4cStorek
8529aa5da4cStorek /* Make 32 bits of color so we can do the ROP without shifting. */
8539aa5da4cStorek color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
8549aa5da4cStorek
8559aa5da4cStorek dstleftignore = ( dx & 3 ) * 8;
8569aa5da4cStorek dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
8579aa5da4cStorek dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
8589aa5da4cStorek
8599aa5da4cStorek dstlin2 = dstlin1 + h * dst->linelongs;
8609aa5da4cStorek dstlin = dstlin1;
8619aa5da4cStorek
8629aa5da4cStorek if ( dstlongs == 1 )
8639aa5da4cStorek {
8649aa5da4cStorek /* It fits into a single longword. */
8659aa5da4cStorek lm = leftmask[dstleftignore] | rightmask[dstrightignore];
8669aa5da4cStorek nlm = ~lm;
8679aa5da4cStorek while ( dstlin != dstlin2 )
8689aa5da4cStorek {
8699aa5da4cStorek ROP_DSTCOLOR(
8709aa5da4cStorek /*op*/ op,
8719aa5da4cStorek /*pre*/ dl = *dstlin;,
8729aa5da4cStorek /*d*/ dl,
8739aa5da4cStorek /*c*/ color,
8749aa5da4cStorek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
8759aa5da4cStorek
8769aa5da4cStorek dstlin += dst->linelongs;
8779aa5da4cStorek }
8789aa5da4cStorek }
8799aa5da4cStorek else
8809aa5da4cStorek {
8819aa5da4cStorek lm = leftmask[dstleftignore];
8829aa5da4cStorek rm = rightmask[dstrightignore];
8839aa5da4cStorek nrm = ~rm;
8849aa5da4cStorek nlm = ~lm;
8859aa5da4cStorek while ( dstlin != dstlin2 )
8869aa5da4cStorek {
8879aa5da4cStorek dstlong = dstlin;
8889aa5da4cStorek dstlong2 = dstlong + dstlongs;
8899aa5da4cStorek if ( dstrightignore != 0 )
8909aa5da4cStorek --dstlong2;
8919aa5da4cStorek
8929aa5da4cStorek /* Leading edge. */
8939aa5da4cStorek if ( dstleftignore != 0 )
8949aa5da4cStorek {
8959aa5da4cStorek ROP_DSTCOLOR(
8969aa5da4cStorek /*op*/ op,
8979aa5da4cStorek /*pre*/ dl = *dstlong;,
8989aa5da4cStorek /*d*/ dl,
8999aa5da4cStorek /*c*/ color,
9009aa5da4cStorek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
9019aa5da4cStorek ++dstlong;
9029aa5da4cStorek }
9039aa5da4cStorek
9049aa5da4cStorek /* Main rop. */
9059aa5da4cStorek ROP_DSTCOLOR(
9069aa5da4cStorek /*op*/ op,
9079aa5da4cStorek /*pre*/ while ( dstlong != dstlong2 )
9089aa5da4cStorek {,
9099aa5da4cStorek /*d*/ *dstlong,
9109aa5da4cStorek /*c*/ color,
9119aa5da4cStorek /*pst*/ ++dstlong;
9129aa5da4cStorek } )
9139aa5da4cStorek
9149aa5da4cStorek /* Trailing edge. */
9159aa5da4cStorek if ( dstrightignore != 0 )
9169aa5da4cStorek {
9179aa5da4cStorek ROP_DSTCOLOR(
9189aa5da4cStorek /*op*/ op,
9199aa5da4cStorek /*pre*/ dl = *dstlong;,
9209aa5da4cStorek /*d*/ dl,
9219aa5da4cStorek /*c*/ color,
9229aa5da4cStorek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
9239aa5da4cStorek }
9249aa5da4cStorek
9259aa5da4cStorek dstlin += dst->linelongs;
9269aa5da4cStorek }
9279aa5da4cStorek }
9289aa5da4cStorek }
9299aa5da4cStorek
9309aa5da4cStorek return 0;
9319aa5da4cStorek }
9329aa5da4cStorek
9339aa5da4cStorek /* This is a general bitblit routine, handling overlapping source and
9349aa5da4cStorek ** destination. It's used for both the 1-to-1 and 8-to-8 cases.
9359aa5da4cStorek */
9369aa5da4cStorek static int
raster_blit(src,srclin1,srcleftignore,srcrightignore,srclongs,dst,dstlin1,dstleftignore,dstrightignore,dstlongs,h,op)9379aa5da4cStorek raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op )
9389aa5da4cStorek struct raster* src;
9399aa5da4cStorek u_long* srclin1;
9409aa5da4cStorek int srcleftignore, srcrightignore, srclongs;
9419aa5da4cStorek struct raster* dst;
9429aa5da4cStorek u_long* dstlin1;
9439aa5da4cStorek int dstleftignore, dstrightignore, dstlongs;
9449aa5da4cStorek int h, op;
9459aa5da4cStorek {
9469aa5da4cStorek u_long* srclin2;
9479aa5da4cStorek u_long* dstlin2;
9489aa5da4cStorek int srclininc, dstlininc;
9499aa5da4cStorek u_long* srclin;
9509aa5da4cStorek u_long* dstlin;
9519aa5da4cStorek register int prevleftshift, currrightshift;
9529aa5da4cStorek int longinc;
9539aa5da4cStorek register u_long* srclong;
9549aa5da4cStorek register u_long* dstlong;
9559aa5da4cStorek register u_long* dstlong2;
9569aa5da4cStorek register u_long dl, lm, nlm, rm, nrm;
9579aa5da4cStorek
9589aa5da4cStorek prevleftshift = ( srcleftignore - dstleftignore ) & 31;
9599aa5da4cStorek
9609aa5da4cStorek srclin2 = srclin1 + h * src->linelongs;
9619aa5da4cStorek dstlin2 = dstlin1 + h * dst->linelongs;
9629aa5da4cStorek srclininc = src->linelongs;
9639aa5da4cStorek dstlininc = dst->linelongs;
9649aa5da4cStorek longinc = 1;
9659aa5da4cStorek
9669aa5da4cStorek /* Check for overlaps. */
9679aa5da4cStorek if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) ||
9689aa5da4cStorek ( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) )
9699aa5da4cStorek {
9709aa5da4cStorek /* Horizontal overlap. Should we reverse? */
9719aa5da4cStorek if ( srclin1 < dstlin1 )
9729aa5da4cStorek {
9739aa5da4cStorek longinc = -1;
9749aa5da4cStorek srclin1 += srclongs - 1;
9759aa5da4cStorek srclin2 += srclongs - 1;
9769aa5da4cStorek dstlin1 += dstlongs - 1;
9779aa5da4cStorek }
9789aa5da4cStorek }
9799aa5da4cStorek else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) ||
9809aa5da4cStorek ( srclin1 >= dstlin1 && srclin1 < dstlin2 ) )
9819aa5da4cStorek {
9829aa5da4cStorek /* Vertical overlap. Should we reverse? */
9839aa5da4cStorek if ( srclin1 < dstlin1 )
9849aa5da4cStorek {
9859aa5da4cStorek srclin2 = srclin1 - srclininc;
9869aa5da4cStorek srclin1 += ( h - 1 ) * srclininc;
9879aa5da4cStorek dstlin1 += ( h - 1 ) * dstlininc;
9889aa5da4cStorek srclininc = -srclininc;
9899aa5da4cStorek dstlininc = -dstlininc;
9909aa5da4cStorek }
9919aa5da4cStorek }
9929aa5da4cStorek srclin = srclin1;
9939aa5da4cStorek dstlin = dstlin1;
9949aa5da4cStorek
9959aa5da4cStorek if ( prevleftshift == 0 )
9969aa5da4cStorek {
9979aa5da4cStorek /* The bits line up, no shifting necessary. */
9989aa5da4cStorek if ( dstlongs == 1 )
9999aa5da4cStorek {
10009aa5da4cStorek /* It all fits into a single longword. */
10019aa5da4cStorek lm = leftmask[dstleftignore] | rightmask[dstrightignore];
10029aa5da4cStorek nlm = ~lm;
10039aa5da4cStorek while ( srclin != srclin2 )
10049aa5da4cStorek {
10059aa5da4cStorek ROP_SRCDST(
10069aa5da4cStorek /*op*/ op,
10079aa5da4cStorek /*pre*/ dl = *dstlin;,
10089aa5da4cStorek /*s*/ *srclin,
10099aa5da4cStorek /*d*/ dl,
10109aa5da4cStorek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
10119aa5da4cStorek
10129aa5da4cStorek srclin += srclininc;
10139aa5da4cStorek dstlin += dstlininc;
10149aa5da4cStorek }
10159aa5da4cStorek }
10169aa5da4cStorek else
10179aa5da4cStorek {
10189aa5da4cStorek /* Multiple longwords. */
10199aa5da4cStorek lm = leftmask[dstleftignore];
10209aa5da4cStorek rm = rightmask[dstrightignore];
10219aa5da4cStorek nrm = ~rm;
10229aa5da4cStorek nlm = ~lm;
10239aa5da4cStorek if ( longinc == 1 )
10249aa5da4cStorek {
10259aa5da4cStorek /* Left to right. */
10269aa5da4cStorek while ( srclin != srclin2 )
10279aa5da4cStorek {
10289aa5da4cStorek srclong = srclin;
10299aa5da4cStorek dstlong = dstlin;
10309aa5da4cStorek dstlong2 = dstlong + dstlongs;
10319aa5da4cStorek if ( dstrightignore != 0 )
10329aa5da4cStorek --dstlong2;
10339aa5da4cStorek
10349aa5da4cStorek /* Leading edge. */
10359aa5da4cStorek if ( dstleftignore != 0 )
10369aa5da4cStorek {
10379aa5da4cStorek ROP_SRCDST(
10389aa5da4cStorek /*op*/ op,
10399aa5da4cStorek /*pre*/ dl = *dstlong;,
10409aa5da4cStorek /*s*/ *srclong,
10419aa5da4cStorek /*d*/ dl,
10429aa5da4cStorek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
10439aa5da4cStorek ++srclong;
10449aa5da4cStorek ++dstlong;
10459aa5da4cStorek }
10469aa5da4cStorek
10479aa5da4cStorek /* Main rop. */
10489aa5da4cStorek ROP_SRCDST(
10499aa5da4cStorek /*op*/ op,
10509aa5da4cStorek /*pre*/ while ( dstlong != dstlong2 )
10519aa5da4cStorek {,
10529aa5da4cStorek /*s*/ *srclong,
10539aa5da4cStorek /*d*/ *dstlong,
10549aa5da4cStorek /*pst*/ ++srclong;
10559aa5da4cStorek ++dstlong;
10569aa5da4cStorek } )
10579aa5da4cStorek
10589aa5da4cStorek /* Trailing edge. */
10599aa5da4cStorek if ( dstrightignore != 0 )
10609aa5da4cStorek {
10619aa5da4cStorek ROP_SRCDST(
10629aa5da4cStorek /*op*/ op,
10639aa5da4cStorek /*pre*/ dl = *dstlong;,
10649aa5da4cStorek /*s*/ *srclong,
10659aa5da4cStorek /*d*/ dl,
10669aa5da4cStorek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
10679aa5da4cStorek }
10689aa5da4cStorek
10699aa5da4cStorek srclin += srclininc;
10709aa5da4cStorek dstlin += dstlininc;
10719aa5da4cStorek }
10729aa5da4cStorek }
10739aa5da4cStorek else
10749aa5da4cStorek {
10759aa5da4cStorek /* Right to left. */
10769aa5da4cStorek while ( srclin != srclin2 )
10779aa5da4cStorek {
10789aa5da4cStorek srclong = srclin;
10799aa5da4cStorek dstlong = dstlin;
10809aa5da4cStorek dstlong2 = dstlong - dstlongs;
10819aa5da4cStorek if ( dstleftignore != 0 )
10829aa5da4cStorek ++dstlong2;
10839aa5da4cStorek
10849aa5da4cStorek /* Leading edge. */
10859aa5da4cStorek if ( dstrightignore != 0 )
10869aa5da4cStorek {
10879aa5da4cStorek ROP_SRCDST(
10889aa5da4cStorek /*op*/ op,
10899aa5da4cStorek /*pre*/ dl = *dstlong;,
10909aa5da4cStorek /*s*/ *srclong,
10919aa5da4cStorek /*d*/ dl,
10929aa5da4cStorek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
10939aa5da4cStorek --srclong;
10949aa5da4cStorek --dstlong;
10959aa5da4cStorek }
10969aa5da4cStorek
10979aa5da4cStorek /* Main rop. */
10989aa5da4cStorek ROP_SRCDST(
10999aa5da4cStorek /*op*/ op,
11009aa5da4cStorek /*pre*/ while ( dstlong != dstlong2 )
11019aa5da4cStorek {,
11029aa5da4cStorek /*s*/ *srclong,
11039aa5da4cStorek /*d*/ *dstlong,
11049aa5da4cStorek /*pst*/ --srclong;
11059aa5da4cStorek --dstlong;
11069aa5da4cStorek } )
11079aa5da4cStorek
11089aa5da4cStorek /* Trailing edge. */
11099aa5da4cStorek if ( dstleftignore != 0 )
11109aa5da4cStorek {
11119aa5da4cStorek ROP_SRCDST(
11129aa5da4cStorek /*op*/ op,
11139aa5da4cStorek /*pre*/ dl = *dstlong;,
11149aa5da4cStorek /*s*/ *srclong,
11159aa5da4cStorek /*d*/ dl,
11169aa5da4cStorek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
11179aa5da4cStorek }
11189aa5da4cStorek
11199aa5da4cStorek srclin += srclininc;
11209aa5da4cStorek dstlin += dstlininc;
11219aa5da4cStorek }
11229aa5da4cStorek }
11239aa5da4cStorek }
11249aa5da4cStorek }
11259aa5da4cStorek
11269aa5da4cStorek else
11279aa5da4cStorek {
11289aa5da4cStorek /* General case, with shifting and everything. */
11299aa5da4cStorek register u_long sl, prevsl;
11309aa5da4cStorek
11319aa5da4cStorek currrightshift = 32 - prevleftshift;
11329aa5da4cStorek if ( srclongs == 1 && dstlongs == 1 )
11339aa5da4cStorek {
11349aa5da4cStorek /* It fits into a single longword, with a shift. */
11359aa5da4cStorek lm = leftmask[dstleftignore] | rightmask[dstrightignore];
11369aa5da4cStorek nlm = ~lm;
11379aa5da4cStorek if ( srcleftignore > dstleftignore )
11389aa5da4cStorek {
11399aa5da4cStorek while ( srclin != srclin2 )
11409aa5da4cStorek {
11419aa5da4cStorek ROP_SRCDST(
11429aa5da4cStorek /*op*/ op,
11439aa5da4cStorek /*pre*/ dl = *dstlin;,
11449aa5da4cStorek /*s*/ *srclin << prevleftshift,
11459aa5da4cStorek /*d*/ dl,
11469aa5da4cStorek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
11479aa5da4cStorek
11489aa5da4cStorek srclin += srclininc;
11499aa5da4cStorek dstlin += dstlininc;
11509aa5da4cStorek }
11519aa5da4cStorek }
11529aa5da4cStorek else
11539aa5da4cStorek {
11549aa5da4cStorek while ( srclin != srclin2 )
11559aa5da4cStorek {
11569aa5da4cStorek ROP_SRCDST(
11579aa5da4cStorek /*op*/ op,
11589aa5da4cStorek /*pre*/ dl = *dstlin;,
11599aa5da4cStorek /*s*/ *srclin >> currrightshift,
11609aa5da4cStorek /*d*/ dl,
11619aa5da4cStorek /*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
11629aa5da4cStorek
11639aa5da4cStorek srclin += srclininc;
11649aa5da4cStorek dstlin += dstlininc;
11659aa5da4cStorek }
11669aa5da4cStorek }
11679aa5da4cStorek }
11689aa5da4cStorek else
11699aa5da4cStorek {
11709aa5da4cStorek /* Multiple longwords. */
11719aa5da4cStorek lm = leftmask[dstleftignore];
11729aa5da4cStorek rm = rightmask[dstrightignore];
11739aa5da4cStorek nrm = ~rm;
11749aa5da4cStorek nlm = ~lm;
11759aa5da4cStorek if ( longinc == 1 )
11769aa5da4cStorek {
11779aa5da4cStorek /* Left to right. */
11789aa5da4cStorek while ( srclin != srclin2 )
11799aa5da4cStorek {
11809aa5da4cStorek srclong = srclin;
11819aa5da4cStorek dstlong = dstlin;
11829aa5da4cStorek dstlong2 = dstlong + dstlongs;
11839aa5da4cStorek if ( srcleftignore > dstleftignore )
11849aa5da4cStorek prevsl = *srclong++ << prevleftshift;
11859aa5da4cStorek else
11869aa5da4cStorek prevsl = 0;
11879aa5da4cStorek if ( dstrightignore != 0 )
11889aa5da4cStorek --dstlong2;
11899aa5da4cStorek
11909aa5da4cStorek /* Leading edge. */
11919aa5da4cStorek if ( dstleftignore != 0 )
11929aa5da4cStorek {
11939aa5da4cStorek ROP_SRCDST(
11949aa5da4cStorek /*op*/ op,
11959aa5da4cStorek /*pre*/ sl = *srclong;
11969aa5da4cStorek dl = *dstlong;,
11979aa5da4cStorek /*s*/ prevsl | ( sl >> currrightshift ),
11989aa5da4cStorek /*d*/ dl,
11999aa5da4cStorek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
12009aa5da4cStorek prevsl = sl << prevleftshift;
12019aa5da4cStorek ++srclong;
12029aa5da4cStorek ++dstlong;
12039aa5da4cStorek }
12049aa5da4cStorek
12059aa5da4cStorek /* Main rop. */
12069aa5da4cStorek ROP_SRCDST(
12079aa5da4cStorek /*op*/ op,
12089aa5da4cStorek /*pre*/ while ( dstlong != dstlong2 )
12099aa5da4cStorek {
12109aa5da4cStorek sl = *srclong;,
12119aa5da4cStorek /*s*/ prevsl | ( sl >> currrightshift ),
12129aa5da4cStorek /*d*/ *dstlong,
12139aa5da4cStorek /*pst*/ prevsl = sl << prevleftshift;
12149aa5da4cStorek ++srclong;
12159aa5da4cStorek ++dstlong;
12169aa5da4cStorek } )
12179aa5da4cStorek
12189aa5da4cStorek /* Trailing edge. */
12199aa5da4cStorek if ( dstrightignore != 0 )
12209aa5da4cStorek {
12219aa5da4cStorek ROP_SRCDST(
12229aa5da4cStorek /*op*/ op,
12239aa5da4cStorek /*pre*/ dl = *dstlong;,
12249aa5da4cStorek /*s*/ prevsl | ( *srclong >> currrightshift ),
12259aa5da4cStorek /*d*/ dl,
12269aa5da4cStorek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
12279aa5da4cStorek }
12289aa5da4cStorek
12299aa5da4cStorek srclin += srclininc;
12309aa5da4cStorek dstlin += dstlininc;
12319aa5da4cStorek }
12329aa5da4cStorek }
12339aa5da4cStorek else
12349aa5da4cStorek {
12359aa5da4cStorek /* Right to left. */
12369aa5da4cStorek while ( srclin != srclin2 )
12379aa5da4cStorek {
12389aa5da4cStorek srclong = srclin;
12399aa5da4cStorek dstlong = dstlin;
12409aa5da4cStorek dstlong2 = dstlong - dstlongs;
12419aa5da4cStorek if ( srcrightignore > dstrightignore )
12429aa5da4cStorek prevsl = *srclong-- >> currrightshift;
12439aa5da4cStorek else
12449aa5da4cStorek prevsl = 0;
12459aa5da4cStorek if ( dstleftignore != 0 )
12469aa5da4cStorek ++dstlong2;
12479aa5da4cStorek
12489aa5da4cStorek /* Leading edge. */
12499aa5da4cStorek if ( dstrightignore != 0 )
12509aa5da4cStorek {
12519aa5da4cStorek ROP_SRCDST(
12529aa5da4cStorek /*op*/ op,
12539aa5da4cStorek /*pre*/ sl = *srclong;
12549aa5da4cStorek dl = *dstlong;,
12559aa5da4cStorek /*s*/ prevsl | ( sl << prevleftshift ),
12569aa5da4cStorek /*d*/ dl,
12579aa5da4cStorek /*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
12589aa5da4cStorek prevsl = sl >> currrightshift;
12599aa5da4cStorek --srclong;
12609aa5da4cStorek --dstlong;
12619aa5da4cStorek }
12629aa5da4cStorek
12639aa5da4cStorek /* Main rop. */
12649aa5da4cStorek ROP_SRCDST(
12659aa5da4cStorek /*op*/ op,
12669aa5da4cStorek /*pre*/ while ( dstlong != dstlong2 )
12679aa5da4cStorek {
12689aa5da4cStorek sl = *srclong;,
12699aa5da4cStorek /*s*/ prevsl | ( sl << prevleftshift ),
12709aa5da4cStorek /*d*/ *dstlong,
12719aa5da4cStorek /*pst*/ prevsl = sl >> currrightshift;
12729aa5da4cStorek --srclong;
12739aa5da4cStorek --dstlong;
12749aa5da4cStorek } )
12759aa5da4cStorek
12769aa5da4cStorek /* Trailing edge. */
12779aa5da4cStorek if ( dstleftignore != 0 )
12789aa5da4cStorek {
12799aa5da4cStorek ROP_SRCDST(
12809aa5da4cStorek /*op*/ op,
12819aa5da4cStorek /*pre*/ dl = *dstlong;,
12829aa5da4cStorek /*s*/ prevsl | ( *srclong << prevleftshift ),
12839aa5da4cStorek /*d*/ dl,
12849aa5da4cStorek /*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
12859aa5da4cStorek }
12869aa5da4cStorek
12879aa5da4cStorek srclin += srclininc;
12889aa5da4cStorek dstlin += dstlininc;
12899aa5da4cStorek }
12909aa5da4cStorek }
12919aa5da4cStorek }
12929aa5da4cStorek }
12939aa5da4cStorek
12949aa5da4cStorek return 0;
12959aa5da4cStorek }
1296