Leaked source code of windows server 2003
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

/******************************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);
}