354 lines
10 KiB
C
354 lines
10 KiB
C
/*
|
|
* 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.
|
|
*
|
|
*/
|
|
/* $XConsortium: emulTile.c /main/4 1996/02/21 17:56:23 kaleb $ */
|
|
|
|
/* 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 */
|
|
}
|