You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1050 lines
33 KiB
1050 lines
33 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: screen.c
|
|
*
|
|
* This file contains the virtual driver that is used for user-mode GDI+
|
|
* painting on the desktop screen.
|
|
*
|
|
* Copyright (c) 1998-1999 Microsoft Corporation
|
|
*
|
|
* Created: 29-Apr-1998
|
|
* Author: J. Andrew Goossen [andrewgo]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
// @@@ Re-visit headers:
|
|
|
|
#define NO_DDRAWINT_NO_COM
|
|
|
|
// @@@ Temporary:
|
|
|
|
#include <stddef.h>
|
|
#include <stdarg.h>
|
|
#include <limits.h>
|
|
#include <windef.h>
|
|
#include <winerror.h>
|
|
#include <ddraw.h>
|
|
#include <wingdi.h>
|
|
#include <winddi.h>
|
|
#include <math.h>
|
|
|
|
VOID vFreeMem(VOID*);
|
|
VOID* pAllocMem(ULONG, ULONG);
|
|
|
|
#define RIP(x) OutputDebugString(x)
|
|
#define WARNING(x) OutputDebugString(x)
|
|
#define ASSERTGDI(x, y) if (!(x)) OutputDebugString(y)
|
|
#define PALLOCMEM(size, tag) pAllocMem(size, tag);
|
|
#define VFREEMEM(p) vFreeMem(p);
|
|
|
|
ULONG
|
|
DbgPrint(
|
|
PCH Format,
|
|
...
|
|
);
|
|
|
|
|
|
typedef struct _GPDEV
|
|
{
|
|
HDEV hdev;
|
|
HWND hwnd; // @@@ Hwnd this HDEV was created from
|
|
HSURF hsurfScreen; // Handle to the screen surface
|
|
SIZEL sizlScreen; // Size of the screen
|
|
ULONG iBitmapFormat; // The color depth
|
|
ULONG flRed; // The RGB color masks
|
|
ULONG flGreen;
|
|
ULONG flBlue;
|
|
HPALETTE hpalDefault; // The GDI palette handle
|
|
PALETTEENTRY* pPal; // The palette table if palette managed
|
|
LPDIRECTDRAW lpDD; // DirectDraw object
|
|
LPDIRECTDRAWSURFACE lpDDPrimary; // DirectDraw primary surface
|
|
LPDIRECTDRAWSURFACE lpDDBuffer; // DirectDraw buffer surface
|
|
LPDIRECTDRAWCLIPPER lpDDClipper; // Primary surface DirectDraw clipper
|
|
SURFOBJ* psoBuffer; // GDI surface wrapped around buffer
|
|
} GDEV;
|
|
|
|
/******************************Public*Structure****************************\
|
|
* GDIINFO ggdiGdiPlusDefault
|
|
*
|
|
* This contains the default GDIINFO fields that are passed back to GDI
|
|
* during DrvEnablePDEV.
|
|
*
|
|
* NOTE: This structure defaults to values for an 8bpp palette device.
|
|
* Some fields are overwritten for different colour depths.
|
|
\**************************************************************************/
|
|
|
|
GDIINFO ggdiGdiPlusDefault = {
|
|
GDI_DRIVER_VERSION,
|
|
DT_RASDISPLAY, // ulTechnology
|
|
320, // ulHorzSize
|
|
240, // ulVertSize
|
|
0, // ulHorzRes (filled in later)
|
|
0, // ulVertRes (filled in later)
|
|
0, // cBitsPixel (filled in later)
|
|
0, // cPlanes (filled in later)
|
|
20, // ulNumColors (palette managed)
|
|
0, // flRaster (DDI reserved field)
|
|
|
|
0, // ulLogPixelsX (filled in later)
|
|
0, // ulLogPixelsY (filled in later)
|
|
|
|
TC_RA_ABLE, // flTextCaps -- If we had wanted console windows
|
|
// to scroll by repainting the entire window,
|
|
// instead of doing a screen-to-screen blt, we
|
|
// would have set TC_SCROLLBLT (yes, the flag is
|
|
// bass-ackwards).
|
|
|
|
8, // ulDACRed (possibly overwritten later)
|
|
8, // ulDACGreen (possibly overwritten later)
|
|
8, // ulDACBlue (possibly overwritten later)
|
|
|
|
0x0024, // ulAspectX
|
|
0x0024, // ulAspectY
|
|
0x0033, // ulAspectXY (one-to-one aspect ratio)
|
|
|
|
1, // xStyleStep
|
|
1, // yStyleSte;
|
|
3, // denStyleStep -- Styles have a one-to-one aspect
|
|
// ratio, and every 'dot' is 3 pixels long
|
|
|
|
{ 0, 0 }, // ptlPhysOffset
|
|
{ 0, 0 }, // szlPhysSize
|
|
|
|
256, // ulNumPalReg
|
|
|
|
// These fields are for halftone initialization. The actual values are
|
|
// a bit magic, but seem to work well on our display.
|
|
|
|
{ // ciDevice
|
|
{ 6700, 3300, 0 }, // Red
|
|
{ 2100, 7100, 0 }, // Green
|
|
{ 1400, 800, 0 }, // Blue
|
|
{ 1750, 3950, 0 }, // Cyan
|
|
{ 4050, 2050, 0 }, // Magenta
|
|
{ 4400, 5200, 0 }, // Yellow
|
|
{ 3127, 3290, 0 }, // AlignmentWhite
|
|
20000, // RedGamma
|
|
20000, // GreenGamma
|
|
20000, // BlueGamma
|
|
0, 0, 0, 0, 0, 0 // No dye correction for raster displays
|
|
},
|
|
|
|
0, // ulDevicePelsDPI (for printers only)
|
|
PRIMARY_ORDER_CBA, // ulPrimaryOrder
|
|
HT_PATSIZE_4x4_M, // ulHTPatternSize
|
|
HT_FORMAT_8BPP, // ulHTOutputFormat
|
|
HT_FLAG_ADDITIVE_PRIMS, // flHTFlags
|
|
0, // ulVRefresh
|
|
0, // ulPanningHorzRes
|
|
0, // ulPanningVertRes
|
|
0, // ulBltAlignment
|
|
};
|
|
|
|
/******************************Public*Structure****************************\
|
|
* DEVINFO gdevinfoGdiPlusDefault
|
|
*
|
|
* This contains the default DEVINFO fields that are passed back to GDI
|
|
* during DrvEnablePDEV.
|
|
*
|
|
* NOTE: This structure defaults to values for an 8bpp palette device.
|
|
* Some fields are overwritten for different colour depths.
|
|
\**************************************************************************/
|
|
|
|
#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"}
|
|
#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"}
|
|
#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"}
|
|
|
|
DEVINFO gdevinfoGdiPlusDefault = {
|
|
(GCAPS_OPAQUERECT |
|
|
GCAPS_PALMANAGED |
|
|
GCAPS_MONO_DITHER |
|
|
GCAPS_COLOR_DITHER),
|
|
// flGraphicsFlags
|
|
SYSTM_LOGFONT, // lfDefaultFont
|
|
HELVE_LOGFONT, // lfAnsiVarFont
|
|
COURI_LOGFONT, // lfAnsiFixFont
|
|
0, // cFonts
|
|
BMF_8BPP, // iDitherFormat
|
|
8, // cxDither
|
|
8, // cyDither
|
|
0 // hpalDefault (filled in later)
|
|
};
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vGpsUninitializeDirectDraw
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vGpsUninitializeDirectDraw(
|
|
GDEV* pgdev)
|
|
{
|
|
HSURF hsurf;
|
|
|
|
if (pgdev->psoBuffer != NULL)
|
|
{
|
|
hsurf = pgdev->psoBuffer->hsurf;
|
|
EngUnlockSurface(pgdev->psoBuffer);
|
|
EngDeleteSurface(hsurf);
|
|
}
|
|
if (pgdev->lpDDClipper != NULL)
|
|
{
|
|
pgdev->lpDDClipper->lpVtbl->Release(pgdev->lpDDClipper);
|
|
pgdev->lpDDClipper = NULL;
|
|
}
|
|
if (pgdev->lpDDBuffer != NULL)
|
|
{
|
|
pgdev->lpDDBuffer->lpVtbl->Release(pgdev->lpDDBuffer);
|
|
pgdev->lpDDBuffer = NULL;
|
|
}
|
|
if (pgdev->lpDDPrimary != NULL)
|
|
{
|
|
pgdev->lpDDPrimary->lpVtbl->Release(pgdev->lpDDPrimary);
|
|
pgdev->lpDDPrimary = NULL;
|
|
}
|
|
if (pgdev->lpDD != NULL)
|
|
{
|
|
pgdev->lpDD->lpVtbl->Release(pgdev->lpDD);
|
|
pgdev->lpDD = NULL;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bGpsInitializeDirectDraw
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL bGpsInitializeDirectDraw(
|
|
GDEV* pgdev,
|
|
HWND hwnd,
|
|
ULONG* pScreenWidth,
|
|
ULONG* pScreenHeight,
|
|
ULONG* pBitsPerPlane,
|
|
ULONG* pRedMask,
|
|
ULONG* pGreenMask,
|
|
ULONG* pBlueMask)
|
|
{
|
|
LPDIRECTDRAW lpDD;
|
|
DDSURFACEDESC DDMode;
|
|
DDSURFACEDESC ddsd;
|
|
LPDIRECTDRAWSURFACE lpDDPrimary;
|
|
LPDIRECTDRAWSURFACE lpDDBuffer;
|
|
LPDIRECTDRAWCLIPPER lpDDClipper;
|
|
SURFOBJ* psoBuffer;
|
|
SIZEL sizl;
|
|
ULONG iFormat;
|
|
HSURF hsurf;
|
|
|
|
DDMode.dwSize = sizeof(DDMode);
|
|
|
|
if (DirectDrawCreate(NULL, &lpDD, NULL) == DD_OK)
|
|
{
|
|
if ((lpDD->lpVtbl->SetCooperativeLevel(lpDD, hwnd, DDSCL_NORMAL) == DD_OK) &&
|
|
(lpDD->lpVtbl->GetDisplayMode(lpDD, &DDMode) == DD_OK))
|
|
{
|
|
*pScreenWidth = DDMode.dwWidth;
|
|
*pScreenHeight = DDMode.dwHeight;
|
|
*pBitsPerPlane = DDMode.ddpfPixelFormat.dwRGBBitCount;
|
|
*pRedMask = DDMode.ddpfPixelFormat.dwRBitMask;
|
|
*pGreenMask = DDMode.ddpfPixelFormat.dwGBitMask;
|
|
*pBlueMask = DDMode.ddpfPixelFormat.dwBBitMask;
|
|
|
|
// Create a primary surface:
|
|
|
|
RtlZeroMemory(&ddsd, sizeof(ddsd));
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
|
|
if (lpDD->lpVtbl->CreateSurface(lpDD, &ddsd, &lpDDPrimary, NULL) == DD_OK)
|
|
{
|
|
if (lpDD->lpVtbl->CreateClipper(lpDD, 0, &lpDDClipper, NULL) == DD_OK)
|
|
{
|
|
if ((lpDDClipper->lpVtbl->SetHWnd(lpDDClipper, 0, hwnd) == DD_OK) &&
|
|
(lpDDPrimary->lpVtbl->SetClipper(lpDDPrimary, lpDDClipper) == DD_OK))
|
|
{
|
|
// Create a temporary DirectDraw surface that's used
|
|
// as a staging area.
|
|
//
|
|
// @@@ This darn well better be temporary!
|
|
|
|
RtlZeroMemory(&ddsd, sizeof(ddsd));
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
|
|
ddsd.dwWidth = DDMode.dwWidth;
|
|
ddsd.dwHeight = DDMode.dwHeight;
|
|
|
|
if (lpDD->lpVtbl->CreateSurface(lpDD, &ddsd, &lpDDBuffer, NULL) == DD_OK)
|
|
{
|
|
if (lpDDBuffer->lpVtbl->Lock(lpDDBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL)
|
|
== DD_OK)
|
|
{
|
|
// Create a GDI surface to wrap around the temporary
|
|
// buffer:
|
|
|
|
sizl.cx = ddsd.dwWidth;
|
|
sizl.cy = ddsd.dwHeight;
|
|
|
|
switch (DDMode.ddpfPixelFormat.dwRGBBitCount)
|
|
{
|
|
case 4: iFormat = BMF_4BPP; break;
|
|
case 8: iFormat = BMF_8BPP; break;
|
|
case 16: iFormat = BMF_16BPP; break;
|
|
case 24: iFormat = BMF_24BPP; break;
|
|
case 32: iFormat = BMF_32BPP; break;
|
|
default: RIP("Unexpected dwRGBBitCount");
|
|
}
|
|
|
|
// !!! @@@ Why did I have to specify BMF_TOPDOWN?
|
|
|
|
hsurf = (HSURF) EngCreateBitmap(sizl,
|
|
ddsd.lPitch,
|
|
iFormat,
|
|
BMF_TOPDOWN,
|
|
ddsd.lpSurface);
|
|
|
|
lpDDBuffer->lpVtbl->Unlock(lpDDBuffer, ddsd.lpSurface);
|
|
|
|
if (hsurf != NULL)
|
|
{
|
|
psoBuffer = EngLockSurface(hsurf);
|
|
|
|
pgdev->hwnd = hwnd;
|
|
pgdev->lpDD = lpDD;
|
|
pgdev->lpDDPrimary = lpDDPrimary;
|
|
pgdev->lpDDBuffer = lpDDBuffer;
|
|
pgdev->psoBuffer = psoBuffer;
|
|
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
lpDDBuffer->lpVtbl->Release(lpDDBuffer);
|
|
}
|
|
}
|
|
|
|
lpDDClipper->lpVtbl->Release(lpDDClipper);
|
|
}
|
|
|
|
lpDDPrimary->lpVtbl->Release(lpDDPrimary);
|
|
}
|
|
}
|
|
|
|
lpDD->lpVtbl->Release(lpDD);
|
|
}
|
|
|
|
WARNING("Failed bGpsInitializeDirectDraw");
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bGpsInitializeModeFields
|
|
*
|
|
* Fill in the GDIINFO and DEVINFO structures required by the engine.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL bGpsInitializeModeFields(
|
|
GDEV* pgdev,
|
|
ULONG* pScreenWidth,
|
|
ULONG* pScreenHeight,
|
|
ULONG* pBitsPerPlane,
|
|
ULONG* pRedMask,
|
|
ULONG* pGreenMask,
|
|
ULONG* pBlueMask,
|
|
GDIINFO* pgdi,
|
|
DEVINFO* pdi)
|
|
{
|
|
ULONG BitsPerPlane;
|
|
ULONG RedMask;
|
|
ULONG GreenMask;
|
|
ULONG BlueMask;
|
|
ULONG ScreenWidth;
|
|
ULONG ScreenHeight;
|
|
|
|
RedMask = *pRedMask;
|
|
GreenMask = *pGreenMask;
|
|
BlueMask = *pBlueMask;
|
|
BitsPerPlane = *pBitsPerPlane;
|
|
ScreenWidth = *pScreenWidth;
|
|
ScreenHeight = *pScreenHeight;
|
|
|
|
pgdev->sizlScreen.cx = ScreenWidth;
|
|
pgdev->sizlScreen.cy = ScreenHeight;
|
|
|
|
// Fill in the GDIINFO data structure with the default 8bpp values:
|
|
|
|
*pgdi = ggdiGdiPlusDefault;
|
|
|
|
// Now overwrite the defaults with the relevant information returned
|
|
// from the kernel driver:
|
|
|
|
pgdi->ulHorzRes = ScreenWidth;
|
|
pgdi->ulVertRes = ScreenHeight;
|
|
pgdi->ulPanningHorzRes = ScreenWidth;
|
|
pgdi->ulPanningVertRes = ScreenHeight;
|
|
|
|
pgdi->cBitsPixel = BitsPerPlane;
|
|
pgdi->cPlanes = 1;
|
|
|
|
pgdi->ulLogPixelsX = 120; // @@@
|
|
pgdi->ulLogPixelsY = 120;
|
|
|
|
// Fill in the devinfo structure with the default 8bpp values:
|
|
|
|
*pdi = gdevinfoGdiPlusDefault;
|
|
|
|
if (BitsPerPlane == 8)
|
|
{
|
|
pgdev->iBitmapFormat = BMF_8BPP;
|
|
|
|
pgdi->ulDACRed = 0;
|
|
pgdi->ulDACGreen = 0;
|
|
pgdi->ulDACBlue = 0;
|
|
}
|
|
else if ((BitsPerPlane == 16) || (BitsPerPlane == 15))
|
|
{
|
|
pgdev->iBitmapFormat = BMF_16BPP;
|
|
pgdev->flRed = RedMask;
|
|
pgdev->flGreen = GreenMask;
|
|
pgdev->flBlue = BlueMask;
|
|
|
|
pgdi->ulNumColors = (ULONG) -1;
|
|
pgdi->ulNumPalReg = 0;
|
|
pgdi->ulHTOutputFormat = HT_FORMAT_16BPP;
|
|
|
|
pdi->iDitherFormat = BMF_16BPP;
|
|
pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
|
|
}
|
|
else if (BitsPerPlane == 24)
|
|
{
|
|
pgdev->iBitmapFormat = BMF_24BPP;
|
|
pgdev->flRed = RedMask;
|
|
pgdev->flGreen = GreenMask;
|
|
pgdev->flBlue = BlueMask;
|
|
|
|
pgdi->ulNumColors = (ULONG) -1;
|
|
pgdi->ulNumPalReg = 0;
|
|
pgdi->ulHTOutputFormat = HT_FORMAT_24BPP;
|
|
|
|
pdi->iDitherFormat = BMF_24BPP;
|
|
pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(BitsPerPlane == 32,
|
|
"This driver supports only 8, 16, 24 and 32bpp");
|
|
|
|
pgdev->iBitmapFormat = BMF_32BPP;
|
|
pgdev->flRed = RedMask;
|
|
pgdev->flGreen = GreenMask;
|
|
pgdev->flBlue = BlueMask;
|
|
|
|
pgdi->ulNumColors = (ULONG) -1;
|
|
pgdi->ulNumPalReg = 0;
|
|
pgdi->ulHTOutputFormat = HT_FORMAT_32BPP;
|
|
|
|
pdi->iDitherFormat = BMF_32BPP;
|
|
pdi->flGraphicsCaps &= ~(GCAPS_PALMANAGED | GCAPS_COLOR_DITHER);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL bGpsInitializePalette
|
|
*
|
|
* Initializes default palette for PDEV.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL bGpsInitializePalette(
|
|
GDEV* pgdev,
|
|
DEVINFO* pdi)
|
|
{
|
|
PALETTEENTRY* ppal;
|
|
PALETTEENTRY* ppalTmp;
|
|
ULONG ulLoop;
|
|
BYTE jRed;
|
|
BYTE jGre;
|
|
BYTE jBlu;
|
|
HPALETTE hpal;
|
|
|
|
if (pgdev->iBitmapFormat == BMF_8BPP)
|
|
{
|
|
// Allocate our palette:
|
|
|
|
ppal = EngAllocMem(FL_ZERO_MEMORY, sizeof(PALETTEENTRY) * 256, 'zzzG');
|
|
if (ppal == NULL)
|
|
goto ReturnFalse;
|
|
|
|
pgdev->pPal = ppal;
|
|
|
|
// Create handle for palette.
|
|
|
|
hpal = EngCreatePalette(PAL_INDEXED, 256, (ULONG*) ppal, 0, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI((pgdev->iBitmapFormat == BMF_16BPP) ||
|
|
(pgdev->iBitmapFormat == BMF_24BPP) ||
|
|
(pgdev->iBitmapFormat == BMF_32BPP),
|
|
"This case handles only 16, 24 or 32bpp");
|
|
|
|
hpal = EngCreatePalette(PAL_BITFIELDS, 0, NULL,
|
|
pgdev->flRed, pgdev->flGreen, pgdev->flBlue);
|
|
}
|
|
|
|
pgdev->hpalDefault = hpal;
|
|
pdi->hpalDefault = hpal;
|
|
|
|
if (hpal == 0)
|
|
goto ReturnFalse;
|
|
|
|
return(TRUE);
|
|
|
|
ReturnFalse:
|
|
|
|
WARNING("Failed bInitializePalette");
|
|
return(FALSE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vGpsUninitializePalette
|
|
*
|
|
* Frees resources allocated by bInitializePalette.
|
|
*
|
|
* Note: In an error case, this may be called before bInitializePalette.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vGpsUninitializePalette(GDEV* gpdev)
|
|
{
|
|
// Delete the default palette if we created one:
|
|
|
|
if (gpdev->hpalDefault != 0)
|
|
EngDeletePalette(gpdev->hpalDefault);
|
|
|
|
if (gpdev->pPal != (PALETTEENTRY*) NULL)
|
|
EngFreeMem(gpdev->pPal);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GpsDisablePDEV
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID GpsDisablePDEV(
|
|
DHPDEV dhpdev)
|
|
{
|
|
GDEV* pgdev;
|
|
|
|
pgdev = (GDEV*) dhpdev;
|
|
|
|
vGpsUninitializePalette(pgdev);
|
|
|
|
vGpsUninitializeDirectDraw(pgdev);
|
|
|
|
VFREEMEM(pgdev);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DHPDEV GpsEnablePDEV
|
|
*
|
|
\**************************************************************************/
|
|
|
|
DHPDEV GpsEnablePDEV(
|
|
DEVMODEW* pdm,
|
|
PWSTR pwszLogAddr,
|
|
ULONG cPat,
|
|
HSURF* phsurfPatterns,
|
|
ULONG cjCaps,
|
|
ULONG* pdevcaps,
|
|
ULONG cjDevInfo,
|
|
DEVINFO* pdi,
|
|
HDEV hdev,
|
|
PWSTR pwszDeviceName,
|
|
HANDLE hDriver)
|
|
{
|
|
GDEV* pgdev;
|
|
HWND hwnd;
|
|
ULONG BitsPerPlane;
|
|
ULONG RedMask;
|
|
ULONG GreenMask;
|
|
ULONG BlueMask;
|
|
ULONG ScreenWidth;
|
|
ULONG ScreenHeight;
|
|
|
|
pgdev = PALLOCMEM(sizeof(GDEV), 'zzzG');
|
|
if (pgdev == NULL)
|
|
{
|
|
goto ReturnFailure0;
|
|
}
|
|
|
|
hwnd = (HWND) pdm;
|
|
|
|
if (!bGpsInitializeDirectDraw(pgdev, hwnd, &ScreenWidth, &ScreenHeight,
|
|
&BitsPerPlane, &RedMask, &GreenMask,
|
|
&BlueMask))
|
|
{
|
|
goto ReturnFailure0;
|
|
}
|
|
|
|
if (!bGpsInitializeModeFields(pgdev, &ScreenWidth, &ScreenHeight,
|
|
&BitsPerPlane, &RedMask, &GreenMask,
|
|
&BlueMask, (GDIINFO*) pdevcaps, pdi))
|
|
{
|
|
goto ReturnFailure0;
|
|
}
|
|
|
|
if (!bGpsInitializePalette(pgdev, pdi))
|
|
{
|
|
goto ReturnFailure1;
|
|
}
|
|
|
|
return((DHPDEV) pgdev);
|
|
|
|
ReturnFailure1:
|
|
GpsDisablePDEV((DHPDEV) pgdev);
|
|
|
|
ReturnFailure0:
|
|
return(0);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID GpsCompletePDEV
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID GpsCompletePDEV(
|
|
DHPDEV dhpdev,
|
|
HDEV hdev)
|
|
{
|
|
((GDEV*) dhpdev)->hdev = hdev;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID GpsDisableSurface
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID GpsDisableSurface(
|
|
DHPDEV dhpdev)
|
|
{
|
|
GDEV* pgdev;
|
|
|
|
pgdev = (GDEV*) dhpdev;
|
|
|
|
EngDeleteSurface(pgdev->hsurfScreen);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* HSURF GpsEnableSurface
|
|
*
|
|
\**************************************************************************/
|
|
|
|
HSURF GpsEnableSurface(
|
|
DHPDEV dhpdev)
|
|
{
|
|
HSURF hsurf;
|
|
GDEV* pgdev;
|
|
|
|
pgdev = (GDEV*) dhpdev;
|
|
|
|
hsurf = EngCreateDeviceSurface(NULL, pgdev->sizlScreen, pgdev->iBitmapFormat);
|
|
if (hsurf == 0)
|
|
{
|
|
goto ReturnFailure;
|
|
}
|
|
|
|
// Associate surface with a physical device now
|
|
|
|
if (!EngAssociateSurface(hsurf, pgdev->hdev, HOOK_BITBLT
|
|
| HOOK_COPYBITS
|
|
| HOOK_STROKEPATH
|
|
| HOOK_TEXTOUT))
|
|
{
|
|
goto ReturnFailure;
|
|
}
|
|
|
|
pgdev->hsurfScreen = hsurf; // Remember it for clean-up
|
|
|
|
return(hsurf);
|
|
|
|
ReturnFailure:
|
|
GpsDisableSurface((DHPDEV) pgdev);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vGpsWindowOffset
|
|
*
|
|
* Hack function to account for the window offset.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vGpsWindowOffset(
|
|
GDEV* pgdev,
|
|
RECTL* prcl,
|
|
RECT* prc)
|
|
{
|
|
RECT rcWindow;
|
|
|
|
GetWindowRect(pgdev->hwnd, &rcWindow);
|
|
|
|
prc->left = rcWindow.left + prcl->left;
|
|
prc->right = rcWindow.left + prcl->right;
|
|
prc->top = rcWindow.top + prcl->top;
|
|
prc->bottom = rcWindow.top + prcl->bottom;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL GpsCopyBits
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL GpsCopyBits(
|
|
SURFOBJ *psoDst,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDst,
|
|
POINTL *pptlSrc)
|
|
{
|
|
GDEV* pgdev;
|
|
RECTL rclSrc;
|
|
HRESULT hr;
|
|
RECT rcWindow;
|
|
RECT rcSrc;
|
|
|
|
rclSrc.left = pptlSrc->x;
|
|
rclSrc.top = pptlSrc->y;
|
|
rclSrc.right = pptlSrc->x + (prclDst->right - prclDst->left);
|
|
rclSrc.bottom = pptlSrc->y + (prclDst->bottom - prclDst->top);
|
|
|
|
if (psoSrc->dhpdev == NULL)
|
|
{
|
|
// DIB-to-screen:
|
|
|
|
pgdev = (GDEV*) psoDst->dhpdev;
|
|
|
|
vGpsWindowOffset(pgdev, prclDst, &rcWindow);
|
|
|
|
if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
|
|
{
|
|
// Read in a copy of the destination bits in order to handle
|
|
// complex clipping because we're going to write everything
|
|
// back out:
|
|
|
|
Repeat1:
|
|
|
|
hr = pgdev->lpDDBuffer->lpVtbl->Blt(pgdev->lpDDBuffer,
|
|
(RECT*) prclDst,
|
|
pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
|
|
if (hr == DDERR_SURFACELOST)
|
|
{
|
|
DbgPrint("Lost!\n");
|
|
pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary);
|
|
goto Repeat1;
|
|
}
|
|
}
|
|
|
|
EngCopyBits(pgdev->psoBuffer, psoSrc, pco, pxlo, prclDst, pptlSrc);
|
|
|
|
Repeat2:
|
|
|
|
hr = pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
pgdev->lpDDBuffer,
|
|
(RECT*) prclDst,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
|
|
if (hr == DDERR_SURFACELOST)
|
|
{
|
|
DbgPrint("Lost2\n");
|
|
pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary);
|
|
goto Repeat2;
|
|
}
|
|
}
|
|
else if (psoDst->dhpdev == NULL)
|
|
{
|
|
// Screen-to-DIB:
|
|
|
|
pgdev = (GDEV*) psoSrc->dhpdev;
|
|
|
|
vGpsWindowOffset(pgdev, &rclSrc, &rcWindow);
|
|
|
|
pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDBuffer,
|
|
(RECT*) &rclSrc,
|
|
pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
|
|
EngCopyBits(psoDst, pgdev->psoBuffer, pco, pxlo, prclDst, pptlSrc);
|
|
}
|
|
else
|
|
{
|
|
// Screen-to-screen:
|
|
|
|
pgdev = (GDEV*) psoDst->dhpdev;
|
|
|
|
vGpsWindowOffset(pgdev, prclDst, &rcWindow);
|
|
vGpsWindowOffset(pgdev, &rclSrc, &rcSrc);
|
|
|
|
pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
pgdev->lpDDPrimary,
|
|
&rcSrc,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL GpsBitBlt
|
|
*
|
|
* An 's' is appended to this function name so that we don't conflict
|
|
* with 'GpsBitBlt' exported from gdiplus.dll.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL GpsBitBlt(
|
|
SURFOBJ* psoDst,
|
|
SURFOBJ* psoSrc,
|
|
SURFOBJ* psoMsk,
|
|
CLIPOBJ* pco,
|
|
XLATEOBJ* pxlo,
|
|
RECTL* prclDst,
|
|
POINTL* pptlSrc,
|
|
POINTL* pptlMsk,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ROP4 rop4)
|
|
{
|
|
GDEV* pgdev;
|
|
HRESULT hr;
|
|
RECT rcWindow;
|
|
|
|
if (psoSrc == NULL)
|
|
{
|
|
// Patblt to screen:
|
|
|
|
pgdev = (GDEV*) psoDst->dhpdev;
|
|
|
|
vGpsWindowOffset(pgdev, prclDst, &rcWindow);
|
|
|
|
if ((pco != NULL) && (pco->iDComplexity != DC_TRIVIAL))
|
|
{
|
|
// Read in a copy of the destination bits in order to handle
|
|
// complex clipping because we're going to write everything
|
|
// back out:
|
|
|
|
Repeat1:
|
|
|
|
hr = pgdev->lpDDBuffer->lpVtbl->Blt(pgdev->lpDDBuffer,
|
|
(RECT*) prclDst,
|
|
pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
|
|
if (hr == DDERR_SURFACELOST)
|
|
{
|
|
DbgPrint("Lost!\n");
|
|
pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary);
|
|
goto Repeat1;
|
|
}
|
|
}
|
|
|
|
EngBitBlt(pgdev->psoBuffer, psoSrc, psoMsk, pco, pxlo, prclDst,
|
|
pptlSrc, pptlMsk, pbo, pptlBrush, rop4);
|
|
|
|
Repeat2:
|
|
|
|
hr = pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
pgdev->lpDDBuffer,
|
|
(RECT*) prclDst,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
|
|
if (hr == DDERR_SURFACELOST)
|
|
{
|
|
DbgPrint("Lost2\n");
|
|
pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary);
|
|
goto Repeat2;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
return(EngBitBlt(psoDst, psoSrc, psoMsk, pco, pxlo, prclDst, pptlSrc,
|
|
pptlMsk, pbo, pptlBrush, rop4));
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL GpsStrokePath
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL GpsStrokePath(
|
|
SURFOBJ* pso,
|
|
PATHOBJ* ppo,
|
|
CLIPOBJ* pco,
|
|
XFORMOBJ* pxlo,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
LINEATTRS* pla,
|
|
MIX mix)
|
|
{
|
|
GDEV* pgdev;
|
|
HRESULT hr;
|
|
RECT rcWindow;
|
|
|
|
Repeat1:
|
|
|
|
pgdev = (GDEV*) pso->dhpdev;
|
|
|
|
vGpsWindowOffset(pgdev, &pco->rclBounds, &rcWindow);
|
|
|
|
hr = pgdev->lpDDBuffer->lpVtbl->Blt(pgdev->lpDDBuffer,
|
|
(RECT*) &pco->rclBounds,
|
|
pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
|
|
if (hr == DDERR_SURFACELOST)
|
|
{
|
|
DbgPrint("Lost!\n");
|
|
pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary);
|
|
goto Repeat1;
|
|
}
|
|
|
|
EngStrokePath(pgdev->psoBuffer, ppo, pco, pxlo, pbo, pptlBrush,
|
|
pla, mix);
|
|
|
|
hr = pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
pgdev->lpDDBuffer,
|
|
(RECT*) &pco->rclBounds,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL GpsTextOut
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL GpsTextOut(
|
|
SURFOBJ* pso,
|
|
STROBJ* pstro,
|
|
FONTOBJ* pfo,
|
|
CLIPOBJ* pco,
|
|
RECTL* prclExtra,
|
|
RECTL* prclOpaque,
|
|
BRUSHOBJ* pboFore,
|
|
BRUSHOBJ* pboOpaque,
|
|
POINTL* pptlOrg,
|
|
MIX mix)
|
|
{
|
|
GDEV* pgdev;
|
|
HRESULT hr;
|
|
RECT rcWindow;
|
|
RECTL* prclDraw;
|
|
|
|
Repeat1:
|
|
|
|
pgdev = (GDEV*) pso->dhpdev;
|
|
|
|
prclDraw = (prclOpaque != NULL) ? prclOpaque : &pstro->rclBkGround;
|
|
|
|
vGpsWindowOffset(pgdev, prclDraw, &rcWindow);
|
|
|
|
hr = pgdev->lpDDBuffer->lpVtbl->Blt(pgdev->lpDDBuffer,
|
|
(RECT*) prclDraw,
|
|
pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
|
|
if (hr == DDERR_SURFACELOST)
|
|
{
|
|
DbgPrint("Lost!\n");
|
|
pgdev->lpDDPrimary->lpVtbl->Restore(pgdev->lpDDPrimary);
|
|
goto Repeat1;
|
|
}
|
|
|
|
EngTextOut(pgdev->psoBuffer, pstro, pfo, pco, prclExtra, prclOpaque,
|
|
pboFore, pboOpaque, pptlOrg, mix);
|
|
|
|
hr = pgdev->lpDDPrimary->lpVtbl->Blt(pgdev->lpDDPrimary,
|
|
&rcWindow,
|
|
pgdev->lpDDBuffer,
|
|
(RECT*) prclDraw,
|
|
DDBLT_WAIT,
|
|
NULL);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Structure****************************\
|
|
* DFVFN gadrvfnGdiPlus[]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
DRVFN gadrvfnGdiPlus[] = {
|
|
{ INDEX_DrvEnablePDEV, (PFN) GpsEnablePDEV },
|
|
{ INDEX_DrvCompletePDEV, (PFN) GpsCompletePDEV },
|
|
{ INDEX_DrvDisablePDEV, (PFN) GpsDisablePDEV },
|
|
{ INDEX_DrvEnableSurface, (PFN) GpsEnableSurface },
|
|
{ INDEX_DrvDisableSurface, (PFN) GpsDisableSurface },
|
|
{ INDEX_DrvCopyBits, (PFN) GpsCopyBits },
|
|
{ INDEX_DrvBitBlt, (PFN) GpsBitBlt },
|
|
{ INDEX_DrvStrokePath, (PFN) GpsStrokePath },
|
|
{ INDEX_DrvTextOut, (PFN) GpsTextOut },
|
|
};
|
|
|
|
ULONG gcdrvfnGdiPlus = sizeof(gadrvfnGdiPlus) / sizeof(DRVFN);
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL GpsEnableDriver
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL GpsEnableDriver(
|
|
ULONG iEngineVersion,
|
|
ULONG cj,
|
|
DRVENABLEDATA* pded)
|
|
{
|
|
pded->pdrvfn = gadrvfnGdiPlus;
|
|
pded->c = gcdrvfnGdiPlus;
|
|
pded->iDriverVersion = DDI_DRIVER_VERSION;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|