:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / dd / vga / display / objects / offscreen.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * PROJECT:         ReactOS VGA16 display driver
22  * FILE:            drivers/dd/vga/display/objects/offscreen.c
23  * PURPOSE:         Manages off-screen video memory.
24  */
25
26 /* INCLUDES ******************************************************************/
27
28 #include "../vgaddi.h"
29 #include "../vgavideo/vgavideo.h"
30 #include <debug.h>
31
32 /* GLOBALS *******************************************************************/
33
34 static LIST_ENTRY SavedBitsList;
35
36 /* FUNCTIONS *****************************************************************/
37
38 VOID
39 VGADDI_BltFromSavedScreenBits(ULONG DestX,
40                               ULONG DestY,
41                               PSAVED_SCREEN_BITS Src,
42                               ULONG SizeX,
43                               ULONG SizeY)
44 {
45   PUCHAR DestOffset;
46   PUCHAR SrcOffset;
47   ULONG i, j;
48
49   /* Select write mode 1. */
50   WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
51   WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1);
52
53   SrcOffset = (PUCHAR)vidmem + Src->Offset;
54   for (i = 0; i < SizeY; i++)
55     {
56       DestOffset = (PUCHAR)vidmem + (i + DestY) * 80 + (DestX >> 3);
57       for (j = 0; j < SizeX; j++, SrcOffset++, DestOffset++)
58         {
59           (VOID)READ_REGISTER_UCHAR(SrcOffset);
60           WRITE_REGISTER_UCHAR(DestOffset, 0);
61         }
62     }
63
64   /* Select write mode 2. */
65   WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
66   WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
67 }
68
69 VOID
70 VGADDI_BltToSavedScreenBits(PSAVED_SCREEN_BITS Dest,
71                             ULONG SourceX,
72                             ULONG SourceY,
73                             ULONG SizeX,
74                             ULONG SizeY)
75 {
76   PUCHAR DestOffset;
77   PUCHAR SrcOffset;
78   ULONG i, j;
79
80   /* Select write mode 1. */
81   WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
82   WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1);
83
84   DestOffset = (PUCHAR)vidmem + Dest->Offset;
85
86   for (i = 0; i < SizeY; i++)
87     {
88       SrcOffset = (PUCHAR)vidmem + (SourceY + i) * 80 + (SourceX >> 3);
89       for (j = 0; j < SizeX; j++, SrcOffset++, DestOffset++)
90         {
91           (VOID)READ_REGISTER_UCHAR(SrcOffset);
92           WRITE_REGISTER_UCHAR(DestOffset, 0);
93         }
94     }
95
96   /* Select write mode 2. */
97   WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
98   WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
99 }
100
101 VOID
102 VGADDI_FreeSavedScreenBits(PSAVED_SCREEN_BITS SavedBits)
103 {
104   SavedBits->Free = TRUE;
105
106   if (SavedBits->ListEntry.Blink != &SavedBitsList)
107     {
108       PSAVED_SCREEN_BITS Previous;
109
110       Previous = CONTAINING_RECORD(SavedBits->ListEntry.Blink, 
111                                    SAVED_SCREEN_BITS, ListEntry);
112       if (Previous->Free)
113         {
114           Previous->Size += SavedBits->Size;
115           RemoveEntryList(&SavedBits->ListEntry);
116           EngFreeMem(SavedBits);
117           SavedBits = Previous;
118         }
119     }
120   if (SavedBits->ListEntry.Flink != &SavedBitsList)
121     {
122       PSAVED_SCREEN_BITS Next;
123
124       Next = CONTAINING_RECORD(SavedBits->ListEntry.Flink, SAVED_SCREEN_BITS, 
125                                ListEntry);
126       if (Next->Free)
127         {
128           SavedBits->Size += Next->Size;
129           RemoveEntryList(&SavedBits->ListEntry);
130           EngFreeMem(SavedBits);
131         }
132     }
133 }
134
135 PSAVED_SCREEN_BITS
136 VGADDI_AllocSavedScreenBits(ULONG Size)
137 {
138   PSAVED_SCREEN_BITS Current;
139   PLIST_ENTRY CurrentEntry;
140   PSAVED_SCREEN_BITS Best;
141   PSAVED_SCREEN_BITS New;
142
143   Best = NULL;
144   CurrentEntry = SavedBitsList.Flink;
145   while (CurrentEntry != &SavedBitsList)
146     {
147       Current = CONTAINING_RECORD(CurrentEntry, SAVED_SCREEN_BITS, ListEntry);
148
149       if (Current->Free && Current->Size >= Size &&
150           (Best == NULL || (Current->Size - Size) < (Best->Size - Size)))
151         {
152           Best = Current;
153         }
154
155       CurrentEntry = CurrentEntry->Flink;
156     }
157
158   if (Best == NULL)
159     {
160       return(NULL);
161     }
162   if (Best->Size == Size)
163     {
164       Best->Free = FALSE;
165       return(Best);
166     }
167   else
168     {
169       New = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG);
170       New->Free = FALSE;
171       New->Offset = Best->Offset + Size;
172       New->Size = Size;
173       Best->Size -= Size;
174       InsertHeadList(&Best->ListEntry, &New->ListEntry);
175       return(New);
176     }
177 }
178
179 VOID
180 VGADDI_InitializeOffScreenMem(ULONG Start, ULONG Length)
181 {
182   PSAVED_SCREEN_BITS FreeBits;
183
184   InitializeListHead(&SavedBitsList);
185
186   FreeBits = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG);
187   FreeBits->Free = TRUE;
188   FreeBits->Offset = Start;
189   FreeBits->Size = Length;
190   InsertHeadList(&SavedBitsList, &FreeBits->ListEntry);
191 }