Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

749 lines
20 KiB

/*++
Copyright (c) 1992-1995 Microsoft Corporation
Module Name:
BitBlt.c
Abstract:
This module hooks DrvBitBlt and DrvCopyBits for the Jaguar VXL board.
The following operations are supported for DrvBitBlt:
SRCCOPY from screen to screen
BLACKNESS
WHITNESS
PATCOPY when the Brush pattern is a solid color
NOTPATCOPY when the Brush pattern is a solid color
DrvCopyBits copies the data if source and dest surfaces are the
frame buffer.
Environment:
User mode.
Revision History:
--*/
#include "driver.h"
//
//Tmp savescreenbits vars
//
BOOL
DrvpIntersectRect(
IN PRECTL Rectl1,
IN PRECTL Rectl2,
OUT PRECTL DestRectl
)
/*++
Routine Description:
This routine checks to see if the two specified retangles intersect.
N.B. This routine is adopted from a routine written by darrinm.
Arguments:
Rectl1 - Supplies the coordinates of the first rectangle.
Rectl2 - Supplies the coordinates of the second rectangle.
DestRectl - Supplies the coordinates of the utput rectangle.
Return Value:
A value of TRUE is returned if the rectangles intersect. Otherwise,
a value of FALSE is returned.
--*/
{
//
// Compute the maximum left edge and the minimum right edge.
//
DestRectl->left = max(Rectl1->left, Rectl2->left);
DestRectl->right = min(Rectl1->right, Rectl2->right);
//
// If the minimum right edge is greater than the maximum left edge,
// then the rectanges may intersect. Otherwise, they do not intersect.
//
if (DestRectl->left < DestRectl->right) {
//
// Compute the maximum top edge and the minimum bottom edge.
//
DestRectl->top = max(Rectl1->top, Rectl2->top);
DestRectl->bottom = min(Rectl1->bottom, Rectl2->bottom);
//
// If the minimum bottom edge is greater than the maximum top
// edge, then the rectanges intersect. Otherwise, they do not
// intersect.
//
if (DestRectl->top < DestRectl->bottom) {
return TRUE;
}
}
return FALSE;
}
VOID
DrvpFillRectangle(
IN PRECTL DstRect,
IN ULONG Color
)
/*++
Routine Description:
Place a solid color fill command into the FIFO
Arguments:
DestRect - Rectangle to fill
Color - Fill color
Return Value:
Status of operation.
--*/
{
ULONG X,Y;
ULONG XYCmd;
ULONG DstAdr;
//
// calculate size of the fill.
//
X = (ULONG)(DstRect->right - DstRect->left);
Y = (ULONG)(DstRect->bottom - DstRect->top);
Y &= 0x3FF;
XYCmd=(JAGUAR_SOLID_FILL << XYCMD_CMD_SHIFT) | (Y << XYCMD_Y_SHIFT) | X;
DstAdr= Vxl.JaguarScreenX*DstRect->top + (DstRect->left << Vxl.ColorModeShift);
//
// Write command to the FIFO.
//
FifoWrite(DstAdr,Color,XYCmd);
}
VOID
DrvpSolidFill(
IN PRECTL DstRect,
IN CLIPOBJ *pco,
IN ULONG Color
)
/*++
Routine Description:
This routine fills the unclipped areas of the destination rectangle with
the given color.
Arguments:
DstRect - Destination Rectangle
pco - Clipping area.
Color - Color to fill with.
Return Value:
None.
--*/
{
RECTL BltRectl;
ENUMRECTLIST ClipEnum;
BOOL MoreClipRects;
ULONG ClipRegions;
BYTE FixedComplexity;
//
// Figure out the real clipping complexity
//
if (pco == (CLIPOBJ *)NULL) {
FixedComplexity = DC_TRIVIAL;
} else {
FixedComplexity = pco->iDComplexity;
}
switch (FixedComplexity) {
//
// Entire destination is to be updated.
// Proceed with the Solid Fill.
//
case DC_TRIVIAL:
DrvpFillRectangle(DstRect, // Target rectangle
Color); // Color
break;
//
// Only one clip region.
//
case DC_RECT:
//
// only do the Fill if there is an intersection
//
if (DrvpIntersectRect(DstRect,&pco->rclBounds,&BltRectl)) {
DrvpFillRectangle(&BltRectl, // Target rectangle
Color); // Color
}
break;
//
// Multiple clip regions.
//
case DC_COMPLEX:
CLIPOBJ_cEnumStart(pco,FALSE,CT_RECTANGLES,CD_ANY,BB_RECT_LIMIT);
do {
//
// Get list of clip rectangles.
//
MoreClipRects = CLIPOBJ_bEnum(pco,sizeof(ClipEnum),(PVOID)&ClipEnum);
for (ClipRegions=0;ClipRegions<ClipEnum.c;ClipRegions++) {
//
// If the rectangles intersect do the fill
//
if (DrvpIntersectRect(DstRect,
&ClipEnum.arcl[ClipRegions],
&BltRectl)) {
DrvpFillRectangle(&BltRectl, // Target rectangle
Color); // Color
}
}
} while (MoreClipRects);
break;
} // end switch complexity
}
VOID
DrvpBitBlt(
IN PRECTL DstRect,
IN PPOINTL SrcPoint,
IN BOOL BltDir
)
/*++
Routine Description:
Place a BitBlt command into the FIFO
Arguments:
DstRect - Destination Rectangle
SrcPoint - Source Point
BltDir - FALSE = Left to Right Top to Bottom.
TRUE = Right to Left Bottom to Top
Return Value:
None.
--*/
{
ULONG X,Y;
ULONG XYCmd;
ULONG SrcAdr;
ULONG DstAdr;
X = DstRect->right - DstRect->left;
Y = DstRect->bottom - DstRect->top;
if (BltDir) {
//
// This is a Right To Left Bottom to Top BitBlt
// Src and Dest adr are the first byte of the pixel to
// be moved. That is the most significant byte of the pixel.
// The Rectangle excludes the bottom right corner which
// is the start address for these sort of bitblts.
// One is substracted from the Y to exclude the last line.
// One is substracted from the X after addjusting it to the
// size of the pixel. So the address of the next pixel is computed
// and then one is substracted which gives the address of the
// most significant byte of the previous pixel.
//
DstAdr=Vxl.JaguarScreenX*(DstRect->bottom-1) + ((DstRect->right) << Vxl.ColorModeShift) -1;
SrcAdr=Vxl.JaguarScreenX*(SrcPoint->y+Y-1) + ((SrcPoint->x+X) << Vxl.ColorModeShift) -1;
XYCmd=JAGUAR_BITBLT_RIGHTLEFT << XYCMD_CMD_SHIFT;
} else {
//
// This is a Left To Right Top to Bottom.
//
DstAdr=Vxl.JaguarScreenX*DstRect->top + (DstRect->left << Vxl.ColorModeShift);
SrcAdr=Vxl.JaguarScreenX*SrcPoint->y + (SrcPoint->x << Vxl.ColorModeShift);
XYCmd=JAGUAR_BITBLT_LEFTRIGHT << XYCMD_CMD_SHIFT;
}
Y &= 0x3FF;
XYCmd = XYCmd | (Y << XYCMD_Y_SHIFT) | X;
FifoWrite(DstAdr,SrcAdr,XYCmd);
}
BOOL
DrvBitBlt(
IN SURFOBJ *psoDst, // Target surface
IN SURFOBJ *psoSrc, // Source surface
IN SURFOBJ *psoMask, // Mask
IN CLIPOBJ *pco, // Clip through this
IN XLATEOBJ *pxlo, // Color translation
IN PRECTL prclDst, // Target offset and extent
IN PPOINTL pptlSrc, // Source offset
IN PPOINTL pptlMask, // Mask offset
IN BRUSHOBJ *pdbrush, // Brush data (from cbRealizeBrush)
IN PPOINTL pptlBrush, // Brush offset (origin)
IN ROP4 rop4 // Raster operation
)
/*++
Routine Description:
Code for "hooking" Bit Blt functions for Jaguar VXL.
Arguments:
Return Value:
--*/
{
FLONG BltDir;
BOOL JaguarDir;
RECTL BltRectl;
ENUMRECTLIST ClipEnum;
BOOL MoreClipRects;
ULONG ClipRegions;
POINTL SrcPoint;
PPDEV ppdev = (PPDEV) psoDst->dhpdev;
BYTE FixedComplexity;
//
// Check that there is no color translation.
//
if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) {
//
// Check that the blt operation has the screen as target surface.
//
if (psoDst->pvBits == (PVOID)Vxl.ScreenBase) {
//
// Check for rops that Jaguar handles.
// Solid Fills,
// SRCCOPPY
//
switch(rop4) {
case 0x00000000: // DDx (BLACKNESS)
DrvpSolidFill(prclDst,pco,0);
return(TRUE);
case 0x0000FFFF: // DDxn (WHITENESS)
DrvpSolidFill(prclDst,pco,0xFFFFFF);
return(TRUE);
case 0x0000F0F0: // P (PATCOPY)
case 0x00000F0F: // Pn (NOTPATCOPY)
//
// This is a pattern fill. Check if the brush pattern
// is just a plain color, in this case procede with the
// Solid Color Fill.
//
if (pdbrush->iSolidColor != 0xFFFFFFFF) {
DrvpSolidFill(prclDst,
pco,
(rop4 == 0xF0F) ? ~(pdbrush->iSolidColor) : pdbrush->iSolidColor);
return(TRUE);
}
break;
//
// Source copy
//
case 0x0000CCCC:
//
// Check that Source and Destination Surfaces are the same.
// This is enough as we already checked that the dst is the frame buffer
//
if (psoDst->pvBits == psoSrc->pvBits) {
//
// check BLT direction for setting up clip regions
// And for Jaguar BitBlt Commands as follows:
// - If BltDir is UPWARDS do the BitBlt RightToLeft Bottom
// to Top except when Src & Dst are in the same scan line
// and BltDir is not LEFTWARDS
//
BltDir = 0;
JaguarDir = FALSE;
if (pptlSrc->y <= prclDst->top) {
BltDir = CD_UPWARDS;
JaguarDir = TRUE;
}
if (pptlSrc->x <= prclDst->left) {
BltDir |= CD_LEFTWARDS;
} else {
if ((JaguarDir) && (pptlSrc->y == prclDst->top)) {
JaguarDir = FALSE;
}
}
//
// Figure out the real clipping complexity
//
if (pco == (CLIPOBJ *)NULL) {
FixedComplexity = DC_TRIVIAL;
} else {
FixedComplexity = pco->iDComplexity;
}
switch (FixedComplexity) {
//
// Entire destination is to be updated.
// Proceed with the BitBlt.
//
case DC_TRIVIAL:
DrvpBitBlt(prclDst, // Target rectangle
pptlSrc, // Source offset
JaguarDir // Direction
);
return(TRUE);
//
// Only one clip region.
//
case DC_RECT:
//
// only do the BLT if there is an intersection
//
if (DrvpIntersectRect(prclDst,&pco->rclBounds,&BltRectl)) {
//
// Adjust the Source for the intersection rectangle.
//
pptlSrc->x += BltRectl.left - prclDst->left;
pptlSrc->y += BltRectl.top - prclDst->top;
DrvpBitBlt(&BltRectl, // Target rectangle
pptlSrc, // Source offset
JaguarDir // Direction
);
}
return(TRUE);
//
// Multiple clip regions.
//
case DC_COMPLEX:
CLIPOBJ_cEnumStart(pco,FALSE,CT_RECTANGLES,BltDir,BB_RECT_LIMIT);
do {
//
// Get list of clip rectangles.
//
MoreClipRects = CLIPOBJ_bEnum(pco,sizeof(ClipEnum),(PVOID)&ClipEnum);
for (ClipRegions=0;ClipRegions<ClipEnum.c;ClipRegions++) {
//
// If the rectangles intersect calculate the offset to the
// source start location to match and do the BitBlt.
//
if (DrvpIntersectRect(prclDst,
&ClipEnum.arcl[ClipRegions],
&BltRectl)) {
SrcPoint.x = pptlSrc->x + BltRectl.left - prclDst->left;
SrcPoint.y = pptlSrc->y + BltRectl.top - prclDst->top;
DrvpBitBlt(&BltRectl, // Target rectangle
&SrcPoint, // Source offset
JaguarDir // Direction
);
}
}
} while (MoreClipRects);
return(TRUE);
//
// Unknown Clip complexity
//
default:
break;
} // end switch complexity
} // end if Src surface = Dst surface
} // end switch rop4
}
}
//
// Call GDI to do the Blt for us. No need to syncrhonize here since
// EngXXX routines call DrvSynchronize.
//
return(EngBitBlt(psoDst, // Target surface
psoSrc, // Source surface
psoMask, // Mask
pco, // Clip through this
pxlo, // Color translation
prclDst, // Target offset and extent
pptlSrc, // Source offset
pptlMask, // Mask offset
pdbrush, // Brush data (from cbRealizeBrush)
pptlBrush, // Brush offset (origin)
rop4 // Raster operation
)
);
}
BOOL
DrvCopyBits(
SURFOBJ *psoDst,
SURFOBJ *psoSrc,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclDst,
POINTL *pptlSrc)
/*++
Routine Description:
Code for "hooking" CopyBits function for Jaguar VXL.
Arguments:
Return Value:
--*/
{
RECTL BltRectl;
ENUMRECTLIST ClipEnum;
BYTE FixedComplexity;
BOOL MoreClipRects;
FLONG BltDir;
BOOL JaguarDir;
ULONG ClipRegions;
POINTL SrcPoint;
//
// Check that there is no color translation.
//
if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) {
//
// Check that source and destination surfaces are the frame buffer.
//
if ((psoSrc->pvBits == (PVOID)Vxl.ScreenBase) &&
(psoDst->pvBits == (PVOID)Vxl.ScreenBase)) {
//
// check BLT direction for setting up clip regions
// And for Jaguar BitBlt Commands as follows:
// - If BltDir is UPWARDS do the BitBlt RightToLeft Bottom
// to Top except when Src & Dst are in the same scan line
// and BltDir is not LEFTWARDS
//
BltDir = 0;
JaguarDir = FALSE;
if (pptlSrc->y <= prclDst->top) {
BltDir = CD_UPWARDS;
JaguarDir = TRUE;
}
if (pptlSrc->x <= prclDst->left) {
BltDir |= CD_LEFTWARDS;
} else {
if ((JaguarDir) && (pptlSrc->y == prclDst->top)) {
JaguarDir = FALSE;
}
}
//
// Figure out the real clipping complexity
//
if (pco == (CLIPOBJ *)NULL) {
FixedComplexity = DC_TRIVIAL;
} else {
FixedComplexity = pco->iDComplexity;
}
switch (FixedComplexity) {
//
// Entire destination is to be updated.
// Proceed with the BitBlt.
//
case DC_TRIVIAL:
DrvpBitBlt(prclDst, // Target rectangle
pptlSrc, // Source offset
JaguarDir // Direction
);
return(TRUE);
//
// Only one clip region.
//
case DC_RECT:
//
// only do the BLT if there is an intersection
//
if (DrvpIntersectRect(prclDst,&pco->rclBounds,&BltRectl)) {
//
// Adjust the Source for the intersection rectangle.
//
pptlSrc->x += BltRectl.left - prclDst->left;
pptlSrc->y += BltRectl.top - prclDst->top;
DrvpBitBlt(&BltRectl, // Target rectangle
pptlSrc, // Source offset
JaguarDir // Direction
);
}
return(TRUE);
//
// Multiple clip regions.
//
case DC_COMPLEX:
CLIPOBJ_cEnumStart(pco,FALSE,CT_RECTANGLES,BltDir,BB_RECT_LIMIT);
do {
//
// Get list of clip rectangles.
//
MoreClipRects = CLIPOBJ_bEnum(pco,sizeof(ClipEnum),(PVOID)&ClipEnum);
for (ClipRegions=0;ClipRegions<ClipEnum.c;ClipRegions++) {
//
// If the rectangles intersect calculate the offset to the
// source start location to match and do the BitBlt.
//
if (DrvpIntersectRect(prclDst,
&ClipEnum.arcl[ClipRegions],
&BltRectl)) {
SrcPoint.x = pptlSrc->x + BltRectl.left - prclDst->left;
SrcPoint.y = pptlSrc->y + BltRectl.top - prclDst->top;
DrvpBitBlt(&BltRectl, // Target rectangle
&SrcPoint, // Source offset
JaguarDir // Direction
);
}
}
} while (MoreClipRects);
return(TRUE);
//
// Unknown Clip complexity
//
default:
break;
} // end switch complexity
}
}
//
// If the copy operation could be performed by the accelerator,
// this routine has already returned.
// If execution falls here, call the Engine routine.
// No need to Synchronize here since the Eng routine will call DrvSyncrhonize.
//
return EngCopyBits(psoDst,
psoSrc,
pco,
pxlo,
prclDst,
pptlSrc);
}