diff options
Diffstat (limited to 'xorg-server/hw/xfree86/xf4bpp/emulTile.c')
-rw-r--r-- | xorg-server/hw/xfree86/xf4bpp/emulTile.c | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/xorg-server/hw/xfree86/xf4bpp/emulTile.c b/xorg-server/hw/xfree86/xf4bpp/emulTile.c new file mode 100644 index 000000000..2f2a758f2 --- /dev/null +++ b/xorg-server/hw/xfree86/xf4bpp/emulTile.c @@ -0,0 +1,352 @@ +/* + * Copyright IBM Corporation 1987,1988,1989 + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of IBM not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * +*/ + +/* ppc Tile + * P. Shupak 11/87 + * Modified From original ppc Tile + * T. Paquin 9/87 + * Uses private imageFill a bunch of times + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf4bpp.h" +#include "OScompiler.h" +#include "ibmTrace.h" + +static void +DrawFirstTile +( + WindowPtr pWin, /* GJA */ + register PixmapPtr pTile, + register int x, + register int y, + int w, + int h, + int alu, + unsigned long int planes, + int xOffset, + int yOffset +) +{ +register int htarget ; +register int vtarget ; + + if ( xOffset ) { /* Not X-Aligned */ + if ( yOffset ) { /* Nor Y-Aligned */ + htarget = MIN( pTile->drawable.width - xOffset, w ), + vtarget = MIN( pTile->drawable.height - yOffset, h ), + yOffset *= pTile->devKind ; + xf4bppDrawColorImage( pWin,x, y, + htarget, + vtarget, + (unsigned char *)pTile->devPrivate.ptr + yOffset + xOffset, + pTile->devKind, + alu, planes ) ; + if ( w > htarget ) { + w = MIN( w, pTile->drawable.width ) ; + if ( h > vtarget ) { + h = MIN( h, pTile->drawable.height ) ; + xf4bppDrawColorImage( pWin, x, y + vtarget, + htarget, + h - vtarget, + (unsigned char *)pTile->devPrivate.ptr + xOffset, + pTile->devKind, + alu, planes ) ; + xf4bppDrawColorImage( pWin, x + htarget, y, + w - htarget, + vtarget, + (unsigned char *)pTile->devPrivate.ptr + yOffset, + pTile->devKind, + alu, planes ) ; + xf4bppDrawColorImage( pWin, x + htarget, + y + vtarget, + w - htarget, + h - vtarget, + pTile->devPrivate.ptr, + pTile->devKind, + alu, planes ) ; + } + else { /* h <= vtarget */ + xf4bppDrawColorImage( pWin, x + htarget, y, + w - htarget, + vtarget, + (unsigned char *)pTile->devPrivate.ptr + yOffset, + pTile->devKind, + alu, planes ) ; + } + } + else if ( h > vtarget ) { + xf4bppDrawColorImage( pWin, x, y + vtarget, + htarget, + MIN( h, pTile->drawable.height ) - vtarget, + (unsigned char *)pTile->devPrivate.ptr + xOffset, + pTile->devKind, + alu, planes ) ; + vtarget = pTile->drawable.height ; + } + } + else { /* No Y Offset */ + xf4bppDrawColorImage( pWin, x, y, + htarget = MIN( pTile->drawable.width - xOffset, w ), + vtarget = MIN( pTile->drawable.height, h ), + (unsigned char *)pTile->devPrivate.ptr + xOffset, + pTile->devKind, + alu, planes ) ; + if ( w > htarget ) { + xf4bppDrawColorImage( pWin, x + htarget, y, + MIN( pTile->drawable.width, w ) - htarget, + vtarget, + pTile->devPrivate.ptr, + pTile->devKind, + alu, planes ) ; + } + } + } + else if ( yOffset ) { + xf4bppDrawColorImage( pWin, x, y, + htarget = MIN( pTile->drawable.width, w ), + vtarget = MIN( pTile->drawable.height - yOffset, h ), + (unsigned char *)pTile->devPrivate.ptr + ( yOffset * pTile->devKind ), + pTile->devKind, + alu, planes ) ; + if ( h > vtarget ) { + xf4bppDrawColorImage( pWin, x, y + vtarget, + htarget, + MIN( pTile->drawable.height, h ) - vtarget, + pTile->devPrivate.ptr, + pTile->devKind, + alu, planes ) ; + } + } + else { /* NO Offset */ + xf4bppDrawColorImage( pWin, x, y, + htarget = MIN( pTile->drawable.width, w ), + vtarget = MIN( pTile->drawable.height, h ), + pTile->devPrivate.ptr, + pTile->devKind, + alu, planes ) ; + } + + return ; +} + +/* GJA -- + * After finding three kinds of errors in this single function, + * (requiring modifications to be made at at least 10 places, + * I decided to REWRITE the body of the xf4bppTileRect function from scratch. + * This version simply computes all relevant margins in advance, and does + * not try to reuse temporary variables. I leave that to the compiler. + * (This was a maintenance and robustness nightmare anyway.) + * The code is pretty obvious: all margins, coordinates, and numbers of tiles + * are computed before drawing starts. + * Notice that the margins consist of incompletely drawn tiles. Therefore + * we need offsets in the data for the left and upper margins. + * The right and lower margins are also incomplete, but start at offset 0 + * in the data. They just end at awkward offsets. + * The center block, by definition, consists of fully drawn tiles. + * Perhaps we could leave out some if's. But why bother? It would decrease + * robustness. + */ +void +xf4bppTileRect( pWin, pTile, alu, planes, x0, y0, w, h, xSrc, ySrc ) +WindowPtr pWin; /* GJA */ +register PixmapPtr pTile ; +const int alu ; +const unsigned long int planes ; +register int x0, y0, w, h ; +int xSrc ; +int ySrc ; +{ +int xOffset ; +int yOffset ; +int width, height; + +TRACE( ( "xf4bppTileRect(pTile=x%x,alu=x%x,planes=x%02x,x0=%d,y0=%d,w=%d,h=%d,xSrc=%d,ySrc=%d\n", + pTile, alu, planes, x0, y0, w, h, xSrc, ySrc ) ) ; + + switch ( alu ) { + case GXclear: /* 0x0 Zero 0 */ + case GXinvert: /* 0xa NOT dst */ + case GXset: /* 0xf 1 */ + xf4bppFillSolid + ( pWin, 0xFF, alu, planes, x0, y0, w, h ) ; + case GXnoop: /* 0x5 dst */ + return ; + default: + break ; +} + + width = pTile->drawable.width; + if ( ( xOffset = ( x0 - xSrc ) ) > 0 ) + xOffset %= width ; + else + xOffset = width - (( - xOffset ) % width ) ; + if ( xOffset == width ) xOffset = 0; /* For else case */ + + height = pTile->drawable.height; + if ( ( yOffset = ( y0 - ySrc ) ) > 0 ) + yOffset %= height ; + else + yOffset = height - (( - yOffset ) % height ) ; + if ( yOffset == height ) yOffset = 0; /* For else case */ + + switch ( alu ) { + case GXcopyInverted: /* 0xc NOT src */ + case GXcopy: /* 0x3 src */ + /* Special Case Code */ + DrawFirstTile( pWin, pTile, x0, y0, w, h, + alu, planes, xOffset, yOffset ) ; + /* Here We Double The Size Of The BLIT Each Iteration */ + xf4bppReplicateArea( pWin, x0, y0, planes, w, h, + MIN( w, pTile->drawable.width ), + MIN( h, pTile->drawable.height ) ) ; + break ; + case GXnor: /* 0x8 NOT src AND NOT dst */ + case GXandReverse: /* 0x2 src AND NOT dst */ + case GXorReverse: /* 0xb src OR NOT dst */ + case GXnand: /* 0xe NOT src OR NOT dst */ + case GXandInverted: /* 0x4 NOT src AND dst */ + case GXand: /* 0x1 src AND dst */ + case GXequiv: /* 0x9 NOT src XOR dst */ + case GXxor: /* 0x6 src XOR dst */ + case GXorInverted: /* 0xd NOT src OR dst */ + case GXor: /* 0x7 src OR dst */ + default: + { + register unsigned char *data ; + register int hcount, vcount ; /* Number of tiles in center */ + int xcount, ycount; /* Temporaries */ + int x1, y1; /* Left upper corner of center */ + int x2, y2; /* Left upper corner of lower right margin */ + int leftmgn, rightmgn, topmgn, botmgn; /* Margins */ + + int htarget, vtarget ; + + data = pTile->devPrivate.ptr; + + /* Compute the various sizes and coordinates. */ + leftmgn = MIN( w, width - xOffset ) ; + x1 = x0 + leftmgn; + topmgn = MIN( h, height - yOffset ) ; + y1 = y0 + topmgn; + + rightmgn = (w - leftmgn) % width; + hcount = (w - leftmgn) / width; + x2 = x0 + w - rightmgn; + botmgn = (h - topmgn) % height; + vcount = (h - topmgn) / height; + y2 = y0 + h - botmgn; + + /* We'll use yOffset as offset in data. + * This requires yOffset != height (ditto xOffset). + */ + yOffset *= pTile->devKind; + + /* Draw top margin, including corners */ + if ( topmgn ) { + if ( leftmgn ) { + xf4bppDrawColorImage( pWin, x0, y0, leftmgn, topmgn, + data + yOffset + xOffset, + pTile->devKind, alu, planes ) ; + } + for ( xcount = hcount, htarget = x1; + xcount ; + xcount--, htarget += width ) + { + xf4bppDrawColorImage( pWin, htarget, y0, width, topmgn, + data + yOffset, + pTile->devKind, alu, planes ) ; + } + if ( rightmgn ) { + xf4bppDrawColorImage( pWin, x2, y0, rightmgn, topmgn, + data + yOffset, + pTile->devKind, alu, planes ) ; + } + } + + /* Draw bottom margin, including corners */ + if ( botmgn ) { + if ( leftmgn ) { + xf4bppDrawColorImage( pWin, x0, y2, leftmgn, botmgn, + data + xOffset, + pTile->devKind, alu, planes ) ; + } + for ( xcount = hcount, htarget = x1; + xcount ; + xcount--, htarget += width ) + { + xf4bppDrawColorImage( pWin, htarget, y2, width, botmgn, + data, + pTile->devKind, alu, planes ) ; + } + if ( rightmgn ) { + xf4bppDrawColorImage( pWin, x2, y2, rightmgn, botmgn, + data, + pTile->devKind, alu, planes ) ; + } + } + + /* Draw left margin, excluding corners */ + if ( leftmgn ) { + for ( ycount = vcount, vtarget = y1 ; + ycount ; + ycount--, vtarget += height ) + { + xf4bppDrawColorImage( pWin, x0, vtarget, leftmgn, height, + data + xOffset, + pTile->devKind, alu, planes ) ; + } + } + + /* Draw right margin, excluding corners */ + if ( rightmgn ) { + for ( ycount = vcount, vtarget = y1 ; + ycount ; + ycount--, vtarget += height ) + { + xf4bppDrawColorImage( pWin, x2, vtarget, rightmgn, height, + data, + pTile->devKind, alu, planes ) ; + } + } + + /* Draw center consisting of full tiles */ + for ( ycount = vcount, vtarget = y1 ; + ycount ; + ycount--, vtarget += height ) + { + for ( xcount = hcount, htarget = x1 ; + xcount ; + xcount--, htarget += width ) + { + xf4bppDrawColorImage( pWin, htarget, vtarget, width, height, + data, + pTile->devKind, alu, planes ) ; + + } + } + } } /* Block + switch */ +} |