mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
52275a92bd
See for example, in DrvEnableSurface(), etc. TODO: framebufacc's comments need to be "translated" into actual English...
420 lines
13 KiB
C
420 lines
13 KiB
C
/*
|
|
* 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;
|
|
}
|