📄 mode.c
字号:
//
// Permedia3 Sample Display Driver
// mode.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This module exposes the code necessary to mange the display mode table.
// This includes managing the current mode that the display is set in.
// The actual table itself is here as well.
#include "pch.h" // Precompiled header support.
#include "debug.h"
#include "const.h"
#include "struct.h"
#include "proto.h"
#include "register.h"
// How many iterations do we wait for the clocks to latch? A somewhat
// arbitrary constant.
#define LOCK_TIMEOUT 0x100000
// All of the display modes we support use 8 pixel characters.
#define PIXELS_PER_CHAR 8
// This is a table of all of the display modes supported by this driver.
// It is derived from the VESA Standard Monitor Timing Specifications.
#define NEG 0
#define POS 1
static const PERM3_VIDEO_MODE l_VideoModeTable[] =
{
// 640x480
{ 640, 100, 2, 12, 6, NEG, 480, 525, 10, 2, 33, NEG, 60, 251750 },
{ 640, 104, 3, 5, 16, NEG, 480, 520, 9, 3, 28, NEG, 72, 315000 },
{ 640, 105, 2, 8, 15, NEG, 480, 500, 1, 3, 16, NEG, 75, 315000 },
{ 640, 104, 7, 7, 10, NEG, 480, 509, 1, 3, 25, NEG, 85, 360000 },
// 640x350
{ 640, 104, 4, 8, 12, POS, 350, 445, 32, 3, 60, NEG, 85, 315000 },
// 640x400
{ 640, 104, 4, 8, 12, NEG, 400, 445, 1, 3, 41, POS, 85, 315000 },
// 720x400
{ 720, 104, 4, 8, 12, NEG, 400, 446, 1, 3, 42, POS, 85, 355000 },
// 800x600
{ 800, 128, 3, 9, 16, POS, 600, 625, 1, 2, 22, POS, 56, 360000 },
{ 800, 132, 5, 16, 11, POS, 600, 628, 1, 4, 23, POS, 60, 400000 },
{ 800, 130, 7, 15, 8, POS, 600, 666, 37, 6, 23, POS, 72, 500000 },
{ 800, 132, 2, 10, 20, POS, 600, 625, 1, 3, 21, POS, 75, 495000 },
{ 800, 131, 4, 8, 19, POS, 600, 631, 1, 3, 27, POS, 85, 562500 },
// 1024x768
{ 1024, 168, 3, 17, 20, NEG, 768, 806, 3, 6, 29, NEG, 60, 650000 },
{ 1024, 166, 3, 17, 18, NEG, 768, 806, 3, 6, 29, NEG, 70, 750000 },
{ 1024, 164, 2, 12, 22, POS, 768, 800, 1, 3, 28, POS, 75, 787500 },
{ 1024, 172, 6, 12, 26, POS, 768, 808, 1, 3, 36, POS, 85, 945000 },
// 1152x864
{ 1152, 200, 8, 16, 32, POS, 864, 900, 1, 3, 32, POS, 75, 1080000 },
// 1280x960
{ 1280, 225, 12, 14, 39, POS, 960, 1000, 1, 3, 36, POS, 60, 1080000 },
{ 1280, 216, 8, 20, 28, POS, 960, 1011, 1, 3, 47, POS, 85, 1485000 },
// 1280x1024
{ 1280, 211, 6, 14, 31, POS, 1024, 1066, 1, 3, 38, POS, 60, 1080000 },
{ 1280, 211, 2, 18, 31, POS, 1024, 1066, 1, 3, 38, POS, 75, 1350000 },
{ 1280, 216, 8, 20, 28, POS, 1024, 1072, 1, 3, 44, POS, 85, 1575000 },
// 1600x1200
{ 1600, 270, 8, 24, 38, POS, 1200, 1250, 1, 3, 46, POS, 60, 1620000 },
{ 1600, 270, 8, 24, 38, POS, 1200, 1250, 1, 3, 46, POS, 65, 1755000 },
{ 1600, 270, 8, 24, 38, POS, 1200, 1250, 1, 3, 46, POS, 70, 1890000 },
{ 1600, 270, 8, 24, 38, POS, 1200, 1250, 1, 3, 46, POS, 75, 2025000 },
{ 1600, 270, 8, 24, 38, POS, 1200, 1250, 1, 3, 46, POS, 85, 2295000 }
};
#undef NEG
#undef POS
// The total number of entries in the l_VideoModeTable.
static const ULONG l_NumVideoModeTable = sizeof(l_VideoModeTable) / sizeof(l_VideoModeTable[0]);
// This sub table contains the various mask arrays for the pixel formats we
// support for the primary surface.
static const ULONG l_PixelTableFormats[][4] = {
{ 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 },
{ 0x0000001F, 0x000003E0, 0x00007C00, 0x00008000 },
{ 0x0000000F, 0x000000F0, 0x00000F00, 0x0000F000 },
{ 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 },
{ 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 },
{ 0x00007C00, 0x000003E0, 0x0000001F, 0x00008000 },
{ 0x00000F00, 0x000000F0, 0x0000000F, 0x0000F000 },
{ 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }
};
// This is the table of all of the RGB pixel formats supported by this driver.
// (Pixel formats for use as a primary surface.)
static const PERM3_FORMAT l_PixelTable[] =
{
// See table on 4-73 in the Permedia3 Reference Guide. We use the formats
// marked Front or not marked at all (Back is the RAMDAC overlay format
// for the OpenGL ICD.) We disregard the "Off" semantic as we never turn
// on the RAMDAC overlay. Note that we always use linear color extension,
// reflected in the RDColorFormat values.
// BGR formats
{ FOURCC_RGB, 32, l_PixelTableFormats[0], FALSE, 64 }, // 8888
{ FOURCC_RGB, 16, l_PixelTableFormats[1], FALSE, 65 }, // 5551
{ FOURCC_RGB, 16, l_PixelTableFormats[2], FALSE, 66 }, // 4444
{ FOURCC_RGB, 16, l_PixelTableFormats[3], FALSE, 80 }, // 565
// RGB formats
{ FOURCC_RGB, 32, l_PixelTableFormats[4], FALSE, 96 }, // 8888
{ FOURCC_RGB, 16, l_PixelTableFormats[5], FALSE, 97 }, // 5551
{ FOURCC_RGB, 16, l_PixelTableFormats[6], FALSE, 98 }, // 4444
{ FOURCC_RGB, 16, l_PixelTableFormats[7], FALSE, 112 } // 565
};
// The total number of entries in the l_PixelTable.
static const ULONG l_NumPixelTable = sizeof(l_PixelTable) / sizeof(l_PixelTable[0]);
// A sentinal value for l_CurrentDisplayMode. Indicates that no mode is currently
// set.
static const ULONG l_NoCurrentMode = 0xFFFFFFFF;
// This is the display mode table. It is built at run-time, according to the
// amount of video memory available and other constraints. Each entry is an
// index to a video mode and to a pixel format.
static PERM3_DISPLAY_MODE * l_DisplayModeTable;
// The total number of entries in the l_DisplayModeTable.
static ULONG l_NumDisplayModeTable;
// This is the current display mode we are set in.
static ULONG l_CurrentDisplayMode;
// This structure contains detials of the primary surface, wrapped up in a way
// that is useful for other modules of the driver to work with.
static PERM3_SURFACE l_PrimarySurface;
// Internal prototypes. These functions are not exposed outside this module.
static ULONG
ComputeStride(
USHORT VideoMode,
USHORT PixelFormat
);
static ULONG
ComputeMemRequired(
USHORT VideoMode,
USHORT PixelFormat
);
static void
RamdacSetMode(
USHORT VideoMode,
USHORT PixelFormat
);
static void
PrimarySurfaceSetMode(
USHORT VideoMode,
USHORT PixelFormat
);
static void
VideoSetMode(
USHORT VideoMode,
USHORT PixelFormat
);
static void
MiscSetMode(
USHORT VideoMode,
USHORT PixelFormat
);
static ULONG
CalculateMNPForClock(
ULONG RefClockFrequency,
ULONG RequiredFrequency,
BYTE * ReturnM,
BYTE * ReturnN,
BYTE * ReturnP
);
static ULONG
CharToOctWord(
ULONG CharCount,
USHORT PixelFormat
);
BOOL
InitializeModes()
{
// InitializeModes
// This function uses the configuration information gathered up to this
// point in the initialization process to build a mode table by looking at
// permutations of video modes and pixel formats against constriants.
// Local variables.
BOOL FnRetVal = FALSE; // Return value for this function.
PERM3_DISPLAY_MODE * TempDisplayMode = NULL;
ULONG NumValidDisplayMode = 0;
ULONG SizeofValidDisplayMode;
USHORT i,j;
Enter(L"InitializeModes");
// Allocate space as if all permutations of video mode and pixel formats
// are going to be valid.
TempDisplayMode = (PERM3_DISPLAY_MODE *)SystemAlloc(sizeof(PERM3_DISPLAY_MODE) * l_NumVideoModeTable * l_NumPixelTable);
if (TempDisplayMode) {
// Run through all of the permutations of the pixel format and the
// resolution. Right now, the only constriant we are working against is the
// amount of memory available on the device: modes that consume more vram
// than the amount avilable are not recorded.
for (i = 0; i < l_NumVideoModeTable; i++) {
for (j = 0; j < l_NumPixelTable; j++) {
if (ComputeMemRequired(i,j) < GetFreeVideoMem()) {
// Yup, it's good.
TempDisplayMode[NumValidDisplayMode].VideoMode = i;
TempDisplayMode[NumValidDisplayMode].PixelFormat = j;
NumValidDisplayMode++;
}
}
}
// Allocate space for the real display mode table, of the correct size,
// and copy the display mode table to it.
SizeofValidDisplayMode = sizeof(PERM3_DISPLAY_MODE) * NumValidDisplayMode;
l_DisplayModeTable = (PERM3_DISPLAY_MODE *)SystemAlloc(SizeofValidDisplayMode);
if (l_DisplayModeTable) {
l_NumDisplayModeTable = NumValidDisplayMode;
memcpy(l_DisplayModeTable, TempDisplayMode, SizeofValidDisplayMode);
// No mode is currently set. So flag it.
l_CurrentDisplayMode = l_NoCurrentMode;
memset(&l_PrimarySurface, 0, sizeof(l_PrimarySurface));
Message(L"Display mode table initialized.\n");
FnRetVal = TRUE;
}
else {
Error(L"System memory allocation failure!\n");
}
SystemFree(TempDisplayMode);
}
else {
Error(L"System memory allocation failure!\n");
}
Exit(L"InitializeModes");
return FnRetVal;
}
ULONG
GetCurrentMode()
{
// GetCurrentMode
// Retuns mode number for the display mode that the device is currently
// operating in. This function is inlined, hence the lack of the
// Enter/Exit convention.
return l_CurrentDisplayMode;
}
ULONG
GetDisplayModeCount()
{
// GetDisplayModeCount
// Returns a count of the number of valid display modes. This function is
// inlined, hence the lack of the Enter/Exit convention.
return l_NumDisplayModeTable;
}
ULONG
GetDisplayModeWidth(
ULONG ModeNumber
)
{
// GetDisplayModeWidth
// Returns the number of pixels wide in the video mode associated with the
// display mode whose number is passed. This is inline, hence no Enter/Exit
// calls.
// Check parameters.
Assert(ModeNumber < GetDisplayModeCount());
return l_VideoModeTable[l_DisplayModeTable[ModeNumber].VideoMode].HResolution;
}
ULONG
GetDisplayModeHeight(
ULONG ModeNumber
)
{
// GetDisplayModeHeight
// Returns the number of lines high in the video mode associated with the
// display mode whose number is passed. This is inline, hence no Enter/Exit
// calls.
// Check parameters.
Assert(ModeNumber < GetDisplayModeCount());
return l_VideoModeTable[l_DisplayModeTable[ModeNumber].VideoMode].VResolution;
}
ULONG
GetDisplayModeBPP(
ULONG ModeNumber
)
{
// GetDisplayModeBPP
// Returns the number of bits per pixel in the pixel format associated with
// the display mode whose number is passed. This is inline, hence no
// Enter/Exit calls.
// Check parameters.
Assert(ModeNumber < GetDisplayModeCount());
return l_PixelTable[l_DisplayModeTable[ModeNumber].PixelFormat].BitsPerPixel;
}
ULONG
GetDisplayModeStride(
ULONG ModeNumber
)
{
// GetDisplayModeStride
// This function returns the number of bytes per scanline for the given
// display mode. It relies on the internal function ComputeStride to do most
// of the work. No Enter/Exit semantics, as this should be inlined.
// Check parameters.
Assert(ModeNumber < GetDisplayModeCount());
return ComputeStride(l_DisplayModeTable[ModeNumber].VideoMode,
l_DisplayModeTable[ModeNumber].PixelFormat);
}
void
GetDisplayModeMasks(
ULONG ModeNumber,
ULONG * RedMask,
ULONG * GreenMask,
ULONG * BlueMask,
ULONG * AlphaMask
)
{
// GetDisplayModeMasks
// This function loads the ULONGs that the user provides pointers to with
// the red, green, blue and alpha masks for the mode given. No Enter/Exit
// semantics for this function, as it should be inlined.
// Local variables.
const PERM3_FORMAT * Format;
// Check parameters.
Assert(ModeNumber < GetDisplayModeCount());
AssertWritePtr(RedMask, sizeof(ULONG));
AssertWritePtr(GreenMask, sizeof(ULONG));
AssertWritePtr(BlueMask, sizeof(ULONG));
AssertWritePtr(AlphaMask, sizeof(ULONG));
// Save some derefrences.
Format = &l_PixelTable[l_DisplayModeTable[ModeNumber].PixelFormat];
*RedMask = Format->Masks[RED_MASK];
*GreenMask = Format->Masks[GREEN_MASK];
*BlueMask = Format->Masks[BLUE_MASK];
*AlphaMask = Format->Masks[ALPHA_MASK];
}
const PERM3_FORMAT *
GetDisplayModeFormat(
ULONG ModeNumber
)
{
// GetDisplayModeFormat
// This function returns a full PERM3_FORMAT structure pointer for the
// given display mode. No Enter/Exit semantics for this inline candidate.
// Check parameters.
Assert(ModeNumber < GetDisplayModeCount());
return (&l_PixelTable[l_DisplayModeTable[ModeNumber].PixelFormat]);
}
ULONG
GetDisplayModeFrequency(
ULONG ModeNumber
)
{
// GetDisplayModeFrequency
// This function returns the frequency that the monito is refreshing at for
// the given display mode. No Enter/Exit semantics for this inline candidate.
// Check parameters.
Assert(ModeNumber < GetDisplayModeCount());
return l_VideoModeTable[l_DisplayModeTable[ModeNumber].VideoMode].Frequency;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -