[WIN32K]
[reactos.git] / reactos / win32ss / drivers / displays / framebufacc / surface.c
1 /*
2 * ReactOS Generic Framebuffer acclations display driver
3 *
4 * Copyright (C) 2004 Filip Navara
5 * Copyright (C) 2007 Magnus Olsen
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include "framebufacc.h"
23
24 BOOL
25 InitSurface(PPDEV ppdev,
26 BOOL bForcemapping)
27 {
28 VIDEO_MEMORY VideoMemory;
29 VIDEO_MEMORY_INFORMATION VideoMemoryInfo;
30 ULONG returnedDataLength;
31 ULONG RemappingNeeded = 0;
32 ULONG PointerMaxWidth = 0;
33 ULONG PointerMaxHeight = 0;
34
35 /*
36 * Set video mode of our adapter.
37 */
38
39 if (EngDeviceIoControl(ppdev->hDriver,
40 IOCTL_VIDEO_SET_CURRENT_MODE,
41 &(ppdev->ModeIndex),
42 sizeof(ULONG),
43 &RemappingNeeded,
44 sizeof(ULONG),
45 &returnedDataLength))
46 {
47 return FALSE;
48 }
49
50 /* Check if mapping is need it */
51 if ((!bForcemapping) &&
52 (!RemappingNeeded))
53 {
54 return TRUE;
55 }
56
57
58 /*
59 * Map the framebuffer into our memory.
60 */
61
62 VideoMemory.RequestedVirtualAddress = NULL;
63 if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_MAP_VIDEO_MEMORY,
64 &VideoMemory, sizeof(VIDEO_MEMORY),
65 &VideoMemoryInfo, sizeof(VIDEO_MEMORY_INFORMATION),
66 &returnedDataLength))
67 {
68 return FALSE;
69 }
70
71 /*
72 * Save the real video memory
73 */
74 ppdev->pRealVideoMem = VideoMemoryInfo.FrameBufferBase;
75 ppdev->VideoMemSize = VideoMemoryInfo.VideoRamLength;
76
77
78 /*
79 * Video memory cached
80 *
81 * We maby should only ask max 8MB as cached ?, think of the video ram length is 256MB
82 */
83
84 ppdev->pVideoMemCache = NULL;
85 #ifdef EXPERIMENTAL_ACC_SUPPORT
86
87 ppdev->pVideoMemCache = EngAllocMem(0, (ULONG)VideoMemoryInfo.VideoRamLength, ALLOC_TAG);
88 if (ppdev->pVideoMemCache == NULL)
89 {
90 /* cached off for no avail system memory */
91 ppdev->ScreenPtr = VideoMemoryInfo.FrameBufferBase;
92 }
93 else
94
95 #endif
96 {
97 /* cached on, system memory is avail */
98 ppdev->ScreenPtr = ppdev->pRealVideoMem;
99 }
100
101 /* hw mouse pointer support */
102 PointerMaxHeight = ppdev->PointerCapabilities.MaxHeight;
103 PointerMaxWidth = ppdev->PointerCapabilities.MaxWidth * sizeof(ULONG);
104 if (ppdev->PointerCapabilities.Flags & VIDEO_MODE_COLOR_POINTER)
105 {
106 PointerMaxWidth = (ppdev->PointerCapabilities.MaxWidth + 7) / 8;
107 }
108
109 ppdev->PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) + ((sizeof(UCHAR) * PointerMaxWidth * PointerMaxHeight) << 1);
110
111 ppdev->pPointerAttributes = EngAllocMem(0, ppdev->PointerAttributesSize, ALLOC_TAG);
112
113 if (ppdev->pPointerAttributes != NULL)
114 {
115 ppdev->pPointerAttributes->Flags = ppdev->PointerCapabilities.Flags;
116 ppdev->pPointerAttributes->WidthInBytes = PointerMaxWidth;
117 ppdev->pPointerAttributes->Width = ppdev->PointerCapabilities.MaxWidth;
118 ppdev->pPointerAttributes->Height = PointerMaxHeight;
119 ppdev->pPointerAttributes->Column = 0;
120 ppdev->pPointerAttributes->Row = 0;
121 ppdev->pPointerAttributes->Enable = 0;
122 }
123 else
124 {
125 /* no hw mouse was avail */
126 ppdev->PointerAttributesSize = 0;
127 }
128
129 return TRUE;
130 }
131
132 /*
133 * DrvEnableSurface
134 *
135 * Create engine bitmap around frame buffer and set the video mode requested
136 * when PDEV was initialized.
137 *
138 * Status
139 * @implemented
140 */
141
142 HSURF APIENTRY
143 DrvEnableSurface(
144 IN DHPDEV dhpdev)
145 {
146 PPDEV ppdev = (PPDEV)dhpdev;
147 HSURF hSurface;
148 ULONG BitmapType;
149 SIZEL ScreenSize;
150
151
152 /* Setup surface and force the mapping */
153 if (!InitSurface(ppdev, TRUE))
154 {
155 return FALSE;
156 }
157
158 /* Rest the desktop vitual position */
159 ppdev->ScreenOffsetXY.x = 0;
160 ppdev->ScreenOffsetXY.y = 0;
161
162
163 switch (ppdev->BitsPerPixel)
164 {
165 case 8:
166 IntSetPalette(dhpdev, ppdev->PaletteEntries, 0, 256);
167 BitmapType = BMF_8BPP;
168 break;
169
170 case 16:
171 BitmapType = BMF_16BPP;
172 break;
173
174 case 24:
175 BitmapType = BMF_24BPP;
176 break;
177
178 case 32:
179 BitmapType = BMF_32BPP;
180 break;
181
182 default:
183 return FALSE;
184 }
185
186 ppdev->iDitherFormat = BitmapType;
187
188 ScreenSize.cx = ppdev->ScreenWidth;
189 ScreenSize.cy = ppdev->ScreenHeight;
190
191 hSurface = (HSURF)EngCreateBitmap(ScreenSize, ppdev->ScreenDelta, BitmapType,
192 (ppdev->ScreenDelta > 0) ? BMF_TOPDOWN : 0,
193 ppdev->ScreenPtr);
194 if (hSurface == NULL)
195 {
196 return FALSE;
197 }
198
199 /* Which api we hooking to */
200 ppdev->dwHooks = HOOK_BITBLT | HOOK_COPYBITS | HOOK_FILLPATH | HOOK_TEXTOUT | HOOK_STROKEPATH | HOOK_LINETO ;
201
202 /*
203 * Associate the surface with our device.
204 */
205
206
207 if (!EngAssociateSurface(hSurface, ppdev->hDevEng, ppdev->dwHooks))
208 {
209 EngDeleteSurface(hSurface);
210 return FALSE;
211 }
212
213 ppdev->hSurfEng = hSurface;
214
215 return hSurface;
216 }
217
218 /*
219 * DrvDisableSurface
220 *
221 * Used by GDI to notify a driver that the surface created by DrvEnableSurface
222 * for the current device is no longer needed.
223 *
224 * Status
225 * @implemented
226 */
227
228 VOID APIENTRY
229 DrvDisableSurface(
230 IN DHPDEV dhpdev)
231 {
232 DWORD ulTemp;
233 VIDEO_MEMORY VideoMemory;
234 PPDEV ppdev = (PPDEV)dhpdev;
235
236 EngDeleteSurface(ppdev->hSurfEng);
237 ppdev->hSurfEng = NULL;
238
239
240 /* Free the video memory cache */
241 if (ppdev->pVideoMemCache)
242 {
243 EngFreeMem(ppdev->pVideoMemCache);
244 }
245
246 /*
247 * Unmap the framebuffer.
248 */
249
250 VideoMemory.RequestedVirtualAddress = ppdev->pRealVideoMem;
251 EngDeviceIoControl(((PPDEV)dhpdev)->hDriver, IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
252 &VideoMemory, sizeof(VIDEO_MEMORY), NULL, 0, &ulTemp);
253
254 ppdev->pRealVideoMem = NULL;
255 ppdev->pVideoMemCache = NULL;
256
257 }
258
259 /*
260 * DrvAssertMode
261 *
262 * Sets the mode of the specified physical device to either the mode specified
263 * when the PDEV was initialized or to the default mode of the hardware.
264 *
265 * Status
266 * @implemented
267 */
268
269 BOOL APIENTRY
270 DrvAssertMode(
271 IN DHPDEV dhpdev,
272 IN BOOL bEnable)
273 {
274 PPDEV ppdev = (PPDEV)dhpdev;
275 ULONG ulTemp;
276 BOOLEAN Result = TRUE;
277
278 if (bEnable)
279 {
280 PVOID pRealVideoMem = ppdev->pRealVideoMem;
281
282 /* Setup surface and remapping if it need it */
283 if (!InitSurface(ppdev, FALSE))
284 {
285 Result = FALSE;
286 }
287 else
288 {
289 /* Check if we got same surface or not */
290 if (pRealVideoMem != ppdev->pRealVideoMem)
291 {
292 PVOID pVideoMem= NULL;
293
294 if (ppdev->pVideoMemCache == NULL)
295 {
296 pVideoMem = ppdev->pRealVideoMem;
297 }
298 else
299 {
300 pVideoMem = ppdev->pVideoMemCache;
301 }
302
303 Result = !EngModifySurface(ppdev->hSurfEng, ppdev->hDevEng,
304 ppdev->dwHooks | HOOK_SYNCHRONIZE,
305 0, (DHSURF)ppdev, pVideoMem,
306 ppdev->ScreenDelta, NULL);
307 }
308
309 /* if the pRealVideoMem == ppdev->pRealVideoMem are
310 * the Result is then TRUE
311 */
312 }
313
314 }
315 else
316 {
317 /*
318 * Call the miniport driver to reset the device to a known state.
319 */
320
321 Result = !EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_RESET_DEVICE,
322 NULL, 0, NULL, 0, &ulTemp);
323 }
324
325 return Result;
326 }