/* Sets the rendering context */ void D3DRenderer::SetContext(long context) { if(context != mContext) { if(mSwapChains.find(context) != mSwapChains.end()) { IDirect3DSwapChain9* pSwapChain = mSwapChains[context].mD3DSwapChain; if(pSwapChain) { LPDIRECT3DSURFACE9 pBack = NULL; HRESULT hr; hr = pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBack); if(SUCCEEDED(hr)) { hr = mD3DDevice->SetRenderTarget(0, pBack); pBack->Release(); } } } mContext = context; } }
//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; }
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(); 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; // On IDirect3DDevice9Ex const unsigned int offsetPresentEx = 121; const unsigned int offsetResetEx = 132; 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)); hhResetEx.setupInterface(idd, offsetResetEx, reinterpret_cast<voidFunc>(myResetEx)); hhPresent.setupInterface(idd, offsetPresent, reinterpret_cast<voidFunc>(myPresent)); hhPresentEx.setupInterface(idd, offsetPresentEx, reinterpret_cast<voidFunc>(myPresentEx)); 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 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 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; }
bool OculusVR::OnPresent_Direct3D9(IDirect3DDevice9* device) { const CHAR* head = "OculusVR::OnPresent_Direct3D9"; if (Renderer == nullptr) { Renderer = new Direct3D11Helper(EDirect3D::DXGI0, device); if (Renderer == nullptr) { LVMSG(head, "alloc renderer object failed"); return false; } } if (device != nullptr) { IDirect3DSwapChain9* swapChain = nullptr; D3DPRESENT_PARAMETERS params; if (FAILED(device->GetSwapChain(0, &swapChain)) || FAILED(swapChain->GetPresentParameters(¶ms))) { LVERROR(head, "get target window from direct9 device failed"); return false; } SGlobalSharedDataInst.SetTargetWindow(params.hDeviceWindow); SAFE_RELEASE(swapChain); } if (!EnsureInitialized(Renderer->GetSwapChain(), false)) { return false; } if (!Renderer->UpdateBuffer_Direct3D9(device)) { LVMSG(head, "update buffer with direct9 device failed"); return false; } //{ // if (RTV == nullptr) // { // if (Renderer->CreateRenderTargetView(Renderer->GetBufferDirect3D9Copy(), &RTV)) // { // return false; // } // } // RenderStateCache cache(Renderer->GetContext()); // cache.Capture(); // D3D11_VIEWPORT vp; // vp.TopLeftX = Layer[0]->EyeRenderViewport[0].Pos.x; // vp.TopLeftY = Layer[0]->EyeRenderViewport[0].Pos.y; // vp.Width = Layer[0]->EyeRenderViewport[0].Size.w; // vp.Height = Layer[0]->EyeRenderViewport[0].Size.h; // vp.MinDepth = 0.01f; // vp.MaxDepth = 10000.f; // Renderer->GetContext()->RSSetViewports(1, &vp); // Renderer->GetContext()->OMSetRenderTargets(1, &RTV, nullptr); // Renderer->UpdateCursor(LVVec3(2.f, 2.f, -1.f), 0.1f, DirectX::XMMatrixIdentity(), DirectX::XMMatrixIdentity(), // SGlobalSharedDataInst.GetBDrawCursor()); // cache.Restore(); //} Layer[0]->GetEyePoses(); ID3D11Texture2D* dst = Layer[0]->pEyeRenderTexture[0]->GetBuffer(); if (!Renderer->OutputBuffer_Texture2D_Direct3D9(dst)) { return false; } Layer[0]->Commit(0); ovrResult ret = DistortAndPresent(1); if (!OVR_SUCCESS(ret)) { //LVERROR(head, "submit failed(%d), ...", ret); return false; } return true; }
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. bool bfound = false; do { bfound = false; IDirect3DSwapChain9 *pSwap = NULL; idd->GetSwapChain(0, &pSwap); if (pSwap) { IDirect3DDevice9 *idorig = NULL; if (SUCCEEDED(pSwap->GetDevice(&idorig))) { if (idorig != idd) { ods("D3D9: 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; // 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; }
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; } }
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; }
/* 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 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); }