Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

3322 lines
89 KiB

/******************************Module*Header*******************************\
* Module Name: enable.c
*
* This module contains the functions that enable and disable the
* driver, the pdev, and the surface.
*
* Copyright (c) 1992 Microsoft Corporation
*
* Copyright (c) 1994 FirePower Systems, Inc.
* Modified for FirePower display model by Neil Ogura (9-7-1994)
*
\**************************************************************************/
/*
* Copyright (c) 1995 FirePower Systems, Inc.
* DO NOT DISTRIBUTE without permission
*
* $RCSfile: enable.c $
* $Revision: 1.3 $
* $Date: 1996/05/13 23:17:20 $
* $Locker: $
*/
#include "driver.h"
PPDEV myPDEV = NULL; // Used for surface identification in HOOKED functions
ULONG ScreenBase = 0; // To make sure that surface is on VRAM
#define NUMCOLOR 256
#if BUG_5737_WORKAROUND
VOID
DisplayModeChanged();
#endif
//
// Define the function table here.
// DrvDitherColor & DrvSetPalette are used only in 8 bpp
//
#if INVESTIGATE
#define MAXBANDWIDTH TRUE
#define BANDWIDTH TRUE
#include <stdio.h>
#include <stdarg.h>
ULONG oneshot = 0;
ULONG traseentry = 0;
ULONG breakentry = 0;
ULONG traseexit = 0;
ULONG breakexit = 0;
ULONG dumpparam = 0;
#define DRV_HOOKED (FL_DRV_COPYBIT | FL_DRV_BITBLT | FL_DRV_TEXTOUT | FL_DRV_STRTBIT | FL_DRV_PAINT)
ULONG paramcheck = DRV_HOOKED;
ULONG compare = 0;
ULONG donebydrv = 0;
ULONG usedrvfunc = DRV_HOOKED ;
ULONG useengfunc = FL_DRV_HOOKED & (~DRV_HOOKED);
ULONG dbgflg = 0xffffffff;
ULONG breakcnt = 0;
ULONG flushtest = 0;
ULONG comparecount = 0;
#define BEFORE_SCREEN 0
#define AFTER_DRV 1
#define AFTER_ENG 2
#define FPSTR_MAX 3
static char *fpstrtbl[FPSTR_MAX] = {"#INVALID#", "ALTERNATE", "WINDING"};
#define ROP_MAX 16
static KEYTABLE bitbltoptbl[ROP_MAX] = {{0x00000000, "BLACKNESS"}, {0x0000FFFF, "WHITENESS"},
{0x0000F0F0, "PATCOPY"}, {0x00000F0F, "NOTPATCOPY"}, {0x0000CCCC, "SOURCE"},
{0x00005555, "DSTINVERT"}, {0x00005a5a, "PATINVERT"}, {0x0000b8b8, "B8OP"},
{0x00006666, "SRCINVERT"}, {0x00008888, "SRCAND"}, {0x0000eeee, "SRCPAINT"},
{0x0000bbbb, "MERGEPAINT"}, {0x00004444, "SRCERASE"}, {0x00001111, "NOTSRCERASE"},
{0x00000a0a, "INVPATANDDEST"}, {0x0000a0a0, "PATANDEST"}};
static ULONG FileNumberBase = 0;
#define BUFBLOCK 8
#define PAGEBLOCK 5
#define BUFPAGE (BUFBLOCK*PAGEBLOCK)
#define BLOCKSIZE (1024*PAGEBLOCK)
#define BUFSIZE (BLOCKSIZE*BUFBLOCK)
static CHAR linebuf[BUFSIZE];
static CHAR linebuf2[BUFSIZE];
static CHAR *category[3] = {"BEF", "DRV", "ENG"};
ULONG ScreenMemory = 0;
PBYTE ScreenBuf1 = 0;
PBYTE ScreenBuf2 = 0;
extern const BYTE gaMix[];
#define PAINT_RECT_LIMIT 10
typedef struct _PAINTENUMRECTLIST
{
ULONG c;
RECTL arcl[PAINT_RECT_LIMIT];
} PAINTENUMRECTLIST;
static PAINTENUMRECTLIST PaintClipEnum;
LONG
SaveScreenMem(
ULONG FileCategory,
ULONG FileNumber
);
LONG
SaveGlyphPos(
STROBJ *pstro
);
LONG
RestoreGlyphPos(
STROBJ *pstro
);
LONG
RestoreScreenMem(
ULONG FileCategory,
ULONG FileNumber
);
LONG
CompareScreenMem(
ULONG FileCategory,
ULONG FileNumber
);
LONG
CheckHeader(
FILE *stream
);
extern ULONG FontTblMax, GlyphTblMax, CacheTblMax;
extern ULONG CopyBitsHist[MAX_CATEGORY];
extern ULONG BitBltHist[MAX_CATEGORY];
extern ULONG TextOutHist[MAX_TEXT_CATEGORY];
extern ULONG fontSize[MAX_FONT_SIZE];
extern ULONG GlyphCountTable[MAX_GLYPH_COUNT];
extern ULONG FontAccl[MAX_CATEGORY];
extern ULONG TextRect[MAX_TEXT_RECT];
extern ULONG TextClip[MAX_CLIP_CONDITION];
extern ULONG TextWidthHist[6][MAX_WIDTH_STEP];
extern ULONG TextHeightHist[6][MAX_HEIGHT_STEP];
extern ULONG FontWidth[MAX_FONT_SIZE];
extern ULONG FontHeight[MAX_FONT_SIZE];
extern ULONG StrObjCountTable[MAX_STROBJ_COUNT];
extern ULONG FontIDTable[MAX_FONT_ENTRY][2];
extern ULONG GlyphHndlTable[MAX_GLYPH_HNDL_ENTRY][2];
extern ULONG CacheTable[MAX_CACHE_ENTRY][3];
extern ULONG CopyBitWidthHist[4][MAX_WIDTH_STEP];
extern ULONG CopyBitHeightHist[4][MAX_HEIGHT_STEP];
extern ULONG BitBltWidthHist[6][MAX_WIDTH_STEP];
extern ULONG BitBltHeightHist[6][MAX_HEIGHT_STEP];
extern ULONG BitBltRop[37][MAX_ROP_ENTRY];
extern ULONG BitBltBrush[2][MAX_BRUSH_ENTRY];
extern ULONG TextPerfByCtgry[4][2];
extern ULONG PaintOp[MAX_PAINT_OPS];
extern ULONG PaintCategories[MAX_PAINT_CATEGORY];
extern ULONG PaintBounds[MAX_PAINT_CATEGORY-1][MAX_PAINT_BOUNDS_ENTRY];
extern ULONG PaintClips[MAX_PAINT_CATEGORY-1][MAX_PAINT_CLIP_ENTRY];
extern ULONG PaintHeight[MAX_PAINT_CATEGORY-1][MAX_PAINT_HEIGHT_ENTRY];
extern ULONG PaintWidth[MAX_PAINT_CATEGORY-1][MAX_PAINT_WIDTH_ENTRY];
extern BOOL InitTable;
#define SO_MASK \
(SO_FLAG_DEFAULT_PLACEMENT | SO_ZERO_BEARINGS | \
SO_CHAR_INC_EQUAL_BM_BASE | SO_MAXEXT_EQUAL_BM_SIDE)
#define SO_LTOR (SO_MASK | SO_HORIZONTAL)
#define SO_RTOL (SO_LTOR | SO_REVERSED)
#define SO_TTOB (SO_MASK | SO_VERTICAL)
#define SO_BTOT (SO_TTOB | SO_REVERSED)
BOOL PDEVDisplay = TRUE;
VOID
DisplayPDEV()
{
ULONG i;
if(! PDEVDisplay)
return;
PDEVDisplay = FALSE;
DebugPrint(1,"hDriver = 0x%08x\n", myPDEV->hDriver);
DebugPrint(1,"hdevEng = 0x%08x\n", myPDEV->hdevEng);
DebugPrint(1,"hsurfEng = 0x%08x\n", myPDEV->hsurfEng);
DebugPrint(1,"hpalDefault = 0x%08x\n", myPDEV->hpalDefault);
DebugPrint(1,"pjScreen = 0x%08x\n", myPDEV->pjScreen);
DebugPrint(1,"pjCachedScreen = 0x%08x\n", myPDEV->pjCachedScreen);
DebugPrint(1,"VRAMcacheflg = 0x%08x\n", myPDEV->VRAMcacheflg);
DebugPrint(1,"Screen = %d X %d\n", myPDEV->cxScreen, myPDEV->cyScreen);
DebugPrint(1,"ulMode = %d\n", myPDEV->ulMode);
DebugPrint(1,"lDeltaScreen = %d\n", myPDEV->lDeltaScreen);
DebugPrint(1,"RGB Mask = (0x%08x, 0x%08x, 0x%08x)\n",
myPDEV->flRed, myPDEV->flGreen, myPDEV->flBlue);
DebugPrint(1,"ulBitCount = %d\n", myPDEV->ulBitCount);
DebugPrint(1,"PointerCapabilities = 0x%08x, (%d X %d), 0x%08x - 0x%08x\n",
myPDEV->PointerCapabilities.Flags, myPDEV->PointerCapabilities.MaxWidth,
myPDEV->PointerCapabilities.MaxHeight, myPDEV->PointerCapabilities.HWPtrBitmapStart,
myPDEV->PointerCapabilities.HWPtrBitmapEnd);
if(myPDEV->pPointerAttributes) {
DebugPrint(1,"PointerAttributes = 0x%08x, Size = (%d X %d), Byte = %d, Enable = 0x%08x, Pos = (%d, %d)\n",
myPDEV->pPointerAttributes->Flags, myPDEV->pPointerAttributes->Width,
myPDEV->pPointerAttributes->Height, myPDEV->pPointerAttributes->WidthInBytes,
myPDEV->pPointerAttributes->Enable, myPDEV->pPointerAttributes->Column,
myPDEV->pPointerAttributes->Row);
}
DebugPrint(1,"cjPointerAttributes = %d\n", myPDEV->cjPointerAttributes);
DebugPrint(1,"fHwCursorActive = %d\n", myPDEV->fHwCursorActive);
DebugPrint(1,"MemorySize = 0x%x (%d)\n", myPDEV->MemorySize, myPDEV->MemorySize);
DebugPrint(1,"FrameBufferWidth = %d\n", myPDEV->FrameBufferWidth);
DebugPrint(1,"ModelID = %d\n", myPDEV->ModelID);
DebugPrint(1,"ColorModeShift = %d\n", myPDEV->ColorModeShift);
if(myPDEV->pPal) {
for(i=0; i<NUMCOLOR; ++i) {
DebugPrint(1, "%03d:%03d,%03d,%03d", i, myPDEV->pPal[i].peRed,
myPDEV->pPal[i].peGreen, myPDEV->pPal[i].peBlue);
if(i%4 != 3)
DebugPrint(1, " ");
else
DebugPrint(1, "\n");
}
}
}
ULONG
GetTime()
{
DWORD returnedDataLength;
ULONG work;
static BOOL TimerError = FALSE;
work = 0;
if(! TimerError) {
if (EngDeviceIoControl(myPDEV->hDriver,
IOCTL_GET_TIMER_COUNTER,
NULL,
0,
&work,
sizeof(ULONG),
&returnedDataLength)) {
DISPDBG((0,"#### Getting Elapse Time Error ####\n"));
TimerError = TRUE;
}
}
return(work);
}
ULONG makemask(
ULONG maxcount)
{
ULONG i;
for(i=2; i<=512; i*=2) {
if(i > maxcount)
break;
}
return(i/2-1);
}
VOID PerformCheck(
ULONG st,
ULONG ed,
ULONG sp,
ULONG height)
{
ULONG i, j, k, bpp, totallen, len, overhead;
UCHAR *cps, *cpt;
ULONG start, srced, sdelta=0, tdelta=0, smask=0, tmask=0, cache, record[2][5];
ULONG flags[4] = { NOCACHECTRL, TTOUCHBIT, TFLUSHBIT, TFLUSHBIT | TTOUCHBIT};
UCHAR *title[14] = { "D->V", "V->V", "D->CV", "D->CV(T)", "D->CV(Ft)", "D->CV(TFt)",
"CV->CV", "CV->CV(T)", "CV->CV(Ft)", "CV->CV(TFt)",
"CV->CV(Fs)", "CV->CV(TFs)", "CV->CV(FtFs)", "CV->CV(TFtFs)" };
st <<= myPDEV->ColorModeShift;
ed <<= myPDEV->ColorModeShift;
sp <<= myPDEV->ColorModeShift;
bpp = 1 << myPDEV->ColorModeShift;
switch(bpp) {
case 1: srced = (ed/256 + 1)*256;
break;
case 2: srced = (ed/1024 + 1)*1024;
break;
case 4: srced = (ed/2560 + 1)*2560;
break;
}
start = GetTime();
for(len=st; len<ed; len += sp) {
for(i=0; i<height; ++i) {
noop(cpt+(i&tmask)*tdelta, cps+(i&smask)*sdelta+j*bpp, len, cache);
}
}
overhead = GetTime() - start;
totallen = 0;
for(j=0; j<4; ++j) {
for(len=st; len<ed; len += sp) {
for(i=0; i<height; ++i) {
totallen += len;
}
}
}
DISPDBG((0, "\n<Total data size = %dKB, Measurement overhead = %d.%02d>\n", totallen/1024, overhead/100, overhead%100));
DISPDBG((0, "MemKind mc-0 mc-1 mc-2 mc-3 mc-ttl mc2-0 mc2-1 mc2-2 mc2-3 mc2-ttl\n"));
for(k=0; k<14; ++k) {
DISPDBG((0, "%s", title[k]));
record[0][4] = record[1][4] = 0; // Clear total
switch(k) {
case 0: // DRAM to VRAM
cpt = myPDEV->pjScreen;
cps = linebuf;
tdelta = myPDEV->lDeltaScreen;
sdelta = srced;
tmask = 0xff;
smask = makemask(BUFSIZE/srced);
cache = NOCACHECTRL;
break;
case 1: // VRAM to VRAM
tdelta = sdelta = myPDEV->lDeltaScreen;
tmask = smask = 0xff;
cpt = myPDEV->pjScreen + (myPDEV->cyScreen)*(tdelta)/2;
cps = myPDEV->pjScreen;
cache = NOCACHECTRL;
break;
default: // 2~5: DRAM to Cached VRAM, 6~13: Cached VRAM to Cached VRAM
if((LONG) myPDEV->ModelID == -1) { // PSI S3 VRAM
cpt = linebuf2;
tdelta = ed;
tmask = makemask(BUFSIZE/ed);
} else { // PSI DCC & VRAM
cpt = myPDEV->pjCachedScreen;
tdelta = myPDEV->lDeltaScreen;
tmask = 0xff;
}
if(k < 6) { // Source is DRAM
cps = linebuf;
sdelta = srced;
smask = makemask(BUFSIZE/srced);
cache = flags[k-2];
} else { // Source is Cached VRAM
if((LONG) myPDEV->ModelID == -1) { // PSI S3 VRAM
sdelta = srced;
smask = makemask(BUFSIZE/srced);
cps = linebuf;
} else { // PSI DCC & VRAM
sdelta = myPDEV->lDeltaScreen;
smask = 0xff;
cpt = myPDEV->pjCachedScreen + (myPDEV->cyScreen)*(tdelta)/2;
cps = myPDEV->pjCachedScreen;
}
if(k < 10)
cache = flags[k-6];
else
cache = flags[k-10] | SFLUSHBIT;
}
break;
}
// DISPDBG((0, "smask=%x tmask=%x sdelta=%d tdelta=%d smax=%d tmax=%d cps=%x cpt=%x cache=%08x\n",
// smask, tmask, sdelta, tdelta, sdelta*(smask+1), tdelta*(tmask+1), cps, cpt, cache));
cache &= myPDEV->VRAMcacheflg;
for(j=0; j<4; ++j) {
start = GetTime();
for(len=st; len<ed; len += sp) {
for(i=0; i<height; ++i) {
memcpy(cpt+(i&tmask)*tdelta, cps+(i&smask)*sdelta+j*bpp, len);
}
}
record[0][j] = GetTime() - start - overhead;
record[0][4] += record[0][j];
start = GetTime();
for(len=st; len<ed; len += sp) {
for(i=0; i<height; ++i) {
memcpy2(cpt+(i&tmask)*tdelta, cps+(i&smask)*sdelta+j*bpp, len, cache);
}
}
record[1][j] = GetTime() - start - overhead;
record[1][4] += record[1][j];
}
for(i=0; i<5; ++i) {
DISPDBG((0, " %d.%02d", record[0][i]/100, record[0][i]%100));
}
for(i=0; i<5; ++i) {
DISPDBG((0, " %d.%02d", record[1][i]/100, record[1][i]%100));
}
DISPDBG((0, "\n"));
}
}
VOID
VramAccess()
{
LONG i, j, k, l, dx, dy, maxtstno;
ULONG m, length, bpp, record[12];
UCHAR *cps, *cpt, *base;
USHORT *sps, *spt;
ULONG *ups, *upt, start, end, data, cache, overhead0, overhead1;
SIZEL sizl;
/***** for debugging only *******
{
cache = SFLUSHBIT | TFLUSHBIT | TTOUCHBIT;
EngDebugBreak();
memcpy2(linebuf, linebuf2, 0, cache);
memcpy2(linebuf, linebuf2, 1, cache);
memcpy2(linebuf, linebuf2, 16, cache);
memcpy2(linebuf, linebuf2, 17, cache);
memcpy2(linebuf, linebuf2, 32*1024-1, cache);
memcpy2(linebuf, linebuf2, 32*1024, cache);
memcpy2(linebuf, linebuf2, 32*1024+1, cache);
memcpy2(linebuf2, linebuf, 0, cache); memcpy2(linebuf2, linebuf, 1, cache);
memcpy2(linebuf2, linebuf, 16, cache);
memcpy2(linebuf2, linebuf, 17, cache);
memcpy2(linebuf2, linebuf, 32*1024-1, cache);
memcpy2(linebuf2, linebuf, 32*1024, cache);
memcpy2(linebuf2, linebuf, 32*1024+1, cache);
EngDebugBreak();
memset2(linebuf, 0xff, 0, cache);
memset2(linebuf, 0xff, 1, cache);
memset2(linebuf, 0xff, 16, cache);
memset2(linebuf, 0xff, 17, cache);
memset2(linebuf, 0xff, 32*1024-1, cache);
memset2(linebuf, 0xff, 32*1024, cache);
memset2(linebuf, 0xff, 32*1024+1, cache);
EngDebugBreak();
}
******************************/
sizl.cx = myPDEV->cxScreen;
sizl.cy = myPDEV->cyScreen;
dx = myPDEV->lDeltaScreen;
bpp = 1 << myPDEV->ColorModeShift;
dy = sizl.cx * bpp;
if(dy >= BLOCKSIZE)
dy = BLOCKSIZE-bpp;
#if MAXBANDWIDTH
base = myPDEV->pjCachedScreen;
cache = (TFLUSHBIT | TTOUCHBIT | SFLUSHBIT) & myPDEV->VRAMcacheflg;
k = sizl.cy * (myPDEV->lDeltaScreen);
length = k*20*10/1024*100/1024; // length = 1/100 MB
if(myPDEV->MemorySize >= (ULONG) k*2)
memcpy2(base+k, base, k, cache);
start = GetTime();
overhead0 = GetTime() - start;
start = GetTime();
for(l=0; l<10; ++l) {
for(i=0; i<20; ++i) {
memcpy2(base, base+dy*35, k, cache);
}
}
end = GetTime() - start - overhead0;
DISPDBG((0,"%d.%02d MB copy %d.%02d milli sec - %d.%02d MB/sec (measurement overhead %d.%02d)\n",
length/100, length%100, end/100, end%100, (length*100000/end)/100, (length*100000/end)%100, overhead0/100, overhead0%100));
#else // MAXBANDWIDTH
switch(myPDEV->ColorModeShift) {
case 0: for(i=0; i<256; ++i)
linebuf[i] = (CHAR) i;
length = 256;
break;
case 1: spt = (PUSHORT) linebuf;
j = 5;
k = 32;
if(myPDEV->VRAM1MBWorkAround && myPDEV->FrameBufferWidth == VRAM_32BIT) {
j = 4;
k = 16;
}
for(i=0; i<k; ++i) {
*spt++ = *spt++ = *spt++ = *spt++ = (SHORT) (i<<(j*2));
}
for(i=0; i<k; ++i) {
*spt++ = *spt++ = *spt++ = *spt++ = (SHORT) (i<<j);
}
for(i=0; i<k; ++i) {
*spt++ = *spt++ = *spt++ = *spt++ = (SHORT) i;
}
for(i=0; i<k; ++i) {
*spt++ = *spt++ = *spt++ = *spt++ = (SHORT) ((i<<(j*2)) | (i<<j) | i);
}
length = k*4*4*2;
break;
case 2: upt = (PULONG) linebuf;
for(i=0; i<128; ++i)
*upt++ = i << 17;
for(i=0; i<128; ++i)
*upt++ = i << 9;
for(i=0; i<128; ++i)
*upt++ = i << 1;
for(i=0; i<256; ++i)
*upt++ = (i<<16) | (i<<8) | i;
length = (128*3 + 256)*4;
}
m = BLOCKSIZE - length;
j = length;
while(m > length) {
memcpy(linebuf+j, linebuf, length);
j += length;
m -= length;
}
memcpy(linebuf+j, linebuf, i);
for(i=1; i<BUFBLOCK; ++i) {
memcpy(linebuf+i*BLOCKSIZE, linebuf, BLOCKSIZE);
}
DISPDBG((0,"<< %dK byte VRAM >>\n", myPDEV->MemorySize/1024));
#if BANDWIDTH
DISPDBG((0,"Access memcpy memcpy2 memcpy-na memcpy2-na memset0 memsetff meset2-0 memset2-ff\n"));
maxtstno = 7;
#else // BANDWIDTH
DISPDBG((0,"Access Byte HW Word memcpy memcpyNA memcpy2 memcpy2NA memset memset2 VLine SameWord Flush\n"));
maxtstno = 11;
#endif // ELSE BANDWIDTH
for(m=0; m<5; ++m) {
base = myPDEV->pjCachedScreen;
if((LONG) myPDEV->ModelID == -1) { // PSI S3 VRAM
cache = NOCACHECTRL;
if(m==1)
break;
}
switch(m) {
case 0: // Non cached VRAM
cache = NOCACHECTRL;
base = myPDEV->pjScreen;
DISPDBG((0,"NonCache"));
break;
case 1: // Cached VRAM no control
cache = NOCACHECTRL;
DISPDBG((0,"NoCTRL"));
break;
case 2: // Cached VRAM src & target touch
cache = TTOUCHBIT;
DISPDBG((0,"Touch"));
break;
case 3: // Cached VRAM target flush
cache = TFLUSHBIT;
DISPDBG((0,"TgtFlush"));
break;
case 4: // Cached VRAM src & target touch and target flush
cache = TFLUSHBIT | TTOUCHBIT;
DISPDBG((0,"Touch&TgtFlush"));
break;
}
cache &= myPDEV->VRAMcacheflg;
for(l=-2; l<=maxtstno; ++l) {
memset2(myPDEV->pjCachedScreen, 0, myPDEV->MemorySize, TFLUSHBIT & myPDEV->VRAMcacheflg);
start = GetTime();
switch(l) {
case -2: // overhead measurement 0
break;
case -1: // overhead measurement 1
for(i=0; i<sizl.cy; ++i) {
cpt = base + i * dx;
noop(cpt, linebuf + (i%BUFBLOCK) * BLOCKSIZE + 1, dy, cache);
}
break;
#if BANDWIDTH
case 0:
k = sizl.cy * (myPDEV->lDeltaScreen);
memcpy(base+k, base, k);
for(i=0; i<18; ++i) {
memcpy(base, base+dy*35, k);
}
memcpy(base, base+k, k);
break;
case 1:
k = sizl.cy * (myPDEV->lDeltaScreen);
memcpy2(base+k, base, k, cache);
for(i=0; i<18; ++i) {
memcpy2(base, base+dy*35, k, cache);
}
memcpy2(base, base+k, k, cache);
break;
case 2:
k = sizl.cy * (myPDEV->lDeltaScreen);
memcpy(base+k, base, k);
for(i=0; i<18; ++i) {
memcpy(base, base+dy*35-1, k);
}
memcpy(base, base+k, k);
break;
case 3:
k = sizl.cy * (myPDEV->lDeltaScreen);
memcpy2(base+k, base, k, cache);
for(i=0; i<18; ++i) {
memcpy2(base, base+dy*35-1, k, cache);
}
memcpy2(base, base+k, k, cache);
break;
case 4: // memset
if(m==0) {
memset(base, 0x01, myPDEV->MemorySize);
memset(base, 0x01, myPDEV->MemorySize);
memset(base, 0x01, myPDEV->MemorySize);
memset(base, 0x01, myPDEV->MemorySize);
memset(base, 0x01, myPDEV->MemorySize);
} else {
memset(base, 0x00, myPDEV->MemorySize);
memset(base, 0x00, myPDEV->MemorySize);
memset(base, 0x00, myPDEV->MemorySize);
memset(base, 0x00, myPDEV->MemorySize);
memset(base, 0x00, myPDEV->MemorySize);
}
break;
case 5: // memset2
memset(base, 0xff, myPDEV->MemorySize);
memset(base, 0xff, myPDEV->MemorySize);
memset(base, 0xff, myPDEV->MemorySize);
memset(base, 0xff, myPDEV->MemorySize);
memset(base, 0xff, myPDEV->MemorySize);
break;
case 6: // memset
memset2(base, 0x00, myPDEV->MemorySize, cache);
memset2(base, 0x00, myPDEV->MemorySize, cache);
memset2(base, 0x00, myPDEV->MemorySize, cache);
memset2(base, 0x00, myPDEV->MemorySize, cache);
memset2(base, 0x00, myPDEV->MemorySize, cache);
break;
case 7: // memset2
memset2(base, 0xff, myPDEV->MemorySize, cache);
memset2(base, 0xff, myPDEV->MemorySize, cache);
memset2(base, 0xff, myPDEV->MemorySize, cache);
memset2(base, 0xff, myPDEV->MemorySize, cache);
memset2(base, 0xff, myPDEV->MemorySize, cache);
break;
#else // BANDWIDTH
case 0: // byte fill
for(i=0; i<sizl.cy; ++i) {
cpt = base + i * dx;
cps = linebuf + (i%BUFBLOCK) * BLOCKSIZE;
for(k=0; k<dy; ++k) {
*cpt++ = *(cps+k);
}
}
break;
case 1: // half word fill
for(i=0; i<sizl.cy; ++i) {
cpt = base + i * dx;
spt = (PUSHORT) cpt;
cps = linebuf + (i%BUFBLOCK) * BLOCKSIZE;
sps = (PUSHORT) cps;
j = dy/2;
for(k=0; k<j; ++k) {
*spt++ = *(sps+k);
}
}
break;
case 2: // word fill
for(i=0; i<sizl.cy; ++i) {
cpt = base + i * dx;
upt = (PULONG) cpt;
cps = linebuf + (i%BUFBLOCK) * BLOCKSIZE;
ups = (PULONG) cps;
j = dy/4;
for(k=0; k<j; ++k) {
*upt++ = *(ups+k);
}
}
break;
case 3: // memcpy fill aligned
for(i=0; i<sizl.cy; ++i) {
cpt = base + i * dx;
memcpy(cpt, linebuf + (i%BUFBLOCK) * BLOCKSIZE, dy);
}
break;
case 4: // memcpy fill not aligned
for(i=0; i<sizl.cy; ++i) {
cpt = base + i * dx;
memcpy(cpt, linebuf + (i%BUFBLOCK) * BLOCKSIZE + bpp, dy);
}
break;
case 5: // memcpy2
for(i=0; i<sizl.cy; ++i) {
cpt = base + i * dx;
memcpy2(cpt, linebuf + (i%BUFBLOCK) * BLOCKSIZE, dy, cache);
}
break;
case 6: // memcpy2 not aligned
for(i=0; i<sizl.cy; ++i) {
cpt = base + i * dx;
memcpy2(cpt, linebuf + (i%BUFBLOCK) * BLOCKSIZE + bpp, dy, cache);
}
break;
case 7: // memset
memset(base, 0xff, myPDEV->MemorySize);
memset(base, 0x88, myPDEV->MemorySize);
break;
case 8: // memset2
memset2(base, 0xff, myPDEV->MemorySize, cache);
memset2(base, 0x88, myPDEV->MemorySize, cache);
break;
case 9: // vertical line
switch(bpp) {
case 1:
for(k=0; k<8; ++k) {
for(j=k*4; j<dx; j+=32) {
cpt = base + j;
for(i=0; i<sizl.cy; ++i) {
*(cpt+i*sizl.cx) = 0xff;
}
}
}
break;
case 2:
for(k=0; k<8; ++k) {
for(j=k*8; j<dx; j+=64) {
cpt = base + j;
spt = (PUSHORT) cpt;
for(i=0; i<sizl.cy; ++i) {
*(spt+i*sizl.cx) = 0xffff;
}
}
}
break;
case 4:
for(k=0; k<8; ++k) {
for(j=k*16; j<dx; j+=128) {
cpt = base + j;
upt = (PULONG) cpt;
for(i=0; i<sizl.cy; ++i) {
*(upt+i*sizl.cx) = 0xffffffff;
}
}
}
break;
}
break;
case 10: // Same word access
memset(myPDEV->pjScreen, 0xff, dy);
memset(myPDEV->pjScreen+(sizl.cy-1)*dx, 0xff, dy);
cpt = myPDEV->pjScreen;
switch(bpp) {
case 1:
for(i=0; i<sizl.cy; ++i) {
*cpt = 0xff;
*(cpt+sizl.cx-1) = 0xff;
cpt += dx;
}
break;
case 2:
j = 0x7fff;
if(myPDEV->VRAM1MBWorkAround && myPDEV->FrameBufferWidth == VRAM_32BIT)
j = 0x0fff;
for(i=0; i<sizl.cy; ++i) {
spt = (PUSHORT) cpt;
*spt = (SHORT) j;
*(spt+sizl.cx-1) = (SHORT) j;
cpt += dx;
}
break;
case 4:
for(i=0; i<sizl.cy; ++i) {
upt = (PULONG) cpt;
*upt = 0x00ffffff;
*(upt+sizl.cx-1) = 0x00ffffff;
cpt += dx;
}
break;
}
i = (LONG) base;
i += sizl.cy * dx / 2 + dx / 2;
i &= 0xffffffe0;
upt = (PULONG)i;
for(i=0; i<2; ++i) {
for(j=0; j<256; ++j) {
data = (j<<24) | (j<<16) | (j<<8) | j;
for(k = 0; k<3000; ++k) {
*upt = data;
*(upt+1) = data;
*(upt+2) = data;
*(upt+3) = data;
*(upt+4) = data;
*(upt+5) = data;
*(upt+6) = data;
*(upt+7) = data;
}
}
}
break;
case 11: // Cache flush cost
flush(myPDEV->pjCachedScreen, myPDEV->MemorySize);
break;
#endif // ELSE BANDWIDTH
}
end = GetTime();
end -= start;
switch(l) {
case -2: if(m==0) {
overhead0 = end;
}
break;
case -1: if(m==0) {
overhead1 = end;
}
break;
case 10: record[l] = (end - overhead0)/10;
Sleep(3000);
break;
default: record[l] = end - overhead0;
}
}
for(i=0; i<=maxtstno; ++i) {
DISPDBG((0," %d.%02d", record[i]/100, record[i]%100));
}
DISPDBG((0,"\n"));
// Cache flush test
if(flushtest) {
cpt = base;
cps = myPDEV->pjScreen;
j = dx/2;
for(i=100; i<=500; i+=100) {
memset2(cpt+i*dx, 0xff, j, cache);
}
for(i=100; i<=500; i+=100) {
memset(cps+i*dx, 0x01, j);
}
memset2((myPDEV->pjScreen), 0xff, (sizl.cx << myPDEV->ColorModeShift), NOCACHECTRL);
Sleep(3000);
memset2(myPDEV->pjCachedScreen, 0, myPDEV->MemorySize, TFLUSHBIT);
for(i=100; i<=500; i+=100) {
memcpy2(cpt+i*dx, linebuf, j, cache);
}
for(i=100; i<=500; i+=100) {
memset(cps+i*dx, 0x01, j);
}
memset2((myPDEV->pjScreen) + 10*dx, 0xff, (sizl.cx << myPDEV->ColorModeShift), NOCACHECTRL);
Sleep(3000);
memset2(myPDEV->pjCachedScreen, 0, myPDEV->MemorySize, TFLUSHBIT);
for(i=100; i<=500; i+=100) {
memset2(cpt+i*dx, 0xff, j, cache);
}
for(i=100; i<=500; i+=100) {
memcpy2(cpt+(i+50)*dx+j, cpt+i*dx, j, cache);
}
for(i=100; i<=550; i+=50) {
memset(cps+i*dx, 0x01, j*2);
}
memset2((myPDEV->pjScreen) + 20*dx, 0xff, (sizl.cx << myPDEV->ColorModeShift), NOCACHECTRL);
Sleep(3000);
memset2(myPDEV->pjCachedScreen, 0, myPDEV->MemorySize, TFLUSHBIT);
for(i=100; i<=500; i+=100) {
memset2(cpt+i*dx, 0xff, j, cache);
}
for(i=100; i<=500; i+=100) {
memcpy2(cpt+(i+50)*dx+j, cpt+i*dx, j, cache | SFLUSHBIT);
}
for(i=100; i<=550; i+=50) {
memset(cps+i*dx, 0x01, j*2);
}
memset2((myPDEV->pjScreen) + 30*dx, 0xff, (sizl.cx << myPDEV->ColorModeShift), NOCACHECTRL);
Sleep(3000);
memset2(myPDEV->pjCachedScreen, 0, myPDEV->MemorySize, TFLUSHBIT);
for(i=100; i<=500; i+=100) {
memset2(cpt+i*dx, 0xff, j, cache);
}
flush(myPDEV->pjCachedScreen, myPDEV->MemorySize);
for(i=100; i<=500; i+=100) {
memset(cps+i*dx, 0x01, j);
}
memset2((myPDEV->pjScreen) + 40*dx, 0xff, (sizl.cx << myPDEV->ColorModeShift), NOCACHECTRL);
Sleep(3000);
memset2(myPDEV->pjCachedScreen, 0, myPDEV->MemorySize, TFLUSHBIT);
for(i=100; i<=500; i+=100) {
memcpy2(cpt+i*dx, linebuf, j, cache);
}
flush(myPDEV->pjCachedScreen, myPDEV->MemorySize);
for(i=100; i<=500; i+=100) {
memset(cps+i*dx, 0x01, j);
}
memset2((myPDEV->pjScreen) + 50*dx, 0xff, (sizl.cx << myPDEV->ColorModeShift), NOCACHECTRL);
Sleep(3000);
memset2(myPDEV->pjCachedScreen, 0, myPDEV->MemorySize, TFLUSHBIT);
for(i=100; i<=500; i+=100) {
memset2(cpt+i*dx, 0xff, j, cache);
}
for(i=100; i<=500; i+=100) {
memcpy2(cpt+(i+50)*dx+j, cpt+i*dx, j, cache);
}
flush(myPDEV->pjCachedScreen, myPDEV->MemorySize);
for(i=100; i<=550; i+=50) {
memset(cps+i*dx, 0x01, j*2);
}
memset2((myPDEV->pjScreen) + 60*dx, 0xff, (sizl.cx << myPDEV->ColorModeShift), NOCACHECTRL);
Sleep(3000);
memset2(myPDEV->pjCachedScreen, 0, myPDEV->MemorySize, TFLUSHBIT);
for(i=100; i<=500; i+=100) {
memset2(cpt+i*dx, 0xff, j, cache);
}
for(i=100; i<=500; i+=100) {
memcpy2(cpt+(i+50)*dx+j, cpt+i*dx, j, cache | SFLUSHBIT);
}
flush(myPDEV->pjCachedScreen, myPDEV->MemorySize);
for(i=100; i<=550; i+=50) {
memset(cps+i*dx, 0x01, j*2);
}
memset2((myPDEV->pjScreen) + 70*dx, 0xff, (sizl.cx << myPDEV->ColorModeShift), NOCACHECTRL);
Sleep(3000);
memset2(myPDEV->pjCachedScreen, 0, myPDEV->MemorySize, TFLUSHBIT);
}
}
#endif // ELSE MAXBANDWIDTH
}
#endif // INVESTIGATE
//
// The driver function table with all function index/address pairs
//
#if INVESTIGATE
#define HOOKS_BMF8BPP_TOP (HOOK_BITBLT | HOOK_COPYBITS | HOOK_STRETCHBLT | \
HOOK_TEXTOUT | HOOK_PAINT | HOOK_STROKEPATH | HOOK_FILLPATH | HOOK_STROKEANDFILLPATH)
#define HOOKS_BMF8BPP_PRO (HOOK_BITBLT | HOOK_COPYBITS | HOOK_STRETCHBLT | \
HOOK_TEXTOUT | HOOK_PAINT | HOOK_STROKEPATH | HOOK_FILLPATH | HOOK_STROKEANDFILLPATH)
#define HOOKS_BMF16BPP (HOOK_BITBLT | HOOK_COPYBITS | HOOK_STRETCHBLT | \
HOOK_TEXTOUT | HOOK_PAINT | HOOK_STROKEPATH | HOOK_FILLPATH | HOOK_STROKEANDFILLPATH)
#define HOOKS_BMF32BPP (HOOK_BITBLT | HOOK_COPYBITS | HOOK_STRETCHBLT | \
HOOK_TEXTOUT | HOOK_PAINT | HOOK_STROKEPATH | HOOK_FILLPATH | HOOK_STROKEANDFILLPATH)
#else // INVESTIGATE
#define HOOKS_BMF8BPP_TOP (HOOK_COPYBITS | HOOK_BITBLT | HOOK_TEXTOUT | HOOK_PAINT)
#define HOOKS_BMF8BPP_PRO (HOOK_COPYBITS | HOOK_BITBLT | HOOK_TEXTOUT)
#define HOOKS_BMF16BPP (HOOK_COPYBITS | HOOK_BITBLT | HOOK_TEXTOUT | HOOK_STRETCHBLT | HOOK_PAINT)
#define HOOKS_BMF32BPP (HOOK_COPYBITS | HOOK_BITBLT | HOOK_TEXTOUT | HOOK_STRETCHBLT | HOOK_PAINT)
#endif
#if INVESTIGATE
BOOL WDrvBitBlt(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
POINTL *pptlMask,
BRUSHOBJ *pbo,
POINTL *pptlBrush,
ROP4 rop4)
{
BOOL rc;
BOOL rcdrv;
BOOL docomparison;
BOOL srcinvolved;
LONG stat;
ULONG ropidx, brop4;
static BOOL ropovfmsg = FALSE;
static BOOL brushovfmsg = FALSE;
docomparison = (compare & dbgflg & FL_DRV_BITBLT) && breakcnt == 0 && ScreenBuf2;
if(paramcheck & FL_DRV_BITBLT) {
ULONG category, ui;
ULONG histidx = 0;
if(((rop4 & 0xc0) != ((rop4 & 0x30) << 2)) || ((rop4 & 0xc) != ((rop4 & 0x3) << 2))) srcinvolved = TRUE;
else
srcinvolved = FALSE;
if(srcinvolved) {
if(psoSrc->pvScan0 == (PVOID)ScreenBase)
histidx = 4;
else
histidx = 2;
} else
histidx = 0;
if(psoTrg->pvScan0 == (PVOID)ScreenBase)
histidx += 1;
ui = (prclTrg->right - prclTrg->left)/10;
if(ui >= MAX_WIDTH_STEP)
ui = MAX_WIDTH_STEP-1;
BitBltWidthHist[histidx][ui] += 1;
ui = (prclTrg->bottom - prclTrg->top)/10;
if(ui >= MAX_HEIGHT_STEP)
ui = MAX_HEIGHT_STEP-1;
BitBltHeightHist[histidx][ui] += 1;
/** BitBlt categories **
0: Not Hooked other reasons
1: Not Hooked because of unsupported operation
2: Not Hooked because Solid Brush is not supported
3: Not Hooked because Pattern Brush is not supported
4: Hooked other operations
5: Hooked SRC + DEST
6: Hooked PAT + DEST
7: Hooked SOLID + DEST
8: Hooked PTN fill
9: Hooked SOLID fill
************************/
category = 0; // default category
if(((rop4 & 0x0f) != ((rop4 & 0xf0)>>4)) || ((rop4 & 0x0f00) != ((rop4 & 0xf000)>>4))) { // Pattern involved?
if(pbo->iSolidColor == 0xFFFFFFFF)
brop4 = rop4 | 0xffff0000;
else {
brop4 = rop4 | 0x11110000;
for(ui=0; ui<MAX_BRUSH_ENTRY; ++ui) {
if(BitBltBrush[1][ui] == 0)
break;
if(BitBltBrush[0][ui] == pbo->iSolidColor) {
BitBltBrush[1][ui] += 1;
break;
}
}
if(ui == MAX_BRUSH_ENTRY) {
if(! brushovfmsg) {
DISPDBG((0,"### Solid Brush Table Overflow ###\n"));
brushovfmsg = TRUE;
}
} else {
if(BitBltBrush[1][ui] == 0) {
BitBltBrush[0][ui] = pbo->iSolidColor;
BitBltBrush[1][ui] = 1;
}
}
}
} else
brop4 = rop4;
for(ropidx=0; ropidx<MAX_ROP_ENTRY; ++ropidx) {
if(BitBltRop[1][ropidx] == 0)
break;
if(BitBltRop[0][ropidx] == brop4) {
BitBltRop[1][ropidx] += 1;
break;
}
}
if(ropidx == MAX_ROP_ENTRY) {
if(! ropovfmsg) {
DISPDBG((0,"### ROP4 Table Overflow ###\n"));
ropovfmsg = TRUE;
}
} else {
if(BitBltRop[1][ropidx] == 0) {
BitBltRop[0][ropidx] = brop4;
BitBltRop[1][ropidx] = 1;
}
BitBltRop[3][ropidx] += (prclTrg->right - prclTrg->left);
if(srcinvolved && psoSrc->pvScan0 == (PVOID)ScreenBase)
BitBltRop[4][ropidx] += 1;
ui = (prclTrg->right - prclTrg->left);
if(ui > 31)
ui = 31;
BitBltRop[ui+5][ropidx] += 1;
}
if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) {
if (psoTrg->pvScan0 != (PVOID)ScreenBase) {
goto DrvExitBitBlt;
}
switch(rop4) {
case 0x00000000: // (BLACKNESS)
case 0x0000FFFF: // (WHITENESS)
category = 9;
break;
case 0x0000F0F0: // (PATCOPY)
if (pbo->iSolidColor != 0xFFFFFFFF) {
category = 9;
} else
category = 8;
break;
case 0x00000F0F: // (NOTPATCOPY)
if (pbo->iSolidColor != 0xFFFFFFFF) {
category = 9;
} else
category = 3;
break;
case 0x00005555: // (Not Dest)
category = 7;
break;
case 0x00005a5a: // (PAT XOR DEST)
case 0x0000a5a5: // (INV PAT XOR DEST)
if (pbo->iSolidColor != 0xFFFFFFFF) {
category = 7;
} else
category = 6;
break;
case 0x0000a0a0: // (PAT XOR DEST)
case 0x00000a0a: // (INV PAT XOR DEST)
if (pbo->iSolidColor != 0xFFFFFFFF) {
category = 2;
} else
category = 6;
break;
case 0x0000b8b8:
if (pbo->iSolidColor != 0xFFFFFFFF) {
category = 4;
} else
category = 3;
break;
case 0x00006666:
case 0x00008888:
case 0x0000eeee:
case 0x0000bbbb:
case 0x00004444:
case 0x00001111:
case 0x00003333:
category = 5;
break;
default:
category = 1;
break;
}
} else {
category=0;
}
DrvExitBitBlt:
BitBltHist[category] += 1;
}
if((dumpparam & dbgflg & FL_DRV_BITBLT) && breakcnt == 0) {
DumpDecimal("[BitBlt parameter]", stat);
DumpSurfObj("Target surface object", psoTrg);
DumpSurfObj("Source surface object", psoSrc);
DumpSurfObj("Mask surface object", psoMask);
DumpClipObj("Clip object", pco);
DumpXlateObj("Xlate object", pxlo);
DumpRectl("Target rectangle", prclTrg);
DumpPointl("Source position", pptlSrc);
DumpPointl("Mask position", pptlMask);
DumpBrushObj("Brush object", pbo);
DumpPointl("Brush position", pptlBrush);
DumpKeyTable("Raster operation", rop4, bitbltoptbl, ROP_MAX);
}
if(docomparison)
SaveScreenMem(BEFORE_SCREEN, FileNumberBase);
if((usedrvfunc & FL_DRV_BITBLT) || docomparison) {
rc = rcdrv = DrvBitBlt(
psoTrg,
psoSrc,
psoMask,
pco,
pxlo,
prclTrg,
pptlSrc,
pptlMask,
pbo,
pptlBrush,
rop4);
if((paramcheck & FL_DRV_BITBLT) && ropidx != MAX_ROP_ENTRY)
BitBltRop[2][ropidx] += spentindrv;
}
if(docomparison && (donebydrv & FL_DRV_BITBLT)) {
SaveScreenMem(AFTER_DRV, FileNumberBase);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase);
}
if((useengfunc & FL_DRV_BITBLT) || (docomparison && (donebydrv & FL_DRV_BITBLT))) {
if(traseentry & dbgflg & FL_DRV_BITBLT)
DISPDBG((0,"+++ Entering EngBitBlt +++\n"));
if(breakentry & FL_DRV_BITBLT)
CountBreak();
CLOCKSTART((TRAP_BITBLT));
rc = EngBitBlt(
psoTrg,
psoSrc,
psoMask,
pco,
pxlo,
prclTrg,
pptlSrc,
pptlMask,
pbo,
pptlBrush,
rop4);
CLOCKEND((TRAP_BITBLT));
if((paramcheck & FL_DRV_BITBLT) && ropidx != MAX_ROP_ENTRY)
BitBltRop[2][ropidx] += spentindrv;
if(traseexit & dbgflg & FL_DRV_BITBLT)
DISPDBG((0,"--- Exiting EngBitBlt ---\n"));
if(breakexit & FL_DRV_BITBLT)
CountBreak();
}
if(docomparison && (donebydrv & FL_DRV_BITBLT)) {
if(rc != rcdrv) {
DISPDBG((0, "BitBlt return code unmatch\n"));
}
if((stat = CompareScreenMem(AFTER_DRV, FileNumberBase)) > 0) { // Result unmatch
SaveScreenMem(BEFORE_SCREEN, FileNumberBase); // Save after ENG result in first screen buf
RestoreScreenMem(AFTER_DRV, FileNumberBase); // Restore result of DRV to compare
DumpDecimal("### BitBlt result unmatch", stat);
DumpSurfObj("Target surface object", psoTrg);
DumpSurfObj("Source surface object", psoSrc);
DumpSurfObj("Mask surface object", psoMask);
DumpClipObj("Clip object", pco);
DumpXlateObj("Xlate object", pxlo);
DumpRectl("Target rectangle", prclTrg);
DumpPointl("Source position", pptlSrc);
DumpPointl("Mask position", pptlMask);
DumpBrushObj("Brush object", pbo);
DumpPointl("Brush position", pptlBrush);
DumpKeyTable("Raster operation", rop4, bitbltoptbl, ROP_MAX);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase); // Restore result of ENG to continue
FileNumberBase += 1;
}
}
return(rc);
}
BOOL WDrvStretchBlt(
SURFOBJ *psoDest,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
COLORADJUSTMENT *pca,
POINTL *pptlHTOrg,
RECTL *prclDest,
RECTL *prclSrc,
POINTL *pptlMask,
ULONG iMode)
{
BOOL rc;
BOOL rcdrv;
LONG stat;
BOOL docomparison;
docomparison = (compare & dbgflg & FL_DRV_STRTBIT) && breakcnt == 0 && ScreenBuf2;
if((dumpparam & dbgflg & FL_DRV_STRTBIT) && breakcnt == 0) {
DumpDecimal("[StretchBlt parameter]", stat);
DumpSurfObj("Target surface object", psoDest);
DumpSurfObj("Source surface object", psoSrc);
DumpSurfObj("Mask surface object", psoMask);
DumpClipObj("Clip object", pco);
DumpXlateObj("Xlate object", pxlo);
DumpColorAdjustment("Color adjustment", pca);
DumpPointl("Halftone brush position", pptlHTOrg);
DumpRectl("Target rectangle", prclDest);
DumpRectl("Source rectangle", prclSrc);
DumpPointl("Mask position", pptlMask);
DumpCombo("iMode", iMode);
}
if(docomparison)
SaveScreenMem(BEFORE_SCREEN, FileNumberBase);
if(docomparison || (usedrvfunc & FL_DRV_STRTBIT)) {
rcdrv = rc = DrvStretchBlt(
psoDest,
psoSrc,
psoMask,
pco,
pxlo,
pca,
pptlHTOrg,
prclDest,
prclSrc,
pptlMask,
iMode);
}
if(docomparison && (donebydrv & FL_DRV_STRTBIT)) {
SaveScreenMem(AFTER_DRV, FileNumberBase);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase);
}
if((useengfunc & FL_DRV_STRTBIT) || (docomparison && (donebydrv & FL_DRV_STRTBIT))) {
if(traseentry & dbgflg & FL_DRV_STRTBIT)
DISPDBG((0,"+++ Entering EngStretchBlt +++\n"));
if(breakentry & FL_DRV_STRTBIT)
CountBreak();
CLOCKSTART((TRAP_STRETCHBLT));
rc = EngStretchBlt(
psoDest,
psoSrc,
psoMask,
pco,
pxlo,
pca,
pptlHTOrg,
prclDest,
prclSrc,
pptlMask,
iMode);
CLOCKEND((TRAP_STRETCHBLT));
if(traseexit & dbgflg & FL_DRV_STRTBIT)
DISPDBG((0,"--- Exiting EngStretchBlt ---\n"));
if(breakexit & FL_DRV_STRTBIT)
CountBreak();
}
if(docomparison && (donebydrv & FL_DRV_STRTBIT)) {
if(rc != rcdrv) {
DISPDBG((0, "StretchBlt return code unmatch\n"));
}
if((stat = CompareScreenMem(AFTER_DRV, FileNumberBase)) > 0) { // Result unmatch
SaveScreenMem(BEFORE_SCREEN, FileNumberBase); // Save after ENG result in first screen buf
RestoreScreenMem(AFTER_DRV, FileNumberBase); // Restore result of DRV to compare
DumpDecimal("### StretchBlt result unmatch", stat);
DumpSurfObj("Target surface object", psoDest);
DumpSurfObj("Source surface object", psoSrc);
DumpSurfObj("Mask surface object", psoMask);
DumpClipObj("Clip object", pco);
DumpXlateObj("Xlate object", pxlo);
DumpColorAdjustment("Color adjustment", pca);
DumpPointl("Halftone brush position", pptlHTOrg);
DumpRectl("Target rectangle", prclDest);
DumpRectl("Source rectangle", prclSrc);
DumpPointl("Mask position", pptlMask);
DumpCombo("iMode", iMode);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase); // Restore result of ENG to continue
FileNumberBase += 1;
}
}
return(rc);
}
VOID SetTextRect(
ULONG width,
ULONG height,
ULONG index
)
{
ULONG ui;
ui = width/10;
if(ui >= MAX_WIDTH_STEP)
ui = MAX_WIDTH_STEP-1;
TextWidthHist[index][ui] += 1;
ui = height;
if(ui >= MAX_HEIGHT_STEP)
ui = MAX_HEIGHT_STEP-1;
TextHeightHist[index][ui] += 1;
}
BOOL WDrvTextOut(
SURFOBJ *pso,
STROBJ *pstro,
FONTOBJ *pfo,
CLIPOBJ *pco,
RECTL *prclExtra,
RECTL *prclOpaque,
BRUSHOBJ *pboFore,
BRUSHOBJ *pboOpaque,
POINTL *pptlOrg,
MIX mix)
{
BOOL rc;
BOOL rcdrv;
LONG stat;
RECTL *prectl;
BOOL docomparison;
LONG textperfidx;
docomparison = (compare & dbgflg & FL_DRV_TEXTOUT) && breakcnt == 0 && ScreenBuf2;
if(paramcheck & FL_DRV_TEXTOUT) {
ULONG ui, category, fontMax, StrCount, CharCount;
ULONG FontId, GlyphHandle;
ULONG GlyphCount;
PGLYPHPOS GlyphEnd;
ULONG GlyphHeight;
PGLYPHPOS GlyphList;
PGLYPHPOS GlyphStart;
ULONG GlyphWidth;
BOOL More;
RECTL OpaqueRectl, *extraRect;
GLYPHBITS *pgb;
textperfidx = -1;
if (pso->pvScan0 != (PVOID) ScreenBase) {
category = 0;
goto DevExitTextOut;
}
fontMax = pfo->cxMax;
if(fontMax >= MAX_FONT_SIZE)
fontMax = MAX_FONT_SIZE-1;
fontSize[fontMax] += 1;
if((pfo->flFontType & DEVICE_FONTTYPE) || (pso->lDelta & 0x03)) {
category = 1;
goto DevExitTextOut;
}
if((pstro->flAccel & (SO_HORIZONTAL | SO_VERTICAL | SO_REVERSED)) != SO_HORIZONTAL) {
category = 2;
goto DevExitTextOut;
}
if((pboFore->iSolidColor == 0xFFFFFFFFL) || ((prclOpaque != (PRECTL) NULL) && (pboOpaque->iSolidColor == 0xFFFFFFFFL))) {
category = 3;
goto DevExitTextOut;
}
if(pco != NULL && pco->iDComplexity != DC_TRIVIAL && pco->iDComplexity != DC_RECT) {
category = 4;
goto DevExitTextOut;
}
if(pfo->cxMax > 32) {
category = 5;
goto DevExitTextOut;
}
FontAccl[0] += 1;
if ((pstro->flAccel & SO_HORIZONTAL) != 0) {
FontAccl[1] += 1;
}
if ((pstro->flAccel & SO_VERTICAL) != 0) {
FontAccl[2] += 1;
}
if ((pstro->flAccel & SO_REVERSED) != 0) {
FontAccl[3] += 1;
}
if ((pstro->flAccel & SO_ZERO_BEARINGS) != 0) {
FontAccl[4] += 1;
}
if ((pstro->flAccel & SO_CHAR_INC_EQUAL_BM_BASE) != 0) {
FontAccl[5] += 1;
}
if ((pstro->flAccel & SO_MAXEXT_EQUAL_BM_SIDE) != 0) {
FontAccl[6] += 1;
}
if ((pstro->flAccel & SO_FLAG_DEFAULT_PLACEMENT) != 0) {
FontAccl[7] += 1;
}
FontId = pfo->iUniq;
for(ui=0; ui<FontTblMax; ++ui) {
if(FontId == FontIDTable[ui][0]) {
FontIDTable[ui][1] += 1;
break;
}
}
if(ui == FontTblMax && FontTblMax < MAX_FONT_ENTRY) {
FontIDTable[ui][0] = FontId;
FontIDTable[ui][1] = 1;
FontTblMax += 1;
}
//
// Check if the background and foreground can be draw at the same time.
//
if(prclOpaque == NULL)
category = 8;
else {
if(pstro->flAccel == SO_LTOR)
category = 6;
else
category = 8;
}
if(pco != NULL && pco->iDComplexity == DC_RECT)
category += 1;
textperfidx = category-6;
TextPerfByCtgry[textperfidx][0] += 1;
if (pstro->ulCharInc != 0) {
//
// The font is fixed pitch. Capture the glyph dimensions and
// compute the starting display address.
//
if (pstro->pgp == NULL) {
More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList);
} else {
GlyphCount = pstro->cGlyphs;
GlyphList = pstro->pgp;
More = FALSE;
}
pgb = GlyphList->pgdf->pgb;
GlyphWidth = pgb->sizlBitmap.cx;
GlyphHeight = pgb->sizlBitmap.cy;
StrCount = CharCount = 0;
do {
CharCount += GlyphCount;
GlyphEnd = &GlyphList[GlyphCount];
GlyphStart = GlyphList;
if(GlyphCount >= MAX_GLYPH_COUNT)
GlyphCount = MAX_GLYPH_COUNT-1;
GlyphCountTable[GlyphCount] += 1;
do {
GlyphHandle = (ULONG) (GlyphStart->hg);
for(ui=0; ui<GlyphTblMax; ++ui) {
if(GlyphHandle == GlyphHndlTable[ui][0]) {
GlyphHndlTable[ui][1] += 1;
break;
}
}
if(ui == GlyphTblMax && GlyphTblMax < MAX_GLYPH_HNDL_ENTRY) {
GlyphHndlTable[ui][0] = GlyphHandle;
GlyphHndlTable[ui][1] = 1;
GlyphTblMax += 1;
}
for(ui=0; ui<CacheTblMax; ++ui) {
if(FontId == CacheTable[ui][0] &&
GlyphHandle == CacheTable[ui][1]) {
CacheTable[ui][2] += 1;
break;
}
}
if(ui == CacheTblMax && CacheTblMax < MAX_CACHE_ENTRY) {
CacheTable[ui][0] = FontId;
CacheTable[ui][1] = GlyphHandle;
CacheTable[ui][2] = 1;
CacheTblMax += 1;
}
GlyphStart += 1;
} while (GlyphStart != GlyphEnd);
StrCount += 1;
if (More) {
More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList);
} else {
break;
}
}while (TRUE);
if(StrCount >= MAX_STROBJ_COUNT)
StrCount = MAX_STROBJ_COUNT-1;
StrObjCountTable[StrCount] += 1;
if(GlyphWidth >= MAX_FONT_SIZE)
GlyphWidth = MAX_FONT_SIZE-1;
if(GlyphHeight >= MAX_FONT_SIZE)
GlyphHeight = MAX_FONT_SIZE-1;
FontWidth[GlyphWidth] += CharCount;
FontHeight[GlyphHeight] += CharCount;
} else {
//
// The font is not fixed pitch. Compute the x and y values for
// each glyph individually.
//
category += 4;
StrCount = 0;
do {
More = STROBJ_bEnum(pstro, &GlyphCount, &GlyphList);
GlyphEnd = &GlyphList[GlyphCount];
GlyphStart = GlyphList;
if(GlyphCount >= MAX_GLYPH_COUNT)
GlyphCount = MAX_GLYPH_COUNT-1;
GlyphCountTable[GlyphCount] += 1;
do {
GlyphHandle = (ULONG) (GlyphStart->hg);
for(ui=0; ui<GlyphTblMax; ++ui) {
if(GlyphHandle == GlyphHndlTable[ui][0]) {
GlyphHndlTable[ui][1] += 1;
break;
}
}
if(ui == GlyphTblMax && GlyphTblMax < MAX_GLYPH_HNDL_ENTRY) {
GlyphHndlTable[ui][0] = GlyphHandle;
GlyphHndlTable[ui][1] = 1;
GlyphTblMax += 1;
}
for(ui=0; ui<CacheTblMax; ++ui) {
if(FontId == CacheTable[ui][0] &&
GlyphHandle == CacheTable[ui][1]) {
CacheTable[ui][2] += 1;
break;
}
}
if(ui == CacheTblMax && CacheTblMax < MAX_CACHE_ENTRY) {
CacheTable[ui][0] = FontId;
CacheTable[ui][1] = GlyphHandle;
CacheTable[ui][2] = 1;
CacheTblMax += 1;
}
pgb = GlyphStart->pgdf->pgb;
GlyphWidth = pgb->sizlBitmap.cx;
GlyphHeight = pgb->sizlBitmap.cy;
if(GlyphWidth >= MAX_FONT_SIZE)
GlyphWidth = MAX_FONT_SIZE-1;
if(GlyphHeight >= MAX_FONT_SIZE)
GlyphHeight = MAX_FONT_SIZE-1;
FontWidth[GlyphWidth] += 1;
FontHeight[GlyphHeight] += 1;
GlyphStart += 1;
} while(GlyphStart != GlyphEnd);
StrCount += 1;
} while(More);
if(StrCount >= MAX_STROBJ_COUNT)
StrCount = MAX_STROBJ_COUNT-1;
StrObjCountTable[StrCount] += 1;
}
if(prclOpaque != NULL) {
TextRect[0] += 1;
OpaqueRectl = *prclOpaque;
if(OpaqueRectl.top < pstro->rclBkGround.top) {
SetTextRect(OpaqueRectl.right-OpaqueRectl.left, pstro->rclBkGround.top-OpaqueRectl.top, 0);
TextRect[1] += 1;
OpaqueRectl.top = pstro->rclBkGround.top;
} else if(OpaqueRectl.top == pstro->rclBkGround.top) {
TextRect[2] += 1;
}
if(OpaqueRectl.bottom > pstro->rclBkGround.bottom) {
SetTextRect(OpaqueRectl.right-OpaqueRectl.left, OpaqueRectl.bottom-pstro->rclBkGround.bottom, 1);
TextRect[3] += 1;
OpaqueRectl.bottom = pstro->rclBkGround.bottom;
} else if(OpaqueRectl.bottom == pstro->rclBkGround.bottom) {
TextRect[4] += 1;
}
if(OpaqueRectl.left < pstro->rclBkGround.left) {
SetTextRect(pstro->rclBkGround.left-OpaqueRectl.left, OpaqueRectl.bottom-OpaqueRectl.top, 2);
TextRect[5] += 1;
} else if(OpaqueRectl.left == pstro->rclBkGround.left) {
TextRect[6] += 1;
}
if(OpaqueRectl.right > pstro->rclBkGround.right) {
SetTextRect(OpaqueRectl.right - pstro->rclBkGround.right, OpaqueRectl.bottom-OpaqueRectl.top, 3);
TextRect[7] += 1;
} else if(OpaqueRectl.right == pstro->rclBkGround.right) {
TextRect[8] += 1;
}
}
if(prclExtra != (PRECTL)NULL) {
extraRect = prclExtra;
while (extraRect->left != extraRect->right) {
SetTextRect(extraRect->right - extraRect->left, extraRect->bottom - extraRect->top, 4);
TextRect[9] += 1;
prclExtra += 1;
}
}
SetTextRect(pstro->rclBkGround.right - pstro->rclBkGround.left, pstro->rclBkGround.bottom - pstro->rclBkGround.top, 5);
if(pco != NULL & pco->iDComplexity == DC_RECT) {
TextClip[0] += 1;
if(pco->rclBounds.top == pstro->rclBkGround.top)
TextClip[1] += 1;
if(pco->rclBounds.bottom == pstro->rclBkGround.bottom)
TextClip[2] += 1;
if(pco->rclBounds.left == pstro->rclBkGround.left)
TextClip[3] += 1;
if(pco->rclBounds.right == pstro->rclBkGround.right)
TextClip[4] += 1;
}
DevExitTextOut:
TextOutHist[category] += 1;
} else {
textperfidx = -1;
}
if((dumpparam & dbgflg & FL_DRV_TEXTOUT) && breakcnt == 0) {
DumpDecimal("[TextOut parameter]", stat);
DumpSurfObj("Source surface object", pso);
DumpStrObj("String object", pstro);
DumpFontObj("Font object", pfo);
DumpClipObj("Clip object", pco);
DumpString("[Extra rectangle array]\n");
prectl = prclExtra;
while(prectl != NULL) {
if(prectl->left || prectl->top || prectl->right || prectl->bottom) {
DumpRectl(" ", prectl);
prectl += 1;
} else
break;
}
DumpRectl("Opaque rectangle", prclOpaque);
DumpBrushObj("Foreground brush object", pboFore);
DumpBrushObj("Opaque brush object", pboOpaque);
DumpPointl("Brush position", pptlOrg);
DumpMix("Fore & back mix mode", mix);
}
if(docomparison) {
SaveScreenMem(BEFORE_SCREEN, FileNumberBase);
SaveGlyphPos(pstro);
}
if(docomparison || (usedrvfunc & FL_DRV_TEXTOUT)) {
rcdrv = rc = DrvTextOut(
pso,
pstro,
pfo,
pco,
prclExtra,
prclOpaque,
pboFore,
pboOpaque,
pptlOrg,
mix);
if(textperfidx >= 0)
TextPerfByCtgry[textperfidx][1] += spentindrv;
}
if(docomparison && (donebydrv & FL_DRV_TEXTOUT)) {
RestoreGlyphPos(pstro);
SaveScreenMem(AFTER_DRV, FileNumberBase);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase);
SaveGlyphPos(pstro);
}
if((useengfunc & FL_DRV_TEXTOUT) || (docomparison && (donebydrv & FL_DRV_TEXTOUT))) {
if(traseentry & dbgflg & FL_DRV_TEXTOUT)
DISPDBG((0,"+++ Entering EngTextOut +++\n"));
if(breakentry & FL_DRV_TEXTOUT)
CountBreak();
CLOCKSTART((TRAP_TEXTOUT));
rc = EngTextOut(
pso,
pstro,
pfo,
pco,
prclExtra,
prclOpaque,
pboFore,
pboOpaque,
pptlOrg,
mix);
CLOCKEND((TRAP_TEXTOUT));
if(textperfidx >= 0)
TextPerfByCtgry[textperfidx][1] += spentindrv;
if(traseexit & dbgflg & FL_DRV_TEXTOUT)
DISPDBG((0,"--- Exiting EngTextOut ---\n"));
if(breakexit & FL_DRV_TEXTOUT)
CountBreak();
}
if(docomparison && (donebydrv & FL_DRV_TEXTOUT)) {
RestoreGlyphPos(pstro);
if(rc != rcdrv) {
DISPDBG((0, "TextOut return code unmatch\n"));
}
if((stat = CompareScreenMem(AFTER_DRV, FileNumberBase)) > 0) { // Result unmatch
SaveScreenMem(BEFORE_SCREEN, FileNumberBase); // Save after ENG result in first screen buf
RestoreScreenMem(AFTER_DRV, FileNumberBase); // Restore result of DRV to compare
DumpDecimal("### TextOut result unmatch", stat);
DumpSurfObj("Source surface object", pso);
DumpStrObj("String object", pstro);
DumpFontObj("Font object", pfo);
DumpClipObj("Clip object", pco);
DumpString("[Extra rectangle array]\n");
prectl = prclExtra;
while(prectl != NULL) {
if(prectl->left || prectl->top || prectl->right || prectl->bottom) {
DumpRectl(" ", prectl);
prectl += 1;
} else
break;
}
DumpRectl("Opaque rectangle", prclOpaque);
DumpBrushObj("Foreground brush object", pboFore);
DumpBrushObj("Opaque brush object", pboOpaque);
DumpPointl("Brush position", pptlOrg);
DumpMix("Fore & back mix mode", mix);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase); // Restore result of ENG to continue
FileNumberBase += 1;
}
}
return(rc);
}
BOOL WDrvStrokePath(
SURFOBJ *pso,
PATHOBJ *ppo,
CLIPOBJ *pco,
XFORMOBJ *pxo,
BRUSHOBJ *pbo,
POINTL *pptlBrushOrg,
LINEATTRS *plineattrs,
MIX mix)
{
BOOL rc;
BOOL rcdrv;
LONG stat;
BOOL docomparison;
docomparison = (compare & dbgflg & FL_DRV_STRKPATH) && breakcnt == 0 && ScreenBuf2;
if((dumpparam & dbgflg & FL_DRV_STRKPATH) && breakcnt == 0) {
DumpDecimal("[StrokePath parameter]", stat);
DumpSurfObj("Target surface object", pso);
DumpPathObj("Path object", ppo);
DumpClipObj("Clip object", pco);
DumpXformObj("Xform object", pxo);
DumpBrushObj("Brush object", pbo);
DumpPointl("Brush position", pptlBrushOrg);
DumpLineAttrs("Line attributes structure", plineattrs);
DumpMix("Brush & target mix mode", mix);
}
if(docomparison)
SaveScreenMem(BEFORE_SCREEN, FileNumberBase);
if(docomparison || (usedrvfunc & FL_DRV_STRKPATH)) {
rcdrv = rc = DrvStrokePath(
pso,
ppo,
pco,
pxo,
pbo,
pptlBrushOrg,
plineattrs,
mix);
}
if(docomparison && (donebydrv & FL_DRV_STRKPATH)) {
SaveScreenMem(AFTER_DRV, FileNumberBase);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase);
}
if((useengfunc & FL_DRV_STRKPATH) || (docomparison && (donebydrv & FL_DRV_STRKPATH))) {
if(traseentry & dbgflg & FL_DRV_STRKPATH)
DISPDBG((0,"+++ Entering EngStrokePath +++\n"));
if(breakentry & FL_DRV_STRKPATH)
CountBreak();
CLOCKSTART((TRAP_STROKEPATH));
rc = EngStrokePath(
pso,
ppo,
pco,
pxo,
pbo,
pptlBrushOrg,
plineattrs,
mix);
CLOCKEND((TRAP_STROKEPATH));
if(traseexit & dbgflg & FL_DRV_STRKPATH)
DISPDBG((0,"--- Exiting EngStrokePath ---\n"));
if(breakexit & FL_DRV_STRKPATH)
CountBreak();
}
if(docomparison && (donebydrv & FL_DRV_STRKPATH)) {
if(rc != rcdrv) {
DISPDBG((0, "StrokePath return code unmatch\n"));
}
if((stat = CompareScreenMem(AFTER_DRV, FileNumberBase)) > 0) { // Result unmatch
SaveScreenMem(BEFORE_SCREEN, FileNumberBase); // Save after ENG result in first screen buf
RestoreScreenMem(AFTER_DRV, FileNumberBase); // Restore result of DRV to compare
DumpDecimal("### StrokePath result unmatch", stat);
DumpSurfObj("Target surface object", pso);
DumpPathObj("Path object", ppo);
DumpClipObj("Clip object", pco);
DumpXformObj("Xform object", pxo);
DumpBrushObj("Brush object", pbo);
DumpPointl("Brush position", pptlBrushOrg);
DumpLineAttrs("Line attributes structure", plineattrs);
DumpMix("Brush & target mix mode", mix);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase); // Restore result of ENG to continue
FileNumberBase += 1;
}
}
return(rc);
}
BOOL WDrvFillPath(
SURFOBJ *pso,
PATHOBJ *ppo,
CLIPOBJ *pco,
BRUSHOBJ *pbo,
POINTL *pptlBrushOrg,
MIX mix,
FLONG flOptions)
{
BOOL rc;
BOOL rcdrv;
LONG stat;
BOOL docomparison;
docomparison = (compare & dbgflg & FL_DRV_FILLPATH) && breakcnt == 0 && ScreenBuf2;
if((dumpparam & dbgflg & FL_DRV_FILLPATH) && breakcnt == 0) {
DumpDecimal("[FillPath parameter]", stat);
DumpSurfObj("Target surface object", pso);
DumpPathObj("Path object", ppo);
DumpClipObj("Clip object", pco);
DumpBrushObj("Brush object", pbo);
DumpPointl("Brush position", pptlBrushOrg);
DumpMix("Pattern & target mix mode", mix);
DumpTable("Fill option", flOptions, fpstrtbl, FPSTR_MAX);
}
if(docomparison)
SaveScreenMem(BEFORE_SCREEN, FileNumberBase);
if(docomparison || (usedrvfunc & FL_DRV_FILLPATH)) {
rcdrv = rc = DrvFillPath(
pso,
ppo,
pco,
pbo,
pptlBrushOrg,
mix,
flOptions);
}
if(docomparison && (donebydrv & FL_DRV_FILLPATH)) {
SaveScreenMem(AFTER_DRV, FileNumberBase);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase);
}
if((useengfunc & FL_DRV_FILLPATH) || (docomparison && (donebydrv & FL_DRV_FILLPATH))) {
if(traseentry & dbgflg & FL_DRV_FILLPATH)
DISPDBG((0,"+++ Entering EngFillPath +++\n"));
if(breakentry & FL_DRV_FILLPATH)
CountBreak();
CLOCKSTART((TRAP_FILLPATH));
rc = EngFillPath(
pso,
ppo,
pco,
pbo,
pptlBrushOrg,
mix,
flOptions);
CLOCKEND((TRAP_FILLPATH));
if(traseexit & dbgflg & FL_DRV_FILLPATH)
DISPDBG((0,"--- Exiting EngFillPath ---\n"));
if(breakexit & FL_DRV_FILLPATH)
CountBreak();
}
if(docomparison && (donebydrv & FL_DRV_FILLPATH)) {
if(rc != rcdrv) {
DISPDBG((0, "FillPath return code unmatch\n"));
}
if((stat = CompareScreenMem(AFTER_DRV, FileNumberBase)) > 0) { // Result unmatch
SaveScreenMem(BEFORE_SCREEN, FileNumberBase); // Save after ENG result in first screen buf
RestoreScreenMem(AFTER_DRV, FileNumberBase); // Restore result of DRV to compare
DumpDecimal("### FillPath result unmatch", stat);
DumpSurfObj("Target surface object", pso);
DumpPathObj("Path object", ppo);
DumpClipObj("Clip object", pco);
DumpBrushObj("Brush object", pbo);
DumpPointl("Brush position", pptlBrushOrg);
DumpMix("Pattern & target mix mode", mix);
DumpTable("Fill option", flOptions, fpstrtbl, FPSTR_MAX);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase); // Restore result of ENG to continue
FileNumberBase += 1;
}
}
return(rc);
}
BOOL WDrvStrokeAndFillPath(
SURFOBJ *pso,
PATHOBJ *ppo,
CLIPOBJ *pco,
XFORMOBJ *pxo,
BRUSHOBJ *pboStroke,
LINEATTRS *plineattrs,
BRUSHOBJ *pboFill,
POINTL *pptlBrushOrg,
MIX mixFill,
FLONG flOptions)
{
BOOL rc;
BOOL rcdrv;
LONG stat;
BOOL docomparison;
docomparison = (compare & dbgflg & FL_DRV_STRKNFILL) && breakcnt == 0 && ScreenBuf2;
if((dumpparam & dbgflg & FL_DRV_STRKNFILL) && breakcnt == 0) {
DumpDecimal("[StrokeAndFillPath parameter]", stat);
DumpSurfObj("Target surface object", pso);
DumpPathObj("Path object", ppo);
DumpClipObj("Clip object", pco);
DumpXformObj("Xform object", pxo);
DumpBrushObj("Brush object for stroke", pboStroke);
DumpLineAttrs("Line attributes structure", plineattrs);
DumpBrushObj("Brush object for fill", pboFill);
DumpPointl("Brush position", pptlBrushOrg);
DumpMix("Fore & back mix mode", mixFill);
DumpTable("Fill option", flOptions, fpstrtbl, FPSTR_MAX);
}
if(docomparison)
SaveScreenMem(BEFORE_SCREEN, FileNumberBase);
if(docomparison || (usedrvfunc & FL_DRV_STRKNFILL)) {
rcdrv = rc = DrvStrokeAndFillPath(
pso,
ppo,
pco,
pxo,
pboStroke,
plineattrs,
pboFill,
pptlBrushOrg,
mixFill,
flOptions);
}
if(docomparison && (donebydrv & FL_DRV_STRKNFILL)) {
SaveScreenMem(AFTER_DRV, FileNumberBase);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase);
}
if((useengfunc & FL_DRV_STRKNFILL) || (docomparison && (donebydrv & FL_DRV_STRKNFILL))) {
if(traseentry & dbgflg & FL_DRV_STRKNFILL)
DISPDBG((0,"+++ Entering EngStrokeAndFillPath +++\n"));
if(breakentry & FL_DRV_STRKNFILL)
CountBreak();
CLOCKSTART((TRAP_STROKENFIL));
rc = EngStrokeAndFillPath(
pso,
ppo,
pco,
pxo,
pboStroke,
plineattrs,
pboFill,
pptlBrushOrg,
mixFill,
flOptions);
CLOCKEND((TRAP_STROKENFIL));
if(traseexit & dbgflg & FL_DRV_STRKNFILL)
DISPDBG((0,"--- Exiting EngStrokeAndFillPath ---\n"));
if(breakexit & FL_DRV_STRKNFILL)
CountBreak();
}
if(docomparison && (donebydrv & FL_DRV_STRKNFILL)) {
if(rc != rcdrv) {
DISPDBG((0, "StrokeAndFillPath return code unmatch\n"));
}
if((stat = CompareScreenMem(AFTER_DRV, FileNumberBase)) > 0) { // Result unmatch
SaveScreenMem(BEFORE_SCREEN, FileNumberBase); // Save after ENG result in first screen buf
RestoreScreenMem(AFTER_DRV, FileNumberBase); // Restore result of DRV to compare
DumpDecimal("### StrokeAndFillPath result unmatch", stat);
DumpSurfObj("Target surface object", pso);
DumpPathObj("Path object", ppo);
DumpClipObj("Clip object", pco);
DumpXformObj("Xform object", pxo);
DumpBrushObj("Brush object for stroke", pboStroke);
DumpLineAttrs("Line attributes structure", plineattrs);
DumpBrushObj("Brush object for fill", pboFill);
DumpPointl("Brush position", pptlBrushOrg);
DumpMix("Fore & back mix mode", mixFill);
DumpTable("Fill option", flOptions, fpstrtbl, FPSTR_MAX);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase); // Restore result of ENG to continue
FileNumberBase += 1;
}
}
return(rc);
}
BOOL WDrvPaint(
SURFOBJ *pso,
CLIPOBJ *pco,
BRUSHOBJ *pbo,
POINTL *pptlBrushOrg,
MIX mix)
{
BOOL rc;
BOOL rcdrv;
LONG stat;
BOOL docomparison;
docomparison = (compare & dbgflg & FL_DRV_PAINT) && breakcnt == 0 && ScreenBuf2;
if(paramcheck & FL_DRV_PAINT) {
ULONG category, index, op, clip, ui, ClipRegions;
BOOL More;
if((index = mix & 0xf) != (mix >> 8))
category = 4;
else {
switch(op = gaMix[index]) {
case 0x00:
case 0xff:
category = 0;
break;
case 0xf0:
if(pbo->iSolidColor == 0xffffffff) {
category = 1;
index = 17;
} else
category = 0;
break;
case 0x0f:
if(pbo->iSolidColor == 0xffffffff) {
category = 4;
index = 18;
} else
category = 0;
break;
case 0x55:
category = 2;
break;
case 0x5a:
if(pbo->iSolidColor == 0xffffffff) {
category = 3;
index = 16;
} else
category = 2;
break;
case 0xa5:
if(pbo->iSolidColor == 0xffffffff) {
category = 3;
index = 19;
} else
category = 2;
break;
default:
category = 4;
}
PaintOp[index] += 1;
}
PaintCategories[category] += 1;
if(category <= 3) {
ui = (pco->rclBounds.right - pco->rclBounds.left)/10;
if(ui >= MAX_PAINT_BOUNDS_ENTRY)
ui = MAX_PAINT_BOUNDS_ENTRY-1;
PaintBounds[category][ui] += 1;
if(pco && pco->iDComplexity == DC_COMPLEX) {
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, PAINT_RECT_LIMIT);
for(clip=1; clip < MAX_PAINT_CLIP_ENTRY-1; ++clip) {
More = CLIPOBJ_bEnum(pco, sizeof(PaintClipEnum), (PVOID)&PaintClipEnum);
for (ClipRegions=0; ClipRegions<PaintClipEnum.c; ClipRegions++) {
ui = PaintClipEnum.arcl[ClipRegions].bottom - PaintClipEnum.arcl[ClipRegions].top;
if(ui >= 10)
ui = ui/10 + 9;
if(ui >= MAX_PAINT_HEIGHT_ENTRY)
ui = MAX_PAINT_HEIGHT_ENTRY-1;
PaintHeight[category][ui] += 1;
ui = PaintClipEnum.arcl[ClipRegions].right - PaintClipEnum.arcl[ClipRegions].left;
ui = ui/10;
if(ui >= MAX_PAINT_WIDTH_ENTRY)
ui = MAX_PAINT_WIDTH_ENTRY-1;
PaintWidth[category][ui] += 1;
}
if(! More)
break;
}
PaintClips[category][clip] += 1;
} else {
PaintClips[category][0] += 1;
}
}
}
if((dumpparam & dbgflg & FL_DRV_PAINT) && breakcnt == 0) {
DumpDecimal("[Paint parameter]", stat);
DumpSurfObj("Target surface object", pso);
DumpClipObj("Clip object", pco);
DumpBrushObj("Brush object", pbo);
DumpPointl("Brush position", pptlBrushOrg);
DumpMix("Fore & back mix mode", mix);
}
if(docomparison)
SaveScreenMem(BEFORE_SCREEN, FileNumberBase);
if(docomparison || (usedrvfunc & FL_DRV_PAINT)) {
rcdrv = rc = DrvPaint(
pso,
pco,
pbo,
pptlBrushOrg,
mix);
}
if(docomparison && (donebydrv & FL_DRV_PAINT)) {
SaveScreenMem(AFTER_DRV, FileNumberBase);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase);
}
if((useengfunc & FL_DRV_PAINT) || (docomparison && (donebydrv & FL_DRV_PAINT))) {
if(traseentry & dbgflg & FL_DRV_PAINT)
DISPDBG((0,"+++ Entering EngPaint +++\n"));
if(breakentry & FL_DRV_PAINT)
CountBreak();
CLOCKSTART((TRAP_PAINT));
rc = EngPaint(
pso,
pco,
pbo,
pptlBrushOrg,
mix);
CLOCKEND((TRAP_PAINT));
if(traseexit & dbgflg & FL_DRV_PAINT)
DISPDBG((0,"--- Exiting EngPaint ---\n"));
if(breakexit & FL_DRV_PAINT)
CountBreak();
}
if(docomparison && (donebydrv & FL_DRV_PAINT)) {
if(rc != rcdrv) {
DISPDBG((0, "Paint return code unmatch\n"));
}
if((stat = CompareScreenMem(AFTER_DRV, FileNumberBase)) > 0) { // Result unmatch
SaveScreenMem(BEFORE_SCREEN, FileNumberBase); // Save after ENG result in first screen buf
RestoreScreenMem(AFTER_DRV, FileNumberBase); // Restore result of DRV to compare
DumpDecimal("### Paint result unmatch", stat);
DumpSurfObj("Target surface object", pso);
DumpClipObj("Clip object", pco);
DumpBrushObj("Brush object", pbo);
DumpPointl("Brush position", pptlBrushOrg);
DumpMix("Fore & back mix mode", mix);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase); // Restore result of ENG to continue
FileNumberBase += 1;
}
}
return(rc);
}
BOOL WDrvCopyBits(
SURFOBJ *psoDest,
SURFOBJ *psoSrc,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclDest,
POINTL *pptlSrc)
{
BOOL rc;
BOOL rcdrv;
LONG stat;
BOOL docomparison;
docomparison = (compare & dbgflg & FL_DRV_COPYBIT) && breakcnt == 0 && ScreenBuf2;
if(paramcheck & FL_DRV_COPYBIT) {
ULONG category, ui, uj;
ULONG histidx = 0;
if(psoSrc->pvScan0 == (PVOID)ScreenBase)
histidx = 2;
else
histidx = 0;
if(psoDest->pvScan0 == (PVOID)ScreenBase)
histidx += 1;
ui = (prclDest->right - prclDest->left)/10;
if(ui >= MAX_WIDTH_STEP)
ui = MAX_WIDTH_STEP-1;
CopyBitWidthHist[histidx][ui] += 1;
uj = (prclDest->bottom - prclDest->top)/10;
if(uj >= MAX_HEIGHT_STEP)
uj = MAX_HEIGHT_STEP-1;
CopyBitHeightHist[histidx][uj] += 1;
if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) {
if (psoDest->pvScan0 != (PVOID)ScreenBase) {
category=1;
goto DevExitCopyBits;
}
if (psoSrc->pvScan0 != (PVOID)ScreenBase) {
category=2;
} else {
category=6;
}
if (pco != (CLIPOBJ *)NULL) {
switch(pco->iDComplexity) {
case DC_TRIVIAL:
break;
case DC_RECT:
category += 1;
break;
case DC_COMPLEX:
category += 2;
break;
default:
category += 3;
}
}
goto DevExitCopyBits;
} else {
category=0;
}
DevExitCopyBits:
CopyBitsHist[category] += 1;
}
if((dumpparam & dbgflg & FL_DRV_COPYBIT) && breakcnt == 0) {
DumpDecimal("[CopyBits parameter]", stat);
DumpSurfObj("Target surface object", psoDest);
DumpSurfObj("Source surface object", psoSrc);
DumpClipObj("Clip object", pco);
DumpXlateObj("Xlate object", pxlo);
DumpRectl("Target rectangle", prclDest);
DumpPointl("Source position", pptlSrc);
}
if(docomparison)
SaveScreenMem(BEFORE_SCREEN, FileNumberBase);
if(docomparison || (usedrvfunc & FL_DRV_COPYBIT)) {
rcdrv = rc = DrvCopyBits(
psoDest,
psoSrc,
pco,
pxlo,
prclDest,
pptlSrc);
}
if(docomparison && (donebydrv & FL_DRV_COPYBIT)) {
SaveScreenMem(AFTER_DRV, FileNumberBase);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase);
}
if((useengfunc & FL_DRV_COPYBIT) || (docomparison && (donebydrv & FL_DRV_COPYBIT))) {
if(traseentry & dbgflg & FL_DRV_COPYBIT)
DISPDBG((0,"+++ Entering EngCopyBits +++\n"));
if(breakentry & FL_DRV_COPYBIT)
CountBreak();
CLOCKSTART((TRAP_COPYBITS));
rc = EngCopyBits(
psoDest,
psoSrc,
pco,
pxlo,
prclDest,
pptlSrc);
CLOCKEND((TRAP_COPYBITS));
if(traseexit & dbgflg & FL_DRV_COPYBIT)
DISPDBG((0,"--- Exiting EngCopyBits ---\n"));
if(breakexit & FL_DRV_COPYBIT)
CountBreak();
}
if(docomparison && (donebydrv & FL_DRV_COPYBIT)) {
if(rc != rcdrv) {
DISPDBG((0, "CopyBits return code unmatch\n"));
}
if((stat = CompareScreenMem(AFTER_DRV, FileNumberBase)) > 0) { // Result unmatch
SaveScreenMem(BEFORE_SCREEN, FileNumberBase); // Save after ENG result in first screen buf
RestoreScreenMem(AFTER_DRV, FileNumberBase); // Restore result of DRV to compare
DumpDecimal("### CopyBits result unmatch", stat);
DumpSurfObj("Target surface object", psoDest);
DumpSurfObj("Source surface object", psoSrc);
DumpClipObj("Clip object", pco);
DumpXlateObj("Xlate object", pxlo);
DumpRectl("Target rectangle", prclDest);
DumpPointl("Source position", pptlSrc);
RestoreScreenMem(BEFORE_SCREEN, FileNumberBase); // Restore result of ENG to continue
FileNumberBase += 1;
}
}
return(rc);
}
LONG
SaveScreenMem(
ULONG FileCategory,
ULONG FileNumber
)
{
switch(FileCategory) {
case 0:
if(ScreenBuf1 != 0) {
memcpy2(ScreenBuf1, myPDEV->pjScreen, ScreenMemory, 0);
return (0);
}
break;
case 1:
if(ScreenBuf2 != 0) {
memcpy2(ScreenBuf2, myPDEV->pjScreen, ScreenMemory, 0);
return (0);
}
break;
}
return (-1);
}
LONG
SaveGlyphPos(
STROBJ *pstro
)
{
ULONG i;
LONG count, *lp;
GLYPHPOS *pgp;
count = 0;
if(pstro && pstro->pgp) {
lp = (PLONG) linebuf;
for(i=0; i<pstro->cGlyphs; ++i) {
if((pgp = &(pstro->pgp[i])) == NULL)
continue;
if(count > BUFSIZE/sizeof(LONG) - 4) {
DISPDBG((0,"### SaveGlyPos buffer overflow ###\n"));
continue;
}
*lp++ = (ULONG) pgp->hg;
*lp++ = (ULONG) pgp->pgdf;
*lp++ = pgp->ptl.x;
*lp++ = pgp->ptl.y;
count += 4;
}
}
return (count/4);
}
LONG
RestoreGlyphPos(
STROBJ *pstro
)
{
ULONG i;
LONG count, *lp;
GLYPHPOS *pgp;
count = 0;
if(pstro && pstro->pgp) {
lp = (PLONG) linebuf;
for(i=0; i<pstro->cGlyphs; ++i) {
if((pgp = (&pstro->pgp[i])) == NULL)
continue;
if(count > BUFSIZE/sizeof(LONG) - 4) {
continue;
}
(ULONG) pgp->hg = *lp++;
(ULONG) pgp->pgdf = *lp++;
pgp->ptl.x = *lp++;
pgp->ptl.y = *lp++;
count += 4;
}
}
return (count/4);
}
LONG
RestoreScreenMem(
ULONG FileCategory,
ULONG FileNumber
)
{
switch(FileCategory) {
case 0:
if(ScreenBuf1 != 0) {
memcpy2(myPDEV->pjScreen, ScreenBuf1, ScreenMemory, 0);
return (0);
}
break;
case 1:
if(ScreenBuf2 != 0) {
memcpy2(myPDEV->pjScreen, ScreenBuf2, ScreenMemory, 0);
return (0);
}
break;
}
return (-1);
}
LONG
CompareScreenMem(
ULONG FileCategory,
ULONG FileNumber
)
{
LONG i, pos;
ULONG imgwidth;
PBYTE ScreenBuf;
PUCHAR pb1, pb2;
switch(FileCategory) {
case 0:
if(ScreenBuf1 != 0) {
ScreenBuf = ScreenBuf1;
} else {
return(0);
}
break;
case 1:
if(ScreenBuf2 != 0) {
ScreenBuf = ScreenBuf2;
} else {
return(0);
}
break;
default:
return(0);
}
imgwidth = (myPDEV->cxScreen) << (myPDEV->ColorModeShift);
for(i=(myPDEV->cyScreen)-1; i>=0; --i) {
pb1 = (myPDEV->pjScreen) + i * (myPDEV->lDeltaScreen);
pb2 = ScreenBuf + i * (myPDEV->lDeltaScreen);
if((pos = memcmp2(pb2, pb1, imgwidth)) >= 0) {
break;
}
}
if(i < 0) {
DISPDBG((1,"... Screen compare %u O.K. ...\r", ++comparecount));
return (0);
} else {
DISPDBG((0,"### Screen Compare error line %d dot %d ###\n",
i+1, (pos >> (myPDEV->ColorModeShift))+1));
return (i+1);
}
}
DRVFN gadrvfn[] = {
{ INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
{ INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
{ INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
{ INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
{ INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
{ INDEX_DrvAssertMode, (PFN) DrvAssertMode },
{ INDEX_DrvStrokePath, (PFN) WDrvStrokePath },
{ INDEX_DrvFillPath, (PFN) WDrvFillPath },
{ INDEX_DrvStrokeAndFillPath, (PFN) WDrvStrokeAndFillPath },
{ INDEX_DrvPaint, (PFN) WDrvPaint },
{ INDEX_DrvTextOut, (PFN) WDrvTextOut },
{ INDEX_DrvBitBlt, (PFN) WDrvBitBlt },
{ INDEX_DrvCopyBits, (PFN) WDrvCopyBits },
{ INDEX_DrvStretchBlt, (PFN) WDrvStretchBlt },
// { INDEX_DrvSynchronize, (PFN) DrvSynchronize },
{ INDEX_DrvDitherColor, (PFN) DrvDitherColor },
// { INDEX_DrvMovePointer, (PFN) DrvMovePointer },
{ INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape },
{ INDEX_DrvGetModes, (PFN) DrvGetModes },
{ INDEX_DrvSetPalette, (PFN) DrvSetPalette },
{ INDEX_DrvRealizeBrush, (PFN) DrvRealizeBrush }
// { INDEX_DrvSaveScreenBits, (PFN) DrvSaveScreenBits },
// { INDEX_DrvDestroyFont, (PFN) DrvDestroyFont }
};
#else // INVESTIGATE
DRVFN gadrvfn[] = {
{ INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
{ INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
{ INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
{ INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
{ INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
{ INDEX_DrvAssertMode, (PFN) DrvAssertMode },
// { INDEX_DrvStrokePath, (PFN) DrvStrokePath },
// { INDEX_DrvFillPath, (PFN) DrvFillPath },
// { INDEX_DrvStrokeAndFillPath, (PFN) DrvStrokeAndFillPath },
{ INDEX_DrvPaint, (PFN) DrvPaint },
{ INDEX_DrvTextOut, (PFN) DrvTextOut },
{ INDEX_DrvBitBlt, (PFN) DrvBitBlt },
{ INDEX_DrvCopyBits, (PFN) DrvCopyBits },
{ INDEX_DrvStretchBlt, (PFN) DrvStretchBlt },
// { INDEX_DrvSynchronize, (PFN) DrvSynchronize },
{ INDEX_DrvDitherColor, (PFN) DrvDitherColor },
// { INDEX_DrvMovePointer, (PFN) DrvMovePointer },
{ INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape },
{ INDEX_DrvGetModes, (PFN) DrvGetModes },
{ INDEX_DrvSetPalette, (PFN) DrvSetPalette },
{ INDEX_DrvRealizeBrush, (PFN) DrvRealizeBrush }
// { INDEX_DrvSaveScreenBits, (PFN) DrvSaveScreenBits },
// { INDEX_DrvDestroyFont, (PFN) DrvDestroyFont }
};
#endif // INVESTIGATE
/******************************Public*Routine******************************\
* DrvDisableDriver
*
* Tells the driver it is being disabled. Release any resources allocated in
* DrvEnableDriver.
*
\**************************************************************************/
VOID DrvDisableDriver(VOID)
{
#if INVESTIGATE
if(traseentry & FL_DRV_DISBLDRIVER)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvDisableDriver +++\n"));
if(breakentry & FL_DRV_DISBLDRIVER)
EngDebugBreak();
#endif
#if INVESTIGATE
if(traseexit & FL_DRV_DISBLDRIVER)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvDisableDriver ---\n"));
if(breakexit & FL_DRV_DISBLDRIVER)
EngDebugBreak();
#endif
return;
}
/******************************Public*Routine******************************\
* DrvEnableDriver
*
* Enables the driver by retrieving the drivers function table and version.
*
\**************************************************************************/
BOOL DrvEnableDriver(
ULONG iEngineVersion,
ULONG cj,
PDRVENABLEDATA pded)
{
// Engine Version is passed down so future drivers can support previous
// engine versions. A next generation driver can support both the old
// and new engine conventions if told what version of engine it is
// working with. For the first version the driver does nothing with it.
#if INVESTIGATE
if(traseentry & FL_DRV_ENBLDRIVER)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvEnableDriver +++\n"));
if(breakentry & FL_DRV_ENBLDRIVER)
EngDebugBreak();
InitializeTable();
#endif
// Fill in as much as we can.
if (cj >= sizeof(DRVENABLEDATA))
pded->pdrvfn = gadrvfn;
if (cj >= (sizeof(ULONG) * 2))
pded->c = sizeof(gadrvfn) / sizeof(DRVFN);
// DDI version this driver was targeted for is passed back to engine.
// Future graphic's engine may break calls down to old driver format.
if (cj >= sizeof(ULONG))
pded->iDriverVersion = DDI_DRIVER_VERSION;
#if INVESTIGATE
if(traseexit & FL_DRV_ENBLDRIVER)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvEnableDriver ---\n"));
if(breakexit & FL_DRV_ENBLDRIVER)
EngDebugBreak();
#endif
return(TRUE);
}
/******************************Public*Routine******************************\
* DrvEnablePDEV
*
* DDI function, Enables the Physical Device.
*
* Return Value: device handle to pdev.
*
\**************************************************************************/
DHPDEV DrvEnablePDEV(
DEVMODEW *pDevmode, // Pointer to DEVMODE
PWSTR pwszLogAddress, // Logical address
ULONG cPatterns, // number of patterns
HSURF *ahsurfPatterns, // return standard patterns
ULONG cjGdiInfo, // Length of memory pointed to by pGdiInfo
ULONG *pGdiInfo, // Pointer to GdiInfo structure
ULONG cjDevInfo, // Length of following PDEVINFO structure
DEVINFO *pDevInfo, // physical device information structure
HDEV hdev, // HDEV, used for callbacks
PWSTR pwszDeviceName, // DeviceName - not used
HANDLE hDriver) // Handle to base driver
{
GDIINFO GdiInfo;
DEVINFO DevInfo;
PPDEV ppdev = (PPDEV) NULL;
#if INVESTIGATE
if(traseentry & FL_DRV_ENBLPDEV)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvEnablePDEV +++\n"));
if(breakentry & FL_DRV_ENBLPDEV)
EngDebugBreak();
#endif
// Allocate a physical device structure.
ppdev = (PPDEV) EngAllocMem(FL_ZERO_MEMORY, sizeof(PDEV), ALLOC_TAG);
if (ppdev == (PPDEV) NULL)
{
DISPDBG((0,"### Exiting DrvEnablePDEV due to EngAllocMem failure ###\n"));
return((DHPDEV) 0);
}
// Save the screen handle in the PDEV.
ppdev->hDriver = hDriver;
// Get the current screen mode information. Set up device caps and devinfo.
if (!bInitPDEV(ppdev, pDevmode, &GdiInfo, &DevInfo))
{
DISPDBG((0,"DISP DrvEnablePDEV failed bInitPDEV\n"));
goto error_free;
}
// Initialize the cursor information.
/******* No support for the pointer *********
if (!bInitPointer(ppdev, &DevInfo))
{
// Not a fatal error...
DISPDBG((0,"DISP DrvEnablePDEV failed bInitPointer\n"));
}
********************************************/
ppdev->pPointerAttributes = (PVIDEO_POINTER_ATTRIBUTES) NULL;
ppdev->cjPointerAttributes = 0; // initialized in screen.c
ppdev->PointerCapabilities.Flags = 0;
// Initialize palette information.
if (!bInitPaletteInfo(ppdev, &DevInfo))
{
DISPDBG((0,"DISP DrvEnableSurface failed bInitPalette\n"));
goto error_free;
}
// Copy the devinfo into the engine buffer.
memcpy(pDevInfo, &DevInfo, min(sizeof(DEVINFO), cjDevInfo));
// Set the pdevCaps with GdiInfo we have prepared to the list of caps for this
// pdev.
memcpy(pGdiInfo, &GdiInfo, min(cjGdiInfo, sizeof(GDIINFO)));
DISPDBG((1, "PDEV CREATED %x\n", ppdev));
#if INVESTIGATE
InitTable = TRUE; // Reset statistics table
if(traseexit & FL_DRV_ENBLPDEV)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvEnablePDEV ---\n"));
if(breakexit & FL_DRV_ENBLPDEV)
EngDebugBreak();
#endif
return((DHPDEV) ppdev);
// Error case for failure.
error_free:
EngFreeMem(ppdev);
DISPDBG((0,"### Exiting DrvEnablePDEV with error ###\n"));
return((DHPDEV) 0);
}
/******************************Public*Routine******************************\
* DrvCompletePDEV
*
* Store the HPDEV, the engines handle for this PDEV, in the DHPDEV.
*
\**************************************************************************/
VOID DrvCompletePDEV(
DHPDEV dhpdev,
HDEV hdev)
{
#if INVESTIGATE
if(traseentry & FL_DRV_CMPLTPDEV)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvCompletePDEV +++\n"));
if(breakentry & FL_DRV_CMPLTPDEV)
EngDebugBreak();
#endif
((PPDEV) dhpdev)->hdevEng = hdev;
#if INVESTIGATE
if(traseexit & FL_DRV_CMPLTPDEV)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvCompletePDEV ---\n"));
if(breakexit & FL_DRV_CMPLTPDEV)
EngDebugBreak();
#endif
}
/******************************Public*Routine******************************\
* DrvDisablePDEV
*
* Release the resources allocated in DrvEnablePDEV. If a surface has been
* enabled DrvDisableSurface will have already been called.
*
\**************************************************************************/
VOID DrvDisablePDEV(
DHPDEV dhpdev)
{
#if INVESTIGATE
if(traseentry & FL_DRV_DISBLPDEV)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvDesablePDEV +++\n"));
if(breakentry & FL_DRV_DISBLPDEV)
EngDebugBreak();
#endif
DISPDBG((1, "--- Disable PDEV %x, myPDEV = %x ---\n", dhpdev, myPDEV));
if(dhpdev == (DHPDEV)myPDEV) {
DISPDBG((0, "### myPDEV %x is disabled\n", dhpdev));
myPDEV = NULL;
}
vDisablePalette((PPDEV) dhpdev);
EngFreeMem(dhpdev);
#if BUG_5737_WORKAROUND
DisplayModeChanged();
#endif
#if INVESTIGATE
if(traseexit & FL_DRV_DISBLPDEV)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvDisablePDEV ---\n"));
if(breakexit & FL_DRV_DISBLPDEV)
EngDebugBreak();
#endif
}
/******************************Public*Routine******************************\
* DrvEnableSurface
*
* Enable the surface for the device. Hook the calls this driver supports.
*
* Return: Handle to the surface if successful, 0 for failure.
*
\**************************************************************************/
HSURF DrvEnableSurface(
DHPDEV dhpdev)
{
PPDEV ppdev;
HSURF hsurf;
SIZEL sizl;
FLONG flHooks;
#if INVESTIGATE
if(traseentry & FL_DRV_ENBLSURF)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvEnableSurface +++\n"));
if(breakentry & FL_DRV_ENBLSURF)
EngDebugBreak();
#endif
// Create engine bitmap around frame buffer.
ppdev = (PPDEV) dhpdev;
if (!bInitSURF(ppdev, TRUE))
{
DISPDBG((0,"### Exiting DrvEnableSurface due to bInitSURF failure ###\n"));
return(FALSE);
}
sizl.cx = ppdev->cxScreen;
sizl.cy = ppdev->cyScreen;
switch (ppdev->ulBitCount)
{
case 8:
if (!bInit256ColorPalette(ppdev)) {
DISPDBG((0,"### Exiting DrvEnableSurface due to failure in initializing the 8bpp palette ###\n"));
return(FALSE);
}
ppdev->iBitmapFormat = BMF_8BPP;
if(ppdev->ModelID == POWER_PRO)
flHooks = (FLONG) HOOKS_BMF8BPP_PRO;
else
flHooks = (FLONG) HOOKS_BMF8BPP_TOP;
break;
case 16:
ppdev->iBitmapFormat = BMF_16BPP;
flHooks = (FLONG) HOOKS_BMF16BPP;
break;
case 32:
ppdev->iBitmapFormat = BMF_32BPP;
flHooks = (FLONG) HOOKS_BMF32BPP;
break;
default:
DISPDBG((0,"### Exiting DrvEnableSurface due to ulBitCount invalid ###\n"));
return FALSE;
}
DISPDBG((1,"Creating Bitmap %d X %d Step %d, %x, %08x\n",
sizl.cx, sizl.cy, ppdev->lDeltaScreen, ppdev->iBitmapFormat, ppdev->pjScreen));
#if FULLCACHE
if(ppdev->VRAMcacheflg == 0) { // Couldn't find DBAT mapping cached VRAM
flHooks = 0;
}
hsurf = (HSURF) EngCreateBitmap(sizl,
ppdev->lDeltaScreen,
ppdev->iBitmapFormat,
(ppdev->lDeltaScreen > 0) ? BMF_TOPDOWN : 0,
(PVOID) (ppdev->pjCachedScreen));
#else // FULLCACHE
hsurf = (HSURF) EngCreateBitmap(sizl,
ppdev->lDeltaScreen,
ppdev->iBitmapFormat,
(ppdev->lDeltaScreen > 0) ? BMF_TOPDOWN : 0,
(PVOID) (ppdev->pjScreen));
#endif
if (hsurf == (HSURF) 0)
{
DISPDBG((0,"### Exiting DrvEnableSurface due to EngCreateBitmap failure ###\n"));
return(FALSE);
}
if (!EngAssociateSurface(hsurf, ppdev->hdevEng, flHooks))
{
DISPDBG((0,"### Exiting DrvEnableSurface due to EngAssociateSurface failure ###\n"));
EngDeleteSurface(hsurf);
return(FALSE);
}
ppdev->hsurfEng = hsurf;
#if INVESTIGATE
{
VIDEO_PUBLIC_ACCESS_RANGES VideoAccessRange;
DWORD ReturnedDataLength;
ppdev->TscStatusReg = NULL;
if(ppdev->ModelID != POWER_PRO) {
if (EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES,
NULL, // input buffer
0,
&VideoAccessRange, // output buffer
sizeof(VideoAccessRange),
&ReturnedDataLength)) {
DISPDBG((0,"### PSIDISP.DLL: VIDEO PUBLIC ACCESS RANGE ERROR ###\n"));
} else {
ppdev->TscStatusReg = (UCHAR*) VideoAccessRange.VirtualAddress;
}
}
}
#endif
#if INVESTIGATE
if(traseexit & FL_DRV_ENBLSURF)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvEnableSurface ---\n"));
if(breakexit & FL_DRV_ENBLSURF)
EngDebugBreak();
#endif
return(hsurf);
}
/******************************Public*Routine******************************\
* DrvDisableSurface
*
* Free resources allocated by DrvEnableSurface. Release the surface.
*
\**************************************************************************/
VOID DrvDisableSurface(
DHPDEV dhpdev)
{
#if INVESTIGATE
if(traseentry & FL_DRV_DISBLSURF)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvDisableSurface +++\n"));
if(breakentry & FL_DRV_DISBLSURF)
EngDebugBreak();
#endif
#if INVESTIGATE
{
VIDEO_MEMORY VideoMemory;
DWORD ReturnedDataLength;
VideoMemory.RequestedVirtualAddress = ((PPDEV) dhpdev)->TscStatusReg;
if(((PPDEV) dhpdev)->ModelID != POWER_PRO && (((PPDEV) dhpdev)->TscStatusReg)) {
if (EngDeviceIoControl(((PPDEV) dhpdev)->hDriver,
IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES,
&VideoMemory,
sizeof(VideoMemory),
NULL,
0,
&ReturnedDataLength)) {
DISPDBG((0,"### PSIDISP.DLL: VIDEO FREE PUBLIC ACCESS RANGE ERROR ###\n"));
}
((PPDEV) dhpdev)->TscStatusReg = NULL;
}
}
#endif
EngDeleteSurface(((PPDEV) dhpdev)->hsurfEng);
vDisableSURF((PPDEV) dhpdev);
((PPDEV) dhpdev)->hsurfEng = (HSURF) 0;
#if INVESTIGATE
if(traseexit & FL_DRV_DISBLSURF)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvDisableSurface ---\n"));
if(breakexit & FL_DRV_DISBLSURF)
EngDebugBreak();
#endif
}
/******************************Public*Routine******************************\
* DrvAssertMode
*
* This asks the device to reset itself to the mode of the pdev passed in.
*
\**************************************************************************/
BOOL DrvAssertMode(
DHPDEV dhpdev,
BOOL bEnable)
{
PPDEV ppdev = (PPDEV) dhpdev;
ULONG ulReturn;
BOOL retval;
#if INVESTIGATE
if(traseentry & FL_DRV_ASSERTMODE)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvAssertMode %s +++\n", bEnable?"TRUE":"FALSE"));
if(breakentry & FL_DRV_ASSERTMODE)
EngDebugBreak();
#endif
if (bEnable)
{
// The screen must be reenabled, reinitialize the device to clean state.
retval = bInitSURF(ppdev, FALSE);
}
else
{
// We must give up the display.
// Call the kernel driver to reset the device to a known state.
if (EngDeviceIoControl(ppdev->hDriver,
IOCTL_VIDEO_RESET_DEVICE,
NULL,
0,
NULL,
0,
&ulReturn))
{
DISPDBG((0,"DISP DrvAssertMode failed IOCTL"));
retval = FALSE;
}
else
{
retval = TRUE;
}
}
#if INVESTIGATE
if(traseexit & FL_DRV_ASSERTMODE)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvAssertMode ---\n"));
if(breakexit & FL_DRV_ASSERTMODE)
EngDebugBreak();
#endif
return retval;
}
/******************************Public*Routine******************************\
* DrvGetModes
*
* Returns the list of available modes for the device.
*
\**************************************************************************/
ULONG DrvGetModes(
HANDLE hDriver,
ULONG cjSize,
DEVMODEW *pdm)
{
DWORD cModes;
DWORD cbOutputSize;
PVIDEO_MODE_INFORMATION pVideoModeInformation, pVideoTemp;
DWORD cOutputModes = cjSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
DWORD cbModeSize;
#if INVESTIGATE
if(traseentry & FL_DRV_GETMODE)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvGetModes +++\n"));
if(breakentry & FL_DRV_GETMODE)
EngDebugBreak();
#endif
cModes = getAvailableModes(hDriver,
(PVIDEO_MODE_INFORMATION *) &pVideoModeInformation,
&cbModeSize);
if (cModes == 0)
{
DISPDBG((0, "### psidisp DrvGetModes failed to get mode information ###"));
return 0;
}
if (pdm == NULL)
{
cbOutputSize = cModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
}
else
{
//
// Now copy the information for the supported modes back into the output
// buffer
//
cbOutputSize = 0;
pVideoTemp = pVideoModeInformation;
do
{
if (pVideoTemp->Length != 0)
{
if (cOutputModes == 0)
{
break;
}
//
// Zero the entire structure to start off with.
//
memset(pdm, 0, sizeof(DEVMODEW));
//
// Set the name of the device to the name of the DLL.
//
memcpy(pdm->dmDeviceName, DLL_NAME, sizeof(DLL_NAME));
pdm->dmSpecVersion = DM_SPECVERSION;
pdm->dmDriverVersion = DM_SPECVERSION;
pdm->dmSize = sizeof(DEVMODEW);
pdm->dmDriverExtra = DRIVER_EXTRA_SIZE;
pdm->dmBitsPerPel = pVideoTemp->NumberOfPlanes *
pVideoTemp->BitsPerPlane;
pdm->dmPelsWidth = pVideoTemp->VisScreenWidth;
pdm->dmPelsHeight = pVideoTemp->VisScreenHeight;
pdm->dmDisplayFrequency = pVideoTemp->Frequency;
pdm->dmDisplayFlags = 0;
pdm->dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_DISPLAYFREQUENCY |
DM_DISPLAYFLAGS ;
//
// Go to the next DEVMODE entry in the buffer.
//
cOutputModes--;
pdm = (LPDEVMODEW) ( ((ULONG)pdm) + sizeof(DEVMODEW) +
DRIVER_EXTRA_SIZE);
cbOutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
}
pVideoTemp = (PVIDEO_MODE_INFORMATION)
(((PUCHAR)pVideoTemp) + cbModeSize);
} while (--cModes);
}
EngFreeMem(pVideoModeInformation);
#if INVESTIGATE
if(traseexit & FL_DRV_GETMODE)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvGetModes ---\n"));
if(breakexit & FL_DRV_GETMODE)
EngDebugBreak();
#endif
return cbOutputSize;
}
/******************************Public*Routine******************************\
* DrvSetPointerShape
*
* Tells the driver the shape of the driver. Since this driver doesn't
* support pointer, this shouldn't be called (with NULL POINTER capability
* flag, but it's called and if this entry doesn't exist, display driver
* crashes, so we need this entry doing nothing.
*
\**************************************************************************/
ULONG DrvSetPointerShape
(
SURFOBJ *pso,
SURFOBJ *psoMask,
SURFOBJ *psoColor,
XLATEOBJ *pxlo,
LONG xHot,
LONG yHot,
LONG x,
LONG y,
RECTL *prcl,
FLONG fl
)
{
#if INVESTIGATE
if(traseentry & dbgflg & FL_DRV_POINTERSHAPE)
DISPDBG((0,"+++ PSIDISP.DLL: Entering DrvSetPointerShape +++\n"));
if(breakentry & FL_DRV_POINTERSHAPE)
CountBreak();
#endif
CLOCKSTART((TRAP_SETPOINTER));
CLOCKEND((TRAP_SETPOINTER));
#if INVESTIGATE
if(traseexit & dbgflg & FL_DRV_POINTERSHAPE)
DISPDBG((0,"--- PSIDISP.DLL: Exiting DrvSetPointerShape ---\n"));
if(breakexit & FL_DRV_POINTERSHAPE)
CountBreak();
#endif
return(SPS_DECLINE);
}