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
12 #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"}
13 #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"}
14 #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"}
16 // This is the basic devinfo for a default driver. This is used as a base and customized based
17 // on information passed back from the miniport driver.
19 const DEVINFO gDevInfoFrameBuffer
= {
21 // eVb: 2.8 [DDK CHANGE] - No dithering support
23 ), /* Graphics capabilities */
24 SYSTM_LOGFONT
, /* Default font description */
25 HELVE_LOGFONT
, /* ANSI variable font description */
26 COURI_LOGFONT
, /* ANSI fixed font description */
27 0, /* Count of device fonts */
28 0, /* Preferred DIB format */
29 // eVb: 2.9 [DDK CHANGE] - No dithering support
30 0, /* Width of color dither */
31 0, /* Height of color dither */
33 0 /* Default palette to use for this device */
36 /******************************Public*Routine******************************\
39 * Enables the surface. Maps the frame buffer into memory.
41 \**************************************************************************/
43 BOOL NTAPI
bInitSURF(PPDEV ppdev
, BOOL bFirst
)
45 DWORD returnedDataLength
;
46 DWORD MaxWidth
, MaxHeight
;
47 VIDEO_MEMORY videoMemory
;
48 VIDEO_MEMORY_INFORMATION videoMemoryInformation
;
49 // eVb: 2.1 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
50 ULONG RemappingNeeded
= 0;
53 // Set the current mode into the hardware.
56 if (EngDeviceIoControl(ppdev
->hDriver
,
57 IOCTL_VIDEO_SET_CURRENT_MODE
,
60 // eVb: 2.2 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
66 RIP("DISP bInitSURF failed IOCTL_SET_MODE\n");
71 // If this is the first time we enable the surface we need to map in the
74 // eVb: 2.3 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
75 if (bFirst
|| RemappingNeeded
)
78 videoMemory
.RequestedVirtualAddress
= NULL
;
80 if (EngDeviceIoControl(ppdev
->hDriver
,
81 IOCTL_VIDEO_MAP_VIDEO_MEMORY
,
84 &videoMemoryInformation
,
85 sizeof(VIDEO_MEMORY_INFORMATION
),
88 RIP("DISP bInitSURF failed IOCTL_VIDEO_MAP\n");
92 ppdev
->pjScreen
= (PBYTE
)(videoMemoryInformation
.FrameBufferBase
);
94 if (videoMemoryInformation
.FrameBufferBase
!=
95 videoMemoryInformation
.VideoRamBase
)
97 RIP("VideoRamBase does not correspond to FrameBufferBase\n");
99 // eVb: 2.4 [DDK Change] - Make sure frame buffer mapping worked
101 // Make sure we can access this video memory
104 *(PULONG
)(ppdev
->pjScreen
) = 0xaa55aa55;
106 if (*(PULONG
)(ppdev
->pjScreen
) != 0xaa55aa55) {
108 DISPDBG((1, "Frame buffer memory is not accessible.\n"));
112 ppdev
->cScreenSize
= videoMemoryInformation
.VideoRamLength
;
115 // Initialize the head of the offscreen list to NULL.
118 ppdev
->pOffscreenList
= NULL
;
120 // It's a hardware pointer; set up pointer attributes.
122 MaxHeight
= ppdev
->PointerCapabilities
.MaxHeight
;
124 // Allocate space for two DIBs (data/mask) for the pointer. If this
125 // device supports a color Pointer, we will allocate a larger bitmap.
126 // If this is a color bitmap we allocate for the largest possible
127 // bitmap because we have no idea of what the pixel depth might be.
129 // Width rounded up to nearest byte multiple
131 if (!(ppdev
->PointerCapabilities
.Flags
& VIDEO_MODE_COLOR_POINTER
))
133 MaxWidth
= (ppdev
->PointerCapabilities
.MaxWidth
+ 7) / 8;
137 MaxWidth
= ppdev
->PointerCapabilities
.MaxWidth
* sizeof(DWORD
);
140 ppdev
->cjPointerAttributes
=
141 sizeof(VIDEO_POINTER_ATTRIBUTES
) +
142 ((sizeof(UCHAR
) * MaxWidth
* MaxHeight
) * 2);
144 ppdev
->pPointerAttributes
= (PVIDEO_POINTER_ATTRIBUTES
)
145 EngAllocMem(0, ppdev
->cjPointerAttributes
, ALLOC_TAG
);
147 if (ppdev
->pPointerAttributes
== NULL
) {
149 DISPDBG((0, "bInitPointer EngAllocMem failed\n"));
153 ppdev
->pPointerAttributes
->Flags
= ppdev
->PointerCapabilities
.Flags
;
154 ppdev
->pPointerAttributes
->WidthInBytes
= MaxWidth
;
155 ppdev
->pPointerAttributes
->Width
= ppdev
->PointerCapabilities
.MaxWidth
;
156 ppdev
->pPointerAttributes
->Height
= MaxHeight
;
157 ppdev
->pPointerAttributes
->Column
= 0;
158 ppdev
->pPointerAttributes
->Row
= 0;
159 ppdev
->pPointerAttributes
->Enable
= 0;
165 /******************************Public*Routine******************************\
168 * Disable the surface. Un-Maps the frame in memory.
170 \**************************************************************************/
172 VOID NTAPI
vDisableSURF(PPDEV ppdev
)
174 DWORD returnedDataLength
;
175 VIDEO_MEMORY videoMemory
;
177 videoMemory
.RequestedVirtualAddress
= (PVOID
) ppdev
->pjScreen
;
179 if (EngDeviceIoControl(ppdev
->hDriver
,
180 IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
,
182 sizeof(VIDEO_MEMORY
),
185 &returnedDataLength
))
187 RIP("DISP vDisableSURF failed IOCTL_VIDEO_UNMAP\n");
192 /******************************Public*Routine******************************\
195 * Determine the mode we should be in based on the DEVMODE passed in.
196 * Query mini-port to get information needed to fill in the DevInfo and the
199 \**************************************************************************/
201 BOOL NTAPI
bInitPDEV(
208 PVIDEO_MODE_INFORMATION pVideoBuffer
, pVideoModeSelected
, pVideoTemp
;
209 VIDEO_COLOR_CAPABILITIES colorCapabilities
;
215 // calls the miniport to get mode information.
218 cModes
= getAvailableModes(ppdev
->hDriver
, &pVideoBuffer
, &cbModeSize
);
226 // Now see if the requested mode has a match in that table.
229 pVideoModeSelected
= NULL
;
230 pVideoTemp
= pVideoBuffer
;
232 if ((pDevMode
->dmPelsWidth
== 0) &&
233 (pDevMode
->dmPelsHeight
== 0) &&
234 (pDevMode
->dmBitsPerPel
== 0) &&
235 (pDevMode
->dmDisplayFrequency
== 0))
237 DISPDBG((2, "Default mode requested"));
238 bSelectDefault
= TRUE
;
242 // eVb: 2.5 [DDK Change] - Add missing newlines to debug output
243 DISPDBG((2, "Requested mode...\n"));
244 DISPDBG((2, " Screen width -- %li\n", pDevMode
->dmPelsWidth
));
245 DISPDBG((2, " Screen height -- %li\n", pDevMode
->dmPelsHeight
));
246 DISPDBG((2, " Bits per pel -- %li\n", pDevMode
->dmBitsPerPel
));
247 DISPDBG((2, " Frequency -- %li\n", pDevMode
->dmDisplayFrequency
));
249 bSelectDefault
= FALSE
;
254 if (pVideoTemp
->Length
!= 0)
256 if (bSelectDefault
||
257 ((pVideoTemp
->VisScreenWidth
== pDevMode
->dmPelsWidth
) &&
258 (pVideoTemp
->VisScreenHeight
== pDevMode
->dmPelsHeight
) &&
259 (pVideoTemp
->BitsPerPlane
*
260 pVideoTemp
->NumberOfPlanes
== pDevMode
->dmBitsPerPel
) &&
261 (pVideoTemp
->Frequency
== pDevMode
->dmDisplayFrequency
)))
263 pVideoModeSelected
= pVideoTemp
;
264 DISPDBG((3, "Found a match\n")) ;
269 pVideoTemp
= (PVIDEO_MODE_INFORMATION
)
270 (((PUCHAR
)pVideoTemp
) + cbModeSize
);
274 // If no mode has been found, return an error
277 if (pVideoModeSelected
== NULL
)
279 EngFreeMem(pVideoBuffer
);
280 DISPDBG((0,"DISP bInitPDEV failed - no valid modes\n"));
285 // Fill in the GDIINFO data structure with the information returned from
286 // the kernel driver.
289 ppdev
->ulMode
= pVideoModeSelected
->ModeIndex
;
290 ppdev
->cxScreen
= pVideoModeSelected
->VisScreenWidth
;
291 ppdev
->cyScreen
= pVideoModeSelected
->VisScreenHeight
;
292 ppdev
->ulBitCount
= pVideoModeSelected
->BitsPerPlane
*
293 pVideoModeSelected
->NumberOfPlanes
;
294 ppdev
->lDeltaScreen
= pVideoModeSelected
->ScreenStride
;
296 ppdev
->flRed
= pVideoModeSelected
->RedMask
;
297 ppdev
->flGreen
= pVideoModeSelected
->GreenMask
;
298 ppdev
->flBlue
= pVideoModeSelected
->BlueMask
;
301 pGdiInfo
->ulVersion
= GDI_DRIVER_VERSION
;
302 pGdiInfo
->ulTechnology
= DT_RASDISPLAY
;
303 pGdiInfo
->ulHorzSize
= pVideoModeSelected
->XMillimeter
;
304 pGdiInfo
->ulVertSize
= pVideoModeSelected
->YMillimeter
;
306 pGdiInfo
->ulHorzRes
= ppdev
->cxScreen
;
307 pGdiInfo
->ulVertRes
= ppdev
->cyScreen
;
308 pGdiInfo
->ulPanningHorzRes
= ppdev
->cxScreen
;
309 pGdiInfo
->ulPanningVertRes
= ppdev
->cyScreen
;
310 pGdiInfo
->cBitsPixel
= pVideoModeSelected
->BitsPerPlane
;
311 pGdiInfo
->cPlanes
= pVideoModeSelected
->NumberOfPlanes
;
312 pGdiInfo
->ulVRefresh
= pVideoModeSelected
->Frequency
;
313 pGdiInfo
->ulBltAlignment
= 1; // We don't have accelerated screen-
314 // to-screen blts, and any
315 // window alignment is okay
317 pGdiInfo
->ulLogPixelsX
= pDevMode
->dmLogPixels
;
318 pGdiInfo
->ulLogPixelsY
= pDevMode
->dmLogPixels
;
321 if (ppdev
->ulBitCount
== 8)
322 pGdiInfo
->flTextCaps
= (TC_RA_ABLE
| TC_SCROLLBLT
);
325 pGdiInfo
->flTextCaps
= TC_RA_ABLE
;
327 pGdiInfo
->flRaster
= 0; // flRaster is reserved by DDI
329 pGdiInfo
->ulDACRed
= pVideoModeSelected
->NumberRedBits
;
330 pGdiInfo
->ulDACGreen
= pVideoModeSelected
->NumberGreenBits
;
331 pGdiInfo
->ulDACBlue
= pVideoModeSelected
->NumberBlueBits
;
333 pGdiInfo
->ulAspectX
= 0x24; // One-to-one aspect ratio
334 pGdiInfo
->ulAspectY
= 0x24;
335 pGdiInfo
->ulAspectXY
= 0x33;
337 pGdiInfo
->xStyleStep
= 1; // A style unit is 3 pels
338 pGdiInfo
->yStyleStep
= 1;
339 pGdiInfo
->denStyleStep
= 3;
341 pGdiInfo
->ptlPhysOffset
.x
= 0;
342 pGdiInfo
->ptlPhysOffset
.y
= 0;
343 pGdiInfo
->szlPhysSize
.cx
= 0;
344 pGdiInfo
->szlPhysSize
.cy
= 0;
346 // RGB and CMY color info.
349 // try to get it from the miniport.
350 // if the miniport doesn ot support this feature, use defaults.
353 if (EngDeviceIoControl(ppdev
->hDriver
,
354 IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES
,
358 sizeof(VIDEO_COLOR_CAPABILITIES
),
362 DISPDBG((2, "getcolorCapabilities failed \n"));
364 pGdiInfo
->ciDevice
.Red
.x
= 6700;
365 pGdiInfo
->ciDevice
.Red
.y
= 3300;
366 pGdiInfo
->ciDevice
.Red
.Y
= 0;
367 pGdiInfo
->ciDevice
.Green
.x
= 2100;
368 pGdiInfo
->ciDevice
.Green
.y
= 7100;
369 pGdiInfo
->ciDevice
.Green
.Y
= 0;
370 pGdiInfo
->ciDevice
.Blue
.x
= 1400;
371 pGdiInfo
->ciDevice
.Blue
.y
= 800;
372 pGdiInfo
->ciDevice
.Blue
.Y
= 0;
373 pGdiInfo
->ciDevice
.AlignmentWhite
.x
= 3127;
374 pGdiInfo
->ciDevice
.AlignmentWhite
.y
= 3290;
375 pGdiInfo
->ciDevice
.AlignmentWhite
.Y
= 0;
377 pGdiInfo
->ciDevice
.RedGamma
= 20000;
378 pGdiInfo
->ciDevice
.GreenGamma
= 20000;
379 pGdiInfo
->ciDevice
.BlueGamma
= 20000;
384 pGdiInfo
->ciDevice
.Red
.x
= colorCapabilities
.RedChromaticity_x
;
385 pGdiInfo
->ciDevice
.Red
.y
= colorCapabilities
.RedChromaticity_y
;
386 pGdiInfo
->ciDevice
.Red
.Y
= 0;
387 pGdiInfo
->ciDevice
.Green
.x
= colorCapabilities
.GreenChromaticity_x
;
388 pGdiInfo
->ciDevice
.Green
.y
= colorCapabilities
.GreenChromaticity_y
;
389 pGdiInfo
->ciDevice
.Green
.Y
= 0;
390 pGdiInfo
->ciDevice
.Blue
.x
= colorCapabilities
.BlueChromaticity_x
;
391 pGdiInfo
->ciDevice
.Blue
.y
= colorCapabilities
.BlueChromaticity_y
;
392 pGdiInfo
->ciDevice
.Blue
.Y
= 0;
393 pGdiInfo
->ciDevice
.AlignmentWhite
.x
= colorCapabilities
.WhiteChromaticity_x
;
394 pGdiInfo
->ciDevice
.AlignmentWhite
.y
= colorCapabilities
.WhiteChromaticity_y
;
395 pGdiInfo
->ciDevice
.AlignmentWhite
.Y
= colorCapabilities
.WhiteChromaticity_Y
;
397 // if we have a color device store the three color gamma values,
398 // otherwise store the unique gamma value in all three.
400 if (colorCapabilities
.AttributeFlags
& VIDEO_DEVICE_COLOR
)
402 pGdiInfo
->ciDevice
.RedGamma
= colorCapabilities
.RedGamma
;
403 pGdiInfo
->ciDevice
.GreenGamma
= colorCapabilities
.GreenGamma
;
404 pGdiInfo
->ciDevice
.BlueGamma
= colorCapabilities
.BlueGamma
;
408 pGdiInfo
->ciDevice
.RedGamma
= colorCapabilities
.WhiteGamma
;
409 pGdiInfo
->ciDevice
.GreenGamma
= colorCapabilities
.WhiteGamma
;
410 pGdiInfo
->ciDevice
.BlueGamma
= colorCapabilities
.WhiteGamma
;
415 pGdiInfo
->ciDevice
.Cyan
.x
= 0;
416 pGdiInfo
->ciDevice
.Cyan
.y
= 0;
417 pGdiInfo
->ciDevice
.Cyan
.Y
= 0;
418 pGdiInfo
->ciDevice
.Magenta
.x
= 0;
419 pGdiInfo
->ciDevice
.Magenta
.y
= 0;
420 pGdiInfo
->ciDevice
.Magenta
.Y
= 0;
421 pGdiInfo
->ciDevice
.Yellow
.x
= 0;
422 pGdiInfo
->ciDevice
.Yellow
.y
= 0;
423 pGdiInfo
->ciDevice
.Yellow
.Y
= 0;
425 // No dye correction for raster displays.
427 pGdiInfo
->ciDevice
.MagentaInCyanDye
= 0;
428 pGdiInfo
->ciDevice
.YellowInCyanDye
= 0;
429 pGdiInfo
->ciDevice
.CyanInMagentaDye
= 0;
430 pGdiInfo
->ciDevice
.YellowInMagentaDye
= 0;
431 pGdiInfo
->ciDevice
.CyanInYellowDye
= 0;
432 pGdiInfo
->ciDevice
.MagentaInYellowDye
= 0;
434 pGdiInfo
->ulDevicePelsDPI
= 0; // For printers only
435 pGdiInfo
->ulPrimaryOrder
= PRIMARY_ORDER_CBA
;
437 // BUGBUG this should be modified to take into account the size
438 // of the display and the resolution.
440 pGdiInfo
->ulHTPatternSize
= HT_PATSIZE_4x4_M
;
442 pGdiInfo
->flHTFlags
= HT_FLAG_ADDITIVE_PRIMS
;
444 // Fill in the basic devinfo structure
446 *pDevInfo
= gDevInfoFrameBuffer
;
448 // Fill in the rest of the devinfo and GdiInfo structures.
450 if (ppdev
->ulBitCount
== 8)
452 // It is Palette Managed.
454 pGdiInfo
->ulNumColors
= 20;
455 pGdiInfo
->ulNumPalReg
= 1 << ppdev
->ulBitCount
;
456 // eVb: 2.7 [DDK CHANGE] - No dithering support
457 pDevInfo
->flGraphicsCaps
|= GCAPS_PALMANAGED
;
459 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_8BPP
;
460 pDevInfo
->iDitherFormat
= BMF_8BPP
;
462 // Assuming palette is orthogonal - all colors are same size.
464 ppdev
->cPaletteShift
= 8 - pGdiInfo
->ulDACRed
;
468 pGdiInfo
->ulNumColors
= (ULONG
) (-1);
469 pGdiInfo
->ulNumPalReg
= 0;
471 if (ppdev
->ulBitCount
== 16)
473 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_16BPP
;
474 pDevInfo
->iDitherFormat
= BMF_16BPP
;
476 else if (ppdev
->ulBitCount
== 24)
478 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_24BPP
;
479 pDevInfo
->iDitherFormat
= BMF_24BPP
;
483 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_32BPP
;
484 pDevInfo
->iDitherFormat
= BMF_32BPP
;
488 EngFreeMem(pVideoBuffer
);
494 /******************************Public*Routine******************************\
497 * Calls the miniport to get the list of modes supported by the kernel driver,
498 * and returns the list of modes supported by the diplay driver among those
500 * returns the number of entries in the videomode buffer.
501 * 0 means no modes are supported by the miniport or that an error occured.
503 * NOTE: the buffer must be freed up by the caller.
505 \**************************************************************************/
507 DWORD NTAPI
getAvailableModes(
509 PVIDEO_MODE_INFORMATION
*modeInformation
,
513 VIDEO_NUM_MODES modes
;
514 PVIDEO_MODE_INFORMATION pVideoTemp
;
517 // Get the number of modes supported by the mini-port
520 if (EngDeviceIoControl(hDriver
,
521 IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
,
525 sizeof(VIDEO_NUM_MODES
),
528 DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_NUM_AVAIL_MODES\n"));
532 *cbModeSize
= modes
.ModeInformationLength
;
535 // Allocate the buffer for the mini-port to write the modes in.
538 *modeInformation
= (PVIDEO_MODE_INFORMATION
)
539 EngAllocMem(0, modes
.NumModes
*
540 modes
.ModeInformationLength
, ALLOC_TAG
);
542 if (*modeInformation
== (PVIDEO_MODE_INFORMATION
) NULL
)
544 DISPDBG((0, "getAvailableModes failed EngAllocMem\n"));
550 // Ask the mini-port to fill in the available modes.
553 if (EngDeviceIoControl(hDriver
,
554 IOCTL_VIDEO_QUERY_AVAIL_MODES
,
558 modes
.NumModes
* modes
.ModeInformationLength
,
562 DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_AVAIL_MODES\n"));
564 EngFreeMem(*modeInformation
);
565 *modeInformation
= (PVIDEO_MODE_INFORMATION
) NULL
;
571 // Now see which of these modes are supported by the display driver.
572 // As an internal mechanism, set the length to 0 for the modes we
576 ulTemp
= modes
.NumModes
;
577 pVideoTemp
= *modeInformation
;
580 // Mode is rejected if it is not one plane, or not graphics, or is not
581 // one of 8, 16 or 32 bits per pel.
586 if ((pVideoTemp
->NumberOfPlanes
!= 1 ) ||
587 !(pVideoTemp
->AttributeFlags
& VIDEO_MODE_GRAPHICS
) ||
588 // eVb: 2.6 [DDK CHANGE] - Do not process banked video modes
589 (pVideoTemp
->AttributeFlags
& VIDEO_MODE_BANKED
) ||
591 ((pVideoTemp
->BitsPerPlane
!= 8) &&
592 (pVideoTemp
->BitsPerPlane
!= 16) &&
593 (pVideoTemp
->BitsPerPlane
!= 24) &&
594 (pVideoTemp
->BitsPerPlane
!= 32)))
596 pVideoTemp
->Length
= 0;
599 pVideoTemp
= (PVIDEO_MODE_INFORMATION
)
600 (((PUCHAR
)pVideoTemp
) + modes
.ModeInformationLength
);
603 return modes
.NumModes
;