From 068cdb802820ea6a50da4244ba3d29189035cfc4 Mon Sep 17 00:00:00 2001 From: narzoul Date: Mon, 16 May 2016 18:16:13 +0200 Subject: [PATCH] Replaced IDirectDrawSurface raw pointers with smart pointers --- DDrawCompat/CompatDirectDraw.cpp | 26 ++-- DDrawCompat/CompatDirectDrawSurface.cpp | 90 +++++-------- DDrawCompat/CompatDirectDrawSurface.h | 3 +- DDrawCompat/CompatGdi.cpp | 1 - DDrawCompat/CompatGdiDcCache.cpp | 24 ++-- DDrawCompat/CompatGdiDcCache.h | 4 +- DDrawCompat/CompatPaletteConverter.cpp | 41 +++--- DDrawCompat/CompatPaletteConverter.h | 6 +- DDrawCompat/DDrawRepository.cpp | 13 +- DDrawCompat/DDrawRepository.h | 4 +- DDrawCompat/DllMain.cpp | 25 ++-- DDrawCompat/RealPrimarySurface.cpp | 161 ++++++++++++------------ DDrawCompat/RealPrimarySurface.h | 6 +- 13 files changed, 187 insertions(+), 217 deletions(-) diff --git a/DDrawCompat/CompatDirectDraw.cpp b/DDrawCompat/CompatDirectDraw.cpp index 9484b08..8d9aae6 100644 --- a/DDrawCompat/CompatDirectDraw.cpp +++ b/DDrawCompat/CompatDirectDraw.cpp @@ -2,6 +2,7 @@ #include "CompatDirectDraw.h" #include "CompatDirectDrawSurface.h" #include "CompatPrimarySurface.h" +#include "CompatPtr.h" #include "IReleaseNotifier.h" namespace @@ -17,13 +18,13 @@ namespace }; DirectDrawInterface* g_fullScreenDirectDraw = nullptr; - IDirectDrawSurface* g_fullScreenTagSurface = nullptr; + CompatWeakPtr g_fullScreenTagSurface; void onReleaseFullScreenTagSurface(); IReleaseNotifier g_fullScreenTagSurfaceReleaseNotifier(&onReleaseFullScreenTagSurface); - IDirectDrawSurface* createFullScreenTagSurface(IDirectDraw& dd) + CompatPtr createFullScreenTagSurface(IDirectDraw& dd) { DDSURFACEDESC desc = {}; desc.dwSize = sizeof(desc); @@ -32,17 +33,14 @@ namespace desc.dwHeight = 1; desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - IDirectDrawSurface* tagSurface = nullptr; - CompatDirectDraw::s_origVtable.CreateSurface(&dd, &desc, &tagSurface, nullptr); + CompatPtr tagSurface; + CompatDirectDraw::s_origVtable.CreateSurface(&dd, &desc, &tagSurface.getRef(), nullptr); if (tagSurface) { - IDirectDrawSurface7* tagSurface7 = nullptr; - CompatDirectDrawSurface::s_origVtable.QueryInterface( - tagSurface, IID_IDirectDrawSurface7, reinterpret_cast(&tagSurface7)); - CompatDirectDrawSurface::s_origVtable.SetPrivateData( + CompatPtr tagSurface7(tagSurface); + tagSurface7->SetPrivateData( tagSurface7, IID_IReleaseNotifier, &g_fullScreenTagSurfaceReleaseNotifier, sizeof(&g_fullScreenTagSurfaceReleaseNotifier), DDSPD_IUNKNOWNPOINTER); - CompatDirectDrawSurface::s_origVtable.Release(tagSurface7); } return tagSurface; @@ -140,12 +138,8 @@ namespace void setFullScreenDirectDraw(IDirectDraw& dd) { - if (g_fullScreenTagSurface) - { - CompatDirectDrawSurface::s_origVtable.Release(g_fullScreenTagSurface); - g_fullScreenTagSurface = nullptr; - } - g_fullScreenTagSurface = createFullScreenTagSurface(dd); + g_fullScreenTagSurface.release(); + g_fullScreenTagSurface = createFullScreenTagSurface(dd).detach(); /* IDirectDraw interfaces don't conform to the COM rule about object identity: @@ -259,7 +253,7 @@ HRESULT STDMETHODCALLTYPE CompatDirectDraw::SetCooperativeLevel( } else if (isFullScreenDirectDraw(This) && g_fullScreenTagSurface) { - CompatDirectDrawSurface::s_origVtable.Release(g_fullScreenTagSurface); + g_fullScreenTagSurface.release(); } } return result; diff --git a/DDrawCompat/CompatDirectDrawSurface.cpp b/DDrawCompat/CompatDirectDrawSurface.cpp index 0061050..3513546 100644 --- a/DDrawCompat/CompatDirectDrawSurface.cpp +++ b/DDrawCompat/CompatDirectDrawSurface.cpp @@ -5,6 +5,7 @@ #include "CompatDirectDrawSurface.h" #include "CompatGdi.h" #include "CompatPrimarySurface.h" +#include "CompatPtr.h" #include "DDrawProcs.h" #include "DDrawRepository.h" #include "IReleaseNotifier.h" @@ -12,11 +13,12 @@ namespace { - bool mirrorBlt(IDirectDrawSurface7& dst, IDirectDrawSurface7& src, RECT srcRect, DWORD mirrorFx); + bool mirrorBlt(CompatRef dst, CompatRef src, + RECT srcRect, DWORD mirrorFx); bool g_lockingPrimary = false; - void fixSurfacePtr(IDirectDrawSurface7& surface, const DDSURFACEDESC2& desc) + void fixSurfacePtr(CompatRef surface, const DDSURFACEDESC2& desc) { if ((desc.dwFlags & DDSD_CAPS) && (desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) || 0 == desc.dwWidth || 0 == desc.dwHeight) @@ -34,48 +36,44 @@ namespace } RECT r = { 0, 0, 1, 1 }; - CompatDirectDrawSurface::s_origVtable.Blt( - &surface, &r, tempSurface.surface, &r, DDBLT_WAIT, nullptr); + surface->Blt(&surface, &r, tempSurface.surface, &r, DDBLT_WAIT, nullptr); } - HRESULT WINAPI enumSurfacesCallback( + HRESULT WINAPI fixSurfacePtrEnumCallback( LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext) { auto& visitedSurfaces = *static_cast*>(lpContext); - if (visitedSurfaces.find(lpDDSurface) == visitedSurfaces.end()) + CompatPtr surface(lpDDSurface); + if (visitedSurfaces.find(surface) == visitedSurfaces.end()) { - visitedSurfaces.insert(lpDDSurface); - fixSurfacePtr(*lpDDSurface, *lpDDSurfaceDesc); - CompatDirectDrawSurface::s_origVtable.EnumAttachedSurfaces( - lpDDSurface, lpContext, &enumSurfacesCallback); + visitedSurfaces.insert(surface); + fixSurfacePtr(*surface, *lpDDSurfaceDesc); + surface->EnumAttachedSurfaces(surface, lpContext, &fixSurfacePtrEnumCallback); } - CompatDirectDrawSurface::s_origVtable.Release(lpDDSurface); return DDENUMRET_OK; } - void fixSurfacePtrs(IDirectDrawSurface7& surface) + void fixSurfacePtrs(CompatRef surface) { DDSURFACEDESC2 desc = {}; desc.dwSize = sizeof(desc); - CompatDirectDrawSurface::s_origVtable.GetSurfaceDesc(&surface, &desc); - + surface->GetSurfaceDesc(&surface, &desc); + fixSurfacePtr(surface, desc); std::set visitedSurfaces{ &surface }; - CompatDirectDrawSurface::s_origVtable.EnumAttachedSurfaces( - &surface, &visitedSurfaces, &enumSurfacesCallback); + surface->EnumAttachedSurfaces(&surface, &visitedSurfaces, &fixSurfacePtrEnumCallback); } - IDirectDrawSurface7* getMirroredSurface(IDirectDrawSurface7& surface, RECT* srcRect, DWORD mirrorFx) + CompatWeakPtr getMirroredSurface( + CompatRef surface, RECT* srcRect, DWORD mirrorFx) { - auto& origVtable = CompatDirectDrawSurface::s_origVtable; - DDSURFACEDESC2 desc = {}; desc.dwSize = sizeof(desc); - HRESULT result = origVtable.GetSurfaceDesc(&surface, &desc); + HRESULT result = surface->GetSurfaceDesc(&surface, &desc); if (FAILED(result)) { LOG_ONCE("Failed to get surface description for mirroring: " << result); @@ -112,34 +110,11 @@ namespace return nullptr; } - origVtable.AddRef(mirroredSurface.surface); return mirroredSurface.surface; } - template - TSurface* getMirroredSurface(TSurface& surface, RECT* rect, DWORD mirrorFx) - { - auto& origVtable = CompatDirectDrawSurface::s_origVtable; - - IDirectDrawSurface7* surface7 = nullptr; - origVtable.QueryInterface(&surface, IID_IDirectDrawSurface7, reinterpret_cast(&surface7)); - IDirectDrawSurface7* mirroredSurface7 = getMirroredSurface(*surface7, rect, mirrorFx); - surface7->lpVtbl->Release(surface7); - - if (!mirroredSurface7) - { - return nullptr; - } - - auto& origVtable7 = CompatDirectDrawSurface::s_origVtable; - TSurface* mirroredSurface = nullptr; - origVtable7.QueryInterface(mirroredSurface7, - CompatDirectDrawSurface::s_iid, reinterpret_cast(&mirroredSurface)); - origVtable7.Release(mirroredSurface7); - return mirroredSurface; - } - - bool mirrorBlt(IDirectDrawSurface7& dst, IDirectDrawSurface7& src, RECT srcRect, DWORD mirrorFx) + bool mirrorBlt(CompatRef dst, CompatRef src, + RECT srcRect, DWORD mirrorFx) { if (DDBLTFX_MIRRORLEFTRIGHT == mirrorFx) { @@ -147,8 +122,7 @@ namespace srcRect.left = srcRect.right - 1; for (LONG x = 0; x < width; ++x) { - HRESULT result = CompatDirectDrawSurface::s_origVtable.BltFast( - &dst, x, 0, &src, &srcRect, DDBLTFAST_WAIT); + HRESULT result = dst->BltFast(&dst, x, 0, &src, &srcRect, DDBLTFAST_WAIT); if (FAILED(result)) { LOG_ONCE("Failed BltFast for mirroring: " << result); @@ -164,8 +138,7 @@ namespace srcRect.top = srcRect.bottom - 1; for (LONG y = 0; y < height; ++y) { - HRESULT result = CompatDirectDrawSurface::s_origVtable.BltFast( - &dst, 0, y, &src, &srcRect, DDBLTFAST_WAIT); + HRESULT result = dst->BltFast(&dst, 0, y, &src, &srcRect, DDBLTFAST_WAIT); if (FAILED(result)) { LOG_ONCE("Failed BltFast for mirroring: " << result); @@ -243,12 +216,10 @@ HRESULT CompatDirectDrawSurface::createCompatPrimarySurface( } template -void CompatDirectDrawSurface::fixSurfacePtrs(TSurface& surface) +void CompatDirectDrawSurface::fixSurfacePtrs(CompatRef surface) { - IDirectDrawSurface7* surface7 = nullptr; - surface.lpVtbl->QueryInterface(&surface, IID_IDirectDrawSurface7, reinterpret_cast(&surface7)); + CompatPtr surface7(Compat::queryInterface(&surface)); ::fixSurfacePtrs(*surface7); - surface7->lpVtbl->Release(surface7); } template @@ -268,12 +239,15 @@ HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::Blt( } HRESULT result = DD_OK; - TSurface* mirroredSrcSurface = nullptr; + CompatPtr mirroredSrcSurface; if (lpDDSrcSurface && (dwFlags & DDBLT_DDFX) && lpDDBltFx && (lpDDBltFx->dwDDFX & (DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN))) { - mirroredSrcSurface = getMirroredSurface(*lpDDSrcSurface, lpSrcRect, lpDDBltFx->dwDDFX); + CompatPtr srcSurface( + Compat::queryInterface(lpDDSrcSurface)); + mirroredSrcSurface.reset(Compat::queryInterface( + getMirroredSurface(*srcSurface, lpSrcRect, lpDDBltFx->dwDDFX).get())); if (!mirroredSrcSurface) { LOG_ONCE("Failed to emulate a mirrored Blt"); @@ -305,8 +279,6 @@ HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::Blt( { result = s_origVtable.Blt(This, lpDestRect, mirroredSrcSurface, nullptr, flags, &fx); } - - s_origVtable.Release(mirroredSrcSurface); } else { @@ -461,8 +433,8 @@ HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::QueryInterface( { if (riid == IID_IDirectDrawGammaControl && CompatPrimarySurface::isPrimary(This)) { - return RealPrimarySurface::getSurface()->lpVtbl->QueryInterface( - RealPrimarySurface::getSurface(), riid, obp); + auto realPrimary(RealPrimarySurface::getSurface()); + return realPrimary->QueryInterface(realPrimary, riid, obp); } return s_origVtable.QueryInterface(This, riid, obp); } diff --git a/DDrawCompat/CompatDirectDrawSurface.h b/DDrawCompat/CompatDirectDrawSurface.h index 3e30372..d59ed91 100644 --- a/DDrawCompat/CompatDirectDrawSurface.h +++ b/DDrawCompat/CompatDirectDrawSurface.h @@ -2,6 +2,7 @@ #include +#include "CompatRef.h" #include "CompatVtable.h" #include "DDrawTypes.h" #include "DirectDrawSurfaceVtblVisitor.h" @@ -22,7 +23,7 @@ public: TSurfaceDesc compatDesc, TSurface*& compatSurface); - static void fixSurfacePtrs(TSurface& surface); + static void fixSurfacePtrs(CompatRef surface); static HRESULT STDMETHODCALLTYPE Blt( TSurface* This, diff --git a/DDrawCompat/CompatGdi.cpp b/DDrawCompat/CompatGdi.cpp index fbd599e..44a95e9 100644 --- a/DDrawCompat/CompatGdi.cpp +++ b/DDrawCompat/CompatGdi.cpp @@ -1,7 +1,6 @@ #include #include "CompatDirectDrawPalette.h" -#include "CompatDirectDrawSurface.h" #include "CompatGdi.h" #include "CompatGdiCaret.h" #include "CompatGdiDcCache.h" diff --git a/DDrawCompat/CompatGdiDcCache.cpp b/DDrawCompat/CompatGdiDcCache.cpp index 953eb6c..9b7a60b 100644 --- a/DDrawCompat/CompatGdiDcCache.cpp +++ b/DDrawCompat/CompatGdiDcCache.cpp @@ -3,9 +3,9 @@ #include "CompatDirectDraw.h" #include "CompatDirectDrawPalette.h" -#include "CompatDirectDrawSurface.h" #include "CompatGdiDcCache.h" #include "CompatPrimarySurface.h" +#include "CompatPtr.h" #include "Config.h" #include "DDrawLog.h" #include "DDrawProcs.h" @@ -27,37 +27,36 @@ namespace void* g_surfaceMemory = nullptr; LONG g_pitch = 0; - IDirectDrawSurface7* createGdiSurface(); + CompatPtr createGdiSurface(); CachedDc createCachedDc() { CachedDc cachedDc = {}; - IDirectDrawSurface7* surface = createGdiSurface(); + CompatPtr surface(createGdiSurface()); if (!surface) { return cachedDc; } HDC dc = nullptr; - HRESULT result = surface->lpVtbl->GetDC(surface, &dc); + HRESULT result = surface->GetDC(surface, &dc); if (FAILED(result)) { LOG_ONCE("Failed to create a GDI DC: " << result); - surface->lpVtbl->Release(surface); return cachedDc; } // Release DD critical section acquired by IDirectDrawSurface7::GetDC to avoid deadlocks Compat::origProcs.ReleaseDDThreadLock(); - cachedDc.surface = surface; + cachedDc.surface = surface.detach(); cachedDc.dc = dc; cachedDc.cacheId = g_cacheId; return cachedDc; } - IDirectDrawSurface7* createGdiSurface() + CompatPtr createGdiSurface() { DDSURFACEDESC2 desc = {}; desc.dwSize = sizeof(desc); @@ -69,9 +68,9 @@ namespace desc.lPitch = g_pitch; desc.lpSurface = g_surfaceMemory; - IDirectDrawSurface7* surface = nullptr; + CompatPtr surface; HRESULT result = CompatDirectDraw::s_origVtable.CreateSurface( - g_directDraw, &desc, &surface, nullptr); + g_directDraw, &desc, &surface.getRef(), nullptr); if (FAILED(result)) { LOG_ONCE("Failed to create a GDI surface: " << result); @@ -80,7 +79,7 @@ namespace if (CompatPrimarySurface::pixelFormat.dwRGBBitCount <= 8) { - CompatDirectDrawSurface::s_origVtable.SetPalette(surface, g_palette); + surface->SetPalette(surface, g_palette); } return surface; @@ -115,14 +114,13 @@ namespace // Reacquire DD critical section that was temporarily released after IDirectDrawSurface7::GetDC Compat::origProcs.AcquireDDThreadLock(); - HRESULT result = CompatDirectDrawSurface::s_origVtable.ReleaseDC( - cachedDc.surface, cachedDc.dc); + HRESULT result = cachedDc.surface->ReleaseDC(cachedDc.surface, cachedDc.dc); if (FAILED(result)) { LOG_ONCE("Failed to release a cached DC: " << result); } - CompatDirectDrawSurface::s_origVtable.Release(cachedDc.surface); + cachedDc.surface.release(); } } diff --git a/DDrawCompat/CompatGdiDcCache.h b/DDrawCompat/CompatGdiDcCache.h index 1450936..3069f4c 100644 --- a/DDrawCompat/CompatGdiDcCache.h +++ b/DDrawCompat/CompatGdiDcCache.h @@ -6,11 +6,13 @@ #include #include +#include "CompatWeakPtr.h" + namespace CompatGdiDcCache { struct CachedDc { - IDirectDrawSurface7* surface; + CompatWeakPtr surface; HDC dc; DWORD cacheId; }; diff --git a/DDrawCompat/CompatPaletteConverter.cpp b/DDrawCompat/CompatPaletteConverter.cpp index f5b739e..42b1eaa 100644 --- a/DDrawCompat/CompatPaletteConverter.cpp +++ b/DDrawCompat/CompatPaletteConverter.cpp @@ -3,9 +3,9 @@ #include "CompatDirectDraw.h" #include "CompatDirectDrawPalette.h" -#include "CompatDirectDrawSurface.h" #include "CompatPaletteConverter.h" #include "CompatPrimarySurface.h" +#include "CompatPtr.h" #include "DDrawRepository.h" #include "DDrawTypes.h" #include "Hook.h" @@ -16,7 +16,7 @@ namespace { HDC g_dc = nullptr; HGDIOBJ g_oldBitmap = nullptr; - IDirectDrawSurface7* g_surface = nullptr; + CompatWeakPtr g_surface; void convertPaletteEntriesToRgbQuad(RGBQUAD* entries, DWORD count) { @@ -27,7 +27,7 @@ namespace } } - HBITMAP createDibSection(void*& bits) + HBITMAP createDibSection(const DDSURFACEDESC2& primaryDesc, void*& bits) { struct PalettizedBitmapInfo { @@ -37,8 +37,8 @@ namespace PalettizedBitmapInfo bmi = {}; bmi.header.biSize = sizeof(bmi.header); - bmi.header.biWidth = RealPrimarySurface::s_surfaceDesc.dwWidth; - bmi.header.biHeight = -static_cast(RealPrimarySurface::s_surfaceDesc.dwHeight); + bmi.header.biWidth = primaryDesc.dwWidth; + bmi.header.biHeight = -static_cast(primaryDesc.dwHeight); bmi.header.biPlanes = 1; bmi.header.biBitCount = 8; bmi.header.biCompression = BI_RGB; @@ -48,7 +48,7 @@ namespace DIB_RGB_COLORS, &bits, nullptr, 0); } - IDirectDrawSurface7* createSurface(void* bits) + CompatPtr createSurface(const DDSURFACEDESC2& primaryDesc, void* bits) { IDirectDraw7* dd = DDrawRepository::getDirectDraw(); if (!dd) @@ -60,38 +60,38 @@ namespace desc.dwSize = sizeof(desc); desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH | DDSD_LPSURFACE; - desc.dwWidth = RealPrimarySurface::s_surfaceDesc.dwWidth; - desc.dwHeight = RealPrimarySurface::s_surfaceDesc.dwHeight; + desc.dwWidth = primaryDesc.dwWidth; + desc.dwHeight = primaryDesc.dwHeight; desc.ddpfPixelFormat = CompatPrimarySurface::displayMode.pixelFormat; desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - desc.lPitch = (RealPrimarySurface::s_surfaceDesc.dwWidth + 3) & ~3; + desc.lPitch = (primaryDesc.dwWidth + 3) & ~3; desc.lpSurface = bits; - IDirectDrawSurface7* surface = nullptr; - CompatDirectDraw::s_origVtable.CreateSurface(dd, &desc, &surface, nullptr); + CompatPtr surface; + CompatDirectDraw::s_origVtable.CreateSurface(dd, &desc, &surface.getRef(), nullptr); return surface; } } namespace CompatPaletteConverter { - bool create() + bool create(const DDSURFACEDESC2& primaryDesc) { if (CompatPrimarySurface::displayMode.pixelFormat.dwRGBBitCount > 8 && - RealPrimarySurface::s_surfaceDesc.ddpfPixelFormat.dwRGBBitCount > 8) + primaryDesc.ddpfPixelFormat.dwRGBBitCount > 8) { return true; } void* bits = nullptr; - HBITMAP dib = createDibSection(bits); + HBITMAP dib = createDibSection(primaryDesc, bits); if (!dib) { Compat::Log() << "Failed to create the palette converter DIB section"; return false; } - IDirectDrawSurface7* surface = createSurface(bits); + CompatPtr surface(createSurface(primaryDesc, bits)); if (!surface) { Compat::Log() << "Failed to create the palette converter surface"; @@ -103,14 +103,13 @@ namespace CompatPaletteConverter if (!dc) { Compat::Log() << "Failed to create the palette converter DC"; - CompatDirectDrawSurface::s_origVtable.Release(surface); DeleteObject(dib); return false; } g_oldBitmap = SelectObject(dc, dib); g_dc = dc; - g_surface = surface; + g_surface = surface.detach(); return true; } @@ -119,7 +118,7 @@ namespace CompatPaletteConverter return g_dc; } - IDirectDrawSurface7* getSurface() + CompatWeakPtr getSurface() { return g_surface; } @@ -131,8 +130,7 @@ namespace CompatPaletteConverter return; } - CompatDirectDrawSurface::s_origVtable.Release(g_surface); - g_surface = nullptr; + g_surface.release(); DeleteObject(SelectObject(g_dc, g_oldBitmap)); DeleteDC(g_dc); @@ -143,8 +141,7 @@ namespace CompatPaletteConverter { if (g_surface) { - HRESULT result = CompatDirectDrawSurface::s_origVtable.SetClipper( - g_surface, clipper); + HRESULT result = g_surface->SetClipper(g_surface, clipper); if (FAILED(result)) { LOG_ONCE("Failed to set a clipper on the palette converter surface: " << result); diff --git a/DDrawCompat/CompatPaletteConverter.h b/DDrawCompat/CompatPaletteConverter.h index d1236dd..765efb1 100644 --- a/DDrawCompat/CompatPaletteConverter.h +++ b/DDrawCompat/CompatPaletteConverter.h @@ -4,11 +4,13 @@ #include +#include "CompatWeakPtr.h" + namespace CompatPaletteConverter { - bool create(); + bool create(const DDSURFACEDESC2& primaryDesc); HDC getDc(); - IDirectDrawSurface7* getSurface(); + CompatWeakPtr getSurface(); void release(); void setClipper(IDirectDrawClipper* clipper); void updatePalette(DWORD startingEntry, DWORD count); diff --git a/DDrawCompat/DDrawRepository.cpp b/DDrawCompat/DDrawRepository.cpp index 01434c6..354cda1 100644 --- a/DDrawCompat/DDrawRepository.cpp +++ b/DDrawCompat/DDrawRepository.cpp @@ -2,7 +2,7 @@ #include #include "CompatDirectDraw.h" -#include "CompatDirectDrawSurface.h" +#include "CompatPtr.h" #include "DDrawLog.h" #include "DDrawProcs.h" #include "DDrawRepository.h" @@ -63,7 +63,7 @@ namespace surface.desc.ddsCaps.dwCaps = caps; CompatDirectDraw::s_origVtable.CreateSurface( - dd, &surface.desc, &surface.surface, nullptr); + dd, &surface.desc, &surface.surface.getRef(), nullptr); return surface; } @@ -76,7 +76,7 @@ namespace if (it->desc.dwWidth <= width && it->desc.dwHeight <= height && 0 == memcmp(&it->desc.ddpfPixelFormat, &pf, sizeof(pf))) { - CompatDirectDrawSurface::s_origVtable.Release(it->surface); + it->surface.release(); it = cachedSurfaces.erase(it); } else @@ -89,17 +89,16 @@ namespace std::vector::iterator findSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf, std::vector& cachedSurfaces) { - auto& origVtable = CompatDirectDrawSurface::s_origVtable; - auto it = cachedSurfaces.begin(); while (it != cachedSurfaces.end()) { if (it->desc.dwWidth >= width && it->desc.dwHeight >= height && 0 == memcmp(&it->desc.ddpfPixelFormat, &pf, sizeof(pf))) { - if (FAILED(origVtable.IsLost(it->surface)) && FAILED(origVtable.Restore(it->surface))) + if (FAILED(it->surface->IsLost(it->surface)) && + FAILED(it->surface->Restore(it->surface))) { - origVtable.Release(it->surface); + it->surface.release(); it = cachedSurfaces.erase(it); continue; } diff --git a/DDrawCompat/DDrawRepository.h b/DDrawCompat/DDrawRepository.h index fb03362..9ffd451 100644 --- a/DDrawCompat/DDrawRepository.h +++ b/DDrawCompat/DDrawRepository.h @@ -4,12 +4,14 @@ #include +#include "CompatWeakPtr.h" + namespace DDrawRepository { struct Surface { DDSURFACEDESC2 desc; - IDirectDrawSurface7* surface; + CompatWeakPtr surface; }; class ScopedSurface : public Surface diff --git a/DDrawCompat/DllMain.cpp b/DDrawCompat/DllMain.cpp index f8c32f2..0fc5cc3 100644 --- a/DDrawCompat/DllMain.cpp +++ b/DDrawCompat/DllMain.cpp @@ -11,6 +11,7 @@ #include "CompatDirectDrawPalette.h" #include "CompatGdi.h" #include "CompatRegistry.h" +#include "CompatPtr.h" #include "CompatVtable.h" #include "DDrawProcs.h" #include "DDrawRepository.h" @@ -35,6 +36,12 @@ namespace } } + template + void hookVtable(const CompatPtr& intf) + { + CompatInterface::hookVtable(*intf); + } + void hookDirectDraw(IDirectDraw7& dd) { IUnknown& ddUnk = reinterpret_cast(dd); @@ -53,17 +60,17 @@ namespace desc.dwHeight = 1; desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - IDirectDrawSurface7* surface = nullptr; - HRESULT result = CompatDirectDraw::s_origVtable.CreateSurface(&dd, &desc, &surface, nullptr); + CompatPtr surface; + HRESULT result = CompatDirectDraw::s_origVtable.CreateSurface( + &dd, &desc, &surface.getRef(), nullptr); if (SUCCEEDED(result)) { - IUnknown& surfaceUnk = reinterpret_cast(*surface); - hookVtable>(IID_IDirectDrawSurface, surfaceUnk); - hookVtable>(IID_IDirectDrawSurface2, surfaceUnk); - hookVtable>(IID_IDirectDrawSurface3, surfaceUnk); - hookVtable>(IID_IDirectDrawSurface4, surfaceUnk); - hookVtable>(IID_IDirectDrawSurface7, surfaceUnk); - surface->lpVtbl->Release(surface); + CompatDirectDrawSurface::s_origVtable = *surface.get()->lpVtbl; + hookVtable>(surface); + hookVtable>(surface); + hookVtable>(surface); + hookVtable>(surface); + hookVtable>(surface); } else { diff --git a/DDrawCompat/RealPrimarySurface.cpp b/DDrawCompat/RealPrimarySurface.cpp index 66d0a97..f7150a1 100644 --- a/DDrawCompat/RealPrimarySurface.cpp +++ b/DDrawCompat/RealPrimarySurface.cpp @@ -6,6 +6,8 @@ #include "CompatGdi.h" #include "CompatPaletteConverter.h" #include "CompatPrimarySurface.h" +#include "CompatPtr.h" +#include "CompatRef.h" #include "Config.h" #include "DDrawScopedThreadLock.h" #include "DDrawProcs.h" @@ -19,9 +21,11 @@ namespace { void onRelease(); void updateNow(long long qpcNow); + DWORD WINAPI updateThreadProc(LPVOID lpParameter); - IDirectDrawSurface7* g_frontBuffer = nullptr; - IDirectDrawSurface7* g_backBuffer = nullptr; + CompatWeakPtr g_frontBuffer; + CompatWeakPtr g_backBuffer; + DDSURFACEDESC2 g_surfaceDesc = {}; IReleaseNotifier g_releaseNotifier(onRelease); bool g_stopUpdateThread = false; @@ -34,7 +38,7 @@ namespace std::atomic g_isFullScreen(false); - bool compatBlt(IDirectDrawSurface7* dest) + bool compatBlt(CompatRef dest) { Compat::LogEnter("RealPrimarySurface::compatBlt", dest); @@ -44,12 +48,11 @@ namespace } bool result = false; - const auto& origVtable = CompatDirectDrawSurface::s_origVtable; if (!RealPrimarySurface::isFullScreen()) { IDirectDrawClipper* clipper = nullptr; - if (FAILED(origVtable.GetClipper(g_frontBuffer, &clipper))) + if (FAILED(g_frontBuffer->GetClipper(g_frontBuffer, &clipper))) { return false; } @@ -59,27 +62,27 @@ namespace auto primary(CompatPrimarySurface::getPrimary()); if (CompatPrimarySurface::pixelFormat.dwRGBBitCount <= 8) { - origVtable.Blt(CompatPaletteConverter::getSurface(), &g_updateRect, + auto paletteConverter(CompatPaletteConverter::getSurface()); + paletteConverter->Blt(paletteConverter, &g_updateRect, primary, &g_updateRect, DDBLT_WAIT, nullptr); HDC destDc = nullptr; - origVtable.GetDC(dest, &destDc); + dest->GetDC(&dest, &destDc); result = TRUE == CALL_ORIG_FUNC(BitBlt)(destDc, g_updateRect.left, g_updateRect.top, g_updateRect.right - g_updateRect.left, g_updateRect.bottom - g_updateRect.top, CompatPaletteConverter::getDc(), g_updateRect.left, g_updateRect.top, SRCCOPY); - origVtable.ReleaseDC(dest, destDc); + dest->ReleaseDC(&dest, destDc); - if (dest == g_frontBuffer) + if (&dest == g_frontBuffer) { // Force the screen to be updated. It won't refresh from BitBlt alone. RECT r = { 0, 0, 1, 1 }; - CompatDirectDrawSurface::s_origVtable.BltFast( - g_frontBuffer, 0, 0, g_frontBuffer, &r, DDBLTFAST_WAIT); + g_frontBuffer->BltFast(g_frontBuffer, 0, 0, g_frontBuffer, &r, DDBLTFAST_WAIT); } } else { - result = SUCCEEDED(origVtable.Blt(dest, &g_updateRect, + result = SUCCEEDED(dest->Blt(&dest, &g_updateRect, primary, &g_updateRect, DDBLT_WAIT, nullptr)); } @@ -99,6 +102,53 @@ namespace return qpcNextUpdate + g_qpcMinUpdateInterval * (missedIntervals + 1); } + HRESULT init(CompatPtr surface) + { + DDSURFACEDESC2 desc = {}; + desc.dwSize = sizeof(desc); + surface->GetSurfaceDesc(surface, &desc); + + if (!CompatPaletteConverter::create(desc)) + { + return DDERR_GENERIC; + } + + CompatPtr backBuffer; + const bool isFlippable = 0 != (desc.ddsCaps.dwCaps & DDSCAPS_FLIP); + if (isFlippable) + { + DDSCAPS2 backBufferCaps = {}; + backBufferCaps.dwCaps = DDSCAPS_BACKBUFFER; + surface->GetAttachedSurface(surface, &backBufferCaps, &backBuffer.getRef()); + } + + g_qpcMinUpdateInterval = Time::g_qpcFrequency / Config::maxPrimaryUpdateRate; + g_qpcNextUpdate = Time::queryPerformanceCounter(); + + if (!g_updateEvent) + { + g_updateEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); + } + + if (!g_updateThread) + { + g_updateThread = CreateThread(nullptr, 0, &updateThreadProc, nullptr, 0, nullptr); + SetThreadPriority(g_updateThread, THREAD_PRIORITY_ABOVE_NORMAL); + } + + surface->SetPrivateData(surface, IID_IReleaseNotifier, + &g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER); + + timeBeginPeriod(1); + + g_frontBuffer = surface.detach(); + g_backBuffer = backBuffer.detach(); + g_surfaceDesc = desc; + g_isFullScreen = isFlippable; + + return DD_OK; + } + bool isNextUpdateSignaledAndReady(long long qpcNow) { return Time::qpcToMs(qpcNow - g_qpcNextUpdate) >= 0 && @@ -112,15 +162,11 @@ namespace ResetEvent(g_updateEvent); timeEndPeriod(1); g_frontBuffer = nullptr; - if (g_backBuffer) - { - CompatDirectDrawSurface::s_origVtable.Release(g_backBuffer); - g_backBuffer = nullptr; - } + g_backBuffer.release(); g_isFullScreen = false; CompatPaletteConverter::release(); - ZeroMemory(&RealPrimarySurface::s_surfaceDesc, sizeof(RealPrimarySurface::s_surfaceDesc)); + ZeroMemory(&g_surfaceDesc, sizeof(g_surfaceDesc)); Compat::LogLeave("RealPrimarySurface::onRelease"); } @@ -129,7 +175,7 @@ namespace { ResetEvent(g_updateEvent); - if (compatBlt(g_frontBuffer)) + if (compatBlt(*g_frontBuffer)) { long long qpcNextUpdate = getNextUpdateQpc(qpcNow); if (Time::qpcToMs(qpcNow - qpcNextUpdate) >= 0) @@ -170,8 +216,6 @@ namespace } } -DDSURFACEDESC2 RealPrimarySurface::s_surfaceDesc = {}; - template HRESULT RealPrimarySurface::create(DirectDraw& dd) { @@ -181,9 +225,9 @@ HRESULT RealPrimarySurface::create(DirectDraw& dd) desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; desc.dwBackBufferCount = 1; - typename Types::TCreatedSurface* surface = nullptr; + CompatPtr::TCreatedSurface> surface; HRESULT result = CompatDirectDraw::s_origVtable.CreateSurface( - &dd, &desc, &surface, nullptr); + &dd, &desc, &surface.getRef(), nullptr); bool isFlippable = true; if (DDERR_NOEXCLUSIVEMODE == result) @@ -193,7 +237,7 @@ HRESULT RealPrimarySurface::create(DirectDraw& dd) desc.dwBackBufferCount = 0; isFlippable = false; result = CompatDirectDraw::s_origVtable.CreateSurface( - &dd, &desc, &surface, nullptr); + &dd, &desc, &surface.getRef(), nullptr); } if (FAILED(result)) @@ -202,48 +246,7 @@ HRESULT RealPrimarySurface::create(DirectDraw& dd) return result; } - surface->lpVtbl->QueryInterface( - surface, IID_IDirectDrawSurface7, reinterpret_cast(&g_frontBuffer)); - surface->lpVtbl->Release(surface); - - s_surfaceDesc.dwSize = sizeof(s_surfaceDesc); - g_frontBuffer->lpVtbl->GetSurfaceDesc(g_frontBuffer, &s_surfaceDesc); - - if (!CompatPaletteConverter::create()) - { - g_frontBuffer->lpVtbl->Release(g_frontBuffer); - g_frontBuffer = nullptr; - return DDERR_GENERIC; - } - - if (isFlippable) - { - DDSCAPS2 backBufferCaps = {}; - backBufferCaps.dwCaps = DDSCAPS_BACKBUFFER; - g_frontBuffer->lpVtbl->GetAttachedSurface(g_frontBuffer, &backBufferCaps, &g_backBuffer); - } - - g_qpcMinUpdateInterval = Time::g_qpcFrequency / Config::maxPrimaryUpdateRate; - g_qpcNextUpdate = Time::queryPerformanceCounter(); - - if (!g_updateEvent) - { - g_updateEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); - } - - if (!g_updateThread) - { - g_updateThread = CreateThread(nullptr, 0, &updateThreadProc, nullptr, 0, nullptr); - SetThreadPriority(g_updateThread, THREAD_PRIORITY_ABOVE_NORMAL); - } - - g_frontBuffer->lpVtbl->SetPrivateData(g_frontBuffer, - IID_IReleaseNotifier, &g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER); - - g_isFullScreen = isFlippable; - timeBeginPeriod(1); - - return DD_OK; + return init(surface); } template HRESULT RealPrimarySurface::create(IDirectDraw&); @@ -267,7 +270,7 @@ void RealPrimarySurface::enableUpdates() HRESULT RealPrimarySurface::flip(DWORD flags) { - if (!g_backBuffer) + if (!g_isFullScreen) { return DDERR_NOTFLIPPABLE; } @@ -275,13 +278,13 @@ HRESULT RealPrimarySurface::flip(DWORD flags) ResetEvent(g_updateEvent); invalidate(nullptr); - compatBlt(g_backBuffer); + compatBlt(*g_backBuffer); if (flags & DDFLIP_DONOTWAIT) { flags ^= DDFLIP_DONOTWAIT; } - HRESULT result = g_frontBuffer->lpVtbl->Flip(g_frontBuffer, nullptr, flags | DDFLIP_WAIT); + HRESULT result = g_frontBuffer->Flip(g_frontBuffer, nullptr, flags | DDFLIP_WAIT); if (SUCCEEDED(result)) { g_qpcNextUpdate = getNextUpdateQpc( @@ -291,7 +294,7 @@ HRESULT RealPrimarySurface::flip(DWORD flags) return result; } -IDirectDrawSurface7* RealPrimarySurface::getSurface() +CompatWeakPtr RealPrimarySurface::getSurface() { return g_frontBuffer; } @@ -316,16 +319,12 @@ bool RealPrimarySurface::isFullScreen() bool RealPrimarySurface::isLost() { - return g_frontBuffer && - DDERR_SURFACELOST == CompatDirectDrawSurface::s_origVtable.IsLost(g_frontBuffer); + return g_frontBuffer && DDERR_SURFACELOST == g_frontBuffer->IsLost(g_frontBuffer); } void RealPrimarySurface::release() { - if (g_frontBuffer) - { - g_frontBuffer->lpVtbl->Release(g_frontBuffer); - } + g_frontBuffer.release(); } void RealPrimarySurface::removeUpdateThread() @@ -349,15 +348,14 @@ void RealPrimarySurface::removeUpdateThread() HRESULT RealPrimarySurface::restore() { - return g_frontBuffer->lpVtbl->Restore(g_frontBuffer); + return g_frontBuffer->Restore(g_frontBuffer); } void RealPrimarySurface::setClipper(LPDIRECTDRAWCLIPPER clipper) { CompatPaletteConverter::setClipper(clipper); - HRESULT result = CompatDirectDrawSurface::s_origVtable.SetClipper( - g_frontBuffer, clipper); + HRESULT result = g_frontBuffer->SetClipper(g_frontBuffer, clipper); if (FAILED(result)) { LOG_ONCE("Failed to set clipper on the real primary surface: " << result); @@ -366,10 +364,9 @@ void RealPrimarySurface::setClipper(LPDIRECTDRAWCLIPPER clipper) void RealPrimarySurface::setPalette() { - if (s_surfaceDesc.ddpfPixelFormat.dwRGBBitCount <= 8) + if (g_surfaceDesc.ddpfPixelFormat.dwRGBBitCount <= 8) { - CompatDirectDrawSurface::s_origVtable.SetPalette( - g_frontBuffer, CompatPrimarySurface::palette); + g_frontBuffer->SetPalette(g_frontBuffer, CompatPrimarySurface::palette); } updatePalette(0, 256); diff --git a/DDrawCompat/RealPrimarySurface.h b/DDrawCompat/RealPrimarySurface.h index ac2e18c..1703c84 100644 --- a/DDrawCompat/RealPrimarySurface.h +++ b/DDrawCompat/RealPrimarySurface.h @@ -4,6 +4,8 @@ #include +#include "CompatWeakPtr.h" + class RealPrimarySurface { public: @@ -13,7 +15,7 @@ public: static void disableUpdates(); static void enableUpdates(); static HRESULT flip(DWORD flags); - static IDirectDrawSurface7* getSurface(); + static CompatWeakPtr getSurface(); static void invalidate(const RECT* rect); static bool isFullScreen(); static bool isLost(); @@ -24,6 +26,4 @@ public: static void setPalette(); static void update(); static void updatePalette(DWORD startingEntry, DWORD count); - - static DDSURFACEDESC2 s_surfaceDesc; };