branch update for HEAD-2003021201
[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           //FIXME: in the loop below we should treat the case when SizeX is not divisible by 8, i.e. partial bytes
58       for (j = 0; j < SizeX>>3; j++, SrcOffset++, DestOffset++)
59         {
60           (VOID)READ_REGISTER_UCHAR(SrcOffset);
61           WRITE_REGISTER_UCHAR(DestOffset, 0);
62         }
63     }
64
65   /* Select write mode 2. */
66   WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
67   WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
68 }
69
70 VOID
71 VGADDI_BltToSavedScreenBits(PSAVED_SCREEN_BITS Dest,
72                             ULONG SourceX,
73                             ULONG SourceY,
74                             ULONG SizeX,
75                             ULONG SizeY)
76 {
77   PUCHAR DestOffset;
78   PUCHAR SrcOffset;
79   ULONG i, j;
80
81   /* Select write mode 1. */
82   WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
83   WRITE_PORT_UCHAR((PUCHAR)GRA_D, 1);
84
85   DestOffset = (PUCHAR)vidmem + Dest->Offset;
86
87   for (i = 0; i < SizeY; i++)
88     {
89       SrcOffset = (PUCHAR)vidmem + (SourceY + i) * 80 + (SourceX >> 3);
90           //FIXME: in the loop below we should treat the case when SizeX is not divisible by 8, i.e. partial bytes
91           for (j = 0; j < SizeX>>3; j++, SrcOffset++, DestOffset++)
92         {
93           (VOID)READ_REGISTER_UCHAR(SrcOffset);
94           WRITE_REGISTER_UCHAR(DestOffset, 0);
95         }
96     }
97
98   /* Select write mode 2. */
99   WRITE_PORT_UCHAR((PUCHAR)GRA_I, 5);
100   WRITE_PORT_UCHAR((PUCHAR)GRA_D, 2);
101 }
102
103 VOID
104 VGADDI_FreeSavedScreenBits(PSAVED_SCREEN_BITS SavedBits)
105 {
106   SavedBits->Free = TRUE;
107
108   if (SavedBits->ListEntry.Blink != &SavedBitsList)
109     {
110       PSAVED_SCREEN_BITS Previous;
111
112       Previous = CONTAINING_RECORD(SavedBits->ListEntry.Blink,
113                                    SAVED_SCREEN_BITS, ListEntry);
114       if (Previous->Free)
115         {
116           Previous->Size += SavedBits->Size;
117           RemoveEntryList(&SavedBits->ListEntry);
118           EngFreeMem(SavedBits);
119           SavedBits = Previous;
120         }
121     }
122   if (SavedBits->ListEntry.Flink != &SavedBitsList)
123     {
124       PSAVED_SCREEN_BITS Next;
125
126       Next = CONTAINING_RECORD(SavedBits->ListEntry.Flink, SAVED_SCREEN_BITS,
127                                ListEntry);
128       if (Next->Free)
129         {
130           SavedBits->Size += Next->Size;
131           RemoveEntryList(&SavedBits->ListEntry);
132           EngFreeMem(SavedBits);
133         }
134     }
135 }
136
137 PSAVED_SCREEN_BITS
138 VGADDI_AllocSavedScreenBits(ULONG Size)
139 {
140   PSAVED_SCREEN_BITS Current;
141   PLIST_ENTRY CurrentEntry;
142   PSAVED_SCREEN_BITS Best;
143   PSAVED_SCREEN_BITS New;
144
145   Best = NULL;
146   CurrentEntry = SavedBitsList.Flink;
147   while (CurrentEntry != &SavedBitsList)
148     {
149       Current = CONTAINING_RECORD(CurrentEntry, SAVED_SCREEN_BITS, ListEntry);
150
151       if (Current->Free && Current->Size >= Size &&
152           (Best == NULL || (Current->Size - Size) < (Best->Size - Size)))
153         {
154           Best = Current;
155         }
156
157       CurrentEntry = CurrentEntry->Flink;
158     }
159
160   if (Best == NULL)
161     {
162       return(NULL);
163     }
164   if (Best->Size == Size)
165     {
166       Best->Free = FALSE;
167       return(Best);
168     }
169   else
170     {
171       New = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG);
172       New->Free = FALSE;
173       New->Offset = Best->Offset + Size;
174       New->Size = Size;
175       Best->Size -= Size;
176       InsertHeadList(&Best->ListEntry, &New->ListEntry);
177       return(New);
178     }
179 }
180
181 VOID
182 VGADDI_InitializeOffScreenMem(ULONG Start, ULONG Length)
183 {
184   PSAVED_SCREEN_BITS FreeBits;
185
186   InitializeListHead(&SavedBitsList);
187
188   FreeBits = EngAllocMem(0, sizeof(SAVED_SCREEN_BITS), ALLOC_TAG);
189   FreeBits->Free = TRUE;
190   FreeBits->Offset = Start;
191   FreeBits->Size = Length;
192   InsertHeadList(&SavedBitsList, &FreeBits->ListEntry);
193 }