/* * ReactOS Generic Framebuffer display driver * * Copyright (C) 2004 Filip Navara * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "framebuf.h" 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" }; 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" }; 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" }; /* * GetAvailableModes * * Calls the miniport to get the list of modes supported by the kernel driver, * and returns the list of modes supported by the display driver. */ DWORD GetAvailableModes( HANDLE hDriver, PVIDEO_MODE_INFORMATION *ModeInfo, DWORD *ModeInfoSize) { ULONG ulTemp; VIDEO_NUM_MODES Modes; PVIDEO_MODE_INFORMATION ModeInfoPtr; /* * Get the number of modes supported by the mini-port */ if (EngDeviceIoControl(hDriver, IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES, NULL, 0, &Modes, sizeof(VIDEO_NUM_MODES), &ulTemp)) { return 0; } if (Modes.NumModes == 0) { return 0; } *ModeInfoSize = Modes.ModeInformationLength; /* * Allocate the buffer for the miniport to write the modes in. */ *ModeInfo = (PVIDEO_MODE_INFORMATION)EngAllocMem(0, Modes.NumModes * Modes.ModeInformationLength, ALLOC_TAG); if (*ModeInfo == NULL) { return 0; } /* * Ask the miniport to fill in the available modes. */ if (EngDeviceIoControl(hDriver, IOCTL_VIDEO_QUERY_AVAIL_MODES, NULL, 0, *ModeInfo, Modes.NumModes * Modes.ModeInformationLength, &ulTemp)) { EngFreeMem(*ModeInfo); *ModeInfo = NULL; return 0; } /* * Now see which of these modes are supported by the display driver. * As an internal mechanism, set the length to 0 for the modes we * DO NOT support. */ ulTemp = Modes.NumModes; ModeInfoPtr = *ModeInfo; /* * Mode is rejected if it is not one plane, or not graphics, or is not * one of 8, 16 or 32 bits per pel. */ while (ulTemp--) { if ((ModeInfoPtr->NumberOfPlanes != 1) || !(ModeInfoPtr->AttributeFlags & VIDEO_MODE_GRAPHICS) || ((ModeInfoPtr->BitsPerPlane != 8) && (ModeInfoPtr->BitsPerPlane != 16) && (ModeInfoPtr->BitsPerPlane != 24) && (ModeInfoPtr->BitsPerPlane != 32))) { ModeInfoPtr->Length = 0; } ModeInfoPtr = (PVIDEO_MODE_INFORMATION) (((PUCHAR)ModeInfoPtr) + Modes.ModeInformationLength); } return Modes.NumModes; } BOOL IntInitScreenInfo( PPDEV ppdev, LPDEVMODEW pDevMode, PGDIINFO pGdiInfo, PDEVINFO pDevInfo) { ULONG ModeCount; ULONG ModeInfoSize; PVIDEO_MODE_INFORMATION ModeInfo, ModeInfoPtr, SelectedMode = NULL; VIDEO_COLOR_CAPABILITIES ColorCapabilities; ULONG Temp; /* * Call miniport to get information about video modes. */ ModeCount = GetAvailableModes(ppdev->hDriver, &ModeInfo, &ModeInfoSize); if (ModeCount == 0) { return FALSE; } /* * Select the video mode depending on the info passed in pDevMode. */ if (pDevMode->dmPelsWidth == 0 && pDevMode->dmPelsHeight == 0 && pDevMode->dmBitsPerPel == 0 && pDevMode->dmDisplayFrequency == 0) { ModeInfoPtr = ModeInfo; while (ModeCount-- > 0) { if (ModeInfoPtr->Length == 0) { ModeInfoPtr = (PVIDEO_MODE_INFORMATION) (((PUCHAR)ModeInfoPtr) + ModeInfoSize); continue; } SelectedMode = ModeInfoPtr; break; } } else { ModeInfoPtr = ModeInfo; while (ModeCount-- > 0) { if (ModeInfoPtr->Length > 0 && pDevMode->dmPelsWidth == ModeInfoPtr->VisScreenWidth && pDevMode->dmPelsHeight == ModeInfoPtr->VisScreenHeight && pDevMode->dmBitsPerPel == (ModeInfoPtr->BitsPerPlane * ModeInfoPtr->NumberOfPlanes) && pDevMode->dmDisplayFrequency == ModeInfoPtr->Frequency) { SelectedMode = ModeInfoPtr; break; } ModeInfoPtr = (PVIDEO_MODE_INFORMATION) (((PUCHAR)ModeInfoPtr) + ModeInfoSize); } } if (SelectedMode == NULL) { EngFreeMem(ModeInfo); return FALSE; } /* * Fill in the GDIINFO data structure with the information returned from * the kernel driver. */ ppdev->ModeIndex = SelectedMode->ModeIndex; ppdev->ScreenWidth = SelectedMode->VisScreenWidth; ppdev->ScreenHeight = SelectedMode->VisScreenHeight; ppdev->ScreenDelta = SelectedMode->ScreenStride; ppdev->BitsPerPixel = (UCHAR)(SelectedMode->BitsPerPlane * SelectedMode->NumberOfPlanes); ppdev->MemWidth = SelectedMode->VideoMemoryBitmapWidth; ppdev->MemHeight = SelectedMode->VideoMemoryBitmapHeight; ppdev->RedMask = SelectedMode->RedMask; ppdev->GreenMask = SelectedMode->GreenMask; ppdev->BlueMask = SelectedMode->BlueMask; pGdiInfo->ulVersion = GDI_DRIVER_VERSION; pGdiInfo->ulTechnology = DT_RASDISPLAY; pGdiInfo->ulHorzSize = SelectedMode->XMillimeter; pGdiInfo->ulVertSize = SelectedMode->YMillimeter; pGdiInfo->ulHorzRes = SelectedMode->VisScreenWidth; pGdiInfo->ulVertRes = SelectedMode->VisScreenHeight; pGdiInfo->ulPanningHorzRes = SelectedMode->VisScreenWidth; pGdiInfo->ulPanningVertRes = SelectedMode->VisScreenHeight; pGdiInfo->cBitsPixel = SelectedMode->BitsPerPlane; pGdiInfo->cPlanes = SelectedMode->NumberOfPlanes; pGdiInfo->ulVRefresh = SelectedMode->Frequency; pGdiInfo->ulBltAlignment = 1; pGdiInfo->ulLogPixelsX = pDevMode->dmLogPixels; pGdiInfo->ulLogPixelsY = pDevMode->dmLogPixels; pGdiInfo->flTextCaps = TC_RA_ABLE; pGdiInfo->flRaster = 0; pGdiInfo->ulDACRed = SelectedMode->NumberRedBits; pGdiInfo->ulDACGreen = SelectedMode->NumberGreenBits; pGdiInfo->ulDACBlue = SelectedMode->NumberBlueBits; pGdiInfo->ulAspectX = 0x24; pGdiInfo->ulAspectY = 0x24; pGdiInfo->ulAspectXY = 0x33; pGdiInfo->xStyleStep = 1; pGdiInfo->yStyleStep = 1; pGdiInfo->denStyleStep = 3; pGdiInfo->ptlPhysOffset.x = 0; pGdiInfo->ptlPhysOffset.y = 0; pGdiInfo->szlPhysSize.cx = 0; pGdiInfo->szlPhysSize.cy = 0; /* * Try to get the color info from the miniport. */ if (!EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES, NULL, 0, &ColorCapabilities, sizeof(VIDEO_COLOR_CAPABILITIES), &Temp)) { pGdiInfo->ciDevice.Red.x = ColorCapabilities.RedChromaticity_x; pGdiInfo->ciDevice.Red.y = ColorCapabilities.RedChromaticity_y; pGdiInfo->ciDevice.Green.x = ColorCapabilities.GreenChromaticity_x; pGdiInfo->ciDevice.Green.y = ColorCapabilities.GreenChromaticity_y; pGdiInfo->ciDevice.Blue.x = ColorCapabilities.BlueChromaticity_x; pGdiInfo->ciDevice.Blue.y = ColorCapabilities.BlueChromaticity_y; pGdiInfo->ciDevice.AlignmentWhite.x = ColorCapabilities.WhiteChromaticity_x; pGdiInfo->ciDevice.AlignmentWhite.y = ColorCapabilities.WhiteChromaticity_y; pGdiInfo->ciDevice.AlignmentWhite.Y = ColorCapabilities.WhiteChromaticity_Y; if (ColorCapabilities.AttributeFlags & VIDEO_DEVICE_COLOR) { pGdiInfo->ciDevice.RedGamma = ColorCapabilities.RedGamma; pGdiInfo->ciDevice.GreenGamma = ColorCapabilities.GreenGamma; pGdiInfo->ciDevice.BlueGamma = ColorCapabilities.BlueGamma; } else { pGdiInfo->ciDevice.RedGamma = ColorCapabilities.WhiteGamma; pGdiInfo->ciDevice.GreenGamma = ColorCapabilities.WhiteGamma; pGdiInfo->ciDevice.BlueGamma = ColorCapabilities.WhiteGamma; } } else { pGdiInfo->ciDevice.Red.x = 6700; pGdiInfo->ciDevice.Red.y = 3300; pGdiInfo->ciDevice.Green.x = 2100; pGdiInfo->ciDevice.Green.y = 7100; pGdiInfo->ciDevice.Blue.x = 1400; pGdiInfo->ciDevice.Blue.y = 800; pGdiInfo->ciDevice.AlignmentWhite.x = 3127; pGdiInfo->ciDevice.AlignmentWhite.y = 3290; pGdiInfo->ciDevice.AlignmentWhite.Y = 0; pGdiInfo->ciDevice.RedGamma = 20000; pGdiInfo->ciDevice.GreenGamma = 20000; pGdiInfo->ciDevice.BlueGamma = 20000; } pGdiInfo->ciDevice.Red.Y = 0; pGdiInfo->ciDevice.Green.Y = 0; pGdiInfo->ciDevice.Blue.Y = 0; pGdiInfo->ciDevice.Cyan.x = 0; pGdiInfo->ciDevice.Cyan.y = 0; pGdiInfo->ciDevice.Cyan.Y = 0; pGdiInfo->ciDevice.Magenta.x = 0; pGdiInfo->ciDevice.Magenta.y = 0; pGdiInfo->ciDevice.Magenta.Y = 0; pGdiInfo->ciDevice.Yellow.x = 0; pGdiInfo->ciDevice.Yellow.y = 0; pGdiInfo->ciDevice.Yellow.Y = 0; pGdiInfo->ciDevice.MagentaInCyanDye = 0; pGdiInfo->ciDevice.YellowInCyanDye = 0; pGdiInfo->ciDevice.CyanInMagentaDye = 0; pGdiInfo->ciDevice.YellowInMagentaDye = 0; pGdiInfo->ciDevice.CyanInYellowDye = 0; pGdiInfo->ciDevice.MagentaInYellowDye = 0; pGdiInfo->ulDevicePelsDPI = 0; pGdiInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA; pGdiInfo->ulHTPatternSize = HT_PATSIZE_4x4_M; pGdiInfo->flHTFlags = HT_FLAG_ADDITIVE_PRIMS; pDevInfo->flGraphicsCaps = 0; pDevInfo->lfDefaultFont = SystemFont; pDevInfo->lfAnsiVarFont = AnsiVariableFont; pDevInfo->lfAnsiFixFont = AnsiFixedFont; pDevInfo->cFonts = 0; pDevInfo->cxDither = 0; pDevInfo->cyDither = 0; pDevInfo->hpalDefault = 0; pDevInfo->flGraphicsCaps2 = 0; if (ppdev->BitsPerPixel == 8) { pGdiInfo->ulNumColors = 20; pGdiInfo->ulNumPalReg = 1 << ppdev->BitsPerPixel; pGdiInfo->ulHTOutputFormat = HT_FORMAT_8BPP; pDevInfo->flGraphicsCaps |= GCAPS_PALMANAGED; pDevInfo->iDitherFormat = BMF_8BPP; /* Assuming palette is orthogonal - all colors are same size. */ ppdev->PaletteShift = (UCHAR)(8 - pGdiInfo->ulDACRed); } else { pGdiInfo->ulNumColors = (ULONG)(-1); pGdiInfo->ulNumPalReg = 0; switch (ppdev->BitsPerPixel) { case 16: pGdiInfo->ulHTOutputFormat = HT_FORMAT_16BPP; pDevInfo->iDitherFormat = BMF_16BPP; break; case 24: pGdiInfo->ulHTOutputFormat = HT_FORMAT_24BPP; pDevInfo->iDitherFormat = BMF_24BPP; break; default: pGdiInfo->ulHTOutputFormat = HT_FORMAT_32BPP; pDevInfo->iDitherFormat = BMF_32BPP; } } EngFreeMem(ModeInfo); return TRUE; } /* * DrvGetModes * * Returns the list of available modes for the device. * * Status * @implemented */ ULONG APIENTRY DrvGetModes( IN HANDLE hDriver, IN ULONG cjSize, OUT DEVMODEW *pdm) { ULONG ModeCount; ULONG ModeInfoSize; PVIDEO_MODE_INFORMATION ModeInfo, ModeInfoPtr; ULONG OutputSize; ModeCount = GetAvailableModes(hDriver, &ModeInfo, &ModeInfoSize); if (ModeCount == 0) { return 0; } if (pdm == NULL) { EngFreeMem(ModeInfo); return ModeCount * sizeof(DEVMODEW); } /* * Copy the information about supported modes into the output buffer. */ OutputSize = 0; ModeInfoPtr = ModeInfo; while (ModeCount-- > 0) { if (ModeInfoPtr->Length == 0) { ModeInfoPtr = (PVIDEO_MODE_INFORMATION)(((ULONG_PTR)ModeInfoPtr) + ModeInfoSize); continue; } memset(pdm, 0, sizeof(DEVMODEW)); memcpy(pdm->dmDeviceName, DEVICE_NAME, sizeof(DEVICE_NAME)); pdm->dmSpecVersion = pdm->dmDriverVersion = DM_SPECVERSION; pdm->dmSize = sizeof(DEVMODEW); pdm->dmDriverExtra = 0; pdm->dmBitsPerPel = ModeInfoPtr->NumberOfPlanes * ModeInfoPtr->BitsPerPlane; pdm->dmPelsWidth = ModeInfoPtr->VisScreenWidth; pdm->dmPelsHeight = ModeInfoPtr->VisScreenHeight; pdm->dmDisplayFrequency = ModeInfoPtr->Frequency; pdm->dmDisplayFlags = 0; pdm->dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS; ModeInfoPtr = (PVIDEO_MODE_INFORMATION)(((ULONG_PTR)ModeInfoPtr) + ModeInfoSize); pdm = (LPDEVMODEW)(((ULONG_PTR)pdm) + sizeof(DEVMODEW)); OutputSize += sizeof(DEVMODEW); } EngFreeMem(ModeInfo); return OutputSize; }