// This code contains NVIDIA Confidential Information and is disclosed // under the Mutual Non-Disclosure Agreement. // // Notice // ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES // NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO // THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT, // MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. // // NVIDIA Corporation assumes no responsibility for the consequences of use of such // information or for any infringement of patents or other rights of third parties that may // result from its use. No license is granted by implication or otherwise under any patent // or patent rights of NVIDIA Corporation. No third party distribution is allowed unless // expressly authorized by NVIDIA. Details are subject to change without notice. // This code supersedes and replaces all information previously supplied. // NVIDIA Corporation products are not authorized for use as critical // components in life support devices or systems without express written approval of // NVIDIA Corporation. // // Copyright © 2008- 2013 NVIDIA Corporation. All rights reserved. // // NVIDIA Corporation and its licensors retain all intellectual property and proprietary // rights in and to this software and related documentation and any modifications thereto. // Any use, reproduction, disclosure or distribution of this software and related // documentation without an express license agreement from NVIDIA Corporation is // strictly prohibited. // //-------------------------------------------------------------------------------------- // File: SDKmisc.cpp // // Various helper functionality that is shared between SDK samples // // Copyright (c) Microsoft Corporation. All rights reserved //-------------------------------------------------------------------------------------- #include "dxstdafx.h" #include "dxut.h" #include "SDKmisc.h" #include "DXUTres.h" #undef min // use __min instead #undef max // use __max instead //-------------------------------------------------------------------------------------- // Global/Static Members //-------------------------------------------------------------------------------------- CDXUTResourceCache& WINAPI DXUTGetGlobalResourceCache() { // Using an accessor function gives control of the construction order static CDXUTResourceCache cache; return cache; } //-------------------------------------------------------------------------------------- // Internal functions forward declarations //-------------------------------------------------------------------------------------- bool DXUTFindMediaSearchTypicalDirs( __in_ecount(cchSearch) WCHAR* strSearchPath, int cchSearch, __in LPCWSTR strLeaf, __in WCHAR* strExePath, __in WCHAR* strExeName ); bool DXUTFindMediaSearchParentDirs( __in_ecount(cchSearch) WCHAR* strSearchPath, int cchSearch, __in WCHAR* strStartAt, __in WCHAR* strLeafName ); INT_PTR CALLBACK DisplaySwitchToREFWarningProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ); //-------------------------------------------------------------------------------------- // Shared code for samples to ask user if they want to use a REF device or quit //-------------------------------------------------------------------------------------- void WINAPI DXUTDisplaySwitchingToREFWarning( DXUTDeviceVersion ver ) { if( DXUTGetShowMsgBoxOnError() ) { DWORD dwSkipWarning = 0, dwRead = 0, dwWritten = 0; HANDLE hFile = NULL; // Read previous user settings WCHAR strPath[MAX_PATH]; SHGetFolderPath( DXUTGetHWND(), CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, strPath ); wcscat_s( strPath, MAX_PATH, L"\\DXUT\\SkipRefWarning.dat" ); if( ( hFile = CreateFile( strPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ) ) != INVALID_HANDLE_VALUE ) { ReadFile( hFile, &dwSkipWarning, sizeof( DWORD ), &dwRead, NULL ); CloseHandle( hFile ); } if( dwSkipWarning == 0 ) { // Compact code to create a custom dialog box without using a template in a resource file. // If this dialog were in a .rc file, this would be a lot simpler but every sample calling this function would // need a copy of the dialog in its own .rc file. Also MessageBox API could be used here instead, but // the MessageBox API is simpler to call but it can't provide a "Don't show again" checkbox typedef struct { DLGITEMTEMPLATE a; WORD b; WORD c; WORD d; WORD e; WORD f; } DXUT_DLG_ITEM; typedef struct { DLGTEMPLATE a; WORD b; WORD c; WCHAR d[2]; WORD e; WCHAR f[16]; DXUT_DLG_ITEM i1; DXUT_DLG_ITEM i2; DXUT_DLG_ITEM i3; DXUT_DLG_ITEM i4; DXUT_DLG_ITEM i5; } DXUT_DLG_DATA; DXUT_DLG_DATA dtp = { {WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_SYSMENU | DS_ABSALIGN | DS_3DLOOK | DS_SETFONT | DS_MODALFRAME | DS_CENTER,0,5,0,0,269,82},0,0,L" ",8,L"MS Shell Dlg 2", { {WS_CHILD | WS_VISIBLE | SS_ICON | SS_CENTERIMAGE,0,7,7,24,24,0x100},0xFFFF,0x0082,0,0,0}, // icon { {WS_CHILD | WS_VISIBLE,0,40,7,230,25,0x101},0xFFFF,0x0082,0,0,0}, // static text { {WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,0,80,39,50,14,IDYES},0xFFFF,0x0080,0,0,0}, // Yes button { {WS_CHILD | WS_VISIBLE | WS_TABSTOP,0,133,39,50,14,IDNO},0xFFFF,0x0080,0,0,0}, // No button { {WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX,0,7,59,70,16,IDIGNORE},0xFFFF,0x0080,0,0,0}, // checkbox }; int nResult = ( int )DialogBoxIndirectParam( DXUTGetHINSTANCE(), ( DLGTEMPLATE* )&dtp, DXUTGetHWND(), DisplaySwitchToREFWarningProc, ( LPARAM ) ( ver == DXUT_D3D9_DEVICE ) ? 9 : 10 ); if( ( nResult & 0x80 ) == 0x80 ) // "Don't show again" checkbox was checked { // Save user settings dwSkipWarning = 1; SHGetFolderPath( DXUTGetHWND(), CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, strPath ); wcscat_s( strPath, MAX_PATH, L"\\DXUT" ); CreateDirectory( strPath, NULL ); wcscat_s( strPath, MAX_PATH, L"\\SkipRefWarning.dat" ); if( ( hFile = CreateFile( strPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL ) ) != INVALID_HANDLE_VALUE ) { WriteFile( hFile, &dwSkipWarning, sizeof( DWORD ), &dwWritten, NULL ); CloseHandle( hFile ); } } // User choose not to continue if( ( nResult & 0x0F ) == IDNO ) DXUTShutdown( 1 ); } } } //-------------------------------------------------------------------------------------- // MsgProc for DXUTDisplaySwitchingToREFWarning() dialog box //-------------------------------------------------------------------------------------- INT_PTR CALLBACK DisplaySwitchToREFWarningProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ) { case WM_INITDIALOG: // Easier to set text here than in the DLGITEMTEMPLATE SetWindowText( hDlg, DXUTGetWindowTitle() ); SendMessage( GetDlgItem( hDlg, 0x100 ), STM_SETIMAGE, IMAGE_ICON, ( LPARAM )LoadIcon( 0, IDI_QUESTION ) ); WCHAR sz[512]; swprintf_s( sz, 512, L"This program needs to use the Direct3D %d reference device. This device implements the entire Direct3D %d feature set, but runs very slowly. Do you wish to continue?", lParam, lParam ); SetDlgItemText( hDlg, 0x101, sz ); SetDlgItemText( hDlg, IDYES, L"&Yes" ); SetDlgItemText( hDlg, IDNO, L"&No" ); SetDlgItemText( hDlg, IDIGNORE, L"&Don't show again" ); break; case WM_COMMAND: switch( LOWORD( wParam ) ) { case IDIGNORE: CheckDlgButton( hDlg, IDIGNORE, ( IsDlgButtonChecked( hDlg, IDIGNORE ) == BST_CHECKED ) ? BST_UNCHECKED : BST_CHECKED ); EnableWindow( GetDlgItem( hDlg, IDNO ), ( IsDlgButtonChecked( hDlg, IDIGNORE ) != BST_CHECKED ) ); break; case IDNO: EndDialog( hDlg, ( IsDlgButtonChecked( hDlg, IDIGNORE ) == BST_CHECKED ) ? IDNO | 0x80 : IDNO | 0x00 ); return TRUE; case IDCANCEL: case IDYES: EndDialog( hDlg, ( IsDlgButtonChecked( hDlg, IDIGNORE ) == BST_CHECKED ) ? IDYES | 0x80 : IDYES | 0x00 ); return TRUE; } break; } return FALSE; } //-------------------------------------------------------------------------------------- // Returns pointer to static media search buffer //-------------------------------------------------------------------------------------- WCHAR* DXUTMediaSearchPath() { static WCHAR s_strMediaSearchPath[MAX_PATH] = {0}; return s_strMediaSearchPath; } //-------------------------------------------------------------------------------------- LPCWSTR WINAPI DXUTGetMediaSearchPath() { return DXUTMediaSearchPath(); } //-------------------------------------------------------------------------------------- HRESULT WINAPI DXUTSetMediaSearchPath( LPCWSTR strPath ) { HRESULT hr = S_OK; WCHAR* s_strSearchPath = DXUTMediaSearchPath(); hr = wcscpy_s( s_strSearchPath, MAX_PATH, strPath ); if( SUCCEEDED( hr ) ) { // append slash if needed size_t ch; ch = wcslen( s_strSearchPath); if( SUCCEEDED( hr ) && s_strSearchPath[ch - 1] != L'\\' ) { hr = wcscat_s( s_strSearchPath, MAX_PATH, L"\\" ); } } return hr; } //-------------------------------------------------------------------------------------- // Tries to find the location of a SDK media file // cchDest is the size in WCHARs of strDestPath. Be careful not to // pass in sizeof(strDest) on UNICODE builds. //-------------------------------------------------------------------------------------- HRESULT WINAPI DXUTFindDXSDKMediaFileCch( __in_ecount(cchDest) WCHAR* strDestPath, int cchDest, __in LPCWSTR strFilename ) { bool bFound; WCHAR strSearchFor[MAX_PATH]; if( NULL == strFilename || strFilename[0] == 0 || NULL == strDestPath || cchDest < 10 ) return E_INVALIDARG; // Get the exe name, and exe path WCHAR strExePath[MAX_PATH] = {0}; WCHAR strExeName[MAX_PATH] = {0}; WCHAR* strLastSlash = NULL; GetModuleFileName( NULL, strExePath, MAX_PATH ); strExePath[MAX_PATH - 1] = 0; strLastSlash = wcsrchr( strExePath, TEXT( '\\' ) ); if( strLastSlash ) { wcscpy_s( strExeName, MAX_PATH, &strLastSlash[1] ); // Chop the exe name from the exe path *strLastSlash = 0; // Chop the .exe from the exe name strLastSlash = wcsrchr( strExeName, TEXT( '.' ) ); if( strLastSlash ) *strLastSlash = 0; } // Typical directories: // .\ // ..\ // ..\..\ // %EXE_DIR%\ // %EXE_DIR%\..\ // %EXE_DIR%\..\..\ // %EXE_DIR%\..\%EXE_NAME% // %EXE_DIR%\..\..\%EXE_NAME% // Typical directory search bFound = DXUTFindMediaSearchTypicalDirs( strDestPath, cchDest, strFilename, strExePath, strExeName ); if( bFound ) return S_OK; // Typical directory search again, but also look in a subdir called "\media\" swprintf_s( strSearchFor, MAX_PATH, L"media\\%s", strFilename ); bFound = DXUTFindMediaSearchTypicalDirs( strDestPath, cchDest, strSearchFor, strExePath, strExeName ); if( bFound ) return S_OK; WCHAR strLeafName[MAX_PATH] = {0}; // Search all parent directories starting at .\ and using strFilename as the leaf name wcscpy_s( strLeafName, MAX_PATH, strFilename ); bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, L".", strLeafName ); if( bFound ) return S_OK; // Search all parent directories starting at the exe's dir and using strFilename as the leaf name bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName ); if( bFound ) return S_OK; // Search all parent directories starting at .\ and using "media\strFilename" as the leaf name swprintf_s( strLeafName, MAX_PATH, L"media\\%s", strFilename ); bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, L".", strLeafName ); if( bFound ) return S_OK; // Search all parent directories starting at the exe's dir and using "media\strFilename" as the leaf name bFound = DXUTFindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName ); if( bFound ) return S_OK; // On failure, return the file as the path but also return an error code wcscpy_s( strDestPath, cchDest, strFilename ); return DXUTERR_MEDIANOTFOUND; } //-------------------------------------------------------------------------------------- // Search a set of typical directories //-------------------------------------------------------------------------------------- bool DXUTFindMediaSearchTypicalDirs( __in_ecount(cchSearch) WCHAR* strSearchPath, int cchSearch, __in LPCWSTR strLeaf, __in WCHAR* strExePath, __in WCHAR* strExeName ) { // Typical directories: // .\ // ..\ // ..\..\ // %EXE_DIR%\ // %EXE_DIR%\..\ // %EXE_DIR%\..\..\ // %EXE_DIR%\..\%EXE_NAME% // %EXE_DIR%\..\..\%EXE_NAME% // DXSDK media path // Search in .\ wcscpy_s( strSearchPath, cchSearch, strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; // Search in ..\ swprintf_s( strSearchPath, cchSearch, L"..\\%s", strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; // Search in ..\..\ swprintf_s( strSearchPath, cchSearch, L"..\\..\\%s", strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; // Search in ..\..\ swprintf_s( strSearchPath, cchSearch, L"..\\..\\%s", strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; // Search in the %EXE_DIR%\ swprintf_s( strSearchPath, cchSearch, L"%s\\%s", strExePath, strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; // Search in the %EXE_DIR%\..\ swprintf_s( strSearchPath, cchSearch, L"%s\\..\\%s", strExePath, strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; // Search in the %EXE_DIR%\..\..\ swprintf_s( strSearchPath, cchSearch, L"%s\\..\\..\\%s", strExePath, strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; // Search in "%EXE_DIR%\..\%EXE_NAME%\". This matches the DirectX SDK layout swprintf_s( strSearchPath, cchSearch, L"%s\\..\\%s\\%s", strExePath, strExeName, strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; // Search in "%EXE_DIR%\..\..\%EXE_NAME%\". This matches the DirectX SDK layout swprintf_s( strSearchPath, cchSearch, L"%s\\..\\..\\%s\\%s", strExePath, strExeName, strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; // Search in media search dir WCHAR* s_strSearchPath = DXUTMediaSearchPath(); if( s_strSearchPath[0] != 0 ) { swprintf_s( strSearchPath, cchSearch, L"%s%s", s_strSearchPath, strLeaf ); if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) return true; } return false; } //-------------------------------------------------------------------------------------- // Search parent directories starting at strStartAt, and appending strLeafName // at each parent directory. It stops at the root directory. //-------------------------------------------------------------------------------------- bool DXUTFindMediaSearchParentDirs( __in_ecount(cchSearch) WCHAR* strSearchPath, int cchSearch, __in WCHAR* strStartAt, __in WCHAR* strLeafName ) { WCHAR strFullPath[MAX_PATH] = {0}; WCHAR strFullFileName[MAX_PATH] = {0}; WCHAR strSearch[MAX_PATH] = {0}; WCHAR* strFilePart = NULL; GetFullPathName( strStartAt, MAX_PATH, strFullPath, &strFilePart ); if( strFilePart == NULL ) return false; while( strFilePart != NULL && *strFilePart != '\0' ) { swprintf_s( strFullFileName, MAX_PATH, L"%s\\%s", strFullPath, strLeafName ); if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF ) { wcscpy_s( strSearchPath, cchSearch, strFullFileName ); return true; } swprintf_s( strSearch, MAX_PATH, L"%s\\..", strFullPath ); GetFullPathName( strSearch, MAX_PATH, strFullPath, &strFilePart ); } return false; } //-------------------------------------------------------------------------------------- // CDXUTResourceCache //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- CDXUTResourceCache::~CDXUTResourceCache() { OnDestroyDevice(); m_TextureCache.RemoveAll(); m_EffectCache.RemoveAll(); m_FontCache.RemoveAll(); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DTEXTURE9* ppTexture ) { return CreateTextureFromFileEx( pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppTexture ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCSTR pSrcFile, LPDIRECT3DTEXTURE9* ppTexture ) { WCHAR szSrcFile[MAX_PATH]; MultiByteToWideChar( CP_ACP, 0, pSrcFile, -1, szSrcFile, MAX_PATH ); szSrcFile[MAX_PATH - 1] = 0; return CreateTextureFromFile( pDevice, szSrcFile, ppTexture ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateTextureFromFile( ID3D10Device* pDevice, LPCTSTR pSrcFile, ID3D10ShaderResourceView** ppOutputRV, bool bSRGB ) { return CreateTextureFromFileEx( pDevice, pSrcFile, NULL, NULL, ppOutputRV, bSRGB ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateTextureFromFile( ID3D10Device* pDevice, LPCSTR pSrcFile, ID3D10ShaderResourceView** ppOutputRV, bool bSRGB ) { WCHAR szSrcFile[MAX_PATH]; MultiByteToWideChar( CP_ACP, 0, pSrcFile, -1, szSrcFile, MAX_PATH ); szSrcFile[MAX_PATH - 1] = 0; return CreateTextureFromFile( pDevice, szSrcFile, ppOutputRV, bSRGB ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, UINT Height, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, LPDIRECT3DTEXTURE9* ppTexture ) { // Search the cache for a matching entry. for( int i = 0; i < m_TextureCache.GetSize(); ++i ) { DXUTCache_Texture& Entry = m_TextureCache[i]; if( Entry.Location == DXUTCACHE_LOCATION_FILE && !lstrcmpW( Entry.wszSource, pSrcFile ) && Entry.Width == Width && Entry.Height == Height && Entry.MipLevels == MipLevels && Entry.Usage9 == Usage && Entry.Format9 == Format && Entry.Pool9 == Pool && Entry.Type9 == D3DRTYPE_TEXTURE ) { // A match is found. Obtain the IDirect3DTexture9 interface and return that. return Entry.pTexture9->QueryInterface( IID_IDirect3DTexture9, ( LPVOID* )ppTexture ); } } HRESULT hr; // No matching entry. Load the resource and create a new entry. hr = D3DXCreateTextureFromFileEx( pDevice, pSrcFile, Width, Height, MipLevels, Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppTexture ); if( FAILED( hr ) ) return hr; DXUTCache_Texture NewEntry; NewEntry.Location = DXUTCACHE_LOCATION_FILE; wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); NewEntry.Width = Width; NewEntry.Height = Height; NewEntry.MipLevels = MipLevels; NewEntry.Usage9 = Usage; NewEntry.Format9 = Format; NewEntry.Pool9 = Pool; NewEntry.Type9 = D3DRTYPE_TEXTURE; ( *ppTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); m_TextureCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateTextureFromFileEx( ID3D10Device* pDevice, LPCTSTR pSrcFile, D3DX10_IMAGE_LOAD_INFO* pLoadInfo, ID3DX10ThreadPump* pPump, ID3D10ShaderResourceView** ppOutputRV, bool bSRGB ) { HRESULT hr = S_OK; D3DX10_IMAGE_LOAD_INFO ZeroInfo; //D3DX10_IMAGE_LOAD_INFO has a default constructor D3DX10_IMAGE_INFO SrcInfo; if( !pLoadInfo ) { pLoadInfo = &ZeroInfo; } if( !pLoadInfo->pSrcInfo ) { D3DX10GetImageInfoFromFile( pSrcFile, NULL, &SrcInfo, NULL ); pLoadInfo->pSrcInfo = &SrcInfo; pLoadInfo->Format = pLoadInfo->pSrcInfo->Format; } // Search the cache for a matching entry. for( int i = 0; i < m_TextureCache.GetSize(); ++i ) { DXUTCache_Texture& Entry = m_TextureCache[i]; if( Entry.Location == DXUTCACHE_LOCATION_FILE && !lstrcmpW( Entry.wszSource, pSrcFile ) && Entry.Width == pLoadInfo->Width && Entry.Height == pLoadInfo->Height && Entry.MipLevels == pLoadInfo->MipLevels && Entry.Usage10 == pLoadInfo->Usage && Entry.Format10 == pLoadInfo->Format && Entry.CpuAccessFlags == pLoadInfo->CpuAccessFlags && Entry.BindFlags == pLoadInfo->BindFlags && Entry.MiscFlags == pLoadInfo->MiscFlags ) { // A match is found. Obtain the IDirect3DTexture9 interface and return that. return Entry.pSRV10->QueryInterface( __uuidof( ID3D10ShaderResourceView ), ( LPVOID* )ppOutputRV ); } } //Ready a new entry to the texture cache //Do this before creating the texture since pLoadInfo may be volatile DXUTCache_Texture NewEntry; NewEntry.Location = DXUTCACHE_LOCATION_FILE; wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); NewEntry.Width = pLoadInfo->Width; NewEntry.Height = pLoadInfo->Height; NewEntry.MipLevels = pLoadInfo->MipLevels; NewEntry.Usage10 = pLoadInfo->Usage; NewEntry.Format10 = pLoadInfo->Format; NewEntry.CpuAccessFlags = pLoadInfo->CpuAccessFlags; NewEntry.BindFlags = pLoadInfo->BindFlags; NewEntry.MiscFlags = pLoadInfo->MiscFlags; //Create the rexture ID3D10Texture2D* pRes = NULL; hr = D3DX10CreateTextureFromFile( pDevice, pSrcFile, pLoadInfo, pPump, ( ID3D10Resource** )&pRes, NULL ); if( FAILED( hr ) ) return hr; if( bSRGB ) { // This is a workaround so that we can load linearly, but sample in SRGB. Right now, we can't load // as linear since D3DX will try to do conversion on load. Loading as TYPELESS doesn't work either, and // loading as typed _UNORM doesn't allow us to create an SRGB view. if( pLoadInfo->pSrcInfo->ResourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D ) { ID3D10Texture2D* pCopyTex = NULL; D3D10_TEXTURE2D_DESC CopyDesc; pRes->GetDesc( &CopyDesc ); CopyDesc.Format = MAKE_TYPELESS( CopyDesc.Format ); hr = pDevice->CreateTexture2D( &CopyDesc, NULL, &pCopyTex ); if( FAILED( hr ) ) return hr; pDevice->CopyResource( pCopyTex, pRes ); pRes->Release(); pRes = pCopyTex; } else { bSRGB = false; } } D3D10_SHADER_RESOURCE_VIEW_DESC SRVDesc; if( bSRGB ) SRVDesc.Format = MAKE_SRGB( ZeroInfo.Format ); else SRVDesc.Format = ZeroInfo.Format; if( pLoadInfo->pSrcInfo->ResourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D ) { SRVDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE1D; SRVDesc.Texture1D.MostDetailedMip = 0; SRVDesc.Texture1D.MipLevels = pLoadInfo->pSrcInfo->MipLevels; } else if( pLoadInfo->pSrcInfo->ResourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D ) { SRVDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MostDetailedMip = 0; SRVDesc.Texture2D.MipLevels = pLoadInfo->pSrcInfo->MipLevels; if( pLoadInfo->pSrcInfo->MiscFlags & D3D10_RESOURCE_MISC_TEXTURECUBE ) { SRVDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURECUBE; SRVDesc.TextureCube.MostDetailedMip = 0; SRVDesc.TextureCube.MipLevels = pLoadInfo->pSrcInfo->MipLevels; } } else if( pLoadInfo->pSrcInfo->ResourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D ) { SRVDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE3D; SRVDesc.Texture3D.MostDetailedMip = 0; SRVDesc.Texture3D.MipLevels = pLoadInfo->pSrcInfo->MipLevels; } hr = pDevice->CreateShaderResourceView( pRes, &SRVDesc, ppOutputRV ); pRes->Release(); if( FAILED( hr ) ) return hr; ( *ppOutputRV )->QueryInterface( __uuidof( ID3D10ShaderResourceView ), ( LPVOID* )&NewEntry.pSRV10 ); m_TextureCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DTEXTURE9* ppTexture ) { return CreateTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppTexture ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, UINT Width, UINT Height, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, LPDIRECT3DTEXTURE9* ppTexture ) { // Search the cache for a matching entry. for( int i = 0; i < m_TextureCache.GetSize(); ++i ) { DXUTCache_Texture& Entry = m_TextureCache[i]; if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE && Entry.hSrcModule == hSrcModule && !lstrcmpW( Entry.wszSource, pSrcResource ) && Entry.Width == Width && Entry.Height == Height && Entry.MipLevels == MipLevels && Entry.Usage9 == Usage && Entry.Format9 == Format && Entry.Pool9 == Pool && Entry.Type9 == D3DRTYPE_TEXTURE ) { // A match is found. Obtain the IDirect3DTexture9 interface and return that. return Entry.pTexture9->QueryInterface( IID_IDirect3DTexture9, ( LPVOID* )ppTexture ); } } HRESULT hr; // No matching entry. Load the resource and create a new entry. hr = D3DXCreateTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, Width, Height, MipLevels, Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppTexture ); if( FAILED( hr ) ) return hr; DXUTCache_Texture NewEntry; NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE; NewEntry.hSrcModule = hSrcModule; wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcResource ); NewEntry.Width = Width; NewEntry.Height = Height; NewEntry.MipLevels = MipLevels; NewEntry.Usage9 = Usage; NewEntry.Format9 = Format; NewEntry.Pool9 = Pool; NewEntry.Type9 = D3DRTYPE_TEXTURE; ( *ppTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); m_TextureCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateCubeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DCUBETEXTURE9* ppCubeTexture ) { return CreateCubeTextureFromFileEx( pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppCubeTexture ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateCubeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, LPDIRECT3DCUBETEXTURE9* ppCubeTexture ) { // Search the cache for a matching entry. for( int i = 0; i < m_TextureCache.GetSize(); ++i ) { DXUTCache_Texture& Entry = m_TextureCache[i]; if( Entry.Location == DXUTCACHE_LOCATION_FILE && !lstrcmpW( Entry.wszSource, pSrcFile ) && Entry.Width == Size && Entry.MipLevels == MipLevels && Entry.Usage9 == Usage && Entry.Format9 == Format && Entry.Pool9 == Pool && Entry.Type9 == D3DRTYPE_CUBETEXTURE ) { // A match is found. Obtain the IDirect3DCubeTexture9 interface and return that. return Entry.pTexture9->QueryInterface( IID_IDirect3DCubeTexture9, ( LPVOID* )ppCubeTexture ); } } HRESULT hr; // No matching entry. Load the resource and create a new entry. hr = D3DXCreateCubeTextureFromFileEx( pDevice, pSrcFile, Size, MipLevels, Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture ); if( FAILED( hr ) ) return hr; DXUTCache_Texture NewEntry; NewEntry.Location = DXUTCACHE_LOCATION_FILE; wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); NewEntry.Width = Size; NewEntry.MipLevels = MipLevels; NewEntry.Usage9 = Usage; NewEntry.Format9 = Format; NewEntry.Pool9 = Pool; NewEntry.Type9 = D3DRTYPE_CUBETEXTURE; ( *ppCubeTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); m_TextureCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateCubeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DCUBETEXTURE9* ppCubeTexture ) { return CreateCubeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppCubeTexture ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateCubeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, LPDIRECT3DCUBETEXTURE9* ppCubeTexture ) { // Search the cache for a matching entry. for( int i = 0; i < m_TextureCache.GetSize(); ++i ) { DXUTCache_Texture& Entry = m_TextureCache[i]; if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE && Entry.hSrcModule == hSrcModule && !lstrcmpW( Entry.wszSource, pSrcResource ) && Entry.Width == Size && Entry.MipLevels == MipLevels && Entry.Usage9 == Usage && Entry.Format9 == Format && Entry.Pool9 == Pool && Entry.Type9 == D3DRTYPE_CUBETEXTURE ) { // A match is found. Obtain the IDirect3DCubeTexture9 interface and return that. return Entry.pTexture9->QueryInterface( IID_IDirect3DCubeTexture9, ( LPVOID* )ppCubeTexture ); } } HRESULT hr; // No matching entry. Load the resource and create a new entry. hr = D3DXCreateCubeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, Size, MipLevels, Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture ); if( FAILED( hr ) ) return hr; DXUTCache_Texture NewEntry; NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE; NewEntry.hSrcModule = hSrcModule; wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcResource ); NewEntry.Width = Size; NewEntry.MipLevels = MipLevels; NewEntry.Usage9 = Usage; NewEntry.Format9 = Format; NewEntry.Pool9 = Pool; NewEntry.Type9 = D3DRTYPE_CUBETEXTURE; ( *ppCubeTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); m_TextureCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateVolumeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture ) { return CreateVolumeTextureFromFileEx( pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppVolumeTexture ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateVolumeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, UINT Height, UINT Depth, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, LPDIRECT3DVOLUMETEXTURE9* ppTexture ) { // Search the cache for a matching entry. for( int i = 0; i < m_TextureCache.GetSize(); ++i ) { DXUTCache_Texture& Entry = m_TextureCache[i]; if( Entry.Location == DXUTCACHE_LOCATION_FILE && !lstrcmpW( Entry.wszSource, pSrcFile ) && Entry.Width == Width && Entry.Height == Height && Entry.Depth == Depth && Entry.MipLevels == MipLevels && Entry.Usage9 == Usage && Entry.Format9 == Format && Entry.Pool9 == Pool && Entry.Type9 == D3DRTYPE_VOLUMETEXTURE ) { // A match is found. Obtain the IDirect3DVolumeTexture9 interface and return that. return Entry.pTexture9->QueryInterface( IID_IDirect3DVolumeTexture9, ( LPVOID* )ppTexture ); } } HRESULT hr; // No matching entry. Load the resource and create a new entry. hr = D3DXCreateVolumeTextureFromFileEx( pDevice, pSrcFile, Width, Height, Depth, MipLevels, Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppTexture ); if( FAILED( hr ) ) return hr; DXUTCache_Texture NewEntry; NewEntry.Location = DXUTCACHE_LOCATION_FILE; wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); NewEntry.Width = Width; NewEntry.Height = Height; NewEntry.Depth = Depth; NewEntry.MipLevels = MipLevels; NewEntry.Usage9 = Usage; NewEntry.Format9 = Format; NewEntry.Pool9 = Pool; NewEntry.Type9 = D3DRTYPE_VOLUMETEXTURE; ( *ppTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); m_TextureCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateVolumeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture ) { return CreateVolumeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppVolumeTexture ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateVolumeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, UINT Width, UINT Height, UINT Depth, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO* pSrcInfo, PALETTEENTRY* pPalette, LPDIRECT3DVOLUMETEXTURE9* ppVolumeTexture ) { // Search the cache for a matching entry. for( int i = 0; i < m_TextureCache.GetSize(); ++i ) { DXUTCache_Texture& Entry = m_TextureCache[i]; if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE && Entry.hSrcModule == hSrcModule && !lstrcmpW( Entry.wszSource, pSrcResource ) && Entry.Width == Width && Entry.Height == Height && Entry.Depth == Depth && Entry.MipLevels == MipLevels && Entry.Usage9 == Usage && Entry.Format9 == Format && Entry.Pool9 == Pool && Entry.Type9 == D3DRTYPE_VOLUMETEXTURE ) { // A match is found. Obtain the IDirect3DVolumeTexture9 interface and return that. return Entry.pTexture9->QueryInterface( IID_IDirect3DVolumeTexture9, ( LPVOID* )ppVolumeTexture ); } } HRESULT hr; // No matching entry. Load the resource and create a new entry. hr = D3DXCreateVolumeTextureFromResourceEx( pDevice, hSrcModule, pSrcResource, Width, Height, Depth, MipLevels, Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppVolumeTexture ); if( FAILED( hr ) ) return hr; DXUTCache_Texture NewEntry; NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE; NewEntry.hSrcModule = hSrcModule; wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcResource ); NewEntry.Width = Width; NewEntry.Height = Height; NewEntry.Depth = Depth; NewEntry.MipLevels = MipLevels; NewEntry.Usage9 = Usage; NewEntry.Format9 = Format; NewEntry.Pool9 = Pool; NewEntry.Type9 = D3DRTYPE_VOLUMETEXTURE; ( *ppVolumeTexture )->QueryInterface( IID_IDirect3DBaseTexture9, ( LPVOID* )&NewEntry.pTexture9 ); m_TextureCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateFont( LPDIRECT3DDEVICE9 pDevice, UINT Height, UINT Width, UINT Weight, UINT MipLevels, BOOL Italic, DWORD CharSet, DWORD OutputPrecision, DWORD Quality, DWORD PitchAndFamily, LPCTSTR pFacename, LPD3DXFONT* ppFont ) { D3DXFONT_DESCW Desc; Desc.Height = Height; Desc.Width = Width; Desc.Weight = Weight; Desc.MipLevels = MipLevels; Desc.Italic = Italic; Desc.CharSet = ( BYTE )CharSet; Desc.OutputPrecision = ( BYTE )OutputPrecision; Desc.Quality = ( BYTE )Quality; Desc.PitchAndFamily = ( BYTE )PitchAndFamily; wcscpy_s( Desc.FaceName, LF_FACESIZE, pFacename ); return CreateFontIndirect( pDevice, &Desc, ppFont ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateFontIndirect( LPDIRECT3DDEVICE9 pDevice, CONST D3DXFONT_DESC *pDesc, LPD3DXFONT *ppFont ) { // Search the cache for a matching entry. for( int i = 0; i < m_FontCache.GetSize(); ++i ) { DXUTCache_Font &Entry = m_FontCache[i]; if( Entry.Width == pDesc->Width && Entry.Height == pDesc->Height && Entry.Weight == pDesc->Weight && Entry.MipLevels == pDesc->MipLevels && Entry.Italic == pDesc->Italic && Entry.CharSet == pDesc->CharSet && Entry.OutputPrecision == pDesc->OutputPrecision && Entry.Quality == pDesc->Quality && Entry.PitchAndFamily == pDesc->PitchAndFamily && CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE, Entry.FaceName, -1, pDesc->FaceName, -1 ) == CSTR_EQUAL ) { // A match is found. Increment the reference and return the ID3DXFont object. Entry.pFont->AddRef(); *ppFont = Entry.pFont; return S_OK; } } HRESULT hr; // No matching entry. Load the resource and create a new entry. hr = D3DXCreateFontIndirect( pDevice, pDesc, ppFont ); if( FAILED( hr ) ) return hr; DXUTCache_Font NewEntry; ( D3DXFONT_DESC & )NewEntry = *pDesc; NewEntry.pFont = *ppFont; NewEntry.pFont->AddRef(); m_FontCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateEffectFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT* ppEffect, LPD3DXBUFFER* ppCompilationErrors ) { // Search the cache for a matching entry. for( int i = 0; i < m_EffectCache.GetSize(); ++i ) { DXUTCache_Effect& Entry = m_EffectCache[i]; if( Entry.Location == DXUTCACHE_LOCATION_FILE && !lstrcmpW( Entry.wszSource, pSrcFile ) && Entry.dwFlags == Flags ) { // A match is found. Increment the ref coutn and return the ID3DXEffect object. *ppEffect = Entry.pEffect; ( *ppEffect )->AddRef(); return S_OK; } } HRESULT hr; // No matching entry. Load the resource and create a new entry. hr = D3DXCreateEffectFromFile( pDevice, pSrcFile, pDefines, pInclude, Flags, pPool, ppEffect, ppCompilationErrors ); if( FAILED( hr ) ) return hr; DXUTCache_Effect NewEntry; NewEntry.Location = DXUTCACHE_LOCATION_FILE; wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcFile ); NewEntry.dwFlags = Flags; NewEntry.pEffect = *ppEffect; NewEntry.pEffect->AddRef(); m_EffectCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::CreateEffectFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT* ppEffect, LPD3DXBUFFER* ppCompilationErrors ) { // Search the cache for a matching entry. for( int i = 0; i < m_EffectCache.GetSize(); ++i ) { DXUTCache_Effect& Entry = m_EffectCache[i]; if( Entry.Location == DXUTCACHE_LOCATION_RESOURCE && Entry.hSrcModule == hSrcModule && !lstrcmpW( Entry.wszSource, pSrcResource ) && Entry.dwFlags == Flags ) { // A match is found. Increment the ref coutn and return the ID3DXEffect object. *ppEffect = Entry.pEffect; ( *ppEffect )->AddRef(); return S_OK; } } HRESULT hr; // No matching entry. Load the resource and create a new entry. hr = D3DXCreateEffectFromResource( pDevice, hSrcModule, pSrcResource, pDefines, pInclude, Flags, pPool, ppEffect, ppCompilationErrors ); if( FAILED( hr ) ) return hr; DXUTCache_Effect NewEntry; NewEntry.Location = DXUTCACHE_LOCATION_RESOURCE; NewEntry.hSrcModule = hSrcModule; wcscpy_s( NewEntry.wszSource, MAX_PATH, pSrcResource ); NewEntry.dwFlags = Flags; NewEntry.pEffect = *ppEffect; NewEntry.pEffect->AddRef(); m_EffectCache.Add( NewEntry ); return S_OK; } //-------------------------------------------------------------------------------------- // Device event callbacks //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::OnCreateDevice( IDirect3DDevice9* pd3dDevice ) { return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::OnResetDevice( IDirect3DDevice9* pd3dDevice ) { // Call OnResetDevice on all effect and font objects for( int i = 0; i < m_EffectCache.GetSize(); ++i ) m_EffectCache[i].pEffect->OnResetDevice(); for( int i = 0; i < m_FontCache.GetSize(); ++i ) m_FontCache[i].pFont->OnResetDevice(); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::OnLostDevice() { // Call OnLostDevice on all effect and font objects for( int i = 0; i < m_EffectCache.GetSize(); ++i ) m_EffectCache[i].pEffect->OnLostDevice(); for( int i = 0; i < m_FontCache.GetSize(); ++i ) m_FontCache[i].pFont->OnLostDevice(); // Release all the default pool textures for( int i = m_TextureCache.GetSize() - 1; i >= 0; --i ) if( m_TextureCache[i].Pool9 == D3DPOOL_DEFAULT ) { SAFE_RELEASE( m_TextureCache[i].pTexture9 ); m_TextureCache.Remove( i ); // Remove the entry } return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTResourceCache::OnDestroyDevice() { // Release all resources for( int i = m_EffectCache.GetSize() - 1; i >= 0; --i ) { SAFE_RELEASE( m_EffectCache[i].pEffect ); m_EffectCache.Remove( i ); } for( int i = m_FontCache.GetSize() - 1; i >= 0; --i ) { SAFE_RELEASE( m_FontCache[i].pFont ); m_FontCache.Remove( i ); } for( int i = m_TextureCache.GetSize() - 1; i >= 0; --i ) { SAFE_RELEASE( m_TextureCache[i].pTexture9 ); SAFE_RELEASE( m_TextureCache[i].pSRV10 ); m_TextureCache.Remove( i ); } return S_OK; } //-------------------------------------------------------------------------------------- // Desc: Returns a view matrix for rendering to a face of a cubemap. //-------------------------------------------------------------------------------------- D3DXMATRIX WINAPI DXUTGetCubeMapViewMatrix( DWORD dwFace ) { D3DXVECTOR3 vEyePt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vLookDir; D3DXVECTOR3 vUpDir; switch( dwFace ) { case D3DCUBEMAP_FACE_POSITIVE_X: vLookDir = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); break; case D3DCUBEMAP_FACE_NEGATIVE_X: vLookDir = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); break; case D3DCUBEMAP_FACE_POSITIVE_Y: vLookDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); vUpDir = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); break; case D3DCUBEMAP_FACE_NEGATIVE_Y: vLookDir = D3DXVECTOR3( 0.0f, -1.0f, 0.0f ); vUpDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); break; case D3DCUBEMAP_FACE_POSITIVE_Z: vLookDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); break; case D3DCUBEMAP_FACE_NEGATIVE_Z: vLookDir = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); break; } // Set the view transform for this cubemap surface D3DXMATRIXA16 mView; D3DXMatrixLookAtLH( &mView, &vEyePt, &vLookDir, &vUpDir ); return mView; } //-------------------------------------------------------------------------------------- CDXUTLineManager::CDXUTLineManager() { m_pd3dDevice = NULL; m_pD3DXLine = NULL; } //-------------------------------------------------------------------------------------- CDXUTLineManager::~CDXUTLineManager() { OnDeletedDevice(); } //-------------------------------------------------------------------------------------- HRESULT CDXUTLineManager::OnCreatedDevice( IDirect3DDevice9* pd3dDevice ) { m_pd3dDevice = pd3dDevice; HRESULT hr; hr = D3DXCreateLine( m_pd3dDevice, &m_pD3DXLine ); if( FAILED( hr ) ) return hr; return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTLineManager::OnResetDevice() { if( m_pD3DXLine ) m_pD3DXLine->OnResetDevice(); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTLineManager::OnRender() { HRESULT hr; if( NULL == m_pD3DXLine ) return E_INVALIDARG; bool bDrawingHasBegun = false; float fLastWidth = 0.0f; bool bLastAntiAlias = false; for( int i = 0; i < m_LinesList.GetSize(); i++ ) { LINE_NODE* pLineNode = m_LinesList.GetAt( i ); if( pLineNode ) { if( !bDrawingHasBegun || fLastWidth != pLineNode->fWidth || bLastAntiAlias != pLineNode->bAntiAlias ) { if( bDrawingHasBegun ) { hr = m_pD3DXLine->End(); if( FAILED( hr ) ) return hr; } m_pD3DXLine->SetWidth( pLineNode->fWidth ); m_pD3DXLine->SetAntialias( pLineNode->bAntiAlias ); fLastWidth = pLineNode->fWidth; bLastAntiAlias = pLineNode->bAntiAlias; hr = m_pD3DXLine->Begin(); if( FAILED( hr ) ) return hr; bDrawingHasBegun = true; } hr = m_pD3DXLine->Draw( pLineNode->pVertexList, pLineNode->dwVertexListCount, pLineNode->Color ); if( FAILED( hr ) ) return hr; } } if( bDrawingHasBegun ) { hr = m_pD3DXLine->End(); if( FAILED( hr ) ) return hr; } return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTLineManager::OnLostDevice() { if( m_pD3DXLine ) m_pD3DXLine->OnLostDevice(); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTLineManager::OnDeletedDevice() { RemoveAllLines(); SAFE_RELEASE( m_pD3DXLine ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTLineManager::AddLine( int* pnLineID, D3DXVECTOR2* pVertexList, DWORD dwVertexListCount, D3DCOLOR Color, float fWidth, float fScaleRatio, bool bAntiAlias ) { if( pVertexList == NULL || dwVertexListCount == 0 ) return E_INVALIDARG; LINE_NODE* pLineNode = new LINE_NODE; if( pLineNode == NULL ) return E_OUTOFMEMORY; ZeroMemory( pLineNode, sizeof( LINE_NODE ) ); pLineNode->nLineID = m_LinesList.GetSize(); pLineNode->Color = Color; pLineNode->fWidth = fWidth; pLineNode->bAntiAlias = bAntiAlias; pLineNode->dwVertexListCount = dwVertexListCount; if( pnLineID ) *pnLineID = pLineNode->nLineID; pLineNode->pVertexList = new D3DXVECTOR2[dwVertexListCount]; if( pLineNode->pVertexList == NULL ) { delete pLineNode; return E_OUTOFMEMORY; } for( DWORD i = 0; i < dwVertexListCount; i++ ) { pLineNode->pVertexList[i] = pVertexList[i] * fScaleRatio; } m_LinesList.Add( pLineNode ); return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTLineManager::AddRect( int* pnLineID, RECT rc, D3DCOLOR Color, float fWidth, float fScaleRatio, bool bAntiAlias ) { if( fWidth > 2.0f ) { D3DXVECTOR2 vertexList[8]; vertexList[0].x = ( float )rc.left; vertexList[0].y = ( float )rc.top - ( fWidth / 2.0f ); vertexList[1].x = ( float )rc.left; vertexList[1].y = ( float )rc.bottom + ( fWidth / 2.0f ); vertexList[2].x = ( float )rc.left; vertexList[2].y = ( float )rc.bottom - 0.5f; vertexList[3].x = ( float )rc.right; vertexList[3].y = ( float )rc.bottom - 0.5f; vertexList[4].x = ( float )rc.right; vertexList[4].y = ( float )rc.bottom + ( fWidth / 2.0f ); vertexList[5].x = ( float )rc.right; vertexList[5].y = ( float )rc.top - ( fWidth / 2.0f ); vertexList[6].x = ( float )rc.right; vertexList[6].y = ( float )rc.top; vertexList[7].x = ( float )rc.left; vertexList[7].y = ( float )rc.top; return AddLine( pnLineID, vertexList, 8, Color, fWidth, fScaleRatio, bAntiAlias ); } else { D3DXVECTOR2 vertexList[5]; vertexList[0].x = ( float )rc.left; vertexList[0].y = ( float )rc.top; vertexList[1].x = ( float )rc.left; vertexList[1].y = ( float )rc.bottom; vertexList[2].x = ( float )rc.right; vertexList[2].y = ( float )rc.bottom; vertexList[3].x = ( float )rc.right; vertexList[3].y = ( float )rc.top; vertexList[4].x = ( float )rc.left; vertexList[4].y = ( float )rc.top; return AddLine( pnLineID, vertexList, 5, Color, fWidth, fScaleRatio, bAntiAlias ); } } //-------------------------------------------------------------------------------------- HRESULT CDXUTLineManager::RemoveLine( int nLineID ) { for( int i = 0; i < m_LinesList.GetSize(); i++ ) { LINE_NODE* pLineNode = m_LinesList.GetAt( i ); if( pLineNode && pLineNode->nLineID == nLineID ) { SAFE_DELETE_ARRAY( pLineNode->pVertexList ); delete pLineNode; m_LinesList.SetAt( i, NULL ); } } return S_OK; } //-------------------------------------------------------------------------------------- HRESULT CDXUTLineManager::RemoveAllLines() { for( int i = 0; i < m_LinesList.GetSize(); i++ ) { LINE_NODE* pLineNode = m_LinesList.GetAt( i ); if( pLineNode ) { SAFE_DELETE_ARRAY( pLineNode->pVertexList ); delete pLineNode; } } m_LinesList.RemoveAll(); return S_OK; } //-------------------------------------------------------------------------------------- CDXUTTextHelper::CDXUTTextHelper( ID3DXFont* pFont9, ID3DXSprite* pSprite9, ID3DX10Font* pFont10, ID3DX10Sprite* pSprite10, int nLineHeight ) { Init( pFont9, pSprite9, pFont10, pSprite10, nLineHeight ); } CDXUTTextHelper::CDXUTTextHelper( ID3DXFont* pFont, ID3DXSprite* pSprite, int nLineHeight ) { Init( pFont, pSprite, NULL, NULL, nLineHeight ); } CDXUTTextHelper::CDXUTTextHelper( ID3DX10Font* pFont, ID3DX10Sprite* pSprite, int nLineHeight ) { Init( NULL, NULL, pFont, pSprite, nLineHeight ); } CDXUTTextHelper::~CDXUTTextHelper() { SAFE_RELEASE( m_pFontBlendState10 ); } //-------------------------------------------------------------------------------------- void CDXUTTextHelper::Init( ID3DXFont* pFont9, ID3DXSprite* pSprite9, ID3DX10Font* pFont10, ID3DX10Sprite* pSprite10, int nLineHeight ) { m_pFont9 = pFont9; m_pSprite9 = pSprite9; m_pFont10 = pFont10; m_pSprite10 = pSprite10; m_clr = D3DXCOLOR( 1, 1, 1, 1 ); m_pt.x = 0; m_pt.y = 0; m_nLineHeight = nLineHeight; m_pFontBlendState10 = NULL; // Create a blend state if a sprite is passed in if( pSprite10 ) { ID3D10Device* pDev = NULL; pSprite10->GetDevice( &pDev ); if( pDev ) { D3D10_BLEND_DESC StateDesc; ZeroMemory( &StateDesc, sizeof( D3D10_BLEND_DESC ) ); StateDesc.AlphaToCoverageEnable = FALSE; StateDesc.BlendEnable[0] = TRUE; StateDesc.SrcBlend = D3D10_BLEND_SRC_ALPHA; StateDesc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA; StateDesc.BlendOp = D3D10_BLEND_OP_ADD; StateDesc.SrcBlendAlpha = D3D10_BLEND_ZERO; StateDesc.DestBlendAlpha = D3D10_BLEND_ZERO; StateDesc.BlendOpAlpha = D3D10_BLEND_OP_ADD; StateDesc.RenderTargetWriteMask[0] = 0xf; pDev->CreateBlendState( &StateDesc, &m_pFontBlendState10 ); pDev->Release(); } } } //-------------------------------------------------------------------------------------- HRESULT CDXUTTextHelper::DrawFormattedTextLine( const WCHAR* strMsg, ... ) { WCHAR strBuffer[512]; va_list args; va_start( args, strMsg ); vswprintf_s( strBuffer, 512, strMsg, args ); strBuffer[511] = L'\0'; va_end( args ); return DrawTextLine( strBuffer ); } //-------------------------------------------------------------------------------------- HRESULT CDXUTTextHelper::DrawTextLine( const WCHAR* strMsg ) { if( NULL == m_pFont9 && NULL == m_pFont10 ) return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG ); HRESULT hr; RECT rc; SetRect( &rc, m_pt.x, m_pt.y, 0, 0 ); if( m_pFont9 ) hr = m_pFont9->DrawText( m_pSprite9, strMsg, -1, &rc, DT_NOCLIP, m_clr ); else hr = m_pFont10->DrawText( m_pSprite10, strMsg, -1, &rc, DT_NOCLIP, m_clr ); if( FAILED( hr ) ) return DXTRACE_ERR_MSGBOX( L"DrawText", hr ); m_pt.y += m_nLineHeight; return S_OK; } HRESULT CDXUTTextHelper::DrawFormattedTextLine( RECT& rc, DWORD dwFlags, const WCHAR* strMsg, ... ) { WCHAR strBuffer[512]; va_list args; va_start( args, strMsg ); vswprintf_s( strBuffer, 512, strMsg, args ); strBuffer[511] = L'\0'; va_end( args ); return DrawTextLine( rc, dwFlags, strBuffer ); } HRESULT CDXUTTextHelper::DrawTextLine( RECT& rc, DWORD dwFlags, const WCHAR* strMsg ) { if( NULL == m_pFont9 && NULL == m_pFont10 ) return DXUT_ERR_MSGBOX( L"DrawTextLine", E_INVALIDARG ); HRESULT hr; if( m_pFont9 ) hr = m_pFont9->DrawText( m_pSprite9, strMsg, -1, &rc, dwFlags, m_clr ); else hr = m_pFont10->DrawText( m_pSprite10, strMsg, -1, &rc, dwFlags, m_clr ); if( FAILED( hr ) ) return DXTRACE_ERR_MSGBOX( L"DrawText", hr ); m_pt.y += m_nLineHeight; return S_OK; } //-------------------------------------------------------------------------------------- void CDXUTTextHelper::Begin() { if( m_pSprite9 ) m_pSprite9->Begin( D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE ); if( m_pSprite10 ) { D3D10_VIEWPORT VPs[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; UINT cVPs = 1; ID3D10Device* pd3dDevice = NULL; m_pSprite10->GetDevice( &pd3dDevice ); if( pd3dDevice ) { // Set projection pd3dDevice->RSGetViewports( &cVPs, VPs ); D3DXMATRIXA16 matProjection; D3DXMatrixOrthoOffCenterLH( &matProjection, ( FLOAT )VPs[0].TopLeftX, ( FLOAT ) ( VPs[0].TopLeftX + VPs[0].Width ), ( FLOAT )VPs[0].TopLeftY, ( FLOAT ) ( VPs[0].TopLeftY + VPs[0].Height ), 0.1f, 10 ); m_pSprite10->SetProjectionTransform( &matProjection ); m_pSprite10->Begin( D3DX10_SPRITE_SORT_TEXTURE ); SAFE_RELEASE( pd3dDevice ); } } } void CDXUTTextHelper::End() { if( m_pSprite9 ) m_pSprite9->End(); if( m_pSprite10 ) { FLOAT OriginalBlendFactor[4]; UINT OriginalSampleMask = 0; ID3D10BlendState* pOriginalBlendState10 = NULL; ID3D10Device* pd3dDevice = NULL; m_pSprite10->GetDevice( &pd3dDevice ); if( pd3dDevice ) { // Get the old blend state and set the new one pd3dDevice->OMGetBlendState( &pOriginalBlendState10, OriginalBlendFactor, &OriginalSampleMask ); if( m_pFontBlendState10 ) { FLOAT NewBlendFactor[4] = {0,0,0,0}; pd3dDevice->OMSetBlendState( m_pFontBlendState10, NewBlendFactor, 0xffffffff ); } } m_pSprite10->End(); // Reset the original blend state if( pd3dDevice && pOriginalBlendState10 ) { pd3dDevice->OMSetBlendState( pOriginalBlendState10, OriginalBlendFactor, OriginalSampleMask ); } SAFE_RELEASE( pOriginalBlendState10 ); SAFE_RELEASE( pd3dDevice ); } } //-------------------------------------------------------------------------------------- HRESULT DXUTSnapD3D9Screenshot( LPCTSTR szFileName ) { HRESULT hr = S_OK; IDirect3DDevice9* pDev = DXUTGetD3D9Device(); if( !pDev ) return E_FAIL; IDirect3DSurface9* pBackBuffer = NULL; V_RETURN( pDev->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ) ); hr = D3DXSaveSurfaceToFile( szFileName, D3DXIFF_BMP, pBackBuffer, NULL, NULL ); SAFE_RELEASE( pBackBuffer ); return hr; } //-------------------------------------------------------------------------------------- HRESULT DXUTSnapD3D10Screenshot( LPCTSTR szFileName ) { IDXGISwapChain *pSwap = DXUTGetDXGISwapChain(); if (!pSwap) return E_FAIL; ID3D10Texture2D* pBackBuffer; HRESULT hr = pSwap->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer); if (hr != S_OK) return hr; ID3D10Device *pDevice = DXUTGetD3D10Device(); if (!pDevice) { SAFE_RELEASE(pBackBuffer); return E_FAIL; } D3D10_TEXTURE2D_DESC dsc; pBackBuffer->GetDesc(&dsc); D3D10_RESOURCE_DIMENSION dim; pBackBuffer->GetType(&dim); // special case msaa textures ID3D10Texture2D *pCompatableTexture = pBackBuffer; if ( dsc.SampleDesc.Count > 1) { D3D10_TEXTURE2D_DESC dsc_new = dsc; dsc_new.SampleDesc.Count = 1; dsc_new.SampleDesc.Quality = 0; dsc_new.Usage = D3D10_USAGE_DEFAULT; dsc_new.BindFlags = 0; dsc_new.CPUAccessFlags = 0; ID3D10Texture2D *resolveTexture; hr = pDevice->CreateTexture2D(&dsc_new, NULL, &resolveTexture); pDevice->ResolveSubresource(resolveTexture, 0, pBackBuffer, 0, dsc.Format); pCompatableTexture = resolveTexture; pCompatableTexture->GetDesc(&dsc); } hr = D3DX10SaveTextureToFileW(pCompatableTexture, D3DX10_IFF_BMP, szFileName); SAFE_RELEASE(pBackBuffer); return hr; }