home *** CD-ROM | disk | FTP | other *** search
- // VirtualDub - Video processing and capture application
- // System library component
- // Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
- //
- // Beginning with 1.6.0, the VirtualDub system library is licensed
- // differently than the remainder of VirtualDub. This particular file is
- // thus licensed as follows (the "zlib" license):
- //
- // This software is provided 'as-is', without any express or implied
- // warranty. In no event will the authors be held liable for any
- // damages arising from the use of this software.
- //
- // Permission is granted to anyone to use this software for any purpose,
- // including commercial applications, and to alter it and redistribute it
- // freely, subject to the following restrictions:
- //
- // 1. The origin of this software must not be misrepresented; you must
- // not claim that you wrote the original software. If you use this
- // software in a product, an acknowledgment in the product
- // documentation would be appreciated but is not required.
- // 2. Altered source versions must be plainly marked as such, and must
- // not be misrepresented as being the original software.
- // 3. This notice may not be removed or altered from any source
- // distribution.
-
- #include "stdafx.h"
- #include <stdio.h>
-
- #include <windows.h>
- #include <intrin.h>
-
- #include <vd2/system/vdtypes.h>
- #include <vd2/system/cpuaccel.h>
- #include <vd2/system/debug.h>
- #include <vd2/system/thread.h>
-
- #ifdef _DEBUG
-
- class VDSafeMessageBoxThreadW32 : public VDThread {
- public:
- VDSafeMessageBoxThreadW32(HWND hwndParent, const char *pszText, const char *pszCaption, DWORD dwFlags)
- : mhwndParent(hwndParent)
- , mpszText(pszText)
- , mpszCaption(pszCaption)
- , mdwFlags(dwFlags)
- {
- }
-
- DWORD GetResult() const { return mdwResult; }
-
- protected:
- void ThreadRun() {
- mdwResult = MessageBox(mhwndParent, mpszText, mpszCaption, mdwFlags);
- }
-
- HWND mhwndParent;
- const char *const mpszText;
- const char *const mpszCaption;
- const DWORD mdwFlags;
- DWORD mdwResult;
- };
-
- UINT VDSafeMessageBoxW32(HWND hwndParent, const char *pszText, const char *pszCaption, DWORD dwFlags) {
- VDSafeMessageBoxThreadW32 mbox(hwndParent, pszText, pszCaption, dwFlags);
-
- mbox.ThreadStart();
- mbox.ThreadWait();
- return mbox.GetResult();
- }
-
- VDAssertResult VDAssert(const char *exp, const char *file, int line) {
- DWORD dwOldError = GetLastError();
- char szText[1024];
-
- VDDEBUG("%s(%d): Assert failed: %s\n", file, line, exp);
-
- wsprintf(szText,
- "Assert failed in module %s, line %d:\n"
- "\n"
- "\t%s\n"
- "\n"
- "Break into debugger?", file, line, exp);
-
- UINT result = VDSafeMessageBoxW32(NULL, szText, "Assert failure", MB_ABORTRETRYIGNORE|MB_ICONWARNING|MB_TASKMODAL);
-
- SetLastError(dwOldError);
-
- switch(result) {
- case IDABORT:
- ::Sleep(250); // Pause for a moment so the VC6 debugger doesn't freeze.
- return kVDAssertBreak;
- case IDRETRY:
- return kVDAssertContinue;
- default:
- VDNEVERHERE;
- case IDIGNORE:
- return kVDAssertIgnore;
- }
- }
-
- VDAssertResult VDAssertPtr(const char *exp, const char *file, int line) {
- DWORD dwOldError = GetLastError();
- char szText[1024];
-
- VDDEBUG("%s(%d): Assert failed: %s is not a valid pointer\n", file, line, exp);
-
- wsprintf(szText,
- "Assert failed in module %s, line %d:\n"
- "\n"
- "\t(%s) not a valid pointer\n"
- "\n"
- "Break into debugger?", file, line, exp);
-
- UINT result = VDSafeMessageBoxW32(NULL, szText, "Assert failure", MB_ABORTRETRYIGNORE|MB_ICONWARNING|MB_TASKMODAL);
-
- SetLastError(dwOldError);
-
- switch(result) {
- case IDABORT:
- return kVDAssertBreak;
- case IDRETRY:
- return kVDAssertContinue;
- default:
- VDNEVERHERE;
- case IDIGNORE:
- return kVDAssertIgnore;
- }
- }
-
- #endif
-
- void VDProtectedAutoScopeICLWorkaround() {}
-
- void VDDebugPrint(const char *format, ...) {
- char buf[4096];
-
- va_list val;
- va_start(val, format);
- _vsnprintf(buf, sizeof buf, format, val);
- va_end(val);
- Sleep(0);
- OutputDebugString(buf);
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- namespace {
- IVDExternalCallTrap *g_pExCallTrap;
- }
-
- void VDSetExternalCallTrap(IVDExternalCallTrap *trap) {
- g_pExCallTrap = trap;
- }
-
- #if defined(WIN32) && defined(_M_IX86)
- namespace {
- bool IsFPUStateOK(unsigned& ctlword) {
- ctlword = 0;
-
- __asm mov eax, ctlword
- __asm fnstcw [eax]
-
- ctlword &= 0x0f3f;
-
- return ctlword == 0x023f;
- }
-
- void ResetFPUState() {
- static const unsigned ctlword = 0x027f;
-
- __asm fnclex
- __asm fldcw ctlword
- }
-
- bool IsSSEStateOK(uint32& ctlword) {
- ctlword = _mm_getcsr();
-
- // Intel C/C++ flips FTZ and DAZ. :(
- return (ctlword & 0x7f80) == 0x1f80;
- }
-
- void ResetSSEState() {
- _mm_setcsr(0x1f80);
- }
- }
-
- bool IsMMXState() {
- char buf[28];
- unsigned short tagword;
-
- __asm fnstenv buf // this resets the FPU control word somehow!?
-
- tagword = *(unsigned short *)(buf + 8);
-
- return (tagword != 0xffff);
- }
- void ClearMMXState() {
- if (MMX_enabled)
- __asm emms
- else {
- __asm {
- ffree st(0)
- ffree st(1)
- ffree st(2)
- ffree st(3)
- ffree st(4)
- ffree st(5)
- ffree st(6)
- ffree st(7)
- }
- }
- }
-
- void VDClearEvilCPUStates() {
- ResetFPUState();
- ClearMMXState();
- }
-
- void VDPreCheckExternalCodeCall(const char *file, int line) {
- unsigned fpucw;
- uint32 mxcsr;
- bool bFPUStateBad = !IsFPUStateOK(fpucw);
- bool bSSEStateBad = SSE_enabled && !IsSSEStateOK(mxcsr);
- bool bMMXStateBad = IsMMXState();
-
- if (bMMXStateBad || bFPUStateBad || bSSEStateBad) {
- ClearMMXState();
- ResetFPUState();
- if (SSE_enabled)
- ResetSSEState();
- }
-
- if (g_pExCallTrap) {
- if (bMMXStateBad)
- g_pExCallTrap->OnMMXTrap(NULL, file, line);
-
- if (bFPUStateBad)
- g_pExCallTrap->OnFPUTrap(NULL, file, line, fpucw);
-
- if (bSSEStateBad)
- g_pExCallTrap->OnSSETrap(NULL, file, line, mxcsr);
- }
- }
-
- void VDPostCheckExternalCodeCall(const wchar_t *mpContext, const char *mpFile, int mLine) {
- unsigned fpucw;
- uint32 mxcsr;
- bool bFPUStateBad = !IsFPUStateOK(fpucw);
- bool bSSEStateBad = SSE_enabled && !IsSSEStateOK(mxcsr);
- bool bMMXStateBad = IsMMXState();
- bool bBadState = bMMXStateBad || bFPUStateBad || bSSEStateBad;
-
- if (bBadState) {
- ClearMMXState();
- ResetFPUState();
- if (SSE_enabled)
- ResetSSEState();
- }
-
- if (g_pExCallTrap) {
- if (bMMXStateBad)
- g_pExCallTrap->OnMMXTrap(mpContext, mpFile, mLine);
-
- if (bFPUStateBad)
- g_pExCallTrap->OnFPUTrap(mpContext, mpFile, mLine, fpucw);
-
- if (bSSEStateBad)
- g_pExCallTrap->OnSSETrap(mpContext, mpFile, mLine, mxcsr);
- }
- }
-
- #else
-
- bool IsMMXState() {
- return false;
- }
-
- void ClearMMXState() {
- }
-
- void VDClearEvilCPUStates() {
- }
-
- void VDPreCheckExternalCodeCall(const char *file, int line) {
- }
-
- void VDPostCheckExternalCodeCall(const wchar_t *mpContext, const char *mpFile, int mLine) {
- }
-
- #endif
-