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
= {
20 // eVb: 2.8 [DDK CHANGE] - No dithering support
22 ), /* Graphics capabilities */
23 SYSTM_LOGFONT
, /* Default font description */
24 HELVE_LOGFONT
, /* ANSI variable font description */
25 COURI_LOGFONT
, /* ANSI fixed font description */
26 0, /* Count of device fonts */
27 0, /* Preferred DIB format */
28 // eVb: 2.9 [DDK CHANGE] - No dithering support
29 0, /* Width of color dither */
30 0, /* Height of color dither */
32 0 /* Default palette to use for this device */
35 /******************************Public*Routine******************************\
38 * Enables the surface. Maps the frame buffer into memory.
40 \**************************************************************************/
42 BOOL
bInitSURF(PPDEV ppdev
, BOOL bFirst
)
44 DWORD returnedDataLength
;
45 DWORD MaxWidth
, MaxHeight
;
46 VIDEO_MEMORY videoMemory
;
47 VIDEO_MEMORY_INFORMATION videoMemoryInformation
;
48 // eVb: 2.1 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
49 ULONG RemappingNeeded
= 0;
52 // Set the current mode into the hardware.
55 if (EngDeviceIoControl(ppdev
->hDriver
,
56 IOCTL_VIDEO_SET_CURRENT_MODE
,
59 // eVb: 2.2 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
65 RIP("DISP bInitSURF failed IOCTL_SET_MODE\n");
70 // If this is the first time we enable the surface we need to map in the
73 // eVb: 2.3 [DDK Change] - Support new VGA Miniport behavior w.r.t updated framebuffer remapping
74 if (bFirst
|| RemappingNeeded
)
77 videoMemory
.RequestedVirtualAddress
= NULL
;
79 if (EngDeviceIoControl(ppdev
->hDriver
,
80 IOCTL_VIDEO_MAP_VIDEO_MEMORY
,
83 &videoMemoryInformation
,
84 sizeof(VIDEO_MEMORY_INFORMATION
),
87 RIP("DISP bInitSURF failed IOCTL_VIDEO_MAP\n");
91 ppdev
->pjScreen
= (PBYTE
)(videoMemoryInformation
.FrameBufferBase
);
93 if (videoMemoryInformation
.FrameBufferBase
!=
94 videoMemoryInformation
.VideoRamBase
)
96 RIP("VideoRamBase does not correspond to FrameBufferBase\n");
98 // eVb: 2.4 [DDK Change] - Make sure frame buffer mapping worked
100 // Make sure we can access this video memory
103 *(PULONG
)(ppdev
->pjScreen
) = 0xaa55aa55;
105 if (*(PULONG
)(ppdev
->pjScreen
) != 0xaa55aa55) {
107 DISPDBG((1, "Frame buffer memory is not accessible.\n"));
111 ppdev
->cScreenSize
= videoMemoryInformation
.VideoRamLength
;
114 // Initialize the head of the offscreen list to NULL.
117 ppdev
->pOffscreenList
= NULL
;
119 // It's a hardware pointer; set up pointer attributes.
121 MaxHeight
= ppdev
->PointerCapabilities
.MaxHeight
;
123 // Allocate space for two DIBs (data/mask) for the pointer. If this
124 // device supports a color Pointer, we will allocate a larger bitmap.
125 // If this is a color bitmap we allocate for the largest possible
126 // bitmap because we have no idea of what the pixel depth might be.
128 // Width rounded up to nearest byte multiple
130 if (!(ppdev
->PointerCapabilities
.Flags
& VIDEO_MODE_COLOR_POINTER
))
132 MaxWidth
= (ppdev
->PointerCapabilities
.MaxWidth
+ 7) / 8;
136 MaxWidth
= ppdev
->PointerCapabilities
.MaxWidth
* sizeof(DWORD
);
139 ppdev
->cjPointerAttributes
=
140 sizeof(VIDEO_POINTER_ATTRIBUTES
) +
141 ((sizeof(UCHAR
) * MaxWidth
* MaxHeight
) * 2);
143 ppdev
->pPointerAttributes
= (PVIDEO_POINTER_ATTRIBUTES
)
144 EngAllocMem(0, ppdev
->cjPointerAttributes
, ALLOC_TAG
);
146 if (ppdev
->pPointerAttributes
== NULL
) {
148 DISPDBG((0, "bInitPointer EngAllocMem failed\n"));
152 ppdev
->pPointerAttributes
->Flags
= ppdev
->PointerCapabilities
.Flags
;
153 ppdev
->pPointerAttributes
->WidthInBytes
= MaxWidth
;
154 ppdev
->pPointerAttributes
->Width
= ppdev
->PointerCapabilities
.MaxWidth
;
155 ppdev
->pPointerAttributes
->Height
= MaxHeight
;
156 ppdev
->pPointerAttributes
->Column
= 0;
157 ppdev
->pPointerAttributes
->Row
= 0;
158 ppdev
->pPointerAttributes
->Enable
= 0;
164 /******************************Public*Routine******************************\
167 * Disable the surface. Un-Maps the frame in memory.
169 \**************************************************************************/
171 VOID
vDisableSURF(PPDEV ppdev
)
173 DWORD returnedDataLength
;
174 VIDEO_MEMORY videoMemory
;
176 videoMemory
.RequestedVirtualAddress
= (PVOID
) ppdev
->pjScreen
;
178 if (EngDeviceIoControl(ppdev
->hDriver
,
179 IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
,
181 sizeof(VIDEO_MEMORY
),
184 &returnedDataLength
))
186 RIP("DISP vDisableSURF failed IOCTL_VIDEO_UNMAP\n");
191 /******************************Public*Routine******************************\
194 * Determine the mode we should be in based on the DEVMODE passed in.
195 * Query mini-port to get information needed to fill in the DevInfo and the
198 \**************************************************************************/
207 PVIDEO_MODE_INFORMATION pVideoBuffer
, pVideoModeSelected
, pVideoTemp
;
208 VIDEO_COLOR_CAPABILITIES colorCapabilities
;
214 // calls the miniport to get mode information.
217 cModes
= getAvailableModes(ppdev
->hDriver
, &pVideoBuffer
, &cbModeSize
);
225 // Now see if the requested mode has a match in that table.
228 pVideoModeSelected
= NULL
;
229 pVideoTemp
= pVideoBuffer
;
231 if ((pDevMode
->dmPelsWidth
== 0) &&
232 (pDevMode
->dmPelsHeight
== 0) &&
233 (pDevMode
->dmBitsPerPel
== 0) &&
234 (pDevMode
->dmDisplayFrequency
== 0))
236 DISPDBG((2, "Default mode requested"));
237 bSelectDefault
= TRUE
;
241 // eVb: 2.5 [DDK Change] - Add missing newlines to debug output
242 DISPDBG((2, "Requested mode...\n"));
243 DISPDBG((2, " Screen width -- %li\n", pDevMode
->dmPelsWidth
));
244 DISPDBG((2, " Screen height -- %li\n", pDevMode
->dmPelsHeight
));
245 DISPDBG((2, " Bits per pel -- %li\n", pDevMode
->dmBitsPerPel
));
246 DISPDBG((2, " Frequency -- %li\n", pDevMode
->dmDisplayFrequency
));
248 bSelectDefault
= FALSE
;
253 if (pVideoTemp
->Length
!= 0)
255 if (bSelectDefault
||
256 ((pVideoTemp
->VisScreenWidth
== pDevMode
->dmPelsWidth
) &&
257 (pVideoTemp
->VisScreenHeight
== pDevMode
->dmPelsHeight
) &&
258 (pVideoTemp
->BitsPerPlane
*
259 pVideoTemp
->NumberOfPlanes
== pDevMode
->dmBitsPerPel
) &&
260 (pVideoTemp
->Frequency
== pDevMode
->dmDisplayFrequency
)))
262 pVideoModeSelected
= pVideoTemp
;
263 DISPDBG((3, "Found a match\n")) ;
268 pVideoTemp
= (PVIDEO_MODE_INFORMATION
)
269 (((PUCHAR
)pVideoTemp
) + cbModeSize
);
273 // If no mode has been found, return an error
276 if (pVideoModeSelected
== NULL
)
278 EngFreeMem(pVideoBuffer
);
279 DISPDBG((0,"DISP bInitPDEV failed - no valid modes\n"));
284 // Fill in the GDIINFO data structure with the information returned from
285 // the kernel driver.
288 ppdev
->ulMode
= pVideoModeSelected
->ModeIndex
;
289 ppdev
->cxScreen
= pVideoModeSelected
->VisScreenWidth
;
290 ppdev
->cyScreen
= pVideoModeSelected
->VisScreenHeight
;
291 ppdev
->ulBitCount
= pVideoModeSelected
->BitsPerPlane
*
292 pVideoModeSelected
->NumberOfPlanes
;
293 ppdev
->lDeltaScreen
= pVideoModeSelected
->ScreenStride
;
295 ppdev
->flRed
= pVideoModeSelected
->RedMask
;
296 ppdev
->flGreen
= pVideoModeSelected
->GreenMask
;
297 ppdev
->flBlue
= pVideoModeSelected
->BlueMask
;
300 pGdiInfo
->ulVersion
= GDI_DRIVER_VERSION
;
301 pGdiInfo
->ulTechnology
= DT_RASDISPLAY
;
302 pGdiInfo
->ulHorzSize
= pVideoModeSelected
->XMillimeter
;
303 pGdiInfo
->ulVertSize
= pVideoModeSelected
->YMillimeter
;
305 pGdiInfo
->ulHorzRes
= ppdev
->cxScreen
;
306 pGdiInfo
->ulVertRes
= ppdev
->cyScreen
;
307 pGdiInfo
->ulPanningHorzRes
= ppdev
->cxScreen
;
308 pGdiInfo
->ulPanningVertRes
= ppdev
->cyScreen
;
309 pGdiInfo
->cBitsPixel
= pVideoModeSelected
->BitsPerPlane
;
310 pGdiInfo
->cPlanes
= pVideoModeSelected
->NumberOfPlanes
;
311 pGdiInfo
->ulVRefresh
= pVideoModeSelected
->Frequency
;
312 pGdiInfo
->ulBltAlignment
= 1; // We don't have accelerated screen-
313 // to-screen blts, and any
314 // window alignment is okay
316 pGdiInfo
->ulLogPixelsX
= pDevMode
->dmLogPixels
;
317 pGdiInfo
->ulLogPixelsY
= pDevMode
->dmLogPixels
;
320 if (ppdev
->ulBitCount
== 8)
321 pGdiInfo
->flTextCaps
= (TC_RA_ABLE
| TC_SCROLLBLT
);
324 pGdiInfo
->flTextCaps
= TC_RA_ABLE
;
326 pGdiInfo
->flRaster
= 0; // flRaster is reserved by DDI
328 pGdiInfo
->ulDACRed
= pVideoModeSelected
->NumberRedBits
;
329 pGdiInfo
->ulDACGreen
= pVideoModeSelected
->NumberGreenBits
;
330 pGdiInfo
->ulDACBlue
= pVideoModeSelected
->NumberBlueBits
;
332 pGdiInfo
->ulAspectX
= 0x24; // One-to-one aspect ratio
333 pGdiInfo
->ulAspectY
= 0x24;
334 pGdiInfo
->ulAspectXY
= 0x33;
336 pGdiInfo
->xStyleStep
= 1; // A style unit is 3 pels
337 pGdiInfo
->yStyleStep
= 1;
338 pGdiInfo
->denStyleStep
= 3;
340 pGdiInfo
->ptlPhysOffset
.x
= 0;
341 pGdiInfo
->ptlPhysOffset
.y
= 0;
342 pGdiInfo
->szlPhysSize
.cx
= 0;
343 pGdiInfo
->szlPhysSize
.cy
= 0;
345 // RGB and CMY color info.
348 // try to get it from the miniport.
349 // if the miniport doesn ot support this feature, use defaults.
352 if (EngDeviceIoControl(ppdev
->hDriver
,
353 IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES
,
357 sizeof(VIDEO_COLOR_CAPABILITIES
),
361 DISPDBG((2, "getcolorCapabilities failed \n"));
363 pGdiInfo
->ciDevice
.Red
.x
= 6700;
364 pGdiInfo
->ciDevice
.Red
.y
= 3300;
365 pGdiInfo
->ciDevice
.Red
.Y
= 0;
366 pGdiInfo
->ciDevice
.Green
.x
= 2100;
367 pGdiInfo
->ciDevice
.Green
.y
= 7100;
368 pGdiInfo
->ciDevice
.Green
.Y
= 0;
369 pGdiInfo
->ciDevice
.Blue
.x
= 1400;
370 pGdiInfo
->ciDevice
.Blue
.y
= 800;
371 pGdiInfo
->ciDevice
.Blue
.Y
= 0;
372 pGdiInfo
->ciDevice
.AlignmentWhite
.x
= 3127;
373 pGdiInfo
->ciDevice
.AlignmentWhite
.y
= 3290;
374 pGdiInfo
->ciDevice
.AlignmentWhite
.Y
= 0;
376 pGdiInfo
->ciDevice
.RedGamma
= 20000;
377 pGdiInfo
->ciDevice
.GreenGamma
= 20000;
378 pGdiInfo
->ciDevice
.BlueGamma
= 20000;
383 pGdiInfo
->ciDevice
.Red
.x
= colorCapabilities
.RedChromaticity_x
;
384 pGdiInfo
->ciDevice
.Red
.y
= colorCapabilities
.RedChromaticity_y
;
385 pGdiInfo
->ciDevice
.Red
.Y
= 0;
386 pGdiInfo
->ciDevice
.Green
.x
= colorCapabilities
.GreenChromaticity_x
;
387 pGdiInfo
->ciDevice
.Green
.y
= colorCapabilities
.GreenChromaticity_y
;
388 pGdiInfo
->ciDevice
.Green
.Y
= 0;
389 pGdiInfo
->ciDevice
.Blue
.x
= colorCapabilities
.BlueChromaticity_x
;
390 pGdiInfo
->ciDevice
.Blue
.y
= colorCapabilities
.BlueChromaticity_y
;
391 pGdiInfo
->ciDevice
.Blue
.Y
= 0;
392 pGdiInfo
->ciDevice
.AlignmentWhite
.x
= colorCapabilities
.WhiteChromaticity_x
;
393 pGdiInfo
->ciDevice
.AlignmentWhite
.y
= colorCapabilities
.WhiteChromaticity_y
;
394 pGdiInfo
->ciDevice
.AlignmentWhite
.Y
= colorCapabilities
.WhiteChromaticity_Y
;
396 // if we have a color device store the three color gamma values,
397 // otherwise store the unique gamma value in all three.
399 if (colorCapabilities
.AttributeFlags
& VIDEO_DEVICE_COLOR
)
401 pGdiInfo
->ciDevice
.RedGamma
= colorCapabilities
.RedGamma
;
402 pGdiInfo
->ciDevice
.GreenGamma
= colorCapabilities
.GreenGamma
;
403 pGdiInfo
->ciDevice
.BlueGamma
= colorCapabilities
.BlueGamma
;
407 pGdiInfo
->ciDevice
.RedGamma
= colorCapabilities
.WhiteGamma
;
408 pGdiInfo
->ciDevice
.GreenGamma
= colorCapabilities
.WhiteGamma
;
409 pGdiInfo
->ciDevice
.BlueGamma
= colorCapabilities
.WhiteGamma
;
414 pGdiInfo
->ciDevice
.Cyan
.x
= 0;
415 pGdiInfo
->ciDevice
.Cyan
.y
= 0;
416 pGdiInfo
->ciDevice
.Cyan
.Y
= 0;
417 pGdiInfo
->ciDevice
.Magenta
.x
= 0;
418 pGdiInfo
->ciDevice
.Magenta
.y
= 0;
419 pGdiInfo
->ciDevice
.Magenta
.Y
= 0;
420 pGdiInfo
->ciDevice
.Yellow
.x
= 0;
421 pGdiInfo
->ciDevice
.Yellow
.y
= 0;
422 pGdiInfo
->ciDevice
.Yellow
.Y
= 0;
424 // No dye correction for raster displays.
426 pGdiInfo
->ciDevice
.MagentaInCyanDye
= 0;
427 pGdiInfo
->ciDevice
.YellowInCyanDye
= 0;
428 pGdiInfo
->ciDevice
.CyanInMagentaDye
= 0;
429 pGdiInfo
->ciDevice
.YellowInMagentaDye
= 0;
430 pGdiInfo
->ciDevice
.CyanInYellowDye
= 0;
431 pGdiInfo
->ciDevice
.MagentaInYellowDye
= 0;
433 pGdiInfo
->ulDevicePelsDPI
= 0; // For printers only
434 pGdiInfo
->ulPrimaryOrder
= PRIMARY_ORDER_CBA
;
436 // BUGBUG this should be modified to take into account the size
437 // of the display and the resolution.
439 pGdiInfo
->ulHTPatternSize
= HT_PATSIZE_4x4_M
;
441 pGdiInfo
->flHTFlags
= HT_FLAG_ADDITIVE_PRIMS
;
443 // Fill in the basic devinfo structure
445 *pDevInfo
= gDevInfoFrameBuffer
;
447 // Fill in the rest of the devinfo and GdiInfo structures.
449 if (ppdev
->ulBitCount
== 8)
451 // It is Palette Managed.
453 pGdiInfo
->ulNumColors
= 20;
454 pGdiInfo
->ulNumPalReg
= 1 << ppdev
->ulBitCount
;
455 // eVb: 2.7 [DDK CHANGE] - No dithering support
456 pDevInfo
->flGraphicsCaps
|= GCAPS_PALMANAGED
;
458 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_8BPP
;
459 pDevInfo
->iDitherFormat
= BMF_8BPP
;
461 // Assuming palette is orthogonal - all colors are same size.
463 ppdev
->cPaletteShift
= 8 - pGdiInfo
->ulDACRed
;
467 pGdiInfo
->ulNumColors
= (ULONG
) (-1);
468 pGdiInfo
->ulNumPalReg
= 0;
470 if (ppdev
->ulBitCount
== 16)
472 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_16BPP
;
473 pDevInfo
->iDitherFormat
= BMF_16BPP
;
475 else if (ppdev
->ulBitCount
== 24)
477 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_24BPP
;
478 pDevInfo
->iDitherFormat
= BMF_24BPP
;
482 pGdiInfo
->ulHTOutputFormat
= HT_FORMAT_32BPP
;
483 pDevInfo
->iDitherFormat
= BMF_32BPP
;
487 EngFreeMem(pVideoBuffer
);
493 /******************************Public*Routine******************************\
496 * Calls the miniport to get the list of modes supported by the kernel driver,
497 * and returns the list of modes supported by the diplay driver among those
499 * returns the number of entries in the videomode buffer.
500 * 0 means no modes are supported by the miniport or that an error occured.
502 * NOTE: the buffer must be freed up by the caller.
504 \**************************************************************************/
506 DWORD
getAvailableModes(
508 PVIDEO_MODE_INFORMATION
*modeInformation
,
512 VIDEO_NUM_MODES modes
;
513 PVIDEO_MODE_INFORMATION pVideoTemp
;
516 // Get the number of modes supported by the mini-port
519 if (EngDeviceIoControl(hDriver
,
520 IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
,
524 sizeof(VIDEO_NUM_MODES
),
527 DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_NUM_AVAIL_MODES\n"));
531 *cbModeSize
= modes
.ModeInformationLength
;
534 // Allocate the buffer for the mini-port to write the modes in.
537 *modeInformation
= (PVIDEO_MODE_INFORMATION
)
538 EngAllocMem(0, modes
.NumModes
*
539 modes
.ModeInformationLength
, ALLOC_TAG
);
541 if (*modeInformation
== (PVIDEO_MODE_INFORMATION
) NULL
)
543 DISPDBG((0, "getAvailableModes failed EngAllocMem\n"));
549 // Ask the mini-port to fill in the available modes.
552 if (EngDeviceIoControl(hDriver
,
553 IOCTL_VIDEO_QUERY_AVAIL_MODES
,
557 modes
.NumModes
* modes
.ModeInformationLength
,
561 DISPDBG((0, "getAvailableModes failed VIDEO_QUERY_AVAIL_MODES\n"));
563 EngFreeMem(*modeInformation
);
564 *modeInformation
= (PVIDEO_MODE_INFORMATION
) NULL
;
570 // Now see which of these modes are supported by the display driver.
571 // As an internal mechanism, set the length to 0 for the modes we
575 ulTemp
= modes
.NumModes
;
576 pVideoTemp
= *modeInformation
;
579 // Mode is rejected if it is not one plane, or not graphics, or is not
580 // one of 8, 16 or 32 bits per pel.
585 if ((pVideoTemp
->NumberOfPlanes
!= 1 ) ||
586 !(pVideoTemp
->AttributeFlags
& VIDEO_MODE_GRAPHICS
) ||
587 // eVb: 2.6 [DDK CHANGE] - Do not process banked video modes
588 (pVideoTemp
->AttributeFlags
& VIDEO_MODE_BANKED
) ||
590 ((pVideoTemp
->BitsPerPlane
!= 8) &&
591 (pVideoTemp
->BitsPerPlane
!= 16) &&
592 (pVideoTemp
->BitsPerPlane
!= 24) &&
593 (pVideoTemp
->BitsPerPlane
!= 32)))
595 pVideoTemp
->Length
= 0;
598 pVideoTemp
= (PVIDEO_MODE_INFORMATION
)
599 (((PUCHAR
)pVideoTemp
) + modes
.ModeInformationLength
);
602 return modes
.NumModes
;