From 9d05bc949e0ddff2b7ae97cbaaa9eef8c580e9f9 Mon Sep 17 00:00:00 2001 From: Elisha Riedlinger Date: Mon, 9 Sep 2024 14:42:28 -0700 Subject: [PATCH] Use shadow surface for Render Target --- ddraw/IDirect3DDeviceX.cpp | 18 ++-- ddraw/IDirectDrawSurfaceX.cpp | 183 +++++++++++++++++++++++++++++----- ddraw/IDirectDrawSurfaceX.h | 7 +- ddraw/IDirectDrawX.cpp | 4 + 4 files changed, 176 insertions(+), 36 deletions(-) diff --git a/ddraw/IDirect3DDeviceX.cpp b/ddraw/IDirect3DDeviceX.cpp index d642e591..72f34322 100644 --- a/ddraw/IDirect3DDeviceX.cpp +++ b/ddraw/IDirect3DDeviceX.cpp @@ -1924,6 +1924,11 @@ HRESULT m_IDirect3DDeviceX::Clear(DWORD dwCount, LPD3DRECT lpRects, DWORD dwFlag return DDERR_INVALIDOBJECT; } + if ((dwFlags & D3DCLEAR_TARGET) && lpCurrentRenderTargetX) + { + lpCurrentRenderTargetX->PrepareRenderTarget(); + } + // Clear primary surface /*if (!Config.DdrawEnableRenderTarget && lpCurrentRenderTargetX && (dwFlags & D3DCLEAR_TARGET)) { @@ -1943,11 +1948,6 @@ HRESULT m_IDirect3DDeviceX::Clear(DWORD dwCount, LPD3DRECT lpRects, DWORD dwFlag lpCurrentRenderTargetX->ClearDirtyFlags(); }*/ - if ((dwFlags & D3DCLEAR_TARGET) && lpCurrentRenderTargetX) - { - lpCurrentRenderTargetX->SetRenderTargetDirty(); - } - return (*d3d9Device)->Clear(dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil); } @@ -4311,6 +4311,10 @@ inline void m_IDirect3DDeviceX::SetDrawStates(DWORD dwVertexTypeDesc, DWORD& dwF } if (Config.Dd7to9) { + if (lpCurrentRenderTargetX) + { + lpCurrentRenderTargetX->PrepareRenderTarget(); + } if (Config.DdrawFixByteAlignment > 1) { for (UINT x = 0; x < MaxTextureStages; x++) @@ -4392,10 +4396,6 @@ inline void m_IDirect3DDeviceX::RestoreDrawStates(DWORD dwVertexTypeDesc, DWORD } if (Config.Dd7to9) { - if (lpCurrentRenderTargetX) - { - lpCurrentRenderTargetX->SetRenderTargetDirty(); - } if (Config.DdrawFixByteAlignment > 1) { for (UINT x = 0; x < MaxTextureStages; x++) diff --git a/ddraw/IDirectDrawSurfaceX.cpp b/ddraw/IDirectDrawSurfaceX.cpp index 3fbd66f4..3afae2d3 100644 --- a/ddraw/IDirectDrawSurfaceX.cpp +++ b/ddraw/IDirectDrawSurfaceX.cpp @@ -2089,6 +2089,12 @@ HRESULT m_IDirectDrawSurfaceX::GetDC(HDC FAR* lphDC, DWORD MipMapLevel) auto startTime = std::chrono::high_resolution_clock::now(); #endif + // Check if render target should use shadow + if (surface.Type == D3DTYPE_RENDERTARGET && !IsUsingShadowSurface()) + { + SetRenderTargetShadow(); + } + HRESULT hr = DD_OK; do { @@ -2123,7 +2129,7 @@ HRESULT m_IDirectDrawSurfaceX::GetDC(HDC FAR* lphDC, DWORD MipMapLevel) else { // Get surface - IDirect3DSurface9* pSurfaceD9 = Get3DSurface(); + IDirect3DSurface9* pSurfaceD9 = Get3DMipMapSurface(0); if (!pSurfaceD9) { LOG_LIMIT(100, __FUNCTION__ << " Error: could not find surface!"); @@ -2694,6 +2700,12 @@ HRESULT m_IDirectDrawSurfaceX::Lock2(LPRECT lpDestRect, LPDDSURFACEDESC2 lpDDSur auto startTime = std::chrono::high_resolution_clock::now(); #endif + // Check if render target should use shadow + if (surface.Type == D3DTYPE_RENDERTARGET && !IsUsingShadowSurface()) + { + SetRenderTargetShadow(); + } + HRESULT hr = DD_OK; do { @@ -2873,6 +2885,11 @@ inline HRESULT m_IDirectDrawSurfaceX::LockD3d9Surface(D3DLOCKED_RECT* pLockedRec pLockedRect->pBits = (pRect) ? (void*)((DWORD)surfaceDesc2.lpSurface + ((pRect->top * pLockedRect->Pitch) + (pRect->left * (surface.BitCount / 8)))) : surfaceDesc2.lpSurface; return DD_OK; } + // Lock shadow surface + else if (IsUsingShadowSurface()) + { + return surface.Shadow->LockRect(pLockedRect, pRect, Flags); + } // Lock 3D surface else if (surface.Surface) { @@ -2931,7 +2948,7 @@ HRESULT m_IDirectDrawSurfaceX::ReleaseDC(HDC hDC) else { // Get surface - IDirect3DSurface9* pSurfaceD9 = Get3DSurface(); + IDirect3DSurface9* pSurfaceD9 = Get3DMipMapSurface(0); if (!pSurfaceD9) { LOG_LIMIT(100, __FUNCTION__ << " Error: could not find surface!"); @@ -3391,6 +3408,11 @@ inline HRESULT m_IDirectDrawSurfaceX::UnLockD3d9Surface(DWORD MipMapLevel) { return DD_OK; } + // Unlock shadow surface + else if (IsUsingShadowSurface()) + { + return surface.Shadow->UnlockRect(); + } // Unlock 3D surface else if (surface.Surface) { @@ -4001,7 +4023,11 @@ inline LPDIRECT3DSURFACE9 m_IDirectDrawSurfaceX::Get3DSurface() inline LPDIRECT3DSURFACE9 m_IDirectDrawSurfaceX::Get3DMipMapSurface(DWORD MipMapLevel) { - if (MipMapLevel == 0 || surface.Type != D3DTYPE_TEXTURE) + if (IsUsingShadowSurface()) + { + return surface.Shadow; + } + else if (MipMapLevel == 0 || surface.Type != D3DTYPE_TEXTURE) { return Get3DSurface(); } @@ -4016,7 +4042,7 @@ inline LPDIRECT3DSURFACE9 m_IDirectDrawSurfaceX::Get3DMipMapSurface(DWORD MipMap inline void m_IDirectDrawSurfaceX::Release3DMipMapSurface(LPDIRECT3DSURFACE9 pSurfaceD9, DWORD MipMapLevel) { - if (pSurfaceD9 && MipMapLevel != 0 && surface.Type == D3DTYPE_TEXTURE) + if (pSurfaceD9 && MipMapLevel != 0 && surface.Type == D3DTYPE_TEXTURE && !IsUsingShadowSurface()) { pSurfaceD9->Release(); } @@ -4124,7 +4150,7 @@ void m_IDirectDrawSurfaceX::CheckMipMapLevelGen() HRESULT m_IDirectDrawSurfaceX::GenerateMipMapLevels() { - IDirect3DSurface9* pSourceSurfaceD9 = Get3DSurface(); + IDirect3DSurface9* pSourceSurfaceD9 = Get3DMipMapSurface(0); if (!pSourceSurfaceD9) { LOG_LIMIT(100, __FUNCTION__ << " Error: could not get surface level!"); @@ -4135,8 +4161,8 @@ HRESULT m_IDirectDrawSurfaceX::GenerateMipMapLevels() { if (!MipMaps[x].HasData && !MipMaps[x].IsDummy) { - IDirect3DSurface9* pDestSurfaceD9 = nullptr; - if (SUCCEEDED(surface.Texture->GetSurfaceLevel(x + 1, &pDestSurfaceD9))) + IDirect3DSurface9* pDestSurfaceD9 = Get3DMipMapSurface(x + 1); + if (pDestSurfaceD9) { LOG_LIMIT(100, __FUNCTION__ << " (" << this << ") Warning: attempting to add missing data to MipMap surface level: " << (x + 1)); if (SUCCEEDED(D3DXLoadSurfaceFromSurface(pDestSurfaceD9, nullptr, nullptr, pSourceSurfaceD9, nullptr, nullptr, D3DX_FILTER_LINEAR, 0x00000000))) @@ -4147,7 +4173,7 @@ HRESULT m_IDirectDrawSurfaceX::GenerateMipMapLevels() { LOG_LIMIT(100, __FUNCTION__ << " Error: could not copy MipMap surface level!"); } - pDestSurfaceD9->Release(); + Release3DMipMapSurface(pDestSurfaceD9, x + 1); } } } @@ -4422,6 +4448,19 @@ HRESULT m_IDirectDrawSurfaceX::CreateD3d9Surface() } } + // Create shadow surface + if (surface.Type == D3DTYPE_RENDERTARGET && surface.Surface) + { + surface.UsingShadowSurface = false; + D3DSURFACE_DESC Desc; + if (FAILED(surface.Surface->GetDesc(&Desc)) || FAILED((*d3d9Device)->CreateOffscreenPlainSurface(Desc.Width, Desc.Height, Desc.Format, D3DPOOL_SYSTEMMEM, &surface.Shadow, nullptr))) + { + LOG_LIMIT(100, __FUNCTION__ << " Error: failed to create shadow surface. Size: " << Width << "x" << Height << " Format: " << Format << " dwCaps: " << surfaceDesc2.ddsCaps); + hr = DDERR_GENERIC; + break; + } + } + // Create primary surface texture if (ShouldPresentToWindow(false)) { @@ -5096,6 +5135,18 @@ void m_IDirectDrawSurfaceX::ReleaseD9Surface(bool BackupData, bool ResetSurface) surface.Surface = nullptr; } + // Release d3d9 shadow surface + if (surface.Shadow && !ResetSurface) + { + Logging::LogDebug() << __FUNCTION__ << " Releasing Direct3D9 surface"; + ULONG ref = surface.Shadow->Release(); + if (ref) + { + Logging::Log() << __FUNCTION__ << " Error: there is still a reference to 'surface.Shadow' " << ref; + } + surface.Shadow = nullptr; + } + // Release d3d9 surface texture if (surface.Texture && (!ResetSurface || IsD9UsingVideoMemory())) { @@ -5561,10 +5612,30 @@ inline HRESULT m_IDirectDrawSurfaceX::LockEmulatedSurface(D3DLOCKED_RECT* pLocke return DD_OK; } -void m_IDirectDrawSurfaceX::SetRenderTargetDirty() +void m_IDirectDrawSurfaceX::PrepareRenderTarget() { - surface.IsRenderTargetDirty = true; - SetDirtyFlag(); + if (IsUsingShadowSurface()) + { + if (SUCCEEDED((*d3d9Device)->UpdateSurface(surface.Shadow, nullptr, surface.Surface, nullptr))) + { + surface.UsingShadowSurface = false; + return; + } + LOG_LIMIT(100, __FUNCTION__ << " Error: failed to update render target!"); + } +} + +void m_IDirectDrawSurfaceX::SetRenderTargetShadow() +{ + if (!IsUsingShadowSurface() && surface.Surface && surface.Shadow) + { + if (SUCCEEDED((*d3d9Device)->GetRenderTargetData(surface.Surface, surface.Shadow))) + { + surface.UsingShadowSurface = true; + return; + } + LOG_LIMIT(100, __FUNCTION__ << " Error: failed to get render target data!"); + } } // Set dirty flag @@ -5886,7 +5957,7 @@ HRESULT m_IDirectDrawSurfaceX::ColorFill(RECT* pRect, D3DCOLOR dwFillColor, DWOR HRESULT hr = DDERR_GENERIC; // Use GPU ColorFill - if (((surface.Usage & D3DUSAGE_RENDERTARGET) || surface.Type == D3DTYPE_OFFPLAINSURFACE) && surface.Pool == D3DPOOL_DEFAULT) + if (!IsUsingShadowSurface() && ((surface.Usage & D3DUSAGE_RENDERTARGET) || surface.Type == D3DTYPE_OFFPLAINSURFACE) && surface.Pool == D3DPOOL_DEFAULT) { IDirect3DSurface9* pDestSurfaceD9 = Get3DMipMapSurface(MipMapLevel); if (pDestSurfaceD9) @@ -6148,6 +6219,14 @@ HRESULT m_IDirectDrawSurfaceX::CopySurface(m_IDirectDrawSurfaceX* pSourceSurface (IsStretchRect) ? D3DX_FILTER_POINT : // Default to point filtering when stretching the rect, same as DirectDraw D3DX_FILTER_NONE; +#ifdef ENABLE_PROFILING + Logging::Log() << __FUNCTION__ << " (" << pSourceSurface << ") -> (" << this << ")" << + " StretchRect = " << IsStretchRect << + " ColorKey = " << IsColorKey << + " MirrorLeftRight = " << IsMirrorLeftRight << + " MirrorUpDown = " << IsMirrorUpDown; +#endif + // Check rect and do clipping if (!pSourceSurface->CheckCoordinates(SrcRect, &SrcRect, &SrcDesc2) || !CheckCoordinates(DestRect, &DestRect, &DestDesc2)) { @@ -6187,14 +6266,14 @@ HRESULT m_IDirectDrawSurfaceX::CopySurface(m_IDirectDrawSurfaceX* pSourceSurface do { // Use StretchRect for video memory to prevent copying out of video memory - if (!IsUsingEmulation() && + if (!IsUsingEmulation() && !IsUsingShadowSurface() && !pSourceSurface->IsUsingShadowSurface() && (pSourceSurface->surface.Pool == D3DPOOL_DEFAULT && surface.Pool == D3DPOOL_DEFAULT) && (pSourceSurface->surface.Type == surface.Type || (pSourceSurface->surface.Type == D3DTYPE_OFFPLAINSURFACE && surface.Type == D3DTYPE_RENDERTARGET)) && (!IsStretchRect || (this != pSourceSurface && !ISDXTEX(SrcFormat) && !ISDXTEX(DestFormat) && surface.Type == D3DTYPE_RENDERTARGET)) && (surface.Type != D3DTYPE_DEPTHSTENCIL || !ddrawParent->IsInScene()) && (surface.Type != D3DTYPE_TEXTURE) && (!pSourceSurface->IsPalette() && !IsPalette()) && - !IsColorKey) + !IsMirrorLeftRight && !IsMirrorUpDown && !IsColorKey) { IDirect3DSurface9* pSourceSurfaceD9 = pSourceSurface->Get3DMipMapSurface(SrcMipMapLevel); IDirect3DSurface9* pDestSurfaceD9 = Get3DMipMapSurface(MipMapLevel); @@ -6220,19 +6299,57 @@ HRESULT m_IDirectDrawSurfaceX::CopySurface(m_IDirectDrawSurfaceX* pSourceSurface } // Use UpdateSurface for copying system memory to video memory - if (!IsUsingEmulation() && - (pSourceSurface->surface.Pool == D3DPOOL_SYSTEMMEM && surface.Pool == D3DPOOL_DEFAULT) && + if (!IsUsingEmulation() && !IsUsingShadowSurface() && surface.Pool == D3DPOOL_DEFAULT && + (pSourceSurface->surface.Pool == D3DPOOL_SYSTEMMEM || pSourceSurface->IsUsingShadowSurface() || + (pSourceSurface->surface.Pool == D3DPOOL_MANAGED && surface.Shadow && (surface.BitCount == 8 || surface.BitCount == 16 || surface.BitCount == 24 || surface.BitCount == 32))) && (pSourceSurface->surface.Type != D3DTYPE_DEPTHSTENCIL && surface.Type != D3DTYPE_DEPTHSTENCIL) && (pSourceSurface->surface.Format == surface.Format) && (!pSourceSurface->IsPalette() && !IsPalette()) && - !IsStretchRect && !IsColorKey) + !IsStretchRect && !IsMirrorLeftRight && !IsMirrorUpDown && !IsColorKey) { IDirect3DSurface9* pSourceSurfaceD9 = pSourceSurface->Get3DMipMapSurface(SrcMipMapLevel); IDirect3DSurface9* pDestSurfaceD9 = Get3DMipMapSurface(MipMapLevel); if (pSourceSurfaceD9 && pDestSurfaceD9) { - hr = (*d3d9Device)->UpdateSurface(pSourceSurfaceD9, &SrcRect, pDestSurfaceD9, (LPPOINT)&DestRect); + if (pSourceSurface->surface.Pool == D3DPOOL_SYSTEMMEM || pSourceSurface->IsUsingShadowSurface()) + { + hr = (*d3d9Device)->UpdateSurface(pSourceSurfaceD9, &SrcRect, pDestSurfaceD9, (LPPOINT)&DestRect); + } + else + { + do { + D3DLOCKED_RECT SrcLockedRect = {}; + if (FAILED(pSourceSurfaceD9->LockRect(&SrcLockedRect, &SrcRect, D3DLOCK_READONLY))) + { + LOG_LIMIT(100, __FUNCTION__ << " Error: failed to lock source surface for update!"); + break; + } + D3DLOCKED_RECT DestLockedRect = {}; + if (FAILED(surface.Shadow->LockRect(&DestLockedRect, &DestRect, 0))) + { + LOG_LIMIT(100, __FUNCTION__ << " Error: failed to lock shadow surface for update!"); + pSourceSurfaceD9->UnlockRect(); + break; + } + + BYTE* SrcBytes = (BYTE*)SrcLockedRect.pBits; + BYTE* DestBytes = (BYTE*)DestLockedRect.pBits; + size_t Size = DestRectWidth * surface.BitCount / 8; + for (int x = 0; x < DestRectHeight ; x++) + { + memcpy(DestBytes, SrcBytes, Size); + SrcBytes += SrcLockedRect.Pitch; + DestBytes += DestLockedRect.Pitch; + } + + surface.Shadow->UnlockRect(); + pSourceSurfaceD9->UnlockRect(); + + hr = (*d3d9Device)->UpdateSurface(surface.Shadow, &DestRect, pDestSurfaceD9, (LPPOINT)&DestRect); + + } while (false); + } if (FAILED(hr)) { @@ -6250,6 +6367,12 @@ HRESULT m_IDirectDrawSurfaceX::CopySurface(m_IDirectDrawSurfaceX* pSourceSurface } } + // Check if render target should use shadow + if (surface.Type == D3DTYPE_RENDERTARGET && !IsUsingShadowSurface()) + { + SetRenderTargetShadow(); + } + // Decode DirectX texture if (ISDXTEX(SrcFormat)) { @@ -6347,17 +6470,27 @@ HRESULT m_IDirectDrawSurfaceX::CopySurface(m_IDirectDrawSurfaceX* pSourceSurface !surface.UsingSurfaceMemory && !pSourceSurface->surface.UsingSurfaceMemory && (pSourceSurface->IsPalette() == IsPalette())) { - IDirect3DSurface9* pSourceSurfaceD9 = pSourceSurface->Get3DSurface(); - IDirect3DSurface9* pDestSurfaceD9 = Get3DSurface(); + IDirect3DSurface9* pSourceSurfaceD9 = pSourceSurface->Get3DMipMapSurface(SrcMipMapLevel); + IDirect3DSurface9* pDestSurfaceD9 = Get3DMipMapSurface(MipMapLevel); if (pSourceSurfaceD9 && pDestSurfaceD9) { - if (SUCCEEDED(D3DXLoadSurfaceFromSurface(pDestSurfaceD9, nullptr, &DestRect, pSourceSurfaceD9, nullptr, &SrcRect, D3DXFilter, 0))) + hr = D3DXLoadSurfaceFromSurface(pDestSurfaceD9, nullptr, &DestRect, pSourceSurfaceD9, nullptr, &SrcRect, D3DXFilter, 0); + + if (FAILED(hr)) { - hr = DD_OK; + LOG_LIMIT(100, __FUNCTION__ << " Error: failed to load surface from surface. " << (D3DERR)hr); break; } } + + pSourceSurface->Release3DMipMapSurface(pSourceSurfaceD9, SrcMipMapLevel); + Release3DMipMapSurface(pDestSurfaceD9, MipMapLevel); + + if (SUCCEEDED(hr)) + { + break; + } } // Check source and destination format @@ -6643,7 +6776,7 @@ HRESULT m_IDirectDrawSurfaceX::CopyToDrawTexture(LPRECT lpDestRect) return DDERR_GENERIC; } - IDirect3DSurface9* SrcSurface = Get3DSurface(); + IDirect3DSurface9* SrcSurface = Get3DMipMapSurface(0); IDirect3DSurface9* DestSurface = nullptr; if (!SrcSurface || FAILED(surface.DrawTexture->GetSurfaceLevel(0, &DestSurface))) { @@ -6698,7 +6831,7 @@ HRESULT m_IDirectDrawSurfaceX::CopyFromEmulatedSurface(LPRECT lpDestRect) } // Get real d3d9 surface - IDirect3DSurface9* pDestSurfaceD9 = Get3DSurface(); + IDirect3DSurface9* pDestSurfaceD9 = Get3DMipMapSurface(0); if (!pDestSurfaceD9) { LOG_LIMIT(100, __FUNCTION__ << " Error: could not get real surface!"); @@ -7138,7 +7271,7 @@ HRESULT m_IDirectDrawSurfaceX::GetPresentWindowRect(LPRECT pRect, RECT& DestRect } // Get source surface - IDirect3DSurface9* pSourceSurfaceD9 = Get3DSurface(); + IDirect3DSurface9* pSourceSurfaceD9 = Get3DMipMapSurface(0); if (!pSourceSurfaceD9) { LOG_LIMIT(100, __FUNCTION__ << " Error: Failed to get source surface!"); diff --git a/ddraw/IDirectDrawSurfaceX.h b/ddraw/IDirectDrawSurfaceX.h index 24366e8b..881c333a 100644 --- a/ddraw/IDirectDrawSurfaceX.h +++ b/ddraw/IDirectDrawSurfaceX.h @@ -112,8 +112,8 @@ class m_IDirectDrawSurfaceX : public IUnknown, public AddressLookupTableDdrawObj bool IsUsingWindowedMode = false; bool SurfaceHasData = false; bool UsingSurfaceMemory = false; + bool UsingShadowSurface = false; bool IsDirtyFlag = false; - bool IsRenderTargetDirty = false; bool IsDrawTextureDirty = false; bool IsPaletteDirty = false; // Used to detect if the palette surface needs to be updated DWORD BitCount = 0; // Bit count for this surface @@ -129,6 +129,7 @@ class m_IDirectDrawSurfaceX : public IUnknown, public AddressLookupTableDdrawObj LPPALETTEENTRY PaletteEntryArray = nullptr; // Used to store palette data address EMUSURFACE* emu = nullptr; // Emulated surface using device context LPDIRECT3DSURFACE9 Surface = nullptr; // Surface used for Direct3D + LPDIRECT3DSURFACE9 Shadow = nullptr; // Shadow surface for render target LPDIRECT3DTEXTURE9 Texture = nullptr; // Main surface texture used for locks, Blts and Flips LPDIRECT3DTEXTURE9 DrawTexture = nullptr; // Main surface texture with SetTexture calls LPDIRECT3DSURFACE9 Context = nullptr; // Context of the main surface texture @@ -276,6 +277,7 @@ class m_IDirectDrawSurfaceX : public IUnknown, public AddressLookupTableDdrawObj inline bool IsSurfaceInDC() { return IsInDC; } inline bool IsSurfaceBusy() { return (IsSurfaceBlitting() || IsSurfaceLocked() || IsSurfaceInDC()); } inline bool IsD9UsingVideoMemory() { return ((surface.Surface || surface.Texture) ? surface.Pool == D3DPOOL_DEFAULT : false); } + inline bool IsUsingShadowSurface() { return (surface.UsingShadowSurface && surface.Shadow); } inline bool IsLockedFromOtherThread() { return (IsSurfaceBlitting() || IsSurfaceLocked()) && LockedWithID && LockedWithID != GetCurrentThreadId(); } inline bool IsDummyMipMap(DWORD MipMapLevel) { return (MipMapLevel > MaxMipMapLevel || ((MipMapLevel & ~DXW_IS_MIPMAP_DUMMY) - 1 < MipMaps.size() && MipMaps[(MipMapLevel & ~DXW_IS_MIPMAP_DUMMY) - 1].IsDummy)); } inline DWORD GetD3d9MipMapLevel(DWORD MipMapLevel) { return min(MipMapLevel, MaxMipMapLevel); } @@ -302,6 +304,7 @@ class m_IDirectDrawSurfaceX : public IUnknown, public AddressLookupTableDdrawObj bool DoesFlipBackBufferExist(m_IDirectDrawSurfaceX* lpSurfaceX); // Copying surface textures + void SetRenderTargetShadow(); HRESULT SaveDXTDataToDDS(const void* data, size_t dataSize, const char* filename, int dxtVersion) const; HRESULT SaveSurfaceToFile(const char* filename, D3DXIMAGE_FILEFORMAT format); HRESULT CopySurface(m_IDirectDrawSurfaceX* pSourceSurface, RECT* pSourceRect, RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter, D3DCOLOR ColorKey, DWORD dwFlags, DWORD SrcMipMapLevel, DWORD MipMapLevel); @@ -466,7 +469,7 @@ class m_IDirectDrawSurfaceX : public IUnknown, public AddressLookupTableDdrawObj inline bool IsSurfaceDirty() { return surface.IsDirtyFlag; } inline bool IsMipMapAutogen() { return surface.Texture && (surface.Usage & D3DUSAGE_AUTOGENMIPMAP); } inline bool IsMipMapGenerated() { return IsMipMapReadyToUse || IsMipMapAutogen(); } - void SetRenderTargetDirty(); + void PrepareRenderTarget(); void ClearDirtyFlags(); bool GetColorKeyForShader(float(&lowColorKey)[4], float(&highColorKey)[4]); bool GetColorKeyForPrimaryShader(float(&lowColorKey)[4], float(&highColorKey)[4]); diff --git a/ddraw/IDirectDrawX.cpp b/ddraw/IDirectDrawX.cpp index 36227268..883a99c6 100644 --- a/ddraw/IDirectDrawX.cpp +++ b/ddraw/IDirectDrawX.cpp @@ -4447,10 +4447,14 @@ HRESULT m_IDirectDrawX::PresentScene(RECT* pRect) HRESULT DrawRet = DDERR_GENERIC; if (IsPrimaryRenderTarget()) { + PrimarySurface->PrepareRenderTarget(); + DrawRet = CopyPrimarySurfaceToBackbuffer(); } else if (RenderTargetSurface) { + RenderTargetSurface->PrepareRenderTarget(); + IDirect3DSurface9* pBackBuffer = nullptr; hr = d3d9Device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); if (SUCCEEDED(hr))