mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Perform sysmem to vidmem render target blits via Direct3D
This commit is contained in:
parent
436a8184bb
commit
075287b16a
@ -62,6 +62,18 @@ namespace D3dDdi
|
||||
return result;
|
||||
}
|
||||
|
||||
Device* Device::findDeviceByResource(HANDLE resource)
|
||||
{
|
||||
for (auto& device : s_devices)
|
||||
{
|
||||
if (device.second.m_resources.find(resource) != device.second.m_resources.end())
|
||||
{
|
||||
return &device.second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Resource* Device::findResource(HANDLE resource)
|
||||
{
|
||||
for (auto& device : s_devices)
|
||||
@ -206,15 +218,9 @@ namespace D3dDdi
|
||||
HRESULT Device::pfnDestroyResource(HANDLE resource)
|
||||
{
|
||||
flushPrimitives();
|
||||
if (g_gdiResource && resource == *g_gdiResource)
|
||||
if (g_gdiResource)
|
||||
{
|
||||
D3DDDIARG_LOCK lock = {};
|
||||
lock.hResource = *g_gdiResource;
|
||||
g_gdiResource->lock(lock);
|
||||
|
||||
D3DDDIARG_UNLOCK unlock = {};
|
||||
unlock.hResource = *g_gdiResource;
|
||||
g_gdiResource->unlock(unlock);
|
||||
g_gdiResource->onDestroyResource(resource);
|
||||
}
|
||||
|
||||
if (resource == m_sharedPrimary)
|
||||
|
@ -63,6 +63,7 @@ namespace D3dDdi
|
||||
static Device& get(HANDLE device) { return s_devices.find(device)->second; }
|
||||
|
||||
static void enableFlush(bool enable) { s_isFlushEnabled = enable; }
|
||||
static Device* findDeviceByResource(HANDLE resource);
|
||||
static Resource* findResource(HANDLE resource);
|
||||
static Resource* getGdiResource();
|
||||
static void setGdiResourceHandle(HANDLE resource);
|
||||
|
@ -593,9 +593,21 @@ namespace D3dDdi
|
||||
m_changedStates |= CS_STREAM_SOURCE;
|
||||
}
|
||||
|
||||
void DeviceState::setTempTexture(UINT stage, HANDLE texture)
|
||||
void DeviceState::setTempTexture(UINT stage, HANDLE texture, const UINT* srcColorKey)
|
||||
{
|
||||
setTexture(stage, texture);
|
||||
if (srcColorKey)
|
||||
{
|
||||
m_current.textures[stage] = nullptr;
|
||||
m_current.textureStageState[stage][D3DDDITSS_DISABLETEXTURECOLORKEY] = 0;
|
||||
m_current.textureStageState[stage][D3DDDITSS_TEXTURECOLORKEYVAL] = *srcColorKey + 1;
|
||||
setTexture(stage, texture);
|
||||
setTextureStageState({ stage, D3DDDITSS_TEXTURECOLORKEYVAL, *srcColorKey });
|
||||
}
|
||||
else
|
||||
{
|
||||
setTexture(stage, texture);
|
||||
}
|
||||
|
||||
m_changedStates |= CS_TEXTURE_STAGE;
|
||||
m_maxChangedTextureStage = max(stage, m_maxChangedTextureStage);
|
||||
}
|
||||
@ -820,6 +832,7 @@ namespace D3dDdi
|
||||
m_device.getOrigVtable().pfnSetTextureStageState(m_device, &tss);
|
||||
m_changedTextureStageStates[stage].reset(D3DDDITSS_DISABLETEXTURECOLORKEY);
|
||||
m_changedTextureStageStates[stage].reset(D3DDDITSS_TEXTURECOLORKEYVAL);
|
||||
LOG_DS << tss;
|
||||
}
|
||||
|
||||
void DeviceState::updateTextureStages()
|
||||
|
@ -88,7 +88,7 @@ namespace D3dDdi
|
||||
void setTempRenderTarget(const D3DDDIARG_SETRENDERTARGET& renderTarget);
|
||||
void setTempStreamSource(const D3DDDIARG_SETSTREAMSOURCE& streamSource);
|
||||
void setTempStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& streamSourceUm, const void* umBuffer);
|
||||
void setTempTexture(UINT stage, HANDLE texture);
|
||||
void setTempTexture(UINT stage, HANDLE texture, const UINT* srcColorKey = nullptr);
|
||||
void setTempTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE& tss);
|
||||
void setTempVertexShaderDecl(HANDLE decl);
|
||||
void setTempViewport(const D3DDDIARG_VIEWPORTINFO& viewport);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <DDraw/Blitter.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <DDraw/Surfaces/SurfaceImpl.h>
|
||||
#include <Gdi/Cursor.h>
|
||||
#include <Gdi/Palette.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
@ -188,6 +189,7 @@ namespace D3dDdi
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DDraw::setBltSrc(data);
|
||||
auto srcResource = m_device.getResource(data.hSrcResource);
|
||||
if (srcResource)
|
||||
{
|
||||
@ -623,6 +625,13 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Resource::lock(D3DDDIARG_LOCK& data)
|
||||
{
|
||||
D3DDDIARG_BLT blt = {};
|
||||
DDraw::setBltSrc(blt);
|
||||
if (blt.hSrcResource)
|
||||
{
|
||||
return E_ABORT;
|
||||
}
|
||||
|
||||
if (isOversized())
|
||||
{
|
||||
if (0 != data.SubResourceIndex ||
|
||||
@ -657,6 +666,16 @@ namespace D3dDdi
|
||||
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
|
||||
}
|
||||
|
||||
void Resource::onDestroyResource(HANDLE resource)
|
||||
{
|
||||
if (resource == m_handle ||
|
||||
m_msaaSurface.resource && *m_msaaSurface.resource == resource ||
|
||||
m_msaaResolvedSurface.resource && *m_msaaResolvedSurface.resource == resource)
|
||||
{
|
||||
loadSysMemResource(0);
|
||||
}
|
||||
}
|
||||
|
||||
Resource& Resource::prepareForBltSrc(const D3DDDIARG_BLT& data)
|
||||
{
|
||||
if (m_lockResource)
|
||||
@ -868,7 +887,7 @@ namespace D3dDdi
|
||||
UINT dstIndex = data.DstSubResourceIndex;
|
||||
RECT dstRect = data.DstRect;
|
||||
|
||||
if (!srcResource.m_fixedData.Flags.Texture)
|
||||
if (!srcResource.m_fixedData.Flags.Texture || D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool)
|
||||
{
|
||||
DWORD width = data.SrcRect.right - data.SrcRect.left;
|
||||
DWORD height = data.SrcRect.bottom - data.SrcRect.top;
|
||||
|
@ -34,6 +34,7 @@ namespace D3dDdi
|
||||
HRESULT colorFill(D3DDDIARG_COLORFILL data);
|
||||
void* getLockPtr(UINT subResourceIndex);
|
||||
HRESULT lock(D3DDDIARG_LOCK& data);
|
||||
void onDestroyResource(HANDLE resource);
|
||||
Resource& prepareForBltSrc(const D3DDDIARG_BLT& data);
|
||||
Resource& prepareForBltDst(D3DDDIARG_BLT& data);
|
||||
void prepareForCpuRead(UINT subResourceIndex);
|
||||
|
@ -65,11 +65,7 @@ namespace D3dDdi
|
||||
state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0xF });
|
||||
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, D3DTEXF_LINEAR == filter });
|
||||
|
||||
setTempTextureStage(0, srcResource, filter);
|
||||
if (srcColorKey)
|
||||
{
|
||||
state.setTempTextureStageState({ 0, D3DDDITSS_TEXTURECOLORKEYVAL, *srcColorKey });
|
||||
}
|
||||
setTempTextureStage(0, srcResource, filter, srcColorKey);
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
@ -241,10 +237,10 @@ namespace D3dDdi
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psPaletteLookup.get(), D3DTEXF_POINT);
|
||||
}
|
||||
|
||||
void ShaderBlitter::setTempTextureStage(UINT stage, HANDLE texture, UINT filter)
|
||||
void ShaderBlitter::setTempTextureStage(UINT stage, HANDLE texture, UINT filter, const UINT* srcColorKey)
|
||||
{
|
||||
auto& state = m_device.getState();
|
||||
state.setTempTexture(stage, texture);
|
||||
state.setTempTexture(stage, texture, srcColorKey);
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSU, D3DTADDRESS_CLAMP });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_ADDRESSV, D3DTADDRESS_CLAMP });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, filter });
|
||||
|
@ -42,7 +42,7 @@ namespace D3dDdi
|
||||
|
||||
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE* code, UINT size);
|
||||
std::unique_ptr<void, ResourceDeleter> createVertexShaderDecl();
|
||||
void setTempTextureStage(UINT stage, HANDLE texture, UINT filter);
|
||||
void setTempTextureStage(UINT stage, HANDLE texture, UINT filter, const UINT* srcColorKey = nullptr);
|
||||
|
||||
Device& m_device;
|
||||
std::unique_ptr<void, ResourceDeleter> m_psDrawCursor;
|
||||
|
@ -22,7 +22,13 @@ namespace DDraw
|
||||
template <typename TSurface>
|
||||
HANDLE getDriverResourceHandle(TSurface& surface)
|
||||
{
|
||||
return *reinterpret_cast<HANDLE*>(getRuntimeResourceHandle(surface));
|
||||
return reinterpret_cast<HANDLE*>(getRuntimeResourceHandle(surface))[0];
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
UINT getSubResourceIndex(TSurface& surface)
|
||||
{
|
||||
return reinterpret_cast<UINT*>(getRuntimeResourceHandle(surface))[1];
|
||||
}
|
||||
|
||||
template <typename Vtable>
|
||||
|
@ -1,8 +1,6 @@
|
||||
#include <initguid.h>
|
||||
|
||||
#include <Common/CompatPtr.h>
|
||||
#include <D3dDdi/Device.h>
|
||||
#include <D3dDdi/Resource.h>
|
||||
#include <DDraw/DirectDrawClipper.h>
|
||||
#include <DDraw/DirectDrawSurface.h>
|
||||
#include <DDraw/Surfaces/Surface.h>
|
||||
|
@ -1,6 +1,11 @@
|
||||
#include <set>
|
||||
|
||||
#include <d3d.h>
|
||||
#include <d3dumddi.h>
|
||||
|
||||
#include <Common/CompatPtr.h>
|
||||
#include <D3dDdi/Device.h>
|
||||
#include <D3dDdi/SurfaceRepository.h>
|
||||
#include <DDraw/DirectDrawClipper.h>
|
||||
#include <DDraw/DirectDrawSurface.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
@ -9,6 +14,83 @@
|
||||
#include <DDraw/Surfaces/SurfaceImpl.h>
|
||||
#include <Dll/Dll.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
HANDLE g_bltSrcResource = nullptr;
|
||||
UINT g_bltSrcSubResourceIndex = 0;
|
||||
RECT g_bltSrcRect = {};
|
||||
|
||||
template <typename TSurface>
|
||||
typename DDraw::Types<TSurface>::TSurfaceDesc getDesc(TSurface* This)
|
||||
{
|
||||
DDraw::Types<TSurface>::TSurfaceDesc desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
getOrigVtable(This).GetSurfaceDesc(This, &desc);
|
||||
return desc;
|
||||
}
|
||||
|
||||
template <typename TSurfaceDesc>
|
||||
RECT getRect(LPRECT rect, const TSurfaceDesc& desc)
|
||||
{
|
||||
return rect ? *rect : RECT{ 0, 0, static_cast<LONG>(desc.dwWidth), static_cast<LONG>(desc.dwHeight) };
|
||||
}
|
||||
|
||||
template <typename TSurface, typename BltFunc>
|
||||
HRESULT blt(TSurface* This, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, BltFunc bltFunc)
|
||||
{
|
||||
if (!lpDDSrcSurface)
|
||||
{
|
||||
return bltFunc(This, lpDDSrcSurface, lpSrcRect);
|
||||
}
|
||||
|
||||
auto dstDesc = getDesc(This);
|
||||
if (!(dstDesc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) || !(dstDesc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
|
||||
{
|
||||
return bltFunc(This, lpDDSrcSurface, lpSrcRect);
|
||||
}
|
||||
|
||||
auto srcDesc = getDesc(lpDDSrcSurface);
|
||||
if (!(srcDesc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
|
||||
{
|
||||
return bltFunc(This, lpDDSrcSurface, lpSrcRect);
|
||||
}
|
||||
|
||||
auto srcResource = DDraw::DirectDrawSurface::getDriverResourceHandle(*lpDDSrcSurface);
|
||||
auto device = D3dDdi::Device::findDeviceByResource(srcResource);
|
||||
if (!device)
|
||||
{
|
||||
return bltFunc(This, lpDDSrcSurface, lpSrcRect);
|
||||
}
|
||||
|
||||
auto& repo = D3dDdi::SurfaceRepository::get(device->getAdapter());
|
||||
RECT srcRect = getRect(lpSrcRect, srcDesc);
|
||||
auto& tex = repo.getTempTexture(srcRect.right - srcRect.left, srcRect.bottom - srcRect.top,
|
||||
srcDesc.ddpfPixelFormat);
|
||||
if (!tex.resource)
|
||||
{
|
||||
return bltFunc(This, lpDDSrcSurface, lpSrcRect);
|
||||
}
|
||||
|
||||
CompatPtr<TSurface> newSrcSurface(tex.surface);
|
||||
DDCOLORKEY ck = {};
|
||||
HRESULT result = getOrigVtable(This).GetColorKey(lpDDSrcSurface, DDCKEY_SRCBLT, &ck);
|
||||
getOrigVtable(This).SetColorKey(newSrcSurface, DDCKEY_SRCBLT, SUCCEEDED(result) ? &ck : nullptr);
|
||||
|
||||
g_bltSrcResource = srcResource;
|
||||
g_bltSrcSubResourceIndex = DDraw::DirectDrawSurface::getSubResourceIndex(*lpDDSrcSurface);
|
||||
g_bltSrcRect = getRect(lpSrcRect, srcDesc);
|
||||
|
||||
RECT r = { 0, 0, g_bltSrcRect.right - g_bltSrcRect.left, g_bltSrcRect.bottom - g_bltSrcRect.top };
|
||||
result = bltFunc(This, newSrcSurface, &r);
|
||||
|
||||
g_bltSrcResource = nullptr;
|
||||
g_bltSrcSubResourceIndex = 0;
|
||||
g_bltSrcRect = {};
|
||||
|
||||
return SUCCEEDED(result) ? DD_OK : bltFunc(This, lpDDSrcSurface, lpSrcRect);
|
||||
}
|
||||
}
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
template <typename TSurface>
|
||||
@ -29,7 +111,8 @@ namespace DDraw
|
||||
{
|
||||
RealPrimarySurface::waitForFlip(m_data);
|
||||
DirectDrawClipper::update();
|
||||
return getOrigVtable(This).Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
|
||||
return blt(This, lpDDSrcSurface, lpSrcRect, [=](TSurface* This, TSurface* lpDDSrcSurface, LPRECT lpSrcRect)
|
||||
{ return getOrigVtable(This).Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); });
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
@ -37,7 +120,8 @@ namespace DDraw
|
||||
TSurface* This, DWORD dwX, DWORD dwY, TSurface* lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans)
|
||||
{
|
||||
RealPrimarySurface::waitForFlip(m_data);
|
||||
return getOrigVtable(This).BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
|
||||
return blt(This, lpDDSrcSurface, lpSrcRect, [=](TSurface* This, TSurface* lpDDSrcSurface, LPRECT lpSrcRect)
|
||||
{ return getOrigVtable(This).BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans); });
|
||||
}
|
||||
|
||||
template <typename TSurface>
|
||||
@ -191,4 +275,14 @@ namespace DDraw
|
||||
template SurfaceImpl<IDirectDrawSurface3>;
|
||||
template SurfaceImpl<IDirectDrawSurface4>;
|
||||
template SurfaceImpl<IDirectDrawSurface7>;
|
||||
|
||||
void setBltSrc(D3DDDIARG_BLT& data)
|
||||
{
|
||||
if (g_bltSrcResource)
|
||||
{
|
||||
data.hSrcResource = g_bltSrcResource;
|
||||
data.SrcSubResourceIndex = g_bltSrcSubResourceIndex;
|
||||
OffsetRect(&data.SrcRect, g_bltSrcRect.left, g_bltSrcRect.top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <Common/CompatVtable.h>
|
||||
#include <DDraw/Types.h>
|
||||
|
||||
struct _D3DDDIARG_BLT;
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
class Surface;
|
||||
@ -46,4 +48,6 @@ namespace DDraw
|
||||
private:
|
||||
void restoreOrigCaps(DWORD& caps);
|
||||
};
|
||||
|
||||
void setBltSrc(_D3DDDIARG_BLT& data);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user