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
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
|
|
|