mirror of
https://github.com/reactos/reactos.git
synced 2024-11-03 13:25:57 +00:00
326 lines
8.1 KiB
C
326 lines
8.1 KiB
C
/*
|
|
* ReactOS Generic Framebuffer acclations display driver
|
|
*
|
|
* Copyright (C) 2004 Filip Navara
|
|
* Copyright (C) 2007 Magnus Olsen
|
|
*
|
|
* 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 "framebufacc.h"
|
|
|
|
BOOL
|
|
InitSurface(PPDEV ppdev,
|
|
BOOL bForcemapping)
|
|
{
|
|
VIDEO_MEMORY VideoMemory;
|
|
VIDEO_MEMORY_INFORMATION VideoMemoryInfo;
|
|
ULONG returnedDataLength;
|
|
ULONG RemappingNeeded = 0;
|
|
ULONG PointerMaxWidth = 0;
|
|
ULONG PointerMaxHeight = 0;
|
|
|
|
/*
|
|
* Set video mode of our adapter.
|
|
*/
|
|
|
|
if (EngDeviceIoControl(ppdev->hDriver,
|
|
IOCTL_VIDEO_SET_CURRENT_MODE,
|
|
&(ppdev->ModeIndex),
|
|
sizeof(ULONG),
|
|
&RemappingNeeded,
|
|
sizeof(ULONG),
|
|
&returnedDataLength))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Check if mapping is need it */
|
|
if ((!bForcemapping) &&
|
|
(!RemappingNeeded))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Map the framebuffer into our memory.
|
|
*/
|
|
|
|
VideoMemory.RequestedVirtualAddress = NULL;
|
|
if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_MAP_VIDEO_MEMORY,
|
|
&VideoMemory, sizeof(VIDEO_MEMORY),
|
|
&VideoMemoryInfo, sizeof(VIDEO_MEMORY_INFORMATION),
|
|
&returnedDataLength))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Save the real video memory
|
|
*/
|
|
ppdev->pRealVideoMem = VideoMemoryInfo.FrameBufferBase;
|
|
ppdev->VideoMemSize = VideoMemoryInfo.VideoRamLength;
|
|
|
|
|
|
/*
|
|
* Video memory cached
|
|
*
|
|
* We maby should only ask max 8MB as cached ?, think of the video ram length is 256MB
|
|
*/
|
|
|
|
ppdev->pVideoMemCache = NULL;
|
|
#ifdef EXPERIMENTAL_ACC_SUPPORT
|
|
|
|
ppdev->pVideoMemCache = EngAllocMem(0, (ULONG)VideoMemoryInfo.VideoRamLength, ALLOC_TAG);
|
|
if (ppdev->pVideoMemCache == NULL)
|
|
{
|
|
/* cached off for no avail system memory */
|
|
ppdev->ScreenPtr = VideoMemoryInfo.FrameBufferBase;
|
|
}
|
|
else
|
|
|
|
#endif
|
|
{
|
|
/* cached on, system memory is avail */
|
|
ppdev->ScreenPtr = ppdev->pRealVideoMem;
|
|
}
|
|
|
|
/* hw mouse pointer support */
|
|
PointerMaxHeight = ppdev->PointerCapabilities.MaxHeight;
|
|
PointerMaxWidth = ppdev->PointerCapabilities.MaxWidth * sizeof(ULONG);
|
|
if (ppdev->PointerCapabilities.Flags & VIDEO_MODE_COLOR_POINTER)
|
|
{
|
|
PointerMaxWidth = (ppdev->PointerCapabilities.MaxWidth + 7) / 8;
|
|
}
|
|
|
|
ppdev->PointerAttributesSize = sizeof(VIDEO_POINTER_ATTRIBUTES) + ((sizeof(UCHAR) * PointerMaxWidth * PointerMaxHeight) << 1);
|
|
|
|
ppdev->pPointerAttributes = EngAllocMem(0, ppdev->PointerAttributesSize, ALLOC_TAG);
|
|
|
|
if (ppdev->pPointerAttributes != NULL)
|
|
{
|
|
ppdev->pPointerAttributes->Flags = ppdev->PointerCapabilities.Flags;
|
|
ppdev->pPointerAttributes->WidthInBytes = PointerMaxWidth;
|
|
ppdev->pPointerAttributes->Width = ppdev->PointerCapabilities.MaxWidth;
|
|
ppdev->pPointerAttributes->Height = PointerMaxHeight;
|
|
ppdev->pPointerAttributes->Column = 0;
|
|
ppdev->pPointerAttributes->Row = 0;
|
|
ppdev->pPointerAttributes->Enable = 0;
|
|
}
|
|
else
|
|
{
|
|
/* no hw mouse was avail */
|
|
ppdev->PointerAttributesSize = 0;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* DrvEnableSurface
|
|
*
|
|
* Create engine bitmap around frame buffer and set the video mode requested
|
|
* when PDEV was initialized.
|
|
*
|
|
* Status
|
|
* @implemented
|
|
*/
|
|
|
|
HSURF APIENTRY
|
|
DrvEnableSurface(
|
|
IN DHPDEV dhpdev)
|
|
{
|
|
PPDEV ppdev = (PPDEV)dhpdev;
|
|
HSURF hSurface;
|
|
ULONG BitmapType;
|
|
SIZEL ScreenSize;
|
|
|
|
|
|
/* Setup surface and force the mapping */
|
|
if (!InitSurface(ppdev, TRUE))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Rest the desktop vitual position */
|
|
ppdev->ScreenOffsetXY.x = 0;
|
|
ppdev->ScreenOffsetXY.y = 0;
|
|
|
|
|
|
switch (ppdev->BitsPerPixel)
|
|
{
|
|
case 8:
|
|
IntSetPalette(dhpdev, ppdev->PaletteEntries, 0, 256);
|
|
BitmapType = BMF_8BPP;
|
|
break;
|
|
|
|
case 16:
|
|
BitmapType = BMF_16BPP;
|
|
break;
|
|
|
|
case 24:
|
|
BitmapType = BMF_24BPP;
|
|
break;
|
|
|
|
case 32:
|
|
BitmapType = BMF_32BPP;
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
ppdev->iDitherFormat = BitmapType;
|
|
|
|
ScreenSize.cx = ppdev->ScreenWidth;
|
|
ScreenSize.cy = ppdev->ScreenHeight;
|
|
|
|
hSurface = (HSURF)EngCreateBitmap(ScreenSize, ppdev->ScreenDelta, BitmapType,
|
|
(ppdev->ScreenDelta > 0) ? BMF_TOPDOWN : 0,
|
|
ppdev->ScreenPtr);
|
|
if (hSurface == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/* Which api we hooking to */
|
|
ppdev->dwHooks = HOOK_BITBLT | HOOK_COPYBITS | HOOK_FILLPATH | HOOK_TEXTOUT | HOOK_STROKEPATH | HOOK_LINETO ;
|
|
|
|
/*
|
|
* Associate the surface with our device.
|
|
*/
|
|
|
|
|
|
if (!EngAssociateSurface(hSurface, ppdev->hDevEng, ppdev->dwHooks))
|
|
{
|
|
EngDeleteSurface(hSurface);
|
|
return FALSE;
|
|
}
|
|
|
|
ppdev->hSurfEng = hSurface;
|
|
|
|
return hSurface;
|
|
}
|
|
|
|
/*
|
|
* DrvDisableSurface
|
|
*
|
|
* Used by GDI to notify a driver that the surface created by DrvEnableSurface
|
|
* for the current device is no longer needed.
|
|
*
|
|
* Status
|
|
* @implemented
|
|
*/
|
|
|
|
VOID APIENTRY
|
|
DrvDisableSurface(
|
|
IN DHPDEV dhpdev)
|
|
{
|
|
DWORD ulTemp;
|
|
VIDEO_MEMORY VideoMemory;
|
|
PPDEV ppdev = (PPDEV)dhpdev;
|
|
|
|
EngDeleteSurface(ppdev->hSurfEng);
|
|
ppdev->hSurfEng = NULL;
|
|
|
|
|
|
/* Free the video memory cache */
|
|
if (ppdev->pVideoMemCache)
|
|
{
|
|
EngFreeMem(ppdev->pVideoMemCache);
|
|
}
|
|
|
|
/*
|
|
* Unmap the framebuffer.
|
|
*/
|
|
|
|
VideoMemory.RequestedVirtualAddress = ppdev->pRealVideoMem;
|
|
EngDeviceIoControl(((PPDEV)dhpdev)->hDriver, IOCTL_VIDEO_UNMAP_VIDEO_MEMORY,
|
|
&VideoMemory, sizeof(VIDEO_MEMORY), NULL, 0, &ulTemp);
|
|
|
|
ppdev->pRealVideoMem = NULL;
|
|
ppdev->pVideoMemCache = NULL;
|
|
|
|
}
|
|
|
|
/*
|
|
* DrvAssertMode
|
|
*
|
|
* Sets the mode of the specified physical device to either the mode specified
|
|
* when the PDEV was initialized or to the default mode of the hardware.
|
|
*
|
|
* Status
|
|
* @implemented
|
|
*/
|
|
|
|
BOOL APIENTRY
|
|
DrvAssertMode(
|
|
IN DHPDEV dhpdev,
|
|
IN BOOL bEnable)
|
|
{
|
|
PPDEV ppdev = (PPDEV)dhpdev;
|
|
ULONG ulTemp;
|
|
BOOLEAN Result = TRUE;
|
|
|
|
if (bEnable)
|
|
{
|
|
PVOID pRealVideoMem = ppdev->pRealVideoMem;
|
|
|
|
/* Setup surface and remapping if it need it */
|
|
if (!InitSurface(ppdev, FALSE))
|
|
{
|
|
Result = FALSE;
|
|
}
|
|
else
|
|
{
|
|
/* Check if we got same surface or not */
|
|
if (pRealVideoMem != ppdev->pRealVideoMem)
|
|
{
|
|
PVOID pVideoMem= NULL;
|
|
|
|
if (ppdev->pVideoMemCache == NULL)
|
|
{
|
|
pVideoMem = ppdev->pRealVideoMem;
|
|
}
|
|
else
|
|
{
|
|
pVideoMem = ppdev->pVideoMemCache;
|
|
}
|
|
|
|
Result = !EngModifySurface(ppdev->hSurfEng, ppdev->hDevEng,
|
|
ppdev->dwHooks | HOOK_SYNCHRONIZE,
|
|
0, (DHSURF)ppdev, pVideoMem,
|
|
ppdev->ScreenDelta, NULL);
|
|
}
|
|
|
|
/* if the pRealVideoMem == ppdev->pRealVideoMem are
|
|
* the Result is then TRUE
|
|
*/
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Call the miniport driver to reset the device to a known state.
|
|
*/
|
|
|
|
Result = !EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_RESET_DEVICE,
|
|
NULL, 0, NULL, 0, &ulTemp);
|
|
}
|
|
|
|
return Result;
|
|
}
|