mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Preparation for splitting the DirectDrawSurface wrapper into layers
This commit is contained in:
parent
b8832a92be
commit
19cce6b9d6
@ -4,8 +4,8 @@
|
||||
#include "DDraw/ActivateAppHandler.h"
|
||||
#include "DDraw/CompatPrimarySurface.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/DirectDrawSurface.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
#include "Win32/FontSmoothing.h"
|
||||
|
||||
@ -41,7 +41,7 @@ namespace
|
||||
auto primary(DDraw::CompatPrimarySurface::getPrimary());
|
||||
if (primary && SUCCEEDED(primary->Restore(primary)))
|
||||
{
|
||||
DDraw::DirectDrawSurface<IDirectDrawSurface7>::fixSurfacePtrs(*primary);
|
||||
DDraw::SurfaceImpl<IDirectDrawSurface7>::fixSurfacePtrs(*primary);
|
||||
Gdi::invalidate(nullptr);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "DDraw/DirectDrawSurface.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/IReleaseNotifier.h"
|
||||
#include "DDraw/Surfaces/Surface.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -106,49 +108,23 @@ namespace DDraw
|
||||
TSurface** lplpDDSurface,
|
||||
IUnknown* pUnkOuter)
|
||||
{
|
||||
if (!This || !lpDDSurfaceDesc || !lplpDDSurface)
|
||||
{
|
||||
return s_origVtable.CreateSurface(This, lpDDSurfaceDesc, lplpDDSurface, pUnkOuter);
|
||||
}
|
||||
|
||||
HRESULT result = DD_OK;
|
||||
|
||||
const bool isPrimary = lpDDSurfaceDesc &&
|
||||
(lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE);
|
||||
const bool isPrimary = 0 != (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE);
|
||||
|
||||
if (isPrimary)
|
||||
{
|
||||
result = DirectDrawSurface<TSurface>::createCompatPrimarySurface<TDirectDraw>(
|
||||
result = SurfaceImpl<TSurface>::createCompatPrimarySurface<TDirectDraw>(
|
||||
*This, *lpDDSurfaceDesc, *lplpDDSurface);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lpDDSurfaceDesc &&
|
||||
(lpDDSurfaceDesc->dwFlags & DDSD_WIDTH) &&
|
||||
(lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT) &&
|
||||
!(lpDDSurfaceDesc->ddsCaps.dwCaps & (DDSCAPS_ALPHA | DDSCAPS_ZBUFFER)))
|
||||
{
|
||||
CompatPtr<IDirectDraw7> dd(Compat::queryInterface<IDirectDraw7>(This));
|
||||
auto dm = DisplayMode::getDisplayMode(*dd);
|
||||
|
||||
TSurfaceDesc desc = *lpDDSurfaceDesc;
|
||||
if (!(desc.dwFlags & DDSD_PIXELFORMAT))
|
||||
{
|
||||
desc.dwFlags |= DDSD_PIXELFORMAT;
|
||||
desc.ddpfPixelFormat = dm.ddpfPixelFormat;
|
||||
}
|
||||
if (!(desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_OVERLAY | DDSCAPS_TEXTURE |
|
||||
DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)))
|
||||
{
|
||||
desc.dwFlags |= DDSD_CAPS;
|
||||
desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
|
||||
}
|
||||
result = s_origVtable.CreateSurface(This, &desc, lplpDDSurface, pUnkOuter);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = s_origVtable.CreateSurface(This, lpDDSurfaceDesc, lplpDDSurface, pUnkOuter);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
DirectDrawSurface<TSurface>::fixSurfacePtrs(**lplpDDSurface);
|
||||
result = Surface::create<TDirectDraw>(*This, *lpDDSurfaceDesc, *lplpDDSurface);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1,535 +1,48 @@
|
||||
#include <set>
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "DDraw/CompatPrimarySurface.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/DirectDrawPalette.h"
|
||||
#include "DDraw/DirectDrawSurface.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/IReleaseNotifier.h"
|
||||
#include "DDraw/RealPrimarySurface.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
#include "DDraw/Surfaces/Surface.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool mirrorBlt(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
RECT srcRect, DWORD mirrorFx);
|
||||
|
||||
bool g_lockingPrimary = false;
|
||||
|
||||
void fixSurfacePtr(CompatRef<IDirectDrawSurface7> surface, const DDSURFACEDESC2& desc)
|
||||
template <typename CompatMethod, CompatMethod compatMethod,
|
||||
typename OrigMethod, OrigMethod origMethod,
|
||||
typename TSurface, typename... Params>
|
||||
HRESULT STDMETHODCALLTYPE callImpl(TSurface* This, Params... params)
|
||||
{
|
||||
if ((desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) || 0 == desc.dwWidth || 0 == desc.dwHeight)
|
||||
DDraw::SurfaceImpl<TSurface>* surfaceImpl =
|
||||
This ? DDraw::Surface::getImpl<TSurface>(*This) : nullptr;
|
||||
if (!surfaceImpl)
|
||||
{
|
||||
return;
|
||||
return (CompatVtableBase<TSurface>::s_origVtable.*origMethod)(This, params...);
|
||||
}
|
||||
|
||||
DDSURFACEDESC2 tempSurfaceDesc = desc;
|
||||
tempSurfaceDesc.dwWidth = 1;
|
||||
tempSurfaceDesc.dwHeight = 1;
|
||||
DDraw::Repository::ScopedSurface tempSurface(desc);
|
||||
if (!tempSurface.surface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RECT r = { 0, 0, 1, 1 };
|
||||
surface->Blt(&surface, &r, tempSurface.surface, &r, DDBLT_WAIT, nullptr);
|
||||
}
|
||||
|
||||
HRESULT WINAPI fixSurfacePtrEnumCallback(
|
||||
LPDIRECTDRAWSURFACE7 lpDDSurface,
|
||||
LPDDSURFACEDESC2 lpDDSurfaceDesc,
|
||||
LPVOID lpContext)
|
||||
{
|
||||
auto& visitedSurfaces = *static_cast<std::set<IDirectDrawSurface7*>*>(lpContext);
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> surface(lpDDSurface);
|
||||
if (visitedSurfaces.find(surface) == visitedSurfaces.end())
|
||||
{
|
||||
visitedSurfaces.insert(surface);
|
||||
fixSurfacePtr(*surface, *lpDDSurfaceDesc);
|
||||
surface->EnumAttachedSurfaces(surface, lpContext, &fixSurfacePtrEnumCallback);
|
||||
}
|
||||
|
||||
return DDENUMRET_OK;
|
||||
}
|
||||
|
||||
void fixSurfacePtrs(CompatRef<IDirectDrawSurface7> surface)
|
||||
{
|
||||
DDSURFACEDESC2 desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
surface->GetSurfaceDesc(&surface, &desc);
|
||||
|
||||
fixSurfacePtr(surface, desc);
|
||||
std::set<IDirectDrawSurface7*> visitedSurfaces{ &surface };
|
||||
surface->EnumAttachedSurfaces(&surface, &visitedSurfaces, &fixSurfacePtrEnumCallback);
|
||||
}
|
||||
|
||||
CompatWeakPtr<IDirectDrawSurface7> getMirroredSurface(
|
||||
CompatRef<IDirectDrawSurface7> surface, RECT* srcRect, DWORD mirrorFx)
|
||||
{
|
||||
DDSURFACEDESC2 desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
HRESULT result = surface->GetSurfaceDesc(&surface, &desc);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_ONCE("Failed to get surface description for mirroring: " << result);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (srcRect)
|
||||
{
|
||||
desc.dwWidth = srcRect->right - srcRect->left;
|
||||
desc.dwHeight = srcRect->bottom - srcRect->top;
|
||||
}
|
||||
|
||||
DDraw::Repository::ScopedSurface mirroredSurface(desc);
|
||||
if (!mirroredSurface.surface)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RECT rect = { 0, 0, static_cast<LONG>(desc.dwWidth), static_cast<LONG>(desc.dwHeight) };
|
||||
if ((mirrorFx & DDBLTFX_MIRRORLEFTRIGHT) && (mirrorFx & DDBLTFX_MIRRORUPDOWN))
|
||||
{
|
||||
DDraw::Repository::Surface tempMirroredSurface = DDraw::Repository::ScopedSurface(desc);
|
||||
if (!tempMirroredSurface.surface ||
|
||||
!mirrorBlt(*tempMirroredSurface.surface, surface, srcRect ? *srcRect : rect,
|
||||
DDBLTFX_MIRRORLEFTRIGHT) ||
|
||||
!mirrorBlt(*mirroredSurface.surface, *tempMirroredSurface.surface, rect,
|
||||
DDBLTFX_MIRRORUPDOWN))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (!mirrorBlt(*mirroredSurface.surface, surface, srcRect ? *srcRect : rect, mirrorFx))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mirroredSurface.surface;
|
||||
}
|
||||
|
||||
bool mirrorBlt(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
RECT srcRect, DWORD mirrorFx)
|
||||
{
|
||||
if (DDBLTFX_MIRRORLEFTRIGHT == mirrorFx)
|
||||
{
|
||||
LONG width = srcRect.right - srcRect.left;
|
||||
srcRect.left = srcRect.right - 1;
|
||||
for (LONG x = 0; x < width; ++x)
|
||||
{
|
||||
HRESULT result = dst->BltFast(&dst, x, 0, &src, &srcRect, DDBLTFAST_WAIT);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_ONCE("Failed BltFast for mirroring: " << result);
|
||||
return false;
|
||||
}
|
||||
--srcRect.left;
|
||||
--srcRect.right;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LONG height = srcRect.bottom - srcRect.top;
|
||||
srcRect.top = srcRect.bottom - 1;
|
||||
for (LONG y = 0; y < height; ++y)
|
||||
{
|
||||
HRESULT result = dst->BltFast(&dst, 0, y, &src, &srcRect, DDBLTFAST_WAIT);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_ONCE("Failed BltFast for mirroring: " << result);
|
||||
return false;
|
||||
}
|
||||
--srcRect.top;
|
||||
--srcRect.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return (surfaceImpl->*compatMethod)(This, params...);
|
||||
}
|
||||
}
|
||||
|
||||
#define SET_COMPAT_METHOD(method) \
|
||||
vtable.method = &callImpl<decltype(&SurfaceImpl<TSurface>::method), &SurfaceImpl<TSurface>::method, \
|
||||
decltype(&Vtable<TSurface>::method), &Vtable<TSurface>::method>
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
template <typename TSurface>
|
||||
void DirectDrawSurface<TSurface>::setCompatVtable(Vtable<TSurface>& vtable)
|
||||
{
|
||||
vtable.Blt = &Blt;
|
||||
vtable.BltFast = &BltFast;
|
||||
vtable.Flip = &Flip;
|
||||
vtable.GetCaps = &GetCaps;
|
||||
vtable.GetSurfaceDesc = &GetSurfaceDesc;
|
||||
vtable.IsLost = &IsLost;
|
||||
vtable.Lock = &Lock;
|
||||
vtable.QueryInterface = &QueryInterface;
|
||||
vtable.ReleaseDC = &ReleaseDC;
|
||||
vtable.Restore = &Restore;
|
||||
vtable.SetClipper = &SetClipper;
|
||||
vtable.SetPalette = &SetPalette;
|
||||
vtable.Unlock = &Unlock;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
template <typename TDirectDraw>
|
||||
HRESULT DirectDrawSurface<TSurface>::createCompatPrimarySurface(
|
||||
CompatRef<TDirectDraw> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
TSurface*& compatSurface)
|
||||
{
|
||||
HRESULT result = RealPrimarySurface::create(dd);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDraw7> dd7(Compat::queryInterface<IDirectDraw7>(&dd));
|
||||
const auto& dm = DisplayMode::getDisplayMode(*dd7);
|
||||
compatDesc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
|
||||
compatDesc.dwWidth = dm.dwWidth;
|
||||
compatDesc.dwHeight = dm.dwHeight;
|
||||
compatDesc.ddsCaps.dwCaps &= ~DDSCAPS_PRIMARYSURFACE;
|
||||
compatDesc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
|
||||
compatDesc.ddpfPixelFormat = dm.ddpfPixelFormat;
|
||||
|
||||
result = dd->CreateSurface(&dd, &compatDesc, &compatSurface, nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
Compat::Log() << "Failed to create the compat primary surface!";
|
||||
RealPrimarySurface::release();
|
||||
return result;
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> primary(Compat::queryInterface<IDirectDrawSurface7>(compatSurface));
|
||||
CompatPrimarySurface::setPrimary(*primary);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
void DirectDrawSurface<TSurface>::fixSurfacePtrs(CompatRef<TSurface> surface)
|
||||
{
|
||||
CompatPtr<IDirectDrawSurface7> surface7(Compat::queryInterface<IDirectDrawSurface7>(&surface));
|
||||
::fixSurfacePtrs(*surface7);
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::Blt(
|
||||
TSurface* This,
|
||||
LPRECT lpDestRect,
|
||||
TSurface* lpDDSrcSurface,
|
||||
LPRECT lpSrcRect,
|
||||
DWORD dwFlags,
|
||||
LPDDBLTFX lpDDBltFx)
|
||||
{
|
||||
const bool isPrimaryDest = CompatPrimarySurface::isPrimary(This);
|
||||
if ((isPrimaryDest || CompatPrimarySurface::isPrimary(lpDDSrcSurface)) &&
|
||||
RealPrimarySurface::isLost())
|
||||
{
|
||||
return DDERR_SURFACELOST;
|
||||
}
|
||||
|
||||
HRESULT result = DD_OK;
|
||||
CompatPtr<TSurface> mirroredSrcSurface;
|
||||
|
||||
if (lpDDSrcSurface && (dwFlags & DDBLT_DDFX) && lpDDBltFx &&
|
||||
(lpDDBltFx->dwDDFX & (DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN)))
|
||||
{
|
||||
CompatPtr<IDirectDrawSurface7> srcSurface(
|
||||
Compat::queryInterface<IDirectDrawSurface7>(lpDDSrcSurface));
|
||||
mirroredSrcSurface.reset(Compat::queryInterface<TSurface>(
|
||||
getMirroredSurface(*srcSurface, lpSrcRect, lpDDBltFx->dwDDFX).get()));
|
||||
if (!mirroredSrcSurface)
|
||||
{
|
||||
LOG_ONCE("Failed to emulate a mirrored Blt");
|
||||
}
|
||||
}
|
||||
|
||||
if (mirroredSrcSurface)
|
||||
{
|
||||
DWORD flags = dwFlags;
|
||||
DDBLTFX fx = *lpDDBltFx;
|
||||
fx.dwDDFX &= ~(DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN);
|
||||
if (0 == fx.dwDDFX)
|
||||
{
|
||||
flags ^= DDBLT_DDFX;
|
||||
}
|
||||
if (flags & DDBLT_KEYSRC)
|
||||
{
|
||||
DDCOLORKEY srcColorKey = {};
|
||||
s_origVtable.GetColorKey(lpDDSrcSurface, DDCKEY_SRCBLT, &srcColorKey);
|
||||
s_origVtable.SetColorKey(mirroredSrcSurface, DDCKEY_SRCBLT, &srcColorKey);
|
||||
}
|
||||
|
||||
if (lpSrcRect)
|
||||
{
|
||||
RECT srcRect = {
|
||||
0, 0, lpSrcRect->right - lpSrcRect->left, lpSrcRect->bottom - lpSrcRect->top };
|
||||
result = s_origVtable.Blt(This, lpDestRect, mirroredSrcSurface, &srcRect, flags, &fx);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = s_origVtable.Blt(This, lpDestRect, mirroredSrcSurface, nullptr, flags, &fx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = s_origVtable.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
|
||||
}
|
||||
|
||||
if (isPrimaryDest && SUCCEEDED(result))
|
||||
{
|
||||
RealPrimarySurface::invalidate(lpDestRect);
|
||||
RealPrimarySurface::update();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::BltFast(
|
||||
TSurface* This,
|
||||
DWORD dwX,
|
||||
DWORD dwY,
|
||||
TSurface* lpDDSrcSurface,
|
||||
LPRECT lpSrcRect,
|
||||
DWORD dwTrans)
|
||||
{
|
||||
const bool isPrimaryDest = CompatPrimarySurface::isPrimary(This);
|
||||
if ((isPrimaryDest || CompatPrimarySurface::isPrimary(lpDDSrcSurface)) &&
|
||||
RealPrimarySurface::isLost())
|
||||
{
|
||||
return DDERR_SURFACELOST;
|
||||
}
|
||||
|
||||
HRESULT result = s_origVtable.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
|
||||
if (isPrimaryDest && SUCCEEDED(result))
|
||||
{
|
||||
const LONG x = dwX;
|
||||
const LONG y = dwY;
|
||||
RECT destRect = { x, y, x, y };
|
||||
if (lpSrcRect)
|
||||
{
|
||||
destRect.right += lpSrcRect->right - lpSrcRect->left;
|
||||
destRect.bottom += lpSrcRect->bottom - lpSrcRect->top;
|
||||
}
|
||||
else
|
||||
{
|
||||
TSurfaceDesc desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
s_origVtable.GetSurfaceDesc(lpDDSrcSurface, &desc);
|
||||
destRect.right += desc.dwWidth;
|
||||
destRect.bottom += desc.dwHeight;
|
||||
}
|
||||
RealPrimarySurface::invalidate(&destRect);
|
||||
RealPrimarySurface::update();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::Flip(
|
||||
TSurface* This,
|
||||
TSurface* lpDDSurfaceTargetOverride,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
HRESULT result = s_origVtable.Flip(This, lpDDSurfaceTargetOverride, dwFlags);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
result = RealPrimarySurface::flip(dwFlags);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::GetCaps(
|
||||
TSurface* This,
|
||||
TDdsCaps* lpDDSCaps)
|
||||
{
|
||||
HRESULT result = s_origVtable.GetCaps(This, lpDDSCaps);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
restorePrimaryCaps(*lpDDSCaps);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::GetSurfaceDesc(
|
||||
TSurface* This,
|
||||
TSurfaceDesc* lpDDSurfaceDesc)
|
||||
{
|
||||
HRESULT result = s_origVtable.GetSurfaceDesc(This, lpDDSurfaceDesc);
|
||||
if (SUCCEEDED(result) && !g_lockingPrimary && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::IsLost(TSurface* This)
|
||||
{
|
||||
HRESULT result = s_origVtable.IsLost(This);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
result = RealPrimarySurface::isLost() ? DDERR_SURFACELOST : DD_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::Lock(
|
||||
TSurface* This,
|
||||
LPRECT lpDestRect,
|
||||
TSurfaceDesc* lpDDSurfaceDesc,
|
||||
DWORD dwFlags,
|
||||
HANDLE hEvent)
|
||||
{
|
||||
if (CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
if (RealPrimarySurface::isLost())
|
||||
{
|
||||
return DDERR_SURFACELOST;
|
||||
}
|
||||
g_lockingPrimary = true;
|
||||
}
|
||||
|
||||
HRESULT result = s_origVtable.Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
|
||||
if (SUCCEEDED(result) && g_lockingPrimary && lpDDSurfaceDesc)
|
||||
{
|
||||
RealPrimarySurface::invalidate(lpDestRect);
|
||||
restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps);
|
||||
}
|
||||
else if (DDERR_SURFACELOST == result)
|
||||
{
|
||||
TSurfaceDesc desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
if (SUCCEEDED(s_origVtable.GetSurfaceDesc(This, &desc)) && !(desc.dwFlags & DDSD_HEIGHT))
|
||||
{
|
||||
// Fixes missing handling for lost vertex buffers in Messiah
|
||||
s_origVtable.Restore(This);
|
||||
// Still, pass back DDERR_SURFACELOST to the application in case it handles it
|
||||
}
|
||||
}
|
||||
|
||||
g_lockingPrimary = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::QueryInterface(
|
||||
TSurface* This,
|
||||
REFIID riid,
|
||||
LPVOID* obp)
|
||||
{
|
||||
if (riid == IID_IDirectDrawGammaControl && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
auto realPrimary(RealPrimarySurface::getSurface());
|
||||
return realPrimary->QueryInterface(realPrimary, riid, obp);
|
||||
}
|
||||
return s_origVtable.QueryInterface(This, riid, obp);
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::ReleaseDC(TSurface* This, HDC hDC)
|
||||
{
|
||||
const bool isPrimary = CompatPrimarySurface::isPrimary(This);
|
||||
if (isPrimary && RealPrimarySurface::isLost())
|
||||
{
|
||||
return DDERR_SURFACELOST;
|
||||
}
|
||||
|
||||
HRESULT result = s_origVtable.ReleaseDC(This, hDC);
|
||||
if (isPrimary && SUCCEEDED(result))
|
||||
{
|
||||
RealPrimarySurface::invalidate(nullptr);
|
||||
RealPrimarySurface::update();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::Restore(TSurface* This)
|
||||
{
|
||||
const bool wasLost = DDERR_SURFACELOST == s_origVtable.IsLost(This);
|
||||
HRESULT result = s_origVtable.Restore(This);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
if (wasLost)
|
||||
{
|
||||
fixSurfacePtrs(*This);
|
||||
}
|
||||
if (CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
result = RealPrimarySurface::restore();
|
||||
if (wasLost)
|
||||
{
|
||||
Gdi::invalidate(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::SetClipper(
|
||||
TSurface* This,
|
||||
LPDIRECTDRAWCLIPPER lpDDClipper)
|
||||
{
|
||||
HRESULT result = s_origVtable.SetClipper(This, lpDDClipper);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
RealPrimarySurface::setClipper(lpDDClipper);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::SetPalette(
|
||||
TSurface* This,
|
||||
LPDIRECTDRAWPALETTE lpDDPalette)
|
||||
{
|
||||
const bool isPrimary = CompatPrimarySurface::isPrimary(This);
|
||||
if (isPrimary)
|
||||
{
|
||||
if (lpDDPalette)
|
||||
{
|
||||
DirectDrawPalette::waitForNextUpdate();
|
||||
}
|
||||
if (lpDDPalette == CompatPrimarySurface::g_palette)
|
||||
{
|
||||
return DD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT result = s_origVtable.SetPalette(This, lpDDPalette);
|
||||
if (isPrimary && SUCCEEDED(result))
|
||||
{
|
||||
CompatPrimarySurface::g_palette = lpDDPalette;
|
||||
RealPrimarySurface::setPalette();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
|
||||
{
|
||||
HRESULT result = s_origVtable.Unlock(This, lpRect);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
RealPrimarySurface::update();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
void DirectDrawSurface<TSurface>::restorePrimaryCaps(TDdsCaps& caps)
|
||||
{
|
||||
caps.dwCaps &= ~(DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);
|
||||
caps.dwCaps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
|
||||
SET_COMPAT_METHOD(Blt);
|
||||
SET_COMPAT_METHOD(BltFast);
|
||||
SET_COMPAT_METHOD(Flip);
|
||||
SET_COMPAT_METHOD(GetCaps);
|
||||
SET_COMPAT_METHOD(GetSurfaceDesc);
|
||||
SET_COMPAT_METHOD(IsLost);
|
||||
SET_COMPAT_METHOD(Lock);
|
||||
SET_COMPAT_METHOD(QueryInterface);
|
||||
SET_COMPAT_METHOD(ReleaseDC);
|
||||
SET_COMPAT_METHOD(Restore);
|
||||
SET_COMPAT_METHOD(SetClipper);
|
||||
SET_COMPAT_METHOD(SetPalette);
|
||||
SET_COMPAT_METHOD(Unlock);
|
||||
}
|
||||
|
||||
template DirectDrawSurface<IDirectDrawSurface>;
|
||||
@ -537,21 +50,4 @@ namespace DDraw
|
||||
template DirectDrawSurface<IDirectDrawSurface3>;
|
||||
template DirectDrawSurface<IDirectDrawSurface4>;
|
||||
template DirectDrawSurface<IDirectDrawSurface7>;
|
||||
|
||||
template HRESULT DirectDrawSurface<IDirectDrawSurface>::createCompatPrimarySurface(
|
||||
CompatRef<IDirectDraw> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
IDirectDrawSurface*& compatSurface);
|
||||
template HRESULT DirectDrawSurface<IDirectDrawSurface>::createCompatPrimarySurface(
|
||||
CompatRef<IDirectDraw2> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
IDirectDrawSurface*& compatSurface);
|
||||
template HRESULT DirectDrawSurface<IDirectDrawSurface4>::createCompatPrimarySurface(
|
||||
CompatRef<IDirectDraw4> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
IDirectDrawSurface4*& compatSurface);
|
||||
template HRESULT DirectDrawSurface<IDirectDrawSurface7>::createCompatPrimarySurface(
|
||||
CompatRef<IDirectDraw7> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
IDirectDrawSurface7*& compatSurface);
|
||||
}
|
||||
|
@ -12,59 +12,8 @@ namespace DDraw
|
||||
{
|
||||
public:
|
||||
typedef typename Types<TSurface>::TSurfaceDesc TSurfaceDesc;
|
||||
typedef typename Types<TSurface>::TDdsCaps TDdsCaps;
|
||||
typedef typename Types<TSurface>::TUnlockParam TUnlockParam;
|
||||
|
||||
static void setCompatVtable(Vtable<TSurface>& vtable);
|
||||
|
||||
template <typename TDirectDraw>
|
||||
static HRESULT createCompatPrimarySurface(
|
||||
CompatRef<TDirectDraw> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
TSurface*& compatSurface);
|
||||
|
||||
static void fixSurfacePtrs(CompatRef<TSurface> surface);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE Blt(
|
||||
TSurface* This,
|
||||
LPRECT lpDestRect,
|
||||
TSurface* lpDDSrcSurface,
|
||||
LPRECT lpSrcRect,
|
||||
DWORD dwFlags,
|
||||
LPDDBLTFX lpDDBltFx);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE BltFast(
|
||||
TSurface* This,
|
||||
DWORD dwX,
|
||||
DWORD dwY,
|
||||
TSurface* lpDDSrcSurface,
|
||||
LPRECT lpSrcRect,
|
||||
DWORD dwTrans);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE Flip(
|
||||
TSurface* This,
|
||||
TSurface* lpDDSurfaceTargetOverride,
|
||||
DWORD dwFlags);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE GetCaps(TSurface* This, TDdsCaps* lpDDSCaps);
|
||||
static HRESULT STDMETHODCALLTYPE GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc);
|
||||
static HRESULT STDMETHODCALLTYPE IsLost(TSurface* This);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE Lock(
|
||||
TSurface* This,
|
||||
LPRECT lpDestRect,
|
||||
TSurfaceDesc* lpDDSurfaceDesc,
|
||||
DWORD dwFlags,
|
||||
HANDLE hEvent);
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE QueryInterface(TSurface* This, REFIID riid, LPVOID* obp);
|
||||
static HRESULT STDMETHODCALLTYPE ReleaseDC(TSurface* This, HDC hDC);
|
||||
static HRESULT STDMETHODCALLTYPE Restore(TSurface* This);
|
||||
static HRESULT STDMETHODCALLTYPE SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper);
|
||||
static HRESULT STDMETHODCALLTYPE SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette);
|
||||
static HRESULT STDMETHODCALLTYPE Unlock(TSurface* This, TUnlockParam lpRect);
|
||||
|
||||
private:
|
||||
static void restorePrimaryCaps(TDdsCaps& caps);
|
||||
};
|
||||
}
|
||||
|
159
DDrawCompat/DDraw/Surfaces/Surface.cpp
Normal file
159
DDrawCompat/DDraw/Surfaces/Surface.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
#include <initguid.h>
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/Surfaces/Surface.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
|
||||
// {C62D8849-DFAC-4454-A1E8-DA67446426BA}
|
||||
DEFINE_GUID(IID_CompatSurfacePrivateData,
|
||||
0xc62d8849, 0xdfac, 0x4454, 0xa1, 0xe8, 0xda, 0x67, 0x44, 0x64, 0x26, 0xba);
|
||||
|
||||
namespace
|
||||
{
|
||||
void fixSurfaceDesc(CompatRef<IDirectDraw7> dd, DWORD& flags, DWORD& caps, DDPIXELFORMAT& pf)
|
||||
{
|
||||
if ((flags & DDSD_WIDTH) &&
|
||||
(flags & DDSD_HEIGHT) &&
|
||||
!(caps & (DDSCAPS_ALPHA | DDSCAPS_ZBUFFER)))
|
||||
{
|
||||
if (!(flags & DDSD_PIXELFORMAT))
|
||||
{
|
||||
auto dm = DDraw::DisplayMode::getDisplayMode(dd);
|
||||
flags |= DDSD_PIXELFORMAT;
|
||||
pf = dm.ddpfPixelFormat;
|
||||
}
|
||||
|
||||
if (!(caps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_OVERLAY | DDSCAPS_TEXTURE |
|
||||
DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)))
|
||||
{
|
||||
flags |= DDSD_CAPS;
|
||||
caps |= DDSCAPS_OFFSCREENPLAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
HRESULT STDMETHODCALLTYPE Surface::QueryInterface(REFIID, LPVOID*)
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE Surface::AddRef()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE Surface::Release()
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Surface::~Surface()
|
||||
{
|
||||
}
|
||||
|
||||
void Surface::attach(CompatRef<IDirectDrawSurface7> dds, std::unique_ptr<Surface>& privateData)
|
||||
{
|
||||
if (SUCCEEDED(dds->SetPrivateData(&dds, IID_CompatSurfacePrivateData,
|
||||
privateData.get(), sizeof(privateData.get()), DDSPD_IUNKNOWNPOINTER)))
|
||||
{
|
||||
privateData.release();
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT WINAPI Surface::attachToLinkedSurfaces(
|
||||
IDirectDrawSurface7* surface, DDSURFACEDESC2* /*desc*/, void* rootSurface)
|
||||
{
|
||||
CompatPtr<IDirectDrawSurface7> surfaceReleaser(surface);
|
||||
if (surface == rootSurface)
|
||||
{
|
||||
return DDENUMRET_CANCEL;
|
||||
}
|
||||
|
||||
std::unique_ptr<DDraw::Surface> privateData(new Surface());
|
||||
attach(*surface, privateData);
|
||||
CompatVtableBase<IDirectDrawSurface7>::s_origVtable.EnumAttachedSurfaces(
|
||||
surface, rootSurface, &attachToLinkedSurfaces);
|
||||
return DDENUMRET_OK;
|
||||
}
|
||||
|
||||
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
|
||||
HRESULT Surface::create(CompatRef<TDirectDraw> dd, TSurfaceDesc desc, TSurface*& surface)
|
||||
{
|
||||
CompatPtr<IDirectDraw7> dd7(Compat::queryInterface<IDirectDraw7>(&dd));
|
||||
fixSurfaceDesc(*dd7, desc.dwFlags, desc.ddsCaps.dwCaps, desc.ddpfPixelFormat);
|
||||
|
||||
HRESULT result = dd->CreateSurface(&dd, &desc, &surface, nullptr);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
SurfaceImpl<TSurface>::fixSurfacePtrs(*surface);
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> surface7(
|
||||
Compat::queryInterface<IDirectDrawSurface7>(surface));
|
||||
std::unique_ptr<Surface> privateData(new Surface());
|
||||
attach(*surface7, privateData);
|
||||
if (desc.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
|
||||
{
|
||||
CompatVtableBase<IDirectDrawSurface7>::s_origVtable.EnumAttachedSurfaces(
|
||||
surface7, surface7, &attachToLinkedSurfaces);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template HRESULT Surface::create(
|
||||
CompatRef<IDirectDraw> dd, DDSURFACEDESC desc, IDirectDrawSurface*& surface);
|
||||
template HRESULT Surface::create(
|
||||
CompatRef<IDirectDraw2> dd, DDSURFACEDESC desc, IDirectDrawSurface*& surface);
|
||||
template HRESULT Surface::create(
|
||||
CompatRef<IDirectDraw4> dd, DDSURFACEDESC2 desc, IDirectDrawSurface4*& surface);
|
||||
template HRESULT Surface::create(
|
||||
CompatRef<IDirectDraw7> dd, DDSURFACEDESC2 desc, IDirectDrawSurface7*& surface);
|
||||
|
||||
void Surface::createImpl()
|
||||
{
|
||||
m_impl.reset(new SurfaceImpl<IDirectDrawSurface>());
|
||||
m_impl2.reset(new SurfaceImpl<IDirectDrawSurface2>());
|
||||
m_impl3.reset(new SurfaceImpl<IDirectDrawSurface3>());
|
||||
m_impl4.reset(new SurfaceImpl<IDirectDrawSurface4>());
|
||||
m_impl7.reset(new SurfaceImpl<IDirectDrawSurface7>());
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
SurfaceImpl<TSurface>* Surface::getImpl(CompatRef<TSurface> dds)
|
||||
{
|
||||
Surface* surface = nullptr;
|
||||
DWORD surfacePtrSize = sizeof(surface);
|
||||
CompatVtableBase<IDirectDrawSurface7>::s_origVtable.GetPrivateData(
|
||||
reinterpret_cast<IDirectDrawSurface7*>(&dds),
|
||||
IID_CompatSurfacePrivateData, &surface, &surfacePtrSize);
|
||||
if (!surface)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return surface->getImpl<TSurface>();
|
||||
}
|
||||
|
||||
template SurfaceImpl<IDirectDrawSurface>* Surface::getImpl(CompatRef<IDirectDrawSurface> dds);
|
||||
template SurfaceImpl<IDirectDrawSurface2>* Surface::getImpl(CompatRef<IDirectDrawSurface2> dds);
|
||||
template SurfaceImpl<IDirectDrawSurface3>* Surface::getImpl(CompatRef<IDirectDrawSurface3> dds);
|
||||
template SurfaceImpl<IDirectDrawSurface4>* Surface::getImpl(CompatRef<IDirectDrawSurface4> dds);
|
||||
template SurfaceImpl<IDirectDrawSurface7>* Surface::getImpl(CompatRef<IDirectDrawSurface7> dds);
|
||||
|
||||
template <>
|
||||
SurfaceImpl<IDirectDrawSurface>* Surface::getImpl<IDirectDrawSurface>() const { return m_impl.get(); }
|
||||
template <>
|
||||
SurfaceImpl<IDirectDrawSurface2>* Surface::getImpl<IDirectDrawSurface2>() const { return m_impl2.get(); }
|
||||
template <>
|
||||
SurfaceImpl<IDirectDrawSurface3>* Surface::getImpl<IDirectDrawSurface3>() const { return m_impl3.get(); }
|
||||
template <>
|
||||
SurfaceImpl<IDirectDrawSurface4>* Surface::getImpl<IDirectDrawSurface4>() const { return m_impl4.get(); }
|
||||
template <>
|
||||
SurfaceImpl<IDirectDrawSurface7>* Surface::getImpl<IDirectDrawSurface7>() const { return m_impl7.get(); }
|
||||
}
|
48
DDrawCompat/DDraw/Surfaces/Surface.h
Normal file
48
DDrawCompat/DDraw/Surfaces/Surface.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include "Common/CompatRef.h"
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
template <typename TSurface>
|
||||
class SurfaceImpl;
|
||||
|
||||
class Surface
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||
virtual ULONG STDMETHODCALLTYPE Release();
|
||||
|
||||
virtual ~Surface();
|
||||
|
||||
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
|
||||
static HRESULT create(CompatRef<TDirectDraw> dd, TSurfaceDesc desc, TSurface*& surface);
|
||||
|
||||
template <typename TSurface>
|
||||
static SurfaceImpl<TSurface>* getImpl(CompatRef<TSurface> dds);
|
||||
|
||||
template <typename TSurface>
|
||||
SurfaceImpl<TSurface>* getImpl() const;
|
||||
|
||||
protected:
|
||||
static void attach(CompatRef<IDirectDrawSurface7> dds, std::unique_ptr<Surface>& privateData);
|
||||
|
||||
std::unique_ptr<SurfaceImpl<IDirectDrawSurface>> m_impl;
|
||||
std::unique_ptr<SurfaceImpl<IDirectDrawSurface2>> m_impl2;
|
||||
std::unique_ptr<SurfaceImpl<IDirectDrawSurface3>> m_impl3;
|
||||
std::unique_ptr<SurfaceImpl<IDirectDrawSurface4>> m_impl4;
|
||||
std::unique_ptr<SurfaceImpl<IDirectDrawSurface7>> m_impl7;
|
||||
|
||||
private:
|
||||
static HRESULT WINAPI attachToLinkedSurfaces(
|
||||
IDirectDrawSurface7* surface, DDSURFACEDESC2* desc, void* rootSurface);
|
||||
virtual void createImpl();
|
||||
};
|
||||
}
|
520
DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp
Normal file
520
DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp
Normal file
@ -0,0 +1,520 @@
|
||||
#include <set>
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "DDraw/CompatPrimarySurface.h"
|
||||
#include "DDraw/DirectDrawPalette.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/RealPrimarySurface.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "DDraw/Surfaces/Surface.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool mirrorBlt(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
RECT srcRect, DWORD mirrorFx);
|
||||
|
||||
bool g_lockingPrimary = false;
|
||||
|
||||
void fixSurfacePtr(CompatRef<IDirectDrawSurface7> surface, const DDSURFACEDESC2& desc)
|
||||
{
|
||||
if ((desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) || 0 == desc.dwWidth || 0 == desc.dwHeight)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DDSURFACEDESC2 tempSurfaceDesc = desc;
|
||||
tempSurfaceDesc.dwWidth = 1;
|
||||
tempSurfaceDesc.dwHeight = 1;
|
||||
DDraw::Repository::ScopedSurface tempSurface(desc);
|
||||
if (!tempSurface.surface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RECT r = { 0, 0, 1, 1 };
|
||||
surface->Blt(&surface, &r, tempSurface.surface, &r, DDBLT_WAIT, nullptr);
|
||||
}
|
||||
|
||||
HRESULT WINAPI fixSurfacePtrEnumCallback(
|
||||
LPDIRECTDRAWSURFACE7 lpDDSurface,
|
||||
LPDDSURFACEDESC2 lpDDSurfaceDesc,
|
||||
LPVOID lpContext)
|
||||
{
|
||||
auto& visitedSurfaces = *static_cast<std::set<IDirectDrawSurface7*>*>(lpContext);
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> surface(lpDDSurface);
|
||||
if (visitedSurfaces.find(surface) == visitedSurfaces.end())
|
||||
{
|
||||
visitedSurfaces.insert(surface);
|
||||
fixSurfacePtr(*surface, *lpDDSurfaceDesc);
|
||||
surface->EnumAttachedSurfaces(surface, lpContext, &fixSurfacePtrEnumCallback);
|
||||
}
|
||||
|
||||
return DDENUMRET_OK;
|
||||
}
|
||||
|
||||
void fixSurfacePtrs(CompatRef<IDirectDrawSurface7> surface)
|
||||
{
|
||||
DDSURFACEDESC2 desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
surface->GetSurfaceDesc(&surface, &desc);
|
||||
|
||||
fixSurfacePtr(surface, desc);
|
||||
std::set<IDirectDrawSurface7*> visitedSurfaces{ &surface };
|
||||
surface->EnumAttachedSurfaces(&surface, &visitedSurfaces, &fixSurfacePtrEnumCallback);
|
||||
}
|
||||
|
||||
CompatWeakPtr<IDirectDrawSurface7> getMirroredSurface(
|
||||
CompatRef<IDirectDrawSurface7> surface, RECT* srcRect, DWORD mirrorFx)
|
||||
{
|
||||
DDSURFACEDESC2 desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
HRESULT result = surface->GetSurfaceDesc(&surface, &desc);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_ONCE("Failed to get surface description for mirroring: " << result);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (srcRect)
|
||||
{
|
||||
desc.dwWidth = srcRect->right - srcRect->left;
|
||||
desc.dwHeight = srcRect->bottom - srcRect->top;
|
||||
}
|
||||
|
||||
DDraw::Repository::ScopedSurface mirroredSurface(desc);
|
||||
if (!mirroredSurface.surface)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RECT rect = { 0, 0, static_cast<LONG>(desc.dwWidth), static_cast<LONG>(desc.dwHeight) };
|
||||
if ((mirrorFx & DDBLTFX_MIRRORLEFTRIGHT) && (mirrorFx & DDBLTFX_MIRRORUPDOWN))
|
||||
{
|
||||
DDraw::Repository::Surface tempMirroredSurface = DDraw::Repository::ScopedSurface(desc);
|
||||
if (!tempMirroredSurface.surface ||
|
||||
!mirrorBlt(*tempMirroredSurface.surface, surface, srcRect ? *srcRect : rect,
|
||||
DDBLTFX_MIRRORLEFTRIGHT) ||
|
||||
!mirrorBlt(*mirroredSurface.surface, *tempMirroredSurface.surface, rect,
|
||||
DDBLTFX_MIRRORUPDOWN))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else if (!mirrorBlt(*mirroredSurface.surface, surface, srcRect ? *srcRect : rect, mirrorFx))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mirroredSurface.surface;
|
||||
}
|
||||
|
||||
bool mirrorBlt(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
RECT srcRect, DWORD mirrorFx)
|
||||
{
|
||||
if (DDBLTFX_MIRRORLEFTRIGHT == mirrorFx)
|
||||
{
|
||||
LONG width = srcRect.right - srcRect.left;
|
||||
srcRect.left = srcRect.right - 1;
|
||||
for (LONG x = 0; x < width; ++x)
|
||||
{
|
||||
HRESULT result = dst->BltFast(&dst, x, 0, &src, &srcRect, DDBLTFAST_WAIT);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_ONCE("Failed BltFast for mirroring: " << result);
|
||||
return false;
|
||||
}
|
||||
--srcRect.left;
|
||||
--srcRect.right;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LONG height = srcRect.bottom - srcRect.top;
|
||||
srcRect.top = srcRect.bottom - 1;
|
||||
for (LONG y = 0; y < height; ++y)
|
||||
{
|
||||
HRESULT result = dst->BltFast(&dst, 0, y, &src, &srcRect, DDBLTFAST_WAIT);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_ONCE("Failed BltFast for mirroring: " << result);
|
||||
return false;
|
||||
}
|
||||
--srcRect.top;
|
||||
--srcRect.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
template <typename TSurface>
|
||||
template <typename TDirectDraw>
|
||||
HRESULT SurfaceImpl<TSurface>::createCompatPrimarySurface(
|
||||
CompatRef<TDirectDraw> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
TSurface*& compatSurface)
|
||||
{
|
||||
HRESULT result = RealPrimarySurface::create(dd);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDraw7> dd7(Compat::queryInterface<IDirectDraw7>(&dd));
|
||||
const auto& dm = DisplayMode::getDisplayMode(*dd7);
|
||||
compatDesc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
|
||||
compatDesc.dwWidth = dm.dwWidth;
|
||||
compatDesc.dwHeight = dm.dwHeight;
|
||||
compatDesc.ddsCaps.dwCaps &= ~DDSCAPS_PRIMARYSURFACE;
|
||||
compatDesc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
|
||||
compatDesc.ddpfPixelFormat = dm.ddpfPixelFormat;
|
||||
|
||||
result = Surface::create(dd, compatDesc, compatSurface);
|
||||
if (FAILED(result))
|
||||
{
|
||||
Compat::Log() << "Failed to create the compat primary surface!";
|
||||
RealPrimarySurface::release();
|
||||
return result;
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> primary(Compat::queryInterface<IDirectDrawSurface7>(compatSurface));
|
||||
CompatPrimarySurface::setPrimary(*primary);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
SurfaceImpl<TSurface>::~SurfaceImpl()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
void SurfaceImpl<TSurface>::fixSurfacePtrs(CompatRef<TSurface> surface)
|
||||
{
|
||||
CompatPtr<IDirectDrawSurface7> surface7(Compat::queryInterface<IDirectDrawSurface7>(&surface));
|
||||
::fixSurfacePtrs(*surface7);
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::Blt(
|
||||
TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect,
|
||||
DWORD dwFlags, LPDDBLTFX lpDDBltFx)
|
||||
{
|
||||
const bool isPrimaryDest = CompatPrimarySurface::isPrimary(This);
|
||||
if ((isPrimaryDest || CompatPrimarySurface::isPrimary(lpDDSrcSurface)) &&
|
||||
RealPrimarySurface::isLost())
|
||||
{
|
||||
return DDERR_SURFACELOST;
|
||||
}
|
||||
|
||||
HRESULT result = DD_OK;
|
||||
CompatPtr<TSurface> mirroredSrcSurface;
|
||||
|
||||
if (lpDDSrcSurface && (dwFlags & DDBLT_DDFX) && lpDDBltFx &&
|
||||
(lpDDBltFx->dwDDFX & (DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN)))
|
||||
{
|
||||
CompatPtr<IDirectDrawSurface7> srcSurface(
|
||||
Compat::queryInterface<IDirectDrawSurface7>(lpDDSrcSurface));
|
||||
mirroredSrcSurface.reset(Compat::queryInterface<TSurface>(
|
||||
getMirroredSurface(*srcSurface, lpSrcRect, lpDDBltFx->dwDDFX).get()));
|
||||
if (!mirroredSrcSurface)
|
||||
{
|
||||
LOG_ONCE("Failed to emulate a mirrored Blt");
|
||||
}
|
||||
}
|
||||
|
||||
if (mirroredSrcSurface)
|
||||
{
|
||||
DWORD flags = dwFlags;
|
||||
DDBLTFX fx = *lpDDBltFx;
|
||||
fx.dwDDFX &= ~(DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN);
|
||||
if (0 == fx.dwDDFX)
|
||||
{
|
||||
flags ^= DDBLT_DDFX;
|
||||
}
|
||||
if (flags & DDBLT_KEYSRC)
|
||||
{
|
||||
DDCOLORKEY srcColorKey = {};
|
||||
s_origVtable.GetColorKey(lpDDSrcSurface, DDCKEY_SRCBLT, &srcColorKey);
|
||||
s_origVtable.SetColorKey(mirroredSrcSurface, DDCKEY_SRCBLT, &srcColorKey);
|
||||
}
|
||||
|
||||
if (lpSrcRect)
|
||||
{
|
||||
RECT srcRect = {
|
||||
0, 0, lpSrcRect->right - lpSrcRect->left, lpSrcRect->bottom - lpSrcRect->top };
|
||||
result = s_origVtable.Blt(This, lpDestRect, mirroredSrcSurface, &srcRect, flags, &fx);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = s_origVtable.Blt(This, lpDestRect, mirroredSrcSurface, nullptr, flags, &fx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = s_origVtable.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
|
||||
}
|
||||
|
||||
if (isPrimaryDest && SUCCEEDED(result))
|
||||
{
|
||||
RealPrimarySurface::invalidate(lpDestRect);
|
||||
RealPrimarySurface::update();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::BltFast(
|
||||
TSurface* This, DWORD dwX, DWORD dwY, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans)
|
||||
{
|
||||
const bool isPrimaryDest = CompatPrimarySurface::isPrimary(This);
|
||||
if ((isPrimaryDest || CompatPrimarySurface::isPrimary(lpDDSrcSurface)) &&
|
||||
RealPrimarySurface::isLost())
|
||||
{
|
||||
return DDERR_SURFACELOST;
|
||||
}
|
||||
|
||||
HRESULT result = s_origVtable.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
|
||||
if (isPrimaryDest && SUCCEEDED(result))
|
||||
{
|
||||
const LONG x = dwX;
|
||||
const LONG y = dwY;
|
||||
RECT destRect = { x, y, x, y };
|
||||
if (lpSrcRect)
|
||||
{
|
||||
destRect.right += lpSrcRect->right - lpSrcRect->left;
|
||||
destRect.bottom += lpSrcRect->bottom - lpSrcRect->top;
|
||||
}
|
||||
else
|
||||
{
|
||||
TSurfaceDesc desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
s_origVtable.GetSurfaceDesc(lpDDSrcSurface, &desc);
|
||||
destRect.right += desc.dwWidth;
|
||||
destRect.bottom += desc.dwHeight;
|
||||
}
|
||||
RealPrimarySurface::invalidate(&destRect);
|
||||
RealPrimarySurface::update();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::Flip(TSurface* This, TSurface* lpDDSurfaceTargetOverride, DWORD dwFlags)
|
||||
{
|
||||
HRESULT result = s_origVtable.Flip(This, lpDDSurfaceTargetOverride, dwFlags);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
result = RealPrimarySurface::flip(dwFlags);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::GetCaps(TSurface* This, TDdsCaps* lpDDSCaps)
|
||||
{
|
||||
HRESULT result = s_origVtable.GetCaps(This, lpDDSCaps);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
restorePrimaryCaps(*lpDDSCaps);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc)
|
||||
{
|
||||
HRESULT result = s_origVtable.GetSurfaceDesc(This, lpDDSurfaceDesc);
|
||||
if (SUCCEEDED(result) && !g_lockingPrimary && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::IsLost(TSurface* This)
|
||||
{
|
||||
HRESULT result = s_origVtable.IsLost(This);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
result = RealPrimarySurface::isLost() ? DDERR_SURFACELOST : DD_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::Lock(
|
||||
TSurface* This, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc,
|
||||
DWORD dwFlags, HANDLE hEvent)
|
||||
{
|
||||
if (CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
if (RealPrimarySurface::isLost())
|
||||
{
|
||||
return DDERR_SURFACELOST;
|
||||
}
|
||||
g_lockingPrimary = true;
|
||||
}
|
||||
|
||||
HRESULT result = s_origVtable.Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent);
|
||||
if (SUCCEEDED(result) && g_lockingPrimary && lpDDSurfaceDesc)
|
||||
{
|
||||
RealPrimarySurface::invalidate(lpDestRect);
|
||||
restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps);
|
||||
}
|
||||
else if (DDERR_SURFACELOST == result)
|
||||
{
|
||||
TSurfaceDesc desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
if (SUCCEEDED(s_origVtable.GetSurfaceDesc(This, &desc)) && !(desc.dwFlags & DDSD_HEIGHT))
|
||||
{
|
||||
// Fixes missing handling for lost vertex buffers in Messiah
|
||||
s_origVtable.Restore(This);
|
||||
// Still, pass back DDERR_SURFACELOST to the application in case it handles it
|
||||
}
|
||||
}
|
||||
|
||||
g_lockingPrimary = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::QueryInterface(TSurface* This, REFIID riid, LPVOID* obp)
|
||||
{
|
||||
if (riid == IID_IDirectDrawGammaControl && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
auto realPrimary(RealPrimarySurface::getSurface());
|
||||
return realPrimary->QueryInterface(realPrimary, riid, obp);
|
||||
}
|
||||
return s_origVtable.QueryInterface(This, riid, obp);
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::ReleaseDC(TSurface* This, HDC hDC)
|
||||
{
|
||||
const bool isPrimary = CompatPrimarySurface::isPrimary(This);
|
||||
if (isPrimary && RealPrimarySurface::isLost())
|
||||
{
|
||||
return DDERR_SURFACELOST;
|
||||
}
|
||||
|
||||
HRESULT result = s_origVtable.ReleaseDC(This, hDC);
|
||||
if (isPrimary && SUCCEEDED(result))
|
||||
{
|
||||
RealPrimarySurface::invalidate(nullptr);
|
||||
RealPrimarySurface::update();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::Restore(TSurface* This)
|
||||
{
|
||||
const bool wasLost = DDERR_SURFACELOST == s_origVtable.IsLost(This);
|
||||
HRESULT result = s_origVtable.Restore(This);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
if (wasLost)
|
||||
{
|
||||
fixSurfacePtrs(*This);
|
||||
}
|
||||
if (CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
result = RealPrimarySurface::restore();
|
||||
if (wasLost)
|
||||
{
|
||||
Gdi::invalidate(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper)
|
||||
{
|
||||
HRESULT result = s_origVtable.SetClipper(This, lpDDClipper);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
RealPrimarySurface::setClipper(lpDDClipper);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette)
|
||||
{
|
||||
const bool isPrimary = CompatPrimarySurface::isPrimary(This);
|
||||
if (isPrimary)
|
||||
{
|
||||
if (lpDDPalette)
|
||||
{
|
||||
DirectDrawPalette::waitForNextUpdate();
|
||||
}
|
||||
if (lpDDPalette == CompatPrimarySurface::g_palette)
|
||||
{
|
||||
return DD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT result = s_origVtable.SetPalette(This, lpDDPalette);
|
||||
if (isPrimary && SUCCEEDED(result))
|
||||
{
|
||||
CompatPrimarySurface::g_palette = lpDDPalette;
|
||||
RealPrimarySurface::setPalette();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
HRESULT SurfaceImpl<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
|
||||
{
|
||||
HRESULT result = s_origVtable.Unlock(This, lpRect);
|
||||
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
|
||||
{
|
||||
RealPrimarySurface::update();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
void SurfaceImpl<TSurface>::restorePrimaryCaps(TDdsCaps& caps)
|
||||
{
|
||||
caps.dwCaps &= ~(DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);
|
||||
caps.dwCaps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
const Vtable<TSurface>& SurfaceImpl<TSurface>::s_origVtable = CompatVtableBase<TSurface>::s_origVtable;
|
||||
|
||||
template SurfaceImpl<IDirectDrawSurface>;
|
||||
template SurfaceImpl<IDirectDrawSurface2>;
|
||||
template SurfaceImpl<IDirectDrawSurface3>;
|
||||
template SurfaceImpl<IDirectDrawSurface4>;
|
||||
template SurfaceImpl<IDirectDrawSurface7>;
|
||||
|
||||
template HRESULT SurfaceImpl<IDirectDrawSurface>::createCompatPrimarySurface(
|
||||
CompatRef<IDirectDraw> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
IDirectDrawSurface*& compatSurface);
|
||||
template HRESULT SurfaceImpl<IDirectDrawSurface>::createCompatPrimarySurface(
|
||||
CompatRef<IDirectDraw2> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
IDirectDrawSurface*& compatSurface);
|
||||
template HRESULT SurfaceImpl<IDirectDrawSurface4>::createCompatPrimarySurface(
|
||||
CompatRef<IDirectDraw4> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
IDirectDrawSurface4*& compatSurface);
|
||||
template HRESULT SurfaceImpl<IDirectDrawSurface7>::createCompatPrimarySurface(
|
||||
CompatRef<IDirectDraw7> dd,
|
||||
TSurfaceDesc compatDesc,
|
||||
IDirectDrawSurface7*& compatSurface);
|
||||
}
|
50
DDrawCompat/DDraw/Surfaces/SurfaceImpl.h
Normal file
50
DDrawCompat/DDraw/Surfaces/SurfaceImpl.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include "Common/CompatRef.h"
|
||||
#include "Common/CompatVtable.h"
|
||||
#include "DDraw/Types.h"
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
template <typename TSurface>
|
||||
class SurfaceImpl
|
||||
{
|
||||
public:
|
||||
typedef typename Types<TSurface>::TSurfaceDesc TSurfaceDesc;
|
||||
typedef typename Types<TSurface>::TDdsCaps TDdsCaps;
|
||||
typedef typename Types<TSurface>::TUnlockParam TUnlockParam;
|
||||
|
||||
virtual ~SurfaceImpl();
|
||||
|
||||
template <typename TDirectDraw>
|
||||
static HRESULT createCompatPrimarySurface(
|
||||
CompatRef<TDirectDraw> dd, TSurfaceDesc compatDesc, TSurface*& compatSurface);
|
||||
static void fixSurfacePtrs(CompatRef<TSurface> surface);
|
||||
|
||||
virtual HRESULT Blt(TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect,
|
||||
DWORD dwFlags, LPDDBLTFX lpDDBltFx);
|
||||
virtual HRESULT BltFast(TSurface* This, DWORD dwX, DWORD dwY,
|
||||
TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans);
|
||||
virtual HRESULT Flip(TSurface* This, TSurface* lpDDSurfaceTargetOverride, DWORD dwFlags);
|
||||
virtual HRESULT GetCaps(TSurface* This, TDdsCaps* lpDDSCaps);
|
||||
virtual HRESULT GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc);
|
||||
virtual HRESULT IsLost(TSurface* This);
|
||||
virtual HRESULT Lock(TSurface* This, LPRECT lpDestRect, TSurfaceDesc* lpDDSurfaceDesc,
|
||||
DWORD dwFlags, HANDLE hEvent);
|
||||
virtual HRESULT QueryInterface(TSurface* This, REFIID riid, LPVOID* obp);
|
||||
virtual HRESULT ReleaseDC(TSurface* This, HDC hDC);
|
||||
virtual HRESULT Restore(TSurface* This);
|
||||
virtual HRESULT SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper);
|
||||
virtual HRESULT SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette);
|
||||
virtual HRESULT Unlock(TSurface* This, TUnlockParam lpRect);
|
||||
|
||||
private:
|
||||
static void restorePrimaryCaps(TDdsCaps& caps);
|
||||
|
||||
static const Vtable<TSurface>& s_origVtable;
|
||||
};
|
||||
}
|
@ -179,6 +179,8 @@
|
||||
<ClInclude Include="DDraw\Hooks.h" />
|
||||
<ClInclude Include="DDraw\Repository.h" />
|
||||
<ClInclude Include="DDraw\ScopedThreadLock.h" />
|
||||
<ClInclude Include="DDraw\Surfaces\Surface.h" />
|
||||
<ClInclude Include="DDraw\Surfaces\SurfaceImpl.h" />
|
||||
<ClInclude Include="DDraw\Types.h" />
|
||||
<ClInclude Include="DDraw\IReleaseNotifier.h" />
|
||||
<ClInclude Include="DDraw\RealPrimarySurface.h" />
|
||||
@ -227,6 +229,8 @@
|
||||
<ClCompile Include="DDraw\Repository.cpp" />
|
||||
<ClCompile Include="DDraw\IReleaseNotifier.cpp" />
|
||||
<ClCompile Include="DDraw\RealPrimarySurface.cpp" />
|
||||
<ClCompile Include="DDraw\Surfaces\Surface.cpp" />
|
||||
<ClCompile Include="DDraw\Surfaces\SurfaceImpl.cpp" />
|
||||
<ClCompile Include="Direct3d\DepthBuffer.cpp" />
|
||||
<ClCompile Include="Direct3d\Direct3d.cpp" />
|
||||
<ClCompile Include="Direct3d\Direct3dDevice.cpp" />
|
||||
|
@ -67,6 +67,12 @@
|
||||
<Filter Include="Source Files\Dll">
|
||||
<UniqueIdentifier>{41544d1c-712a-4bef-8913-a40155a33ba0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\DDraw\Surfaces">
|
||||
<UniqueIdentifier>{0550f0bd-b66f-4c6a-9072-e83bdfc52e4d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\DDraw\Surfaces">
|
||||
<UniqueIdentifier>{c60f8247-4d67-4dcf-9f97-f1c5b1acc469}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Gdi\Gdi.h">
|
||||
@ -240,6 +246,12 @@
|
||||
<ClInclude Include="Dll\Procs.h">
|
||||
<Filter>Header Files\Dll</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DDraw\Surfaces\Surface.h">
|
||||
<Filter>Header Files\DDraw\Surfaces</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DDraw\Surfaces\SurfaceImpl.h">
|
||||
<Filter>Header Files\DDraw\Surfaces</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -359,6 +371,12 @@
|
||||
<ClCompile Include="Dll\UnmodifiedProcs.cpp">
|
||||
<Filter>Source Files\Dll</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DDraw\Surfaces\Surface.cpp">
|
||||
<Filter>Source Files\DDraw\Surfaces</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DDraw\Surfaces\SurfaceImpl.cpp">
|
||||
<Filter>Source Files\DDraw\Surfaces</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Dll\DDrawCompat.def">
|
||||
|
Loading…
x
Reference in New Issue
Block a user