📄 misc.c
字号:
//
// Permedia3 Sample Display Driver
// misc.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This module contains various utility routines that don't fit into any
// of the other source modules.
#include "pch.h" // Precompiled header support.
#include "debug.h"
#include "struct.h"
#include "proto.h"
// Dumb little helper macro.
#define TwoToThe(a) (1 << (a))
// These tables allows us an easy conversion from a GDI format value to a
// useable PERM3_FORMAT structure. We only use these if we are not given an
// XLATEOBJ to extract mask info from.
// The masks and palettes are from the Platform Builder documentation on
// display formats.
static const ULONG l_Perm3FormatLookup1BppPalette[] = {
0x00000000, // 0 = Black
0x00FFFFFF // 1 = White
};
static const ULONG l_Perm3FormatLookup2BppPalette[] = {
0x00000000, // 0 = Black
0x00808080, // 1 = Dark gray
0x00C0C0C0, // 2 = Light gray
0x00FFFFFF // 3 = White
};
static const ULONG l_Perm3FormatLookup4BppPalette[] = {
0x00000000, // 0 = Black
0x00000080, // 1 = Dark red
0x000000FF, // 2 = Red
0x00008000, // 3 = Dark green
0x00008080, // 4 = Dark yellow
0x0000FF00, // 5 = Green
0x0000FFFF, // 6 = Yellow
0x00800000, // 7 = Dark blue
0x00800080, // 8 = Dark purple
0x00808000, // 9 = Dark teal
0x00808080, // 10 = Dark gray
0x00C0C0C0, // 11 = Light gray
0x00FF0000, // 12 = Blue
0x00FF00FF, // 13 = Purple
0x00FFFF00, // 14 = Teal
0x00FFFFFF // 15 = White
};
static const ULONG l_Perm3FormatLookup8BppPalette[] = {
0x00000000, // 0 = Black
0x00000080, // 1 = Dark red
0x000000FF, // 2 = Red
0x00008000, // 3 = Dark green
0x00008080, // 4 = Dark yellow
0x0000FF00, // 5 = Green
0x0000FFFF, // 6 = Yellow
0x00800000, // 7 = Dark blue
0x00800080, // 8 = Dark purple
0x00808000, // 9 = Dark teal
0x00808080, // 10 = Dark gray
0x00C0C0C0, // 11 = Light gray
0x00FF0000, // 12 = Blue
0x00FF00FF, // 13 = Purple
0x00FFFF00, // 14 = Teal
0x00FFFFFF // 15 = White
// !TODO! what's the rest of the standard windows 8bpp palette?
};
static const ULONG l_Perm3FormatLookupMasks[][4] = {
// Red Green Blue Alpha
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, // NULL format
{ 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, // 565
{ 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } // 888
};
static const PERM3_FORMAT l_Perm3FormatLookup[] = {
{ 0, 0, l_Perm3FormatLookupMasks[0], FALSE, 0 },
{ FOURCC_PAL, 1, l_Perm3FormatLookup1BppPalette, FALSE, 0 },
{ FOURCC_PAL, 4, l_Perm3FormatLookup4BppPalette, FALSE, 0 },
{ FOURCC_PAL, 8, l_Perm3FormatLookup8BppPalette, FALSE, 0 },
{ FOURCC_RGB, 16, l_Perm3FormatLookupMasks[1], FALSE, 0 },
{ FOURCC_RGB, 24, l_Perm3FormatLookupMasks[2], FALSE, 0 },
{ FOURCC_RGB, 32, l_Perm3FormatLookupMasks[2], FALSE, 0 },
{ 0, 0, l_Perm3FormatLookupMasks[0], FALSE, 0 },
{ 0, 0, l_Perm3FormatLookupMasks[0], FALSE, 0 },
{ FOURCC_PAL, 2, l_Perm3FormatLookup2BppPalette, FALSE, 0 }
};
static const ULONG l_NumPerm3FormatLookup = sizeof(l_Perm3FormatLookup) / sizeof(PERM3_FORMAT);
// We also keep cached PERM3_FORMAT structures that pertain to the GDI RGB and
// BGR formats.
static const ULONG l_RGBMasks[4] = {
0x000000FF,
0x0000FF00,
0x00FF0000,
0x00000000
};
static const PERM3_FORMAT l_RGBFormat = {
FOURCC_RGB,
24,
l_RGBMasks
};
static const ULONG l_BGRMasks[4] = {
0x00FF0000,
0x0000FF00,
0x000000FF,
0x00000000
};
static const PERM3_FORMAT l_BGRFormat = {
FOURCC_RGB,
24,
l_BGRMasks
};
// Internal prototypes. These functions are not exposed outside this module.
static void
LoadPaletteMasks(
PERM3_FORMAT * Format,
XLATEOBJ * Xlate,
ULONG Fields,
ULONG Entries
);
ULONG
GdiFormatToBPP(
ULONG GdiFormat
)
{
// GdiFormatToBPP
// This function converts a GDI format value to an integer bits per
// pixel value. No Enter/Exit semantics as this function should be
// inlined.
// Local constants.
// This lookup table is derived from the BMF_*BPP macros in the
// winddi.h header file. 0s are set in the undefined format values.
const ULONG Lookup[] = { 0, 1, 4, 8, 16, 24, 32, 0, 0, 2 };
const ULONG NumLookup = sizeof(Lookup) / sizeof(ULONG);
// Check parameters.
Assert(GdiFormat < NumLookup);
return (Lookup[GdiFormat]);
}
ULONG
BPPToGdiFormat(
ULONG BitsPerPixel
)
{
// BPPToGdiFormat
// This function converts a bits per pixel integer to a GDI format
// value. No Enter/Exit semantics are used as this function should be
// inlined.
// Local variables.
ULONG GdiFormat;
// Check parameters.
// BitsPerPixel is check implicitly by the code.
// The BMF_*BPP macros are defined in winddi.h.
switch (BitsPerPixel) {
case 1: GdiFormat = BMF_1BPP; break;
case 2: GdiFormat = BMF_2BPP; break;
case 4: GdiFormat = BMF_4BPP; break;
case 8: GdiFormat = BMF_8BPP; break;
case 16: GdiFormat = BMF_16BPP; break;
case 24: GdiFormat = BMF_24BPP; break;
case 32: GdiFormat = BMF_32BPP; break;
default:
Error(L"Unknown BitsPerPixel = %d.\n", BitsPerPixel);
GdiFormat = 0;
break;
}
return GdiFormat;
}
const PERM3_FORMAT *
GdiFormatToPerm3Format(
ULONG GdiFormat
)
{
// GdiFormatToPerm3Format
// This function returns a filled out PERM3_FORMAT structure (from a table)
// coresponding to the given GDI format value. No Enter/Exit semantics
// for inlined functions.
// Check parameters.
Assert(GdiFormat < l_NumPerm3FormatLookup);
return (&l_Perm3FormatLookup[GdiFormat]);
}
void
SurfobjToPerm3Surface(
PERM3_SURFACE * Perm3Surface,
SURFOBJ * Surfobj,
XLATEOBJ * Xlate,
BOOL Source
)
{
// SurfobjToPerm3Surface
// This function converts a GDI SURFOBJ into a PERM3_SURFACE structure. We
// will be able to use the pointer we stored in the SURFOBJ for video
// memory allocations. Other times, when we haven't seen the surface
// before, we will need to fill out the Perm3Surface by hand.
// We'll use the Xlateobj to get our format detail if it's avialable.
// Otherwise, we have sensible defualts available through
// GdiFormatToPerm3Format.
// Local variables.
PERM3_SURFACE * Dhsurf;
PERM3_FORMAT * Format;
// Check parameters.
Assert(sizeof(SIZE) == sizeof(SIZEL));
// !TODO!
Enter(L"SurfobjToPerm3Surface");
Dhsurf = (PERM3_SURFACE *)(Surfobj->dhsurf);
if (Dhsurf != NULL) {
// If there is a Dhsurf, it mean's that this is a "device managed" surface.
// It was created by DrvCreateDeviceBitmap, and the PERM3_SURFACE data
// is all already available.
memcpy(Perm3Surface,
Dhsurf,
sizeof(PERM3_SURFACE));
}
else {
// GDI created this suface on it's own. Do it the hard way.
Perm3Surface->Ptr = Surfobj->pvScan0;
// We copy from a SIZEL to a SIZE. This is protected by the assert above.
memcpy(&Perm3Surface->Size,
&Surfobj->sizlBitmap,
sizeof(SIZE));
Perm3Surface->Stride = Surfobj->lDelta;
Perm3Surface->Type = SystemMemory;
// Now, the format may be given by the XLATEOBJ, in which case we copy
// it out. If not, we rely on GdiFormatToPerm3Format to provide a
// reasonable default.
if (Xlate && Xlate->flXlate != XO_TRIVIAL) {
switch (Source ? Xlate->iSrcType : Xlate->iDstType) {
case PAL_INDEXED:
Format = (PERM3_FORMAT *)SystemAlloc(sizeof(PERM3_FORMAT));
if (Format != NULL) {
Format->BitsPerPixel = GdiFormatToBPP(Surfobj->iBitmapFormat);
Format->FourCC = FOURCC_PAL;
// The XLATEOBJ identifies a number of special case translations,
// generally, we need only deal with those special cases when
// we are looking for a palette.
if ((Xlate->flXlate == XO_TABLE && Source) ||
(Xlate->flXlate == XO_TO_MONO && Format->BitsPerPixel == 1)) {
// GDI has already prepared a lookup table. Use it.
Format->Palette = Xlate->pulXlate;
Format->FreePaletteMasks = FALSE;
}
else {
LoadPaletteMasks(Format,
Xlate,
(Source) ? XO_SRCPALETTE : XO_DESTPALETTE,
TwoToThe(Format->BitsPerPixel));
}
Perm3Surface->FreeFormat = TRUE;
Perm3Surface->Format = (const FORMAT *)Format;
}
else {
Error(L"System memory allocation failure.\n");
}
break;
case PAL_BITFIELDS:
Format = (PERM3_FORMAT *)SystemAlloc(sizeof(PERM3_FORMAT));
if (Format != NULL) {
Format->BitsPerPixel = GdiFormatToBPP(Surfobj->iBitmapFormat);
Format->FourCC = FOURCC_RGB;
LoadPaletteMasks(Format,
Xlate,
(Source) ? XO_SRCBITFIELDS : XO_DESTBITFIELDS,
4);
Perm3Surface->FreeFormat = TRUE;
Perm3Surface->Format = (const FORMAT *)Format;
}
else {
Error(L"System memory allocation failure.\n");
}
break;
case PAL_RGB:
// We have a cached PERM3_FORMAT for RGB.
Perm3Surface->FreeFormat = FALSE;
Perm3Surface->Format = (const FORMAT *)&l_RGBFormat;
break;
case PAL_BGR:
// We have a cached PERM3_FORMAT for BGR.
Perm3Surface->FreeFormat = FALSE;
Perm3Surface->Format = (const FORMAT *)&l_BGRFormat;
break;
default:
Error(L"Unknown surface type in Xlateobj.\n");
break;
}
}
else {
Perm3Surface->FreeFormat = FALSE;
Perm3Surface->Format = (const FORMAT *)GdiFormatToPerm3Format(Surfobj->iBitmapFormat);
}
}
Exit(L"SurfobjToPerm3Surface");
}
void
FreeSurfobjDerivedPerm3Surface(
PERM3_SURFACE * Perm3Surface
)
{
// FreeSurfobjDerivedPerm3Surface
// This function is used to cleanup the Perm3Surface structures created
// by SurfobjToPerm3Surface. It handles freeing the format and masks
// if necessary.
// Local variables.
PERM3_FORMAT * Format;
// Check parameters.
// !TODO!
Enter(L"FreeSurfobjDerivedPerm3Surface");
Format = (PERM3_FORMAT *)(Perm3Surface->Format);
if (Format->FreePaletteMasks) {
// Again, note that the fact that Masks and Palette are a union means that
// this also handles paletted formats.
SystemFree((ULONG *)Format->Masks);
}
if (Perm3Surface->FreeFormat) {
SystemFree(Format);
}
Exit(L"FreeSurfobjDerivedPerm3Surface");
}
const PERM3_FORMAT *
GetRGBFormat()
{
// GetRGBFormat
// This function returns a PERM3_FORMAT coresponding to GDI's conception
// of a 24 bpp, xRGB color format, which we happen to have cached locally.
// No Enter/Exit semantics are used for inlined functions.
return (&l_RGBFormat);
}
const PERM3_FORMAT *
GetBGRFormat()
{
// GetBGRFormat
// This function returns a PERM3_FORMAT coresponding to GDI's conception
// of a 24 bpp, xBGR color format, which we happen to have cached locally.
// No Enter/Exit semantics are used for inlined functions.
return (&l_BGRFormat);
}
ULONG
PackXY(
ULONG X,
ULONG Y
)
{
// PackXY
// Many Permedia3 registers require an (x,y) coordinate pair packed into
// a single 32 bit value. This function does just that. No Enter/Exit
// semantics for inlined functions.
return ((X & 0xFFFF) | ((Y & 0xFFFF) << 16));
}
ULONG
Abs(
LONG Value
)
{
// Abs
// Return the absolute value of a signed value in an unsigned value. No
// Enter/Exit semantics for inlined code.
return ((ULONG)(Value > 0 ? Value : -Value));
}
void
LoadPaletteMasks(
PERM3_FORMAT * Format,
XLATEOBJ * Xlate,
ULONG Fields,
ULONG Entries
)
{
// LoadPaletteMasks
// This function extracts the Mask/Palette data from an XLATEOBJ. It assumes
// that at some later time, the Palette/Mask pointer will be freed. It
// sets a flag to enfore this.
// Local variables.
ULONG * Masks;
// Check parameters.
// !TODO!
// Note that Masks and Palette members of the FORMAT struct are in a union.
// Therefore, we can load both just by refering to Masks.
Enter(L"LoadPaletteMasks");
Masks = (ULONG *)SystemAlloc(sizeof(ULONG) * Entries);
if (Masks != NULL) {
if (!XLATEOBJ_cGetPalette(Xlate,
Fields,
Entries,
Masks) == 0) {
Format->FreePaletteMasks = TRUE;
Format->Masks = Masks;
}
else {
Error(L"XLATEOBJ failure.\n");
}
}
else {
Error(L"System memory allocation failure.\n");
}
Exit(L"LoadPaletteMasks");
}
ULONG
GetSizeofPaletteMasks(
const PERM3_FORMAT * Format
)
{
// GetSizeofPaletteMasks
// This function computes the number of bytes there should be in the
// palette/mask union array for a given format.
// Local variables.
ULONG SizeofPaletteMasks;
// Check parameters.
// !TODO!
Enter(L"GetSizeofPaletteMasks");
if (Format->FourCC == FOURCC_RGB) {
SizeofPaletteMasks = sizeof(ULONG) * 4;
}
else if (Format->FourCC == FOURCC_PAL) {
SizeofPaletteMasks = TwoToThe(Format->BitsPerPixel);
}
else {
Error(L"Unknown FourCC detected.\n");
SizeofPaletteMasks = 0;
}
Exit(L"GetSizeofPaletteMasks");
return (SizeofPaletteMasks);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -