1554 lines
35 KiB
C
1554 lines
35 KiB
C
/* $NetBSD: raster_op.c,v 1.6 1999/01/11 11:08:14 drochner Exp $ */
|
|
|
|
/*-
|
|
* Copyright (c) 1991, 1993
|
|
* The Regents of the University of California. All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to the Computer Systems
|
|
* Engineering Group at Lawrence Berkeley Laboratory and to the University
|
|
* of California at Berkeley by Jef Poskanzer.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the University of
|
|
* California, Berkeley and its contributors.
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* @(#)raster_op.c 8.1 (Berkeley) 6/11/93
|
|
*/
|
|
|
|
/*
|
|
* Bitblit routine for raster library.
|
|
*
|
|
* This raster-op is machined to exacting tolerances by skilled native
|
|
* craftsmen with pride in their work.
|
|
*
|
|
* The various cases are broken down like this:
|
|
*
|
|
* src required
|
|
* 1-bit to 1-bit
|
|
* 1-bit to 2-bits
|
|
* 1-bit to 8-bits
|
|
* 2-bits to 2-bits
|
|
* 2-bits to 8-bits
|
|
* 8-bits to 8-bits
|
|
* no src required
|
|
* 1-bit no-src
|
|
* 2-bits no-src
|
|
* 8-bits no-src
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#ifdef _KERNEL
|
|
#include <dev/rcons/raster.h>
|
|
#else
|
|
#include "raster.h"
|
|
#endif
|
|
|
|
/* CONFIGURE: To save on executable size, you can configure out the seldom-used
|
|
** logical operations. With this variable set, the only operations implemented
|
|
** are: RAS_SRC, RAS_CLEAR, RAS_SET, RAS_INVERT, RAS_XOR, RAS_INVERTSRC.
|
|
*/
|
|
#ifdef _KERNEL
|
|
#define PARTIAL_LOGICAL_OPS
|
|
#endif
|
|
|
|
/* CONFIGURE: bcopy() is supposed to be the ultimately fastest way to move
|
|
** bytes, overlapping or not, ignoring the startup cost. Unfortunately
|
|
** this is not true on some systems. For example, on a Sun 3 running
|
|
** SunOS 3.5, bcopy() is about five times slower than a simple for loop
|
|
** on overlapping copies. And on a 4.1.1 SPARC, bcopy() is about 2/3rds
|
|
** as fast on backwards overlaps. So, only define this if your bcopy is ok.
|
|
*/
|
|
#undef BCOPY_FASTER
|
|
|
|
/* End of configurable definitions. */
|
|
|
|
|
|
/* Definitions. */
|
|
|
|
/* Raster-op macros. These encapsulate the switch statements and so make
|
|
** the source code 16 times smaller. The pre and pst args are code
|
|
** fragments to put before and after the assignment in each case. They
|
|
** can be the beginning and end of a loop. If the pst fragment includes a
|
|
** masked assignment, for example to handle the left or right edge cases,
|
|
** a good optimizing compiler will simplify the boolean expressions very
|
|
** nicely - both cc and gcc on the SPARC will do this.
|
|
*/
|
|
|
|
#ifndef PARTIAL_LOGICAL_OPS
|
|
|
|
#define ROP_DST(op,pre,d,pst) \
|
|
switch ( op ) \
|
|
{ \
|
|
case RAS_CLEAR: \
|
|
pre \
|
|
(d) = 0; \
|
|
pst \
|
|
break; \
|
|
case RAS_INVERT: \
|
|
pre \
|
|
(d) = ~(d); \
|
|
pst \
|
|
break; \
|
|
case RAS_DST: \
|
|
/* noop */ \
|
|
break; \
|
|
case RAS_SET: \
|
|
pre \
|
|
(d) = ~0; \
|
|
pst \
|
|
break; \
|
|
default: \
|
|
return -1; \
|
|
}
|
|
|
|
#define ROP_DSTCOLOR(op,pre,d,c,pst) \
|
|
switch ( op ) \
|
|
{ \
|
|
case RAS_CLEAR: \
|
|
pre \
|
|
(d) = 0; \
|
|
pst \
|
|
break; \
|
|
case RAS_INVERT: \
|
|
pre \
|
|
(d) = ~(d); \
|
|
pst \
|
|
break; \
|
|
case RAS_DST: \
|
|
/* noop */ \
|
|
break; \
|
|
case RAS_SET: \
|
|
pre \
|
|
(d) = (c); \
|
|
pst \
|
|
break; \
|
|
default: \
|
|
return -1; \
|
|
}
|
|
|
|
#define ROP_SRCDST(op,pre,s,d,pst) \
|
|
switch ( op ) \
|
|
{ \
|
|
case RAS_NOTOR: \
|
|
pre \
|
|
(d) = ~( (s) | (d) ); \
|
|
pst \
|
|
break; \
|
|
case RAS_NOTSRC_AND_DST: \
|
|
pre \
|
|
(d) = ~(s) & (d); \
|
|
pst \
|
|
break; \
|
|
case RAS_INVERTSRC: \
|
|
pre \
|
|
(d) = ~(s); \
|
|
pst \
|
|
break; \
|
|
case RAS_SRC_AND_NOTDST: \
|
|
pre \
|
|
(d) = (s) & ~(d); \
|
|
pst \
|
|
break; \
|
|
case RAS_XOR: \
|
|
pre \
|
|
(d) = (s) ^ (d); \
|
|
pst \
|
|
break; \
|
|
case RAS_NOTAND: \
|
|
pre \
|
|
(d) = ~( (s) & (d) ); \
|
|
pst \
|
|
break; \
|
|
case RAS_AND: \
|
|
pre \
|
|
(d) = (s) & (d); \
|
|
pst \
|
|
break; \
|
|
case RAS_NOTXOR: \
|
|
pre \
|
|
(d) = ~( (s) ^ (d) ); \
|
|
pst \
|
|
break; \
|
|
case RAS_NOTSRC_OR_DST: \
|
|
pre \
|
|
(d) = ~(s) | (d); \
|
|
pst \
|
|
break; \
|
|
case RAS_SRC: \
|
|
pre \
|
|
(d) = (s); \
|
|
pst \
|
|
break; \
|
|
case RAS_SRC_OR_NOTDST: \
|
|
pre \
|
|
(d) = (s) | ~(d); \
|
|
pst \
|
|
break; \
|
|
case RAS_OR: \
|
|
pre \
|
|
(d) = (s) | (d); \
|
|
pst \
|
|
break; \
|
|
default: \
|
|
return -1; \
|
|
}
|
|
|
|
#define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
|
|
switch ( op ) \
|
|
{ \
|
|
case RAS_NOTOR: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = ~( (c) | (d) ); \
|
|
else \
|
|
(d) = ~(d); \
|
|
pst \
|
|
break; \
|
|
case RAS_NOTSRC_AND_DST: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = ~(c) & (d); \
|
|
pst \
|
|
break; \
|
|
case RAS_INVERTSRC: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = ~(c); \
|
|
else \
|
|
(d) = ~0; \
|
|
pst \
|
|
break; \
|
|
case RAS_SRC_AND_NOTDST: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = (c) & ~(d); \
|
|
else \
|
|
(d) = 0; \
|
|
pst \
|
|
break; \
|
|
case RAS_XOR: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = (c) ^ (d); \
|
|
pst \
|
|
break; \
|
|
case RAS_NOTAND: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = ~( (c) & (d) ); \
|
|
else \
|
|
(d) = ~0; \
|
|
pst \
|
|
break; \
|
|
case RAS_AND: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = (c) & (d); \
|
|
else \
|
|
(d) = 0; \
|
|
pst \
|
|
break; \
|
|
case RAS_NOTXOR: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = ~( (c) ^ (d) ); \
|
|
else \
|
|
(d) = ~(d); \
|
|
pst \
|
|
break; \
|
|
case RAS_NOTSRC_OR_DST: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = ~(c) | (d); \
|
|
else \
|
|
(d) = ~0; \
|
|
pst \
|
|
break; \
|
|
case RAS_SRC: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = (c); \
|
|
else \
|
|
(d) = 0; \
|
|
pst \
|
|
break; \
|
|
case RAS_SRC_OR_NOTDST: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = (c) | ~(d); \
|
|
else \
|
|
(d) = ~(d); \
|
|
pst \
|
|
break; \
|
|
case RAS_OR: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = (c) | (d); \
|
|
pst \
|
|
break; \
|
|
default: \
|
|
return -1; \
|
|
}
|
|
|
|
#else /*PARTIAL_LOGICAL_OPS*/
|
|
|
|
#define ROP_DST(op,pre,d,pst) \
|
|
switch ( op ) \
|
|
{ \
|
|
case RAS_CLEAR: \
|
|
pre \
|
|
(d) = 0; \
|
|
pst \
|
|
break; \
|
|
case RAS_INVERT: \
|
|
pre \
|
|
(d) = ~(d); \
|
|
pst \
|
|
break; \
|
|
case RAS_SET: \
|
|
pre \
|
|
(d) = ~0; \
|
|
pst \
|
|
break; \
|
|
default: \
|
|
return -1; \
|
|
}
|
|
|
|
#define ROP_DSTCOLOR(op,pre,d,c,pst) \
|
|
switch ( op ) \
|
|
{ \
|
|
case RAS_CLEAR: \
|
|
pre \
|
|
(d) = 0; \
|
|
pst \
|
|
break; \
|
|
case RAS_INVERT: \
|
|
pre \
|
|
(d) = ~(d); \
|
|
pst \
|
|
break; \
|
|
case RAS_SET: \
|
|
pre \
|
|
(d) = (c); \
|
|
pst \
|
|
break; \
|
|
default: \
|
|
return -1; \
|
|
}
|
|
|
|
#define ROP_SRCDST(op,pre,s,d,pst) \
|
|
switch ( op ) \
|
|
{ \
|
|
case RAS_INVERTSRC: \
|
|
pre \
|
|
(d) = ~(s); \
|
|
pst \
|
|
break; \
|
|
case RAS_XOR: \
|
|
pre \
|
|
(d) = (s) ^ (d); \
|
|
pst \
|
|
break; \
|
|
case RAS_SRC: \
|
|
pre \
|
|
(d) = (s); \
|
|
pst \
|
|
break; \
|
|
default: \
|
|
return -1; \
|
|
}
|
|
|
|
#define ROP_SRCDSTCOLOR(op,pre,s,d,c,pst) \
|
|
switch ( op ) \
|
|
{ \
|
|
case RAS_INVERTSRC: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = ~(c); \
|
|
else \
|
|
(d) = ~0; \
|
|
pst \
|
|
break; \
|
|
case RAS_XOR: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = (c) ^ (d); \
|
|
pst \
|
|
break; \
|
|
case RAS_SRC: \
|
|
pre \
|
|
if ( s ) \
|
|
(d) = (c); \
|
|
else \
|
|
(d) = 0; \
|
|
pst \
|
|
break; \
|
|
default: \
|
|
return -1; \
|
|
}
|
|
|
|
#endif /*PARTIAL_LOGICAL_OPS*/
|
|
|
|
|
|
/* Variables. */
|
|
|
|
static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
|
|
/* CLEAR INVERT DST SET */
|
|
|
|
#ifdef MSBIT_FIRST
|
|
|
|
u_int32_t raster_bitmask[32] = {
|
|
0x80000000, 0x40000000, 0x20000000, 0x10000000,
|
|
0x08000000, 0x04000000, 0x02000000, 0x01000000,
|
|
0x00800000, 0x00400000, 0x00200000, 0x00100000,
|
|
0x00080000, 0x00040000, 0x00020000, 0x00010000,
|
|
0x00008000, 0x00004000, 0x00002000, 0x00001000,
|
|
0x00000800, 0x00000400, 0x00000200, 0x00000100,
|
|
0x00000080, 0x00000040, 0x00000020, 0x00000010,
|
|
0x00000008, 0x00000004, 0x00000002, 0x00000001 };
|
|
|
|
#ifdef MSBYTE_FIRST
|
|
static u_int32_t leftmask[32] = {
|
|
0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
|
|
0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
|
|
0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
|
|
0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
|
|
0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
|
|
0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
|
|
0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
|
|
0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
|
|
static u_int32_t rightmask[32] = {
|
|
0x00000000, 0x00000001, 0x00000003, 0x00000007,
|
|
0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
|
|
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
|
|
0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
|
|
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
|
|
0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
|
|
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
|
|
0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
|
|
|
|
#define LSOP <<
|
|
#define RSOP >>
|
|
#endif /*MSBYTE_FIRST*/
|
|
|
|
#else /*MSBIT_FIRST*/
|
|
|
|
u_int32_t raster_bitmask[32] = {
|
|
0x00000001, 0x00000002, 0x00000004, 0x00000008,
|
|
0x00000010, 0x00000020, 0x00000040, 0x00000080,
|
|
0x00000100, 0x00000200, 0x00000400, 0x00000800,
|
|
0x00001000, 0x00002000, 0x00004000, 0x00008000,
|
|
0x00010000, 0x00020000, 0x00040000, 0x00080000,
|
|
0x00100000, 0x00200000, 0x00400000, 0x00800000,
|
|
0x01000000, 0x02000000, 0x04000000, 0x08000000,
|
|
0x10000000, 0x20000000, 0x40000000, 0x80000000 };
|
|
|
|
#ifndef MSBYTE_FIRST
|
|
static u_int32_t leftmask[32] = {
|
|
0x00000000, 0x00000001, 0x00000003, 0x00000007,
|
|
0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
|
|
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
|
|
0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
|
|
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
|
|
0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
|
|
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
|
|
0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff };
|
|
static u_int32_t rightmask[32] = {
|
|
0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
|
|
0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
|
|
0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
|
|
0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
|
|
0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
|
|
0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
|
|
0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
|
|
0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe };
|
|
#define LSOP >>
|
|
#define RSOP <<
|
|
#endif /*not MSBYTE_FIRST*/
|
|
|
|
#endif /*MSBIT_FIRST*/
|
|
|
|
/* (The odd combinations MSBIT+~MSBYTE and ~MSBIT+MSBYTE could be added.) */
|
|
|
|
#ifdef MSBYTE_FIRST
|
|
static u_int32_t bytemask[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
|
|
#ifdef RCONS_2BPP
|
|
static u_int32_t twobitmask[16] = {
|
|
0xc0000000, 0x30000000, 0x0c000000, 0x03000000,
|
|
0x00c00000, 0x00300000, 0x000c0000, 0x00030000,
|
|
0x0000c000, 0x00003000, 0x00000c00, 0x00000300,
|
|
0x000000c0, 0x00000030, 0x0000000c, 0x00000003 };
|
|
#endif /* RCONS_2BPP */
|
|
#else /*MSBYTE_FIRST*/
|
|
static u_int32_t bytemask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
|
|
#ifdef RCONS_2BPP
|
|
static u_int32_t twobitmask[16] = {
|
|
0x00000003, 0x0000000c, 0x00000030, 0x000000c0,
|
|
0x00000300, 0x00000c00, 0x00003000, 0x0000c000,
|
|
0x00030000, 0x000c0000, 0x00300000, 0x00c00000,
|
|
0x03000000, 0x0c000000, 0x30000000, 0xc0000000 };
|
|
#endif /* RCONS_2BPP */
|
|
#endif /*MSBYTE_FIRST*/
|
|
|
|
|
|
/* Forward routines. */
|
|
|
|
static int raster_blit __P((struct raster *, u_int32_t *, int, int, int,
|
|
struct raster *, u_int32_t *, int, int, int,
|
|
int, int));
|
|
|
|
/* Raster operations. */
|
|
|
|
/* Performs a bitblit. Returns 0 on success, -1 on failure. */
|
|
int
|
|
raster_op( dst, dx, dy, w, h, rop, src, sx, sy )
|
|
struct raster* dst;
|
|
int dx, dy, w, h, rop;
|
|
struct raster* src;
|
|
int sx, sy;
|
|
{
|
|
if ( dst == (struct raster*) 0 )
|
|
return -1; /* no destination */
|
|
|
|
if ( needsrc[RAS_GETOP( rop )] )
|
|
{
|
|
/* Two-operand blit. */
|
|
if ( src == (struct raster*) 0 )
|
|
return -1; /* no source */
|
|
|
|
/* Clip against source. */
|
|
if ( sx < 0 )
|
|
{
|
|
w += sx;
|
|
sx = 0;
|
|
}
|
|
if ( sy < 0 )
|
|
{
|
|
h += sy;
|
|
sy = 0;
|
|
}
|
|
if ( sx + w > src->width )
|
|
w = src->width - sx;
|
|
if ( sy + h > src->height )
|
|
h = src->height - sy;
|
|
|
|
/* Clip against dest. */
|
|
if ( dx < 0 )
|
|
{
|
|
w += dx;
|
|
sx -= dx;
|
|
dx = 0;
|
|
}
|
|
if ( dy < 0 )
|
|
{
|
|
h += dy;
|
|
sy -= dy;
|
|
dy = 0;
|
|
}
|
|
if ( dx + w > dst->width )
|
|
w = dst->width - dx;
|
|
if ( dy + h > dst->height )
|
|
h = dst->height - dy;
|
|
|
|
if ( w <= 0 || h <= 0 )
|
|
return 0; /* nothing to do */
|
|
|
|
return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy );
|
|
}
|
|
|
|
/* No source necessary - one-operand blit. */
|
|
if ( src != (struct raster*) 0 )
|
|
return -1; /* unwanted source */
|
|
|
|
/* Clip against dest. */
|
|
if ( dx < 0 )
|
|
{
|
|
w += dx;
|
|
dx = 0;
|
|
}
|
|
if ( dy < 0 )
|
|
{
|
|
h += dy;
|
|
dy = 0;
|
|
}
|
|
if ( dx + w > dst->width )
|
|
w = dst->width - dx;
|
|
if ( dy + h > dst->height )
|
|
h = dst->height - dy;
|
|
|
|
if ( w <= 0 || h <= 0 )
|
|
return 0; /* nothing to do */
|
|
|
|
return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop );
|
|
}
|
|
|
|
/* Semi-public routine to do a bitblit without clipping. Returns 0 on
|
|
** success, -1 on failure.
|
|
*/
|
|
int
|
|
raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy )
|
|
struct raster* dst;
|
|
int dx, dy, w, h, rop;
|
|
struct raster* src;
|
|
int sx, sy;
|
|
{
|
|
int op;
|
|
|
|
op = RAS_GETOP( rop );
|
|
|
|
if ( src->depth == 1 )
|
|
{
|
|
/* One-bit to ? blit. */
|
|
if ( dst->depth == 1 )
|
|
{
|
|
/* One to one blit. */
|
|
u_int32_t* srclin1;
|
|
u_int32_t* dstlin1;
|
|
int srcleftignore, srcrightignore, srclongs;
|
|
int dstleftignore, dstrightignore, dstlongs;
|
|
|
|
srclin1 = RAS_ADDR( src, sx, sy );
|
|
dstlin1 = RAS_ADDR( dst, dx, dy );
|
|
|
|
#ifdef BCOPY_FASTER
|
|
/* Special-case full-width to full-width copies. */
|
|
if ( op == RAS_SRC && src->width == w && dst->width == w &&
|
|
src->linelongs == dst->linelongs && src->linelongs == w >> 5 )
|
|
{
|
|
bcopy(
|
|
(char*) srclin1, (char*) dstlin1,
|
|
h * src->linelongs * sizeof(u_int32_t) );
|
|
return 0;
|
|
}
|
|
#endif /*BCOPY_FASTER*/
|
|
|
|
srcleftignore = ( sx & 31 );
|
|
srclongs = ( srcleftignore + w + 31 ) >> 5;
|
|
srcrightignore = ( srclongs * 32 - w - srcleftignore ) & 31;
|
|
dstleftignore = ( dx & 31 );
|
|
dstlongs = ( dstleftignore + w + 31 ) >> 5;
|
|
dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
|
|
|
|
return raster_blit(
|
|
src, srclin1, srcleftignore, srcrightignore, srclongs,
|
|
dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
|
|
}
|
|
|
|
#ifdef RCONS_2BPP
|
|
else if ( dst->depth == 2 )
|
|
{
|
|
/* One to two, using the color in the rop. */
|
|
u_int32_t* srclin1;
|
|
u_int32_t* dstlin1;
|
|
u_int32_t* srclin2;
|
|
u_int32_t* srclin;
|
|
u_int32_t* dstlin;
|
|
register u_int32_t* srclong;
|
|
register u_int32_t* dstlong;
|
|
register u_int32_t color, dl;
|
|
register int srcbit, dstbyte, i;
|
|
|
|
color = RAS_GETCOLOR( rop );
|
|
if ( color == 0 )
|
|
color = 3;
|
|
|
|
/* Make 32 bits of color so we can do the ROP without shifting. */
|
|
color |= (( color << 30 ) | ( color << 28 ) | ( color << 26 )
|
|
| ( color << 24 ) | ( color << 22 ) | ( color << 20 )
|
|
| ( color << 18 ) | ( color << 16 ) | ( color << 14 )
|
|
| ( color << 12 ) | ( color << 10 ) | ( color << 8 )
|
|
| ( color << 6 ) | ( color << 4 ) | ( color << 2 ));
|
|
|
|
/* Don't have to worry about overlapping blits here. */
|
|
srclin1 = RAS_ADDR( src, sx, sy );
|
|
srclin2 = srclin1 + h * src->linelongs;
|
|
dstlin1 = RAS_ADDR( dst, dx, dy );
|
|
srclin = srclin1;
|
|
dstlin = dstlin1;
|
|
|
|
while ( srclin != srclin2 )
|
|
{
|
|
srclong = srclin;
|
|
srcbit = sx & 31;
|
|
dstlong = dstlin;
|
|
dstbyte = dx & 15;
|
|
i = w;
|
|
|
|
/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
|
|
ROP_SRCDSTCOLOR(
|
|
/*op*/ op,
|
|
/*pre*/ while ( i > 0 )
|
|
{
|
|
dl = *dstlong;,
|
|
/*s*/ *srclong & raster_bitmask[srcbit],
|
|
/*d*/ dl,
|
|
/*c*/ color,
|
|
/*pst*/ *dstlong = ( *dstlong & ~twobitmask[dstbyte] ) |
|
|
( dl & twobitmask[dstbyte] );
|
|
if ( srcbit == 31 )
|
|
{
|
|
srcbit = 0;
|
|
++srclong;
|
|
}
|
|
else
|
|
++srcbit;
|
|
if ( dstbyte == 15 )
|
|
{
|
|
dstbyte = 0;
|
|
++dstlong;
|
|
}
|
|
else
|
|
++dstbyte;
|
|
--i;
|
|
} )
|
|
|
|
srclin += src->linelongs;
|
|
dstlin += dst->linelongs;
|
|
}
|
|
}
|
|
#endif /* RCONS_2BPP */
|
|
else
|
|
{
|
|
/* One to eight, using the color in the rop. This could
|
|
** probably be sped up by handling each four-bit source nybble
|
|
** as a group, indexing into a 16-element runtime-constructed
|
|
** table of longwords.
|
|
*/
|
|
u_int32_t* srclin1;
|
|
u_int32_t* dstlin1;
|
|
u_int32_t* srclin2;
|
|
u_int32_t* srclin;
|
|
u_int32_t* dstlin;
|
|
register u_int32_t* srclong;
|
|
register u_int32_t* dstlong;
|
|
register u_int32_t color, dl;
|
|
register int srcbit, dstbyte, i;
|
|
|
|
color = RAS_GETCOLOR( rop );
|
|
if ( color == 0 )
|
|
color = 255;
|
|
|
|
/* Make 32 bits of color so we can do the ROP without shifting. */
|
|
color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
|
|
|
|
/* Don't have to worry about overlapping blits here. */
|
|
srclin1 = RAS_ADDR( src, sx, sy );
|
|
srclin2 = srclin1 + h * src->linelongs;
|
|
dstlin1 = RAS_ADDR( dst, dx, dy );
|
|
srclin = srclin1;
|
|
dstlin = dstlin1;
|
|
while ( srclin != srclin2 )
|
|
{
|
|
srclong = srclin;
|
|
srcbit = sx & 31;
|
|
dstlong = dstlin;
|
|
dstbyte = dx & 3;
|
|
i = w;
|
|
|
|
/* WARNING: this code is KNOWN TO FAIL on Sun 3's / CG2's. */
|
|
ROP_SRCDSTCOLOR(
|
|
/*op*/ op,
|
|
/*pre*/ while ( i > 0 )
|
|
{
|
|
dl = *dstlong;,
|
|
/*s*/ *srclong & raster_bitmask[srcbit],
|
|
/*d*/ dl,
|
|
/*c*/ color,
|
|
/*pst*/ *dstlong = ( *dstlong & ~bytemask[dstbyte] ) |
|
|
( dl & bytemask[dstbyte] );
|
|
if ( srcbit == 31 )
|
|
{
|
|
srcbit = 0;
|
|
++srclong;
|
|
}
|
|
else
|
|
++srcbit;
|
|
if ( dstbyte == 3 )
|
|
{
|
|
dstbyte = 0;
|
|
++dstlong;
|
|
}
|
|
else
|
|
++dstbyte;
|
|
--i;
|
|
} )
|
|
|
|
srclin += src->linelongs;
|
|
dstlin += dst->linelongs;
|
|
}
|
|
}
|
|
}
|
|
#ifdef RCONS_2BPP
|
|
else if ( src->depth == 2 )
|
|
{
|
|
/* Two to two blit. */
|
|
u_int32_t* srclin1;
|
|
u_int32_t* dstlin1;
|
|
int srcleftignore, srcrightignore, srclongs;
|
|
int dstleftignore, dstrightignore, dstlongs;
|
|
|
|
srclin1 = RAS_ADDR( src, sx, sy );
|
|
dstlin1 = RAS_ADDR( dst, dx, dy );
|
|
|
|
srcleftignore = ( sx & 15 ) * 2;
|
|
srclongs = ( srcleftignore + w * 2 + 31 ) >> 5;
|
|
srcrightignore = ( srclongs * 32 - w * 2 - srcleftignore ) & 31;
|
|
dstleftignore = ( dx & 15 ) * 2;
|
|
dstlongs = ( dstleftignore + w * 2 + 31 ) >> 5;
|
|
dstrightignore = ( dstlongs * 32 - w * 2 - dstleftignore ) & 31;
|
|
|
|
return raster_blit(
|
|
src, srclin1, srcleftignore, srcrightignore, srclongs,
|
|
dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
|
|
}
|
|
#endif /* RCONS_2BPP */
|
|
|
|
else
|
|
{
|
|
/* Eight to eight blit. */
|
|
u_int32_t* srclin1;
|
|
u_int32_t* dstlin1;
|
|
int srcleftignore, srcrightignore, srclongs;
|
|
int dstleftignore, dstrightignore, dstlongs;
|
|
|
|
if ( dst->depth != 8 )
|
|
return -1; /* depth mismatch */
|
|
|
|
srclin1 = RAS_ADDR( src, sx, sy );
|
|
dstlin1 = RAS_ADDR( dst, dx, dy );
|
|
|
|
#ifdef BCOPY_FASTER
|
|
/* Special-case full-width to full-width copies. */
|
|
if ( op == RAS_SRC && src->width == w && dst->width == w &&
|
|
src->linelongs == dst->linelongs && src->linelongs == w >> 2 )
|
|
{
|
|
bcopy( (char*) srclin1, (char*) dstlin1,
|
|
h * src->linelongs * sizeof(u_int32_t) );
|
|
return 0;
|
|
}
|
|
#endif /*BCOPY_FASTER*/
|
|
|
|
srcleftignore = ( sx & 3 ) * 8;
|
|
srclongs = ( srcleftignore + w * 8 + 31 ) >> 5;
|
|
srcrightignore = ( srclongs * 32 - w * 8 - srcleftignore ) & 31;
|
|
dstleftignore = ( dx & 3 ) * 8;
|
|
dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
|
|
dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
|
|
|
|
return raster_blit(
|
|
src, srclin1, srcleftignore, srcrightignore, srclongs,
|
|
dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Semi-public routine to do a no-src bitblit without clipping. Returns 0
|
|
** on success, -1 on failure.
|
|
*/
|
|
int
|
|
raster_op_nosrc_noclip( dst, dx, dy, w, h, rop )
|
|
struct raster* dst;
|
|
int dx, dy, w, h, rop;
|
|
{
|
|
int op;
|
|
|
|
op = RAS_GETOP( rop );
|
|
|
|
if ( dst->depth == 1 )
|
|
{
|
|
/* One-bit no-src blit. */
|
|
u_int32_t* dstlin1;
|
|
u_int32_t* dstlin2;
|
|
u_int32_t* dstlin;
|
|
int dstleftignore, dstrightignore, dstlongs;
|
|
u_int32_t dl, lm, nlm, rm, nrm;
|
|
register u_int32_t* dstlong2;
|
|
register u_int32_t* dstlong;
|
|
|
|
dstlin1 = RAS_ADDR( dst, dx, dy );
|
|
|
|
#ifdef BCOPY_FASTER
|
|
/* Special-case full-width clears. */
|
|
if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
|
|
{
|
|
bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_int32_t) );
|
|
return 0;
|
|
}
|
|
#endif /*BCOPY_FASTER*/
|
|
|
|
dstleftignore = ( dx & 31 );
|
|
dstlongs = ( dstleftignore + w + 31 ) >> 5;
|
|
dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
|
|
|
|
dstlin2 = dstlin1 + h * dst->linelongs;
|
|
dstlin = dstlin1;
|
|
|
|
if ( dstlongs == 1 )
|
|
{
|
|
/* It fits into a single longword. */
|
|
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
|
|
nlm = ~lm;
|
|
while ( dstlin != dstlin2 )
|
|
{
|
|
ROP_DST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlin;,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
|
|
|
|
dstlin += dst->linelongs;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lm = leftmask[dstleftignore];
|
|
rm = rightmask[dstrightignore];
|
|
nrm = ~rm;
|
|
nlm = ~lm;
|
|
|
|
while ( dstlin != dstlin2 )
|
|
{
|
|
dstlong = dstlin;
|
|
dstlong2 = dstlong + dstlongs;
|
|
if ( dstrightignore != 0 )
|
|
--dstlong2;
|
|
|
|
/* Leading edge. */
|
|
if ( dstleftignore != 0 )
|
|
{
|
|
ROP_DST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
|
|
++dstlong;
|
|
}
|
|
|
|
/* Main rop. */
|
|
ROP_DST(
|
|
/*op*/ op,
|
|
/*pre*/ while ( dstlong != dstlong2 )
|
|
{,
|
|
/*d*/ *dstlong,
|
|
/*pst*/ ++dstlong;
|
|
} )
|
|
|
|
/* Trailing edge. */
|
|
if ( dstrightignore != 0 )
|
|
{
|
|
ROP_DST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
|
|
}
|
|
|
|
dstlin += dst->linelongs;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef RCONS_2BPP
|
|
else if ( dst->depth == 2 )
|
|
{
|
|
/* Two-bit no-src blit. */
|
|
register u_int32_t color;
|
|
u_int32_t* dstlin1;
|
|
u_int32_t* dstlin2;
|
|
u_int32_t* dstlin;
|
|
int dstleftignore, dstrightignore, dstlongs;
|
|
u_int32_t dl, lm, nlm, rm, nrm;
|
|
register u_int32_t* dstlong2;
|
|
register u_int32_t* dstlong;
|
|
|
|
dstlin1 = RAS_ADDR( dst, dx, dy );
|
|
|
|
#ifdef BCOPY_FASTER
|
|
/* Special-case full-width clears. */
|
|
if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
|
|
{
|
|
bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_int32_t) );
|
|
return 0;
|
|
}
|
|
#endif /*BCOPY_FASTER*/
|
|
|
|
color = RAS_GETCOLOR( rop );
|
|
if ( color == 0 )
|
|
color = 3;
|
|
|
|
/* Make 32 bits of color so we can do the ROP without shifting. */
|
|
color |= (( color << 30 ) | ( color << 28 ) | ( color << 26 )
|
|
| ( color << 24 ) | ( color << 22 ) | ( color << 20 )
|
|
| ( color << 18 ) | ( color << 16 ) | ( color << 14 )
|
|
| ( color << 12 ) | ( color << 10 ) | ( color << 8 )
|
|
| ( color << 6 ) | ( color << 4 ) | ( color << 2 ));
|
|
|
|
dstleftignore = ( dx & 15 ) * 2;
|
|
dstlongs = ( dstleftignore + w * 2 + 31 ) >> 5;
|
|
dstrightignore = ( dstlongs * 32 - w * 2 - dstleftignore ) & 31;
|
|
|
|
dstlin2 = dstlin1 + h * dst->linelongs;
|
|
dstlin = dstlin1;
|
|
|
|
if ( dstlongs == 1 )
|
|
{
|
|
/* It fits into a single longword. */
|
|
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
|
|
nlm = ~lm;
|
|
while ( dstlin != dstlin2 )
|
|
{
|
|
ROP_DST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlin;,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
|
|
|
|
dstlin += dst->linelongs;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lm = leftmask[dstleftignore];
|
|
rm = rightmask[dstrightignore];
|
|
nrm = ~rm;
|
|
nlm = ~lm;
|
|
|
|
while ( dstlin != dstlin2 )
|
|
{
|
|
dstlong = dstlin;
|
|
dstlong2 = dstlong + dstlongs;
|
|
if ( dstrightignore != 0 )
|
|
--dstlong2;
|
|
|
|
/* Leading edge. */
|
|
if ( dstleftignore != 0 )
|
|
{
|
|
ROP_DST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
|
|
++dstlong;
|
|
}
|
|
|
|
/* Main rop. */
|
|
ROP_DST(
|
|
/*op*/ op,
|
|
/*pre*/ while ( dstlong != dstlong2 )
|
|
{,
|
|
/*d*/ *dstlong,
|
|
/*pst*/ ++dstlong;
|
|
} )
|
|
|
|
/* Trailing edge. */
|
|
if ( dstrightignore != 0 )
|
|
{
|
|
ROP_DST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
|
|
}
|
|
|
|
dstlin += dst->linelongs;
|
|
}
|
|
}
|
|
}
|
|
#endif /* RCONS_2BPP */
|
|
else
|
|
{
|
|
/* Eight-bit no-src blit. */
|
|
register u_int32_t color;
|
|
u_int32_t* dstlin1;
|
|
u_int32_t* dstlin2;
|
|
u_int32_t* dstlin;
|
|
int dstleftignore, dstrightignore, dstlongs;
|
|
u_int32_t dl, lm, nlm, rm, nrm;
|
|
register u_int32_t* dstlong2;
|
|
register u_int32_t* dstlong;
|
|
|
|
dstlin1 = RAS_ADDR( dst, dx, dy );
|
|
|
|
#ifdef BCOPY_FASTER
|
|
/* Special-case full-width clears. */
|
|
if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 )
|
|
{
|
|
bzero( (char*) dstlin1, h * dst->linelongs * sizeof(u_int32_t) );
|
|
return 0;
|
|
}
|
|
#endif /*BCOPY_FASTER*/
|
|
|
|
color = RAS_GETCOLOR( rop );
|
|
if ( color == 0 )
|
|
color = 255;
|
|
|
|
/* Make 32 bits of color so we can do the ROP without shifting. */
|
|
color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
|
|
|
|
dstleftignore = ( dx & 3 ) * 8;
|
|
dstlongs = ( dstleftignore + w * 8 + 31 ) >> 5;
|
|
dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
|
|
|
|
dstlin2 = dstlin1 + h * dst->linelongs;
|
|
dstlin = dstlin1;
|
|
|
|
if ( dstlongs == 1 )
|
|
{
|
|
/* It fits into a single longword. */
|
|
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
|
|
nlm = ~lm;
|
|
while ( dstlin != dstlin2 )
|
|
{
|
|
ROP_DSTCOLOR(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlin;,
|
|
/*d*/ dl,
|
|
/*c*/ color,
|
|
/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
|
|
|
|
dstlin += dst->linelongs;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lm = leftmask[dstleftignore];
|
|
rm = rightmask[dstrightignore];
|
|
nrm = ~rm;
|
|
nlm = ~lm;
|
|
while ( dstlin != dstlin2 )
|
|
{
|
|
dstlong = dstlin;
|
|
dstlong2 = dstlong + dstlongs;
|
|
if ( dstrightignore != 0 )
|
|
--dstlong2;
|
|
|
|
/* Leading edge. */
|
|
if ( dstleftignore != 0 )
|
|
{
|
|
ROP_DSTCOLOR(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*d*/ dl,
|
|
/*c*/ color,
|
|
/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
|
|
++dstlong;
|
|
}
|
|
|
|
/* Main rop. */
|
|
ROP_DSTCOLOR(
|
|
/*op*/ op,
|
|
/*pre*/ while ( dstlong != dstlong2 )
|
|
{,
|
|
/*d*/ *dstlong,
|
|
/*c*/ color,
|
|
/*pst*/ ++dstlong;
|
|
} )
|
|
|
|
/* Trailing edge. */
|
|
if ( dstrightignore != 0 )
|
|
{
|
|
ROP_DSTCOLOR(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*d*/ dl,
|
|
/*c*/ color,
|
|
/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
|
|
}
|
|
|
|
dstlin += dst->linelongs;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* This is a general bitblit routine, handling overlapping source and
|
|
** destination. It's used for both the 1-to-1 and 8-to-8 cases.
|
|
*/
|
|
static int
|
|
raster_blit( src, srclin1, srcleftignore, srcrightignore, srclongs, dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op )
|
|
struct raster* src;
|
|
u_int32_t* srclin1;
|
|
int srcleftignore, srcrightignore, srclongs;
|
|
struct raster* dst;
|
|
u_int32_t* dstlin1;
|
|
int dstleftignore, dstrightignore, dstlongs;
|
|
int h, op;
|
|
{
|
|
u_int32_t* srclin2;
|
|
u_int32_t* dstlin2;
|
|
int srclininc, dstlininc;
|
|
u_int32_t* srclin;
|
|
u_int32_t* dstlin;
|
|
register int prevleftshift, currrightshift;
|
|
int longinc;
|
|
register u_int32_t* srclong;
|
|
register u_int32_t* dstlong;
|
|
register u_int32_t* dstlong2;
|
|
register u_int32_t dl, lm, nlm, rm, nrm;
|
|
|
|
prevleftshift = ( srcleftignore - dstleftignore ) & 31;
|
|
|
|
srclin2 = srclin1 + h * src->linelongs;
|
|
dstlin2 = dstlin1 + h * dst->linelongs;
|
|
srclininc = src->linelongs;
|
|
dstlininc = dst->linelongs;
|
|
longinc = 1;
|
|
|
|
/* Check for overlaps. */
|
|
if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) ||
|
|
( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) )
|
|
{
|
|
/* Horizontal overlap. Should we reverse? */
|
|
if ( srclin1 < dstlin1 )
|
|
{
|
|
longinc = -1;
|
|
srclin1 += srclongs - 1;
|
|
srclin2 += srclongs - 1;
|
|
dstlin1 += dstlongs - 1;
|
|
}
|
|
}
|
|
else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) ||
|
|
( srclin1 >= dstlin1 && srclin1 < dstlin2 ) )
|
|
{
|
|
/* Vertical overlap. Should we reverse? */
|
|
if ( srclin1 < dstlin1 )
|
|
{
|
|
srclin2 = srclin1 - srclininc;
|
|
srclin1 += ( h - 1 ) * srclininc;
|
|
dstlin1 += ( h - 1 ) * dstlininc;
|
|
srclininc = -srclininc;
|
|
dstlininc = -dstlininc;
|
|
}
|
|
}
|
|
srclin = srclin1;
|
|
dstlin = dstlin1;
|
|
|
|
if ( prevleftshift == 0 )
|
|
{
|
|
/* The bits line up, no shifting necessary. */
|
|
if ( dstlongs == 1 )
|
|
{
|
|
/* It all fits into a single longword. */
|
|
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
|
|
nlm = ~lm;
|
|
while ( srclin != srclin2 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlin;,
|
|
/*s*/ *srclin,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
|
|
|
|
srclin += srclininc;
|
|
dstlin += dstlininc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Multiple longwords. */
|
|
lm = leftmask[dstleftignore];
|
|
rm = rightmask[dstrightignore];
|
|
nrm = ~rm;
|
|
nlm = ~lm;
|
|
if ( longinc == 1 )
|
|
{
|
|
/* Left to right. */
|
|
while ( srclin != srclin2 )
|
|
{
|
|
srclong = srclin;
|
|
dstlong = dstlin;
|
|
dstlong2 = dstlong + dstlongs;
|
|
if ( dstrightignore != 0 )
|
|
--dstlong2;
|
|
|
|
/* Leading edge. */
|
|
if ( dstleftignore != 0 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*s*/ *srclong,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
|
|
++srclong;
|
|
++dstlong;
|
|
}
|
|
|
|
/* Main rop. */
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ while ( dstlong != dstlong2 )
|
|
{,
|
|
/*s*/ *srclong,
|
|
/*d*/ *dstlong,
|
|
/*pst*/ ++srclong;
|
|
++dstlong;
|
|
} )
|
|
|
|
/* Trailing edge. */
|
|
if ( dstrightignore != 0 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*s*/ *srclong,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
|
|
}
|
|
|
|
srclin += srclininc;
|
|
dstlin += dstlininc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Right to left. */
|
|
while ( srclin != srclin2 )
|
|
{
|
|
srclong = srclin;
|
|
dstlong = dstlin;
|
|
dstlong2 = dstlong - dstlongs;
|
|
if ( dstleftignore != 0 )
|
|
++dstlong2;
|
|
|
|
/* Leading edge. */
|
|
if ( dstrightignore != 0 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*s*/ *srclong,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
|
|
--srclong;
|
|
--dstlong;
|
|
}
|
|
|
|
/* Main rop. */
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ while ( dstlong != dstlong2 )
|
|
{,
|
|
/*s*/ *srclong,
|
|
/*d*/ *dstlong,
|
|
/*pst*/ --srclong;
|
|
--dstlong;
|
|
} )
|
|
|
|
/* Trailing edge. */
|
|
if ( dstleftignore != 0 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*s*/ *srclong,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
|
|
}
|
|
|
|
srclin += srclininc;
|
|
dstlin += dstlininc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
/* General case, with shifting and everything. */
|
|
register u_int32_t sl, prevsl;
|
|
|
|
currrightshift = 32 - prevleftshift;
|
|
if ( srclongs == 1 && dstlongs == 1 )
|
|
{
|
|
/* It fits into a single longword, with a shift. */
|
|
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
|
|
nlm = ~lm;
|
|
if ( srcleftignore > dstleftignore )
|
|
{
|
|
while ( srclin != srclin2 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlin;,
|
|
/*s*/ *srclin LSOP prevleftshift,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
|
|
|
|
srclin += srclininc;
|
|
dstlin += dstlininc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while ( srclin != srclin2 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlin;,
|
|
/*s*/ *srclin RSOP currrightshift,
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
|
|
|
|
srclin += srclininc;
|
|
dstlin += dstlininc;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Multiple longwords. */
|
|
lm = leftmask[dstleftignore];
|
|
rm = rightmask[dstrightignore];
|
|
nrm = ~rm;
|
|
nlm = ~lm;
|
|
if ( longinc == 1 )
|
|
{
|
|
/* Left to right. */
|
|
while ( srclin != srclin2 )
|
|
{
|
|
srclong = srclin;
|
|
dstlong = dstlin;
|
|
dstlong2 = dstlong + dstlongs;
|
|
if ( srcleftignore > dstleftignore )
|
|
prevsl = *srclong++ LSOP prevleftshift;
|
|
else
|
|
prevsl = 0;
|
|
if ( dstrightignore != 0 )
|
|
--dstlong2;
|
|
|
|
/* Leading edge. */
|
|
if ( dstleftignore != 0 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ sl = *srclong;
|
|
dl = *dstlong;,
|
|
/*s*/ prevsl | ( sl RSOP currrightshift ),
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
|
|
prevsl = sl LSOP prevleftshift;
|
|
++srclong;
|
|
++dstlong;
|
|
}
|
|
|
|
/* Main rop. */
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ while ( dstlong != dstlong2 )
|
|
{
|
|
sl = *srclong;,
|
|
/*s*/ prevsl | ( sl RSOP currrightshift ),
|
|
/*d*/ *dstlong,
|
|
/*pst*/ prevsl = sl LSOP prevleftshift;
|
|
++srclong;
|
|
++dstlong;
|
|
} )
|
|
|
|
/* Trailing edge. */
|
|
if ( dstrightignore != 0 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*s*/ prevsl | ( *srclong RSOP currrightshift ),
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
|
|
}
|
|
|
|
srclin += srclininc;
|
|
dstlin += dstlininc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Right to left. */
|
|
while ( srclin != srclin2 )
|
|
{
|
|
srclong = srclin;
|
|
dstlong = dstlin;
|
|
dstlong2 = dstlong - dstlongs;
|
|
if ( srcrightignore > dstrightignore )
|
|
prevsl = *srclong-- RSOP currrightshift;
|
|
else
|
|
prevsl = 0;
|
|
if ( dstleftignore != 0 )
|
|
++dstlong2;
|
|
|
|
/* Leading edge. */
|
|
if ( dstrightignore != 0 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ sl = *srclong;
|
|
dl = *dstlong;,
|
|
/*s*/ prevsl | ( sl LSOP prevleftshift ),
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
|
|
prevsl = sl RSOP currrightshift;
|
|
--srclong;
|
|
--dstlong;
|
|
}
|
|
|
|
/* Main rop. */
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ while ( dstlong != dstlong2 )
|
|
{
|
|
sl = *srclong;,
|
|
/*s*/ prevsl | ( sl LSOP prevleftshift ),
|
|
/*d*/ *dstlong,
|
|
/*pst*/ prevsl = sl RSOP currrightshift;
|
|
--srclong;
|
|
--dstlong;
|
|
} )
|
|
|
|
/* Trailing edge. */
|
|
if ( dstleftignore != 0 )
|
|
{
|
|
ROP_SRCDST(
|
|
/*op*/ op,
|
|
/*pre*/ dl = *dstlong;,
|
|
/*s*/ prevsl | ( *srclong LSOP prevleftshift ),
|
|
/*d*/ dl,
|
|
/*pst*/ *dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
|
|
}
|
|
|
|
srclin += srclininc;
|
|
dstlin += dstlininc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|