📄 blt.c
字号:
}
// Move to next mask pixel.
if (Parameters->Mask) {
// Check bits remaining in mask cache.
if (!(Mask.CacheState & 0x00ff00)) {
Mask.Ptr += Mask.BytesPerAccess; // == +/- 4
Mask.CacheState = Mask.CacheStateNewDWord;
Mask.Cache = *(UNALIGNED ULONG *)Mask.Ptr;
}
Mask.CacheState += Mask.CacheStateIncrement;
}
xAccum += xDMinor;
}
xAccum += xDMajor;
}
}
// Do we do destination pixel read-back?
if (DestMatters) {
// We maintain dst.Cache valid at all times if not doing quickWrite.
if (QuickWrite) {
switch (Dest.Bpp) {
case 8:
*(BYTE *)&Dest.Value = *(BYTE *)Dest.Ptr;
break;
case 16:
*(WORD *)&Dest.Value = *(WORD *)Dest.Ptr;
break;
case 32:
*(ULONG *)&Dest.Value = *(ULONG *)Dest.Ptr;
break;
case 24:
Dest.Value = (*(Dest.Ptr + 2) << 16) + (*(Dest.Ptr + 1) << 8) + *(Dest.Ptr);
break;
}
}
else {
Dest.Value = Dest.Cache >> ((Dest.CacheState >> 16) ^ Dest.MaskShiftXor);
}
}
switch (Rop3) {
// The compiler sorts these and creates a binary search set of tests to
// get to an entry quickly. Branch "prediction" helps this a lot.
// Remember that masked rop4s makes NOP and SRCCOPY more likely.
case 0xCC: break; // SRCCOPY
case 0xAA: Source.Value = Dest.Value; break;
case 0x00: Source.Value = 0; break; // BLACKNESS
case 0x22: Source.Value = (~Source.Value) & Dest.Value; break;
case 0xB8: Source.Value = (Brush.Value & ~Source.Value) | (Source.Value & Dest.Value); break;
case 0x11: Source.Value = ~(Source.Value | Dest.Value); break; // NOTSRCERASE
case 0x33: Source.Value = ~Source.Value; break; // NOTSRCCOPY
case 0x44: Source.Value &= ~Dest.Value; break; // SRCERASE
case 0x55: Source.Value = ~Dest.Value; break; // DSTINVERT
case 0x5A: Source.Value = Brush.Value ^ Dest.Value; break; // PATINVERT
case 0x66: Source.Value ^= Dest.Value; break; // SRCINVERT
case 0x88: Source.Value &= Dest.Value; break; // SRCAND
case 0xBB: Source.Value = ~Source.Value | Dest.Value; break; // MERGEPAINT
case 0xC0: Source.Value &= Brush.Value; break; // MERGECOPY
case 0xEE: Source.Value |= Dest.Value; break; // SRCPAINT
case 0xF0: Source.Value = Brush.Value; break; // PATCOPY
case 0xFB: Source.Value = Brush.Value | ~Source.Value | Dest.Value; break; // PATPAINT
case 0xFF: Source.Value = 0xFFFFFFFF; break; // WHITENESS
case 0xE2: Source.Value = (Dest.Value & ~Source.Value) | (Brush.Value & Source.Value); break;
case 0xAC: Source.Value = ((Source.Value ^ Dest.Value) & Brush.Value) ^ Source.Value; break;
default:
Source.Value = ProcessRop3(Dest.Value,
Source.Value,
Brush.Value,
Rop3,
(BYTE)Dest.Bpp);
break;
}
Source.Value &= Dest.Mask;
if ((DoSourceColorKey && OriginalSrc == SourceColorKeyValue) ||
(DoDestColorKey && Dest.Value == DestColorKeyValue)) {
// This pixel is being color-keyed out.
if (QuickWrite) {
Dest.Ptr += Dest.BytesPerAccess;
}
else {
// Leave dirty flag as-is.
Dest.CacheState += Dest.CacheStateIncrement;
// Check bits remaining in Dest cache.
if (!(Dest.CacheState & 0x00ff00)) {
if (Dest.CacheState & 0x0000ff) {
// Flush cache.
*(ULONG *)Dest.Ptr = Dest.Cache;
}
// Clear dirty flag.
Dest.CacheState = Dest.CacheStateNewDWord;
Dest.Ptr += Dest.BytesPerAccess; // +/- 4
Dest.Cache = *(ULONG *)Dest.Ptr;
}
}
continue;
}
}
// Now, we are ready to write the value from Source.Value into the
// destination pixel.
if (QuickWrite) {
switch (Dest.Bpp) {
case 8:
*(BYTE *)Dest.Ptr = (BYTE)Source.Value;
break;
case 16:
*(WORD *)Dest.Ptr = (WORD)Source.Value;
break;
case 32:
*(ULONG *)Dest.Ptr = (ULONG)Source.Value;
break;
case 24:
*Dest.Ptr = (BYTE)(Source.Value);
*(Dest.Ptr + 1) = (BYTE)(Source.Value >> 8);
*(Dest.Ptr + 2) = (BYTE)(Source.Value >> 16);
break;
}
Dest.Ptr += Dest.BytesPerAccess;
}
else {
TempShift = (BYTE)((Dest.CacheState >> 16 ) ^ Dest.MaskShiftXor);
Dest.Cache &= ~(Dest.Mask << TempShift);
Dest.Cache |= Source.Value << TempShift;
Dest.CacheState += Dest.CacheStateIncrementDirty; // sets dirty flag
// Check bits remaining in Dest cache.
if (!(Dest.CacheState & 0x00ff00)) {
// Flush cache (We know it was dirty.)
*(ULONG *)Dest.Ptr = Dest.Cache;
// Clear dirty flag.
Dest.CacheState = Dest.CacheStateNewDWord;
Dest.Ptr += Dest.BytesPerAccess; // +/- 4
if (x != Width - 1) Dest.Cache = *(ULONG *)Dest.Ptr;
}
}
} // Next column
// Flush out destination pixel cache for next row.
if (Dest.CacheState & 0x0000ff) *(ULONG *)Dest.Ptr = Dest.Cache;
} // Next row
// Cleanup the color converter.
if (DoColorConvert) {
CleanupColorConverter();
}
return TRUE;
}
void
InitPixelBuffer(
PIXEL_BUFFER * Buffer,
const SURFACE * Surface,
BOOL xPositive,
BOOL yPositive,
const RECT * Rect,
ULONG xSkip,
ULONG ySkip
)
{
// InitPixelBuffer
// This function fills out a PIXEL_BUFFER structure using the data provided
// on the stack. Do not use this function for brushes.
// Local variables.
LONG StartX;
LONG StartBit;
// Check parameters.
// !TODO!
// Set pointer to start of first row to use
Buffer->RowPtr = (BYTE *)Surface->Ptr;
if (yPositive) {
Buffer->RowIncrement = Surface->Stride;
Buffer->RowPtr += Surface->Stride * (Rect->top + ySkip);
}
else {
Buffer->RowIncrement = -Surface->Stride;
Buffer->RowPtr += Surface->Stride * (Rect->bottom - 1 - ySkip);
}
Buffer->Bpp = Surface->Format->BitsPerPixel;
Buffer->MaskShiftXor = (Buffer->Bpp < 8) ? (LONG)(8 - Buffer->Bpp) : 0;
// Initally 32 / Bpp pixels in dword, 0 offset
Buffer->CacheStateNewDWord = (32 / Buffer->Bpp) << 8;
if (xPositive) {
StartX = Rect->left + xSkip;
Buffer->CacheStateIncrement = ((Buffer->Bpp << 8) - 1) << 8;
}
else {
StartX = Rect->right - 1 - xSkip;
Buffer->CacheStateIncrement = (((-(LONG)Buffer->Bpp) << 8) - 1) << 8;
// Initial offset points to last pixel in dword
Buffer->CacheStateNewDWord |= (32 - (LONG)Buffer->Bpp) << 16;
}
Buffer->CacheStateIncrementDirty = Buffer->CacheStateIncrement + 1;
// Deliberate assignment.
if (Buffer->Is24Bit = (Buffer->Bpp == 24)) {
Buffer->RowPtr += 3 * StartX;
Buffer->BytesPerAccess = 3;
}
else {
StartBit = Buffer->Bpp * StartX;
Buffer->RowPtr += (StartBit & ~31) >> 3;
// Since the first pixel on row specified in Rect may not be on dword
// alignment:
Buffer->CacheStateNewRow = Buffer->CacheStateNewDWord;
while (((Buffer->CacheStateNewRow >> 16) ^ StartBit) & 31) {
Buffer->CacheStateNewRow += Buffer->CacheStateIncrement;
}
Buffer->BytesPerAccess = 4;
}
if (!xPositive) {
Buffer->BytesPerAccess = -Buffer->BytesPerAccess;
}
Buffer->Mask = (2 << (Buffer->Bpp - 1)) - 1;
}
void
InitBrushPixelBuffer(
BRUSH_PIXEL_BUFFER * Buffer,
const SURFACE * Surface,
BOOL xPositive,
BOOL yPositive,
const RECT * Rect
)
{
// InitBrushPixelBuffer
// This function should be called to fill out one of the specialized
// BRUSH_PIXEL_BUFFER structures. Obviously, this should only be used for
// brushes.
// Check parameters.
// !TODO!
// We can safely cast BRUSH_PIXEL_BUFFER to PIXEL_BUFFER because of the
// embedded structure.
InitPixelBuffer((PIXEL_BUFFER *)Buffer,
Surface,
xPositive,
yPositive,
Rect,
0,
0);
Buffer->PixelsPerRow = Surface->Size.cx;
Buffer->Rows = Surface->Size.cy;
Buffer->RowInitialPixelsRemaining = xPositive ? Buffer->PixelsPerRow - Rect->left : Rect->right;
Buffer->RowsRemaining = yPositive ? Buffer->Rows - Rect->top : Rect->bottom;
Buffer->FirstRowPtr = Buffer->RowPtr - Buffer->RowIncrement * ( Buffer->Rows - Buffer->RowsRemaining);
}
ULONG
ProcessRop3(
ULONG DestValue,
ULONG SourceValue,
ULONG BrushValue,
BYTE Rop3,
BYTE DestBitsPerPixel
)
{
// ProcessRop3
// This function will use the given D, S, and B values to execute an
// arbitrary ROP. It returns the value. This function may call itself
// recursively.
// Local variables.
ULONG Result = 0;
ULONG ResultBit = 1;
// Check parameters.
// !TODO!
if (DestBitsPerPixel > 24) {
// Recursively break into two halves, otherwise the brushValue <<= 2 below
// will overflow.
return (( ProcessRop3(DestValue,
SourceValue,
BrushValue,
Rop3,
16))
|
( ProcessRop3(DestValue >> 16,
SourceValue >> 16,
BrushValue >> 16,
Rop3,
(BYTE)(DestBitsPerPixel - 16)) << 16)
);
}
BrushValue <<= 2;
SourceValue <<= 1;
while (DestBitsPerPixel--) {
if ((1 << (BrushValue & 4 | SourceValue & 2 | DestValue & 1)) & Rop3) {
Result |= ResultBit;
}
BrushValue >>= 1;
SourceValue >>= 1;
DestValue >>= 1;
ResultBit <<= 1;
}
return Result;
}
LONG
RectWidth(
const RECT * Rect
)
{
// RectWidth
// This function returns the width of a rectangle. Inlined.
// Check parameters
// !TODO!
return (Rect->right - Rect->left);
}
LONG
RectHeight(
const RECT * Rect
)
{
// RectHeight
// This function returns the height of a rectangle. Inlined.
// Check parameters
// !TODO!
return (Rect->bottom - Rect->top);
}
void
SelectFill(
ULONG BitsPerPixel,
BLT_FN Fill2,
BLT_FN Fill8,
BLT_FN Fill16,
BLT_FN Fill32,
BLT_FN * OutFill
)
{
// SelectFill
// This function may be used to select a blitting function that has 2, 8, 16
// and 32 bit destination variants. Currently, this is used for fill
// functions. If the BitsPerPixel value is not 2, 8, 16 (15), or 32 (24),
// then the output fill function pointer is not touched.
// Check parameters.
// !TODO!
switch (BitsPerPixel) {
case 2: *OutFill = Fill2; break;
case 8: *OutFill = Fill8; break;
case 15:
case 16: *OutFill = Fill16; break;
case 24:
case 32: *OutFill = Fill32; break;
}
}
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
)
{
// SelectSrcLogic
// This function may be used to select a blitting function from a number of
// different variants, depending on source and destination bits per pixel.
// If no match is found, the output function pointer is not touched. This
// function is currently used for the "source logic" ROPs. (SRCAND, SRCPAINT,
// and SRCINVERT).
// Check parameters.
// !TODO!
switch (DestBitsPerPixel) {
case 2:
if (SrcBitsPerPixel == 2) {
*OutLogic = Logic0202;
}
break;
case 8:
switch (SrcBitsPerPixel) {
case 1: *OutLogic = Logic0108; break;
case 8: *OutLogic = Logic0808; break;
}
break;
case 16:
switch (SrcBitsPerPixel) {
case 1: *OutLogic = Logic0116; break;
case 8: *OutLogic = Logic0816; break;
case 16: *OutLogic = Logic1616; break;
}
break;
case 32:
switch (SrcBitsPerPixel) {
case 1: *OutLogic = Logic0132; break;
case 8: *OutLogic = Logic0832; break;
case 32: *OutLogic = Logic3232; break;
}
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -