📄 blt.c
字号:
//
// Permedia3 Sample Display Driver
// blt.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This code contains the various GDI and DirectDraw entry points for blitting,
// as well as our hardware accelerated blitting functions.
#include "pch.h" // Precompiled header support.
#include "debug.h"
#include "struct.h"
#include "proto.h"
#include "register.h"
// Used to report that no Permedia3 logicop is appropriate for the given
// Rop3.
#define NO_APPROPRIATE_OP 16
// Internal prototypes. These functions are not exposed outside this module.
static USHORT
LookupLogicop(
BYTE Rop3
);
static void
UploadBitMask(
const PERM3_SURFACE * Mask,
const RECT * Rect
);
BOOL
DrvBitBlt(
SURFOBJ * DestSurface,
SURFOBJ * SourceSurface,
SURFOBJ * MaskSurface,
CLIPOBJ * Clipper,
XLATEOBJ * Xlate,
RECTL * DestRect,
POINTL * SourceTopLeft,
POINTL * MaskTopLeft,
BRUSHOBJ * Brush,
POINTL * BrushOrigin,
ROP4 Rop
)
{
// DrvBitBlt
// This function peforms a GDI BitBlt. It is capable of all ROPs, including
// masked blits. It can express color conversion blits, blits with clipping,
// and blits with brushes, and text out through a special ROP code.
// This is implemented in terms of DrvAnyBlt.
// Stretch blits, color keying and alpha blending are not expressable.
// Local variables.
RECT SourceRect;
BOOL FnRetVal; // Return value for this function.
// Check parameters.
Assert(sizeof(RECT) == sizeof(RECTL));
// !TODO! Finish parameter check.
Enter(L"DrvBitBlt");
// Put together the source rectangle.
if (SourceTopLeft) {
SourceRect.left = SourceTopLeft->x;
SourceRect.top = SourceTopLeft->y;
}
else {
SourceRect.left = 0;
SourceRect.top = 0;
}
// Rely on the fact that a RECT is rely the same as a RECTL. This is
// asserted above.
SourceRect.right = SourceRect.left + RectWidth((RECT *)DestRect);
SourceRect.bottom = SourceRect.top + RectHeight((RECT *)DestRect);
// Do the blit.
FnRetVal = DrvAnyBlt(DestSurface,
SourceSurface,
MaskSurface,
Clipper,
Xlate,
NULL, // No OrginTopLeft...
DestRect,
(RECTL *)&SourceRect,
MaskTopLeft,
Brush,
BrushOrigin,
Rop,
0, // No Mode...
0); // No Flags
Exit(L"DrvBitBlt");
return FnRetVal;
}
BOOL
DrvAnyBlt(
SURFOBJ * DestSurface,
SURFOBJ * SourceSurface,
SURFOBJ * MaskSurface,
CLIPOBJ * Clipper,
XLATEOBJ * Xlate,
POINTL * OriginTopLeft,
RECTL * DestRect,
RECTL * SourceRect,
POINTL * MaskTopLeft,
BRUSHOBJ * Brush,
POINTL * BrushOrigin,
ROP4 Rop,
ULONG Mode,
ULONG Flags
)
{
// DrvAnyBlt
// This function peforms a GDI Blit. It is capable of all ROPs, including
// masked blits. It can express color conversion blits, blits with clipping,
// and blits with brushes, text out through a special ROP code, and stretch
// blits.
// Color keying and alpha blending are not expressable.
// Local variables.
PERM3_BLT_PARAM Parameters;
PERM3_SURFACE Dest;
RECT LocalDestRect;
PERM3_SURFACE Source;
RECT LocalSourceRect;
PERM3_SURFACE * BrushSurface;
RECT BrushRect;
POINT LocalBrushOrigin;
RECT MaskRect;
PERM3_SURFACE Mask;
BOOL FnRetVal; // This is the return value from the function.
XLATEOBJ * FixedXlate;
ENUMRECTS * ClipperRects = NULL;
ULONG SizeofClipperRects;
ULONG ClipperSortDirection = CD_ANY;
// Check parameters.
Assert(sizeof(SIZE) == sizeof(SIZEL));
Assert(sizeof(RECT) == sizeof(RECTL));
Assert(sizeof(POINT) == sizeof(POINTL));
// !TODO! Change this once we return something real from DrvEnablePDEV.
Assert((ULONG)DestSurface->dhpdev == 123);
// !TODO! Finish parameter check.
Enter(L"DrvAnyBlt");
memset(&Parameters, 0, sizeof(PERM3_BLT_PARAM));
// GDI, in all of it's magnificent stupidity, will pass us a bogus XLATEOBJ
// when we don't need it, as opposed to NULL. Work around this by detecting
// the conditions where bogusness might occur.
FixedXlate = (SourceSurface != NULL) ? Xlate : NULL;
// Fill in Parameters.
Parameters.Rop = Rop;
SurfobjToPerm3Surface(&Dest,
DestSurface,
FixedXlate,
FALSE);
Parameters.Destination = (const SURFACE *)&Dest;
if (DestRect != NULL) {
// We know that RECT and RECL are really the same thing. The assert above
// protects this.
Parameters.DestRect = (RECT *)DestRect;
}
else {
LocalDestRect.left = 0;
LocalDestRect.top = 0;
LocalDestRect.right = Dest.Size.cx;
LocalDestRect.bottom = Dest.Size.cy;
Parameters.DestRect = &LocalDestRect;
}
// Reject blits that have no height or width.
if (Parameters.DestRect->top == Parameters.DestRect->bottom ||
Parameters.DestRect->left == Parameters.DestRect->right) {
return TRUE;
}
// Default to left-down blitting.
Parameters.ScanXPositive = TRUE;
Parameters.ScanYPositive = TRUE;
// Source surface details.
if (SourceSurface != NULL) {
SurfobjToPerm3Surface(&Source,
SourceSurface,
FixedXlate,
TRUE);
Parameters.Source = (const SURFACE *)&Source;
if (SourceRect != NULL) {
// We know that RECT and RECL are really the same thing. The assert above
// protects this.
Parameters.SourceRect = (RECT *)SourceRect;
}
else {
LocalSourceRect.left = 0;
LocalSourceRect.top = 0;
LocalSourceRect.right = Source.Size.cx;
LocalSourceRect.bottom = Source.Size.cy;
Parameters.SourceRect = &LocalSourceRect;
}
// Check for an overlap, and set the blitting direction appropriately.
if (Source.Ptr == Dest.Ptr) {
if (Parameters.SourceRect->bottom > Parameters.DestRect->top &&
Parameters.SourceRect->top < Parameters.DestRect->bottom &&
Parameters.SourceRect->right > Parameters.DestRect->left &&
Parameters.SourceRect->left < Parameters.DestRect->right) {
if (Parameters.SourceRect->top == Parameters.DestRect->top) {
// Horizontal blt, just set ScanXPositive appropriately.
Parameters.ScanXPositive = (BOOL)(Parameters.SourceRect->left >= Parameters.DestRect->left);
}
else {
// Non horizontal blts, just set ScanYPositive appropriately.
Parameters.ScanYPositive = (BOOL)(Parameters.SourceRect->top >= Parameters.DestRect->top);
}
// Might need particular clipping rectangles sort order.
if (Clipper) {
if (Parameters.SourceRect->top > Parameters.DestRect->top) {
ClipperSortDirection = (Parameters.SourceRect->left > Parameters.DestRect->left) ? CD_RIGHTDOWN : CD_LEFTDOWN;
}
else {
ClipperSortDirection = (Parameters.SourceRect->left > Parameters.DestRect->left) ? CD_RIGHTUP : CD_LEFTUP;
}
}
}
}
}
else {
// It's possible there is no source surface. We know that the memset above
// has set all pertanent parameters to 0, NULL, so we're good to go.
}
// Handle the brush for pattern blits.
if (Brush) {
if (Brush->iSolidColor == 0xFFFFFFFF) {
Parameters.PatternType = BitmapPattern;
// Get the brush surface and transfer the appropriate details into
// the parameters structure.
if (Brush->pvRbrush == NULL) {
BrushSurface = (PERM3_SURFACE *)(BRUSHOBJ_pvGetRbrush(Brush));
// !TODO! Check return code?
}
else {
BrushSurface = (PERM3_SURFACE *)(Brush->pvRbrush);
}
Parameters.Brush = (const SURFACE *)BrushSurface;
BrushRect.left = 0;
BrushRect.top = 0;
BrushRect.right = Parameters.Brush->Size.cx;
BrushRect.bottom = Parameters.Brush->Size.cy;
Parameters.BrushRect = &BrushRect;
if (BrushOrigin) {
Parameters.BrushOrigin = (POINT *)BrushOrigin;
}
else {
LocalBrushOrigin.x = 0;
LocalBrushOrigin.y = 0;
Parameters.BrushOrigin = &LocalBrushOrigin;
}
}
else {
Parameters.PatternType = SolidPattern;
Parameters.FillValue = Brush->iSolidColor;
}
}
if (MaskSurface) {
// We only support 1bpp masks.
Assert(MaskSurface->iBitmapFormat == BMF_1BPP);
SurfobjToPerm3Surface(&Mask,
MaskSurface,
NULL,
FALSE);
Parameters.Mask = (const SURFACE *)&Mask;
// Sometimes, mask surfaces are given to us with a size of (0,0) This
// might trip up our blitting code later, so in such a case, we will
// replace with the height and width of the destination rectnagle.
if (Mask.Size.cx == 0 || Mask.Size.cy == 0) {
// Rely on the fact that a RECT is rely the same as a RECTL. This is
// asserted above.
Mask.Size.cx = RectWidth((RECT *)DestRect);
Mask.Size.cy = RectHeight((RECT *)DestRect);
}
// Build the rectangle of the mask to be used in the blit from the size
// and the given top-left.
if (MaskTopLeft) {
MaskRect.left = MaskTopLeft->x;
MaskRect.top = MaskTopLeft->y;
}
else {
MaskRect.left = 0;
MaskRect.top = 0;
}
MaskRect.right = MaskRect.left + Mask.Size.cx;
MaskRect.bottom = MaskRect.top + Mask.Size.cy;
Parameters.MaskRect = &MaskRect;
}
if (Clipper && Clipper->iDComplexity != DC_TRIVIAL) {
if (Clipper->iDComplexity == DC_RECT) {
// Sometimes GDI wants us to clip to the dimensions of the destination
// surface: which is implicit, and should not be specified as a clip
// rectangle.
if (!(Clipper->rclBounds.left == 0 &&
Clipper->rclBounds.top == 0 &&
Clipper->rclBounds.right == Parameters.Destination->Size.cx &&
Clipper->rclBounds.bottom == Parameters.Destination->Size.cy)) {
Parameters.ClipRectCount = 1;
Parameters.ClipRect = (const RECT *)&(Clipper->rclBounds);
}
}
else if (Clipper->iDComplexity == DC_COMPLEX) {
// Extract all of the rectangles from GDI.
Parameters.ClipRectCount = CLIPOBJ_cEnumStart(Clipper,
TRUE,
CT_RECTANGLES,
ClipperSortDirection,
0);
// The ENUMRECTS strcuture already contains space for 1 rectangle.
SizeofClipperRects = sizeof(ENUMRECTS) +
sizeof(RECT) * (Parameters.ClipRectCount - 1);
ClipperRects = SystemAlloc(SizeofClipperRects);
if (ClipperRects) {
CLIPOBJ_bEnum(Clipper,
SizeofClipperRects,
(ULONG *)ClipperRects);
Assert(ClipperRects->c == Parameters.ClipRectCount);
Parameters.ClipRect = (const RECT *)ClipperRects->arcl;
}
else {
Error(L"System memory allocation failure.\n");
}
}
else {
Error(L"Unknown clipping complexity.\n");
}
}
// Call the Blt with our newly constructed parameter block.
FnRetVal = TryBothBlt(&Parameters);
FreeSurfobjDerivedPerm3Surface(&Dest);
if (SourceSurface) {
FreeSurfobjDerivedPerm3Surface(&Source);
}
if (MaskSurface) {
FreeSurfobjDerivedPerm3Surface(&Mask);
}
if (ClipperRects) {
SystemFree(ClipperRects);
}
Exit(L"DrvAnyBlt");
return FnRetVal;
}
BOOL
DrvTransparentBlt(
SURFOBJ * DestSurface,
SURFOBJ * SourceSurface,
CLIPOBJ * Clipper,
XLATEOBJ * Xlate,
RECTL * DestRect,
RECTL * SourceRect,
ULONG TransColor
)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -