2004-01-10 14:39:21 +00:00
|
|
|
/*
|
2007-10-21 18:35:19 +00:00
|
|
|
* PROJECT: ReactOS VGA display driver
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2015-11-05 18:07:00 +00:00
|
|
|
* FILE: win32ss/drivers/displays/vga/objects/offscreen.c
|
2007-10-21 18:35:19 +00:00
|
|
|
* PURPOSE: Manages off-screen video memory
|
|
|
|
* PROGRAMMERS: Copyright (C) 1998-2001 ReactOS Team
|
2004-01-10 14:39:21 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
2007-10-31 09:45:15 +00:00
|
|
|
#include <vgaddi.h>
|
2004-01-10 14:39:21 +00:00
|
|
|
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
|
|
|
|
static LIST_ENTRY SavedBitsList;
|
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
|
|
|
VOID
|
2007-10-21 18:35:19 +00:00
|
|
|
VGADDI_BltFromSavedScreenBits(
|
|
|
|
IN ULONG DestX,
|
|
|
|
IN ULONG DestY,
|
|
|
|
IN PSAVED_SCREEN_BITS Src,
|
|
|
|
IN ULONG SizeX,
|
|
|
|
IN ULONG SizeY)
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
PUCHAR DestOffset;
|
|
|
|
PUCHAR SrcOffset;
|
|
|
|
ULONG i, j;
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
/* Select write mode 1. */
|
|
|
|
WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
|
|
|
|
WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1);
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
SrcOffset = (PUCHAR)vidmem + Src->Offset;
|
|
|
|
for (i = 0; i < SizeY; i++)
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
DestOffset = (PUCHAR)vidmem + (i + DestY) * 80 + (DestX >> 3);
|
|
|
|
//FIXME: in the loop below we should treat the case when SizeX is not divisible by 8, i.e. partial bytes
|
|
|
|
for (j = 0; j < SizeX>>3; j++, SrcOffset++, DestOffset++)
|
|
|
|
{
|
|
|
|
(VOID)READ_REGISTER_UCHAR(SrcOffset);
|
|
|
|
WRITE_REGISTER_UCHAR(DestOffset, 0);
|
|
|
|
}
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
/* Select write mode 2. */
|
|
|
|
WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
|
|
|
|
WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
2007-10-21 18:35:19 +00:00
|
|
|
VGADDI_BltToSavedScreenBits(
|
|
|
|
IN PSAVED_SCREEN_BITS Dest,
|
|
|
|
IN ULONG SourceX,
|
|
|
|
IN ULONG SourceY,
|
|
|
|
IN ULONG SizeX,
|
|
|
|
IN ULONG SizeY)
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
PUCHAR DestOffset;
|
|
|
|
PUCHAR SrcOffset;
|
|
|
|
ULONG i, j;
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
/* Select write mode 1. */
|
|
|
|
WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
|
|
|
|
WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1);
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
DestOffset = (PUCHAR)vidmem + Dest->Offset;
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
for (i = 0; i < SizeY; i++)
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
SrcOffset = (PUCHAR)vidmem + (SourceY + i) * 80 + (SourceX >> 3);
|
|
|
|
//FIXME: in the loop below we should treat the case when SizeX is not divisible by 8, i.e. partial bytes
|
|
|
|
for (j = 0; j < SizeX>>3; j++, SrcOffset++, DestOffset++)
|
|
|
|
{
|
|
|
|
(VOID)READ_REGISTER_UCHAR(SrcOffset);
|
|
|
|
WRITE_REGISTER_UCHAR(DestOffset, 0);
|
|
|
|
}
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
/* Select write mode 2. */
|
|
|
|
WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
|
|
|
|
WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
VGADDI_FreeSavedScreenBits(PSAVED_SCREEN_BITS SavedBits)
|
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
SavedBits->Free = TRUE;
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
if (SavedBits->ListEntry.Blink != &SavedBitsList)
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
PSAVED_SCREEN_BITS Previous;
|
|
|
|
|
|
|
|
Previous = CONTAINING_RECORD(SavedBits->ListEntry.Blink,
|
|
|
|
SAVED_SCREEN_BITS, ListEntry);
|
|
|
|
if (Previous->Free)
|
|
|
|
{
|
|
|
|
Previous->Size += SavedBits->Size;
|
|
|
|
RemoveEntryList(&SavedBits->ListEntry);
|
|
|
|
EngFreeMem(SavedBits);
|
|
|
|
SavedBits = Previous;
|
|
|
|
}
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|
2007-10-21 18:35:19 +00:00
|
|
|
if (SavedBits->ListEntry.Flink != &SavedBitsList)
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
PSAVED_SCREEN_BITS Next;
|
|
|
|
|
|
|
|
Next = CONTAINING_RECORD(SavedBits->ListEntry.Flink, SAVED_SCREEN_BITS,
|
|
|
|
ListEntry);
|
|
|
|
if (Next->Free)
|
|
|
|
{
|
|
|
|
SavedBits->Size += Next->Size;
|
|
|
|
RemoveEntryList(&SavedBits->ListEntry);
|
|
|
|
EngFreeMem(SavedBits);
|
|
|
|
}
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PSAVED_SCREEN_BITS
|
|
|
|
VGADDI_AllocSavedScreenBits(ULONG Size)
|
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
PSAVED_SCREEN_BITS Current;
|
|
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
PSAVED_SCREEN_BITS Best;
|
|
|
|
PSAVED_SCREEN_BITS New;
|
|
|
|
|
|
|
|
Best = NULL;
|
|
|
|
CurrentEntry = SavedBitsList.Flink;
|
|
|
|
while (CurrentEntry != &SavedBitsList)
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
Current = CONTAINING_RECORD(CurrentEntry, SAVED_SCREEN_BITS, ListEntry);
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
if (Current->Free && Current->Size >= Size &&
|
|
|
|
(Best == NULL || (Current->Size - Size) < (Best->Size - Size)))
|
|
|
|
{
|
|
|
|
Best = Current;
|
|
|
|
}
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
CurrentEntry = CurrentEntry->Flink;
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
if (!Best)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (Best->Size == Size)
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
Best->Free = FALSE;
|
|
|
|
return Best;
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|
2007-10-21 18:35:19 +00:00
|
|
|
else
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
New = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG);
|
|
|
|
New->Free = FALSE;
|
|
|
|
New->Offset = Best->Offset + Size;
|
|
|
|
New->Size = Size;
|
|
|
|
Best->Size -= Size;
|
|
|
|
InsertHeadList(&Best->ListEntry, &New->ListEntry);
|
|
|
|
return New;
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
2007-10-21 18:35:19 +00:00
|
|
|
VGADDI_InitializeOffScreenMem(
|
|
|
|
IN ULONG Start,
|
|
|
|
IN ULONG Length)
|
2004-01-10 14:39:21 +00:00
|
|
|
{
|
2007-10-21 18:35:19 +00:00
|
|
|
PSAVED_SCREEN_BITS FreeBits;
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
InitializeListHead(&SavedBitsList);
|
2004-01-10 14:39:21 +00:00
|
|
|
|
2007-10-21 18:35:19 +00:00
|
|
|
FreeBits = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG);
|
|
|
|
FreeBits->Free = TRUE;
|
|
|
|
FreeBits->Offset = Start;
|
|
|
|
FreeBits->Size = Length;
|
|
|
|
InsertHeadList(&SavedBitsList, &FreeBits->ListEntry);
|
2004-01-10 14:39:21 +00:00
|
|
|
}
|