677 lines
22 KiB
C
677 lines
22 KiB
C
|
/******************************Module*Header*******************************\
|
||
|
*
|
||
|
* *******************
|
||
|
* * GDI SAMPLE CODE *
|
||
|
* *******************
|
||
|
*
|
||
|
* Module Name: heap.c
|
||
|
*
|
||
|
* This module contains the routines for an off-screen video heap manager.
|
||
|
* It is used primarily for allocating space for device-format-bitmaps in
|
||
|
* off-screen memory.
|
||
|
*
|
||
|
* Off-screen bitmaps are a big deal on NT because:
|
||
|
*
|
||
|
* 1) It reduces the working set. Any bitmap stored in off-screen
|
||
|
* memory is a bitmap that isn't taking up space in main memory.
|
||
|
*
|
||
|
* 2) There is a speed win by using the accelerator hardware for
|
||
|
* drawing, in place of NT's GDI code. NT's GDI is written entirely
|
||
|
* in 'C++' and perhaps isn't as fast as it could be.
|
||
|
*
|
||
|
* 3) It raises your Winbench score.
|
||
|
*
|
||
|
* Copyright (c) 1993-1998 Microsoft Corporation
|
||
|
\**************************************************************************/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* DSURF* pVidMemAllocate
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
DSURF* pVidMemAllocate(
|
||
|
PDEV* ppdev,
|
||
|
LONG cx,
|
||
|
LONG cy)
|
||
|
{
|
||
|
ULONG iHeap;
|
||
|
VIDEOMEMORY* pvmHeap;
|
||
|
FLATPTR fpVidMem;
|
||
|
DSURF* pdsurf;
|
||
|
LONG lDelta;
|
||
|
SURFACEALIGNMENT Alignment;
|
||
|
|
||
|
memset(&Alignment, 0, sizeof(Alignment));
|
||
|
|
||
|
// Ensure quadword x-alignment in video memory:
|
||
|
|
||
|
Alignment.Rectangular.dwXAlignment = 8;
|
||
|
Alignment.Rectangular.dwFlags |= SURFACEALIGN_DISCARDABLE;
|
||
|
|
||
|
for (iHeap = 0; iHeap < ppdev->cHeaps; iHeap++)
|
||
|
{
|
||
|
pvmHeap = &ppdev->pvmList[iHeap];
|
||
|
|
||
|
// AGP memory could be potentially used for device-bitmaps, with
|
||
|
// two very large caveats:
|
||
|
//
|
||
|
// 1. No kernel-mode view is made for the AGP memory (would take
|
||
|
// up too many PTEs and too much virtual address space).
|
||
|
// No user-mode view is made either unless a DirectDraw
|
||
|
// application happens to be running. Consequently, neither
|
||
|
// GDI nor the driver can use the CPU to directly access the
|
||
|
// bits. (It can be done through the accelerator, however.)
|
||
|
//
|
||
|
// 2. AGP heaps never shrink their committed allocations. The
|
||
|
// only time AGP memory gets de-committed is when the entire
|
||
|
// heap is empty. And don't forget that committed AGP memory
|
||
|
// is non-pageable. Consequently, if you were to enable a
|
||
|
// 50 MB AGP heap for DirectDraw, and were sharing that heap
|
||
|
// for device bitmap allocations, after running a D3D game
|
||
|
// the system would never be able to free that 50 MB of non-
|
||
|
// pageable memory until every single device bitmap was deleted!
|
||
|
// Just watch your Winstone scores plummet if someone plays
|
||
|
// a D3D game first.
|
||
|
|
||
|
if (!(pvmHeap->dwFlags & VIDMEM_ISNONLOCAL))
|
||
|
{
|
||
|
fpVidMem = HeapVidMemAllocAligned(pvmHeap,
|
||
|
cx * ppdev->cjPelSize,
|
||
|
cy,
|
||
|
&Alignment,
|
||
|
&lDelta);
|
||
|
if (fpVidMem != 0)
|
||
|
{
|
||
|
pdsurf = EngAllocMem(FL_ZERO_MEMORY, sizeof(DSURF), ALLOC_TAG);
|
||
|
if (pdsurf != NULL)
|
||
|
{
|
||
|
pdsurf->dt = 0;
|
||
|
pdsurf->ppdev = ppdev;
|
||
|
pdsurf->x = (LONG)(fpVidMem % ppdev->lDelta)
|
||
|
/ ppdev->cjPelSize;
|
||
|
pdsurf->y = (LONG)(fpVidMem / ppdev->lDelta);
|
||
|
pdsurf->cx = cx;
|
||
|
pdsurf->cy = cy;
|
||
|
pdsurf->fpVidMem = fpVidMem;
|
||
|
pdsurf->pvmHeap = pvmHeap;
|
||
|
|
||
|
return(pdsurf);
|
||
|
}
|
||
|
|
||
|
VidMemFree(pvmHeap->lpHeap, fpVidMem);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vVidMemFree
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vVidMemFree(
|
||
|
DSURF* pdsurf)
|
||
|
{
|
||
|
DSURF* pTmp;
|
||
|
|
||
|
if (pdsurf == NULL)
|
||
|
return;
|
||
|
|
||
|
if (!(pdsurf->dt & DT_DIRECTDRAW))
|
||
|
{
|
||
|
if (pdsurf->dt & DT_DIB)
|
||
|
{
|
||
|
EngFreeMem(pdsurf->pvScan0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Update the uniqueness to show that space has been freed, so
|
||
|
// that we may decide to see if some DIBs can be moved back into
|
||
|
// off-screen memory:
|
||
|
|
||
|
pdsurf->ppdev->iHeapUniq++;
|
||
|
|
||
|
VidMemFree(pdsurf->pvmHeap->lpHeap, pdsurf->fpVidMem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EngFreeMem(pdsurf);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* BOOL bMoveOldestOffscreenDfbToDib
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
BOOL bMoveOldestOffscreenDfbToDib(
|
||
|
PDEV* ppdev)
|
||
|
{
|
||
|
DSURF* pdsurf;
|
||
|
LONG lDelta;
|
||
|
VOID* pvScan0;
|
||
|
RECTL rclDst;
|
||
|
POINTL ptlSrc;
|
||
|
SURFOBJ soTmp;
|
||
|
|
||
|
pdsurf = ppdev->pdsurfDiscardableList;
|
||
|
if (pdsurf != NULL)
|
||
|
{
|
||
|
// Make the system-memory scans quadword aligned:
|
||
|
|
||
|
lDelta = (pdsurf->cx * ppdev->cjPelSize + 7) & ~7;
|
||
|
|
||
|
// Note that there's no point in zero-initializing this memory:
|
||
|
|
||
|
pvScan0 = EngAllocMem(0, lDelta * pdsurf->cy, ALLOC_TAG);
|
||
|
|
||
|
if (pvScan0 != NULL)
|
||
|
{
|
||
|
// The following 'EngModifySurface' call tells GDI to
|
||
|
// modify the surface to point to system-memory for
|
||
|
// the bits, and changes what Drv calls we want to
|
||
|
// hook for the surface.
|
||
|
//
|
||
|
// By specifying the surface address, GDI will convert the
|
||
|
// surface to an STYPE_BITMAP surface (if necessary) and
|
||
|
// point the bits to the memory we just allocated. The
|
||
|
// next time we see it in a DrvBitBlt call, the 'dhsurf'
|
||
|
// field will still point to our 'pdsurf' structure.
|
||
|
//
|
||
|
// Note that we hook only CopyBits and BitBlt when we
|
||
|
// convert the device-bitmap to a system-memory surface.
|
||
|
// This is so that we don't have to worry about getting
|
||
|
// DrvTextOut, DrvLineTo, etc. calls on bitmaps that
|
||
|
// we've converted to system-memory -- GDI will just
|
||
|
// automatically do the drawing for us.
|
||
|
//
|
||
|
// However, we are still interested in seeing DrvCopyBits
|
||
|
// and DrvBitBlt calls involving this surface, because
|
||
|
// in those calls we take the opportunity to see if it's
|
||
|
// worth putting the device-bitmap back into video memory
|
||
|
// (if some room has been freed up).
|
||
|
|
||
|
if (EngModifySurface(pdsurf->hsurf,
|
||
|
ppdev->hdevEng,
|
||
|
HOOK_COPYBITS | HOOK_BITBLT,
|
||
|
0, // It's system-memory
|
||
|
(DHSURF) pdsurf,
|
||
|
pvScan0,
|
||
|
lDelta,
|
||
|
NULL))
|
||
|
{
|
||
|
// First, copy the bits from off-screen memory to the DIB:
|
||
|
|
||
|
rclDst.left = 0;
|
||
|
rclDst.top = 0;
|
||
|
rclDst.right = pdsurf->cx;
|
||
|
rclDst.bottom = pdsurf->cy;
|
||
|
|
||
|
|
||
|
ptlSrc.x = pdsurf->x;
|
||
|
ptlSrc.y = pdsurf->y;
|
||
|
|
||
|
soTmp.lDelta = lDelta;
|
||
|
soTmp.pvScan0 = pvScan0;
|
||
|
|
||
|
vGetBits(ppdev, &soTmp, &rclDst, &ptlSrc);
|
||
|
|
||
|
// Now free the off-screen memory:
|
||
|
|
||
|
VidMemFree(pdsurf->pvmHeap->lpHeap, pdsurf->fpVidMem);
|
||
|
|
||
|
// Remove this node from the discardable list:
|
||
|
|
||
|
ASSERTDD(ppdev->pdsurfDiscardableList == pdsurf,
|
||
|
"Expected node to be head of the list");
|
||
|
|
||
|
ppdev->pdsurfDiscardableList = pdsurf->pdsurfDiscardableNext;
|
||
|
|
||
|
pdsurf->pdsurfDiscardableNext = NULL;
|
||
|
pdsurf->dt = DT_DIB;
|
||
|
pdsurf->pvScan0 = pvScan0;
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
EngFreeMem(pvScan0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* BOOL bMoveEverythingFromOffscreenToDibs
|
||
|
*
|
||
|
* This function is used when we're about to enter full-screen mode, which
|
||
|
* would wipe all our off-screen bitmaps. GDI can ask us to draw on
|
||
|
* device bitmaps even when we're in full-screen mode, and we do NOT have
|
||
|
* the option of stalling the call until we switch out of full-screen.
|
||
|
* We have no choice but to move all the off-screen DFBs to DIBs.
|
||
|
*
|
||
|
* Returns TRUE if all DSURFs have been successfully moved.
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
BOOL bMoveAllDfbsFromOffscreenToDibs(
|
||
|
PDEV* ppdev)
|
||
|
{
|
||
|
do {} while (bMoveOldestOffscreenDfbToDib(ppdev));
|
||
|
|
||
|
return(ppdev->pdsurfDiscardableList == NULL);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* BOOL bMoveDibToOffscreenDfbIfRoom
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
BOOL bMoveDibToOffscreenDfbIfRoom(
|
||
|
PDEV* ppdev,
|
||
|
DSURF* psurf)
|
||
|
{
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* HBITMAP DrvCreateDeviceBitmap
|
||
|
*
|
||
|
* Function called by GDI to create a device-format-bitmap (DFB). We will
|
||
|
* always try to allocate the bitmap in off-screen; if we can't, we simply
|
||
|
* fail the call and GDI will create and manage the bitmap itself.
|
||
|
*
|
||
|
* Note: We do not have to zero the bitmap bits. GDI will automatically
|
||
|
* call us via DrvBitBlt to zero the bits (which is a security
|
||
|
* consideration).
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
HBITMAP DrvCreateDeviceBitmap(
|
||
|
DHPDEV dhpdev,
|
||
|
SIZEL sizl,
|
||
|
ULONG iFormat)
|
||
|
{
|
||
|
PDEV* ppdev;
|
||
|
DSURF* pdsurf;
|
||
|
HBITMAP hbmDevice;
|
||
|
BYTE* pjSurface;
|
||
|
LONG lDelta;
|
||
|
FLONG flHooks;
|
||
|
DSURF* pTmp;
|
||
|
|
||
|
ppdev = (PDEV*) dhpdev;
|
||
|
|
||
|
// If we're in full-screen mode, we hardly have any off-screen memory
|
||
|
// in which to allocate a DFB.
|
||
|
|
||
|
if (!ppdev->bEnabled)
|
||
|
return(0);
|
||
|
|
||
|
// We only support device bitmaps that are the same colour depth
|
||
|
// as our display.
|
||
|
//
|
||
|
// Actually, those are the only kind GDI will ever call us with,
|
||
|
// but we may as well check. Note that this implies you'll never
|
||
|
// get a crack at 1bpp bitmaps.
|
||
|
// Note: we can't create a device bitmap when the color depth is 24
|
||
|
// BPP. Otherwise, we will have problem in vBankStart when we hack the
|
||
|
// pbnk->pso->pvScan0 = ppdev->pjScreen - cjOffset
|
||
|
// + yOffset * ppdev->lDelta
|
||
|
// + CONVERT_TO_BYTES(xOffset, ppdev);
|
||
|
// this pvScan0 is not guaranteed be DWORD aligned
|
||
|
|
||
|
if ( (iFormat != ppdev->iBitmapFormat)
|
||
|
||(iFormat == BMF_24BPP) )
|
||
|
return(0);
|
||
|
|
||
|
// We don't want anything 8x8 or smaller -- they're typically brush
|
||
|
// patterns which we don't particularly want to stash in off-screen
|
||
|
// memory.
|
||
|
//
|
||
|
// Note if you're tempted to extend this philosophy to surfaces
|
||
|
// larger than 8x8: in NT5, software cursors will use device-bitmaps
|
||
|
// when possible, which is a big win when they're in video-memory
|
||
|
// because we avoid the horrendous reads from video memory whenever
|
||
|
// the cursor has to be redrawn. But the problem is that these
|
||
|
// are small! (Typically 16x16 to 32x32.)
|
||
|
|
||
|
if ((sizl.cx <= 8) && (sizl.cy <= 8))
|
||
|
return(0);
|
||
|
|
||
|
do {
|
||
|
pdsurf = pVidMemAllocate(ppdev, sizl.cx, sizl.cy);
|
||
|
if (pdsurf != NULL)
|
||
|
{
|
||
|
hbmDevice = EngCreateDeviceBitmap((DHSURF) pdsurf, sizl, iFormat);
|
||
|
if (hbmDevice != NULL)
|
||
|
{
|
||
|
// If we're running on a card that can map all of off-screen
|
||
|
// video-memory, give a pointer to the bits to GDI so that
|
||
|
// it can draw directly on the bits when it wants to.
|
||
|
//
|
||
|
// Note that this requires that we hook DrvSynchronize and
|
||
|
// set HOOK_SYNCHRONIZE.
|
||
|
|
||
|
if ((ppdev->flCaps & CAPS_NEW_MMIO) &&
|
||
|
!(ppdev->flCaps & CAPS_NO_DIRECT_ACCESS))
|
||
|
{
|
||
|
pjSurface = pdsurf->fpVidMem + ppdev->pjScreen;
|
||
|
lDelta = ppdev->lDelta;
|
||
|
flHooks = ppdev->flHooks | HOOK_SYNCHRONIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pjSurface = NULL;
|
||
|
lDelta = 0;
|
||
|
flHooks = ppdev->flHooks;
|
||
|
}
|
||
|
|
||
|
if (EngModifySurface((HSURF) hbmDevice,
|
||
|
ppdev->hdevEng,
|
||
|
flHooks,
|
||
|
MS_NOTSYSTEMMEMORY, // It's video-memory
|
||
|
(DHSURF) pdsurf,
|
||
|
pjSurface,
|
||
|
lDelta,
|
||
|
NULL))
|
||
|
{
|
||
|
pdsurf->hsurf = (HSURF) hbmDevice;
|
||
|
|
||
|
// Add this to the tail of the discardable surface list:
|
||
|
|
||
|
if (ppdev->pdsurfDiscardableList == NULL)
|
||
|
ppdev->pdsurfDiscardableList = pdsurf;
|
||
|
else
|
||
|
{
|
||
|
for (pTmp = ppdev->pdsurfDiscardableList;
|
||
|
pTmp->pdsurfDiscardableNext != NULL;
|
||
|
pTmp = pTmp->pdsurfDiscardableNext)
|
||
|
;
|
||
|
|
||
|
pTmp->pdsurfDiscardableNext = pdsurf;
|
||
|
}
|
||
|
|
||
|
return(hbmDevice);
|
||
|
}
|
||
|
|
||
|
EngDeleteSurface((HSURF) hbmDevice);
|
||
|
}
|
||
|
|
||
|
vVidMemFree(pdsurf);
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
} while (bMoveOldestOffscreenDfbToDib(ppdev));
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* HBITMAP DrvDeriveSurface
|
||
|
*
|
||
|
* This function is new to NT5, and allows the driver to accelerate any
|
||
|
* GDI drawing to a DirectDraw surface.
|
||
|
*
|
||
|
* Note the similarity of this function to DrvCreateDeviceBitmap.
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
HBITMAP DrvDeriveSurface(
|
||
|
DD_DIRECTDRAW_GLOBAL* lpDirectDraw,
|
||
|
DD_SURFACE_LOCAL* lpLocal)
|
||
|
{
|
||
|
PDEV* ppdev;
|
||
|
DSURF* pdsurf;
|
||
|
HBITMAP hbmDevice;
|
||
|
DD_SURFACE_GLOBAL* lpSurface;
|
||
|
SIZEL sizl;
|
||
|
|
||
|
ppdev = (PDEV*) lpDirectDraw->dhpdev;
|
||
|
|
||
|
lpSurface = lpLocal->lpGbl;
|
||
|
|
||
|
// GDI should never call us for a non-RGB surface, but let's assert just
|
||
|
// to make sure they're doing their job properly.
|
||
|
|
||
|
ASSERTDD(!(lpSurface->ddpfSurface.dwFlags & DDPF_FOURCC),
|
||
|
"GDI called us with a non-RGB surface!");
|
||
|
|
||
|
// The rest of our driver expects GDI calls to come in with the same
|
||
|
// format as the primary surface. So we'd better not wrap a device
|
||
|
// bitmap around an RGB format that the rest of our driver doesn't
|
||
|
// understand. Also, we must check to see that it is not a surface
|
||
|
// whose pitch does not match the primary surface.
|
||
|
|
||
|
// NOTE: Most surfaces created by this driver are allocated as 2D surfaces
|
||
|
// whose lPitch's are equal to the screen pitch. However, overlay surfaces
|
||
|
// are allocated such that there lPitch's are usually different then the
|
||
|
// screen pitch. The hardware can not accelerate drawing operations to
|
||
|
// these surfaces and thus we fail to derive these surfaces.
|
||
|
|
||
|
|
||
|
if (lpSurface->ddpfSurface.dwRGBBitCount == (DWORD) ppdev->cjPelSize * 8 &&
|
||
|
lpSurface->lPitch == ppdev->lDelta)
|
||
|
{
|
||
|
pdsurf = EngAllocMem(FL_ZERO_MEMORY, sizeof(DSURF), ALLOC_TAG);
|
||
|
if (pdsurf != NULL)
|
||
|
{
|
||
|
sizl.cx = lpSurface->wWidth;
|
||
|
sizl.cy = lpSurface->wHeight;
|
||
|
|
||
|
hbmDevice = EngCreateDeviceBitmap((DHSURF) pdsurf,
|
||
|
sizl,
|
||
|
ppdev->iBitmapFormat);
|
||
|
if (hbmDevice != NULL)
|
||
|
{
|
||
|
// Note that HOOK_SYNCHRONIZE must always be hooked when
|
||
|
// we give GDI a pointer to the bitmap bits.
|
||
|
|
||
|
if (EngModifySurface((HSURF) hbmDevice,
|
||
|
ppdev->hdevEng,
|
||
|
ppdev->flHooks | HOOK_SYNCHRONIZE,
|
||
|
MS_NOTSYSTEMMEMORY, // It's video-memory
|
||
|
(DHSURF) pdsurf,
|
||
|
ppdev->pjScreen + lpSurface->fpVidMem,
|
||
|
lpSurface->lPitch,
|
||
|
NULL))
|
||
|
{
|
||
|
pdsurf->dt = DT_DIRECTDRAW;
|
||
|
pdsurf->ppdev = ppdev;
|
||
|
pdsurf->x = lpSurface->xHint;
|
||
|
pdsurf->y = lpSurface->yHint;
|
||
|
pdsurf->cx = lpSurface->wWidth;
|
||
|
pdsurf->cy = lpSurface->wHeight;
|
||
|
pdsurf->fpVidMem = lpSurface->fpVidMem;
|
||
|
|
||
|
return(hbmDevice);
|
||
|
}
|
||
|
|
||
|
EngDeleteSurface((HSURF) hbmDevice);
|
||
|
}
|
||
|
|
||
|
EngFreeMem(pdsurf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID DrvDeleteDeviceBitmap
|
||
|
*
|
||
|
* Deletes a DFB.
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID DrvDeleteDeviceBitmap(
|
||
|
DHSURF dhsurf)
|
||
|
{
|
||
|
DSURF* pdsurf;
|
||
|
PDEV* ppdev;
|
||
|
DSURF* pTmp;
|
||
|
|
||
|
pdsurf = (DSURF*) dhsurf;
|
||
|
|
||
|
ppdev = pdsurf->ppdev;
|
||
|
|
||
|
if ((pdsurf->dt & (DT_DIB | DT_DIRECTDRAW)) == 0)
|
||
|
{
|
||
|
// It's a surface stashed in video memory, so we have to remove
|
||
|
// it from the discardable surface list:
|
||
|
|
||
|
if (ppdev->pdsurfDiscardableList == pdsurf)
|
||
|
ppdev->pdsurfDiscardableList = pdsurf->pdsurfDiscardableNext;
|
||
|
else
|
||
|
{
|
||
|
for (pTmp = ppdev->pdsurfDiscardableList;
|
||
|
pTmp->pdsurfDiscardableNext != pdsurf;
|
||
|
pTmp = pTmp->pdsurfDiscardableNext)
|
||
|
;
|
||
|
|
||
|
pTmp->pdsurfDiscardableNext = pdsurf->pdsurfDiscardableNext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vVidMemFree(pdsurf);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* BOOL bAssertModeOffscreenHeap
|
||
|
*
|
||
|
* This function is called whenever we switch in or out of full-screen
|
||
|
* mode. We have to convert all the off-screen bitmaps to DIBs when
|
||
|
* we switch to full-screen (because we may be asked to draw on them even
|
||
|
* when in full-screen, and the mode switch would probably nuke the video
|
||
|
* memory contents anyway).
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
BOOL bAssertModeOffscreenHeap(
|
||
|
PDEV* ppdev,
|
||
|
BOOL bEnable)
|
||
|
{
|
||
|
BOOL b;
|
||
|
|
||
|
b = TRUE;
|
||
|
|
||
|
if (!bEnable)
|
||
|
{
|
||
|
b = bMoveAllDfbsFromOffscreenToDibs(ppdev);
|
||
|
}
|
||
|
|
||
|
return(b);
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* VOID vDisableOffscreenHeap
|
||
|
*
|
||
|
* Frees any resources allocated by the off-screen heap.
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
VOID vDisableOffscreenHeap(
|
||
|
PDEV* ppdev)
|
||
|
{
|
||
|
SURFOBJ* psoPunt;
|
||
|
HSURF hsurf;
|
||
|
|
||
|
psoPunt = ppdev->psoPunt;
|
||
|
if (psoPunt != NULL)
|
||
|
{
|
||
|
hsurf = psoPunt->hsurf;
|
||
|
EngUnlockSurface(psoPunt);
|
||
|
EngDeleteSurface(hsurf);
|
||
|
}
|
||
|
|
||
|
psoPunt = ppdev->psoPunt2;
|
||
|
if (psoPunt != NULL)
|
||
|
{
|
||
|
hsurf = psoPunt->hsurf;
|
||
|
EngUnlockSurface(psoPunt);
|
||
|
EngDeleteSurface(hsurf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* BOOL bEnableOffscreenHeap
|
||
|
*
|
||
|
* Initializes the off-screen heap using all available video memory,
|
||
|
* accounting for the portion taken by the visible screen.
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
BOOL bEnableOffscreenHeap(
|
||
|
PDEV* ppdev)
|
||
|
{
|
||
|
SIZEL sizl;
|
||
|
HSURF hsurf;
|
||
|
|
||
|
// Allocate a 'punt' SURFOBJ we'll use when the device-bitmap is in
|
||
|
// off-screen memory, but we want GDI to draw to it directly as an
|
||
|
// engine-managed surface:
|
||
|
|
||
|
sizl.cx = ppdev->cxMemory;
|
||
|
sizl.cy = ppdev->cyMemory;
|
||
|
|
||
|
// We want to create it with exactly the same hooks and capabilities
|
||
|
// as our primary surface. We will override the 'lDelta' and 'pvScan0'
|
||
|
// fields later:
|
||
|
|
||
|
hsurf = (HSURF) EngCreateBitmap(sizl,
|
||
|
0xbadf00d,
|
||
|
ppdev->iBitmapFormat,
|
||
|
BMF_TOPDOWN,
|
||
|
(VOID*) 0xbadf00d);
|
||
|
|
||
|
// We don't want GDI to turn around and call any of our Drv drawing
|
||
|
// functions when drawing to these surfaces, so always set the hooks
|
||
|
// to '0':
|
||
|
|
||
|
if ((hsurf == 0) ||
|
||
|
(!EngAssociateSurface(hsurf, ppdev->hdevEng, 0)) ||
|
||
|
(!(ppdev->psoPunt = EngLockSurface(hsurf))))
|
||
|
{
|
||
|
DISPDBG((1, "Failed punt surface creation"));
|
||
|
|
||
|
EngDeleteSurface(hsurf);
|
||
|
goto ReturnFalse;
|
||
|
}
|
||
|
|
||
|
// We don't want GDI to turn around and call any of our Drv drawing
|
||
|
// functions when drawing to these surfaces, so always set the hooks
|
||
|
// to '0':
|
||
|
|
||
|
hsurf = (HSURF) EngCreateBitmap(sizl,
|
||
|
0xbadf00d,
|
||
|
ppdev->iBitmapFormat,
|
||
|
BMF_TOPDOWN,
|
||
|
(VOID*) 0xbadf00d);
|
||
|
|
||
|
// We don't want GDI to call us back when drawing to these surfaces,
|
||
|
// so always set the hooks to '0':
|
||
|
|
||
|
if ((hsurf == 0) ||
|
||
|
(!EngAssociateSurface(hsurf, ppdev->hdevEng, 0)) ||
|
||
|
(!(ppdev->psoPunt2 = EngLockSurface(hsurf))))
|
||
|
{
|
||
|
DISPDBG((1, "Failed punt surface creation"));
|
||
|
|
||
|
EngDeleteSurface(hsurf);
|
||
|
goto ReturnFalse;
|
||
|
}
|
||
|
|
||
|
DISPDBG((5, "Passed bEnableOffscreenHeap"));
|
||
|
|
||
|
return(TRUE);
|
||
|
|
||
|
ReturnFalse:
|
||
|
|
||
|
DISPDBG((1, "Failed bEnableOffscreenHeap"));
|
||
|
|
||
|
return(FALSE);
|
||
|
}
|