- Do not recalculate at each refresh the new resolution that usually does not change (if it changes because of a modification of some VGA register, we detect that, and we change the vga mode). So keep the current resolution and use it in paint functions.
- Really reenter a new text/graphic mode when needed (ie. when alphanumeric bit and computed resolution change), this avoids useless console screenbuffers recreations (and flickering), things go faster, yet the VGA registers are still updated (as expected). See r65379, r65018 and r65015 for more details.

svn path=/trunk/; revision=65424
This commit is contained in:
Hermès Bélusca-Maïto 2014-11-17 00:12:20 +00:00
parent 9219f1f8ef
commit 5dbe74176e

View file

@ -284,12 +284,14 @@ static BOOLEAN ModeChanged = FALSE;
static BOOLEAN CursorChanged = FALSE;
static BOOLEAN PaletteChanged = FALSE;
static
enum SCREEN_MODE
typedef enum _SCREEN_MODE
{
TEXT_MODE,
GRAPHICS_MODE
} ScreenMode = TEXT_MODE;
} SCREEN_MODE, *PSCREEN_MODE;
static SCREEN_MODE ScreenMode = TEXT_MODE;
static COORD CurrResolution = {0};
static SMALL_RECT UpdateRectangle = { 0, 0, 0, 0 };
@ -920,8 +922,6 @@ static VOID VgaLeaveGraphicsMode(VOID)
static BOOL VgaEnterTextMode(PCOORD Resolution)
{
DPRINT1("VgaEnterTextMode\n");
/* Switch to the text buffer */
VgaSetActiveScreenBuffer(TextConsoleBuffer);
@ -977,7 +977,20 @@ static VOID VgaLeaveTextMode(VOID)
static VOID VgaChangeMode(VOID)
{
COORD Resolution = VgaGetDisplayResolution();
COORD NewResolution = VgaGetDisplayResolution();
SCREEN_MODE NewScreenMode =
!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) ? TEXT_MODE
: GRAPHICS_MODE;
/*
* No need to switch to a different screen mode + resolution
* if the new ones are the same as the old ones.
*/
if ((ScreenMode == NewScreenMode) &&
(CurrResolution.X == NewResolution.X && CurrResolution.Y == NewResolution.Y))
{
goto Quit;
}
if (ScreenMode == GRAPHICS_MODE)
{
@ -990,11 +1003,16 @@ static VOID VgaChangeMode(VOID)
VgaLeaveTextMode();
}
/* Update the current resolution */
CurrResolution = NewResolution;
/* The new screen mode will be updated via the VgaEnterText/GraphicsMode functions */
/* Check if the new mode is alphanumeric */
if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA))
if (NewScreenMode == TEXT_MODE)
{
/* Enter new text mode */
if (!VgaEnterTextMode(&Resolution))
if (!VgaEnterTextMode(&CurrResolution))
{
DisplayMessage(L"An unexpected VGA error occurred while switching into text mode. Error: %u", GetLastError());
EmulatorTerminate();
@ -1004,7 +1022,7 @@ static VOID VgaChangeMode(VOID)
else
{
/* Enter graphics mode */
if (!VgaEnterGraphicsMode(&Resolution))
if (!VgaEnterGraphicsMode(&CurrResolution))
{
DisplayMessage(L"An unexpected VGA error occurred while switching into graphics mode. Error: %u", GetLastError());
EmulatorTerminate();
@ -1012,12 +1030,14 @@ static VOID VgaChangeMode(VOID)
}
}
Quit:
/* Trigger a full update of the screen */
NeedsUpdate = TRUE;
UpdateRectangle.Left = 0;
UpdateRectangle.Top = 0;
UpdateRectangle.Right = Resolution.X;
UpdateRectangle.Bottom = Resolution.Y;
UpdateRectangle.Top = 0;
UpdateRectangle.Right = CurrResolution.X;
UpdateRectangle.Bottom = CurrResolution.Y;
/* Reset the mode change flag */
ModeChanged = FALSE;
@ -1026,7 +1046,6 @@ static VOID VgaChangeMode(VOID)
static VOID VgaUpdateFramebuffer(VOID)
{
SHORT i, j, k;
COORD Resolution = VgaGetDisplayResolution();
DWORD AddressSize = VgaGetAddressSize();
DWORD Address = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_START_ADDR_LOW_REG],
VgaCrtcRegisters[VGA_CRTC_START_ADDR_HIGH_REG]);
@ -1058,7 +1077,7 @@ static VOID VgaUpdateFramebuffer(VOID)
}
/* Loop through the scanlines */
for (i = 0; i < Resolution.Y; i++)
for (i = 0; i < CurrResolution.Y; i++)
{
if ((VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_OE) && (i & 1))
{
@ -1067,7 +1086,7 @@ static VOID VgaUpdateFramebuffer(VOID)
}
/* Loop through the pixels */
for (j = 0; j < Resolution.X; j++)
for (j = 0; j < CurrResolution.X; j++)
{
BYTE PixelData = 0;
@ -1189,13 +1208,13 @@ static VOID VgaUpdateFramebuffer(VOID)
if (DoubleWidth && DoubleHeight)
{
/* Now check if the resulting pixel data has changed */
if (GraphicsBuffer[(i * 2 * Resolution.X * 2) + (j * 2)] != PixelData)
if (GraphicsBuffer[(i * 2 * CurrResolution.X * 2) + (j * 2)] != PixelData)
{
/* Yes, write the new value */
GraphicsBuffer[(i * 2 * Resolution.X * 2) + (j * 2)] = PixelData;
GraphicsBuffer[(i * 2 * Resolution.X * 2) + (j * 2 + 1)] = PixelData;
GraphicsBuffer[((i * 2 + 1) * Resolution.X * 2) + (j * 2)] = PixelData;
GraphicsBuffer[((i * 2 + 1) * Resolution.X * 2) + (j * 2 + 1)] = PixelData;
GraphicsBuffer[(i * 2 * CurrResolution.X * 2) + (j * 2)] = PixelData;
GraphicsBuffer[(i * 2 * CurrResolution.X * 2) + (j * 2 + 1)] = PixelData;
GraphicsBuffer[((i * 2 + 1) * CurrResolution.X * 2) + (j * 2)] = PixelData;
GraphicsBuffer[((i * 2 + 1) * CurrResolution.X * 2) + (j * 2 + 1)] = PixelData;
/* Mark the specified pixel as changed */
VgaMarkForUpdate(i, j);
@ -1204,11 +1223,11 @@ static VOID VgaUpdateFramebuffer(VOID)
else if (DoubleWidth && !DoubleHeight)
{
/* Now check if the resulting pixel data has changed */
if (GraphicsBuffer[(i * Resolution.X * 2) + (j * 2)] != PixelData)
if (GraphicsBuffer[(i * CurrResolution.X * 2) + (j * 2)] != PixelData)
{
/* Yes, write the new value */
GraphicsBuffer[(i * Resolution.X * 2) + (j * 2)] = PixelData;
GraphicsBuffer[(i * Resolution.X * 2) + (j * 2 + 1)] = PixelData;
GraphicsBuffer[(i * CurrResolution.X * 2) + (j * 2)] = PixelData;
GraphicsBuffer[(i * CurrResolution.X * 2) + (j * 2 + 1)] = PixelData;
/* Mark the specified pixel as changed */
VgaMarkForUpdate(i, j);
@ -1217,11 +1236,11 @@ static VOID VgaUpdateFramebuffer(VOID)
else if (!DoubleWidth && DoubleHeight)
{
/* Now check if the resulting pixel data has changed */
if (GraphicsBuffer[(i * 2 * Resolution.X) + j] != PixelData)
if (GraphicsBuffer[(i * 2 * CurrResolution.X) + j] != PixelData)
{
/* Yes, write the new value */
GraphicsBuffer[(i * 2 * Resolution.X) + j] = PixelData;
GraphicsBuffer[((i * 2 + 1) * Resolution.X) + j] = PixelData;
GraphicsBuffer[(i * 2 * CurrResolution.X) + j] = PixelData;
GraphicsBuffer[((i * 2 + 1) * CurrResolution.X) + j] = PixelData;
/* Mark the specified pixel as changed */
VgaMarkForUpdate(i, j);
@ -1230,10 +1249,10 @@ static VOID VgaUpdateFramebuffer(VOID)
else // if (!DoubleWidth && !DoubleHeight)
{
/* Now check if the resulting pixel data has changed */
if (GraphicsBuffer[i * Resolution.X + j] != PixelData)
if (GraphicsBuffer[i * CurrResolution.X + j] != PixelData)
{
/* Yes, write the new value */
GraphicsBuffer[i * Resolution.X + j] = PixelData;
GraphicsBuffer[i * CurrResolution.X + j] = PixelData;
/* Mark the specified pixel as changed */
VgaMarkForUpdate(i, j);
@ -1268,10 +1287,10 @@ static VOID VgaUpdateFramebuffer(VOID)
CHAR_CELL CharInfo;
/* Loop through the scanlines */
for (i = 0; i < Resolution.Y; i++)
for (i = 0; i < CurrResolution.Y; i++)
{
/* Loop through the characters */
for (j = 0; j < Resolution.X; j++)
for (j = 0; j < CurrResolution.X; j++)
{
CurrentAddr = LOWORD((Address + j) * AddressSize);
@ -1282,11 +1301,11 @@ static VOID VgaUpdateFramebuffer(VOID)
CharInfo.Attributes = VgaMemory[CurrentAddr + VGA_BANK_SIZE];
/* Now check if the resulting character data has changed */
if ((CharBuffer[i * Resolution.X + j].Char != CharInfo.Char) ||
(CharBuffer[i * Resolution.X + j].Attributes != CharInfo.Attributes))
if ((CharBuffer[i * CurrResolution.X + j].Char != CharInfo.Char) ||
(CharBuffer[i * CurrResolution.X + j].Attributes != CharInfo.Attributes))
{
/* Yes, write the new value */
CharBuffer[i * Resolution.X + j] = CharInfo;
CharBuffer[i * CurrResolution.X + j] = CharInfo;
/* Mark the specified cell as changed */
VgaMarkForUpdate(i, j);
@ -1787,7 +1806,6 @@ COORD VgaGetDisplayResolution(VOID)
VOID VgaRefreshDisplay(VOID)
{
HANDLE ConsoleBufferHandle = NULL;
COORD Resolution;
/* Set the vertical retrace flag */
InVerticalRetrace = TRUE;
@ -1802,17 +1820,14 @@ VOID VgaRefreshDisplay(VOID)
/* Change the text cursor appearance */
if (CursorChanged) VgaUpdateTextCursor();
/* Retrieve the current resolution */
Resolution = VgaGetDisplayResolution();
if (PaletteChanged)
{
/* Trigger a full update of the screen */
NeedsUpdate = TRUE;
UpdateRectangle.Left = 0;
UpdateRectangle.Top = 0;
UpdateRectangle.Right = Resolution.X;
UpdateRectangle.Bottom = Resolution.Y;
UpdateRectangle.Top = 0;
UpdateRectangle.Right = CurrResolution.X;
UpdateRectangle.Bottom = CurrResolution.Y;
PaletteChanged = FALSE;
}