From fbe34c034124800a739a40846eb13472603d32ce Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 23 Oct 2016 15:07:50 +0200 Subject: [PATCH] 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. --- DDrawCompat/D3dDdi/AdapterFuncs.cpp | 11 ++ DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp | 141 +-------------------- 2 files changed, 12 insertions(+), 140 deletions(-) diff --git a/DDrawCompat/D3dDdi/AdapterFuncs.cpp b/DDrawCompat/D3dDdi/AdapterFuncs.cpp index 9084404..e5d562c 100644 --- a/DDrawCompat/D3dDdi/AdapterFuncs.cpp +++ b/DDrawCompat/D3dDdi/AdapterFuncs.cpp @@ -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(pData->pData)->FxCaps = 0; + } + return result; + } } namespace D3dDdi @@ -33,5 +43,6 @@ namespace D3dDdi { vtable.pfnCloseAdapter = &closeAdapter; vtable.pfnCreateDevice = &createDevice; + vtable.pfnGetCaps = &getCaps; } } diff --git a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp index 977c058..c0a1ac3 100644 --- a/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp +++ b/DDrawCompat/DDraw/Surfaces/SurfaceImpl.cpp @@ -1,8 +1,5 @@ #include -#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 dst, CompatRef src, - RECT srcRect, DWORD mirrorFx); - void fixSurfacePtr(CompatRef surface, const DDSURFACEDESC2& desc) { if ((desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) || 0 == desc.dwWidth || 0 == desc.dwHeight) @@ -60,91 +54,6 @@ namespace std::set visitedSurfaces{ &surface }; surface->EnumAttachedSurfaces(&surface, &visitedSurfaces, &fixSurfacePtrEnumCallback); } - - CompatWeakPtr getMirroredSurface( - CompatRef 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(desc.dwWidth), static_cast(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 dst, CompatRef 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 mirroredSrcSurface; - - if (lpDDSrcSurface && (dwFlags & DDBLT_DDFX) && lpDDBltFx && - (lpDDBltFx->dwDDFX & (DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN))) - { - 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"); - } - } - - 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