Start source tree (final, I hope!) restructuration. Part 1/X
[reactos.git] / reactos / win32ss / core / drivers / displays / framebufacc / screen.c
1 /*
2 * ReactOS Generic Framebuffer display driver
3 *
4 * Copyright (C) 2004 Filip Navara
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "framebufacc.h"
22
23 /*
24 * GetAvailableModes
25 *
26 * Calls the miniport to get the list of modes supported by the kernel driver,
27 * and returns the list of modes supported by the display driver.
28 */
29
30 DWORD
31 GetAvailableModes(
32 HANDLE hDriver,
33 PVIDEO_MODE_INFORMATION *ModeInfo,
34 DWORD *ModeInfoSize)
35 {
36 ULONG ulTemp;
37 VIDEO_NUM_MODES Modes;
38 PVIDEO_MODE_INFORMATION ModeInfoPtr;
39
40 /*
41 * Get the number of modes supported by the mini-port
42 */
43
44 if (EngDeviceIoControl(hDriver, IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES, NULL,
45 0, &Modes, sizeof(VIDEO_NUM_MODES), &ulTemp))
46 {
47 return 0;
48 }
49
50 *ModeInfoSize = Modes.ModeInformationLength;
51
52 /*
53 * Allocate the buffer for the miniport to write the modes in.
54 */
55
56 *ModeInfo = (PVIDEO_MODE_INFORMATION)EngAllocMem(0, Modes.NumModes *
57 Modes.ModeInformationLength, ALLOC_TAG);
58
59 if (*ModeInfo == NULL)
60 {
61 return 0;
62 }
63
64 /*
65 * Ask the miniport to fill in the available modes.
66 */
67
68 if (EngDeviceIoControl(hDriver, IOCTL_VIDEO_QUERY_AVAIL_MODES, NULL, 0,
69 *ModeInfo, Modes.NumModes * Modes.ModeInformationLength,
70 &ulTemp))
71 {
72 EngFreeMem(*ModeInfo);
73 *ModeInfo = (PVIDEO_MODE_INFORMATION)NULL;
74 return 0;
75 }
76
77 /*
78 * Now see which of these modes are supported by the display driver.
79 * As an internal mechanism, set the length to 0 for the modes we
80 * DO NOT support.
81 */
82
83 ulTemp = Modes.NumModes;
84 ModeInfoPtr = *ModeInfo;
85
86 /*
87 * Mode is rejected if it is not one plane, or not graphics, or is not
88 * one of 8, 16 or 32 bits per pel.
89 */
90
91 while (ulTemp--)
92 {
93 /* FIXME add banked graphic mode */
94 if ((ModeInfoPtr->NumberOfPlanes != 1) ||
95 !(ModeInfoPtr->AttributeFlags & VIDEO_MODE_GRAPHICS) ||
96 ((ModeInfoPtr->BitsPerPlane != 8) &&
97 (ModeInfoPtr->BitsPerPlane != 16) &&
98 (ModeInfoPtr->BitsPerPlane != 24) &&
99 (ModeInfoPtr->BitsPerPlane != 32)))
100 {
101 ModeInfoPtr->Length = 0;
102 }
103
104 ModeInfoPtr = (PVIDEO_MODE_INFORMATION)
105 (((PUCHAR)ModeInfoPtr) + Modes.ModeInformationLength);
106 }
107
108 return Modes.NumModes;
109 }
110
111 BOOL
112 IntInitScreenInfo(
113 PPDEV ppdev,
114 LPDEVMODEW pDevMode,
115 PGDIINFO pGdiInfo,
116 PDEVINFO pDevInfo)
117 {
118 ULONG ModeCount;
119 ULONG ModeInfoSize;
120 PVIDEO_MODE_INFORMATION ModeInfo, ModeInfoPtr, SelectedMode = NULL;
121 VIDEO_COLOR_CAPABILITIES ColorCapabilities;
122 /* hack
123 LOGFONTW SystemFont = {16, 7, 0, 0, 700, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_DONTCARE, L"System"};
124 LOGFONTW AnsiVariableFont = {12, 9, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_STROKE_PRECIS, PROOF_QUALITY, VARIABLE_PITCH | FF_DONTCARE, L"MS Sans Serif"};
125 LOGFONTW AnsiFixedFont = {12, 9, 0, 0, 400, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_STROKE_PRECIS, PROOF_QUALITY, FIXED_PITCH | FF_DONTCARE, L"Courier"};
126 */
127 ULONG Temp;
128
129 /*
130 * Call miniport to get information about video modes.
131 */
132
133 ModeCount = GetAvailableModes(ppdev->hDriver, &ModeInfo, &ModeInfoSize);
134 if (ModeCount == 0)
135 {
136 return FALSE;
137 }
138
139 /*
140 * Select the video mode depending on the info passed in pDevMode.
141 */
142
143 if (pDevMode->dmPelsWidth == 0 && pDevMode->dmPelsHeight == 0 &&
144 pDevMode->dmBitsPerPel == 0 && pDevMode->dmDisplayFrequency == 0)
145 {
146 ModeInfoPtr = ModeInfo;
147 while (ModeCount-- > 0)
148 {
149 if (ModeInfoPtr->Length == 0)
150 {
151 ModeInfoPtr = (PVIDEO_MODE_INFORMATION)
152 (((PUCHAR)ModeInfoPtr) + ModeInfoSize);
153 continue;
154 }
155 SelectedMode = ModeInfoPtr;
156 break;
157 }
158 }
159 else
160 {
161 ModeInfoPtr = ModeInfo;
162 while (ModeCount-- > 0)
163 {
164 if (ModeInfoPtr->Length > 0 &&
165 pDevMode->dmPelsWidth == ModeInfoPtr->VisScreenWidth &&
166 pDevMode->dmPelsHeight == ModeInfoPtr->VisScreenHeight &&
167 pDevMode->dmBitsPerPel == (ModeInfoPtr->BitsPerPlane *
168 ModeInfoPtr->NumberOfPlanes) &&
169 pDevMode->dmDisplayFrequency == ModeInfoPtr->Frequency)
170 {
171 SelectedMode = ModeInfoPtr;
172 break;
173 }
174
175 ModeInfoPtr = (PVIDEO_MODE_INFORMATION)
176 (((PUCHAR)ModeInfoPtr) + ModeInfoSize);
177 }
178 }
179
180 if (SelectedMode == NULL)
181 {
182 EngFreeMem(ModeInfo);
183 return FALSE;
184 }
185
186 /*
187 * Fill in the GDIINFO data structure with the information returned from
188 * the kernel driver.
189 */
190
191 ppdev->ModeIndex = SelectedMode->ModeIndex;
192 ppdev->ScreenWidth = SelectedMode->VisScreenWidth;
193 ppdev->ScreenHeight = SelectedMode->VisScreenHeight;
194 ppdev->ScreenDelta = SelectedMode->ScreenStride;
195 ppdev->BitsPerPixel = SelectedMode->BitsPerPlane * SelectedMode->NumberOfPlanes;
196
197 ppdev->MemWidth = SelectedMode->VideoMemoryBitmapWidth;
198 ppdev->MemHeight = SelectedMode->VideoMemoryBitmapHeight;
199
200 ppdev->RedMask = SelectedMode->RedMask;
201 ppdev->GreenMask = SelectedMode->GreenMask;
202 ppdev->BlueMask = SelectedMode->BlueMask;
203
204 pGdiInfo->ulVersion = GDI_DRIVER_VERSION;
205 pGdiInfo->ulTechnology = DT_RASDISPLAY;
206 pGdiInfo->ulHorzSize = SelectedMode->XMillimeter;
207 pGdiInfo->ulVertSize = SelectedMode->YMillimeter;
208 pGdiInfo->ulHorzRes = SelectedMode->VisScreenWidth;
209 pGdiInfo->ulVertRes = SelectedMode->VisScreenHeight;
210 pGdiInfo->ulPanningHorzRes = SelectedMode->VisScreenWidth;
211 pGdiInfo->ulPanningVertRes = SelectedMode->VisScreenHeight;
212 pGdiInfo->cBitsPixel = SelectedMode->BitsPerPlane;
213 pGdiInfo->cPlanes = SelectedMode->NumberOfPlanes;
214 pGdiInfo->ulVRefresh = SelectedMode->Frequency;
215 pGdiInfo->ulBltAlignment = 1;
216 pGdiInfo->ulLogPixelsX = pDevMode->dmLogPixels;
217 pGdiInfo->ulLogPixelsY = pDevMode->dmLogPixels;
218 pGdiInfo->flTextCaps = TC_RA_ABLE;
219 pGdiInfo->flRaster = 0;
220 pGdiInfo->ulDACRed = SelectedMode->NumberRedBits;
221 pGdiInfo->ulDACGreen = SelectedMode->NumberGreenBits;
222 pGdiInfo->ulDACBlue = SelectedMode->NumberBlueBits;
223 pGdiInfo->ulAspectX = 0x24;
224 pGdiInfo->ulAspectY = 0x24;
225 pGdiInfo->ulAspectXY = 0x33;
226 pGdiInfo->xStyleStep = 1;
227 pGdiInfo->yStyleStep = 1;
228 pGdiInfo->denStyleStep = 3;
229 pGdiInfo->ptlPhysOffset.x = 0;
230 pGdiInfo->ptlPhysOffset.y = 0;
231 pGdiInfo->szlPhysSize.cx = 0;
232 pGdiInfo->szlPhysSize.cy = 0;
233
234 /*
235 * Try to get the color info from the miniport.
236 */
237
238 if (!EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES,
239 NULL, 0, &ColorCapabilities,
240 sizeof(VIDEO_COLOR_CAPABILITIES), &Temp))
241 {
242 pGdiInfo->ciDevice.Red.x = ColorCapabilities.RedChromaticity_x;
243 pGdiInfo->ciDevice.Red.y = ColorCapabilities.RedChromaticity_y;
244 pGdiInfo->ciDevice.Green.x = ColorCapabilities.GreenChromaticity_x;
245 pGdiInfo->ciDevice.Green.y = ColorCapabilities.GreenChromaticity_y;
246 pGdiInfo->ciDevice.Blue.x = ColorCapabilities.BlueChromaticity_x;
247 pGdiInfo->ciDevice.Blue.y = ColorCapabilities.BlueChromaticity_y;
248 pGdiInfo->ciDevice.AlignmentWhite.x = ColorCapabilities.WhiteChromaticity_x;
249 pGdiInfo->ciDevice.AlignmentWhite.y = ColorCapabilities.WhiteChromaticity_y;
250 pGdiInfo->ciDevice.AlignmentWhite.Y = ColorCapabilities.WhiteChromaticity_Y;
251 if (ColorCapabilities.AttributeFlags & VIDEO_DEVICE_COLOR)
252 {
253 pGdiInfo->ciDevice.RedGamma = ColorCapabilities.RedGamma;
254 pGdiInfo->ciDevice.GreenGamma = ColorCapabilities.GreenGamma;
255 pGdiInfo->ciDevice.BlueGamma = ColorCapabilities.BlueGamma;
256 }
257 else
258 {
259 pGdiInfo->ciDevice.RedGamma = ColorCapabilities.WhiteGamma;
260 pGdiInfo->ciDevice.GreenGamma = ColorCapabilities.WhiteGamma;
261 pGdiInfo->ciDevice.BlueGamma = ColorCapabilities.WhiteGamma;
262 }
263 }
264 else
265 {
266 pGdiInfo->ciDevice.Red.x = 6700;
267 pGdiInfo->ciDevice.Red.y = 3300;
268 pGdiInfo->ciDevice.Green.x = 2100;
269 pGdiInfo->ciDevice.Green.y = 7100;
270 pGdiInfo->ciDevice.Blue.x = 1400;
271 pGdiInfo->ciDevice.Blue.y = 800;
272 pGdiInfo->ciDevice.AlignmentWhite.x = 3127;
273 pGdiInfo->ciDevice.AlignmentWhite.y = 3290;
274 pGdiInfo->ciDevice.AlignmentWhite.Y = 0;
275 pGdiInfo->ciDevice.RedGamma = 20000;
276 pGdiInfo->ciDevice.GreenGamma = 20000;
277 pGdiInfo->ciDevice.BlueGamma = 20000;
278 }
279
280 pGdiInfo->ciDevice.Red.Y = 0;
281 pGdiInfo->ciDevice.Green.Y = 0;
282 pGdiInfo->ciDevice.Blue.Y = 0;
283 pGdiInfo->ciDevice.Cyan.x = 0;
284 pGdiInfo->ciDevice.Cyan.y = 0;
285 pGdiInfo->ciDevice.Cyan.Y = 0;
286 pGdiInfo->ciDevice.Magenta.x = 0;
287 pGdiInfo->ciDevice.Magenta.y = 0;
288 pGdiInfo->ciDevice.Magenta.Y = 0;
289 pGdiInfo->ciDevice.Yellow.x = 0;
290 pGdiInfo->ciDevice.Yellow.y = 0;
291 pGdiInfo->ciDevice.Yellow.Y = 0;
292 pGdiInfo->ciDevice.MagentaInCyanDye = 0;
293 pGdiInfo->ciDevice.YellowInCyanDye = 0;
294 pGdiInfo->ciDevice.CyanInMagentaDye = 0;
295 pGdiInfo->ciDevice.YellowInMagentaDye = 0;
296 pGdiInfo->ciDevice.CyanInYellowDye = 0;
297 pGdiInfo->ciDevice.MagentaInYellowDye = 0;
298 pGdiInfo->ulDevicePelsDPI = 0;
299 pGdiInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA;
300 pGdiInfo->ulHTPatternSize = HT_PATSIZE_4x4_M;
301 pGdiInfo->flHTFlags = HT_FLAG_ADDITIVE_PRIMS;
302
303 pDevInfo->flGraphicsCaps = 0;
304 /* hack
305 pDevInfo->lfDefaultFont = SystemFont;
306 pDevInfo->lfAnsiVarFont = AnsiVariableFont;
307 pDevInfo->lfAnsiFixFont = AnsiFixedFont;
308 */
309 pDevInfo->cFonts = 0;
310 pDevInfo->cxDither = 0;
311 pDevInfo->cyDither = 0;
312 pDevInfo->hpalDefault = 0;
313 pDevInfo->flGraphicsCaps2 = 0;
314
315 if (ppdev->BitsPerPixel == 8)
316 {
317 pGdiInfo->ulNumColors = 20;
318 pGdiInfo->ulNumPalReg = 1 << ppdev->BitsPerPixel;
319 pGdiInfo->ulHTOutputFormat = HT_FORMAT_8BPP;
320 pDevInfo->flGraphicsCaps |= GCAPS_PALMANAGED;
321 pDevInfo->iDitherFormat = BMF_8BPP;
322 /* Assuming palette is orthogonal - all colors are same size. */
323 ppdev->PaletteShift = 8 - pGdiInfo->ulDACRed;
324 }
325 else
326 {
327 pGdiInfo->ulNumColors = (ULONG)(-1);
328 pGdiInfo->ulNumPalReg = 0;
329 switch (ppdev->BitsPerPixel)
330 {
331 case 16:
332 pGdiInfo->ulHTOutputFormat = HT_FORMAT_16BPP;
333 pDevInfo->iDitherFormat = BMF_16BPP;
334 break;
335
336 case 24:
337 pGdiInfo->ulHTOutputFormat = HT_FORMAT_24BPP;
338 pDevInfo->iDitherFormat = BMF_24BPP;
339 break;
340
341 default:
342 pGdiInfo->ulHTOutputFormat = HT_FORMAT_32BPP;
343 pDevInfo->iDitherFormat = BMF_32BPP;
344 }
345 }
346
347 EngFreeMem(ModeInfo);
348 return TRUE;
349 }
350
351 /*
352 * DrvGetModes
353 *
354 * Returns the list of available modes for the device.
355 *
356 * Status
357 * @implemented
358 */
359
360 ULONG APIENTRY
361 DrvGetModes(
362 IN HANDLE hDriver,
363 IN ULONG cjSize,
364 OUT DEVMODEW *pdm)
365 {
366 ULONG ModeCount;
367 ULONG ModeInfoSize;
368 PVIDEO_MODE_INFORMATION ModeInfo, ModeInfoPtr;
369 ULONG OutputSize;
370
371 ModeCount = GetAvailableModes(hDriver, &ModeInfo, &ModeInfoSize);
372 if (ModeCount == 0)
373 {
374 return 0;
375 }
376
377 if (pdm == NULL)
378 {
379 EngFreeMem(ModeInfo);
380 return ModeCount * sizeof(DEVMODEW);
381 }
382
383 /*
384 * Copy the information about supported modes into the output buffer.
385 */
386
387 OutputSize = 0;
388 ModeInfoPtr = ModeInfo;
389
390 while (ModeCount-- > 0)
391 {
392 if (ModeInfoPtr->Length == 0)
393 {
394 ModeInfoPtr = (PVIDEO_MODE_INFORMATION)(((ULONG_PTR)ModeInfoPtr) + ModeInfoSize);
395 continue;
396 }
397
398 memset(pdm, 0, sizeof(DEVMODEW));
399 memcpy(pdm->dmDeviceName, DEVICE_NAME, sizeof(DEVICE_NAME));
400 pdm->dmSpecVersion =
401 pdm->dmDriverVersion = DM_SPECVERSION;
402 pdm->dmSize = sizeof(DEVMODEW);
403 pdm->dmDriverExtra = 0;
404 pdm->dmBitsPerPel = ModeInfoPtr->NumberOfPlanes * ModeInfoPtr->BitsPerPlane;
405 pdm->dmPelsWidth = ModeInfoPtr->VisScreenWidth;
406 pdm->dmPelsHeight = ModeInfoPtr->VisScreenHeight;
407 pdm->dmDisplayFrequency = ModeInfoPtr->Frequency;
408 pdm->dmDisplayFlags = 0;
409 pdm->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
410 DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS;
411
412 ModeInfoPtr = (PVIDEO_MODE_INFORMATION)(((ULONG_PTR)ModeInfoPtr) + ModeInfoSize);
413 pdm = (LPDEVMODEW)(((ULONG_PTR)pdm) + sizeof(DEVMODEW));
414 OutputSize += sizeof(DEVMODEW);
415 }
416
417 EngFreeMem(ModeInfo);
418 return OutputSize;
419 }