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.
 
 
 
 
 
 

2027 lines
67 KiB

/******************************Module*Header**********************************\
*
* **************************
* * SAMPLE CODE *
* **************************
*
* Module Name: debug.c
*
* Content: Debugging aids
*
* Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
// Debug routines
#include "glint.h"
#include "dma.h"
#include <windef.h>
#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
#if DBG
#if DBG_TRACK_CODE
// we don't want to ever do code coverage of the debugging tools
// (otherwise we might loop forever)
#undef if
#undef while
#endif // DBG_TRACK_CODE
#if DBG_TRACK_FUNCS || DBG_TRACK_CODE
// Common helper functions
//-----------------------------------------------------------------------------
// __ShortFileName
//
// Leave just an 8.3 filename to store rather than a full path name
//
//-----------------------------------------------------------------------------
char *
__ShortFileName(char *pInStr)
{
char *pShortFN;
pShortFN = pInStr;
if (pInStr != NULL)
{
while (*pInStr != '\0')
{
if (*pInStr++ == '\\')
{
pShortFN = pInStr;
}
}
}
return (pShortFN);
} // __ShortFileName
#endif // DBG_TRACK_FUNCS || DBG_TRACK_CODE
#if DBG_TRACK_FUNCS
//-----------------------------------------------------------------------------
//
// ****************** FUNCTION COVERAGE DEBUGGING SUPPORT ********************
//
//-----------------------------------------------------------------------------
//
// This mechanism enables us to track which functions are called (entered),
// how many times they are called, what values do they return (and if they exit
// through all expected return points). Support to track maximum, minimum and
// average time per call can also be implemented.
//
// To use it, add the DBG_ENTRY macro at the start of important functions you
// want to track and before taking any return statement, add a DBG_EXIT macro
// giving a DWORD value representative of the return value of the function.
// Different return values will be tracked independently.
//
//
// ********** This support should only be enabled for test runs. **********
// ** IT SHOULD NOT BE SET BY DEFAULT ON NEITHER ON FREE OR CHECKED BUILDS **
//
//-----------------------------------------------------------------------------
// Maximum of functions to be tracked. Code will take care of not exceeding
// this, but it should be adjusted upward if necessary.
#define DEBUG_MAX_FUNC_COUNT 200
// Maximum of different return values to keep track of. Can be independent
// of DEBUG_MAX_FUNC_COUNT, just using a heuristic here instead of a wild guess.
#define DEBUG_MAX_RETVALS (DEBUG_MAX_FUNC_COUNT * 30)
// global structures that will hold our data
struct {
VOID *pFuncAddr; //
DWORD dwRetVal; //
DWORD dwLine; //
DWORD dwCount; //
} g_DbgFuncRetVal[DEBUG_MAX_RETVALS];
struct {
VOID *pFuncAddr; //
char *pszFuncName; //
char *pszFileName; //
DWORD dwLine; //
DWORD dwEntryCount; //
DWORD dwExitCount; //
DWORD dwIndxLastRetVal; //
// profiling support - not yet implemented //azn
LONGLONG LastStartTime; //
DWORD MinTime; //
DWORD MaxTime; //
DWORD AvgTime; //
} g_DbgFuncCoverage[DEBUG_MAX_FUNC_COUNT];
DWORD g_dwRetVal_Cnt = 0;
DWORD g_dwFuncCov_Cnt = 0;
DWORD g_dwFuncCov_Extra = 0;
//-----------------------------------------------------------------------------
// __Find
//
// Does a binary search on the g_DbgFuncCoverage array
//
// Since 0 is a valid array element, we return DEBUG_MAX_FUNC_COUNT if we
// fail to find a suitable match.
//
//-----------------------------------------------------------------------------
DWORD
__Find(
VOID *pFuncAddr, DWORD *pdwNearFail)
{
DWORD dwLower ,dwUpper ,dwNewProbe ;
*pdwNearFail = 0; // default failure value
if (g_dwFuncCov_Cnt > 0)
{
dwLower = 0;
dwUpper = g_dwFuncCov_Cnt - 1; // dwUpper points to a valid element
do
{
dwNewProbe = (dwUpper + dwLower) / 2;
//DISPDBG((0,"%x %d %d %d",pFuncAddr,dwLower,dwUpper,dwNewProbe));
if (g_DbgFuncCoverage[dwNewProbe].pFuncAddr == pFuncAddr)
{
// Found!!!
return dwNewProbe;
}
*pdwNearFail = dwNewProbe; // nearest element where we failed.
// The new values for dwNewProbe make sure that we don't retest
// the same value again unless dwUpper == dwLower in which case
// we're done.
if (g_DbgFuncCoverage[dwNewProbe].pFuncAddr > pFuncAddr)
{
if (dwNewProbe > 0)
{
dwUpper = dwNewProbe - 1;
}
else
{ // all elements in the array are larger than pFuncAdrr
// so this is just a way to exit from the loop since
// our vars are unsigned
dwUpper = 0;
dwLower = 1;
}
}
else
{
dwLower = dwNewProbe + 1;
}
} while(dwUpper >= dwLower);
}
return DEBUG_MAX_FUNC_COUNT; // return error - element not found
} // __Find
//-----------------------------------------------------------------------------
// __FindOrAdd
//
// Does a binary search on the g_DbgFuncCoverage array, but if the element
// isn't there, it is added.
//
// If we fail to add the element, we return the DEBUG_MAX_FUNC_COUNT value
//
//-----------------------------------------------------------------------------
DWORD
__FindOrAdd(
VOID *pFuncAddr,
char *pszFuncName,
DWORD dwLine ,
char *pszFileName)
{
DWORD dwNearFail;
DWORD iEntry;
DWORD dwNewElem;
BOOL bNeedToMoveElems;
// Do the normal search of the element first
iEntry = __Find(pFuncAddr, &dwNearFail);
if (iEntry != DEBUG_MAX_FUNC_COUNT)
{
return iEntry; //we're done!
}
// Now we have to add the new element. Do we have enough space?
if (g_dwFuncCov_Cnt == DEBUG_MAX_FUNC_COUNT)
{
g_dwFuncCov_Extra++; // Keep count of how many extra
// entries we really need
return DEBUG_MAX_FUNC_COUNT; // return error - not enough space left
}
// Do we need to move elements to insert the new one ?
if ( g_dwFuncCov_Cnt == 0)
{
bNeedToMoveElems = FALSE;
dwNewElem = 0;
}
else if ( (dwNearFail == g_dwFuncCov_Cnt - 1) &&
(g_DbgFuncCoverage[dwNearFail].pFuncAddr < pFuncAddr) )
{
bNeedToMoveElems = FALSE;
dwNewElem = g_dwFuncCov_Cnt;
}
else if (g_DbgFuncCoverage[dwNearFail].pFuncAddr < pFuncAddr)
{
bNeedToMoveElems = TRUE;
dwNewElem = dwNearFail + 1;
}
else
{
bNeedToMoveElems = TRUE;
dwNewElem = dwNearFail;
}
// Do the move inside the array if necessary
if (bNeedToMoveElems)
{
// we need to move (g_dwFuncCov_Cnt - dwNewElem) elements
// we use memmove as memcpy doesn't handle overlaps!
// (remember: first param of memcpy is dst, 2nd is src!)
memmove(&g_DbgFuncCoverage[dwNewElem+1],
&g_DbgFuncCoverage[dwNewElem],
sizeof(g_DbgFuncCoverage[0])*(g_dwFuncCov_Cnt - dwNewElem));
// now cleanup the fields
memset(&g_DbgFuncCoverage[dwNewElem],
0,
sizeof(g_DbgFuncCoverage[dwNewElem]));
}
// Now init the main fields
g_DbgFuncCoverage[dwNewElem].pFuncAddr = pFuncAddr;
g_DbgFuncCoverage[dwNewElem].pszFuncName = pszFuncName;
g_DbgFuncCoverage[dwNewElem].pszFileName = __ShortFileName(pszFileName);
g_DbgFuncCoverage[dwNewElem].dwLine = dwLine;
// Mark the fact that the array has grown by one element
g_dwFuncCov_Cnt++;
DISPDBG((DBGLVL,"*** DEBUG FUNC COVERAGE New Elem (total now:%d) %x @ %d",
g_dwFuncCov_Cnt, pFuncAddr, dwNewElem));
return dwNewElem;
} // __FindOrAdd
//-----------------------------------------------------------------------------
// __GetTime
//-----------------------------------------------------------------------------
VOID
__GetTime( LONGLONG *pllTime)
{
*pllTime = 0; //azn - temporary
} // __GetTime
//-----------------------------------------------------------------------------
// Debug_Func_Entry
//-----------------------------------------------------------------------------
VOID
Debug_Func_Entry(
VOID *pFuncAddr,
char *pszFuncName,
DWORD dwLine ,
char *pszFileName)
{
DWORD iEntry;
LONGLONG llTimer;
// Look for a log element for entry to this function. If not found it
// is added to the current list of covered functions.
iEntry = __FindOrAdd(pFuncAddr, pszFuncName, dwLine, pszFileName);
// Didn't found one and no more space left in the internal data
// structures ? Report error and return!
if (iEntry == DEBUG_MAX_FUNC_COUNT)
{
DISPDBG((ERRLVL,"*** DEBUG FUNC COVERAGE ERROR in Debug_Func_Entry"));
return;
}
// Update/Add information for this entry
if (g_DbgFuncCoverage[iEntry].dwEntryCount != 0)
{
// This is an update
g_DbgFuncCoverage[iEntry].dwEntryCount++;
__GetTime(&llTimer);
g_DbgFuncCoverage[iEntry].LastStartTime = llTimer;
}
else
{
// This is an addition
g_DbgFuncCoverage[iEntry].dwEntryCount = 1;
g_DbgFuncCoverage[iEntry].dwExitCount = 0;
g_DbgFuncCoverage[iEntry].dwIndxLastRetVal = 0;
__GetTime(&llTimer);
g_DbgFuncCoverage[iEntry].LastStartTime = llTimer;
g_DbgFuncCoverage[iEntry].MinTime = 0;
g_DbgFuncCoverage[iEntry].MaxTime = 0;
g_DbgFuncCoverage[iEntry].AvgTime = 0;
}
} // Debug_Func_Entry
//-----------------------------------------------------------------------------
// Debug_Func_Exit
//-----------------------------------------------------------------------------
VOID
Debug_Func_Exit(
VOID *pFuncAddr,
DWORD dwRetVal,
DWORD dwLine)
{
DWORD iEntry;
LONGLONG llTimer;
DWORD dwElapsedTime;
DWORD dwDummy;
DWORD iRVEntry;
__GetTime(&llTimer);
// Look for a log element for entry to this function
iEntry = __Find(pFuncAddr, &dwDummy);
// Record and update relevant info in g_DbgFuncCoverage
if (iEntry != DEBUG_MAX_FUNC_COUNT)
{
// keep track of times we've exited this function
g_DbgFuncCoverage[iEntry].dwExitCount++;
// Keep track of elapsed times for this function
//@@BEGIN_DDKSPLIT
// possibly an evil data conversion - azn
//@@END_DDKSPLIT
dwElapsedTime = (DWORD)(llTimer -
g_DbgFuncCoverage[iEntry].LastStartTime);
if (dwElapsedTime > g_DbgFuncCoverage[iEntry].MaxTime)
{
g_DbgFuncCoverage[iEntry].MaxTime = dwElapsedTime;
}
if (dwElapsedTime < g_DbgFuncCoverage[iEntry].MinTime)
{
g_DbgFuncCoverage[iEntry].MinTime = dwElapsedTime;
}
g_DbgFuncCoverage[iEntry].AvgTime =
( (g_DbgFuncCoverage[iEntry].dwExitCount - 1)*
g_DbgFuncCoverage[iEntry].AvgTime +
dwElapsedTime
) / g_DbgFuncCoverage[iEntry].dwExitCount;
g_DbgFuncCoverage[iEntry].LastStartTime = 0;
}
else
{
DISPDBG((ERRLVL,"*** DEBUG FUNC COVERAGE ERROR not found %x",pFuncAddr));
return; // don't even try adding this to the return value table
}
iRVEntry = g_DbgFuncCoverage[iEntry].dwIndxLastRetVal;
if (iRVEntry != 0)
{
// Check if the last time we recorded a return value for this function
// it was the exact same one. This way will save space recording some
// duplicate info. The method is not perfect, but it's fast.
if (( g_DbgFuncRetVal[iRVEntry].pFuncAddr == pFuncAddr) &&
( g_DbgFuncRetVal[iRVEntry].dwRetVal == dwRetVal ) &&
( g_DbgFuncRetVal[iRVEntry].dwLine == dwLine ) )
{
//increment count for this event
g_DbgFuncRetVal[iRVEntry].dwCount += 1;
return; // we won't store a new record for this event
}
}
// We couldn't save space, so we add info about the return value
if (g_dwRetVal_Cnt < DEBUG_MAX_RETVALS)
{
g_DbgFuncCoverage[iEntry].dwIndxLastRetVal = g_dwRetVal_Cnt;
g_DbgFuncRetVal[g_dwRetVal_Cnt].pFuncAddr = pFuncAddr;
g_DbgFuncRetVal[g_dwRetVal_Cnt].dwRetVal = dwRetVal;
g_DbgFuncRetVal[g_dwRetVal_Cnt].dwLine = dwLine;
g_DbgFuncRetVal[g_dwRetVal_Cnt].dwCount = 1;
g_dwRetVal_Cnt++;
}
} // Debug_Func_Exit
//-----------------------------------------------------------------------------
//
// Debug_Func_Report_And_Reset
//
// Report the accumulated stats and then reset them.
//
// This should be called through the DrvEscape mechanism(Win2K) or through some
// easily controllable code path which we can use to trigger it.
//
//-----------------------------------------------------------------------------
VOID
Debug_Func_Report_And_Reset(void)
{
DWORD i,j,k; // counters
DWORD dwCount;
DISPDBG((ERRLVL,"********* DEBUG FUNC COVERAGE (Debug_Func_Report) *********"));
// Report if we have overflowed in any of our internal structures
// which would invalidate much of our results.
if (g_dwFuncCov_Cnt >= DEBUG_MAX_FUNC_COUNT)
{
DISPDBG((ERRLVL,"*** DEBUG FUNC COVERAGE: g_DbgFuncCoverage exceeded "
"%d entries by %d ***",
DEBUG_MAX_FUNC_COUNT,
g_dwFuncCov_Extra));
}
if (g_dwRetVal_Cnt >= DEBUG_MAX_RETVALS)
{
DISPDBG((ERRLVL,"*** DEBUG FUNC COVERAGE: g_DbgFuncRetVal exceeded "
"%d entries ***",DEBUG_MAX_RETVALS));
}
// Headers of function coverage report
DISPDBG((ERRLVL,"%25s %12s %4s %6s %6s %8s",
"Function","File","Line","#Entry","#Exit","ExitValue"));
// Go through each function called and report on its results
for (i = 0; i < g_dwFuncCov_Cnt; i++)
{
DISPDBG((ERRLVL,"%25s %12s %4d %6d %6d",
g_DbgFuncCoverage[i].pszFuncName,
g_DbgFuncCoverage[i].pszFileName,
g_DbgFuncCoverage[i].dwLine,
g_DbgFuncCoverage[i].dwEntryCount,
g_DbgFuncCoverage[i].dwExitCount));
// Get result values
for(j = 0; j < g_dwRetVal_Cnt; j++)
{
if(g_DbgFuncRetVal[j].pFuncAddr ==
g_DbgFuncCoverage[i].pFuncAddr)
{
// This entry is a valid exit value report for
// our g_DbgFuncCoverage entry, count instances
dwCount = g_DbgFuncRetVal[j].dwCount;
// Now get rid of any duplicate records of this
// same exit event while counting
for (k = j + 1; k < g_dwRetVal_Cnt; k++)
{
if ( (g_DbgFuncRetVal[j].pFuncAddr ==
g_DbgFuncRetVal[k].pFuncAddr) &&
(g_DbgFuncRetVal[j].dwLine ==
g_DbgFuncRetVal[k].dwLine) &&
(g_DbgFuncRetVal[j].dwRetVal ==
g_DbgFuncRetVal[k].dwRetVal))
{
dwCount += g_DbgFuncRetVal[k].dwCount;
g_DbgFuncRetVal[k].pFuncAddr = NULL;
g_DbgFuncRetVal[k].dwRetVal = 0;
g_DbgFuncRetVal[k].dwLine = 0;
g_DbgFuncRetVal[k].dwCount = 0;
}
}
// Display it
DISPDBG((ERRLVL,"%25s %12s %4d %6d %6s %8d",
"\"",
g_DbgFuncCoverage[i].pszFileName,
g_DbgFuncRetVal[j].dwLine,
dwCount,"",
g_DbgFuncRetVal[j].dwRetVal));
}
}
}
DISPDBG((ERRLVL,
"************************************************************"));
// Clear structures for next round of statistics gathering
for (i = 0; i < DEBUG_MAX_RETVALS; i++)
{
g_DbgFuncRetVal[i].pFuncAddr = NULL;
g_DbgFuncRetVal[i].dwRetVal = 0;
g_DbgFuncRetVal[i].dwLine = 0;
g_DbgFuncRetVal[i].dwCount = 0;
}
for (i= 0; i < DEBUG_MAX_FUNC_COUNT; i++)
{
g_DbgFuncCoverage[i].pFuncAddr = NULL;
g_DbgFuncCoverage[i].pszFuncName = NULL;
g_DbgFuncCoverage[i].pszFileName = NULL;
g_DbgFuncCoverage[i].dwLine = 0;
g_DbgFuncCoverage[i].dwEntryCount = 0;
g_DbgFuncCoverage[i].dwExitCount = 0;
g_DbgFuncCoverage[i].dwIndxLastRetVal = 0;
g_DbgFuncCoverage[i].LastStartTime = 0;
g_DbgFuncCoverage[i].MinTime = 0;
g_DbgFuncCoverage[i].MaxTime = 0;
g_DbgFuncCoverage[i].AvgTime = 0;
}
g_dwRetVal_Cnt = 0;
g_dwFuncCov_Cnt = 0;
g_dwFuncCov_Extra = 0;
} // Debug_Func_Report
#endif // DBG_TRACK_FUNCS
#if DBG_TRACK_CODE
//-----------------------------------------------------------------------------
//
// ******************** STATEMENT COVERAGE DEBUGGING SUPPORT ******************
//
//-----------------------------------------------------------------------------
// Maximum of code branches to be tracked. Code will take care of not exceeding
// this, but it should be adjusted upward if necessary.
#define DEBUG_MAX_CODE_COUNT 20000
struct {
VOID *pCodeAddr; //
char *pszFileName; //
DWORD dwLine; //
DWORD dwCodeType; //
DWORD dwCountFALSE; //
DWORD dwCountTRUE; //
} g_DbgCodeCoverage[DEBUG_MAX_CODE_COUNT];
DWORD g_dwCodeCov_Cnt = 0;
static char* g_cDbgCodeStrings[DBG_FOR_CODE+1] = { "NONE",
"IF" ,
"WHILE",
"SWITCH",
"FOR" };
//-----------------------------------------------------------------------------
// __FindCode
//
// Does a binary search on the g_DbgCodeCoverage array
//
// Since 0 is a valid array element, we return DEBUG_MAX_CODE_COUNT if we
// fail to find a suitable match.
//
//-----------------------------------------------------------------------------
DWORD
__FindCode(
VOID *pCodeAddr,
DWORD *pdwNearFail)
{
DWORD dwLower ,dwUpper ,dwNewProbe ;
*pdwNearFail = 0; // default failure value
if (g_dwCodeCov_Cnt > 0)
{
dwLower = 0;
dwUpper = g_dwCodeCov_Cnt - 1; // dwUpper points to a valid element
do
{
dwNewProbe = (dwUpper + dwLower) / 2;
if (g_DbgCodeCoverage[dwNewProbe].pCodeAddr == pCodeAddr)
{
// Found!!!
return dwNewProbe;
}
*pdwNearFail = dwNewProbe; // nearest element where we failed.
// The new values for dwNewProbe make sure that we don't retest
// the same value again unless dwUpper == dwLower in which case
// we're done.
if (g_DbgCodeCoverage[dwNewProbe].pCodeAddr > pCodeAddr)
{
if (dwNewProbe > 0)
{
dwUpper = dwNewProbe - 1;
}
else
{ // all elements in the array are larger than pCodeAdrr
// so this is just a way to exit from the loop since
// our vars are unsigned
dwUpper = 0;
dwLower = 1;
}
}
else
{
dwLower = dwNewProbe + 1;
}
} while(dwUpper >= dwLower);
}
return DEBUG_MAX_CODE_COUNT; // return error - element not found
} // __FindCode
//-----------------------------------------------------------------------------
// __FindOrAddCode
//
// Does a binary search on the g_DbgCodeCoverage array, but if the element
// isn't there, it is added.
//
// If we fail to add the element, we return the DEBUG_MAX_CODE_COUNT value
//
//-----------------------------------------------------------------------------
DWORD
__FindOrAddCode(
VOID *pCodeAddr,
DWORD dwLine ,
char *pszFileName)
{
DWORD dwNearFail;
DWORD iEntry;
DWORD dwNewElem;
BOOL bNeedToMoveElems;
// Do the normal search of the element first
iEntry = __FindCode(pCodeAddr, &dwNearFail);
if (iEntry != DEBUG_MAX_CODE_COUNT)
{
return iEntry; //we're done!
}
// Now we have to add the new element. Do we have enough space?
if (g_dwCodeCov_Cnt == DEBUG_MAX_CODE_COUNT)
{
return DEBUG_MAX_CODE_COUNT; // return error - not enough space left
}
// Do we need to move elements to insert the new one ?
if ( g_dwCodeCov_Cnt == 0)
{
bNeedToMoveElems = FALSE;
dwNewElem = 0;
}
else if ( (dwNearFail == g_dwCodeCov_Cnt - 1) &&
(g_DbgCodeCoverage[dwNearFail].pCodeAddr < pCodeAddr) )
{
bNeedToMoveElems = FALSE;
dwNewElem = g_dwCodeCov_Cnt;
}
else if (g_DbgCodeCoverage[dwNearFail].pCodeAddr < pCodeAddr)
{
bNeedToMoveElems = TRUE;
dwNewElem = dwNearFail + 1;
}
else
{
bNeedToMoveElems = TRUE;
dwNewElem = dwNearFail;
}
// Do the move inside the array if necessary
if (bNeedToMoveElems)
{
// we need to move (g_dwFuncCov_Cnt - dwNewElem) elements
// we use memmove as memcpy doesn't handle overlaps!
// (remember: first param of memcpy is dst, 2nd is src!)
memmove(&g_DbgCodeCoverage[dwNewElem+1],
&g_DbgCodeCoverage[dwNewElem],
sizeof(g_DbgCodeCoverage[0])*(g_dwCodeCov_Cnt - dwNewElem));
// now cleanup the fields
memset(&g_DbgCodeCoverage[dwNewElem],
0,
sizeof(g_DbgCodeCoverage[dwNewElem]));
}
// Now init the main fields
g_DbgCodeCoverage[dwNewElem].pCodeAddr = pCodeAddr;
g_DbgCodeCoverage[dwNewElem].pszFileName = __ShortFileName(pszFileName);
g_DbgCodeCoverage[dwNewElem].dwLine = dwLine;
g_DbgCodeCoverage[dwNewElem].dwCodeType = 0;
g_DbgCodeCoverage[dwNewElem].dwCountFALSE = 0;
g_DbgCodeCoverage[dwNewElem].dwCountTRUE = 0;
// Mark the fact that the array has grown by one element
g_dwCodeCov_Cnt++;
// Check if we're about to fail! (in order to report this only once)
if (g_dwCodeCov_Cnt == DEBUG_MAX_CODE_COUNT)
{
DISPDBG((ERRLVL,"*** DEBUG CODE COVERAGE ERROR in Debug_Code_Coverage"));
}
return dwNewElem;
} // __FindOrAddCode
//-----------------------------------------------------------------------------
// Debug_Code_Coverage
//-----------------------------------------------------------------------------
BOOL
Debug_Code_Coverage(
DWORD dwCodeType,
DWORD dwLine ,
char *pszFileName,
BOOL bCodeResult)
{
DWORD iEntry;
DWORD *pCodeAddr;
// Get the 32-bit address of our caller from the stack
__asm mov eax, [ebp+0x4];
__asm mov pCodeAddr,eax;
// Look for a log element for entry to this code. If not found it
// is added to the current list of covered code.
iEntry = __FindOrAddCode(pCodeAddr, dwLine, pszFileName);
// Didn't found one and no more space left in the internal data
// structures ? Get out and do nothing!
if (iEntry == DEBUG_MAX_CODE_COUNT)
{
return bCodeResult;
}
if (dwCodeType == DBG_IF_CODE || dwCodeType == DBG_WHILE_CODE )
{
// Update/Add information for this entry
g_DbgCodeCoverage[iEntry].dwCodeType = dwCodeType;
if (bCodeResult)
{
g_DbgCodeCoverage[iEntry].dwCountTRUE++;
}
else
{
g_DbgCodeCoverage[iEntry].dwCountFALSE++;
}
}
else if (dwCodeType == DBG_SWITCH_CODE)
{
// special case for the switch statement since its multivalued
// Is the entry new? (uninitalized)
if(g_DbgCodeCoverage[iEntry].dwCodeType == 0)
{
// just init and get out of here
g_DbgCodeCoverage[iEntry].dwCodeType = DBG_SWITCH_CODE;
g_DbgCodeCoverage[iEntry].dwCountFALSE = bCodeResult; // switch value
g_DbgCodeCoverage[iEntry].dwCountTRUE = 1; // found once
}
else
{
// need to look for already initialized elememt
int iLookAt;
// look at current element and back
DWORD dwNewElem;
iLookAt = iEntry;
while ( (iLookAt >= 0 ) &&
(g_DbgCodeCoverage[iLookAt].pCodeAddr == pCodeAddr) )
{
if (g_DbgCodeCoverage[iLookAt].dwCountFALSE == (DWORD)bCodeResult)
{
// found - so update and get out of here
g_DbgCodeCoverage[iLookAt].dwCountTRUE++;
return bCodeResult;
}
// move to previous
iLookAt--;
}
// look forward from current element
iLookAt = iEntry + 1;
while ( ((DWORD)iLookAt < g_dwCodeCov_Cnt ) &&
(g_DbgCodeCoverage[iLookAt].pCodeAddr == pCodeAddr) )
{
if (g_DbgCodeCoverage[iLookAt].dwCountFALSE == (DWORD)bCodeResult)
{
// found - so update and get out of here
g_DbgCodeCoverage[iLookAt].dwCountTRUE++;
return bCodeResult;
}
// move to next
iLookAt++;
}
// not found - so we must add it!
dwNewElem = iEntry;
// we need to move (g_dwFuncCov_Cnt - dwNewElem) elements
// we use memmove as memcpy doesn't handle overlaps!
// (remember: first param of memcpy is dst, 2nd is src!)
memmove(&g_DbgCodeCoverage[dwNewElem+1],
&g_DbgCodeCoverage[dwNewElem],
sizeof(g_DbgCodeCoverage[0])*(g_dwCodeCov_Cnt - dwNewElem));
// now cleanup the fields
memset(&g_DbgCodeCoverage[dwNewElem],
0,
sizeof(g_DbgCodeCoverage[dwNewElem]));
// now init them
g_DbgCodeCoverage[dwNewElem].pCodeAddr = pCodeAddr;
g_DbgCodeCoverage[dwNewElem].pszFileName =
g_DbgCodeCoverage[dwNewElem+1].pszFileName;
g_DbgCodeCoverage[dwNewElem].dwLine = dwLine;
g_DbgCodeCoverage[dwNewElem].dwCodeType = DBG_SWITCH_CODE;
g_DbgCodeCoverage[dwNewElem].dwCountFALSE = bCodeResult; // switch value
g_DbgCodeCoverage[dwNewElem].dwCountTRUE = 1; // found once
}
}
return bCodeResult;
} // Debug_Code_Coverage
//-----------------------------------------------------------------------------
//
// Debug_Code_Report_And_Reset
//
// Report the accumulated stats and then reset them.
//
// This should be called through the DrvEscape mechanism(Win2K) or through some
// easily controllable code path which we can use to trigger it.
//
//-----------------------------------------------------------------------------
VOID
Debug_Code_Report_And_Reset(void)
{
DWORD i; // counters
DISPDBG((ERRLVL,
"********* DEBUG FUNC COVERAGE (Debug_Code_Report) *********"));
// Report if we have overflowed in any of our internal structures
// which would invalidate much of our results.
if (g_dwCodeCov_Cnt >= DEBUG_MAX_CODE_COUNT)
{
DISPDBG((ERRLVL,"*** DEBUG CODE COVERAGE: g_DbgCodeCoverage exceeded "
"%d entries ***",DEBUG_MAX_CODE_COUNT));
}
// Headers of code coverage report
DISPDBG((ERRLVL,"%12s %4s %8s %6s %6s",
"File","Line","Code","FALSE","TRUE"));
// Go through each code called and report on its results
for (i = 0; i < g_dwCodeCov_Cnt; i++)
{
#if DBG_TRACK_CODE_REPORT_PROBLEMS_ONLY
// Report only
// - if's that branched only one way
// - while's which were evaluated but not entered
if ( ( (g_DbgCodeCoverage[i].dwCodeType == DBG_IF_CODE) &&
(g_DbgCodeCoverage[i].dwCountFALSE == 0 ||
g_DbgCodeCoverage[i].dwCountTRUE == 0) ) ||
( (g_DbgCodeCoverage[i].dwCodeType == DBG_WHILE_CODE) &&
(g_DbgCodeCoverage[i].dwCountTRUE == 0) ) ||
( (g_DbgCodeCoverage[i].dwCodeType == DBG_SWITCH_CODE)) )
#endif
// We report all the conditionals we've gone through so far
DISPDBG((ERRLVL,"%12s %4d %8s %6d %6d",
g_DbgCodeCoverage[i].pszFileName,
g_DbgCodeCoverage[i].dwLine,
g_cDbgCodeStrings[g_DbgCodeCoverage[i].dwCodeType],
g_DbgCodeCoverage[i].dwCountFALSE,
g_DbgCodeCoverage[i].dwCountTRUE ));
}
DISPDBG((ERRLVL,
"************************************************************"));
// Clear structures for next round of statistics gathering
for (i= 0; i < DEBUG_MAX_CODE_COUNT; i++)
{
g_DbgCodeCoverage[i].pCodeAddr = NULL;
g_DbgCodeCoverage[i].pszFileName = NULL;
g_DbgCodeCoverage[i].dwLine = 0;
g_DbgCodeCoverage[i].dwCodeType = 0;
g_DbgCodeCoverage[i].dwCountFALSE = 0;
g_DbgCodeCoverage[i].dwCountTRUE = 0;
}
g_dwCodeCov_Cnt = 0;
} // Debug_Code_Report_And_Reset
#endif // DBG_TRACK_CODE
//-----------------------------------------------------------------------------
//
// ******************** PUBLIC DATA STRUCTURE DUMPING ************************
//
//-----------------------------------------------------------------------------
//
// These are functions that help to dump the values of common DDI structures
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// DumpD3DBlend
//
// Dumps a D3DBLEND value
//
//-----------------------------------------------------------------------------
void DumpD3DBlend(int Level, DWORD i )
{
switch ((D3DBLEND)i)
{
case D3DBLEND_ZERO:
DISPDBG((Level, " ZERO"));
break;
case D3DBLEND_ONE:
DISPDBG((Level, " ONE"));
break;
case D3DBLEND_SRCCOLOR:
DISPDBG((Level, " SRCCOLOR"));
break;
case D3DBLEND_INVSRCCOLOR:
DISPDBG((Level, " INVSRCCOLOR"));
break;
case D3DBLEND_SRCALPHA:
DISPDBG((Level, " SRCALPHA"));
break;
case D3DBLEND_INVSRCALPHA:
DISPDBG((Level, " INVSRCALPHA"));
break;
case D3DBLEND_DESTALPHA:
DISPDBG((Level, " DESTALPHA"));
break;
case D3DBLEND_INVDESTALPHA:
DISPDBG((Level, " INVDESTALPHA"));
break;
case D3DBLEND_DESTCOLOR:
DISPDBG((Level, " DESTCOLOR"));
break;
case D3DBLEND_INVDESTCOLOR:
DISPDBG((Level, " INVDESTCOLOR"));
break;
case D3DBLEND_SRCALPHASAT:
DISPDBG((Level, " SRCALPHASAT"));
break;
case D3DBLEND_BOTHSRCALPHA:
DISPDBG((Level, " BOTHSRCALPHA"));
break;
case D3DBLEND_BOTHINVSRCALPHA:
DISPDBG((Level, " BOTHINVSRCALPHA"));
break;
}
} // DumpD3DBlend
//-----------------------------------------------------------------------------
//
// DumpD3DLight
//
// Dumps a D3DLIGHT7 structure
//
//-----------------------------------------------------------------------------
void DumpD3DLight(int DebugLevel, D3DLIGHT7* pLight)
{
// FIXME
DISPDBG((DebugLevel, "dltType: %d", pLight->dltType));
DISPDBG((DebugLevel, "dcvDiffuse: (%f,%f,%f)",
pLight->dcvDiffuse.r,
pLight->dcvDiffuse.g,
pLight->dcvDiffuse.b,
pLight->dcvDiffuse.a));
DISPDBG((DebugLevel, "dvPosition: (%f,%f,%f)",
pLight->dvPosition.x,
pLight->dvPosition.y,
pLight->dvPosition.z));
DISPDBG((DebugLevel, "dvDirection: (%f,%f,%f)",
pLight->dvDirection.x,
pLight->dvDirection.y,
pLight->dvDirection.z));
DISPDBG((DebugLevel, "dvRange: %f", pLight->dvRange));
DISPDBG((DebugLevel, "dvFalloff: %f", pLight->dvFalloff));
DISPDBG((DebugLevel, "dvAttenuation0: %f", pLight->dvAttenuation0));
DISPDBG((DebugLevel, "dvAttenuation1: %f", pLight->dvAttenuation1));
DISPDBG((DebugLevel, "dvAttenuation2: %f", pLight->dvAttenuation2));
DISPDBG((DebugLevel, "dvTheta: %f", pLight->dvTheta));
DISPDBG((DebugLevel, "dvPhi: %f", pLight->dvPhi));
} // DumpD3DLight
//-----------------------------------------------------------------------------
//
// DumpD3DMaterial
//
// Dumps a D3DMATERIAL7 structure
//
//-----------------------------------------------------------------------------
void DumpD3DMaterial(int DebugLevel, D3DMATERIAL7* pMaterial)
{
DISPDBG((DebugLevel, "Diffuse (%f, %f, %f)",
pMaterial->diffuse.r,
pMaterial->diffuse.g,
pMaterial->diffuse.b,
pMaterial->diffuse.a));
DISPDBG((DebugLevel, "Ambient (%f, %f, %f)",
pMaterial->ambient.r,
pMaterial->ambient.g,
pMaterial->ambient.b,
pMaterial->ambient.a));
DISPDBG((DebugLevel, "Specular (%f, %f, %f)",
pMaterial->specular.r,
pMaterial->specular.g,
pMaterial->specular.b,
pMaterial->specular.a));
DISPDBG((DebugLevel, "Emmisive (%f, %f, %f)",
pMaterial->emissive.r,
pMaterial->emissive.g,
pMaterial->emissive.b,
pMaterial->emissive.a));
DISPDBG((DebugLevel, "Power (%f)", pMaterial->power));
} // DumpD3DMaterial
//-----------------------------------------------------------------------------
//
// DumpD3DMatrix
//
// Dumps a D3DMATRIX structure
//
//-----------------------------------------------------------------------------
void DumpD3DMatrix(int DebugLevel, D3DMATRIX* pMatrix)
{
DISPDBG((DebugLevel, "(%f) (%f) (%f) (%f)",
pMatrix->_11,
pMatrix->_12,
pMatrix->_13,
pMatrix->_14));
DISPDBG((DebugLevel, "(%f) (%f) (%f) (%f)",
pMatrix->_21,
pMatrix->_22,
pMatrix->_23,
pMatrix->_24));
DISPDBG((DebugLevel, "(%f) (%f) (%f) (%f)",
pMatrix->_31,
pMatrix->_32,
pMatrix->_33,
pMatrix->_34));
DISPDBG((DebugLevel, "(%f) (%f) (%f) (%f)",
pMatrix->_41,
pMatrix->_42,
pMatrix->_43,
pMatrix->_44));
} // DumpD3DMatrix
//-----------------------------------------------------------------------------
//
// DumpD3DState
//
// Dumps relevant D3D RS and TSS
//
//-----------------------------------------------------------------------------
void DumpD3DState(int lvl, DWORD RS[], TexStageState TS[])
{
#define DUMPRS(rs) DISPDBG((lvl,"%s = 0x%08x",#rs,RS[rs]));
DWORD i,j;
DISPDBG((lvl,"RELEVANT DX7 renderstates:"));
DUMPRS( D3DRENDERSTATE_ZENABLE );
DUMPRS( D3DRENDERSTATE_FILLMODE );
DUMPRS( D3DRENDERSTATE_SHADEMODE );
DUMPRS( D3DRENDERSTATE_LINEPATTERN );
DUMPRS( D3DRENDERSTATE_ZWRITEENABLE );
DUMPRS( D3DRENDERSTATE_ALPHATESTENABLE );
DUMPRS( D3DRENDERSTATE_LASTPIXEL );
DUMPRS( D3DRENDERSTATE_SRCBLEND );
DUMPRS( D3DRENDERSTATE_DESTBLEND );
DUMPRS( D3DRENDERSTATE_CULLMODE );
DUMPRS( D3DRENDERSTATE_ZFUNC );
DUMPRS( D3DRENDERSTATE_ALPHAREF );
DUMPRS( D3DRENDERSTATE_ALPHAFUNC );
DUMPRS( D3DRENDERSTATE_DITHERENABLE );
DUMPRS( D3DRENDERSTATE_BLENDENABLE );
DUMPRS( D3DRENDERSTATE_FOGENABLE );
DUMPRS( D3DRENDERSTATE_SPECULARENABLE );
DUMPRS( D3DRENDERSTATE_ZVISIBLE );
DUMPRS( D3DRENDERSTATE_STIPPLEDALPHA );
DUMPRS( D3DRENDERSTATE_FOGCOLOR );
DUMPRS( D3DRENDERSTATE_FOGTABLEMODE );
DUMPRS( D3DRENDERSTATE_FOGTABLESTART );
DUMPRS( D3DRENDERSTATE_FOGTABLEEND );
DUMPRS( D3DRENDERSTATE_FOGTABLEDENSITY );
DUMPRS( D3DRENDERSTATE_EDGEANTIALIAS );
DUMPRS( D3DRENDERSTATE_ZBIAS );
DUMPRS( D3DRENDERSTATE_RANGEFOGENABLE );
DUMPRS( D3DRENDERSTATE_STENCILENABLE );
DUMPRS( D3DRENDERSTATE_STENCILFAIL );
DUMPRS( D3DRENDERSTATE_STENCILZFAIL );
DUMPRS( D3DRENDERSTATE_STENCILPASS );
DUMPRS( D3DRENDERSTATE_STENCILFUNC );
DUMPRS( D3DRENDERSTATE_STENCILREF );
DUMPRS( D3DRENDERSTATE_STENCILMASK );
DUMPRS( D3DRENDERSTATE_STENCILWRITEMASK );
DUMPRS( D3DRENDERSTATE_TEXTUREFACTOR );
DUMPRS( D3DRENDERSTATE_WRAP0 );
DUMPRS( D3DRENDERSTATE_WRAP1 );
DUMPRS( D3DRENDERSTATE_WRAP2 );
DUMPRS( D3DRENDERSTATE_WRAP3 );
DUMPRS( D3DRENDERSTATE_WRAP4 );
DUMPRS( D3DRENDERSTATE_WRAP5 );
DUMPRS( D3DRENDERSTATE_WRAP6 );
DUMPRS( D3DRENDERSTATE_WRAP7 );
DUMPRS( D3DRENDERSTATE_LOCALVIEWER );
DUMPRS( D3DRENDERSTATE_CLIPPING );
DUMPRS( D3DRENDERSTATE_LIGHTING );
DUMPRS( D3DRENDERSTATE_AMBIENT );
DUMPRS( D3DRENDERSTATE_SCENECAPTURE );
DUMPRS( D3DRENDERSTATE_EVICTMANAGEDTEXTURES );
DUMPRS( D3DRENDERSTATE_TEXTUREHANDLE );
DUMPRS( D3DRENDERSTATE_ANTIALIAS );
DUMPRS( D3DRENDERSTATE_TEXTUREPERSPECTIVE );
DUMPRS( D3DRENDERSTATE_TEXTUREMAPBLEND );
DUMPRS( D3DRENDERSTATE_TEXTUREMAG );
DUMPRS( D3DRENDERSTATE_TEXTUREMIN );
DUMPRS( D3DRENDERSTATE_WRAPU );
DUMPRS( D3DRENDERSTATE_WRAPV );
DUMPRS( D3DRENDERSTATE_TEXTUREADDRESS );
DUMPRS( D3DRENDERSTATE_TEXTUREADDRESSU );
DUMPRS( D3DRENDERSTATE_TEXTUREADDRESSV );
DUMPRS( D3DRENDERSTATE_MIPMAPLODBIAS );
DUMPRS( D3DRENDERSTATE_BORDERCOLOR );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN00 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN01 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN02 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN03 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN04 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN05 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN06 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN07 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN08 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN09 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN10 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN11 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN12 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN13 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN14 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN15 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN16 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN17 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN18 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN19 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN20 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN21 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN22 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN23 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN24 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN25 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN26 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN27 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN28 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN29 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN30 );
DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN31 );
DUMPRS( D3DRENDERSTATE_ROP2 );
DUMPRS( D3DRENDERSTATE_PLANEMASK );
DUMPRS( D3DRENDERSTATE_MONOENABLE );
DUMPRS( D3DRENDERSTATE_SUBPIXEL );
DUMPRS( D3DRENDERSTATE_SUBPIXELX );
DUMPRS( D3DRENDERSTATE_STIPPLEENABLE );
DUMPRS( D3DRENDERSTATE_COLORKEYENABLE );
#if DX8_DDI
DISPDBG((lvl,"RELEVANT DX8 renderstates:"));
DUMPRS( D3DRS_POINTSIZE );
DUMPRS( D3DRS_POINTSPRITEENABLE );
DUMPRS( D3DRS_POINTSIZE_MIN );
DUMPRS( D3DRS_POINTSIZE_MAX );
DUMPRS( D3DRS_POINTSCALEENABLE );
DUMPRS( D3DRS_POINTSCALE_A );
DUMPRS( D3DRS_POINTSCALE_B );
DUMPRS( D3DRS_POINTSCALE_C );
DUMPRS( D3DRS_SOFTWAREVERTEXPROCESSING );
DUMPRS( D3DRS_COLORWRITEENABLE );
DUMPRS( D3DRS_MULTISAMPLEANTIALIAS );
#endif // DX8_DDI
for (i=0; i<D3DHAL_TSS_MAXSTAGES; i++)
{
DISPDBG((lvl," TS[%d].",i));
for (j=0; j<D3DTSS_MAX; j++)
{
DISPDBG((lvl, " .[%d] = 0x%08x",j,TS[i].m_dwVal[j] ));
}
}
} // DumpD3DState
//-----------------------------------------------------------------------------
//
// DumpVertices
//
// Dumps vertices from a VB
//
//-----------------------------------------------------------------------------
void DumpVertices(int lvl,
P3_D3DCONTEXT* pContext,
LPBYTE lpVertices,
DWORD dwNumVertices)
{
DWORD i,j;
DWORD *lpw = (DWORD *)lpVertices;
for (i=0 ; i<dwNumVertices; i++)
{
DISPDBG((lvl,"Vertex # %d", i));
for (j=0; j < pContext->FVFData.dwStride; j+=4)
{
DISPDBG((lvl," 0x%08x",*lpw++));
}
}
} // DumpVertices
//-----------------------------------------------------------------------------
//
// DumpHexData
//
// Dumps hexadecimal data
//
//-----------------------------------------------------------------------------
void DumpHexData(int lvl,
LPBYTE lpData,
DWORD dwNumBytes)
{
DWORD i , iRemChars, iSlen;
DWORD *lpdw = (DWORD *)lpData;
char s[80] = "",m[80] = "";
iRemChars = 80;
for (i=0 ; i <= (dwNumBytes / sizeof(DWORD)); i++)
{
sprintf(s,"0x%08x ",*lpdw++);
iSlen = strlen(s);
if (iSlen < iRemChars)
{
strncat(m,s,iRemChars);
iRemChars -= iSlen;
}
if ( ((i % 6) == 5) ||
(i == (dwNumBytes / sizeof(DWORD))) )
{
DISPDBG((lvl,"%s",m));
s[0] = m[0] = '\0';
}
}
} // DumpVertices
//-----------------------------------------------------------------------------
//
// DumpDDSurface
//
// Dumps a LPDDRAWI_DDRAWSURFACE_LCL ( PDD_SURFACE_LOCAL on Win2K) structure
//
//-----------------------------------------------------------------------------
#define CAPS_REPORT(param) \
if (ddsCaps.dwCaps & DDSCAPS_##param) \
{ \
DISPDBG((Level, " " #param)); \
}
#define CAPS_REPORT2(param) \
if (pSurface->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_##param) \
{ \
DISPDBG((Level, " " #param)); \
}
void DumpDDSurface(int DebugLevel, LPDDRAWI_DDRAWSURFACE_LCL pSurface)
{
LPDDPIXELFORMAT pPixFormat;
P3_SURF_FORMAT* pFormatSurface = _DD_SUR_GetSurfaceFormat(pSurface);
DDSCAPS ddsCaps;
int Level = -100;
if (DebugLevel <= P3R3DX_DebugLevel)
{
DISPDBG((Level,"Surface Dump:"));
DISPDBG((Level,"Format: %s", pFormatSurface->pszStringFormat));
// Get the surface format
pPixFormat = DDSurf_GetPixelFormat(pSurface);
ddsCaps = pSurface->ddsCaps;
DISPDBG((Level, " Surface Width: 0x%x", pSurface->lpGbl->wWidth));
DISPDBG((Level, " Surface Height: 0x%x", pSurface->lpGbl->wHeight));
DISPDBG((Level, " Surface Pitch: 0x%x", pSurface->lpGbl->lPitch));
DISPDBG((Level, " ddsCaps.dwCaps: 0x%x", pSurface->ddsCaps.dwCaps));
DISPDBG((Level, " dwFlags: 0x%x", pSurface->dwFlags));
DISPDBG((Level, " Pixel Format:"));
DISPDBG((Level, " dwFourCC: 0x%x", pPixFormat->dwFourCC));
DISPDBG((Level, " dwRGBBitCount: 0x%x", pPixFormat->dwRGBBitCount));
DISPDBG((Level, " dwR/Y BitMask: 0x%x", pPixFormat->dwRBitMask));
DISPDBG((Level, " dwG/U BitMask: 0x%x", pPixFormat->dwGBitMask));
DISPDBG((Level, " dwB/V BitMask: 0x%x", pPixFormat->dwBBitMask));
DISPDBG((Level, " dwRGBAlphaBitMask: 0x%x", pPixFormat->dwRGBAlphaBitMask));
#ifndef WNT_DDRAW
DISPDBG((Level, " DestBlt: dwColorSpaceLowValue: 0x%x", pSurface->ddckCKDestBlt.dwColorSpaceLowValue));
DISPDBG((Level, " DestBlt: dwColorSpaceHighValue: 0x%x", pSurface->ddckCKDestBlt.dwColorSpaceHighValue));
DISPDBG((Level, " SrcBlt: dwColorSpaceLowValue: 0x%x", pSurface->ddckCKSrcBlt.dwColorSpaceLowValue));
DISPDBG((Level, " SrcBlt: dwColorSpaceHighValue: 0x%x", pSurface->ddckCKSrcBlt.dwColorSpaceHighValue));
#endif
DISPDBG((Level, " Surface Is:"));
CAPS_REPORT(TEXTURE);
CAPS_REPORT(PRIMARYSURFACE);
CAPS_REPORT(OFFSCREENPLAIN);
CAPS_REPORT(FRONTBUFFER);
CAPS_REPORT(BACKBUFFER);
CAPS_REPORT(COMPLEX);
CAPS_REPORT(FLIP);
CAPS_REPORT(OVERLAY);
CAPS_REPORT(MODEX);
CAPS_REPORT(ALLOCONLOAD);
CAPS_REPORT(LIVEVIDEO);
CAPS_REPORT(PALETTE);
CAPS_REPORT(SYSTEMMEMORY);
CAPS_REPORT(3DDEVICE);
CAPS_REPORT(VIDEOMEMORY);
CAPS_REPORT(VISIBLE);
CAPS_REPORT(MIPMAP);
// not supported in NT until we get NT5 (which will have DX5)
CAPS_REPORT(VIDEOPORT);
CAPS_REPORT(LOCALVIDMEM);
CAPS_REPORT(NONLOCALVIDMEM);
CAPS_REPORT(WRITEONLY);
if (pSurface->lpSurfMore)
{
CAPS_REPORT2(HARDWAREDEINTERLACE);
CAPS_REPORT2(HINTDYNAMIC);
CAPS_REPORT2(HINTSTATIC);
CAPS_REPORT2(TEXTUREMANAGE);
CAPS_REPORT2(OPAQUE);
CAPS_REPORT2(HINTANTIALIASING);
#if W95_DDRAW
CAPS_REPORT2(VERTEXBUFFER);
CAPS_REPORT2(COMMANDBUFFER);
#endif
}
if (pPixFormat->dwFlags & DDPF_ZBUFFER)
{
DISPDBG((Level," Z BUFFER"));
}
if (pPixFormat->dwFlags & DDPF_ALPHAPIXELS)
{
DISPDBG((Level," ALPHAPIXELS"));
}
// not supported in NT until we get NT5
if (pPixFormat->dwFlags & DDPF_LUMINANCE)
{
DISPDBG((Level," LUMINANCE"));
}
if (pPixFormat->dwFlags & DDPF_ALPHA)
{
DISPDBG((Level," ALPHA"));
}
}
} // DumpDDSurface
char *pcSimpleCapsString(DWORD dwCaps)
{
static char flags[5];
flags[0] = flags[1] = flags[2] = flags[3] = ' '; flags[4] = 0;
if(dwCaps & DDSCAPS_TEXTURE) flags[1] = 'T';
if(dwCaps & DDSCAPS_ZBUFFER) flags[2] = 'Z';
if(dwCaps & DDSCAPS_3DDEVICE) flags[3] = 'R';
if(dwCaps & DDSCAPS_VIDEOMEMORY)
{
flags[0] = 'V';
}
else if(dwCaps & DDSCAPS_NONLOCALVIDMEM)
{
flags[0] = 'A';
}
else
{
flags[0] = 'S';
}
return flags;
} // cSimpleCapsString
//-----------------------------------------------------------------------------
//
// DumpDDSurfaceDesc
//
// Dumps a DDSURFACEDESC structure
//
//-----------------------------------------------------------------------------
#define CAPS_REPORT_DESC(param) \
if (pDesc->ddsCaps.dwCaps & DDSCAPS_##param) \
{ \
DISPDBG((Level, " " #param)); \
}
#define CAPS_REPORT_DESC2(param) \
if (((DDSURFACEDESC2*)pDesc)->ddsCaps.dwCaps2 & DDSCAPS2_##param) \
{ \
DISPDBG((Level, " " #param)); \
}
void DumpDDSurfaceDesc(int DebugLevel, DDSURFACEDESC* pDesc)
{
DDPIXELFORMAT* pPixFormat = &pDesc->ddpfPixelFormat;
int Level = -100;
if (DebugLevel <= P3R3DX_DebugLevel)
{
DISPDBG((Level,"Surface Dump:"));
DISPDBG((Level, " Surface Width: 0x%x", pDesc->dwWidth));
DISPDBG((Level, " Surface Height: 0x%x", pDesc->dwHeight));
DISPDBG((Level, " ddsCaps.dwCaps: 0x%x", pDesc->ddsCaps.dwCaps));
DISPDBG((Level, " dwFlags: 0x%x", pDesc->dwFlags));
DISPDBG((Level, "Pixel Format:"));
DISPDBG((Level, " dwFourCC: 0x%x", pPixFormat->dwFourCC));
DISPDBG((Level, " dwRGBBitCount: 0x%x", pPixFormat->dwRGBBitCount));
DISPDBG((Level, " dwR/Y BitMask: 0x%x", pPixFormat->dwRBitMask));
DISPDBG((Level, " dwG/U BitMask: 0x%x", pPixFormat->dwGBitMask));
DISPDBG((Level, " dwB/V BitMask: 0x%x", pPixFormat->dwBBitMask));
DISPDBG((Level, " dwRGBAlphaBitMask: 0x%x", pPixFormat->dwRGBAlphaBitMask));
DISPDBG((Level, "Surface Is:"));
CAPS_REPORT_DESC(TEXTURE);
CAPS_REPORT_DESC(PRIMARYSURFACE);
CAPS_REPORT_DESC(OFFSCREENPLAIN);
CAPS_REPORT_DESC(FRONTBUFFER);
CAPS_REPORT_DESC(BACKBUFFER);
CAPS_REPORT_DESC(COMPLEX);
CAPS_REPORT_DESC(FLIP);
CAPS_REPORT_DESC(OVERLAY);
CAPS_REPORT_DESC(MODEX);
CAPS_REPORT_DESC(ALLOCONLOAD);
CAPS_REPORT_DESC(LIVEVIDEO);
CAPS_REPORT_DESC(PALETTE);
CAPS_REPORT_DESC(SYSTEMMEMORY);
CAPS_REPORT_DESC(3DDEVICE);
CAPS_REPORT_DESC(VIDEOMEMORY);
CAPS_REPORT_DESC(VISIBLE);
CAPS_REPORT_DESC(MIPMAP);
CAPS_REPORT_DESC(VIDEOPORT);
CAPS_REPORT_DESC(LOCALVIDMEM);
CAPS_REPORT_DESC(NONLOCALVIDMEM);
CAPS_REPORT_DESC(STANDARDVGAMODE);
CAPS_REPORT_DESC(OPTIMIZED);
CAPS_REPORT_DESC(EXECUTEBUFFER);
CAPS_REPORT_DESC(WRITEONLY);
if (pDesc->dwSize == sizeof(DDSURFACEDESC2))
{
CAPS_REPORT_DESC2(HARDWAREDEINTERLACE);
CAPS_REPORT_DESC2(HINTDYNAMIC);
CAPS_REPORT_DESC2(HINTSTATIC);
CAPS_REPORT_DESC2(TEXTUREMANAGE);
CAPS_REPORT_DESC2(OPAQUE);
CAPS_REPORT_DESC2(HINTANTIALIASING);
#if W95_DDRAW
CAPS_REPORT_DESC2(VERTEXBUFFER);
CAPS_REPORT_DESC2(COMMANDBUFFER);
#endif
}
if (pPixFormat->dwFlags & DDPF_ZBUFFER)
{
DISPDBG((Level," Z BUFFER"));
}
if (pPixFormat->dwFlags & DDPF_ALPHAPIXELS)
{
DISPDBG((Level," ALPHAPIXELS"));
}
if (pPixFormat->dwFlags & DDPF_ALPHA)
{
DISPDBG((Level," ALPHA"));
}
}
}
//-----------------------------------------------------------------------------
//
// DumpDP2Flags
//
// Dumps the meaning of the D3D DrawPrimitives2 flags
//
//-----------------------------------------------------------------------------
void
DumpDP2Flags( DWORD lvl, DWORD flags )
{
if( flags & D3DHALDP2_USERMEMVERTICES )
DISPDBG((lvl, " USERMEMVERTICES" ));
if( flags & D3DHALDP2_EXECUTEBUFFER )
DISPDBG((lvl, " EXECUTEBUFFER" ));
if( flags & D3DHALDP2_SWAPVERTEXBUFFER )
DISPDBG((lvl, " SWAPVERTEXBUFFER" ));
if( flags & D3DHALDP2_SWAPCOMMANDBUFFER )
DISPDBG((lvl, " SWAPCOMMANDBUFFER" ));
if( flags & D3DHALDP2_REQVERTEXBUFSIZE )
DISPDBG((lvl, " REQVERTEXBUFSIZE" ));
if( flags & D3DHALDP2_REQCOMMANDBUFSIZE )
DISPDBG((lvl, " REQCOMMANDBUFSIZE" ));
} // DumpDP2Flags
//-----------------------------------------------------------------------------
//
// ********************** LOW LEVEL DEBUGGING SUPPORT ************************
//
//-----------------------------------------------------------------------------
LONG P3R3DX_DebugLevel = 0;
#if W95_DDRAW
void DebugRIP()
{
_asm int 1;
}
#endif // W95_DDRAW
static char *BIG = "<+/-large_float>";
#if defined(_X86_)
void
expandFloats(char *flts, char *format, va_list argp)
{
int ch;
double f;
unsigned int ip, fp;
int *ap = (int *)argp;
int *dp = ap;
while (ch = *format++) {
if (ch == '%') {
ch = *format++; // Get the f, s, c, i, d, x etc...
if (!ch)
return; // If someone foolishly gave me "hello %"
switch (ch) {
case 'f':
case 'g':
case 'e':
// Here we have a double that needs
// replacing with a string equivalent.
f = *(double *)ap;
*(format - 1) = 's'; // Tell it to get a string next time!
*((char **)dp) = flts; // This is where I'll put the string
ap += 2; // Skip the double in the source
dp++; // Skip the new string pointer
if (f < 0)
{
*flts++ = '-';
f = -f;
}
if (f > LONG_MAX)
{
*((char **)ap - 2) = BIG;
break;
}
myFtoi((int*)&ip, (float)f);
// The state of the floating point flags is indeterminate here.
// You may get truncation which you want, you may get rounding,
// which you don't want.
if (ip > f)
{
// rounding will have made (ip = f+1) sometimes
ip -= 1;
}
{
double fTemp = ((f * 1e6) - (ip * 1e6));
myFtoi((int*)&fp, (float)fTemp);
}
#if W95_DDRAW
wsprintf(flts, "%u.%06u", ip, fp);
#endif
flts += 1 + strlen(flts); // advance the pointer to where
// the next float will be expanded
break;
case '%':
break;
default:
*dp++ = *ap++; // copy the argument (down) the list
break;
}
}
}
} // expandFloats()
#else
void
expandFloats(char *flts, char *format, va_list argp)
{
// do nothing if it's not _X86_
}
#endif // defined(_X86_)
#ifdef WNT_DDRAW
void Drv_strcpy(char *szDest, char *szSrc)
{
do
{
*szDest++ = *szSrc++;
} while (*szSrc != 0);
*szDest = '\0';
}
void __cdecl DebugPrintNT(LONG DebugPrintLevel, PCHAR DebugMessage, ...)
{
char floatstr[256];
char szFormat[256];
va_list ap;
va_start(ap, DebugMessage);
CheckChipErrorFlags();
if (DebugPrintLevel <= P3R3DX_DebugLevel)
{
Drv_strcpy(szFormat, DebugMessage);
expandFloats(floatstr, szFormat, ap);
EngDebugPrint("PERM3DD: ", szFormat, ap);
EngDebugPrint("", "\n", ap);
}
va_end(ap);
} // DebugPrint()
#else
#define START_STR "DX"
#define END_STR ""
//
// DebugPrint
//
// display a debug message
//
void __cdecl DebugPrint(LONG DebugLevelPrint, LPSTR format, ... )
{
char str[256];
char floatstr[256];
char szFormat[256];
va_list ap;
va_start(ap, format);
// If you set the debug level negative then you don't check the error
// flags - this lets an optimised debug build run quicker
if( P3R3DX_DebugLevel >= 0 )
{
CheckChipErrorFlags();
}
if (DebugLevelPrint <= P3R3DX_DebugLevel)
{
// Take a copy of the format string so that I can change "%f" to "%s".
lstrcpy(szFormat, format);
expandFloats(floatstr, szFormat, ap);
if (g_pThisTemp)
{
wsprintf((LPSTR)str, "%s(%d): ",
START_STR,
(int)g_pThisTemp->pGLInfo->dwCurrentContext);
}
else
{
wsprintf((LPSTR)str, "%s: 0 ", START_STR);
}
wvsprintf(str + strlen(START_STR) + 7, szFormat, ap);
wsprintf( str + strlen( str ), "%s", "\r\n" );
OutputDebugString( str );
}
va_end(ap);
} // DebugPrint
#endif // WNT_DDRAW
//-----------------------------------------------------------------------------
//
// ****************** HARDWARE DEPENDENT DEBUGGING SUPPORT *******************
//
//-----------------------------------------------------------------------------
P3_THUNKEDDATA* g_pThisTemp = NULL;
BOOL g_bDetectedFIFOError = FALSE;
BOOL CheckFIFOEntries(DWORD Count)
{
if (g_pThisTemp)
{
if (!g_bDetectedFIFOError)
{
g_pThisTemp->EntriesLeft -= Count;
g_pThisTemp->DMAEntriesLeft -= Count;
// TURN_ON_DISCONNECT will set Entries left to -20000
if ( ( (signed)g_pThisTemp->EntriesLeft < 0 ) &&
( (signed)g_pThisTemp->EntriesLeft > -10000 ) )
{
g_bDetectedFIFOError = TRUE;
return TRUE;
}
// Disconnects are irrelevant to DMA buffers.
if ( ( (signed)g_pThisTemp->DMAEntriesLeft < 0 ) &&
( (signed)g_pThisTemp->DMAEntriesLeft > -10000 ) )
{
g_bDetectedFIFOError = TRUE;
return TRUE;
}
}
}
return FALSE;
} // CheckFIFOEntries
#ifdef WNT_DDRAW
void
CheckChipErrorFlags()
{
char Buff[100];
if (g_pThisTemp != NULL)
{
P3_THUNKEDDATA* pThisDisplay = g_pThisTemp;
DWORD _temp_ul;
DWORD _temp_ul2;
_temp_ul = READ_GLINT_CTRL_REG(ErrorFlags);
_temp_ul2 = READ_GLINT_CTRL_REG(DeltaErrorFlags);
_temp_ul |= _temp_ul2;
_temp_ul &= ~0x2; // we're not interested in output fifo errors
_temp_ul &= ~0x10; // ignore any Video FIFO underrun errors on P2
_temp_ul &= ~0x2000; // ignore any host-in DMA errors
if (_temp_ul != 0)
{
// DISPDBG((-1000, "PERM3DD: %s", Buff));
//EngDebugBreak();
LOAD_GLINT_CTRL_REG(ErrorFlags, _temp_ul);
LOAD_GLINT_CTRL_REG(DeltaErrorFlags, _temp_ul);
}
}
} // CheckChipErrorFlags()
#else
void
CheckChipErrorFlags()
{
DWORD dw;
char buff[64];
if (!g_pThisTemp) return;
if (!g_pThisTemp->pGLInfo) return;
// Only check the error flags if we aren't DMA'ing.
if (!(g_pThisTemp->pGLInfo->GlintBoardStatus & GLINT_DMA_COMPLETE)) return;
if (g_pThisTemp->pGlint) {
dw = g_pThisTemp->pGlint->ErrorFlags & ~0x10;
if (dw & (dw != 2)) {
wsprintf(buff, "** Render Chip Error ** [0x%X]!\r\n", dw);
OutputDebugString(buff);
g_pThisTemp->pGlint->ErrorFlags = dw;
OutputDebugString("** Cleared... **\r\n");
DebugRIP();
}
dw = g_pThisTemp->pGlint->DeltaErrorFlags & ~0x10;
if (dw & (dw != 2)) {
wsprintf(buff, "** Delta Error ** [0x%X]!\r\n", dw);
OutputDebugString(buff);
g_pThisTemp->pGlint->DeltaErrorFlags = dw;
OutputDebugString("** Cleared... **\r\n");
DebugRIP();
}
}
} // CheckChipErrorFlags()
#endif // WNT_DDRAW
void
ColorArea(
ULONG_PTR pBuffer,
DWORD dwWidth,
DWORD dwHeight,
DWORD dwPitch,
int iBitDepth,
DWORD dwValue)
{
DWORD CountY;
DWORD CountX;
switch (iBitDepth)
{
case __GLINT_8BITPIXEL:
{
for (CountY = 0; CountY < dwHeight; CountY++)
{
BYTE* pCurrentPixel = (BYTE*)pBuffer;
for (CountX = 0; CountX < dwWidth; CountX++)
{
*pCurrentPixel++ = (BYTE)dwValue;
}
pBuffer += dwPitch;
}
}
break;
case __GLINT_16BITPIXEL:
{
for (CountY = 0; CountY < dwHeight; CountY++)
{
WORD* pCurrentPixel = (WORD*)pBuffer;
for (CountX = 0; CountX < dwWidth; CountX++)
{
*pCurrentPixel++ = (WORD)dwValue;
}
pBuffer += dwPitch;
}
}
break;
case __GLINT_32BITPIXEL:
case __GLINT_24BITPIXEL:
{
for (CountY = 0; CountY < dwHeight; CountY++)
{
DWORD* pCurrentPixel = (DWORD*)pBuffer;
for (CountX = 0; CountX < dwWidth; CountX++)
{
*pCurrentPixel++ = (DWORD)dwValue;
}
pBuffer += dwPitch;
}
}
break;
}
} // ColorArea
//@@BEGIN_DDKSPLIT
static int unitsBits[] = {
13, 12, 11, 10,
3, 2, 8, 7,
18, 15, 14, 6,
5, 1, 0
};
static char *unitNames[] = {
"HostOut", "FBWrite", "LogicOp", "Dither",
"Texture/Fog/Blend", "ColourDDA", "FBRead", "LBWrite",
"YUV", "TextureRead", "TextureAddress", "StencilDepth",
"LBRead", "Scissor/Stipple", "Rasterizer"
};
#define NUM_UNITS (sizeof(unitsBits) / sizeof(unitsBits[0]))
void
DisableChipUnits()
{
int i, count;
DWORD inSpace = g_pThisTemp->pGlint->InFIFOSpace;
BOOL helped = FALSE;
volatile DWORD *testReg;
volatile DWORD *addrMode = &g_pThisTemp->pGlint->TextureAddressMode;
DISPDBG((ERRLVL, "TextureAddressMode = 0x%08X", *addrMode));
i = 0;
testReg = &g_pThisTemp->pGlint->TestRegister;
for (count = 0; count < NUM_UNITS; count++) {
i = 1L << unitsBits[count];
*testReg = i;
*testReg = 0;
*testReg = i;
*testReg = 0;
if (inSpace != g_pThisTemp->pGlint->InFIFOSpace) {
DISPDBG((ERRLVL, "Chip unlocked by disabling unit \"%s\"", unitNames[count]));
helped = TRUE;
inSpace = g_pThisTemp->pGlint->InFIFOSpace;
}
}
if (helped) {
DISPDBG((ERRLVL, "Which helped..."));
} else {
DISPDBG((ERRLVL, "Chip still locked"));
*testReg = ~0UL;
*testReg = 0;
*testReg = ~0UL;
*testReg = 0;
if (inSpace == g_pThisTemp->pGlint->InFIFOSpace) {
DISPDBG((ERRLVL, "Writing -1 didn't help"));
} else {
DISPDBG((ERRLVL, "BUT! Writing -1 frees some space..."));
}
}
DISPDBG((ERRLVL, "TextureAddressMode = 0x%08X", *addrMode));
} // DisableChipUnits()
#if 0
StatRecord stats[LAST_STAT + 2] = {
{"Locks ", 0, 0},
{"TextureChanges", 0, 0},
{"D3DSynchs ", 0, 0},
{"StateChanges ", 0, 0},
{"...no change ", 0, 0},
{"Blits ", 0, 0},
{"DMA Buffers ", 0, 0},
{"DMA DWORDS ", 0, 0},
{"DMA time > CPU", 0, 0},
{"CPU time > DMA", 0, 0},
{"Wait on DMA ", 0, 0},
{"Execute ", 0, 0},
{"Tris ", 0, 0},
{"FF Tris ", 0, 0},
{"Vanilla Render", 0, 0},
{"Points ", 0, 0},
{"Lines ", 0, 0},
{"DPrm TFans ", 0, 0},
{"DPrm TStrps ", 0, 0},
{"DPrm TLists ", 0, 0},
{"DPrm TFansIdx ", 0, 0},
{"DPrm TStrpsIdx", 0, 0},
{"DPrm TListsIdx", 0, 0},
{"Total vertices", 0, 0},
{"...cached ", 0, 0},
{"Alpha strips ", 0, 0},
{"Mip strips ", 0, 0},
{"VALIDATEDEVICE", 0, 0},
// Add any extras just in front of this comment
{"**scene no** ", 0, 0},
{"**flip count**", 0, 0}
};
#endif
//@@END_DDKSPLIT
const char *getTagString( GlintDataPtr glintInfo, ULONG tag ) {
return p3r3TagString( tag & ((1 << 12) - 1) );
}
#endif // DBG