📄 blt.c
字号:
//
// Windows CE Software Graphics Library
// blt.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This source file contains the implementation of the software blit routine.
#include "pch.h"
#include "swg.h"
#include "specialcase.h"
// This is a dumb little helper macro.
#define Swap(a,b) \
{ \
(a) = (a) ^ (b); \
(b) = (a) ^ (b); \
(a) = (a) ^ (b); \
}
// The pixel buffer structure is used to store all of the details concerning
// the source, destination and mask surfaces.
typedef struct t_PIXEL_BUFFER {
BYTE * RowPtr;
LONG RowIncrement;
ULONG CacheStateNewDWord;
ULONG CacheStateNewRow;
ULONG CacheStateIncrement;
ULONG CacheStateIncrementDirty;
BOOL Is24Bit;
ULONG Mask;
LONG BytesPerAccess;
ULONG Bpp;
BYTE * Ptr;
ULONG Cache;
ULONG Value;
ULONG CacheState;
BYTE MaskShiftXor;
} PIXEL_BUFFER;
// This is a special variant of the PIXEL_BUFFER structure with extra members
// for brushs.
typedef struct t_BRUSH_PIXEL_BUFFER {
// Note the use of the "anonymous structure" Microsoft C extension.
PIXEL_BUFFER;
// Pixels still available this row of brush including cache.
LONG PixelsRemaining;
// Width of source surface.
LONG PixelsPerRow;
// PixelsRemaining at start of each destination row.
LONG RowInitialPixelsRemaining;
// Rows (including this one) left in pattern.
LONG RowsRemaining;
// Total rows in pattern.
LONG Rows;
// Pointer to first ulong to use in top/bottom row.
BYTE * FirstRowPtr;
// Pointer to *left* of pattern of current row.
BYTE * LeftRowPtr;
} BRUSH_PIXEL_BUFFER;
// This is a function pointer to a blitting function.
typedef BOOL (*BLT_FN)(BLT_PARAM *);
// Internal prototypes. These functions are not exposed outside this module.
static void
InitPixelBuffer(
PIXEL_BUFFER * Buffer,
const SURFACE * Surface,
BOOL xPositive,
BOOL yPositive,
const RECT * Rect,
ULONG xSkip,
ULONG ySkip
);
static void
InitBrushPixelBuffer(
BRUSH_PIXEL_BUFFER * Buffer,
const SURFACE * Surface,
BOOL xPositive,
BOOL yPositive,
const RECT * Rect
);
static ULONG
ProcessRop3(
ULONG DestValue,
ULONG SourceValue,
ULONG BrushValue,
BYTE Rop3,
BYTE DestBitsPerPixel
);
static BOOL
AnyBlt(
BLT_PARAM * Parameters
);
static void
SelectFill(
ULONG BitsPerPixel,
BLT_FN Fill2,
BLT_FN Fill8,
BLT_FN Fill16,
BLT_FN Fill32,
BLT_FN * OutFill
);
static void
SelectSrcLogic(
ULONG DestBitsPerPixel,
ULONG SrcBitsPerPixel,
BLT_FN Logic0202,
BLT_FN Logic0108,
BLT_FN Logic0808,
BLT_FN Logic0116,
BLT_FN Logic0816,
BLT_FN Logic1616,
BLT_FN Logic0132,
BLT_FN Logic0832,
BLT_FN Logic3232,
BLT_FN * OutLogic
);
BOOL
SoftwareBlt(
BLT_PARAM * Parameters
)
{
// SoftwareBlt
// This routine will examine the blit's parameters and determine if any
// special case software blitting routines are appropriate to do the job.
// If so, the special case is called, if not, we use the AnyBlt routine to
// handle the blit.
// Local variables.
BLT_FN BltFn;
BOOL Stretching;
// Check parameters.
// !TODO!
// Default to the blit routine that can handle anything.
BltFn = AnyBlt;
// Are we stretching?
Stretching = FALSE;
if (Parameters->Source) {
if (RectWidth(Parameters->SourceRect) != RectWidth(Parameters->DestRect) ||
RectHeight(Parameters->SourceRect) != RectHeight(Parameters->DestRect)) {
Stretching = TRUE;
}
}
// !TODO! Add checking for color conversion.
// None of the optimized software routines color key or handle stretching.
if (Parameters->ColorKeyType == NoColorKey &&
!Stretching &&
Parameters->ClipRectCount == 0) {
switch (Parameters->Rop) {
case 0x0000: // BLACKNESS
Parameters->PatternType = SolidPattern;
Parameters->FillValue = 0x00000000;
SelectFill(Parameters->Destination->Format->BitsPerPixel,
SolidFill02,
SolidFill08,
SolidFill16,
SolidFill32,
&BltFn);
break;
case 0xFFFF: // WHITENESS
Parameters->PatternType = SolidPattern;
Parameters->FillValue = 0xFFFFFFFF;
SelectFill(Parameters->Destination->Format->BitsPerPixel,
SolidFill02,
SolidFill08,
SolidFill16,
SolidFill32,
&BltFn);
break;
case 0xAAF0: // Masked fill : usually text.
// !TODO!
case 0xF0F0: // PATCOPY
if (Parameters->PatternType == SolidPattern) {
SelectFill(Parameters->Destination->Format->BitsPerPixel,
SolidFill02,
SolidFill08,
SolidFill16,
SolidFill32,
&BltFn);
}
break;
case 0xCCCC:
switch (Parameters->Destination->Format->BitsPerPixel) {
case 2:
if (Parameters->Source->Format->BitsPerPixel == 2) {
BltFn = SrcCopy0202;
}
break;
case 8:
switch (Parameters->Source->Format->BitsPerPixel) {
case 1: BltFn = SrcCopy0108; break;
case 4: BltFn = SrcCopy0408; break;
case 8: BltFn = SrcCopy0808; break;
}
break;
case 15:
case 16:
switch (Parameters->Source->Format->BitsPerPixel) {
case 1: BltFn = SrcCopy0116; break;
case 4: BltFn = SrcCopy0416; break;
case 8: BltFn = SrcCopy0816; break;
case 16: BltFn = SrcCopy1616; break;
}
break;
case 24:
case 32:
switch (Parameters->Source->Format->BitsPerPixel) {
case 1: BltFn = SrcCopy0132; break;
case 4: BltFn = SrcCopy0432; break;
case 8: BltFn = SrcCopy0832; break;
case 32: BltFn = SrcCopy3232; break;
}
break;
}
break;
case 0x8888: // SRCAND
SelectSrcLogic(Parameters->Destination->Format->BitsPerPixel,
Parameters->Source->Format->BitsPerPixel,
SrcAnd0202,
SrcAnd0108,
SrcAnd0808,
SrcAnd0116,
SrcAnd0816,
SrcAnd1616,
SrcAnd0132,
SrcAnd0832,
SrcAnd3232,
&BltFn);
break;
case 0xEEEE: // SRCPAINT
SelectSrcLogic(Parameters->Destination->Format->BitsPerPixel,
Parameters->Source->Format->BitsPerPixel,
SrcPaint0202,
SrcPaint0108,
SrcPaint0808,
SrcPaint0116,
SrcPaint0816,
SrcPaint1616,
SrcPaint0132,
SrcPaint0832,
SrcPaint3232,
&BltFn);
break;
case 0x6666: // SRCINVERT
SelectSrcLogic(Parameters->Destination->Format->BitsPerPixel,
Parameters->Source->Format->BitsPerPixel,
SrcInvert0202,
SrcInvert0108,
SrcInvert0808,
SrcInvert0116,
SrcInvert0816,
SrcInvert1616,
SrcInvert0132,
SrcInvert0832,
SrcInvert3232,
&BltFn);
break;
}
}
// Call the blitter.
return (BltFn(Parameters));
}
BOOL
AnyBlt(
BLT_PARAM * Parameters
)
{
// AnyBlt
// This is the fully-featured software blitting routine. It can be called to
// perform blits that the hardware cannot do. It supports the following
// features:
//
// - Arbitrary ROP
// - Source and destination color key (single color only)
// - Shrink and Scale
// - Color format conversion
//
// Note: this function assume that all surfaces are locked and that if we
// are rendering to the primary, that the graphics pipe is flushed and
// stalled.
// Local variables.
BYTE Rop3 = (BYTE)Parameters->Rop;
BYTE MaskedRop3 = (BYTE)(Parameters->Rop >> 8);
BYTE UnmaskedRop3 = Rop3;
BYTE TempShift;
BOOL ComplexBlt = 0;
BOOL QuickWrite = 0;
LONG Width = RectWidth(Parameters->DestRect);
LONG Height = RectHeight(Parameters->DestRect);
LONG x;
BOOL DestMatters = (((Parameters->Rop >> 1) ^ Parameters->Rop) & 0x5555) != 0;
BOOL DestXPositive = Parameters->ScanXPositive;
BOOL DestYPositive = Parameters->ScanYPositive;
const RECT * DestRect = Parameters->DestRect;
RECT TempDestRect;
RECT ClippedDestRect;
BOOL xShrinkStretch = FALSE;
BOOL xShrink = FALSE;
BOOL xStretch = FALSE;
BOOL yShrinkStretch = FALSE;
BOOL yShrink = FALSE;
BOOL yStretch = FALSE;
LONG SourceWidth;
LONG SourceHeight;
LONG RowXAccum, xAccum, xDMajor, xDMinor; // only valid if xShrinkStretch
LONG yAccum, yDMajor, yDMinor; // only valid if yShrinkStretch
LONG OriginalMaskRowInc, OriginalSrcRowInc; // only valid if yShrinkStretch
BYTE * PrevMaskPtr, * PrevSrcPtr;
ULONG PrevMaskCache, PrevSrcCache;
ULONG PrevMaskCacheState, PrevSrcCacheState;
ULONG OriginalSrc;
RECT BrushRect;
LONG BrushTopIndent;
LONG BrushLeftIndent;
// Number of dst pixels to not write (left if dstXPositive else right)
LONG DestXStartSkip = 0;
LONG SourceXStartSkip = 0;
// Number of rows to ignore (top if dstYPositive)
LONG DestYStartSkip = 0;
LONG SourceYStartSkip = 0;
LONG SkipCount;
BOOL DoSourceColorKey;
ULONG SourceColorKeyValue;
BOOL DoDestColorKey;
ULONG DestColorKeyValue;
PIXEL_BUFFER Source, Dest, Mask;
BRUSH_PIXEL_BUFFER Brush;
BOOL DoColorConvert;
// Check parameters.
// !TODO!
// Handle improperly ordered prclDst resulting from stretch Blt
// Note that only prclDst is ever improperly ordered
if (Width < 0 || Height < 0) {
memcpy(&TempDestRect, DestRect, sizeof(RECT));
DestRect = &TempDestRect;
if (Width < 0) {
Swap(TempDestRect.left, TempDestRect.right);
Width = -Width;
DestXPositive = !DestXPositive;
}
if (Height < 0) {
Swap(TempDestRect.top, TempDestRect.bottom);
Height = -Height;
DestYPositive = !DestYPositive;
}
}
// DestRect is now properly ordered.
// Check for stretching and/or shrinking.
if (Parameters->Source) {
SourceWidth = RectWidth(Parameters->SourceRect);
SourceHeight = RectHeight(Parameters->SourceRect);
if (Width > SourceWidth) {
xStretch = TRUE;
xDMajor = Width;
xDMinor = SourceWidth;
}
else if (Width < SourceWidth) {
xShrink = TRUE;
xDMajor = SourceWidth;
xDMinor = Width;
}
if (xStretch || xShrink) {
xShrinkStretch = TRUE;
// Convert to Bresenham parameters.
xDMinor *= 2;
xDMajor = xDMinor - 2 * xDMajor;
RowXAccum = xShrink ? (2 * Width - SourceWidth) : (3 * SourceWidth - 2 * Width);
// Loaded into xAccum at start of each row.
}
if (Height > SourceHeight) {
yStretch = TRUE;
yDMajor = Height;
yDMinor = SourceHeight;
}
if (Height < SourceHeight) {
yShrink = TRUE;
yDMajor = SourceHeight;
yDMinor = Height;
}
if (yStretch || yShrink) {
yShrinkStretch = TRUE;
// Convert to Bresenham parameters.
yDMinor *= 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -