Author: aandrejevic
Date: Fri Aug 26 01:22:00 2016
New Revision: 72464
URL:
http://svn.reactos.org/svn/reactos?rev=72464&view=rev
Log:
[NTVDM:SVGA]
Implement the extended wrapping control (64 KB / 1 MB).
Transpose the video memory so that it corresponds to chain-4 and packed-pixel
modes. This allows us to optimize video memory access, since the majority of all
SVGA modes are packed-pixel. Only VgaReadMemory has been optimized so far.
Modified:
trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c
trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hard…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.c [iso-8859-1] Fri Aug 26
01:22:00 2016
@@ -24,6 +24,9 @@
#include "../../console/video.h"
/* PRIVATE VARIABLES **********************************************************/
+
+#define WRAP_OFFSET(x) ((VgaCrtcRegisters[SVGA_CRTC_EXT_DISPLAY_REG] &
SVGA_CRTC_EXT_ADDR_WRAP) \
+ ? ((x) & 0xFFFFF) : LOWORD(x))
static CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
static CONST DWORD MemorySize[] = { 0x20000, 0x10000, 0x08000, 0x08000 };
@@ -330,45 +333,7 @@
}
}
-static inline DWORD VgaTranslateReadAddress(DWORD Address)
-{
- DWORD Offset = LOWORD(Address - VgaGetVideoBaseAddress());
- DWORD ExtOffset = ((VgaGcRegisters[SVGA_GC_EXT_MODE_REG] &
SVGA_GC_EXT_MODE_WND_B) && (Offset & (1 << 15)))
- ? VgaGcRegisters[SVGA_GC_OFFSET_1_REG]
- : VgaGcRegisters[SVGA_GC_OFFSET_0_REG];
- BYTE Plane;
-
- /* Check for chain-4 and odd-even mode */
- if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
- {
- /* The lowest two bits are the plane number */
- Plane = Offset & 0x03;
- Offset &= ~3;
- }
- else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
- {
- /* The LSB is the plane number */
- Plane = Offset & 0x01;
- Offset &= ~1;
- }
- else
- {
- /* Use the read mode */
- Plane = VgaGcRegisters[VGA_GC_READ_MAP_SEL_REG] & 0x03;
- }
-
- if (ExtOffset)
- {
- /* Add the extended offset */
- Offset += ExtOffset << ((VgaGcRegisters[SVGA_GC_EXT_MODE_REG] &
SVGA_GC_EXT_MODE_GRAN) ? 14 : 12);
- }
-
- /* Return the offset on plane 0 for read mode 1 */
- if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_READ) return Offset;
- else return Offset + Plane * SVGA_BANK_SIZE;
-}
-
-static inline DWORD VgaTranslateWriteAddress(DWORD Address)
+static inline DWORD VgaTranslateAddress(DWORD Address)
{
DWORD Offset = LOWORD(Address - VgaGetVideoBaseAddress());
DWORD ExtOffset = ((VgaGcRegisters[SVGA_GC_EXT_MODE_REG] &
SVGA_GC_EXT_MODE_WND_B) && (Offset & (1 << 15)))
@@ -867,17 +832,15 @@
if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT)
{
/* One byte per pixel */
- PixelData = VgaMemory[(X % VGA_NUM_BANKS) * SVGA_BANK_SIZE
- + LOWORD((Address + (X / VGA_NUM_BANKS))
- * AddressSize)];
+ PixelData = VgaMemory[WRAP_OFFSET((Address + (X / VGA_NUM_BANKS))
* AddressSize)
+ * VGA_NUM_BANKS + (X % VGA_NUM_BANKS)];
}
else
{
/* 4-bits per pixel */
- PixelData = VgaMemory[(X % VGA_NUM_BANKS) * SVGA_BANK_SIZE
- + LOWORD((Address + (X / (VGA_NUM_BANKS *
2)))
- * AddressSize)];
+ PixelData = VgaMemory[WRAP_OFFSET((Address + (X / (VGA_NUM_BANKS
* 2))) * AddressSize)
+ * VGA_NUM_BANKS + (X % VGA_NUM_BANKS)];
/* Check if we should use the highest 4 bits or lowest 4 */
if (((X / VGA_NUM_BANKS) % 2) == 0)
@@ -908,8 +871,8 @@
*/
DWORD BankNumber = (X / 4) % 2;
DWORD Offset = Address + (X / 8);
- BYTE LowPlaneData = VgaMemory[BankNumber * SVGA_BANK_SIZE +
LOWORD(Offset * AddressSize)];
- BYTE HighPlaneData = VgaMemory[(BankNumber + 2) * SVGA_BANK_SIZE
+ LOWORD(Offset * AddressSize)];
+ BYTE LowPlaneData = VgaMemory[WRAP_OFFSET(Offset * AddressSize) *
VGA_NUM_BANKS + BankNumber];
+ BYTE HighPlaneData = VgaMemory[WRAP_OFFSET(Offset * AddressSize)
* VGA_NUM_BANKS + (BankNumber + 2)];
/* Extract the two bits from each plane */
LowPlaneData = (LowPlaneData >> (6 - ((X % 4) * 2)))
& 0x03;
@@ -931,9 +894,7 @@
for (k = 0; k < VGA_NUM_BANKS; k++)
{
/* The data is on plane k, 4 pixels per byte */
- BYTE PlaneData = VgaMemory[k * SVGA_BANK_SIZE
- + LOWORD((Address + (X /
VGA_NUM_BANKS))
- * AddressSize)];
+ BYTE PlaneData = VgaMemory[WRAP_OFFSET((Address + (X >>
2)) * AddressSize) * VGA_NUM_BANKS + k];
/* The mask of the first bit in the pair */
BYTE BitMask = 1 << (((3 - (X % VGA_NUM_BANKS)) * 2) +
1);
@@ -951,9 +912,7 @@
for (k = 0; k < VGA_NUM_BANKS; k++)
{
- BYTE PlaneData = VgaMemory[k * SVGA_BANK_SIZE
- + LOWORD((Address + (X /
(VGA_NUM_BANKS * 2)))
- * AddressSize)];
+ BYTE PlaneData = VgaMemory[WRAP_OFFSET((Address + (X >>
3)) * AddressSize) * VGA_NUM_BANKS + k];
/* If the bit on that plane is set, set it */
if (PlaneData & (1 << (7 - (X % 8)))) PixelData |=
1 << k;
@@ -1084,13 +1043,13 @@
/* Loop through the characters */
for (j = 0; j < CurrResolution.X; j++)
{
- CurrentAddr = LOWORD((Address + j) * AddressSize);
+ CurrentAddr = WRAP_OFFSET((Address + j) * AddressSize);
/* Plane 0 holds the character itself */
- CharInfo.Char = VgaMemory[CurrentAddr];
+ CharInfo.Char = VgaMemory[CurrentAddr * VGA_NUM_BANKS];
/* Plane 1 holds the attribute */
- CharInfo.Attributes = VgaMemory[CurrentAddr + SVGA_BANK_SIZE];
+ CharInfo.Attributes = VgaMemory[CurrentAddr * VGA_NUM_BANKS + 1];
/* Now check if the resulting character data has changed */
if ((CharBuffer[i * CurrResolution.X + j].Char != CharInfo.Char) ||
@@ -1752,71 +1711,142 @@
VOID FASTCALL VgaReadMemory(ULONG Address, PVOID Buffer, ULONG Size)
{
+ DWORD i;
+ DWORD VideoAddress;
+ PUCHAR BufPtr = (PUCHAR)Buffer;
+
+ DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n", Address, Size);
+
+ /* Ignore if video RAM access is disabled */
+ if (!Size) return;
+ if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return;
+
+ if (!(VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_READ))
+ {
+ VideoAddress = VgaTranslateAddress(Address);
+
+ /* Check for chain-4 and odd-even mode */
+ if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4)
+ {
+ /* Just copy from the video memory */
+ PVOID VideoMemory = &VgaMemory[VideoAddress * VGA_NUM_BANKS + (Address
& 3)];
+
+ switch (Size)
+ {
+ case sizeof(UCHAR):
+ *(PUCHAR)Buffer = *(PUCHAR)VideoMemory;
+ return;
+
+ case sizeof(USHORT):
+ *(PUSHORT)Buffer = *(PUSHORT)VideoMemory;
+ return;
+
+ case sizeof(ULONG):
+ *(PULONG)Buffer = *(PULONG)VideoMemory;
+ return;
+
+ case sizeof(ULONGLONG):
+ *(PULONGLONG)Buffer = *(PULONGLONG)VideoMemory;
+ return;
+
+ default:
+#if defined(__GNUC__)
+ __builtin_memcpy(Buffer, VideoMemory, Size);
+#else
+ RtlCopyMemory(Buffer, VideoMemory, Size);
+#endif
+ }
+ }
+ else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE)
+ {
+ i = 0;
+
+ /* Check if the starting address is odd */
+ if (Address & 1) BufPtr[i++] = VgaMemory[(VideoAddress++) * VGA_NUM_BANKS
+ 1];
+
+ while (i < (Size - 1))
+ {
+ *(PUSHORT)&BufPtr[i] = *(PUSHORT)&VgaMemory[VideoAddress *
VGA_NUM_BANKS];
+
+ i += 2;
+ VideoAddress += 2;
+ }
+
+ /* Check if there is one more byte to read */
+ if (i == Size - 1) BufPtr[i] = VgaMemory[VideoAddress * VGA_NUM_BANKS +
((Address + i) & 1)];
+ }
+ else
+ {
+ /* Use the selected map */
+ BYTE Plane = VgaGcRegisters[VGA_GC_READ_MAP_SEL_REG] & 0x03;
+
+ for (i = 0; i < Size; i++)
+ {
+ /* Copy the value to the buffer */
+ BufPtr[i] = VgaMemory[(VideoAddress++) * VGA_NUM_BANKS + Plane];
+ }
+ }
+ }
+ else
+ {
+ const ULONG BitExpandTable[] =
+ {
+ 0x00000000, 0x000000FF, 0x0000FF00, 0x0000FFFF,
+ 0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00FFFFFF,
+ 0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFF00FFFF,
+ 0xFFFF0000, 0xFFFF00FF, 0xFFFFFF00, 0xFFFFFFFF
+ };
+
+ ULONG ColorCompareBytes = BitExpandTable[VgaGcRegisters[VGA_GC_COLOR_COMPARE_REG]
& 0x0F];
+ ULONG ColorIgnoreBytes = BitExpandTable[VgaGcRegisters[VGA_GC_COLOR_IGNORE_REG]
& 0x0F];
+
+ /*
+ * These values can also be computed in the following way, but using the table
seems to be faster:
+ *
+ * ColorCompareBytes = VgaGcRegisters[VGA_GC_COLOR_COMPARE_REG];
+ * ColorCompareBytes |= (ColorCompareBytes << 7) | (ColorCompareBytes
<< 14) | (ColorCompareBytes << 21);
+ * ColorCompareBytes &= 0x01010101;
+ * ColorCompareBytes = (ColorCompareBytes << 8) - ColorCompareBytes;
+ *
+ * ColorIgnoreBytes = VgaGcRegisters[VGA_GC_COLOR_IGNORE_REG];
+ * ColorIgnoreBytes |= (ColorIgnoreBytes << 7) | (ColorIgnoreBytes <<
14) | (ColorIgnoreBytes << 21);
+ * ColorIgnoreBytes &= 0x01010101;
+ * ColorIgnoreBytes = (ColorIgnoreBytes << 8) - ColorIgnoreBytes;
+ */
+
+ /* Loop through each byte */
+ for (i = 0; i < Size; i++)
+ {
+ ULONG PlaneData;
+
+ /* This should always return a plane 0 address */
+ VideoAddress = VgaTranslateAddress(Address + i);
+
+ /* Read all 4 planes */
+ PlaneData = *(PULONG)&VgaMemory[VideoAddress * VGA_NUM_BANKS];
+
+ /* Reverse the bytes for which the color compare register is zero */
+ PlaneData ^= ~ColorCompareBytes;
+
+ /* Apply the color ignore register */
+ PlaneData |= ColorIgnoreBytes;
+
+ /* Store the value in the buffer */
+ BufPtr[i] = (PlaneData | (PlaneData >> 8) | (PlaneData >> 16) |
(PlaneData >> 24)) & 0xFF;
+ }
+ }
+
+ /* Load the latch registers */
+ VideoAddress = VgaTranslateAddress(Address + Size - 1);
+ *(PULONG)VgaLatchRegisters = *(PULONG)&VgaMemory[WRAP_OFFSET(VideoAddress) *
VGA_NUM_BANKS];
+}
+
+BOOLEAN FASTCALL VgaWriteMemory(ULONG Address, PVOID Buffer, ULONG Size)
+{
DWORD i, j;
DWORD VideoAddress;
PUCHAR BufPtr = (PUCHAR)Buffer;
- DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n", Address, Size);
-
- /* Ignore if video RAM access is disabled */
- if ((VgaMiscRegister & VGA_MISC_RAM_ENABLED) == 0) return;
-
- if (!(VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_READ))
- {
- /* Loop through each byte */
- for (i = 0; i < Size; i++)
- {
- VideoAddress = VgaTranslateReadAddress(Address + i);
-
- /* Copy the value to the buffer */
- BufPtr[i] = VgaMemory[VideoAddress];
- }
- }
- else
- {
- /* Loop through each byte */
- for (i = 0; i < Size; i++)
- {
- BYTE Result = 0xFF;
-
- /* This should always return a plane 0 address for read mode 1 */
- VideoAddress = VgaTranslateReadAddress(Address + i);
-
- for (j = 0; j < VGA_NUM_BANKS; j++)
- {
- /* Don't consider ignored banks */
- if (!(VgaGcRegisters[VGA_GC_COLOR_IGNORE_REG] & (1 << j)))
continue;
-
- if (VgaGcRegisters[VGA_GC_COLOR_COMPARE_REG] & (1 << j))
- {
- /* Comparing with 11111111 */
- Result &= VgaMemory[j * SVGA_BANK_SIZE + LOWORD(VideoAddress)];
- }
- else
- {
- /* Comparing with 00000000 */
- Result &= ~(VgaMemory[j * SVGA_BANK_SIZE +
LOWORD(VideoAddress)]);
- }
- }
-
- /* Copy the value to the buffer */
- BufPtr[i] = Result;
- }
- }
-
- /* Load the latch registers */
- VgaLatchRegisters[0] = VgaMemory[LOWORD(VideoAddress)];
- VgaLatchRegisters[1] = VgaMemory[SVGA_BANK_SIZE + LOWORD(VideoAddress)];
- VgaLatchRegisters[2] = VgaMemory[(2 * SVGA_BANK_SIZE) + LOWORD(VideoAddress)];
- VgaLatchRegisters[3] = VgaMemory[(3 * SVGA_BANK_SIZE) + LOWORD(VideoAddress)];
-}
-
-BOOLEAN FASTCALL VgaWriteMemory(ULONG Address, PVOID Buffer, ULONG Size)
-{
- DWORD i, j;
- DWORD VideoAddress;
- PUCHAR BufPtr = (PUCHAR)Buffer;
-
DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n", Address, Size);
/* Ignore if video RAM access is disabled */
@@ -1828,7 +1858,7 @@
/* Loop through each byte */
for (i = 0; i < Size; i++)
{
- VideoAddress = VgaTranslateWriteAddress(Address + i);
+ VideoAddress = VgaTranslateAddress(Address + i);
for (j = 0; j < VGA_NUM_BANKS; j++)
{
@@ -1856,7 +1886,7 @@
}
/* Copy the value to the VGA memory */
- VgaMemory[VideoAddress + j * SVGA_BANK_SIZE] =
VgaTranslateByteForWriting(BufPtr[i], j);
+ VgaMemory[VideoAddress * VGA_NUM_BANKS + j] =
VgaTranslateByteForWriting(BufPtr[i], j);
}
}
@@ -1871,8 +1901,6 @@
VOID VgaWriteTextModeFont(UINT FontNumber, CONST UCHAR* FontData, UINT Height)
{
UINT i, j;
- PUCHAR FontMemory = (PUCHAR)&VgaMemory[SVGA_BANK_SIZE * VGA_FONT_BANK +
(FontNumber * VGA_FONT_SIZE)];
-
ASSERT(Height <= VGA_MAX_FONT_HEIGHT);
for (i = 0 ; i < VGA_FONT_CHARACTERS; i++)
@@ -1880,13 +1908,13 @@
/* Write the character */
for (j = 0; j < Height; j++)
{
- FontMemory[i * VGA_MAX_FONT_HEIGHT + j] = FontData[i * Height + j];
+ VgaMemory[(i * VGA_MAX_FONT_HEIGHT + j) * VGA_NUM_BANKS + VGA_FONT_BANK] =
FontData[i * Height + j];
}
/* Clear the unused part */
for (j = Height; j < VGA_MAX_FONT_HEIGHT; j++)
{
- FontMemory[i * VGA_MAX_FONT_HEIGHT + j] = 0;
+ VgaMemory[(i * VGA_MAX_FONT_HEIGHT + j) * VGA_NUM_BANKS + VGA_FONT_BANK] =
0;
}
}
}
Modified: trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/mvdm/ntvdm/hard…
==============================================================================
--- trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/mvdm/ntvdm/hardware/video/svga.h [iso-8859-1] Fri Aug 26
01:22:00 2016
@@ -190,6 +190,7 @@
/* CRTC extended display register bits */
#define SVGA_CRTC_EXT_ADDR_BIT16 (1 << 0)
+#define SVGA_CRTC_EXT_ADDR_WRAP (1 << 1)
#define SVGA_CRTC_EXT_ADDR_BITS1718 ((1 << 2) | (1 << 3))
#define SVGA_CRTC_EXT_OFFSET_BIT8 (1 << 4)