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.
 
 
 
 
 
 

2081 lines
67 KiB

/******************************************************************************
* Module Name: BITBLT.c
* Author: Noel VanHook
* Purpose: Handle calls to DrvBitBlt
*
* Copyright (c) 1995,1996 Cirrus Logic, Inc.
*
* $Log: X:/log/laguna/nt35/displays/cl546x/BITBLT.C $
*
* Rev 1.45 Mar 04 1998 15:11:56 frido
* Added new shadow macros.
*
* Rev 1.44 Feb 24 1998 13:24:40 frido
* Removed some warning messages for NT 5.0 build.
*
* Rev 1.43 Jan 22 1998 18:15:58 frido
* Revised the pattern blit filter for Access again.
*
* Rev 1.42 Jan 21 1998 17:33:56 frido
* Revised the 24-bpp filter for Access & Excel.
*
* Rev 1.41 Jan 20 1998 11:43:56 frido
* Added a filter for 24-bpp PatBlt.
*
* Rev 1.40 Nov 03 1997 11:35:48 frido
* Added REQUIRE macros.
*
* Rev 1.39 18 Aug 1997 09:24:04 FRIDO
*
* Changed all SWAT5 labels into MEMMGR (I forgot that during the merge).
* Added dynamic bitmap filter, borrowed from Windows 95.
*
* Rev 1.38 29 May 1997 10:59:24 noelv
*
* Frido's fix for 9773
* SWAT:
* SWAT: Rev 1.12 29 May 1997 12:12:20 frido
* SWAT: Changed striping code from 16-bit to 32-bit.
* SWAT:
* SWAT: Rev 1.10 09 May 1997 12:57:30 frido
* SWAT: Added support for new memory manager.
*
* Rev 1.37 29 Apr 1997 16:28:12 noelv
*
* Merged in new SWAT code.
* SWAT:
* SWAT: Rev 1.9 24 Apr 1997 11:45:54 frido
* SWAT: NT140b09 merge.
* SWAT: Revised comments.
* SWAT:
* SWAT: Rev 1.8 19 Apr 1997 16:42:30 frido
* SWAT: Added SWAT.h include file.
* SWAT:
* SWAT: Rev 1.7 18 Apr 1997 00:14:58 frido
* SWAT: NT140b07 merge.
* SWAT:
* SWAT: Rev 1.6 15 Apr 1997 19:13:34 frido
* SWAT: Added SWAT6: striping in PatBlt.
* SWAT:
* SWAT: Rev 1.5 14 Apr 1997 15:30:12 frido
* SWAT: Enabled SWAT5 (new bitmap allocation scheme).
* SWAT:
* SWAT: Rev 1.4 10 Apr 1997 17:37:12 frido
* SWAT: Started work on SWAT5 optimizations.
* SWAT:
* SWAT: Rev 1.3 09 Apr 1997 20:24:18 frido
* SWAT: Revised SWAT1 once again.
* SWAT:
* SWAT: Rev 1.2 09 Apr 1997 17:36:48 frido
* SWAT: Changed SWAT1 pre-allocation scheme.
* SWAT: Added SWAT1 and SWAT2 switches.
* SWAT:
* SWAT: Rev 1.1 07 Apr 1997 17:48:06 frido
* SWAT: SWAT1: Added heap pre-allocation during WB97 pause.
*
* Rev 1.36 08 Apr 1997 11:52:46 einkauf
*
* add SYNC_W_3D to coordination MCD and 2D hw access
*
* Rev 1.35 21 Mar 1997 10:52:58 noelv
* Combined do_flag and sw_test_flag together into 'pointer_switch'.
*
* Rev 1.34 04 Feb 1997 10:34:18 SueS
* Added support for hardware clipping for the 5465.
*
* Rev 1.33 23 Jan 1997 11:03:18 noelv
*
* PuntBitBlt now handles device bitmaps stored on the host.
* bCreateScreenFromDIB now checks the return code from host to screen operati
*
* Rev 1.32 17 Dec 1996 16:57:04 SueS
* Reject bitmaps of 32x64 or smaller. This is based on WinBench97
* optimization. Reject bitmaps that are larger than the visible screen
* width. Added some things to log file writes.
*
* Rev 1.31 27 Nov 1996 11:32:46 noelv
* Disabled Magic Bitmap. Yeah!!!
*
* Rev 1.30 26 Nov 1996 10:48:40 SueS
* Changed WriteLogFile parameters for buffering.
*
* Rev 1.29 13 Nov 1996 17:05:12 SueS
* Changed WriteFile calls to WriteLogFile.
*
* Rev 1.28 07 Nov 1996 16:07:08 bennyn
*
* Added no offscn mem allocation if DD enabled
*
* Rev 1.27 18 Sep 1996 13:49:04 noelv
* Opps. Forgot to unhook STROKEANDFILLPATH.
*
* Rev 1.26 12 Sep 1996 09:18:42 noelv
* Fixed bug in infinite offscreen memory.
*
* Rev 1.25 06 Sep 1996 09:03:54 noelv
*
* Cleaned up NULL driver code.
*
* Rev 1.24 20 Aug 1996 11:03:10 noelv
* Bugfix release from Frido 8-19-96
*
* Rev 1.3 18 Aug 1996 22:48:42 frido
* #lineto - Added DrvLineTo.
*
* Rev 1.2 17 Aug 1996 19:35:36 frido
* Cleaned source.
* Changed ScreenToMemory bitblt.
*
* Rev 1.1 15 Aug 1996 11:45:32 frido
* Added precompiled header.
*
* Rev 1.0 14 Aug 1996 17:16:14 frido
* Initial revision.
*
* Rev 1.23 07 Aug 1996 09:04:00 noelv
* Sync before punting.
*
* Rev 1.22 11 Jul 1996 15:52:30 bennyn
* Changed constant 400 and 90 to #define variables
*
* Rev 1.21 04 Jun 1996 15:56:32 noelv
* Debug code.
*
* Rev 1.20 28 May 1996 15:11:02 noelv
* Updated data logging.
*
* Rev 1.19 16 May 1996 15:05:54 bennyn
* Added PIXEL_ALIGN to allocoffscnmem()
*
* Rev 1.18 16 May 1996 14:54:10 noelv
* Added logging code.
*
* Rev 1.17 08 May 1996 17:02:46 noelv
*
* Preallocate device bitmap
*
* Rev 1.16 03 May 1996 14:41:42 noelv
* Modified device bitmap allocation scheme.
*
* Rev 1.15 01 May 1996 10:57:28 bennyn
*
* Modified for NT4.0
*
* Rev 1.14 29 Apr 1996 14:16:20 noelv
* Clean up.
*
* Rev 1.13 10 Apr 1996 14:13:52 NOELV
* Frido release 27
*
* Rev 1.22 08 Apr 1996 16:47:44 frido
* Added PuntBitBlt.
*
* Rev 1.21 27 Mar 1996 13:06:58 frido
* Added check for destination in ROP.
* Masked color expansions.
* Added return value to clipping routine.
*
* Rev 1.20 25 Mar 1996 11:52:30 frido
* Bellevue 102B03.
*
* Rev 1.9 20 Mar 1996 14:17:30 bennyn
*
* Rev 1.8 18 Mar 1996 11:42:30 noelv
* Added data loggin stuff. Code cleanup.
*
* Rev 1.7 13 Mar 1996 13:21:04 noelv
* Cleanup, documentation, and data logging.
*
* Rev 1.6 12 Mar 1996 15:43:36 noelv
* Added data logging.
* Cleanup.
*
* Rev 1.5 12 Mar 1996 11:17:48 noelv
* Code cleanup
*
* Rev 1.4 08 Mar 1996 11:08:50 noelv
* Code cleanup and comments
*
* Rev 1.3 05 Mar 1996 11:57:28 noelv
* Frido version 19
*
* Rev 1.15 04 Mar 1996 20:21:44 frido
* Removed check for monochrome source and brush.
*
* Rev 1.14 01 Mar 1996 17:47:58 frido
* Added check for destination in BLTDEF.
*
* Rev 1.13 29 Feb 1996 20:17:32 frido
* Added test for special size device bitmaps.
* Check for bEnable in CreateScreenFromDib.
*
* Rev 1.12 28 Feb 1996 22:37:12 frido
* Added Optimize.h.
* Added check for brushes with monochrome source.
*
* Rev 1.11 27 Feb 1996 16:38:04 frido
* Added device bitmap store/restore.
*
* Rev 1.10 26 Feb 1996 23:37:32 frido
* Fixed several bugs.
*
* Rev 1.9 24 Feb 1996 01:25:12 frido
* Added device bitmaps.
* Removed old BitBlt code.
*
* Rev 1.8 10 Feb 1996 21:39:28 frido
* Used SetBrush again for PatternBLT.
*
* Rev 1.7 08 Feb 1996 00:19:50 frido
* Changed the interpretation of cache_slot.
*
* Rev 1.6 05 Feb 1996 17:35:58 frido
* Added translation cache.
*
* Rev 1.5 03 Feb 1996 13:58:28 frido
* Use the compile switch "-Dfrido=0" to disable my extensions.
*
* Rev 1.4 31 Jan 1996 12:57:50 frido
* Called EngBitBlt in case of error.
* Changed clipping algorithmns.
*
* Rev 1.3 25 Jan 1996 22:46:10 frido
* Removed bug in complex clipping.
*
* Rev 1.2 25 Jan 1996 22:07:54 frido
* Speeded up the pattern blit.
*
\**************************************************************************/
#include "precomp.h"
#include "SWAT.h" // SWAT optimizations.
#define BITBLT_DBG_LEVEL 1
#define CLIP_DBG_LEVEL 1
#define BITMAP_DBG_LEVEL 1
#define PUNT_DBG_LEVEL 1
#define P 1
#define S 2
#define D 4
#define PS (P|S)
#define DP (P|D)
#define DPS (P|D|S)
#define DS (S|D)
//
// Table with ROP flags.
//
BYTE ropFlags[256] =
{
0, DPS, DPS, PS, DPS, DP, DPS, DPS, DPS, DPS, DP, DPS, PS, DPS, DPS, P,
DPS, DS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS,
DPS, DPS, DS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS,
PS, DPS, DPS, S, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, PS, DPS, DPS, PS,
DPS, DPS, DPS, DPS, DS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS,
DP, DPS, DPS, DPS, DPS, D, DPS, DPS, DPS, DPS, DP, DPS, DPS, DPS, DPS, DP,
DPS, DPS, DPS, DPS, DPS, DPS, DS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS,
DPS, DPS, DPS, DPS, DPS, DPS, DPS, DS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS,
DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DS, DPS, DPS, DPS, DPS, DPS, DPS, DPS,
DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DS, DPS, DPS, DPS, DPS, DPS, DPS,
DP, DPS, DPS, DPS, DPS, DP, DPS, DPS, DPS, DPS, D, DPS, DPS, DPS, DPS, DP,
DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DS, DPS, DPS, DPS, DPS,
PS, DPS, DPS, PS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, S, DPS, DPS, PS,
DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DS, DPS, DPS,
DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DPS, DS, DPS,
P, DPS, DPS, PS, DPS, DP, DPS, DPS, DPS, DPS, DP, DPS, PS, DPS, DPS, 0
};
extern void HostifyAllBitmaps(PPDEV ppdev);
COPYFN DoDeviceToDevice;
BOOL CopyDeviceBitmap(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF,
COPYFN *pfn);
BOOL PuntBitBlt(
SURFOBJ* psoDest,
SURFOBJ* psoSrc,
SURFOBJ* psoMask,
CLIPOBJ* pco,
XLATEOBJ* pxlo,
RECTL* prclDest,
POINTL* pptlSrc,
POINTL* pptlMask,
BRUSHOBJ* pbo,
POINTL* pptlBrush,
ROP4 rop4);
#if SWAT6
void StripePatBlt(
PPDEV ppdev,
ULONG x,
ULONG y,
ULONG cx,
ULONG cy);
#endif
//
// If data logging is enabled, Prototype the logging files.
//
#if LOG_CALLS
void LogBitBlt(
int acc,
SURFOBJ* psoSrc,
SURFOBJ* psoDest,
ROP4 rop4,
CLIPOBJ* pco,
BRUSHOBJ* pbo,
XLATEOBJ* pxlo);
void LogDrvCreateDevBmp(
int acc,
PPDEV ppdev,
SIZEL sizl,
PDSURF pdsurf);
void LogDrvDeleteDevBmp(
PDSURF pdsurf);
void LogCreateDibFromScreen(
int acc,
PPDEV ppdev,
PDSURF pdsurf);
void LogCreateScreenFromDib(
int acc,
PPDEV ppdev,
PDSURF pdsurf);
//
// If data logging is not enabled, compile out the calls.
//
#else
#define LogBitBlt(acc, psoSrc, psoDest, rop4, pco, pbo, pxlo)
#define LogDrvCreateDevBmp(acc, ppdev, sizl, pdsurf)
#define LogDrvDeleteDevBmp(pdsurf)
#define LogCreateDibFromScreen(acc, ppdev, pdsurf)
#define LogCreateScreenFromDib(acc, ppdev, pdsurf)
#endif
/****************************************************************************\
* bIntersectTest *
* Test for intersection between two rectangles. *
\****************************************************************************/
#define bIntersectTest(prcl1, prcl2) \
(((prcl1)->left < (prcl2)->right) && \
((prcl1)->right > (prcl2)->left) && \
((prcl1)->top < (prcl2)->bottom) && \
((prcl1)->bottom > (prcl2)->top))
/*****************************************************************************\
* BOOL DrvBitBlt *
\*****************************************************************************/
#if (USE_ASM && defined(i386))
BOOL i386BitBlt(
#else
BOOL DrvBitBlt(
#endif
SURFOBJ* psoDest,
SURFOBJ* psoSrc,
SURFOBJ* psoMask,
CLIPOBJ* pco,
XLATEOBJ* pxlo,
RECTL* prclDest,
POINTL* pptlSrc,
POINTL* pptlMask,
BRUSHOBJ* pbo,
POINTL* pptlBrush,
ROP4 rop4)
{
PPDEV ppdev;
ULONG fg_rop, bg_rop;
ULONG bltdef = 0;
BOOL fSrc, fDest;
#if NULL_BITBLT
{
if (pointer_switch) return(TRUE);
}
#endif
DISPDBG((BITBLT_DBG_LEVEL, "DrvBitBlt: Entry.\n"));
ASSERTMSG(psoDest != NULL, "DrvBitBlt: No destination.\n");
//
// Get the PDEV associated with the destination.
//
ppdev = (PPDEV) ((psoDest != NULL) ? psoDest->dhpdev :
((psoSrc != NULL) ? psoSrc->dhpdev : NULL));
// Bad PDEV?
if (ppdev == NULL) goto GoToEngine;
SYNC_W_3D(ppdev);
//
// Set a flag to tell us if the source is the frame buffer.
//
fSrc = (psoSrc != NULL) && // Is there a source?
((psoSrc->iType == STYPE_DEVBITMAP) || // Is it a device bmp?
(psoSrc->hsurf == ppdev->hsurfEng) ); // Is it the screen?
//
// Set a flag telling us if the destination is the frame buffer.
//
fDest = (psoDest != NULL) && // Is there a dest?
((psoDest->iType == STYPE_DEVBITMAP) || // Is it a device bmp?
(psoDest->hsurf == ppdev->hsurfEng) ); // Is it the screen?
//
// If the destination is a DIB device bitmap, try copying it into
// off-screen memory.
//
if ( fDest && // If dest is supposed to be
// the frame buffer,
(psoDest->iType == STYPE_DEVBITMAP) && // and it's a device bitmap,
((PDSURF)psoDest->dhsurf)->pso ) // but it's really on the host,
{
// try to copy it back into off screen memory.
if ( !bCreateScreenFromDib(ppdev, (DSURF*) psoDest->dhsurf) )
{
// If that fails, then the destination is now on the host.
psoDest = ((PDSURF)psoDest->dhsurf)->pso; // Host surface.
fDest = FALSE; // Dest is not frame buffer.
}
}
//
// If the source is a DIB device bitmap, try copying it into off-screen
// memory.
//
if ( fSrc && // If the source is supposed to
// be the frame buffer,
(psoSrc->iType == STYPE_DEVBITMAP) && // and it's a device bmp,
((PDSURF)psoSrc->dhsurf)->pso ) // but it's really on the host,
{
// try to copy it back into off-screen memory.
if ( !bCreateScreenFromDib(ppdev, (DSURF*) psoSrc->dhsurf) )
{
// If that fails, then our source is really the host.
psoSrc = ((PDSURF)psoSrc->dhsurf)->pso; // Host surface.
fSrc = FALSE; // Src is not frame buffer.
}
}
if ( fDest )
{
BYTE bROP;
if (psoDest->iType == STYPE_DEVBITMAP)
ppdev->ptlOffset = ((PDSURF)psoDest->dhsurf)->ptl;
else
ppdev->ptlOffset.x = ppdev->ptlOffset.y = 0;
//
// Extract the foreground and background ROP from the ROP4
//
ASSERTMSG( (rop4>>16) == 0, "DrvBitBlt: Upper word in ROP4 non-zero. \n");
fg_rop = rop4 & 0x000000FF;
bg_rop = (rop4>>8) & 0x000000FF;
// Punt all true 4 op rops.
// If fg_rop != bg_rop, then this is a true 4 op rop, so punt it.
// If fg_rop == bg_rop, then it's really a three op rop.
if ((fg_rop != bg_rop)) // It's a three op rop,
goto GoToEngine;
bROP = ropFlags[fg_rop];
#if !(USE_ASM && defined(i386))
{
if (!(bROP & S))
{
// It is a PatBLT. This is very important, so all calls to the
// support routines are stretched into linear code, except for
// the caching of the brushes, which should happen only once
// for each brush.
ULONG drawbltdef = 0x10000000 | fg_rop;
if (bROP & D)
drawbltdef |= 0x01000000;
// Do we have a pttern to load?
if (bROP & P)
{
ULONG color = pbo->iSolidColor;
if (color != (ULONG) -1)
{
// We have a solid color.
switch (ppdev->ulBitCount)
{
case 8:
color = (color << 8) | (color & 0xFF);
case 16:
color = (color << 16) | (color & 0xFFFF);
}
drawbltdef |= 0x00070000;
REQUIRE(2);
LL_BGCOLOR(color, 2);
}
else
{
if (!SetBrush(ppdev, &bltdef, pbo, pptlBrush))
goto GoToEngine;
drawbltdef |= bltdef << 16;
}
}
// Test for no clipping.
if ( (pco == NULL) || (pco->iDComplexity == DC_TRIVIAL) )
{
#if SWAT6
REQUIRE(2);
LL_DRAWBLTDEF(drawbltdef, 2);
StripePatBlt(ppdev, prclDest->left + ppdev->ptlOffset.x,
prclDest->top + ppdev->ptlOffset.y,
prclDest->right - prclDest->left,
prclDest->bottom - prclDest->top);
#else
REQUIRE(7);
LL_DRAWBLTDEF(drawbltdef, 0);
LL_OP0(prclDest->left + ppdev->ptlOffset.x,
prclDest->top + ppdev->ptlOffset.y);
LL_BLTEXT(prclDest->right - prclDest->left,
prclDest->bottom - prclDest->top);
#endif
}
// Test for rectangle clipping.
else if (pco->iDComplexity == DC_RECT)
{
LONG x, y, cx, cy;
x = max(prclDest->left, pco->rclBounds.left);
y = max(prclDest->top, pco->rclBounds.top);
cx = min(prclDest->right, pco->rclBounds.right) - x;
cy = min(prclDest->bottom, pco->rclBounds.bottom) - y;
if ( (cx > 0) && (cy > 0) )
{
#if SWAT6
REQUIRE(2);
LL_DRAWBLTDEF(drawbltdef, 2);
StripePatBlt(ppdev, x + ppdev->ptlOffset.x,
y + ppdev->ptlOffset.y, cx, cy);
#else
REQUIRE(7);
LL_DRAWBLTDEF(drawbltdef, 0);
LL_OP0(x + ppdev->ptlOffset.x, y + ppdev->ptlOffset.y);
LL_BLTEXT(cx, cy);
#endif
}
}
// Complex clipping.
else
{
BOOL bMore;
ENUMRECTS8 ce;
RECTL* prcl;
#if DRIVER_5465 && HW_CLIPPING
// Get a chunk of rectangles.
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
// Enable clipping
REQUIRE(6);
LL_DRAWBLTDEF(drawbltdef | DD_CLIPEN, 0);
LL_CLIPULE(prclDest->left + ppdev->ptlOffset.x,
prclDest->top + ppdev->ptlOffset.y);
LL_CLIPLOR(prclDest->right + ppdev->ptlOffset.x,
prclDest->bottom + ppdev->ptlOffset.y);
do
{
bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG *) &ce);
for (prcl = ce.arcl; ce.c--; prcl++)
{
if ((prcl->right > prcl->left) &&
(prcl->bottom > prcl->top))
{
#if SWAT6
StripePatBlt(ppdev,
prcl->left + ppdev->ptlOffset.x,
prcl->top + ppdev->ptlOffset.y,
prcl->right - prcl->left,
prcl->bottom - prcl->top);
#else
REQUIRE(5);
LL_OP0(prcl->left + ppdev->ptlOffset.x,
prcl->top + ppdev->ptlOffset.y);
LL_BLTEXT(prcl->right - prcl->left,
prcl->bottom - prcl->top);
#endif
}
}
} while (bMore);
#else
REQUIRE(2);
LL_DRAWBLTDEF(drawbltdef, 2);
// Get a chunk of rectangles.
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
do
{
bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG *) &ce);
for (prcl = ce.arcl; ce.c--; prcl++)
{
LONG x, y, cx, cy;
x = max(prclDest->left, prcl->left);
y = max(prclDest->top, prcl->top);
cx = min(prclDest->right, prcl->right) - x;
cy = min(prclDest->bottom, prcl->bottom) - y;
if ( (cx > 0) && (cy > 0) )
{
#if SWAT6
StripePatBlt(ppdev, x + ppdev->ptlOffset.x,
y + ppdev->ptlOffset.y, cx, cy);
#else
REQUIRE(5);
LL_OP0(x + ppdev->ptlOffset.x,
y + ppdev->ptlOffset.y);
LL_BLTEXT(cx, cy);
#endif
}
}
}
while (bMore);
#endif
}
LogBitBlt(0, psoSrc, psoDest, rop4, pco, pbo, pxlo);
return(TRUE);
}
}
#endif // !(USE_ASM && defined(i386))
// We only support HostToScreen blits where the Host is either
// 1-bpp, 4-bpp, 8-bpp, or the same format as the screen.
if ( ((psoSrc->iBitmapFormat > BMF_8BPP) &&
(psoSrc->iBitmapFormat != psoDest->iBitmapFormat)) )
{
goto GoToEngine;
}
if (bROP & P)
{
// Realize the brush.
if (!SetBrush(ppdev, &bltdef, pbo, pptlBrush))
{
goto GoToEngine;
}
}
// If the destination is part of the ROP, set the bit.
if (bROP & D)
{
bltdef |= 0x0100;
}
// Do the blit.
if (CopyDeviceBitmap(psoDest, psoSrc, pco, pxlo, prclDest,
pptlSrc, (bltdef << 16) | fg_rop,
fSrc ? DoDeviceToDevice : ppdev->pfnHostToScreen))
{
LogBitBlt(0, psoSrc, psoDest, rop4, pco, pbo, pxlo);
return(TRUE);
}
} // fDest
else if (fSrc) // Destination is bitmap, source is screen or device bitmap.
{
if (psoSrc->iType == STYPE_DEVBITMAP)
{
ppdev->ptlOffset = ((PDSURF) psoSrc->dhsurf)->ptl;
}
else
{
ppdev->ptlOffset.x = ppdev->ptlOffset.y = 0;
}
#if S2H_USE_ENGINE
{
// ROP3?
fg_rop = (BYTE) rop4;
if (fg_rop == (rop4 >> 8))
{
BYTE bROP = ropFlags[fg_rop];
// We dont's support ROPs where the destination is part of.
if ( !(bROP & D) )
{
// If we need a brush, load it.
if (bROP & P)
{
if (!SetBrush(ppdev, &bltdef, pbo, pptlBrush))
{
goto GoToEngine;
}
}
// Now, call the routine through the clip manager.
if (CopyDeviceBitmap(psoDest, psoSrc, pco, pxlo,
prclDest, pptlSrc,
(bltdef << 16) | fg_rop,
ppdev->pfnScreenToHost))
{
LogBitBlt(0, psoSrc, psoDest, rop4, pco, pbo, pxlo);
return(TRUE);
}
}
}
}
#else
{
// We only support SRCCOPY.
if (rop4 == 0x0000CCCC)
{
// Now, call the routine through the clip manager.
if (CopyDeviceBitmap(psoDest, psoSrc, pco, pxlo, prclDest,
pptlSrc, 0x000000CC,
ppdev->pfnScreenToHost))
{
LogBitBlt(0, psoSrc, psoDest, rop4, pco, pbo, pxlo);
return(TRUE);
}
}
}
#endif
}
GoToEngine:
// BLT is too complex. Punt it to GDI.
DISPDBG((BITBLT_DBG_LEVEL, "DrvBitBlt: Exit (punt). ROP4 = 0x%02X%02X.\n",
bg_rop,fg_rop));
LogBitBlt(1, psoSrc, psoDest, rop4, pco, pbo, pxlo);
return PuntBitBlt(psoDest, psoSrc, psoMask, pco, pxlo, prclDest, pptlSrc,
pptlMask, pbo, pptlBrush, rop4);
}
/*****************************************************************************\
* DrvCreateDeviceBitmap
*
* This routine creates a device bitmap that is allocated off-screen.
*
* On entry: dhpdev Handle of PDEV structure.
* sizl Size of the device bitmap to create.
* iFormat Bitmap format of the device bitmap to create.
*
* Returns: We return the handle of a surface object that holds our device
* bitmap or 0 if there is an error.
\*****************************************************************************/
HBITMAP DrvCreateDeviceBitmap(
DHPDEV dhpdev,
SIZEL sizl,
ULONG iFormat
)
{
PPDEV ppdev = (PPDEV) dhpdev;
POFMHDL pofm;
HBITMAP hbmDevice;
PDSURF pdsurf;
FLONG flHooks = HOOK_SYNCHRONIZEACCESS | HOOK_TEXTOUT
| HOOK_BITBLT | HOOK_COPYBITS | HOOK_PAINT
| HOOK_STROKEPATH | HOOK_FILLPATH
#ifdef WINNT_VER40
| HOOK_LINETO
#endif
;
SYNC_W_3D(ppdev);
#if WINBENCH96
//
// We support only device bitmaps that WinBench is going to use. This
// to circumvent the limitations of the heap management when there is
// not so much video memory.
//
// Only support bitmaps with a width between 20 and 31, and bitmaps
// wider than 100.
if ( (sizl.cx < 20) || ((sizl.cx >= 32) && (sizl.cx < 100)) )
{
LogDrvCreateDevBmp(1, ppdev, sizl, NULL);
return(0);
}
#else
// We don't support anything under or equal to 8x8 (brushes) since
// these will only slow us down.
if ((sizl.cx <= 8) || (sizl.cy <= 8))
{
LogDrvCreateDevBmp(2, ppdev, sizl, NULL);
return(0);
}
#if MEMMGR
// New bitmap filter, borrowed from Windows 95.
if (ppdev->fBitmapFilter)
{
if (( (sizl.cx <= ppdev->szlBitmapMin.cx)
&& (sizl.cy <= ppdev->szlBitmapMin.cy)
)
|| (sizl.cx > ppdev->szlBitmapMax.cx)
|| (sizl.cy > ppdev->szlBitmapMax.cy)
)
{
LogDrvCreateDevBmp(8, ppdev, sizl, NULL);
DISPDBG((BITMAP_DBG_LEVEL, "DrvCreateDeviceBitmap - Rejected\n"));
return(0);
}
}
#else
// Reject any x<=32, or y<=64, for 16 or 24 bpp.
// Improves WinBench97 scores.
if ((iFormat == BMF_16BPP) || (iFormat == BMF_24BPP))
{
if ((sizl.cx <= 32) || (sizl.cy <= 64))
{
LogDrvCreateDevBmp(8, ppdev, sizl, NULL);
DISPDBG((BITMAP_DBG_LEVEL, "DrvCreateDeviceBitmap - Reject x<=32||y<=64\n"));
return(0);
}
}
#endif
#endif
// Reject if bigger than current screen size
if ((ULONG)sizl.cx > ppdev->cxScreen)
{
LogDrvCreateDevBmp(9, ppdev, sizl, NULL);
DISPDBG((BITMAP_DBG_LEVEL, "DrvCreateDeviceBitmap - Reject > cxScreen\n"));
return(0);
}
// If the hardware is not in graphics mode, don't create a device bitmap!
if (!ppdev->bEnable)
{
LogDrvCreateDevBmp(3, ppdev, sizl, NULL);
return(0);
}
// We don't support device bitmaps in any other mode than the hardware.
if (iFormat != ppdev->iBitmapFormat)
{
return(0);
}
#ifdef ALLOC_IN_CREATESURFACE
if (ppdev->bDirectDrawInUse)
return (0);
#endif
#if SWAT1
// Is this the very first device bitmap?
if (ppdev->fPreAllocate == FALSE)
{
// Setup step-down counter.
ppdev->fPreAllocate = TRUE;
ppdev->nPages = 10;
}
// Is this the WinBench 97 pause bitmap?
else if (sizl.cx == 300 && sizl.cy == 150)
{
if (ppdev->nPages == 0)
{
PVOID p;
// Allocate 8 full-screen pages from the heap.
#ifdef WINNT_VER40
p = MEM_ALLOC(FL_ZERO_MEMORY, 8 * ppdev->cxScreen *
ppdev->iBytesPerPixel * ppdev->cyScreen, ALLOC_TAG);
#else
p = MEM_ALLOC(LPTR, 8 * ppdev->cxScreen * ppdev->iBytesPerPixel *
ppdev->cyScreen);
#endif
// Free it again.
MEMORY_FREE(p);
}
else
{
// Decrement step-down counter.
ppdev->nPages--;
}
}
// Is this a full-screen device bitmap?
else if ( (ppdev->nPages == 0)
&& (sizl.cx == (LONG) ppdev->cxScreen)
&& (sizl.cy == (LONG) ppdev->cyScreen)
)
{
PVOID p;
// Allocate 8 full-screen pages from the heap.
#ifdef WINNT_VER40
p = MEM_ALLOC(FL_ZERO_MEMORY, 8 * ppdev->cxScreen *
ppdev->iBytesPerPixel * ppdev->cyScreen, ALLOC_TAG);
#else
p = MEM_ALLOC(LPTR, 8 * ppdev->cxScreen * ppdev->iBytesPerPixel *
ppdev->cyScreen);
#endif
// Free it again.
MEMORY_FREE(p);
}
#endif // SWAT1
#if SWAT2
// Is this a full-screen device bitmap?
if ( (sizl.cx == (LONG) ppdev->cxScreen)
&& (sizl.cy == (LONG) ppdev->cyScreen)
)
{
#if MEMMGR
// Hostify all device bitmaps.
extern void HostifyAllBitmaps(PPDEV ppdev);
HostifyAllBitmaps(ppdev);
#else
POFMHDL pofm, pofmNext;
// Hostify all current off-screen device bitmaps.
for (pofm = ppdev->OFM_UsedQ; pofm; pofm = pofmNext)
{
pofmNext = pofm->nexthdl;
if (pofm->pdsurf && pofm->pdsurf->pofm)
{
bCreateDibFromScreen(ppdev, pofm->pdsurf);
}
else if (pofm->alignflag & SAVESCREEN_FLAG)
{
FreeOffScnMem(ppdev, pofm);
}
}
#endif
}
#endif // SWAT2
//
// Allocate off-screen memory.
//
{
#if INFINITE_OFFSCREEN_MEM
//
// This is our "infinite offscreen memory" test. Here we always
// succeed in memory allocation. We do this by always allocating
// bitmaps at screen 0,0.
// It looks ugly, but we can use it to tell of our memory management
// is hurting our benchmark scores.
// This option is turned off for the retail version of the driver.
// 'pointer_switch' is turned on and off in POINTER.C by moving the pointer
// to a special place on the screen.
//
if (pointer_switch)
{
pofm = ppdev->ScrnHandle;
}
else
#endif // INFINITE_OFFSCREEN_MEM
{
#if WINBENCH96
//
// This is our Magic Bitmap.
// Winbench 96 allocates one special bitmap into which it does *lots*
// of drawing. If the allocation for this bitmap fails, our WinBench
// score will be poor. We ensure that this allocation succeeds
// by pre-allocating it at boot time.
//
// If the size of the requested bitmap matches our magic bitmap, we
// assume that Winbench is requesting it's special bitmap, and so we
// use the magic bitmap.
//
if ( (sizl.cx == MAGIC_SIZEX) && (sizl.cy == MAGIC_SIZEY) &&
ppdev->pofmMagic && !ppdev->bMagicUsed)
{
// If fits. Use pre-allocated bitmap.
DISPDBG((BITMAP_DBG_LEVEL,
"DrvCreateDeviceBitmap - Using the Magic Bitmap.\n"));
ppdev->bMagicUsed = 1;
pofm = ppdev->pofmMagic;
}
else
#endif
{
DISPDBG((BITMAP_DBG_LEVEL,
"DrvCreateDeviceBitmap - Allocating a %d x %d device bitmap.\n",
sizl.cx, sizl.cy));
#if MEMMGR
if (ppdev->fBitmapFilter)
{
pofm = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN, NULL);
if (pofm == NULL)
{
HostifyAllBitmaps(ppdev);
pofm = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN, NULL);
}
}
else if (sizl.cx <= ppdev->must_have_width)
{
pofm = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN | MUST_HAVE,
NULL);
}
else
#endif
pofm = AllocOffScnMem(ppdev, &sizl, PIXEL_AlIGN, NULL);
}
}
}
//
// If we got the offscreen memory we need, then let's do some work.
//
if (pofm != NULL)
{
// Allocate device bitmap structure.
#ifdef WINNT_VER40
pdsurf = MEM_ALLOC(FL_ZERO_MEMORY, sizeof(DSURF), ALLOC_TAG);
#else
pdsurf = MEM_ALLOC(LPTR, sizeof(DSURF));
#endif
if (pdsurf != NULL)
{
// Create the device bitmap object.
hbmDevice = EngCreateDeviceBitmap((DHSURF) pdsurf, sizl, iFormat);
if (hbmDevice != NULL)
{
// Associate the device bitmap with the surface.
if (EngAssociateSurface((HSURF) hbmDevice,
ppdev->hdevEng,
flHooks)
)
{
// Store a pointer to the surface.
{
#if INFINITE_OFFSCREEN_MEM
//
// If we're using screen(0,0) as a device bitmap
// then don't walk on ScrnHandle->pdsurf!
//
if (pofm != ppdev->ScrnHandle)
#endif
pofm->pdsurf = pdsurf;
}
// Initialize the device bitmap structure.
pdsurf->ppdev = ppdev;
pdsurf->pofm = pofm;
pdsurf->ptl.x = pofm->aligned_x / ppdev->iBytesPerPixel;
pdsurf->ptl.y = pofm->aligned_y;
pdsurf->packedXY = (pdsurf->ptl.y << 16) | pdsurf->ptl.x;
pdsurf->sizl = sizl;
LogDrvCreateDevBmp(0, ppdev, sizl, pdsurf);
return(hbmDevice);
}
else
{
LogDrvCreateDevBmp(4, ppdev, sizl, NULL);
}
// Delete the surface
EngDeleteSurface((HSURF) hbmDevice);
}
else
{
LogDrvCreateDevBmp(5, ppdev, sizl, NULL);
}
// Free the device bitmap structure.
MEMORY_FREE(pdsurf);
}
else
{
LogDrvCreateDevBmp(6, ppdev, sizl, NULL);
}
#if WINBENCH96
// Free the off-screen memory.
if (pofm == ppdev->pofmMagic)
{
// We were using the preallocated memory block. Don't free it,
// just mark it as unused.
ppdev->bMagicUsed = 0;
}
else
#endif
{
#if INFINITE_OFFSCREEN_MEM
// But don't free it if the device bitmap is at screen(0,0)...
if (pofm != ppdev->ScrnHandle)
#endif
FreeOffScnMem(ppdev, pofm);
}
}
else
{
LogDrvCreateDevBmp(7, ppdev, sizl, NULL);
}
return(0);
}
/*****************************************************************************\
* DrvDeleteDeviceBitmap
*
* This routine deletes a device bitmap and frees the off-screen memory.
*
* On entry: pdsurf Pointer to device bitmap to delete.
\*****************************************************************************/
void DrvDeleteDeviceBitmap(DHSURF dhsurf)
{
PDSURF pdsurf = (PDSURF) dhsurf;
//
// Log this call to a file.
//
LogDrvDeleteDevBmp(pdsurf);
// Is the device bitmap stored in a DIB?
if (pdsurf->pso)
{
// Delete the in-memory DIB.
HSURF hsurfDib = pdsurf->pso->hsurf;
EngUnlockSurface(pdsurf->pso);
EngDeleteSurface(hsurfDib);
}
else
{
PPDEV ppdev = pdsurf->ppdev;
#if INFINITE_OFFSCREEN_MEM
//
// If we're using screen(0,0) as a device bitmap
// then don't walk on ScrnHandle->pdsurf!
//
if (pdsurf->pofm != ppdev->ScrnHandle)
#endif
pdsurf->pofm->pdsurf = NULL;
#if WINBENCH96
if ( pdsurf->pofm == ppdev->pofmMagic)
{
// We were using the preallocated chunk of memory. Don't free
// it, just mark it as unused.
ppdev->bMagicUsed = 0;
}
else
#endif
{
// Free the off-screen memory.
#if INFINITE_OFFSCREEN_MEM
// unless our device bitmap is at screen(0,0)...
if (pdsurf->pofm != ppdev->ScrnHandle)
#endif
FreeOffScnMem(pdsurf->ppdev, pdsurf->pofm);
}
}
// Free the device bitmap structure.
MEMORY_FREE(pdsurf);
}
/*****************************************************************************\
* bCreateDibFromScreen
*
* This routine copy a device bitmap into a DIB and frees the off-screen
* memory.
*
* On entry: ppdev Pointer to physical device.
* pdsurf Pointer to device bitmap to copy.
*
* Returns: TRUE if the off-screen device bitmap was sucessfully copied
* into a memory DIB.
\*****************************************************************************/
BOOL bCreateDibFromScreen(
PPDEV ppdev,
PDSURF pdsurf
)
{
HBITMAP hbmDib;
// Create a DIB.
hbmDib = EngCreateBitmap(pdsurf->sizl, 0, ppdev->iBitmapFormat,
BMF_TOPDOWN, NULL);
if (hbmDib)
{
// Associate the surface with the driver.
if (EngAssociateSurface((HSURF) hbmDib, ppdev->hdevEng, 0))
{
// Lock the surface.
SURFOBJ* pso = EngLockSurface((HSURF) hbmDib);
if (pso != NULL)
{
SIZEL sizl;
PBYTE pjScreen, pjBits;
// Calculate the size of the blit.
sizl.cx = pdsurf->sizl.cx * ppdev->iBytesPerPixel;
sizl.cy = pdsurf->sizl.cy;
// Calculate the destination variables.
pjBits = (PBYTE) pso->pvScan0;
// Calculate the screen address.
pjScreen = ppdev->pjScreen
+ (pdsurf->ptl.x * ppdev->iBytesPerPixel)
+ (pdsurf->ptl.y * ppdev->lDeltaScreen);
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
while (sizl.cy--)
{
// Copy all pixels from screen to memory.
memcpy(pjBits, pjScreen, sizl.cx);
// Next line.
pjScreen += ppdev->lDeltaScreen;
pjBits += pso->lDelta;
}
#if WINBENCH96
//
// If the block we are freeing is our preallocated
// piece, then invalidate it's pointer.
//
if ( pdsurf->pofm == ppdev->pofmMagic)
ppdev->pofmMagic = 0;
#endif
#if !MEMMGR
// Free the off-screen memory handle.
#if INFINITE_OFFSCREEN_MEM
// unless our device bitmap is at screen(0,0)...
if (pdsurf->pofm != ppdev->ScrnHandle)
#endif
FreeOffScnMem(pdsurf->ppdev, pdsurf->pofm);
#endif
// Mark the device bitmap as DIB.
pdsurf->pofm = NULL;
pdsurf->pso = pso;
// Done.
LogCreateDibFromScreen(0, ppdev, pdsurf);
return(TRUE);
}
else
{
// Failed to lock host surface
LogCreateDibFromScreen(1, ppdev, pdsurf);
}
}
else
{
// Failed to associate host surface
LogCreateDibFromScreen(2, ppdev, pdsurf);
}
// Delete the DIB.
EngDeleteSurface((HSURF) hbmDib);
}
else
{
// Failed to create host surface.
LogCreateDibFromScreen(3, ppdev, pdsurf);
}
// Error.
return(FALSE);
}
/*****************************************************************************\
* bCreateScreenFromDib
*
* This routine copys a DIB into a device bitmap and frees the DIB from memory.
*
* On entry: ppdev Pointer to physical device.
* pdsurf Pointer to device bitmap to copy.
*
* Returns: TRUE if the DIB was sucessfully copied into an off-screen
* device bitmap.
\*****************************************************************************/
BOOL bCreateScreenFromDib(
PPDEV ppdev,
PDSURF pdsurf
)
{
POFMHDL pofm;
HSURF hsurf;
SURFOBJ* pso;
#if MEMMGR
// In low memory situations, bitmaps will be hostified very frequently, so
// don't copy them back to the off-screen...
if (ppdev->fBitmapFilter)
{
return FALSE;
}
#endif
// If the hardware is not in graphics mode, keep the device bitmap in
// memory.
if (!ppdev->bEnable)
{
LogCreateScreenFromDib (1, ppdev, pdsurf);
return(FALSE);
}
#ifdef ALLOC_IN_CREATESURFACE
if (ppdev->bDirectDrawInUse)
return (FALSE);
#endif
// Allocate off-screen memory.
pofm = AllocOffScnMem(ppdev, &pdsurf->sizl, PIXEL_AlIGN, NULL);
if (pofm != NULL)
{
SURFOBJ psoDest;
RECTL rclDest;
POINTL ptlSrc;
//
// Tell the device bitmap where it lives in offscreen memory.
//
pdsurf->ptl.x = pofm->aligned_x / ppdev->iBytesPerPixel;
pdsurf->ptl.y = pofm->aligned_y;
pdsurf->packedXY = (pdsurf->ptl.y << 16) | pdsurf->ptl.x;
//
// Create a two way link between the device bitmap and
// its offscreen memory block.
//
pdsurf->pofm = pofm; // Attach offscreen memory block to device bitmap
pofm->pdsurf = pdsurf; // Attach device bitmap to offscreen memory block
//
// Disattach the host bitmap from the device bitmap.
// Save the pointer, because if we fail to move the device bitmap
// into the frame buffer, it will remain in host memory, and we
// will have to restore this pointer.
//
pso = pdsurf->pso; // Save pointer to bitmap in host memory.
pdsurf->pso = NULL; // disattach host memory
//
// Wrap the offscreen memory in a destination surface object.
// This is so we can use a host to screen BLT to move the bitmap
// from the host to the offscreen memory.
//
psoDest.dhsurf = (DHSURF) pdsurf;
psoDest.iType = STYPE_DEVBITMAP;
//
// Build a destination rectangle that describes where to put the
// bitmap in offscreen memory. This rectangle is relative to
// upper left corner of the allocated block of offscreen memory.
//
rclDest.left = 0;
rclDest.top = 0;
rclDest.right = pdsurf->sizl.cx;
rclDest.bottom = pdsurf->sizl.cy;
//
// Build a source point.
// Since we're moving the entire bitmap, its (0,0).
//
ptlSrc.x = ptlSrc.y = 0;
//
// Use our host to screen code to copy the DIB into off-screen memory.
//
if (!ppdev->pfnHostToScreen(&psoDest, pso, NULL, &rclDest, &ptlSrc,
0x000000CC))
{
//
// BLT engine couldn't put it back into off screen memory.
// Maybe the DIB engine can.
//
DISPDBG (( 0, "Couldn't BLT device bitmap back into framebuffer.\n"));
if (! PuntBitBlt(&psoDest, pso, NULL, NULL, NULL,
&rclDest, &ptlSrc, NULL, NULL, NULL, 0x0000CCCC))
{
// Nope! We can't move it back to the frame buffer.
DISPDBG (( 0, "Couldn't punt device bitmap back into framebuffer.\n"));
DISPDBG (( 0, "Device bitmap will remain in offscreen memory.\n"));
// Restore the surface object pointers.
pdsurf->pofm = NULL; // This device bitmap has no offscreen memory.
pdsurf->pso = pso; // This device bitmap lives here, on the host.
// Free the offscreen memory we allocated and fail.
FreeOffScnMem(ppdev, pofm);
return FALSE;
}
}
// Delete the DIB.
hsurf = pso->hsurf;
EngUnlockSurface(pso);
EngDeleteSurface(hsurf);
// Done.
LogCreateScreenFromDib (0, ppdev, pdsurf);
return(TRUE);
}
// Error.
LogCreateScreenFromDib (2, ppdev, pdsurf);
return(FALSE);
}
#if LOG_CALLS
// ============================================================================
//
// Everything from here down is for data logging and is not used in the
// production driver.
//
// ============================================================================
extern long lg_i;
extern char lg_buf[256];
// ****************************************************************************
//
// LogBitBlt()
// This routine is called only from DrvBitBlt()
// Dump information to a file about what is going on in BitBlt land.
//
// ****************************************************************************
void LogBitBlt(
int acc,
SURFOBJ* psoSrc,
SURFOBJ* psoDest,
ROP4 rop4,
CLIPOBJ* pco,
BRUSHOBJ* pbo,
XLATEOBJ* pxlo)
{
PPDEV dppdev,sppdev,ppdev;
BYTE fg_rop, bg_rop;
ULONG iDComplexity;
dppdev = (PPDEV) (psoDest ? psoDest->dhpdev : 0);
sppdev = (PPDEV) (psoSrc ? psoSrc->dhpdev : 0);
ppdev = dppdev ? dppdev : sppdev;
#if ENABLE_LOG_SWITCH
if (pointer_switch == 0) return;
#endif
lg_i = sprintf(lg_buf,"DBB: ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
if (acc)
{
lg_i = sprintf(lg_buf,"PNT ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
fg_rop = (BYTE) (rop4 & 0xff);
bg_rop = (BYTE) ((rop4>>8) & 0xff);
//
// Check the SRC
//
if ( (ropFlags[fg_rop] & S) &&
(psoSrc))
{
if (psoSrc->iType == STYPE_DEVBITMAP)
{
lg_i = sprintf(lg_buf, "Src Id=%p ", psoSrc->dhsurf);
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
if ( ((PDSURF)psoSrc->dhsurf)->pso )
lg_i = sprintf(lg_buf,"S=DH ");
else
lg_i = sprintf(lg_buf,"S=DF ");
}
else if (psoSrc->hsurf == ppdev->hsurfEng)
lg_i = sprintf(lg_buf,"S=S ");
else
lg_i = sprintf(lg_buf,"S=H ");
}
else
lg_i = sprintf(lg_buf,"S=N ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
//
// Check the DEST
//
if (psoDest)
{
if (psoDest->iType == STYPE_DEVBITMAP)
{
lg_i = sprintf(lg_buf, "Dst Id=%p ", psoDest->dhsurf);
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
if ( ((PDSURF)psoDest->dhsurf)->pso )
lg_i = sprintf(lg_buf,"D=DH ");
else
lg_i = sprintf(lg_buf,"D=DF ");
}
else if (psoDest->hsurf == ppdev->hsurfEng)
lg_i = sprintf(lg_buf,"D=S ");
else
lg_i = sprintf(lg_buf,"D=H ");
}
else
lg_i = sprintf(lg_buf,"D=N ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
//
// Check the ROP
//
if (fg_rop == bg_rop)
lg_i = sprintf(lg_buf,"R3=%02X ", fg_rop);
else
lg_i = sprintf(lg_buf,"R4=%04X ", rop4&0xFFFF);
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
//
// Check the type of clipping.
//
iDComplexity = (pco ? pco->iDComplexity : DC_TRIVIAL);
lg_i = sprintf(lg_buf,"C=%s ",
(iDComplexity==DC_TRIVIAL ? "T":
(iDComplexity == DC_RECT ? "R" : "C" )));
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
//
// Type of pattern.
//
if (ropFlags[fg_rop] & P)
{
if (pbo->iSolidColor == 0xFFFFFFFF )
{
lg_i = sprintf(lg_buf,"BR=P ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
else
{
lg_i = sprintf(lg_buf,"BR=0x%X ",(pbo->iSolidColor));
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
}
else
{
lg_i = sprintf(lg_buf,"BR=N ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
//
// Type of translation
//
if (!pxlo)
{
lg_i = sprintf(lg_buf,"TR=N ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
else if (pxlo->flXlate & XO_TRIVIAL)
{
lg_i = sprintf(lg_buf,"TR=T ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
else
{
lg_i = sprintf(lg_buf,"TR=NT ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
lg_i = sprintf(lg_buf,"\r\n");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
return;
}
// ****************************************************************************
//
// LogDrvCreateDevBmp()
// This routine is called only from DrvCreateDeviceBitmap()
// Dump information to a file about what is going on in device bitmap land.
//
// ****************************************************************************
void LogDrvCreateDevBmp(
int acc,
PPDEV ppdev,
SIZEL sizl,
PDSURF pdsurf)
{
#if ENABLE_LOG_SWITCH
if (pointer_switch == 0) return;
#endif
switch(acc)
{
case 0: // Accelerated
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Id: 0x%08X Loc: %d,%d \r\n",
sizl.cx, sizl.cy, pdsurf, pdsurf->pofm->x, pdsurf->pofm->y );
break;
case 1: // Punted
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt size.\r\n",
sizl.cx, sizl.cy);
break;
case 2: // Punted
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt 8x8.\r\n",
sizl.cx, sizl.cy);
break;
case 3: // Punted
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt mode.\r\n",
sizl.cx, sizl.cy);
break;
case 4: // Punted
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt assoc.\r\n",
sizl.cx, sizl.cy);
break;
case 5: // Punted
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt bitmap.\r\n",
sizl.cx, sizl.cy);
break;
case 6: // Punted
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt DSURF.\r\n",
sizl.cx, sizl.cy);
break;
case 7: // Punted
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt FB alloc.\r\n",
sizl.cx, sizl.cy);
break;
case 8: // Punted
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt 32x64.\r\n",
sizl.cx, sizl.cy);
break;
case 9: // Punted
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt > cxScreen.\r\n",
sizl.cx, sizl.cy);
break;
default:
lg_i = sprintf(lg_buf,
"DrvCreateDeviceBitmap: %4d x %4d Punt unknown.\r\n",
sizl.cx, sizl.cy);
break;
}
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
// ****************************************************************************
//
// LogDrvDeleteDevBmp()
// This routine is called only from DrvDeleteDeviceBitmap()
// Dump information to a file about what is going on in device bitmap land.
//
// ****************************************************************************
void LogDrvDeleteDevBmp(
PDSURF pdsurf)
{
#if ENABLE_LOG_SWITCH
if (pointer_switch == 0) return;
#endif
lg_i = sprintf(lg_buf, "DrvDeleteDeviceBitmap: Id: 0x%08X. ", pdsurf);
WriteLogFile(pdsurf->ppdev->pmfile, lg_buf,
lg_i, pdsurf->ppdev->TxtBuff, &pdsurf->ppdev->TxtBuffIndex);
if (pdsurf->pso)
{
lg_i = sprintf(lg_buf, "Loc: HOST\r\n");
WriteLogFile(pdsurf->ppdev->pmfile, lg_buf, lg_i,
pdsurf->ppdev->TxtBuff, &pdsurf->ppdev->TxtBuffIndex);
}
else
{
lg_i = sprintf(lg_buf, "Loc: %d,%d\r\n", pdsurf->pofm->x, pdsurf->pofm->y);
WriteLogFile(pdsurf->ppdev->pmfile, lg_buf, lg_i,
pdsurf->ppdev->TxtBuff, &pdsurf->ppdev->TxtBuffIndex);
}
}
// ****************************************************************************
//
// LogCreateDibFromScreen()
// This routine is called only from bCreateDibFromScreen()
// Dump information to a file about what is going on in device bitmap land.
//
// ****************************************************************************
void LogCreateDibFromScreen(
int acc,
PPDEV ppdev,
PDSURF pdsurf
)
{
#if ENABLE_LOG_SWITCH
if (pointer_switch == 0) return;
#endif
lg_i = sprintf(lg_buf, "CreateDibFromScreen: Id: 0x%08X ", pdsurf);
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
switch(acc)
{
case 0: // Succeeded
lg_i = sprintf(lg_buf, " \r\n");
break;
case 1: // Failed
lg_i = sprintf(lg_buf, "Fail lock\r\n");
break;
case 2: // Failed
lg_i = sprintf(lg_buf, "Fail assoc\r\n");
break;
case 3: // Failed
lg_i = sprintf(lg_buf, " Fail create\r\n");
break;
default:
lg_i = sprintf(lg_buf, "Failed unknown\r\n");
break;
}
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
// ****************************************************************************
//
// LogCreateScreenFromDib()
// This routine is called only from bCreateScreenFromDib()
// Dump information to a file about what is going on in device bitmap land.
//
// ****************************************************************************
void LogCreateScreenFromDib(
int acc,
PPDEV ppdev,
PDSURF pdsurf
)
{
#if ENABLE_LOG_SWITCH
if (pointer_switch == 0) return;
#endif
lg_i = sprintf(lg_buf, "CreateScreenFromDib: ");
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
switch(acc)
{
case 0: // Succeeded
lg_i = sprintf(lg_buf, "Id: 0x%08X Dest: %d,%d\r\n",
pdsurf, pdsurf->pofm->x, pdsurf->pofm->y );
break;
case 1: // Failed
lg_i = sprintf(lg_buf, "Fail mode\r\n");
break;
case 2: // Failed
lg_i = sprintf(lg_buf, "Fail alloc\r\n");
break;
default: // Failed
lg_i = sprintf(lg_buf, "Fail unknown\r\n");
break;
}
WriteLogFile(ppdev->pmfile, lg_buf, lg_i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
#endif // LOG_CALLS
// ============================================================================
//
// Punt a drawing operation back to GDI.
// Return TRUE if punt was successful.
// Return FALSE if punt failed.
//
BOOL PuntBitBlt(
SURFOBJ* psoDest,
SURFOBJ* psoSrc,
SURFOBJ* psoMask,
CLIPOBJ* pco,
XLATEOBJ* pxlo,
RECTL* prclDest,
POINTL* pptlSrc,
POINTL* pptlMask,
BRUSHOBJ* pbo,
POINTL* pptlBrush,
ROP4 rop4)
{
HBITMAP hbmDibSrc = 0;
HBITMAP hbmDibDest = 0;
PBYTE pjScreen;
BOOL bStatus;
PDSURF pdsurf;
PPDEV ppdev = 0;
DISPDBG((PUNT_DBG_LEVEL, "PuntBitBlt: Entry.\n"));
//
// If the source is a device bitmap, build a wrapper around it.
//
if ( psoSrc && (psoSrc->iType == STYPE_DEVBITMAP))
{
// Source is a device bitmap.
pdsurf = (PDSURF) psoSrc->dhsurf;
ppdev = pdsurf->ppdev;
if ( pdsurf->pofm ) // If it's in the frame buffer.
{
DISPDBG((PUNT_DBG_LEVEL,
" Source is device bitmap at (%d,%d).\n",
(pdsurf->ptl.x), (pdsurf->ptl.y)));
// Calculate the off-screen address.
// This is the upper left pixel in the device bitmap.
pjScreen = ppdev->pjScreen
+ (pdsurf->ptl.x * ppdev->iBytesPerPixel)
+ (pdsurf->ptl.y * ppdev->lDeltaScreen);
// Create a DIB. Point it's bits at the device bitmap.
hbmDibSrc = EngCreateBitmap(pdsurf->sizl, ppdev->lDeltaScreen,
ppdev->iBitmapFormat, BMF_TOPDOWN,
pjScreen);
// Associate the DIB surface with the driver.
EngAssociateSurface((HSURF) hbmDibSrc, ppdev->hdevEng, 0);
// Lock the DIB surface.
psoSrc = EngLockSurface((HSURF) hbmDibSrc);
}
else // The device bitmap is on the host.
{
DISPDBG((PUNT_DBG_LEVEL, " Source is device bitmap on host.\n"));
psoSrc = pdsurf->pso; // This is where it lives on the host.
}
}
//
// If the destination is a device bitmap, build a wrapper around it.
//
if ( psoDest && (psoDest->iType == STYPE_DEVBITMAP))
{
// Destination is a device bitmap.
pdsurf = (PDSURF) psoDest->dhsurf;
ppdev = pdsurf->ppdev;
if ( pdsurf->pofm ) // If it's in the frame buffer.
{
DISPDBG((PUNT_DBG_LEVEL,
" Dest is device bitmap at (%d,%d).\n",
(pdsurf->ptl.x), (pdsurf->ptl.y)));
// Calculate the off-screen address.
// This is the upper left pixel in the device bitmap.
pjScreen = ppdev->pjScreen
+ (pdsurf->ptl.x * ppdev->iBytesPerPixel)
+ (pdsurf->ptl.y * ppdev->lDeltaScreen);
// Create a DIB. Point it's bits at the device bitmap.
hbmDibDest = EngCreateBitmap(pdsurf->sizl, ppdev->lDeltaScreen,
ppdev->iBitmapFormat, BMF_TOPDOWN,
pjScreen);
// Associate the DIB surface with the driver.
EngAssociateSurface((HSURF) hbmDibDest, ppdev->hdevEng, 0);
// Lock the DIB surface.
psoDest = EngLockSurface((HSURF) hbmDibDest);
}
else // The device bitmap is on the host.
{
DISPDBG((PUNT_DBG_LEVEL, " Dest is device bitmap on host.\n"));
psoDest = pdsurf->pso;
}
}
//
// We're fooling GDI into thinking it's drawing to memory, when it's really
// drawing to the frame buffer. This means GDI won't call DrvSync() before
// drawing.
//
if (ppdev == 0)
{
ppdev = (PPDEV) psoDest->dhpdev;
if (ppdev == 0)
ppdev = (PPDEV) psoSrc->dhpdev;
}
ASSERTMSG(ppdev,"Panic. No ppdev in PuntBitBlt()!");
DrvSynchronize((DHPDEV) ppdev, NULL);
// Now, call the GDI.
bStatus = EngBitBlt(psoDest, psoSrc, psoMask, pco, pxlo, prclDest, pptlSrc,
pptlMask, pbo, pptlBrush, rop4);
// Delete the wrappers if they are created.
if (hbmDibSrc)
{
EngUnlockSurface(psoSrc);
EngDeleteSurface((HSURF) hbmDibSrc);
}
if (hbmDibDest)
{
EngUnlockSurface(psoDest);
EngDeleteSurface((HSURF) hbmDibDest);
}
DISPDBG((PUNT_DBG_LEVEL, "PuntBitBlt: Exit.\n"));
// Return the status.
return(bStatus);
}
#if SWAT6
/******************************************************************************\
* FUNCTION: StripePatBlt
*
* DESCRIPTION: Perform a PatBlt with striping.
*
* ON ENTRY: ppdev Pointer to physical device.
* x X coordinate of blit.
* y Y coordinate of blit.
* cx Width of blit.
* cy Height of blit.
*
* RETURNS: void Nothing.
\******************************************************************************/
void
StripePatBlt(
PPDEV ppdev,
ULONG x,
ULONG y,
ULONG cx,
ULONG cy
)
{
ULONG cxWidth;
ULONG TileWidth;
// Determine number of pixels per tile.
switch (ppdev->iBytesPerPixel)
{
case 1:
// 8-bpp.
TileWidth = (ULONG) ppdev->lTileSize;
break;
case 2:
// 16-bpp.
TileWidth = (ULONG) (ppdev->lTileSize) / 2;
break;
case 3:
// 24-bpp, perform the PatBlt at once since we don't have a nice
// number of pixels per tile.
REQUIRE(5);
LL_OP0(x, y);
LL_BLTEXT(cx, cy);
if (cx >= 0x391 && cy >= 0x24B)
{
ENDREQUIRE();
}
return;
case 4:
// 32-bpp.
TileWidth = (ULONG) (ppdev->lTileSize) / 4;
break;
}
// Determine number of pixels left in first tile.
cxWidth = TileWidth - (x & (TileWidth - 1));
if ( (cxWidth >= cx) || (cy == 1) )
{
// PatBlt width fits in a single tile.
REQUIRE(5);
LL_OP0(x, y);
LL_BLTEXT(cx, cy);
return;
}
// Perform the PatBlt in the first tile.
REQUIRE(5);
LL_OP0(x, y);
LL_BLTEXT(cxWidth, cy);
cx -= cxWidth;
x += cxWidth;
// Keep looping until we reach the last tile of the PatBlt.
while (cx > TileWidth)
{
// Perform the PatBlt on a complete tile (only x changes).
REQUIRE(5);
LL_OP0(x, y);
LL_BLTEXT(TileWidth, cy);
cx -= TileWidth;
x += TileWidth;
}
// Perform the PatBlt in the last tile (only x changes).
REQUIRE(5);
LL_OP0(x, y);
LL_BLTEXT(cx, cy);
} // StripePatBlt();
#endif // SWAT6