void set_synchronization(bool enable) //TODO: Needs to be rewritten { if (d3dmgr == NULL) { return; } IDirect3DSwapChain9 *sc; d3dmgr->GetSwapChain(0, &sc); D3DPRESENT_PARAMETERS d3dpp; sc->GetPresentParameters(&d3dpp); if (enable) { d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; //Present the frame immediately } else { d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //Present the frame immediately } sc->Release(); d3dmgr->Reset(&d3dpp); }
static IDirect3DDevice9* findOriginalDevice(IDirect3DDevice9 *device) { IDirect3DSwapChain9 *pSwap = NULL; device->GetSwapChain(0, &pSwap); if (pSwap) { IDirect3DDevice9 *originalDevice = NULL; if (SUCCEEDED(pSwap->GetDevice(&originalDevice))) { if (originalDevice == device) { // Found the original device. Release responsibility is passed // to the caller. } else { device = findOriginalDevice(originalDevice); originalDevice->Release(); } } else { ods("D3D9: Failed to recurse to find original device. Could not get Device from Swapchain."); } pSwap->Release(); } else { ods("D3D9: Failed to recurse to find original device. Could not get Swapchain."); } return device; }
static HRESULT __stdcall myCreateDeviceEx(IDirect3D9Ex * id3d, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, IDirect3DDevice9Ex** ppReturnedDeviceInterface) { Mutex m; ods("D3D9: Chaining CreateDeviceEx"); // BehaviorFlags &= ~D3DCREATE_PUREDEVICE; //TODO: Move logic to HardHook. // Call base without active hook in case of no trampoline. CreateDeviceExType oCreateDeviceEx = (CreateDeviceExType) hhCreateDeviceEx.call; hhCreateDeviceEx.restore(); HRESULT hr = oCreateDeviceEx(id3d, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, pFullscreenDisplayMode, ppReturnedDeviceInterface); hhCreateDeviceEx.inject(); if (FAILED(hr)) return hr; IDirect3DDevice9Ex *idd = *ppReturnedDeviceInterface; DevState *ds = new DevState; ds->dev = idd; idd->AddRef(); ds->initRefCount = idd->Release(); devMap[idd] = ds; // The offsets are dependent on the declaration order of the struct. // See IDirect3DDevice9 (2nd, 3rd, 17th, 18th functions) const unsigned int offsetAddref = 1; const unsigned int offsetRelease = 2; const unsigned int offsetReset = 16; const unsigned int offsetPresent = 17; if (bIsWin8) { hhAddRef.setupInterface(idd, offsetAddref, reinterpret_cast<voidFunc>(myWin8AddRef)); hhRelease.setupInterface(idd, offsetRelease, reinterpret_cast<voidFunc>(myWin8Release)); } else { hhAddRef.setupInterface(idd, offsetAddref, reinterpret_cast<voidFunc>(myAddRef)); hhRelease.setupInterface(idd, offsetRelease, reinterpret_cast<voidFunc>(myRelease)); } hhReset.setupInterface(idd, offsetReset, reinterpret_cast<voidFunc>(myReset)); hhPresent.setupInterface(idd, offsetPresent, reinterpret_cast<voidFunc>(myPresent)); IDirect3DSwapChain9 *pSwap = NULL; idd->GetSwapChain(0, &pSwap); if (pSwap) { // The offset is dependent on the declaration order of the struct. // See IDirect3DSwapChain9 (Present is the fourth function) const unsigned int offsetPresent = 3; hhSwapPresent.setupInterface(pSwap, offsetPresent, reinterpret_cast<voidFunc>(mySwapPresent)); pSwap->Release(); } else { ods("D3D9: Failed to get swapchain for DevEx"); } ds->createCleanState(); return hr; }
void _stdcall ProxyDevice::GetGammaRamp(D3DGAMMARAMP *a) { IDirect3DSwapChain9 *sc; D3DPRESENT_PARAMETERS pp; realDevice->GetSwapChain(0, &sc); sc->GetPresentParameters(&pp); sc->Release(); if(pp.Windowed) GetDeviceGammaRamp(GetDC(pp.hDeviceWindow), (void*)a); else realDevice->GetGammaRamp(0, a); }
/* Destroys a context */ void D3DRenderer::DestroyContext(long context) { if(mSwapChains.find(context) == mSwapChains.end()) return; IDirect3DSwapChain9* pSwapChain = mSwapChains[context].mD3DSwapChain; if(!pSwapChain) return; pSwapChain->Release(); mSwapChains.erase(context); if(context == mContext) mContext = 0; }
static HRESULT __stdcall myCreateDeviceEx(IDirect3D9Ex * id3d, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, IDirect3DDevice9Ex** ppReturnedDeviceInterface) { Mutex m; ods("D3D9: Chaining CreateDeviceEx"); // BehaviorFlags &= ~D3DCREATE_PUREDEVICE; CreateDeviceExType oCreateDeviceEx = (CreateDeviceExType) hhCreateDeviceEx.call; hhCreateDeviceEx.restore(); HRESULT hr=oCreateDeviceEx(id3d, Adapter,DeviceType,hFocusWindow,BehaviorFlags,pPresentationParameters,pFullscreenDisplayMode,ppReturnedDeviceInterface); hhCreateDeviceEx.inject(); if (FAILED(hr)) return hr; IDirect3DDevice9Ex *idd = *ppReturnedDeviceInterface; DevState *ds = new DevState; ds->dev = idd; idd->AddRef(); ds->initRefCount = idd->Release(); devMap[idd] = ds; if (bIsWin8) { hhAddRef.setupInterface(idd, 1, reinterpret_cast<voidFunc>(myWin8AddRef)); hhRelease.setupInterface(idd, 2, reinterpret_cast<voidFunc>(myWin8Release)); } else { hhAddRef.setupInterface(idd, 1, reinterpret_cast<voidFunc>(myAddRef)); hhRelease.setupInterface(idd, 2, reinterpret_cast<voidFunc>(myRelease)); } hhReset.setupInterface(idd, 16, reinterpret_cast<voidFunc>(myReset)); hhPresent.setupInterface(idd, 17, reinterpret_cast<voidFunc>(myPresent)); IDirect3DSwapChain9 *pSwap = NULL; idd->GetSwapChain(0, &pSwap); if (pSwap) { hhSwapPresent.setupInterface(pSwap, 3, reinterpret_cast<voidFunc>(mySwapPresent)); pSwap->Release(); } else { ods("D3D9: Failed to get swapchain for DevEx"); } ds->createCleanState(); return hr; }
void WindowResized() { if (d3dmgr == NULL) { return; } IDirect3DSwapChain9 *sc; d3dmgr->GetSwapChain(0, &sc); D3DPRESENT_PARAMETERS d3dpp; sc->GetPresentParameters(&d3dpp); int ww = window_get_width(), wh = window_get_height(); d3dpp.BackBufferWidth = ww <= 0 ? 1 : ww; d3dpp.BackBufferHeight = wh <= 0 ? 1 : wh; sc->Release(); OnDeviceLost(); d3dmgr->Reset(&d3dpp); OnDeviceReset(); // clear the window color, viewport does not need set because backbuffer was just recreated enigma_user::draw_clear(enigma_user::window_get_color()); }
//----------------------------------------------------------------------------- bool D3D9StereoDriverAMD::getPresentParamsAndVerifyStereoSettings() { // Verify the swap chain exists UINT numberOfSwapChains = mDevice->GetNumberOfSwapChains(); if (numberOfSwapChains < 0) return false; // Get the first swap chain IDirect3DSwapChain9* swapChain = NULL; if (FAILED(mDevice->GetSwapChain(0, &swapChain))) return false; // Cache the swap chain presentation parameters and release the swap chain swapChain->GetPresentParameters(&mSwapChainPresentParameters); swapChain->Release(); // Check if multi sample type must be set to a value greater than 1 to enable stereo if (D3DMULTISAMPLE_NONE == mSwapChainPresentParameters.MultiSampleType || D3DMULTISAMPLE_NONMASKABLE == mSwapChainPresentParameters.MultiSampleType) return false; return true; }
/// @copydoc Renderer::CreateSubContext() RRenderContext* D3D9Renderer::CreateSubContext( const ContextInitParameters& rInitParameters ) { // Make sure the main context has been initialized. HELIUM_ASSERT( m_spMainContext ); if( !m_spMainContext ) { HELIUM_TRACE( TRACE_ERROR, ( TXT( "D3D9Renderer: Attempted creation of a renderer sub-context without creating a main context " ) TXT( "first.\n" ) ) ); return NULL; } // Build the presentation parameters and create the swap chain. D3DPRESENT_PARAMETERS presentParameters; GetPresentParameters( presentParameters, rInitParameters ); IDirect3DSwapChain9* pSwapChain = NULL; HRESULT createResult = m_pD3DDevice->CreateAdditionalSwapChain( &presentParameters, &pSwapChain ); if( FAILED( createResult ) ) { HELIUM_TRACE( TRACE_ERROR, TXT( "D3D9Renderer: Swap chain creation failed (error code: 0x%x).\n" ), createResult ); return NULL; } // Create the rendering sub-context interface. D3D9SubContext* pSubContext = new D3D9SubContext( pSwapChain ); HELIUM_ASSERT( pSubContext ); // D3D9SubContext instance now has its own reference to the swap chain, so release our reference. pSwapChain->Release(); return pSubContext; }
static bool d3d9_get_swap_desc(D3DPRESENT_PARAMETERS &pp) { IDirect3DSwapChain9 *swap = nullptr; HRESULT hr; hr = data.device->GetSwapChain(0, &swap); if (FAILED(hr)) { hlog_hr("d3d9_get_swap_desc: Failed to get swap chain", hr); return false; } hr = swap->GetPresentParameters(&pp); swap->Release(); if (FAILED(hr)) { hlog_hr("d3d9_get_swap_desc: Failed to get " "presentation parameters", hr); return false; } return true; }
void display_reset(int samples, bool vsync) { if (d3dmgr == NULL) { return; } IDirect3DSwapChain9 *sc; d3dmgr->GetSwapChain(0, &sc); D3DPRESENT_PARAMETERS d3dpp; sc->GetPresentParameters(&d3dpp); if (vsync) { d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; //Present the frame immediately } else { d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //Present the frame immediately } d3dpp.MultiSampleType = (D3DMULTISAMPLE_TYPE)((int)D3DMULTISAMPLE_NONE + samples); // Levels of multi-sampling d3dpp.MultiSampleQuality = 0; //No multi-sampling if (samples) { d3dmgr->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); } else { d3dmgr->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE); } sc->Release(); enigma::OnDeviceLost(); d3dmgr->Reset(&d3dpp); enigma::OnDeviceReset(); }
static HRESULT __stdcall myCreateDevice(IDirect3D9 * id3d, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DDevice9 **ppReturnedDeviceInterface) { ods("D3D9: Chaining CreateDevice"); Mutex m; // BehaviorFlags &= ~D3DCREATE_PUREDEVICE; CreateDeviceType oCreateDevice = (CreateDeviceType) hhCreateDevice.call; hhCreateDevice.restore(); HRESULT hr=oCreateDevice(id3d, Adapter,DeviceType,hFocusWindow,BehaviorFlags,pPresentationParameters,ppReturnedDeviceInterface); hhCreateDevice.inject(); if (FAILED(hr)) return hr; IDirect3DDevice9 *idd = *ppReturnedDeviceInterface; IDirect3DSwapChain9 *pSwap = NULL; // Get real interface, please. bool bfound; do { bfound = false; idd->GetSwapChain(0, &pSwap); if (pSwap) { IDirect3DDevice9 *idorig = NULL; if (SUCCEEDED(pSwap->GetDevice(&idorig))) { if (idorig != idd) { ods("Prepatched device, using original. %p => %p", idorig, idd); if (idd != *ppReturnedDeviceInterface) idd->Release(); idd = idorig; bfound = true; } else { idorig->Release(); } } pSwap->Release(); } } while (bfound); DevState *ds = new DevState; ds->dev = idd; idd->AddRef(); ds->initRefCount = idd->Release(); devMap[idd] = ds; if (bIsWin8) { hhAddRef.setupInterface(idd, 1, reinterpret_cast<voidFunc>(myWin8AddRef)); hhRelease.setupInterface(idd, 2, reinterpret_cast<voidFunc>(myWin8Release)); } else { hhAddRef.setupInterface(idd, 1, reinterpret_cast<voidFunc>(myAddRef)); hhRelease.setupInterface(idd, 2, reinterpret_cast<voidFunc>(myRelease)); } hhReset.setupInterface(idd, 16, reinterpret_cast<voidFunc>(myReset)); hhPresent.setupInterface(idd, 17, reinterpret_cast<voidFunc>(myPresent)); pSwap = NULL; idd->GetSwapChain(0, &pSwap); if (pSwap) { hhSwapPresent.setupInterface(pSwap, 3, reinterpret_cast<voidFunc>(mySwapPresent)); pSwap->Release(); } else { ods("D3D9: Failed to get swapchain"); } ds->createCleanState(); return hr; }
static HRESULT __stdcall myCreateDevice(IDirect3D9 *id3d, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DDevice9 **ppReturnedDeviceInterface) { Mutex m; ods("D3D9: Chaining CreateDevice"); // BehaviorFlags &= ~D3DCREATE_PUREDEVICE; //TODO: Move logic to HardHook. // Call base without active hook in case of no trampoline. CreateDeviceType oCreateDevice = (CreateDeviceType) hhCreateDevice.call; hhCreateDevice.restore(); HRESULT hr = oCreateDevice(id3d, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); hhCreateDevice.inject(); if (FAILED(hr)) return hr; IDirect3DDevice9 *idd = *ppReturnedDeviceInterface; // Get real interface, please. IDirect3DDevice9 *originalDevice = findOriginalDevice(idd); if (idd != originalDevice) { ods("D3D9: Prepatched device, using original. %p => %p", idd, originalDevice); idd = originalDevice; } DevState *ds = new DevState; ds->dev = idd; idd->AddRef(); ds->initRefCount = idd->Release(); DevMapType::iterator it = devMap.find(idd); if (it != devMap.end()) { ods("Device exists in devMap already - canceling injection into device. Thread prev: %d ; new: %d", it->second->dwMyThread, GetCurrentThreadId()); delete ds; return hr; } devMap[idd] = ds; // The offsets are dependent on the declaration order of the struct. // See IDirect3DDevice9 (2nd, 3rd, 17th, 18th functions) const unsigned int offsetAddref = 1; const unsigned int offsetRelease = 2; const unsigned int offsetReset = 16; const unsigned int offsetPresent = 17; if (bIsWin8) { hhAddRef.setupInterface(idd, offsetAddref, reinterpret_cast<voidFunc>(myWin8AddRef)); hhRelease.setupInterface(idd, offsetRelease, reinterpret_cast<voidFunc>(myWin8Release)); } else { hhAddRef.setupInterface(idd, offsetAddref, reinterpret_cast<voidFunc>(myAddRef)); hhRelease.setupInterface(idd, offsetRelease, reinterpret_cast<voidFunc>(myRelease)); } hhReset.setupInterface(idd, offsetReset, reinterpret_cast<voidFunc>(myReset)); hhPresent.setupInterface(idd, offsetPresent, reinterpret_cast<voidFunc>(myPresent)); IDirect3DSwapChain9 *pSwap = NULL; idd->GetSwapChain(0, &pSwap); if (pSwap) { // The offset is dependent on the declaration order of the struct. // See IDirect3DSwapChain9 (Present is the fourth function) const unsigned int offsetPresent = 3; hhSwapPresent.setupInterface(pSwap, offsetPresent, reinterpret_cast<voidFunc>(mySwapPresent)); pSwap->Release(); } else { ods("D3D9: Failed to get swapchain"); } ds->createCleanState(); return hr; }
/* Called when a drawing pass has ended */ void D3DRenderer::OnDrawEnd() { mDeviceLost = false; mD3DDevice->SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, 0); mD3DDevice->EndScene(); HRESULT result = 0; result = mD3DDevice->TestCooperativeLevel(); if(result == D3DERR_DEVICELOST) return; if(result == D3DERR_DEVICENOTRESET) { mDeviceLost = true; // Release the existing swap chains SwapChainMap::iterator swapChainIt = mSwapChains.begin(); for(; swapChainIt != mSwapChains.end(); swapChainIt++) { IDirect3DSwapChain9* pSwapChain = swapChainIt->second.mD3DSwapChain; if(pSwapChain) { pSwapChain->Release(); } } // Release the shaders ShaderMap::iterator shaderIt = mShaders.begin(); for(; shaderIt != mShaders.end(); shaderIt++) { (*shaderIt).second.mEffect->Release(); } // Release the vbuffer mVertexBuffer->Release(); mVertexBuffer = NULL; // Release the vertex decl mVertexDeclaration->Release(); mVertexDeclaration = NULL; // Reset the device D3DPRESENT_PARAMETERS d3dpp; GetPresentParams(d3dpp); HRESULT hr = mD3DDevice->Reset(&d3dpp); if(FAILED(hr)) { printf("FAILED\n"); } // Recreate the swap chains swapChainIt = mSwapChains.begin(); for(; swapChainIt != mSwapChains.end(); swapChainIt++) { SwapChain swapChain = swapChainIt->second; CreateContext(swapChain.mWindow, swapChain.mWidth, swapChain.mHeight, swapChainIt->first); } // Create the Vertex Buffer CreateBuffers(); // Recreate the shaders ShaderMap tmp = mShaders; mShaders.clear(); CreateShaders(); shaderIt = tmp.begin(); for(; shaderIt != tmp.end(); shaderIt++) { Shader& shader = shaderIt->second; if(shader.mSource != "") LoadShader(shader.mName.c_str(), shader.mSource.c_str()); } // By setting mContext to zero, we force the back-buffer changes in the next frame long oldContext = mContext; mContext = 0; SetContext(oldContext); } SwapChainMap::iterator it = mSwapChains.find(mContext); if(it != mSwapChains.end()) { IDirect3DSwapChain9* pSwapChain = it->second.mD3DSwapChain; if(pSwapChain) result = pSwapChain->Present(NULL, NULL, NULL, NULL, 0); } }
void Render( IDirect3DDevice9Ex* pDev ) { // Begin the scene if( !g_bSkipRendering && SUCCEEDED( pDev->BeginScene() ) ) { // disable lighting pDev->SetRenderState( D3DRS_LIGHTING, FALSE ); // // Render the background // // set the texture pDev->SetTexture( 0, g_pSharedBackgroundTexture ); pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); // stream sources pDev->SetStreamSource( 0, g_pScreenVB, 0, sizeof(SCREENVERTEX) ); pDev->SetFVF( D3DFVF_SCREENVERTEX ); // draw pDev->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 ); // // Render the cursor // pDev->SetTexture( 0, NULL ); // set the texture stage states pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE ); // stream sources pDev->SetStreamSource( 0, g_pCursorVB, 0, sizeof(CURSORVERTEX) ); pDev->SetFVF( D3DFVF_CURSORVERTEX ); // draw pDev->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 ); // render text RenderText( pDev ); // End the scene pDev->EndScene(); } else if( g_bSkipRendering ) Sleep(20); //don't hog the entire CPU // Present the backbuffer contents to the display HRESULT hr = pDev->Present( NULL, NULL, NULL, NULL ); // Handle Occluded, DeviceReset, or Mode Changes if( S_PRESENT_OCCLUDED == hr ) { g_bSkipRendering = true; } else if( D3DERR_DEVICELOST == hr ) { if(FAILED( Reset( pDev ) ) ) g_bSkipRendering = true; } else if( S_PRESENT_MODE_CHANGED == hr ) { // // Reenumerate modes by calling IDirect3D9::GetAdapterModeCountEx // D3DDISPLAYMODEFILTER DisplayModeFilter; ZeroMemory(&DisplayModeFilter, sizeof(DisplayModeFilter)); DisplayModeFilter.Size = sizeof(DisplayModeFilter); DisplayModeFilter.Format = D3DFMT_UNKNOWN; DisplayModeFilter.ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE; UINT ModeCount = g_pD3D9->GetAdapterModeCountEx(D3DADAPTER_DEFAULT, &DisplayModeFilter); if(FAILED( Reset( pDev ) ) ) g_bSkipRendering = true; } else if( D3DERR_DEVICEHUNG == hr ) { MessageBox( g_hWnd, L"This application has caused the graphics adapter to hang, check with the hardware vendor for a new driver.", L"Graphics Adapter Hang", MB_OK ); PostQuitMessage(0); g_bSkipRendering = true; } else { g_bSkipRendering = false; } // Get some presents stats IDirect3DSwapChain9* pSwapChain; if( SUCCEEDED( pDev->GetSwapChain( 0, &pSwapChain ) ) ) { IDirect3DSwapChain9Ex* pSwapChainEx; if( SUCCEEDED( pSwapChain->QueryInterface( IID_IDirect3DSwapChain9Ex, (void**)&pSwapChainEx ) ) ) { hr = pSwapChainEx->GetLastPresentCount( &g_PresentStats.PresentCount ); if( SUCCEEDED( hr ) ) hr = pSwapChainEx->GetPresentStats( &g_PresentStats ); pSwapChainEx->Release(); } pSwapChain->Release(); } // Get the time LARGE_INTEGER liCurrentTime; QueryPerformanceCounter( &liCurrentTime ); g_fLastFrameTime = (float)(liCurrentTime.QuadPart - g_liLastTimerUpdate.QuadPart) / (float)g_liTimerFrequency.QuadPart; g_liLastTimerUpdate.QuadPart = liCurrentTime.QuadPart; }
static bool manually_get_d3d9_addrs(HMODULE d3d9_module, void **present_addr, void **present_ex_addr, void **present_swap_addr) { d3d9create_ex_t create_ex; D3DPRESENT_PARAMETERS pp; HRESULT hr; IDirect3DDevice9Ex *device; IDirect3D9Ex *d3d9ex; hlog("D3D9 values invalid, manually obtaining"); create_ex = (d3d9create_ex_t)GetProcAddress(d3d9_module, "Direct3DCreate9Ex"); if (!create_ex) { hlog("Failed to load Direct3DCreate9Ex"); return false; } if (FAILED(create_ex(D3D_SDK_VERSION, &d3d9ex))) { hlog("Failed to create D3D9 context"); return false; } memset(&pp, 0, sizeof(pp)); pp.Windowed = 1; pp.SwapEffect = D3DSWAPEFFECT_FLIP; pp.BackBufferFormat = D3DFMT_A8R8G8B8; pp.BackBufferCount = 1; pp.hDeviceWindow = (HWND)dummy_window; pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; hr = d3d9ex->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, dummy_window, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_NOWINDOWCHANGES, &pp, NULL, &device); d3d9ex->Release(); if (SUCCEEDED(hr)) { uintptr_t *vtable = *(uintptr_t**)device; IDirect3DSwapChain9 *swap; *present_addr = (void*)vtable[17]; *present_ex_addr = (void*)vtable[121]; hr = device->GetSwapChain(0, &swap); if (SUCCEEDED(hr)) { vtable = *(uintptr_t**)swap; *present_swap_addr = (void*)vtable[3]; swap->Release(); } device->Release(); } else { hlog("Failed to create D3D9 device"); return false; } return true; }
HRESULT WINAPI D3D9Present(IDirect3DDevice9 *pDev, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) { D3D9FrameGrabber *d3d9FrameGrabber = D3D9FrameGrabber::getInstance(); Logger *logger = d3d9FrameGrabber->m_logger; DWORD errorcode; if (WAIT_OBJECT_0 == (errorcode = WaitForSingleObject(d3d9FrameGrabber->m_syncRunMutex, 0))) { IPCContext *ipcContext = d3d9FrameGrabber->m_ipcContext; logger->reportLogDebug(L"D3D9Present"); HRESULT hRes; RECT newRect = RECT(); IDirect3DSurface9 *pBackBuffer = NULL; IDirect3DSurface9 *pDemultisampledSurf = NULL; IDirect3DSurface9 *pOffscreenSurf = NULL; IDirect3DSwapChain9 *pSc = NULL; D3DPRESENT_PARAMETERS params; if(FAILED( hRes = pDev->GetSwapChain(0, &pSc))) { logger->reportLogError(L"d3d9present couldn't get swapchain. result 0x%x", hRes); goto end; } hRes = pSc->GetPresentParameters(¶ms); if (FAILED(hRes) || params.Windowed) { goto end; } if(FAILED( hRes = pDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer))) { goto end; } D3DSURFACE_DESC surfDesc; pBackBuffer->GetDesc(&surfDesc); hRes = pDev->CreateRenderTarget( surfDesc.Width, surfDesc.Height, surfDesc.Format, D3DMULTISAMPLE_NONE, 0, false, &pDemultisampledSurf, NULL ); if (FAILED(hRes)) { logger->reportLogError(L"GetFramePrep: FAILED to create demultisampled render target. 0x%x, width=%u, height=%u, format=%x", hRes, surfDesc.Width, surfDesc.Height, surfDesc.Format ); goto end; } hRes = pDev->StretchRect(pBackBuffer, NULL, pDemultisampledSurf, NULL, D3DTEXF_LINEAR ); if (FAILED(hRes)) { logger->reportLogError(L"GetFramePrep: StretchRect FAILED for image surfacee. 0x%x, width=%u, height=%u, format=%x", hRes, surfDesc.Width, surfDesc.Height, surfDesc.Format ); goto end; } hRes = pDev->CreateOffscreenPlainSurface( surfDesc.Width, surfDesc.Height, surfDesc.Format, D3DPOOL_SYSTEMMEM, &pOffscreenSurf, NULL ); if (FAILED(hRes)) { logger->reportLogError(L"GetFramePrep: FAILED to create image surface. 0x%x, width=%u, height=%u, format=%x", hRes, surfDesc.Width, surfDesc.Height, surfDesc.Format ); goto end; } hRes = pDev->GetRenderTargetData(pDemultisampledSurf, pOffscreenSurf ); if (FAILED(hRes)) { logger->reportLogError(L"GetFramePrep: GetRenderTargetData() FAILED for image surfacee. 0x%x, width=%u, height=%u, format=%x", hRes, surfDesc.Width, surfDesc.Height, surfDesc.Format ); goto end; } D3DLOCKED_RECT lockedSrcRect; newRect.right = surfDesc.Width; newRect.bottom = surfDesc.Height; hRes = pOffscreenSurf->LockRect( &lockedSrcRect, &newRect, 0); if (FAILED(hRes)) { logger->reportLogError(L"GetFramePrep: FAILED to lock source rect. (0x%x)", hRes ); goto end; } ipcContext->m_memDesc.width = surfDesc.Width; ipcContext->m_memDesc.height = surfDesc.Height; ipcContext->m_memDesc.rowPitch = lockedSrcRect.Pitch; ipcContext->m_memDesc.frameId++; ipcContext->m_memDesc.format = getCompatibleBufferFormat(surfDesc.Format); DWORD errorcode; if (WAIT_OBJECT_0 == (errorcode = WaitForSingleObject(ipcContext->m_hMutex, 0))) { // reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d9 writing description to mem mapped file"); memcpy(ipcContext->m_pMemMap, &(ipcContext->m_memDesc), sizeof (ipcContext->m_memDesc)); // reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d9 writing data to mem mapped file"); PVOID pMemDataMap = incPtr(ipcContext->m_pMemMap, sizeof (ipcContext->m_memDesc)); if (static_cast<UINT>(lockedSrcRect.Pitch) == surfDesc.Width * 4) { memcpy(pMemDataMap, lockedSrcRect.pBits, surfDesc.Width * surfDesc.Height * 4); } else { UINT i = 0, cleanOffset = 0, pitchOffset = 0; while (i < surfDesc.Height) { memcpy(incPtr(pMemDataMap, cleanOffset), incPtr(lockedSrcRect.pBits, pitchOffset), surfDesc.Width * 4); cleanOffset += surfDesc.Width * 4; pitchOffset += lockedSrcRect.Pitch; i++; } } ReleaseMutex(ipcContext->m_hMutex); SetEvent(ipcContext->m_hFrameGrabbedEvent); } else { logger->reportLogError(L"d3d9 couldn't wait mutex. errocode = 0x%x", errorcode); } end: if(pOffscreenSurf) pOffscreenSurf->Release(); if(pDemultisampledSurf) pDemultisampledSurf->Release(); if(pBackBuffer) pBackBuffer->Release(); if(pSc) pSc->Release(); ProxyFuncJmp *d3d9PresentProxyFuncJmp = d3d9FrameGrabber->m_d3d9PresentProxyFuncJmp; if(!d3d9PresentProxyFuncJmp->removeHook()) { int i = GetLastError(); logger->reportLogError(L"d3d9 error occured while trying to removeHook before original call0x%x", i); } HRESULT result = pDev->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); if(!d3d9PresentProxyFuncJmp->installHook()) { int i = GetLastError(); logger->reportLogError(L"d3d9 error occured while trying to installHook after original call0x%x", i); } ReleaseMutex(d3d9FrameGrabber->m_syncRunMutex); return result; } else { logger->reportLogError(L"d3d9sc present is skipped because mutex is busy"); return S_FALSE; } }
//Given device to draw to, see if we already have it cached and if not, cache it. //Also check if we have switched mode (i.e. we were windowed and this device is //a fullscreen device, or we were full-screen and this is a windowed one). void CFSXGUI::CheckIfNewDevice(IDirect3DDevice9 *pI) { if (!pI) return; //Check if already have it bool bAlreadyHave = false; if (m_WindowedDeviceDesc.pDevice == pI) bAlreadyHave = true; else for (size_t i = 0; !bAlreadyHave && i < m_aFullscreenDevices.size(); i++) { if (m_aFullscreenDevices[i].pDevice == pI) bAlreadyHave = true; } //If we don't have it, determine if it's windowed or full-screen device and cache it if (!bAlreadyHave) { IDirect3DSwapChain9 *pISwapChain; if (FAILED(pI->GetSwapChain(0, &pISwapChain))) return; D3DPRESENT_PARAMETERS PP; if (FAILED(pISwapChain->GetPresentParameters(&PP))) { pISwapChain->Release(); return; } pISwapChain->Release(); //Windowed? if (PP.Windowed) { //There is only one windowed device, so we don't cache it. Also since we're presenting //on one, we must be in windowed mode. m_WindowedDeviceDesc.hWnd = PP.hDeviceWindow; //should always be m_hFSXWin? m_WindowedDeviceDesc.pDevice = pI; m_pFullscreenPrimaryDevice = nullptr; if (!m_bInWindowedMode) { m_bInWindowedMode = true; NotifyDialogsNowWindowed(PP.hDeviceWindow); } } //Fullscreen -- add to list. else { static DeviceDescStruct D; D.hWnd = PP.hDeviceWindow; D.pDevice = pI; m_aFullscreenDevices.push_back(D); //Currently only draw to device associated with FSX's main window (primary screen on multi-monitor setups). //We cache the other devices in case we want to drag to other monitors in fullscreen mode, someday. if (PP.hDeviceWindow == m_hFSXWindow) { m_pFullscreenPrimaryDevice = pI; m_bInWindowedMode = false; m_WindowedDeviceDesc.pDevice = nullptr; //no longer valid (FSX likely deletes it) NotifyDialogsNowFullscreen(pI, PP.BackBufferWidth, PP.BackBufferHeight); } } } return; }
void Surface::resetSwapChain() { IDirect3DDevice9 *device = mDisplay->getDevice(); D3DPRESENT_PARAMETERS presentParameters = {0}; presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat; presentParameters.BackBufferCount = 1; presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat; presentParameters.EnableAutoDepthStencil = FALSE; presentParameters.Flags = 0; presentParameters.hDeviceWindow = getWindowHandle(); presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented presentParameters.PresentationInterval = Display::convertInterval(mConfig->mMinSwapInterval); presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; presentParameters.Windowed = TRUE; RECT windowRect; if (!GetClientRect(getWindowHandle(), &windowRect)) { ASSERT(false); return; } presentParameters.BackBufferWidth = windowRect.right - windowRect.left; presentParameters.BackBufferHeight = windowRect.bottom - windowRect.top; IDirect3DSwapChain9 *swapChain = NULL; HRESULT result = device->CreateAdditionalSwapChain(&presentParameters, &swapChain); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); ERR("Could not create additional swap chains: %08lX", result); return error(EGL_BAD_ALLOC); } IDirect3DSurface9 *depthStencilSurface = NULL; result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType, presentParameters.MultiSampleQuality, FALSE, &depthStencilSurface, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); swapChain->Release(); ERR("Could not create depthstencil surface for new swap chain: %08lX", result); return error(EGL_BAD_ALLOC); } IDirect3DSurface9 *renderTarget = NULL; result = device->CreateRenderTarget(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, presentParameters.BackBufferFormat, presentParameters.MultiSampleType, presentParameters.MultiSampleQuality, FALSE, &renderTarget, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); swapChain->Release(); depthStencilSurface->Release(); ERR("Could not create render target surface for new swap chain: %08lX", result); return error(EGL_BAD_ALLOC); } ASSERT(SUCCEEDED(result)); IDirect3DTexture9 *flipTexture = NULL; result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET, presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &flipTexture, NULL); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); swapChain->Release(); depthStencilSurface->Release(); renderTarget->Release(); ERR("Could not create flip texture for new swap chain: %08lX", result); return error(EGL_BAD_ALLOC); } IDirect3DSurface9 *backBuffer = NULL; swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer); if (mSwapChain) mSwapChain->Release(); if (mDepthStencil) mDepthStencil->Release(); if (mBackBuffer) mBackBuffer->Release(); if (mRenderTarget) mRenderTarget->Release(); if (mFlipTexture) mFlipTexture->Release(); mWidth = presentParameters.BackBufferWidth; mHeight = presentParameters.BackBufferHeight; mSwapChain = swapChain; mDepthStencil = depthStencilSurface; mBackBuffer = backBuffer; mRenderTarget = renderTarget; mFlipTexture = flipTexture; // The flip state block recorded mFlipTexture so it is now invalid. releaseRecordedState(device); }