📄 brush.c
字号:
//
// Permedia3 Sample Display Driver
// brush.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This module includes the source code necessary to support GDI brushes.
#include "pch.h" // Precompiled header support.
#include "debug.h"
#include "struct.h"
#include "proto.h"
#include "register.h"
BOOL
DrvRealizeBrush(
BRUSHOBJ * Brush,
SURFOBJ * TargetSurface,
SURFOBJ * PatternSurface,
SURFOBJ * MaskSurface,
XLATEOBJ * Xlate,
ULONG Hatch
)
{
// DrvRealizeBrush
// GDI calls this function when it needs to convert a brush into a format
// that the driver can use.
// Local variables.
BOOL FnRetVal = FALSE;
PERM3_SURFACE Target;
PERM3_SURFACE Pattern;
PERM3_SURFACE * RBrush;
LONG RBrushStride;
ULONG BytesForRBrush;
PERM3_BLT_PARAM Parameters;
PERM3_FORMAT * Format;
ULONG * Masks;
RECT DestRect;
RECT SourceRect;
ULONG SizeofMaskArray;
// Check parameters.
// !TODO! Finish parameter check.
// Neither of these parameters is used by Windows CE.
Assert(Xlate != NULL);
Assert(MaskSurface == NULL);
Assert(Hatch == 0);
Enter(L"DrvRealizeBrush");
SurfobjToPerm3Surface(&Target,
TargetSurface,
Xlate,
FALSE);
SurfobjToPerm3Surface(&Pattern,
PatternSurface,
Xlate,
TRUE);
// Our realized brush will use the dimensions from the "Pattern" surface and
// same pixel format as the "Target" surface. As such, we must copy the
// masks or palette from the "Target" surface. We know that all FORMAT *
// actually point to PERM3_FORMAT *, so this cast is legal.
SizeofMaskArray = GetSizeofPaletteMasks((const PERM3_FORMAT *)Target.Format);
// We need to allocate the bits for the realized brush along with
// the brush data structure becasue GDI does not call us when it
// deallocate this. It is done automatically.
RBrushStride = Pattern.Size.cx * Target.Format->BitsPerPixel / 8;
// This can happen with very small 1 Bpp patterns. The blitting code that
// we are about to call requires at least 4 bytes per scanline, as it does
// ULONG fetchs on each line.
if (RBrushStride < 4) {
RBrushStride = 4;
}
BytesForRBrush = (RBrushStride * Pattern.Size.cy) + 4 +
sizeof(PERM3_FORMAT) +
sizeof(PERM3_SURFACE) +
SizeofMaskArray;
// This call also associates this lump of memory with the given brush.
// We need only initialize that memory correctly to be finished.
RBrush = BRUSHOBJ_pvAllocRbrush(Brush, BytesForRBrush);
memset(RBrush, 0, sizeof(PERM3_SURFACE));
if (RBrush != NULL ) {
// Setup the format and mask pointers.
Format = (PERM3_FORMAT *)(((BYTE *)RBrush) + sizeof(PERM3_SURFACE));
Masks = (ULONG *)(((BYTE *)Format) + sizeof(PERM3_FORMAT));
// Copy the relevant data in from the target surface.
Format->BitsPerPixel = Target.Format->BitsPerPixel;
Format->FourCC = Target.Format->FourCC;
memcpy(Masks,
Target.Format->Masks,
SizeofMaskArray);
// The PERM3_FORMAT and masks will be freed when all of the brush
// memory is freed.
Format->FreePaletteMasks = FALSE;
Format->Masks = Masks;
RBrush->FreeFormat = FALSE;
RBrush->Format = (const FORMAT *)Format;
memcpy(&RBrush->Size, &Pattern.Size, sizeof(SIZE));
RBrush->Stride = RBrushStride;
// Make sure the brush surface is 32 bit aligned.
RBrush->Ptr = (LPVOID)((((DWORD)Format->Masks + SizeofMaskArray) & 0xFFFFFFFC) + 4);
RBrush->BitmapHandle = 0;
RBrush->Type = SystemMemory;
// Use a SRCCOPY blit to copy the bits from the pattern to the
// realized brush. This will color convert from the "Pattern"
// pixel format to the "realized" "Target" format.
memset(&Parameters, 0, sizeof(PERM3_BLT_PARAM));
Parameters.Rop = 0xCCCC; // SRCCOPY
Parameters.Destination = (const SURFACE *)RBrush;
Parameters.Source = (const SURFACE *)&Pattern;
DestRect.top = 0;
DestRect.left = 0;
DestRect.bottom = RBrush->Size.cy;
DestRect.right = RBrush->Size.cx;
Parameters.DestRect = &DestRect;
SourceRect.top = 0;
SourceRect.left = 0;
SourceRect.bottom = Pattern.Size.cy;
SourceRect.right = Pattern.Size.cx;
Parameters.SourceRect = &SourceRect;
Parameters.ScanXPositive = TRUE;
Parameters.ScanYPositive = TRUE;
FnRetVal = TryBothBlt(&Parameters);
}
else {
Error(L"BRUSHOBJ_pvAllocRbrush failed.\n");
}
FreeSurfobjDerivedPerm3Surface(&Target);
FreeSurfobjDerivedPerm3Surface(&Pattern);
Exit(L"DrvRealizeBrush");
return FnRetVal;
}
void
HwBrush(
PERM3_BLT_PARAM * Parameters
)
{
// HwBrush
// This function, loads pattern, or brush, as specified in the blit parameter
// structure, into the hardware. This needs to be called in a DMA block of
// appropriate size.
// Local variables.
ULONG DataUlongCount;
ULONG * BrushData;
ULONG i;
// Check parameters.
// !TODO!
Enter(L"HwBrush");
Assert(Parameters->Brush->Stride > 0);
Assert(IsSameFormat(Parameters->Brush->Format,
(const FORMAT *)GetDisplayModeFormat(GetCurrentMode())));
// Some locals to help out in the actual loop that queues the data.
BrushData = (ULONG *)Parameters->Brush->Ptr;
// This cast is protected by the assertion above. We always realize brushes
// with positive slopes.
DataUlongCount = (ULONG)Parameters->Brush->Stride *
Parameters->Brush->Size.cy / 4;
// We don't allow brushes of any size but 8x8.
Assert(Parameters->BrushOrigin->x < 8);
Assert(Parameters->BrushOrigin->y < 8);
// Enable the LUT, and set the pattern origin.
WriteRegUlong(r_LUTMode,
b_LUTMode_Enable |
(1 << 8) | // SpanOperation = SpanPattern
(Parameters->BrushOrigin->x << 12) |
(Parameters->BrushOrigin->y << 15) |
b_LUTMode_SpanVCXAlignment);
// If we did pattern caching, we might want to load a different index here.
WriteRegUlong(r_LUTIndex, 0);
// Move the data into the LUT in ulongs. This works because we know that
// we will always be moving 8x8 surfaces: even if the surface is 8bpp, the
// data is still some multiple of 32 bit values. We also know that
// DrvRealizeBrush has converted the data to the same format as the screen.
for (i = 0; i < DataUlongCount; i++) {
WriteRegUlong(r_LUTData, *(BrushData + i));
}
Exit(L"HwBrush");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -