#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: raster_op.c,v 1.19 2012/01/31 04:28:02 matt Exp $");
#include <sys/types.h>
#ifdef _KERNEL
#include "opt_rcons.h"
#include <dev/rcons/raster.h>
#else
#include "raster.h"
#endif
#ifdef _KERNEL
#define PARTIAL_LOGICAL_OPS
#endif
#undef BCOPY_FASTER
#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: \
\
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: \
\
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
#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
static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
#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
#else
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
#endif
#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
#ifdef RCONS_4BPP
static u_int32_t fourbitmask[8] = {
0xf0000000, 0x0f000000,
0x00f00000, 0x000f0000,
0x0000f000, 0x00000f00,
0x000000f0, 0x0000000f };
#endif
#ifdef RCONS_16BPP
static u_int32_t twobytemask[2] = { 0xffff0000, 0x0000ffff };
#endif
#else
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
#ifdef RCONS_4BPP
static u_int32_t fourbitmask[16] = {
0x0000000f, 0x000000f0,
0x00000f00, 0x0000f000,
0x000f0000, 0x00f00000,
0x0f000000, 0xf0000000 };
#endif
#ifdef RCONS_16BPP
static u_int32_t twobytemask[2] = { 0x0000ffff, 0xffff0000 };
#endif
#endif
static int raster_blit(struct raster *, u_int32_t *, int, int, int,
struct raster *, u_int32_t *, int, int, int,
int, int);
int
raster_op(struct raster* dst, int dx, int dy, int w, int h, int rop,
struct raster* src, int sx, int sy)
{
if ( dst == (struct raster*) 0 )
return -1;
if ( needsrc[RAS_GETOP( rop )] )
{
if ( src == (struct raster*) 0 )
return -1;
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;
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;
return raster_op_noclip( dst, dx, dy, w, h, rop, src, sx, sy );
}
if ( src != (struct raster*) 0 )
return -1;
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;
return raster_op_nosrc_noclip( dst, dx, dy, w, h, rop );
}
int
raster_op_noclip(struct raster* dst, int dx, int dy, int w, int h, int rop,
struct raster* src, int sx, int sy)
{
int op;
op = RAS_GETOP( rop );
if ( src->depth == 1 )
{
if ( dst->depth == 1 )
{
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
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
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 )
{
u_int32_t* srclin1;
u_int32_t* dstlin1;
u_int32_t* srclin2;
u_int32_t* srclin;
u_int32_t* dstlin;
u_int32_t* srclong;
u_int32_t* dstlong;
u_int32_t color, dl;
int srcbit, dstbyte, i;
color = RAS_GETCOLOR( rop );
if ( color == 0 )
color = 3;
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 ));
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;
ROP_SRCDSTCOLOR(
op,
while ( i > 0 )
{
dl = *dstlong;,
*srclong & raster_bitmask[srcbit],
dl,
color,
*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
#ifdef RCONS_4BPP
else if ( dst->depth == 4 )
{
u_int32_t* srclin1;
u_int32_t* dstlin1;
u_int32_t* srclin2;
u_int32_t* srclin;
u_int32_t* dstlin;
u_int32_t* srclong;
u_int32_t* dstlong;
u_int32_t color, dl;
int srcbit, dstbyte, i;
color = RAS_GETCOLOR( rop );
if ( color == 0 )
color = 15;
color |= (( color << 28 ) | ( color << 24 )
| ( color << 20 ) | ( color << 16 )
| ( color << 12 ) | ( color << 8 )
| ( color << 4 ));
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 & 7;
i = w;
ROP_SRCDSTCOLOR(
op,
while ( i > 0 )
{
dl = *dstlong;,
*srclong & raster_bitmask[srcbit],
dl,
color,
*dstlong = ( *dstlong & ~fourbitmask[dstbyte] ) |
( dl & fourbitmask[dstbyte] );
if ( srcbit == 31 )
{
srcbit = 0;
++srclong;
}
else
++srcbit;
if ( dstbyte == 7 )
{
dstbyte = 0;
++dstlong;
}
else
++dstbyte;
--i;
} )
srclin += src->linelongs;
dstlin += dst->linelongs;
}
}
#endif
else if ( dst->depth == 8 )
{
u_int32_t* srclin1;
u_int32_t* dstlin1;
u_int32_t* srclin2;
u_int32_t* srclin;
u_int32_t* dstlin;
u_int32_t* srclong;
u_int32_t* dstlong;
u_int32_t color, dl;
int srcbit, dstbyte, i;
color = RAS_GETCOLOR( rop );
if ( color == 0 )
color = 255;
color |= ( color << 24 ) | ( color << 16 ) | ( color << 8 );
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;
ROP_SRCDSTCOLOR(
op,
while ( i > 0 )
{
dl = *dstlong;,
*srclong & raster_bitmask[srcbit],
dl,
color,
*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_16BPP
else
{
u_int32_t* srclin1;
u_int32_t* dstlin1;
u_int32_t* srclin2;
u_int32_t* srclin;
u_int32_t* dstlin;
u_int32_t* srclong;
u_int32_t* dstlong;
u_int32_t color, dl;
int srcbit, dstbyte, i;
color = RAS_GETCOLOR( rop );
if ( color == 0 )
color = 0xffff;
color |= ( color << 16 );
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 & 1;
i = w;
ROP_SRCDSTCOLOR(
op,
while ( i > 0 )
{
dl = *dstlong;,
*srclong & raster_bitmask[srcbit],
dl,
color,
*dstlong = ( *dstlong & ~twobytemask[dstbyte] ) |
( dl & twobytemask[dstbyte] );
if ( srcbit == 31 )
{
srcbit = 0;
++srclong;
}
else
++srcbit;
if ( dstbyte == 1 )
{
dstbyte = 0;
++dstlong;
}
else
++dstbyte;
--i;
} )
srclin += src->linelongs;
dstlin += dst->linelongs;
}
}
#endif
}
#ifdef RCONS_2BPP
else if ( src->depth == 2 )
{
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
#ifdef RCONS_4BPP
else if ( src->depth == 4 )
{
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 & 7 ) * 4;
srclongs = ( srcleftignore + w * 4 + 31 ) >> 5;
srcrightignore = ( srclongs * 32 - w * 4 - srcleftignore ) & 31;
dstleftignore = ( dx & 7 ) * 4;
dstlongs = ( dstleftignore + w * 4 + 31 ) >> 5;
dstrightignore = ( dstlongs * 32 - w * 4 - dstleftignore ) & 31;
return raster_blit(
src, srclin1, srcleftignore, srcrightignore, srclongs,
dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
}
#endif
else if ( src->depth == 8 )
{
u_int32_t* srclin1;
u_int32_t* dstlin1;
int srcleftignore, srcrightignore, srclongs;
int dstleftignore, dstrightignore, dstlongs;
if ( dst->depth != 8 )
return -1;
srclin1 = RAS_ADDR( src, sx, sy );
dstlin1 = RAS_ADDR( dst, dx, dy );
#ifdef BCOPY_FASTER
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
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 );
}
#ifdef RCONS_16BPP
else
{
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 & 1 ) * 16;
srclongs = ( srcleftignore + w * 16 + 31 ) >> 5;
srcrightignore = ( srclongs * 32 - w * 16 - srcleftignore ) & 31;
dstleftignore = ( dx & 1 ) * 16;
dstlongs = ( dstleftignore + w * 16 + 31 ) >> 5;
dstrightignore = ( dstlongs * 32 - w * 16 - dstleftignore ) & 31;
return raster_blit(
src, srclin1, srcleftignore, srcrightignore, srclongs,
dst, dstlin1, dstleftignore, dstrightignore, dstlongs, h, op );
}
#endif
return 0;
}
int
raster_op_nosrc_noclip(struct raster* dst,
int dx, int dy, int w, int h, int rop)
{
int op;
op = RAS_GETOP( rop );
if ( dst->depth == 1 )
{
u_int32_t* dstlin1;
u_int32_t* dstlin2;
u_int32_t* dstlin;
int dstleftignore, dstrightignore, dstlongs;
u_int32_t dl, lm, nlm, rm, nrm;
u_int32_t* dstlong2;
u_int32_t* dstlong;
dstlin1 = RAS_ADDR( dst, dx, dy );
#ifdef BCOPY_FASTER
if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 5 )
{
memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
return 0;
}
#endif
dstleftignore = ( dx & 31 );
dstlongs = ( dstleftignore + w + 31 ) >> 5;
dstrightignore = ( dstlongs * 32 - w - dstleftignore ) & 31;
dstlin2 = dstlin1 + h * dst->linelongs;
dstlin = dstlin1;
if ( dstlongs == 1 )
{
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
nlm = ~lm;
while ( dstlin != dstlin2 )
{
ROP_DST(
op,
dl = *dstlin;,
dl,
*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;
if ( dstleftignore != 0 )
{
ROP_DST(
op,
dl = *dstlong;,
dl,
*dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
++dstlong;
}
ROP_DST(
op,
while ( dstlong != dstlong2 )
{,
*dstlong,
++dstlong;
} )
if ( dstrightignore != 0 )
{
ROP_DST(
op,
dl = *dstlong;,
dl,
*dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
}
dstlin += dst->linelongs;
}
}
}
#ifdef RCONS_2BPP
else if ( dst->depth == 2 )
{
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;
u_int32_t* dstlong2;
u_int32_t* dstlong;
dstlin1 = RAS_ADDR( dst, dx, dy );
#ifdef BCOPY_FASTER
if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 4 )
{
memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
return 0;
}
#endif
color = RAS_GETCOLOR( rop );
if ( color == 0 )
color = 3;
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 )
{
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
nlm = ~lm;
while ( dstlin != dstlin2 )
{
ROP_DST(
op,
dl = *dstlin;,
dl,
*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;
if ( dstleftignore != 0 )
{
ROP_DST(
op,
dl = *dstlong;,
dl,
*dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
++dstlong;
}
ROP_DST(
op,
while ( dstlong != dstlong2 )
{,
*dstlong,
++dstlong;
} )
if ( dstrightignore != 0 )
{
ROP_DST(
op,
dl = *dstlong;,
dl,
*dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
}
dstlin += dst->linelongs;
}
}
}
#endif
#ifdef RCONS_4BPP
else if ( dst->depth == 4 )
{
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;
u_int32_t* dstlong2;
u_int32_t* dstlong;
dstlin1 = RAS_ADDR( dst, dx, dy );
#ifdef BCOPY_FASTER
if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 3 )
{
memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
return 0;
}
#endif
color = RAS_GETCOLOR( rop );
if ( color == 0 )
color = 15;
color |= (( color << 28 ) | ( color << 24 )
| ( color << 20 ) | ( color << 16 )
| ( color << 12 ) | ( color << 8 )
| ( color << 4 ));
dstleftignore = ( dx & 7 ) * 4;
dstlongs = ( dstleftignore + w * 4 + 31 ) >> 5;
dstrightignore = ( dstlongs * 32 - w * 4 - dstleftignore ) & 31;
dstlin2 = dstlin1 + h * dst->linelongs;
dstlin = dstlin1;
if ( dstlongs == 1 )
{
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
nlm = ~lm;
while ( dstlin != dstlin2 )
{
ROP_DST(
op,
dl = *dstlin;,
dl,
*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;
if ( dstleftignore != 0 )
{
ROP_DST(
op,
dl = *dstlong;,
dl,
*dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
++dstlong;
}
ROP_DST(
op,
while ( dstlong != dstlong2 )
{,
*dstlong,
++dstlong;
} )
if ( dstrightignore != 0 )
{
ROP_DST(
op,
dl = *dstlong;,
dl,
*dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
}
dstlin += dst->linelongs;
}
}
}
#endif
else if ( dst->depth == 8)
{
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;
u_int32_t* dstlong2;
u_int32_t* dstlong;
dstlin1 = RAS_ADDR( dst, dx, dy );
#ifdef BCOPY_FASTER
if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 2 )
{
memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
return 0;
}
#endif
color = RAS_GETCOLOR( rop );
if ( color == 0 )
color = 255;
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 )
{
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
nlm = ~lm;
while ( dstlin != dstlin2 )
{
ROP_DSTCOLOR(
op,
dl = *dstlin;,
dl,
color,
*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;
if ( dstleftignore != 0 )
{
ROP_DSTCOLOR(
op,
dl = *dstlong;,
dl,
color,
*dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
++dstlong;
}
ROP_DSTCOLOR(
op,
while ( dstlong != dstlong2 )
{,
*dstlong,
color,
++dstlong;
} )
if ( dstrightignore != 0 )
{
ROP_DSTCOLOR(
op,
dl = *dstlong;,
dl,
color,
*dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
}
dstlin += dst->linelongs;
}
}
}
#ifdef RCONS_16BPP
else
{
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;
u_int32_t* dstlong2;
u_int32_t* dstlong;
dstlin1 = RAS_ADDR( dst, dx, dy );
#ifdef BCOPY_FASTER
if ( op == RAS_CLEAR && dst->width == w && dst->linelongs == w >> 1 )
{
memset( (char*) dstlin1, 0, h * dst->linelongs * sizeof(u_int32_t) );
return 0;
}
#endif
color = RAS_GETCOLOR( rop );
if ( color == 0 )
color = 0xffff;
color |= ( color << 16 );
dstleftignore = ( dx & 1 ) * 16;
dstlongs = ( dstleftignore + w * 16 + 31 ) >> 5;
dstrightignore = ( dstlongs * 32 - w * 8 - dstleftignore ) & 31;
dstlin2 = dstlin1 + h * dst->linelongs;
dstlin = dstlin1;
if ( dstlongs == 1 )
{
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
nlm = ~lm;
while ( dstlin != dstlin2 )
{
ROP_DSTCOLOR(
op,
dl = *dstlin;,
dl,
color,
*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;
if ( dstleftignore != 0 )
{
ROP_DSTCOLOR(
op,
dl = *dstlong;,
dl,
color,
*dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
++dstlong;
}
ROP_DSTCOLOR(
op,
while ( dstlong != dstlong2 )
{,
*dstlong,
color,
++dstlong;
} )
if ( dstrightignore != 0 )
{
ROP_DSTCOLOR(
op,
dl = *dstlong;,
dl,
color,
*dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
}
dstlin += dst->linelongs;
}
}
}
#endif
return 0;
}
static int
raster_blit(
struct raster* src, uint32_t* srclin1,
int srcleftignore, int srcrightignore, int srclongs,
struct raster* dst,
uint32_t* dstlin1,
int dstleftignore, int dstrightignore, int dstlongs,
int h, int op)
{
u_int32_t* srclin2;
u_int32_t* dstlin2;
int srclininc, dstlininc;
u_int32_t* srclin;
u_int32_t* dstlin;
int prevleftshift, currrightshift;
int longinc;
u_int32_t* srclong;
u_int32_t* dstlong;
u_int32_t* dstlong2;
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;
if ( ( dstlin1 >= srclin1 && dstlin1 < srclin1 + srclongs ) ||
( srclin1 >= dstlin1 && srclin1 < dstlin1 + dstlongs ) )
{
if ( srclin1 < dstlin1 )
{
longinc = -1;
srclin1 += srclongs - 1;
srclin2 += srclongs - 1;
dstlin1 += dstlongs - 1;
}
}
else if ( ( dstlin1 >= srclin1 && dstlin1 < srclin2 ) ||
( srclin1 >= dstlin1 && srclin1 < dstlin2 ) )
{
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 )
{
if ( dstlongs == 1 )
{
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
nlm = ~lm;
while ( srclin != srclin2 )
{
ROP_SRCDST(
op,
dl = *dstlin;,
*srclin,
dl,
*dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
srclin += srclininc;
dstlin += dstlininc;
}
}
else
{
lm = leftmask[dstleftignore];
rm = rightmask[dstrightignore];
nrm = ~rm;
nlm = ~lm;
if ( longinc == 1 )
{
while ( srclin != srclin2 )
{
srclong = srclin;
dstlong = dstlin;
dstlong2 = dstlong + dstlongs;
if ( dstrightignore != 0 )
--dstlong2;
if ( dstleftignore != 0 )
{
ROP_SRCDST(
op,
dl = *dstlong;,
*srclong,
dl,
*dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
++srclong;
++dstlong;
}
ROP_SRCDST(
op,
while ( dstlong != dstlong2 )
{,
*srclong,
*dstlong,
++srclong;
++dstlong;
} )
if ( dstrightignore != 0 )
{
ROP_SRCDST(
op,
dl = *dstlong;,
*srclong,
dl,
*dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
}
srclin += srclininc;
dstlin += dstlininc;
}
}
else
{
while ( srclin != srclin2 )
{
srclong = srclin;
dstlong = dstlin;
dstlong2 = dstlong - dstlongs;
if ( dstleftignore != 0 )
++dstlong2;
if ( dstrightignore != 0 )
{
ROP_SRCDST(
op,
dl = *dstlong;,
*srclong,
dl,
*dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
--srclong;
--dstlong;
}
ROP_SRCDST(
op,
while ( dstlong != dstlong2 )
{,
*srclong,
*dstlong,
--srclong;
--dstlong;
} )
if ( dstleftignore != 0 )
{
ROP_SRCDST(
op,
dl = *dstlong;,
*srclong,
dl,
*dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
}
srclin += srclininc;
dstlin += dstlininc;
}
}
}
}
else
{
u_int32_t sl, prevsl;
currrightshift = 32 - prevleftshift;
if ( srclongs == 1 && dstlongs == 1 )
{
lm = leftmask[dstleftignore] | rightmask[dstrightignore];
nlm = ~lm;
if ( srcleftignore > dstleftignore )
{
while ( srclin != srclin2 )
{
ROP_SRCDST(
op,
dl = *dstlin;,
*srclin LSOP prevleftshift,
dl,
*dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
srclin += srclininc;
dstlin += dstlininc;
}
}
else
{
while ( srclin != srclin2 )
{
ROP_SRCDST(
op,
dl = *dstlin;,
*srclin RSOP currrightshift,
dl,
*dstlin = ( *dstlin & lm ) | ( dl & nlm ); )
srclin += srclininc;
dstlin += dstlininc;
}
}
}
else
{
lm = leftmask[dstleftignore];
rm = rightmask[dstrightignore];
nrm = ~rm;
nlm = ~lm;
if ( longinc == 1 )
{
while ( srclin != srclin2 )
{
srclong = srclin;
dstlong = dstlin;
dstlong2 = dstlong + dstlongs;
if ( srcleftignore > dstleftignore )
prevsl = *srclong++ LSOP prevleftshift;
else
prevsl = 0;
if ( dstrightignore != 0 )
--dstlong2;
if ( dstleftignore != 0 )
{
ROP_SRCDST(
op,
sl = *srclong;
dl = *dstlong;,
prevsl | ( sl RSOP currrightshift ),
dl,
*dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
prevsl = sl LSOP prevleftshift;
++srclong;
++dstlong;
}
ROP_SRCDST(
op,
while ( dstlong != dstlong2 )
{
sl = *srclong;,
prevsl | ( sl RSOP currrightshift ),
*dstlong,
prevsl = sl LSOP prevleftshift;
++srclong;
++dstlong;
} )
if ( dstrightignore != 0 )
{
ROP_SRCDST(
op,
dl = *dstlong;,
prevsl | ( *srclong RSOP currrightshift ),
dl,
*dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
}
srclin += srclininc;
dstlin += dstlininc;
}
}
else
{
while ( srclin != srclin2 )
{
srclong = srclin;
dstlong = dstlin;
dstlong2 = dstlong - dstlongs;
if ( srcrightignore > dstrightignore )
prevsl = *srclong-- RSOP currrightshift;
else
prevsl = 0;
if ( dstleftignore != 0 )
++dstlong2;
if ( dstrightignore != 0 )
{
ROP_SRCDST(
op,
sl = *srclong;
dl = *dstlong;,
prevsl | ( sl LSOP prevleftshift ),
dl,
*dstlong = ( dl & nrm ) | ( *dstlong & rm ); )
prevsl = sl RSOP currrightshift;
--srclong;
--dstlong;
}
ROP_SRCDST(
op,
while ( dstlong != dstlong2 )
{
sl = *srclong;,
prevsl | ( sl LSOP prevleftshift ),
*dstlong,
prevsl = sl RSOP currrightshift;
--srclong;
--dstlong;
} )
if ( dstleftignore != 0 )
{
ROP_SRCDST(
op,
dl = *dstlong;,
prevsl | ( *srclong LSOP prevleftshift ),
dl,
*dstlong = ( *dstlong & lm ) | ( dl & nlm ); )
}
srclin += srclininc;
dstlin += dstlininc;
}
}
}
}
return 0;
}