Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / win32ss / drivers / displays / vga / objects / offscreen.c
diff --git a/win32ss/drivers/displays/vga/objects/offscreen.c b/win32ss/drivers/displays/vga/objects/offscreen.c
new file mode 100644 (file)
index 0000000..66a0706
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * PROJECT:         ReactOS VGA display driver
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            win32ss/drivers/displays/vga/objects/offscreen.c
+ * PURPOSE:         Manages off-screen video memory
+ * PROGRAMMERS:     Copyright (C) 1998-2001 ReactOS Team
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <vgaddi.h>
+
+/* GLOBALS *******************************************************************/
+
+static LIST_ENTRY SavedBitsList;
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+VGADDI_BltFromSavedScreenBits(
+    IN ULONG DestX,
+    IN ULONG DestY,
+    IN PSAVED_SCREEN_BITS Src,
+    IN ULONG SizeX,
+    IN ULONG SizeY)
+{
+    PUCHAR DestOffset;
+    PUCHAR SrcOffset;
+    ULONG i, j;
+
+    /* Select write mode 1. */
+    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
+    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1);
+
+    SrcOffset = (PUCHAR)vidmem + Src->Offset;
+    for (i = 0; i < SizeY; i++)
+    {
+        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);
+        }
+    }
+
+    /* Select write mode 2. */
+    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
+    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
+}
+
+VOID
+VGADDI_BltToSavedScreenBits(
+    IN PSAVED_SCREEN_BITS Dest,
+    IN ULONG SourceX,
+    IN ULONG SourceY,
+    IN ULONG SizeX,
+    IN ULONG SizeY)
+{
+    PUCHAR DestOffset;
+    PUCHAR SrcOffset;
+    ULONG i, j;
+
+    /* Select write mode 1. */
+    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
+    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1);
+
+    DestOffset = (PUCHAR)vidmem + Dest->Offset;
+
+    for (i = 0; i < SizeY; i++)
+    {
+        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);
+        }
+    }
+
+    /* Select write mode 2. */
+    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
+    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
+}
+
+VOID
+VGADDI_FreeSavedScreenBits(PSAVED_SCREEN_BITS SavedBits)
+{
+    SavedBits->Free = TRUE;
+
+    if (SavedBits->ListEntry.Blink != &SavedBitsList)
+    {
+        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;
+        }
+    }
+    if (SavedBits->ListEntry.Flink != &SavedBitsList)
+    {
+        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);
+        }
+    }
+}
+
+PSAVED_SCREEN_BITS
+VGADDI_AllocSavedScreenBits(ULONG Size)
+{
+    PSAVED_SCREEN_BITS Current;
+    PLIST_ENTRY CurrentEntry;
+    PSAVED_SCREEN_BITS Best;
+    PSAVED_SCREEN_BITS New;
+
+    Best = NULL;
+    CurrentEntry = SavedBitsList.Flink;
+    while (CurrentEntry != &SavedBitsList)
+    {
+        Current = CONTAINING_RECORD(CurrentEntry, SAVED_SCREEN_BITS, ListEntry);
+
+        if (Current->Free && Current->Size >= Size &&
+            (Best == NULL || (Current->Size - Size) < (Best->Size - Size)))
+        {
+            Best = Current;
+        }
+
+        CurrentEntry = CurrentEntry->Flink;
+    }
+
+    if (!Best)
+      return NULL;
+
+    if (Best->Size == Size)
+    {
+        Best->Free = FALSE;
+        return Best;
+    }
+    else
+    {
+        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;
+    }
+}
+
+VOID
+VGADDI_InitializeOffScreenMem(
+    IN ULONG Start,
+    IN ULONG Length)
+{
+    PSAVED_SCREEN_BITS FreeBits;
+
+    InitializeListHead(&SavedBitsList);
+
+    FreeBits = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG);
+    FreeBits->Free = TRUE;
+    FreeBits->Offset = Start;
+    FreeBits->Size = Length;
+    InsertHeadList(&SavedBitsList, &FreeBits->ListEntry);
+}