mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Handle mirrored blits via HEL
Disabled the indication of mirrored blit support via the driver GetCaps routine as this may be reported as supported on modern GPUs even when it's not. Removing this indication allows the HEL (Hardware Emulation Layer) to correctly handle all mirrored blits. It also seems to perform better than the previous clumsy line-by-line mirroring emulation.
This commit is contained in:
parent
0edcde6d55
commit
fbe34c0341
@ -25,6 +25,16 @@ namespace
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT APIENTRY getCaps(HANDLE hAdapter, const D3DDDIARG_GETCAPS* pData)
|
||||
{
|
||||
HRESULT result = D3dDdi::AdapterFuncs::s_origVtables.at(hAdapter).pfnGetCaps(hAdapter, pData);
|
||||
if (SUCCEEDED(result) && D3DDDICAPS_DDRAW == pData->Type)
|
||||
{
|
||||
static_cast<DDRAW_CAPS*>(pData->pData)->FxCaps = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3dDdi
|
||||
@ -33,5 +43,6 @@ namespace D3dDdi
|
||||
{
|
||||
vtable.pfnCloseAdapter = &closeAdapter;
|
||||
vtable.pfnCreateDevice = &createDevice;
|
||||
vtable.pfnGetCaps = &getCaps;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
#include <set>
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "DDraw/DirectDrawSurface.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "DDraw/Surfaces/Surface.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
|
||||
@ -18,9 +15,6 @@ namespace
|
||||
DWORD unknown2;
|
||||
};
|
||||
|
||||
bool mirrorBlt(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
RECT srcRect, DWORD mirrorFx);
|
||||
|
||||
void fixSurfacePtr(CompatRef<IDirectDrawSurface7> surface, const DDSURFACEDESC2& desc)
|
||||
{
|
||||
if ((desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) || 0 == desc.dwWidth || 0 == desc.dwHeight)
|
||||
@ -60,91 +54,6 @@ namespace
|
||||
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;
|
||||
}
|
||||
|
||||
auto dd(DDraw::getDirectDraw(surface));
|
||||
DDraw::Repository::ScopedSurface mirroredSurface(*dd, 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(*dd, 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
|
||||
@ -166,55 +75,7 @@ namespace DDraw
|
||||
TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect,
|
||||
DWORD dwFlags, LPDDBLTFX lpDDBltFx)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
return result;
|
||||
return s_origVtable.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
|
Loading…
x
Reference in New Issue
Block a user