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