mirror of
https://github.com/libretro/pcsx2.git
synced 2024-12-02 23:26:43 +00:00
9c77896f2d
surprisingly, GSdx never ran into this issue prior as linux didn't use baseclasses but used wxwidgets, while windows did but used the winAPI GUI system. Software is cursed
354 lines
12 KiB
C++
354 lines
12 KiB
C++
//------------------------------------------------------------------------------
|
|
// File: WXDebug.h
|
|
//
|
|
// Desc: DirectShow base classes - provides debugging facilities.
|
|
//
|
|
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
#pragma once
|
|
|
|
// This library provides fairly straight forward debugging functionality, this
|
|
// is split into two main sections. The first is assertion handling, there are
|
|
// three types of assertions provided here. The most commonly used one is the
|
|
// ASSERT(condition) macro which will pop up a message box including the file
|
|
// and line number if the condition evaluates to FALSE. Then there is the
|
|
// EXECUTE_ASSERT macro which is the same as ASSERT except the condition will
|
|
// still be executed in NON debug builds. The final type of assertion is the
|
|
// KASSERT macro which is more suitable for pure (perhaps kernel) filters as
|
|
// the condition is printed onto the debugger rather than in a message box.
|
|
//
|
|
// The other part of the debug module facilties is general purpose logging.
|
|
// This is accessed by calling DbgLog(). The function takes a type and level
|
|
// field which define the type of informational string you are presenting and
|
|
// it's relative importance. The type field can be a combination (one or more)
|
|
// of LOG_TIMING, LOG_TRACE, LOG_MEMORY, LOG_LOCKING and LOG_ERROR. The level
|
|
// is a DWORD value where zero defines highest important. Use of zero as the
|
|
// debug logging level is to be encouraged ONLY for major errors or events as
|
|
// they will ALWAYS be displayed on the debugger. Other debug output has it's
|
|
// level matched against the current debug output level stored in the registry
|
|
// for this module and if less than the current setting it will be displayed.
|
|
//
|
|
// Each module or executable has it's own debug output level for each of the
|
|
// five types. These are read in when the DbgInitialise function is called
|
|
// for DLLs linking to STRMBASE.LIB this is done automatically when the DLL
|
|
// is loaded, executables must call it explicitely with the module instance
|
|
// handle given to them through the WINMAIN entry point. An executable must
|
|
// also call DbgTerminate when they have finished to clean up the resources
|
|
// the debug library uses, once again this is done automatically for DLLs
|
|
|
|
// These are the five different categories of logging information
|
|
|
|
enum { LOG_TIMING = 0x01, // Timing and performance measurements
|
|
LOG_TRACE = 0x02, // General step point call tracing
|
|
LOG_MEMORY = 0x04, // Memory and object allocation/destruction
|
|
LOG_LOCKING = 0x08, // Locking/unlocking of critical sections
|
|
LOG_ERROR = 0x10, // Debug error notification
|
|
LOG_CUSTOM1 = 0x20,
|
|
LOG_CUSTOM2 = 0x40,
|
|
LOG_CUSTOM3 = 0x80,
|
|
LOG_CUSTOM4 = 0x100,
|
|
LOG_CUSTOM5 = 0x200,
|
|
};
|
|
|
|
#define LOG_FORCIBLY_SET 0x80000000
|
|
|
|
enum { CDISP_HEX = 0x01,
|
|
CDISP_DEC = 0x02};
|
|
|
|
// For each object created derived from CBaseObject (in debug builds) we
|
|
// create a descriptor that holds it's name (statically allocated memory)
|
|
// and a cookie we assign it. We keep a list of all the active objects
|
|
// we have registered so that we can dump a list of remaining objects
|
|
|
|
typedef struct tag_ObjectDesc {
|
|
LPCSTR m_szName;
|
|
LPCWSTR m_wszName;
|
|
DWORD m_dwCookie;
|
|
tag_ObjectDesc *m_pNext;
|
|
} ObjectDesc;
|
|
|
|
#define DLLIMPORT __declspec(dllimport)
|
|
#define DLLEXPORT __declspec(dllexport)
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define NAME(x) TEXT(x)
|
|
|
|
// These are used internally by the debug library (PRIVATE)
|
|
|
|
void WINAPI DbgInitKeyLevels(HKEY hKey, bool fTakeMax);
|
|
void WINAPI DbgInitGlobalSettings(bool fTakeMax);
|
|
void WINAPI DbgInitModuleSettings(bool fTakeMax);
|
|
void WINAPI DbgInitModuleName();
|
|
DWORD WINAPI DbgRegisterObjectCreation(
|
|
LPCSTR szObjectName, LPCWSTR wszObjectName);
|
|
|
|
BOOL WINAPI DbgRegisterObjectDestruction(DWORD dwCookie);
|
|
|
|
// These are the PUBLIC entry points
|
|
|
|
BOOL WINAPI DbgCheckModuleLevel(DWORD Type,DWORD Level);
|
|
void WINAPI DbgSetModuleLevel(DWORD Type,DWORD Level);
|
|
void WINAPI DbgSetAutoRefreshLevels(bool fAuto);
|
|
|
|
// Initialise the library with the module handle
|
|
|
|
void WINAPI DbgInitialise(HINSTANCE hInst);
|
|
void WINAPI DbgTerminate();
|
|
|
|
void WINAPI DbgDumpObjectRegister();
|
|
|
|
// Display error and logging to the user
|
|
|
|
void WINAPI DbgAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
|
|
void WINAPI DbgBreakPoint(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
|
|
void WINAPI DbgBreakPoint(LPCTSTR pFileName,INT iLine,__format_string LPCTSTR szFormatString,...);
|
|
|
|
void WINAPI DbgKernelAssert(LPCTSTR pCondition,LPCTSTR pFileName,INT iLine);
|
|
void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCTSTR pFormat,...);
|
|
#ifdef UNICODE
|
|
void WINAPI DbgLogInfo(DWORD Type,DWORD Level,__format_string LPCSTR pFormat,...);
|
|
void WINAPI DbgAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
|
|
void WINAPI DbgBreakPoint(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
|
|
void WINAPI DbgKernelAssert(LPCSTR pCondition,LPCSTR pFileName,INT iLine);
|
|
#endif
|
|
void WINAPI DbgOutString(LPCTSTR psz);
|
|
|
|
// Debug infinite wait stuff
|
|
DWORD WINAPI DbgWaitForSingleObject(HANDLE h);
|
|
DWORD WINAPI DbgWaitForMultipleObjects(DWORD nCount,
|
|
__in_ecount(nCount) CONST HANDLE *lpHandles,
|
|
BOOL bWaitAll);
|
|
void WINAPI DbgSetWaitTimeout(DWORD dwTimeout);
|
|
|
|
#ifdef __strmif_h__
|
|
// Display a media type: Terse at level 2, verbose at level 5
|
|
void WINAPI DisplayType(LPCTSTR label, const AM_MEDIA_TYPE *pmtIn);
|
|
|
|
// Dump lots of information about a filter graph
|
|
void WINAPI DumpGraph(IFilterGraph *pGraph, DWORD dwLevel);
|
|
#endif
|
|
|
|
#define KASSERT(_x_) if (!(_x_)) \
|
|
DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
|
|
|
|
// Break on the debugger without putting up a message box
|
|
// message goes to debugger instead
|
|
|
|
#define KDbgBreak(_x_) \
|
|
DbgKernelAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
|
|
|
|
// We chose a common name for our ASSERT macro, MFC also uses this name
|
|
// So long as the implementation evaluates the condition and handles it
|
|
// then we will be ok. Rather than override the behaviour expected we
|
|
// will leave whatever first defines ASSERT as the handler (i.e. MFC)
|
|
#ifndef ASSERT
|
|
#define ASSERT(_x_) if (!(_x_)) \
|
|
DbgAssert(TEXT(#_x_),TEXT(__FILE__),__LINE__)
|
|
#endif
|
|
|
|
#define DbgAssertAligned( _ptr_, _alignment_ ) ASSERT( ((DWORD_PTR) (_ptr_)) % (_alignment_) == 0)
|
|
|
|
// Put up a message box informing the user of a halt
|
|
// condition in the program
|
|
|
|
#define DbgBreak(_x_) \
|
|
DbgBreakPoint(TEXT(#_x_),TEXT(__FILE__),__LINE__)
|
|
|
|
#define EXECUTE_ASSERT(_x_) ASSERT(_x_)
|
|
#define DbgLog(_x_) DbgLogInfo _x_
|
|
// MFC style trace macros
|
|
|
|
#define NOTE(_x_) DbgLog((LOG_TRACE,5,TEXT(_x_)))
|
|
#define NOTE1(_x_,a) DbgLog((LOG_TRACE,5,TEXT(_x_),a))
|
|
#define NOTE2(_x_,a,b) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b))
|
|
#define NOTE3(_x_,a,b,c) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c))
|
|
#define NOTE4(_x_,a,b,c,d) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d))
|
|
#define NOTE5(_x_,a,b,c,d,e) DbgLog((LOG_TRACE,5,TEXT(_x_),a,b,c,d,e))
|
|
|
|
#else
|
|
|
|
// Retail builds make public debug functions inert - WARNING the source
|
|
// files do not define or build any of the entry points in debug builds
|
|
// (public entry points compile to nothing) so if you go trying to call
|
|
// any of the private entry points in your source they won't compile
|
|
|
|
#define NAME(_x_) ((LPTSTR) NULL)
|
|
|
|
#define DbgInitialise(hInst)
|
|
#define DbgTerminate()
|
|
#define DbgLog(_x_) 0
|
|
#define DbgOutString(psz)
|
|
#define DbgAssertAligned( _ptr_, _alignment_ ) 0
|
|
|
|
#define DbgRegisterObjectCreation(pObjectName)
|
|
#define DbgRegisterObjectDestruction(dwCookie)
|
|
#define DbgDumpObjectRegister()
|
|
|
|
#define DbgCheckModuleLevel(Type,Level)
|
|
#define DbgSetModuleLevel(Type,Level)
|
|
#define DbgSetAutoRefreshLevels(fAuto)
|
|
|
|
#define DbgWaitForSingleObject(h) WaitForSingleObject(h, INFINITE)
|
|
#define DbgWaitForMultipleObjects(nCount, lpHandles, bWaitAll) \
|
|
WaitForMultipleObjects(nCount, lpHandles, bWaitAll, INFINITE)
|
|
#define DbgSetWaitTimeout(dwTimeout)
|
|
|
|
#define KDbgBreak(_x_)
|
|
#define DbgBreak(_x_)
|
|
|
|
#define KASSERT(_x_) ((void)0)
|
|
#ifndef ASSERT
|
|
#define ASSERT(_x_) ((void)0)
|
|
#endif
|
|
#define EXECUTE_ASSERT(_x_) ((void)(_x_))
|
|
|
|
// MFC style trace macros
|
|
|
|
#define NOTE(_x_) ((void)0)
|
|
#define NOTE1(_x_,a) ((void)0)
|
|
#define NOTE2(_x_,a,b) ((void)0)
|
|
#define NOTE3(_x_,a,b,c) ((void)0)
|
|
#define NOTE4(_x_,a,b,c,d) ((void)0)
|
|
#define NOTE5(_x_,a,b,c,d,e) ((void)0)
|
|
|
|
#define DisplayType(label, pmtIn) ((void)0)
|
|
#define DumpGraph(pGraph, label) ((void)0)
|
|
#endif
|
|
|
|
|
|
// Checks a pointer which should be non NULL - can be used as follows.
|
|
|
|
#define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
|
|
|
|
// HRESULT Foo(VOID *pBar)
|
|
// {
|
|
// CheckPointer(pBar,E_INVALIDARG)
|
|
// }
|
|
//
|
|
// Or if the function returns a boolean
|
|
//
|
|
// BOOL Foo(VOID *pBar)
|
|
// {
|
|
// CheckPointer(pBar,FALSE)
|
|
// }
|
|
|
|
#define ValidateReadPtr(p,cb) 0
|
|
#define ValidateWritePtr(p,cb) 0
|
|
#define ValidateReadWritePtr(p,cb) 0
|
|
#define ValidateStringPtr(p) 0
|
|
#define ValidateStringPtrA(p) 0
|
|
#define ValidateStringPtrW(p) 0
|
|
|
|
|
|
#ifdef _OBJBASE_H_
|
|
|
|
// Outputting GUID names. If you want to include the name
|
|
// associated with a GUID (eg CLSID_...) then
|
|
//
|
|
// GuidNames[yourGUID]
|
|
//
|
|
// Returns the name defined in uuids.h as a string
|
|
|
|
typedef struct {
|
|
CHAR *szName;
|
|
GUID guid;
|
|
} GUID_STRING_ENTRY;
|
|
|
|
class CGuidNameList {
|
|
public:
|
|
CHAR *operator [] (const GUID& guid);
|
|
};
|
|
|
|
extern CGuidNameList GuidNames;
|
|
|
|
#endif
|
|
|
|
#ifndef REMIND
|
|
// REMIND macro - generates warning as reminder to complete coding
|
|
// (eg) usage:
|
|
//
|
|
// #pragma message (REMIND("Add automation support"))
|
|
|
|
|
|
#define QUOTE(x) #x
|
|
#define QQUOTE(y) QUOTE(y)
|
|
#define REMIND(str) __FILE__ "(" QQUOTE(__LINE__) ") : " str
|
|
#endif
|
|
|
|
// Method to display objects in a useful format
|
|
//
|
|
// eg If you want to display a LONGLONG ll in a debug string do (eg)
|
|
//
|
|
// DbgLog((LOG_TRACE, n, TEXT("Value is %s"), (LPCTSTR)CDisp(ll, CDISP_HEX)));
|
|
|
|
|
|
class CDispBasic
|
|
{
|
|
public:
|
|
CDispBasic() { m_pString = m_String; };
|
|
~CDispBasic();
|
|
protected:
|
|
PTCHAR m_pString; // normally points to m_String... unless too much data
|
|
TCHAR m_String[50];
|
|
};
|
|
class CDisp : public CDispBasic
|
|
{
|
|
public:
|
|
CDisp(LONGLONG ll, int Format = CDISP_HEX); // Display a LONGLONG in CDISP_HEX or CDISP_DEC form
|
|
CDisp(REFCLSID clsid); // Display a GUID
|
|
CDisp(double d); // Display a floating point number
|
|
#ifdef __strmif_h__
|
|
#ifdef __STREAMS__
|
|
CDisp(CRefTime t); // Display a Reference Time
|
|
#endif
|
|
CDisp(IPin *pPin); // Display a pin as {filter clsid}(pin name)
|
|
CDisp(IUnknown *pUnk); // Display a filter or pin
|
|
#endif // __strmif_h__
|
|
~CDisp();
|
|
|
|
// Implement cast to (LPCTSTR) as parameter to logger
|
|
operator LPCTSTR()
|
|
{
|
|
return (LPCTSTR)m_pString;
|
|
};
|
|
};
|
|
|
|
|
|
#if defined(DEBUG)
|
|
class CAutoTrace
|
|
{
|
|
private:
|
|
LPCTSTR _szBlkName;
|
|
const int _level;
|
|
static const TCHAR _szEntering[];
|
|
static const TCHAR _szLeaving[];
|
|
public:
|
|
CAutoTrace(LPCTSTR szBlkName, const int level = 15)
|
|
: _szBlkName(szBlkName), _level(level)
|
|
{DbgLog((LOG_TRACE, _level, _szEntering, _szBlkName));}
|
|
|
|
~CAutoTrace()
|
|
{DbgLog((LOG_TRACE, _level, _szLeaving, _szBlkName));}
|
|
};
|
|
|
|
#if defined (__FUNCTION__)
|
|
|
|
#define AMTRACEFN() CAutoTrace __trace(TEXT(__FUNCTION__))
|
|
#define AMTRACE(_x_) CAutoTrace __trace(TEXT(__FUNCTION__))
|
|
|
|
#else
|
|
|
|
#define AMTRACE(_x_) CAutoTrace __trace _x_
|
|
#define AMTRACEFN()
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
#define AMTRACE(_x_)
|
|
#define AMTRACEFN()
|
|
|
|
#endif |