2 * PROJECT: ReactOS Framebuffer Display Driver
3 * LICENSE: Microsoft NT4 DDK Sample Code License
4 * FILE: boot/drivers/video/displays/framebuf/screen.c
5 * PURPOSE: Surface, Screen and PDEV support/initialization
6 * PROGRAMMERS: Copyright (c) 1992-1995 Microsoft Corporation
7 * ReactOS Portable Systems Group
11 #define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_DONTCARE,L"System"}
12 #define HELVE_LOGFONT {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"}
13 #define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,FIXED_PITCH | FF_DONTCARE, L"Courier"}
15 // This is the basic devinfo for a default driver. This is used as a base and customized based
16 // on information passed back from the miniport driver.
18 const DEVINFO gDevInfoFrameBuffer
= {
21 ), /* Graphics capabilities */
22 SYSTM_LOGFONT
, /* Default font description */
23 HELVE_LOGFONT
, /* ANSI variable font description */
24 COURI_LOGFONT
, /* ANSI fixed font description */
25 0, /* Count of device fonts */
26 0, /* Preferred DIB format */
27 8, /* Width of color dither */
28 8, /* Height of color dither */
29 0 /* Default palette to use for this device */
32 /******************************Public*Routine******************************\
35 * Enables the surface. Maps the frame buffer into memory.
37 \**************************************************************************/
39 BOOL
bInitSURF(PPDEV ppdev
, BOOL bFirst
)
41 DWORD returnedDataLength
;
42 DWORD MaxWidth
, MaxHeight
;
43 VIDEO_MEMORY videoMemory
;
44 VIDEO_MEMORY_INFORMATION videoMemoryInformation
;
45 // eVb: 2.1 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
46 ULONG RemappingNeeded
= 0;
49 // Set the current mode into the hardware.
52 if (EngDeviceIoControl(ppdev
->hDriver
,
53 IOCTL_VIDEO_SET_CURRENT_MODE
,
56 // eVb: 2.2 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
62 RIP("DISP bInitSURF failed IOCTL_SET_MODE\n");
67 // If this is the first time we enable the surface we need to map in the
70 // eVb: 2.3 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
71 if (bFirst
|| RemappingNeeded
)
74 videoMemory
.RequestedVirtualAddress
= NULL
;
76 if (EngDeviceIoControl(ppdev
->hDriver
,
77 IOCTL_VIDEO_MAP_VIDEO_MEMORY
,
80 &videoMemoryInformation
,
81 sizeof(VIDEO_MEMORY_INFORMATION
),
84 RIP("DISP bInitSURF failed IOCTL_VIDEO_MAP\n");
88 ppdev
->pjScreen
= (PBYTE
)(videoMemoryInformation
.FrameBufferBase
);
90 if (videoMemoryInformation
.FrameBufferBase
!=
91 videoMemoryInformation
.VideoRamBase
)
93 RIP("VideoRamBase does not correspond to FrameBufferBase\n");
95 // eVb: 2.4 [DDK Change] - Make sure frame buffer mapping worked
97 // Make sure we can access this video memory
100 *(PULONG
)(ppdev
->pjScreen
) = 0xaa55aa55;
102 if (*(PULONG
)(ppdev
->pjScreen
) != 0xaa55aa55) {
104 DISPDBG((1, "Frame buffer memory is not accessible.\n"));
108 ppdev
->cScreenSize
= videoMemoryInformation
.VideoRamLength
;
111 // Initialize the head of the offscreen list to NULL.
114 ppdev
->pOffscreenList
= NULL
;
116 // It's a hardware pointer; set up pointer attributes.
118 MaxHeight
= ppdev
->PointerCapabilities
.MaxHeight
;
120 // Allocate space for two DIBs (data/mask) for the pointer. If this
121 // device supports a color Pointer, we will allocate a larger bitmap.
122 // If this is a color bitmap we allocate for the largest possible
123 // bitmap because we have no idea of what the pixel depth might be.
125 // Width rounded up to nearest byte multiple
127 if (!(ppdev
->PointerCapabilities
.Flags
& VIDEO_MODE_COLOR_POINTER
))
129 MaxWidth
= (ppdev
->PointerCapabilities
.MaxWidth
+ 7) / 8;
133 MaxWidth
= ppdev
->PointerCapabilities
.MaxWidth
* sizeof(DWORD
);
136 ppdev
->cjPointerAttributes
=
137 sizeof(VIDEO_POINTER_ATTRIBUTES
) +
138 ((sizeof(UCHAR
) * MaxWidth
* MaxHeight
) * 2);
140 ppdev
->pPointerAttributes
= (PVIDEO_POINTER_ATTRIBUTES
)
141 EngAllocMem(0, ppdev
->cjPointerAttributes
, ALLOC_TAG
);
143 if (ppdev
->pPointerAttributes
== NULL
) {
145 DISPDBG((0, "bInitPointer EngAllocMem failed\n"));
149 ppdev
->pPointerAttributes
->Flags
= ppdev
->PointerCapabilities
.Flags
;
150 ppdev
->pPointerAttributes
->WidthInBytes
= MaxWidth
;
151 ppdev
->pPointerAttributes
->Width
= ppdev
->PointerCapabilities
.MaxWidth
;
152 ppdev
->pPointerAttributes
->Height
= MaxHeight
;
153 ppdev
->pPointerAttributes
->Column
= 0;
154 ppdev
->pPointerAttributes
->Row
= 0;
155 ppdev
->pPointerAttributes
->Enable
= 0;
161 /******************************Public*Routine******************************\
164 * Disable the surface. Un-Maps the frame in memory.
166 \**************************************************************************/
168 VOID
vDisableSURF(PPDEV ppdev
)
170 DWORD returnedDataLength
;
171 VIDEO_MEMORY videoMemory
;
173 videoMemory
.RequestedVirtualAddress
= (PVOID
) ppdev
->pjScreen
;
175 if (EngDeviceIoControl(ppdev
->hDriver
,
176 IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
,
178 sizeof(VIDEO_MEMORY
),
181 &returnedDataLength
))
183 RIP("DISP vDisableSURF failed IOCTL_VIDEO_UNMAP\n");
188 /******************************Public*Routine******************************\
191 * Determine the mode we should be in based on the DEVMODE passed in.
192 * Query mini-port to get information needed to fill in the DevInfo and the
195 \**************************************************************************/
204 PVIDEO_MODE_INFORMATION pVideoBuffer
, pVideoModeSelected
, pVideoTemp
;
205 VIDEO_COLOR_CAPABILITIES colorCapabilities
;
211 // calls the miniport to get mode information.
214 cModes
= getAvailableModes(ppdev
->hDriver
, &pVideoBuffer
, &cbModeSize
);
222 // Now see if the requested mode has a match in that table.
225 pVideoModeSelected
= NULL
;
226 pVideoTemp
= pVideoBuffer
;
228 if ((pDevMode
->dmPelsWidth
== 0) &&
229 (pDevMode
->dmPelsHeight
== 0) &&
230 (pDevMode
->dmBitsPerPel
== 0) &&
231 (pDevMode
->dmDisplayFrequency
== 0))
233 DISPDBG((2, "Default mode requested"));
234 bSelectDefault
= TRUE
;
238 // eVb: 2.5 [DDK Change] - Add missing newlines to debug output
239 DISPDBG((2, "Requested mode...\n"));
240 DISPDBG((2, " Screen width -- %li\n", pDevMode
->dmPelsWidth
));
241 DISPDBG((2, " Screen height -- %li\n", pDevMode
->dmPelsHeight
));
242 DISPDBG((2, " Bits per pel -- %li\n", pDevMode
->dmBitsPerPel
));
243 DISPDBG((2, " Frequency -- %li\n", pDevMode
->dmDisplayFrequency
));
245 bSelectDefault
= FALSE
;
250 if (pVideoTemp
->Length
!= 0)
252 if (bSelectDefault
||
253 ((pVideoTemp
->VisScreenWidth
== pDevMode
->dmPelsWidth
) &&
254 (pVideoTemp
->VisScreenHeight
== pDevMode
->dmPelsHeight
) &&
255 (pVideoTemp
->BitsPerPlane
*
256 pVideoTemp
->NumberOfPlanes
== pDevMode
->dmBitsPerPel
) &&
257 (pVideoTemp
->Frequency
== pDevMode
->dmDisplayFrequency
)))
259 pVideoModeSelected
= pVideoTemp
;
260 DISPDBG((3, "Found a match\n")) ;
265 pVideoTemp
= (PVIDEO_MODE_INFORMATION
)
266 (((PUCHAR
)pVideoTemp
) + cbModeSize
);
270 // If no mode has been found, return an error
273 if (pVideoModeSelected
== NULL
)
275 EngFreeMem(pVideoBuffer
);
276 DISPDBG((0,"DISP bInitPDEV failed - no valid modes\n"));
281 // Fill in the GDIINFO data structure with the information returned from
282 // the kernel driver.
285 ppdev
->ulMode
= pVideoModeSelected
->ModeIndex
;
286 ppdev
->cxScreen
= pVideoModeSelected
->VisScreenWidth
;
287 ppdev
->cyScreen
= pVideoModeSelected
->VisScreenHeight
;
288 ppdev
->ulBitCount
= pVideoModeSelected
->BitsPerPlane
*
289 pVideoModeSelected
->NumberOfPlanes
;
290 ppdev
->lDeltaScreen
= pVideoModeSelected
->ScreenStride
;
292 ppdev
->flRed
= pVideoModeSelected
->RedMask
;
293 ppdev
->flGreen
= pVideoModeSelected
->GreenMask
;
294 ppdev
->flBlue
= pVideoModeSelected
->BlueMask
;
297 pGdiInfo
->ulVersion
= GDI_DRIVER_VERSION
;
298 pGdiInfo
->ulTechnology
= DT_RASDISPLAY
;
299 pGdiInfo
->ulHorzSize
= pVideoModeSelected
->XMillimeter
;
300 pGdiInfo
->ulVertSize
= pVideoModeSelected
->YMillimeter
;
302 pGdiInfo
->ulHorzRes
= ppdev
->cxScreen
;
303 pGdiInfo
->ulVertRes
= ppdev
->cyScreen
;
304 pGdiInfo
->ulPanningHorzRes
= ppdev
->cxScreen
;
305 pGdiInfo
->ulPanningVertRes
= ppdev
->cyScreen
;
306 pGdiInfo
->cBitsPixel
= pVideoModeSelected
->BitsPerPlane
;
307 pGdiInfo
->cPlanes
= pVideoModeSelected
->NumberOfPlanes
;
308 pGdiInfo
->ulVRefresh
= pVideoModeSelected
->Frequency
;
309 pGdiInfo
->ulBltAlignment
= 1; // We don't have accelerated screen-
310 // to-screen blts, and any
311 // window alignment is okay
313 pGdiInfo
->ulLogPixelsX
= pDevMode
->dmLogPixels
;
314 pGdiInfo
->ulLogPixelsY
= pDevMode
->dmLogPixels
;
317 if (ppdev
->ulBitCount
== 8)
318 pGdiInfo
->flTextCaps
= (TC_RA_ABLE
| TC_SCROLLBLT
);
321 pGdiInfo
->flTextCaps
= TC_RA_ABLE
;
323 pGdiInfo
->flRaster
= 0; // flRaster is reserved by DDI
325 pGdiInfo
->ulDACRed
= pVideoModeSelected
->NumberRedBits
;
326 pGdiInfo
->ulDACGreen
= pVideoModeSelected
->NumberGreenBits
;
327 pGdiInfo
->ulDACBlue
= pVideoModeSelected
->NumberBlueBits
;
329 pGdiInfo
->ulAspectX
= 0x24; // One-to-one aspect ratio
330 pGdiInfo
->ulAspectY
= 0x24;
331 pGdiInfo
->ulAspectXY
= 0x33;
333 pGdiInfo
->xStyleStep
= 1; // A style unit is 3 pels
334 pGdiInfo
->yStyleStep
= 1;
335 pGdiInfo
->denStyleStep
= 3;
337 pGdiInfo
->ptlPhysOffset
.x
= 0;
338 pGdiInfo
->ptlPhysOffset
.y
= 0;
339 pGdiInfo
->szlPhysSize
.cx
= 0;
340 pGdiInfo
->szlPhysSize
.cy
= 0;
342 // RGB and CMY color info.
345 // try to get it from the miniport.
346 // if the miniport doesn ot support this feature, use defaults.
349 if (EngDeviceIoControl(ppdev
->hDriver
,
350 IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES
,
354 sizeof(VIDEO_COLOR_CAPABILITIES
),
358 DISPDBG((2, "getcolorCapabilities failed \n"));
360 pGdiInfo
->ciDevice
.Red
.x
= 6700;
361 pGdiInfo
->ciDevice
.Red
.y
= 3300;
362 pGdiInfo
->ciDevice
.Red
.Y
= 0;
363 pGdiInfo
->ciDevice
.Green
.x
= 2100;
364 pGdiInfo
->ciDevice
.Green
.y
= 7100;
365 pGdiInfo
->ciDevice
.Green
.Y
= 0;
366 pGdiInfo
->ciDevice
.Blue
.x
= 1400;
367 pGdiInfo
->ciDevice
.Blue
.y
= 800;
368 pGdiInfo
->ciDevice
.Blue
.Y
= 0;
369 pGdiInfo
->ciDevice
.AlignmentWhite
.x
= 3127;
370 pGdiInfo
->ciDevice
.AlignmentWhite
.y
= 3290;
371 pGdiInfo
->ciDevice
.AlignmentWhite
.Y
= 0;
373 pGdiInfo
->ciDevice
.RedGamma
= 20000;
374 pGdiInfo
->ciDevice
.GreenGamma
= 20000;
375 pGdiInfo
->ciDevice
.BlueGamma
= 20000;
380 pGdiInfo
->ciDevice
.Red
.x
= colorCapabilities
.RedChromaticity_x
;
381 pGdiInfo
->ciDevice
.Red
.y
= colorCapabilities
.RedChromaticity_y
;
382 pGdiInfo
->ciDevice
.Red
.Y
= 0;
383 pGdiInfo
->ciDevice
.Green
.x
= colorCapabilities
.GreenChromaticity_x
;
384 pGdiInfo
->ciDevice
.Green
.y
= colorCapabilities
.GreenChromaticity_y
;
385 pGdiInfo
->ciDevice
.Green
.Y
= 0;
386 pGdiInfo
->ciDevice
.Blue
.x
= colorCapabilities
.BlueChromaticity_x
;
387 pGdiInfo
->ciDevice
.Blue
.y
= colorCapabilities
.BlueChromaticity_y
;
388 pGdiInfo
->ciDevice
.Blue
.Y
= 0;
389 pGdiInfo
->ciDevice
.AlignmentWhite
.x
= colorCapabilities
.WhiteChromaticity_x
;
390 pGdiInfo
->ciDevice
.AlignmentWhite
.y
= colorCapabilities
.WhiteChromaticity_y
;
391 pGdiInfo
->ciDevice
.AlignmentWhite
.Y
= colorCapabilities
.WhiteChromaticity_Y
;
393 // if we have a color device store the three color gamma values,
394 // otherwise store the unique gamma value in all three.
396 if (colorCapabilities
.AttributeFlags
& VIDEO_DEVICE_COLOR
)
398 pGdiInfo
->ciDevice
.RedGamma
= colorCapabilities
.RedGamma
;
399 pGdiInfo
->ciDevice
.GreenGamma
= colorCapabilities
.GreenGamma
;
400 pGdiInfo
->ciDevice
.BlueGamma
= colorCapabilities
.BlueGamma
;
404 pGdiInfo
->ciDevice
.RedGamma
= colorCapabilities
.WhiteGamma
;
405 pGdiInfo
->ciDevice
.GreenGamma
= colorCapabilities
.WhiteGamma
;
406 pGdiInfo
->ciDevice
.BlueGamma
= colorCapabilities
.WhiteGamma
;
411 pGdiInfo
->ciDevice
.Cyan
.x
= 0;
412 pGdiInfo
->ciDevice
.Cyan
.y
= 0;
413 pGdiInfo
->ciDevice
.Cyan
.Y
= 0;
414 pGdiInfo
->ciDevice
.Magenta
.x
= 0;
415 pGdiInfo
->ciDevice
.Magenta
.y
= 0;
416 pGdiInfo
->ciDevice
.Magenta
.Y
= 0;
417 pGdiInfo
->ciDevice
.Yellow
.x
= 0;
418 pGdiInfo
->ciDevice
.Yellow
.y
= 0;
419 pGdiInfo
->ciDevice
.Yellow
.Y
= 0;
421 // No dye correction for raster displays.
423 pGdiInfo
->ciDevice
.MagentaInCyanDye
= 0;
424 pGdiInfo
->ciDevice
.YellowInCyanDye
= 0;
425 pGdiInfo
->ciDevice
.CyanInMagentaDye
= 0;
426 pGdiInfo
->ciDevice
.YellowInMagentaDye
= 0;
427 pGdiInfo
->ciDevice
.CyanInYellowDye
= 0;
428 pGdiInfo
->ciDevice
.MagentaInYellowDye
= 0;
430 pGdiInfo
->ulDevicePelsDPI
= 0; // For printers only
431 pGdiInfo
->ulPrimaryOrder
= PRIMARY_ORDER_CBA
;
433 // BUGBUG this should be modified to take into account the size
434 // of the display and the resolution.
436 pGdiInfo
->ulHTPatternSize
= HT_PATSIZE_4x4_M
;
438 pGdiInfo
->flHTFlags
= HT_FLAG_ADDITIVE_PRIMS
;
440 // Fill in the basic devinfo structure
442 *pDevInfo
= gDevInfoFrameBuffer
;
444 // Fill in the rest of the devinfo and GdiInfo structures.
446 if (ppdev
->ulBitCount
== 8)
448 // It is Palette Managed.
450 pGdiInfo
->ulNumColors
= 20;
451 pGdiInfo
->ulNumPalReg
= 1 << ppdev
->ulBitCount
;
453 pDevInfo
->flGraphicsCaps
|= (GCAPS_PALMANAGED
| GCAPS_COLOR_DITHER
);
455 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_8BPP
;
456 pDevInfo
->iDitherFormat
= BMF_8BPP
;
458 // Assuming palette is orthogonal - all colors are same size.
460 ppdev
->cPaletteShift
= 8 - pGdiInfo
->ulDACRed
;
464 pGdiInfo
->ulNumColors
= (ULONG
) (-1);
465 pGdiInfo
->ulNumPalReg
= 0;
467 if (ppdev
->ulBitCount
== 16)
469 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_16BPP
;
470 pDevInfo
->iDitherFormat
= BMF_16BPP
;
472 else if (ppdev
->ulBitCount
== 24)
474 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_24BPP
;
475 pDevInfo
->iDitherFormat
= BMF_24BPP
;
479 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_32BPP
;
480 pDevInfo
->iDitherFormat
= BMF_32BPP
;
484 EngFreeMem(pVideoBuffer
);
490 /******************************Public*Routine******************************\
493 * Calls the miniport to get the list of modes supported by the kernel driver,
494 * and returns the list of modes supported by the diplay driver among those
496 * returns the number of entries in the videomode buffer.
497 * 0 means no modes are supported by the miniport or that an error occured.
499 * NOTE: the buffer must be freed up by the caller.
501 \**************************************************************************/
503 DWORD
getAvailableModes(
505 PVIDEO_MODE_INFORMATION
*modeInformation
,
509 VIDEO_NUM_MODES modes
;
510 PVIDEO_MODE_INFORMATION pVideoTemp
;
513 // Get the number of modes supported by the mini-port
516 if (EngDeviceIoControl(hDriver
,
517 IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
,
521 sizeof(VIDEO_NUM_MODES
),
524 DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_NUM_AVAIL_MODES\n"));
528 *cbModeSize
= modes
.ModeInformationLength
;
531 // Allocate the buffer for the mini-port to write the modes in.
534 *modeInformation
= (PVIDEO_MODE_INFORMATION
)
535 EngAllocMem(0, modes
.NumModes
*
536 modes
.ModeInformationLength
, ALLOC_TAG
);
538 if (*modeInformation
== (PVIDEO_MODE_INFORMATION
) NULL
)
540 DISPDBG((0, "getAvailableModes failed EngAllocMem\n"));
546 // Ask the mini-port to fill in the available modes.
549 if (EngDeviceIoControl(hDriver
,
550 IOCTL_VIDEO_QUERY_AVAIL_MODES
,
554 modes
.NumModes
* modes
.ModeInformationLength
,
558 DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_AVAIL_MODES\n"));
560 EngFreeMem(*modeInformation
);
561 *modeInformation
= (PVIDEO_MODE_INFORMATION
) NULL
;
567 // Now see which of these modes are supported by the display driver.
568 // As an internal mechanism, set the length to 0 for the modes we
572 ulTemp
= modes
.NumModes
;
573 pVideoTemp
= *modeInformation
;
576 // Mode is rejected if it is not one plane, or not graphics, or is not
577 // one of 8, 16 or 32 bits per pel.
582 if ((pVideoTemp
->NumberOfPlanes
!= 1 ) ||
583 !(pVideoTemp
->AttributeFlags
& VIDEO_MODE_GRAPHICS
) ||
584 // eVb: 2.6 [DDK CHANGE] - Do not process banked video modes
585 (pVideoTemp
->AttributeFlags
& VIDEO_MODE_BANKED
) ||
587 ((pVideoTemp
->BitsPerPlane
!= 8) &&
588 (pVideoTemp
->BitsPerPlane
!= 16) &&
589 (pVideoTemp
->BitsPerPlane
!= 24) &&
590 (pVideoTemp
->BitsPerPlane
!= 32)))
592 pVideoTemp
->Length
= 0;
595 pVideoTemp
= (PVIDEO_MODE_INFORMATION
)
596 (((PUCHAR
)pVideoTemp
) + modes
.ModeInformationLength
);
599 return modes
.NumModes
;