mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Reworked oversized surface support
This commit is contained in:
parent
3e0eada40d
commit
07de716af9
14
DDrawCompat/Common/HResultException.h
Normal file
14
DDrawCompat/Common/HResultException.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef long HRESULT;
|
||||||
|
|
||||||
|
class HResultException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HResultException(HRESULT result) : m_result(result) {}
|
||||||
|
|
||||||
|
HRESULT getResult() const { return m_result; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
HRESULT m_result;
|
||||||
|
};
|
@ -13,8 +13,9 @@ namespace D3dDdi
|
|||||||
public:
|
public:
|
||||||
Adapter(HANDLE adapter, HMODULE module);
|
Adapter(HANDLE adapter, HMODULE module);
|
||||||
|
|
||||||
|
operator HANDLE() const { return m_adapter; }
|
||||||
|
|
||||||
const D3DNTHAL_D3DEXTENDEDCAPS& getD3dExtendedCaps() const { return m_d3dExtendedCaps; }
|
const D3DNTHAL_D3DEXTENDEDCAPS& getD3dExtendedCaps() const { return m_d3dExtendedCaps; }
|
||||||
HANDLE getHandle() const { return m_adapter; }
|
|
||||||
HMODULE getModule() const { return m_module; }
|
HMODULE getModule() const { return m_module; }
|
||||||
|
|
||||||
static void add(HANDLE adapter, HMODULE module);
|
static void add(HANDLE adapter, HMODULE module);
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
#include <d3d.h>
|
#include <d3d.h>
|
||||||
#include <../km/d3dkmthk.h>
|
#include <../km/d3dkmthk.h>
|
||||||
|
|
||||||
|
#include "Common/HResultException.h"
|
||||||
#include "D3dDdi/Adapter.h"
|
#include "D3dDdi/Adapter.h"
|
||||||
#include "D3dDdi/Device.h"
|
#include "D3dDdi/Device.h"
|
||||||
#include "D3dDdi/DeviceFuncs.h"
|
#include "D3dDdi/DeviceFuncs.h"
|
||||||
#include "D3dDdi/KernelModeThunks.h"
|
#include "D3dDdi/KernelModeThunks.h"
|
||||||
|
#include "D3dDdi/Resource.h"
|
||||||
#include "Gdi/AccessGuard.h"
|
#include "Gdi/AccessGuard.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
D3DDDI_RESOURCEFLAGS getResourceTypeFlags();
|
|
||||||
|
|
||||||
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
|
|
||||||
HANDLE g_gdiResourceHandle = nullptr;
|
HANDLE g_gdiResourceHandle = nullptr;
|
||||||
bool g_isReadOnlyGdiLockEnabled = false;
|
bool g_isReadOnlyGdiLockEnabled = false;
|
||||||
|
|
||||||
@ -35,37 +34,6 @@ namespace
|
|||||||
private:
|
private:
|
||||||
D3dDdi::Device & m_device;
|
D3dDdi::Device & m_device;
|
||||||
};
|
};
|
||||||
|
|
||||||
D3DDDI_RESOURCEFLAGS getResourceTypeFlags()
|
|
||||||
{
|
|
||||||
D3DDDI_RESOURCEFLAGS flags = {};
|
|
||||||
flags.RenderTarget = 1;
|
|
||||||
flags.ZBuffer = 1;
|
|
||||||
flags.DMap = 1;
|
|
||||||
flags.Points = 1;
|
|
||||||
flags.RtPatches = 1;
|
|
||||||
flags.NPatches = 1;
|
|
||||||
flags.Video = 1;
|
|
||||||
flags.CaptureBuffer = 1;
|
|
||||||
flags.Primary = 1;
|
|
||||||
flags.Texture = 1;
|
|
||||||
flags.CubeMap = 1;
|
|
||||||
flags.VertexBuffer = 1;
|
|
||||||
flags.IndexBuffer = 1;
|
|
||||||
flags.DecodeRenderTarget = 1;
|
|
||||||
flags.DecodeCompressedBuffer = 1;
|
|
||||||
flags.VideoProcessRenderTarget = 1;
|
|
||||||
flags.Overlay = 1;
|
|
||||||
flags.TextApi = 1;
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isVidMemPool(D3DDDI_POOL pool)
|
|
||||||
{
|
|
||||||
return D3DDDIPOOL_VIDEOMEMORY == pool ||
|
|
||||||
D3DDDIPOOL_LOCALVIDMEM == pool ||
|
|
||||||
D3DDDIPOOL_NONLOCALVIDMEM == pool;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace D3dDdi
|
namespace D3dDdi
|
||||||
@ -110,19 +78,11 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
RenderGuard srcRenderGuard(*this, Gdi::ACCESS_READ, data.hSrcResource, data.SrcSubResourceIndex);
|
RenderGuard srcRenderGuard(*this, Gdi::ACCESS_READ, data.hSrcResource, data.SrcSubResourceIndex);
|
||||||
RenderGuard dstRenderGuard(*this, Gdi::ACCESS_WRITE, data.hDstResource, data.DstSubResourceIndex);
|
RenderGuard dstRenderGuard(*this, Gdi::ACCESS_WRITE, data.hDstResource, data.DstSubResourceIndex);
|
||||||
|
auto it = m_resources.find(data.hDstResource);
|
||||||
auto it = m_oversizedResources.find(data.hSrcResource);
|
if (it != m_resources.end())
|
||||||
if (it != m_oversizedResources.end())
|
|
||||||
{
|
{
|
||||||
return it->second.bltFrom(data);
|
return it->second.blt(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
it = m_oversizedResources.find(data.hDstResource);
|
|
||||||
if (it != m_oversizedResources.end())
|
|
||||||
{
|
|
||||||
return it->second.bltTo(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_origVtable.pfnBlt(m_device, &data);
|
return m_origVtable.pfnBlt(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,76 +98,29 @@ namespace D3dDdi
|
|||||||
return m_origVtable.pfnColorFill(m_device, &data);
|
return m_origVtable.pfnColorFill(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename CreateResourceArg, typename CreateResourceFunc>
|
template <typename Arg>
|
||||||
HRESULT Device::createOversizedResource(
|
HRESULT Device::createResourceImpl(Arg& data)
|
||||||
CreateResourceArg& data,
|
|
||||||
CreateResourceFunc origCreateResource,
|
|
||||||
const D3DNTHAL_D3DEXTENDEDCAPS& caps)
|
|
||||||
{
|
{
|
||||||
D3DDDI_SURFACEINFO compatSurfaceInfo = data.pSurfList[0];
|
try
|
||||||
if (0 != caps.dwMaxTextureWidth && compatSurfaceInfo.Width > caps.dwMaxTextureWidth)
|
|
||||||
{
|
{
|
||||||
compatSurfaceInfo.Width = caps.dwMaxTextureWidth;
|
Resource resource(Resource::create(*this, data));
|
||||||
|
m_resources.emplace(resource, resource);
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
if (0 != caps.dwMaxTextureHeight && compatSurfaceInfo.Height > caps.dwMaxTextureHeight)
|
catch (const HResultException& e)
|
||||||
{
|
{
|
||||||
compatSurfaceInfo.Height = caps.dwMaxTextureHeight;
|
return e.getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
const D3DDDI_SURFACEINFO* origSurfList = data.pSurfList;
|
|
||||||
data.pSurfList = &compatSurfaceInfo;
|
|
||||||
HRESULT result = origCreateResource(m_device, &data);
|
|
||||||
data.pSurfList = origSurfList;
|
|
||||||
|
|
||||||
if (SUCCEEDED(result))
|
|
||||||
{
|
|
||||||
m_oversizedResources.emplace(data.hResource, OversizedResource(*this, data.Format, origSurfList[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename CreateResourceArg, typename CreateResourceFunc>
|
|
||||||
HRESULT Device::createResourceImpl(CreateResourceArg& data, CreateResourceFunc origCreateResource)
|
|
||||||
{
|
|
||||||
const bool isOffScreenPlain = 0 == (data.Flags.Value & g_resourceTypeFlags);
|
|
||||||
if (D3DDDIPOOL_SYSTEMMEM == data.Pool &&
|
|
||||||
(isOffScreenPlain || data.Flags.Texture) &&
|
|
||||||
OversizedResource::isSupportedFormat(data.Format) &&
|
|
||||||
1 == data.SurfCount)
|
|
||||||
{
|
|
||||||
const auto& caps = m_adapter.getD3dExtendedCaps();
|
|
||||||
const auto& surfaceInfo = data.pSurfList[0];
|
|
||||||
if (0 != caps.dwMaxTextureWidth && surfaceInfo.Width > caps.dwMaxTextureWidth ||
|
|
||||||
0 != caps.dwMaxTextureHeight && surfaceInfo.Height > caps.dwMaxTextureHeight)
|
|
||||||
{
|
|
||||||
return createOversizedResource(data, origCreateResource, caps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.Flags.Primary)
|
|
||||||
{
|
|
||||||
data.Format = D3DDDIFMT_X8R8G8B8;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT result = origCreateResource(m_device, &data);
|
|
||||||
if (SUCCEEDED(result) && data.Flags.RenderTarget && !data.Flags.Primary && isVidMemPool(data.Pool))
|
|
||||||
{
|
|
||||||
m_renderTargetResources.emplace(data.hResource,
|
|
||||||
RenderTargetResource(*this, data.hResource, data.Format, data.SurfCount));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::createResource(D3DDDIARG_CREATERESOURCE& data)
|
HRESULT Device::createResource(D3DDDIARG_CREATERESOURCE& data)
|
||||||
{
|
{
|
||||||
return createResourceImpl(data, m_origVtable.pfnCreateResource);
|
return createResourceImpl(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::createResource2(D3DDDIARG_CREATERESOURCE2& data)
|
HRESULT Device::createResource2(D3DDDIARG_CREATERESOURCE2& data)
|
||||||
{
|
{
|
||||||
return createResourceImpl(data, m_origVtable.pfnCreateResource2);
|
return createResourceImpl(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Device::destroyResource(HANDLE resource)
|
HRESULT Device::destroyResource(HANDLE resource)
|
||||||
@ -220,7 +133,7 @@ namespace D3dDdi
|
|||||||
HRESULT result = m_origVtable.pfnDestroyResource(m_device, resource);
|
HRESULT result = m_origVtable.pfnDestroyResource(m_device, resource);
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
{
|
{
|
||||||
m_oversizedResources.erase(resource);
|
m_resources.erase(resource);
|
||||||
m_renderTargetResources.erase(resource);
|
m_renderTargetResources.erase(resource);
|
||||||
m_lockedRenderTargetResources.erase(resource);
|
m_lockedRenderTargetResources.erase(resource);
|
||||||
|
|
||||||
@ -292,6 +205,13 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto resourceIter = m_resources.find(data.hResource);
|
||||||
|
if (resourceIter != m_resources.end())
|
||||||
|
{
|
||||||
|
return resourceIter->second.lock(data);
|
||||||
|
}
|
||||||
|
|
||||||
return m_origVtable.pfnLock(m_device, &data);
|
return m_origVtable.pfnLock(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,6 +271,13 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
return it->second.unlock(data);
|
return it->second.unlock(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto resourceIter = m_resources.find(data.hResource);
|
||||||
|
if (resourceIter != m_resources.end())
|
||||||
|
{
|
||||||
|
return resourceIter->second.unlock(data);
|
||||||
|
}
|
||||||
|
|
||||||
return m_origVtable.pfnUnlock(m_device, &data);
|
return m_origVtable.pfnUnlock(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,6 +293,12 @@ namespace D3dDdi
|
|||||||
return m_origVtable.pfnUpdateWInfo(m_device, &data);
|
return m_origVtable.pfnUpdateWInfo(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Device::addRenderTargetResource(const D3DDDIARG_CREATERESOURCE& data)
|
||||||
|
{
|
||||||
|
m_renderTargetResources.emplace(data.hResource,
|
||||||
|
RenderTargetResource(*this, data.hResource, data.Format, data.SurfCount));
|
||||||
|
}
|
||||||
|
|
||||||
void Device::prepareForRendering(RenderTargetResource& resource, UINT subResourceIndex)
|
void Device::prepareForRendering(RenderTargetResource& resource, UINT subResourceIndex)
|
||||||
{
|
{
|
||||||
resource.prepareForRendering(subResourceIndex);
|
resource.prepareForRendering(subResourceIndex);
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <d3dnthal.h>
|
#include <d3dnthal.h>
|
||||||
#include <d3dumddi.h>
|
#include <d3dumddi.h>
|
||||||
|
|
||||||
#include "D3dDdi/OversizedResource.h"
|
|
||||||
#include "D3dDdi/RenderTargetResource.h"
|
#include "D3dDdi/RenderTargetResource.h"
|
||||||
|
|
||||||
namespace D3dDdi
|
namespace D3dDdi
|
||||||
@ -14,10 +13,13 @@ namespace D3dDdi
|
|||||||
UINT getBytesPerPixel(D3DDDIFORMAT format);
|
UINT getBytesPerPixel(D3DDDIFORMAT format);
|
||||||
|
|
||||||
class Adapter;
|
class Adapter;
|
||||||
|
class Resource;
|
||||||
|
|
||||||
class Device
|
class Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
operator HANDLE() const { return m_device; }
|
||||||
|
|
||||||
HRESULT blt(const D3DDDIARG_BLT& data);
|
HRESULT blt(const D3DDDIARG_BLT& data);
|
||||||
HRESULT clear(const D3DDDIARG_CLEAR& data, UINT numRect, const RECT* rect);
|
HRESULT clear(const D3DDDIARG_CLEAR& data, UINT numRect, const RECT* rect);
|
||||||
HRESULT colorFill(const D3DDDIARG_COLORFILL& data);
|
HRESULT colorFill(const D3DDDIARG_COLORFILL& data);
|
||||||
@ -43,9 +45,10 @@ namespace D3dDdi
|
|||||||
HRESULT updateWInfo(const D3DDDIARG_WINFO& data);
|
HRESULT updateWInfo(const D3DDDIARG_WINFO& data);
|
||||||
|
|
||||||
Adapter& getAdapter() const { return m_adapter; }
|
Adapter& getAdapter() const { return m_adapter; }
|
||||||
HANDLE getHandle() const { return m_device; }
|
|
||||||
const D3DDDI_DEVICEFUNCS& getOrigVtable() const { return m_origVtable; }
|
const D3DDDI_DEVICEFUNCS& getOrigVtable() const { return m_origVtable; }
|
||||||
|
std::map<HANDLE, Resource>& getResources() { return m_resources; }
|
||||||
|
|
||||||
|
void addRenderTargetResource(const D3DDDIARG_CREATERESOURCE& data);
|
||||||
void prepareForRendering(HANDLE resource, UINT subResourceIndex = UINT_MAX);
|
void prepareForRendering(HANDLE resource, UINT subResourceIndex = UINT_MAX);
|
||||||
void prepareForRendering();
|
void prepareForRendering();
|
||||||
|
|
||||||
@ -59,21 +62,15 @@ namespace D3dDdi
|
|||||||
private:
|
private:
|
||||||
Device(HANDLE adapter, HANDLE device);
|
Device(HANDLE adapter, HANDLE device);
|
||||||
|
|
||||||
template <typename CreateResourceArg, typename CreateResourceFunc>
|
template <typename Arg>
|
||||||
HRESULT createOversizedResource(
|
HRESULT createResourceImpl(Arg& data);
|
||||||
CreateResourceArg& data,
|
|
||||||
CreateResourceFunc origCreateResource,
|
|
||||||
const D3DNTHAL_D3DEXTENDEDCAPS& caps);
|
|
||||||
|
|
||||||
template <typename CreateResourceArg, typename CreateResourceFunc>
|
|
||||||
HRESULT createResourceImpl(CreateResourceArg& data, CreateResourceFunc origCreateResource);
|
|
||||||
|
|
||||||
void prepareForRendering(RenderTargetResource& resource, UINT subResourceIndex = UINT_MAX);
|
void prepareForRendering(RenderTargetResource& resource, UINT subResourceIndex = UINT_MAX);
|
||||||
|
|
||||||
const D3DDDI_DEVICEFUNCS& m_origVtable;
|
const D3DDDI_DEVICEFUNCS& m_origVtable;
|
||||||
Adapter& m_adapter;
|
Adapter& m_adapter;
|
||||||
HANDLE m_device;
|
HANDLE m_device;
|
||||||
std::map<HANDLE, OversizedResource> m_oversizedResources;
|
std::map<HANDLE, Resource> m_resources;
|
||||||
std::map<HANDLE, RenderTargetResource> m_renderTargetResources;
|
std::map<HANDLE, RenderTargetResource> m_renderTargetResources;
|
||||||
std::map<HANDLE, RenderTargetResource&> m_lockedRenderTargetResources;
|
std::map<HANDLE, RenderTargetResource&> m_lockedRenderTargetResources;
|
||||||
HANDLE m_sharedPrimary;
|
HANDLE m_sharedPrimary;
|
||||||
|
@ -33,6 +33,7 @@ namespace
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::map<D3DKMT_HANDLE, ContextInfo> g_contexts;
|
std::map<D3DKMT_HANDLE, ContextInfo> g_contexts;
|
||||||
|
D3DDDIFORMAT g_dcFormatOverride = D3DDDIFMT_UNKNOWN;
|
||||||
AdapterInfo g_gdiAdapterInfo = {};
|
AdapterInfo g_gdiAdapterInfo = {};
|
||||||
AdapterInfo g_lastOpenAdapterInfo = {};
|
AdapterInfo g_lastOpenAdapterInfo = {};
|
||||||
std::string g_lastDDrawCreateDcDevice;
|
std::string g_lastDDrawCreateDcDevice;
|
||||||
@ -80,8 +81,15 @@ namespace
|
|||||||
NTSTATUS APIENTRY createDcFromMemory(D3DKMT_CREATEDCFROMMEMORY* pData)
|
NTSTATUS APIENTRY createDcFromMemory(D3DKMT_CREATEDCFROMMEMORY* pData)
|
||||||
{
|
{
|
||||||
LOG_FUNC("D3DKMTCreateDCFromMemory", pData);
|
LOG_FUNC("D3DKMTCreateDCFromMemory", pData);
|
||||||
|
|
||||||
|
auto origFormat = pData->Format;
|
||||||
|
if (D3DDDIFMT_UNKNOWN != g_dcFormatOverride)
|
||||||
|
{
|
||||||
|
pData->Format = g_dcFormatOverride;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS result = 0;
|
NTSTATUS result = 0;
|
||||||
if (pData && D3DDDIFMT_P8 == pData->Format && !pData->pColorTable &&
|
if (D3DDDIFMT_P8 == pData->Format && !pData->pColorTable &&
|
||||||
DDraw::PrimarySurface::s_palette)
|
DDraw::PrimarySurface::s_palette)
|
||||||
{
|
{
|
||||||
pData->pColorTable = DDraw::PrimarySurface::s_paletteEntries;
|
pData->pColorTable = DDraw::PrimarySurface::s_paletteEntries;
|
||||||
@ -92,6 +100,8 @@ namespace
|
|||||||
{
|
{
|
||||||
result = CALL_ORIG_FUNC(D3DKMTCreateDCFromMemory)(pData);
|
result = CALL_ORIG_FUNC(D3DKMTCreateDCFromMemory)(pData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pData->Format = origFormat;
|
||||||
return LOG_RESULT(result);
|
return LOG_RESULT(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,6 +360,11 @@ namespace D3dDdi
|
|||||||
g_flipIntervalOverride = flipInterval;
|
g_flipIntervalOverride = flipInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setDcFormatOverride(UINT format)
|
||||||
|
{
|
||||||
|
g_dcFormatOverride = static_cast<D3DDDIFORMAT>(format);
|
||||||
|
}
|
||||||
|
|
||||||
void waitForVerticalBlank()
|
void waitForVerticalBlank()
|
||||||
{
|
{
|
||||||
D3DKMT_WAITFORVERTICALBLANKEVENT data = {};
|
D3DKMT_WAITFORVERTICALBLANKEVENT data = {};
|
||||||
|
@ -15,6 +15,7 @@ namespace D3dDdi
|
|||||||
long long getQpcLastVerticalBlank();
|
long long getQpcLastVerticalBlank();
|
||||||
void installHooks(HMODULE origDDrawModule);
|
void installHooks(HMODULE origDDrawModule);
|
||||||
void setFlipIntervalOverride(UINT flipInterval);
|
void setFlipIntervalOverride(UINT flipInterval);
|
||||||
|
void setDcFormatOverride(UINT format);
|
||||||
void waitForVerticalBlank();
|
void waitForVerticalBlank();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,19 @@ std::ostream& operator<<(std::ostream& os, const D3DDDI_SURFACEINFO& val)
|
|||||||
<< val.SysMemSlicePitch;
|
<< val.SysMemSlicePitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_BLT& val)
|
||||||
|
{
|
||||||
|
return Compat::LogStruct(os)
|
||||||
|
<< val.hSrcResource
|
||||||
|
<< val.SrcSubResourceIndex
|
||||||
|
<< val.SrcRect
|
||||||
|
<< val.hDstResource
|
||||||
|
<< val.DstSubResourceIndex
|
||||||
|
<< val.DstRect
|
||||||
|
<< Compat::hex(val.ColorKey)
|
||||||
|
<< Compat::hex(val.Flags.Value);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CLEAR& val)
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CLEAR& val)
|
||||||
{
|
{
|
||||||
return Compat::LogStruct(os)
|
return Compat::LogStruct(os)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDI_RATIONAL& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDI_RATIONAL& val);
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDI_SURFACEINFO& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDI_SURFACEINFO& val);
|
||||||
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_BLT& val);
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CLEAR& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CLEAR& val);
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_COLORFILL& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_COLORFILL& val);
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATERESOURCE& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATERESOURCE& val);
|
||||||
|
@ -45,6 +45,7 @@ std::ostream& operator<<(std::ostream& os, const D3DKMT_CREATEDCFROMMEMORY& data
|
|||||||
{
|
{
|
||||||
return Compat::LogStruct(os)
|
return Compat::LogStruct(os)
|
||||||
<< data.pMemory
|
<< data.pMemory
|
||||||
|
<< data.Format
|
||||||
<< data.Width
|
<< data.Width
|
||||||
<< data.Height
|
<< data.Height
|
||||||
<< data.Pitch
|
<< data.Pitch
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
#include "D3dDdi/Adapter.h"
|
|
||||||
#include "D3dDdi/Device.h"
|
|
||||||
#include "D3dDdi/OversizedResource.h"
|
|
||||||
|
|
||||||
namespace D3dDdi
|
|
||||||
{
|
|
||||||
OversizedResource::OversizedResource(Device& device, D3DDDIFORMAT format, const D3DDDI_SURFACEINFO& surfaceInfo)
|
|
||||||
: m_device(device)
|
|
||||||
, m_format(format)
|
|
||||||
, m_surfaceInfo(surfaceInfo)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT OversizedResource::blt(D3DDDIARG_BLT& data, HANDLE& resource, RECT& rect)
|
|
||||||
{
|
|
||||||
const auto& caps = m_device.getAdapter().getD3dExtendedCaps();
|
|
||||||
if (rect.right <= static_cast<LONG>(caps.dwMaxTextureWidth) &&
|
|
||||||
rect.bottom <= static_cast<LONG>(caps.dwMaxTextureHeight))
|
|
||||||
{
|
|
||||||
return m_device.getOrigVtable().pfnBlt(m_device.getHandle(), &data);
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE origResource = resource;
|
|
||||||
RECT origRect = rect;
|
|
||||||
HANDLE bltResource = createBltResource(rect);
|
|
||||||
|
|
||||||
if (bltResource)
|
|
||||||
{
|
|
||||||
resource = bltResource;
|
|
||||||
rect = RECT{ 0, 0, rect.right - rect.left, rect.bottom - rect.top };
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT result = m_device.getOrigVtable().pfnBlt(m_device.getHandle(), &data);
|
|
||||||
|
|
||||||
if (bltResource)
|
|
||||||
{
|
|
||||||
resource = origResource;
|
|
||||||
rect = origRect;
|
|
||||||
m_device.getOrigVtable().pfnDestroyResource(m_device.getHandle(), bltResource);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT OversizedResource::bltFrom(D3DDDIARG_BLT data)
|
|
||||||
{
|
|
||||||
return blt(data, data.hSrcResource, data.SrcRect);
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT OversizedResource::bltTo(D3DDDIARG_BLT data)
|
|
||||||
{
|
|
||||||
return blt(data, data.hDstResource, data.DstRect);
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE OversizedResource::createBltResource(RECT bltRect)
|
|
||||||
{
|
|
||||||
const RECT surfaceRect = {
|
|
||||||
0, 0, static_cast<LONG>(m_surfaceInfo.Width), static_cast<LONG>(m_surfaceInfo.Height) };
|
|
||||||
IntersectRect(&bltRect, &surfaceRect, &bltRect);
|
|
||||||
|
|
||||||
D3DDDI_SURFACEINFO bltSurfaceInfo = {};
|
|
||||||
bltSurfaceInfo.Width = bltRect.right - bltRect.left;
|
|
||||||
bltSurfaceInfo.Height = bltRect.bottom - bltRect.top;
|
|
||||||
bltSurfaceInfo.pSysMem = static_cast<const unsigned char*>(m_surfaceInfo.pSysMem) +
|
|
||||||
bltRect.top * m_surfaceInfo.SysMemPitch +
|
|
||||||
bltRect.left * getBytesPerPixel(m_format);
|
|
||||||
bltSurfaceInfo.SysMemPitch = m_surfaceInfo.SysMemPitch;
|
|
||||||
|
|
||||||
D3DDDIARG_CREATERESOURCE2 bltResourceData = {};
|
|
||||||
bltResourceData.Format = m_format;
|
|
||||||
bltResourceData.Pool = D3DDDIPOOL_SYSTEMMEM;
|
|
||||||
bltResourceData.pSurfList = &bltSurfaceInfo;
|
|
||||||
bltResourceData.SurfCount = 1;
|
|
||||||
|
|
||||||
if (m_device.getOrigVtable().pfnCreateResource2)
|
|
||||||
{
|
|
||||||
m_device.getOrigVtable().pfnCreateResource2(m_device.getHandle(), &bltResourceData);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_device.getOrigVtable().pfnCreateResource(m_device.getHandle(),
|
|
||||||
reinterpret_cast<D3DDDIARG_CREATERESOURCE*>(&bltResourceData));
|
|
||||||
}
|
|
||||||
return bltResourceData.hResource;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OversizedResource::isSupportedFormat(D3DDDIFORMAT format)
|
|
||||||
{
|
|
||||||
return 0 != getBytesPerPixel(format);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <d3d.h>
|
|
||||||
#include <d3dumddi.h>
|
|
||||||
|
|
||||||
namespace D3dDdi
|
|
||||||
{
|
|
||||||
class Device;
|
|
||||||
|
|
||||||
class OversizedResource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
OversizedResource(Device& device, D3DDDIFORMAT format, const D3DDDI_SURFACEINFO& surfaceInfo);
|
|
||||||
|
|
||||||
HRESULT bltFrom(D3DDDIARG_BLT data);
|
|
||||||
HRESULT bltTo(D3DDDIARG_BLT data);
|
|
||||||
|
|
||||||
static bool isSupportedFormat(D3DDDIFORMAT format);
|
|
||||||
|
|
||||||
private:
|
|
||||||
HRESULT blt(D3DDDIARG_BLT& data, HANDLE& resource, RECT& rect);
|
|
||||||
HANDLE createBltResource(RECT bltRect);
|
|
||||||
|
|
||||||
Device& m_device;
|
|
||||||
D3DDDIFORMAT m_format;
|
|
||||||
D3DDDI_SURFACEINFO m_surfaceInfo;
|
|
||||||
};
|
|
||||||
}
|
|
@ -15,7 +15,7 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
if (data.SubResourceIndex >= m_subResources.size())
|
if (data.SubResourceIndex >= m_subResources.size())
|
||||||
{
|
{
|
||||||
return m_device.getOrigVtable().pfnLock(m_device.getHandle(), &data);
|
return m_device.getOrigVtable().pfnLock(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& subResource = m_subResources[data.SubResourceIndex];
|
auto& subResource = m_subResources[data.SubResourceIndex];
|
||||||
@ -34,7 +34,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
const UINT origFlags = data.Flags.Value;
|
const UINT origFlags = data.Flags.Value;
|
||||||
data.Flags.Value = 0;
|
data.Flags.Value = 0;
|
||||||
const HRESULT result = m_device.getOrigVtable().pfnLock(m_device.getHandle(), &data);
|
const HRESULT result = m_device.getOrigVtable().pfnLock(m_device, &data);
|
||||||
data.Flags.Value = origFlags;
|
data.Flags.Value = origFlags;
|
||||||
|
|
||||||
if (SUCCEEDED(result))
|
if (SUCCEEDED(result))
|
||||||
@ -52,7 +52,7 @@ namespace D3dDdi
|
|||||||
{
|
{
|
||||||
if (data.SubResourceIndex >= m_subResources.size())
|
if (data.SubResourceIndex >= m_subResources.size())
|
||||||
{
|
{
|
||||||
return m_device.getOrigVtable().pfnUnlock(m_device.getHandle(), &data);
|
return m_device.getOrigVtable().pfnUnlock(m_device, &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_subResources[data.SubResourceIndex].isLocked = false;
|
m_subResources[data.SubResourceIndex].isLocked = false;
|
||||||
@ -86,7 +86,7 @@ namespace D3dDdi
|
|||||||
D3DDDIARG_UNLOCK data = {};
|
D3DDDIARG_UNLOCK data = {};
|
||||||
data.hResource = m_resource;
|
data.hResource = m_resource;
|
||||||
data.SubResourceIndex = subResourceIndex;
|
data.SubResourceIndex = subResourceIndex;
|
||||||
m_device.getOrigVtable().pfnUnlock(m_device.getHandle(), &data);
|
m_device.getOrigVtable().pfnUnlock(m_device, &data);
|
||||||
|
|
||||||
subResource.surfacePtr = nullptr;
|
subResource.surfacePtr = nullptr;
|
||||||
subResource.pitch = 0;
|
subResource.pitch = 0;
|
||||||
|
328
DDrawCompat/D3dDdi/Resource.cpp
Normal file
328
DDrawCompat/D3dDdi/Resource.cpp
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "Common/HResultException.h"
|
||||||
|
#include "Common/Log.h"
|
||||||
|
#include "D3dDdi/Adapter.h"
|
||||||
|
#include "D3dDdi/Device.h"
|
||||||
|
#include "D3dDdi/Log/DeviceFuncsLog.h"
|
||||||
|
#include "D3dDdi/Resource.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
D3DDDI_RESOURCEFLAGS getResourceTypeFlags();
|
||||||
|
bool isVidMemPool(D3DDDI_POOL pool);
|
||||||
|
void splitToTiles(D3DDDIARG_CREATERESOURCE& data, const UINT tileWidth, const UINT tileHeight);
|
||||||
|
|
||||||
|
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
|
||||||
|
|
||||||
|
LONG divCeil(LONG n, LONG d)
|
||||||
|
{
|
||||||
|
return (n + d - 1) / d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fixResourceData(D3dDdi::Device& device, D3DDDIARG_CREATERESOURCE& data)
|
||||||
|
{
|
||||||
|
if (data.Flags.Primary)
|
||||||
|
{
|
||||||
|
data.Format = D3DDDIFMT_X8R8G8B8;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool isOffScreenPlain = 0 == (data.Flags.Value & g_resourceTypeFlags);
|
||||||
|
if (D3DDDIPOOL_SYSTEMMEM == data.Pool &&
|
||||||
|
(isOffScreenPlain || data.Flags.Texture) &&
|
||||||
|
1 == data.SurfCount &&
|
||||||
|
0 == data.pSurfList[0].Depth &&
|
||||||
|
0 != D3dDdi::getBytesPerPixel(data.Format))
|
||||||
|
{
|
||||||
|
const auto& caps = device.getAdapter().getD3dExtendedCaps();
|
||||||
|
const auto& surfaceInfo = data.pSurfList[0];
|
||||||
|
if (0 != caps.dwMaxTextureWidth && surfaceInfo.Width > caps.dwMaxTextureWidth ||
|
||||||
|
0 != caps.dwMaxTextureHeight && surfaceInfo.Height > caps.dwMaxTextureHeight)
|
||||||
|
{
|
||||||
|
splitToTiles(data, caps.dwMaxTextureWidth, caps.dwMaxTextureHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DDDI_RESOURCEFLAGS getResourceTypeFlags()
|
||||||
|
{
|
||||||
|
D3DDDI_RESOURCEFLAGS flags = {};
|
||||||
|
flags.RenderTarget = 1;
|
||||||
|
flags.ZBuffer = 1;
|
||||||
|
flags.DMap = 1;
|
||||||
|
flags.Points = 1;
|
||||||
|
flags.RtPatches = 1;
|
||||||
|
flags.NPatches = 1;
|
||||||
|
flags.Video = 1;
|
||||||
|
flags.CaptureBuffer = 1;
|
||||||
|
flags.Primary = 1;
|
||||||
|
flags.Texture = 1;
|
||||||
|
flags.CubeMap = 1;
|
||||||
|
flags.VertexBuffer = 1;
|
||||||
|
flags.IndexBuffer = 1;
|
||||||
|
flags.DecodeRenderTarget = 1;
|
||||||
|
flags.DecodeCompressedBuffer = 1;
|
||||||
|
flags.VideoProcessRenderTarget = 1;
|
||||||
|
flags.Overlay = 1;
|
||||||
|
flags.TextApi = 1;
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isVidMemPool(D3DDDI_POOL pool)
|
||||||
|
{
|
||||||
|
return D3DDDIPOOL_VIDEOMEMORY == pool ||
|
||||||
|
D3DDDIPOOL_LOCALVIDMEM == pool ||
|
||||||
|
D3DDDIPOOL_NONLOCALVIDMEM == pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
void splitToTiles(D3DDDIARG_CREATERESOURCE& data, const UINT tileWidth, const UINT tileHeight)
|
||||||
|
{
|
||||||
|
static std::vector<D3DDDI_SURFACEINFO> tiles;
|
||||||
|
tiles.clear();
|
||||||
|
|
||||||
|
const UINT bytesPerPixel = D3dDdi::getBytesPerPixel(data.Format);
|
||||||
|
|
||||||
|
for (UINT y = 0; y < data.pSurfList[0].Height; y += tileHeight)
|
||||||
|
{
|
||||||
|
for (UINT x = 0; x < data.pSurfList[0].Width; x += tileWidth)
|
||||||
|
{
|
||||||
|
D3DDDI_SURFACEINFO tile = {};
|
||||||
|
tile.Width = min(data.pSurfList[0].Width - x, tileWidth);
|
||||||
|
tile.Height = min(data.pSurfList[0].Height - y, tileHeight);
|
||||||
|
tile.pSysMem = static_cast<const unsigned char*>(data.pSurfList[0].pSysMem) +
|
||||||
|
y * data.pSurfList[0].SysMemPitch + x * bytesPerPixel;
|
||||||
|
tile.SysMemPitch = data.pSurfList[0].SysMemPitch;
|
||||||
|
tiles.push_back(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.SurfCount = tiles.size();
|
||||||
|
data.pSurfList = tiles.data();
|
||||||
|
data.Flags.Texture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DDDIARG_CREATERESOURCE2 upgradeResourceData(const D3DDDIARG_CREATERESOURCE& data)
|
||||||
|
{
|
||||||
|
D3DDDIARG_CREATERESOURCE2 data2 = {};
|
||||||
|
reinterpret_cast<D3DDDIARG_CREATERESOURCE&>(data2) = data;
|
||||||
|
return data2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace D3dDdi
|
||||||
|
{
|
||||||
|
Resource::Data::Data()
|
||||||
|
: D3DDDIARG_CREATERESOURCE2{}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Data::Data(const D3DDDIARG_CREATERESOURCE& data)
|
||||||
|
: Data(upgradeResourceData(data))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Data::Data(const D3DDDIARG_CREATERESOURCE2& data)
|
||||||
|
: D3DDDIARG_CREATERESOURCE2(data)
|
||||||
|
{
|
||||||
|
surfaceData.reserve(data.SurfCount);
|
||||||
|
for (UINT i = 0; i < data.SurfCount; ++i)
|
||||||
|
{
|
||||||
|
surfaceData.push_back(data.pSurfList[i]);
|
||||||
|
}
|
||||||
|
pSurfList = surfaceData.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Data::Data(const Data& other)
|
||||||
|
: D3DDDIARG_CREATERESOURCE2(other)
|
||||||
|
, surfaceData(other.surfaceData)
|
||||||
|
{
|
||||||
|
pSurfList = surfaceData.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Data& Resource::Data::operator=(const Data& other)
|
||||||
|
{
|
||||||
|
static_cast<D3DDDIARG_CREATERESOURCE2&>(*this) = other;
|
||||||
|
surfaceData = other.surfaceData;
|
||||||
|
pSurfList = surfaceData.data();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Resource(Device& device, const D3DDDIARG_CREATERESOURCE& data)
|
||||||
|
: Resource(device, upgradeResourceData(data))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Resource(Device& device, const D3DDDIARG_CREATERESOURCE2& data)
|
||||||
|
: m_device(device)
|
||||||
|
, m_handle(nullptr)
|
||||||
|
, m_origData(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Resource::blt(D3DDDIARG_BLT data)
|
||||||
|
{
|
||||||
|
if (isOversized())
|
||||||
|
{
|
||||||
|
return splitBlt(data, data.DstSubResourceIndex, data.DstRect, data.SrcRect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto& resources = m_device.getResources();
|
||||||
|
auto it = resources.find(data.hSrcResource);
|
||||||
|
if (it != resources.end() && it->second.isOversized())
|
||||||
|
{
|
||||||
|
return it->second.splitBlt(data, data.SrcSubResourceIndex, data.SrcRect, data.DstRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_device.getOrigVtable().pfnBlt(m_device, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg>
|
||||||
|
Resource Resource::create(Device& device, Arg& data, HRESULT(APIENTRY *createResourceFunc)(HANDLE, Arg*))
|
||||||
|
{
|
||||||
|
Resource resource(device, data);
|
||||||
|
Arg origData = data;
|
||||||
|
auto& baseData = reinterpret_cast<D3DDDIARG_CREATERESOURCE&>(data);
|
||||||
|
fixResourceData(device, baseData);
|
||||||
|
resource.m_fixedData = data;
|
||||||
|
|
||||||
|
HRESULT result = createResourceFunc(device, &data);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
data = origData;
|
||||||
|
throw HResultException(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.Flags.RenderTarget && !data.Flags.Primary && isVidMemPool(data.Pool))
|
||||||
|
{
|
||||||
|
device.addRenderTargetResource(baseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
resource.m_handle = data.hResource;
|
||||||
|
data = origData;
|
||||||
|
data.hResource = resource.m_handle;
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource Resource::create(Device& device, D3DDDIARG_CREATERESOURCE& data)
|
||||||
|
{
|
||||||
|
return create(device, data, device.getOrigVtable().pfnCreateResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource Resource::create(Device& device, D3DDDIARG_CREATERESOURCE2& data)
|
||||||
|
{
|
||||||
|
return create(device, data, device.getOrigVtable().pfnCreateResource2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Resource::isOversized() const
|
||||||
|
{
|
||||||
|
return m_fixedData.SurfCount != m_origData.SurfCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Resource::lock(D3DDDIARG_LOCK& data)
|
||||||
|
{
|
||||||
|
if (isOversized())
|
||||||
|
{
|
||||||
|
if (0 != data.SubResourceIndex ||
|
||||||
|
data.Flags.RangeValid || data.Flags.AreaValid || data.Flags.BoxValid)
|
||||||
|
{
|
||||||
|
LOG_ONCE("WARNING: Unsupported lock of oversized resource: " << data);
|
||||||
|
return m_device.getOrigVtable().pfnLock(m_device, &data);
|
||||||
|
}
|
||||||
|
return splitLock(data, m_device.getOrigVtable().pfnLock);
|
||||||
|
}
|
||||||
|
return m_device.getOrigVtable().pfnLock(m_device, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Resource::splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect)
|
||||||
|
{
|
||||||
|
LOG_FUNC("Resource::splitBlt", data, subResourceIndex, rect, otherRect);
|
||||||
|
|
||||||
|
if (0 != subResourceIndex ||
|
||||||
|
data.SrcRect.right - data.SrcRect.left != data.DstRect.right - data.DstRect.left ||
|
||||||
|
data.SrcRect.bottom - data.SrcRect.top != data.DstRect.bottom - data.DstRect.top ||
|
||||||
|
data.Flags.MirrorLeftRight ||
|
||||||
|
data.Flags.MirrorUpDown ||
|
||||||
|
data.Flags.Rotate)
|
||||||
|
{
|
||||||
|
LOG_ONCE("WARNING: Unsupported blt of oversized resource: " << data);
|
||||||
|
return LOG_RESULT(m_device.getOrigVtable().pfnBlt(m_device, &data));
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& caps = m_device.getAdapter().getD3dExtendedCaps();
|
||||||
|
const auto tilesPerRow = divCeil(m_origData.pSurfList[0].Width, caps.dwMaxTextureWidth);
|
||||||
|
|
||||||
|
const RECT origRect = rect;
|
||||||
|
const POINT otherRectOffset = { otherRect.left - rect.left, otherRect.top - rect.top };
|
||||||
|
|
||||||
|
POINT tilePos = {};
|
||||||
|
tilePos.y = rect.top / static_cast<LONG>(caps.dwMaxTextureHeight);
|
||||||
|
|
||||||
|
RECT tileRect = {};
|
||||||
|
tileRect.top = tilePos.y * caps.dwMaxTextureHeight;
|
||||||
|
tileRect.bottom = tileRect.top + caps.dwMaxTextureHeight;
|
||||||
|
|
||||||
|
while (tileRect.top < origRect.bottom)
|
||||||
|
{
|
||||||
|
tilePos.x = origRect.left / static_cast<LONG>(caps.dwMaxTextureWidth);
|
||||||
|
tileRect.left = tilePos.x * caps.dwMaxTextureWidth;
|
||||||
|
tileRect.right = tileRect.left + caps.dwMaxTextureWidth;
|
||||||
|
|
||||||
|
while (tileRect.left < origRect.right)
|
||||||
|
{
|
||||||
|
IntersectRect(&rect, &tileRect, &origRect);
|
||||||
|
otherRect = rect;
|
||||||
|
OffsetRect(&otherRect, otherRectOffset.x, otherRectOffset.y);
|
||||||
|
OffsetRect(&rect, -tileRect.left, -tileRect.top);
|
||||||
|
subResourceIndex = tilePos.y * tilesPerRow + tilePos.x;
|
||||||
|
|
||||||
|
HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
return LOG_RESULT(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
++tilePos.x;
|
||||||
|
tileRect.left += caps.dwMaxTextureWidth;
|
||||||
|
tileRect.right += caps.dwMaxTextureWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
++tilePos.y;
|
||||||
|
tileRect.top += caps.dwMaxTextureHeight;
|
||||||
|
tileRect.bottom += caps.dwMaxTextureHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LOG_RESULT(S_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg>
|
||||||
|
HRESULT Resource::splitLock(Arg& data, HRESULT(APIENTRY *lockFunc)(HANDLE, Arg*))
|
||||||
|
{
|
||||||
|
LOG_FUNC("Resource::splitLock", data, lockFunc);
|
||||||
|
std::remove_const<Arg>::type tmpData = data;
|
||||||
|
HRESULT result = lockFunc(m_device, &data);
|
||||||
|
if (SUCCEEDED(result))
|
||||||
|
{
|
||||||
|
for (UINT i = 1; i < m_fixedData.SurfCount; ++i)
|
||||||
|
{
|
||||||
|
tmpData.SubResourceIndex = i;
|
||||||
|
lockFunc(m_device, &tmpData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LOG_RESULT(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Resource::unlock(const D3DDDIARG_UNLOCK& data)
|
||||||
|
{
|
||||||
|
if (isOversized())
|
||||||
|
{
|
||||||
|
if (0 != data.SubResourceIndex)
|
||||||
|
{
|
||||||
|
LOG_ONCE("WARNING: Unsupported unlock of oversized resource: " << data);
|
||||||
|
return m_device.getOrigVtable().pfnUnlock(m_device, &data);
|
||||||
|
}
|
||||||
|
return splitLock(data, m_device.getOrigVtable().pfnUnlock);
|
||||||
|
}
|
||||||
|
return m_device.getOrigVtable().pfnUnlock(m_device, &data);
|
||||||
|
}
|
||||||
|
}
|
56
DDrawCompat/D3dDdi/Resource.h
Normal file
56
DDrawCompat/D3dDdi/Resource.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <d3d.h>
|
||||||
|
#include <d3dumddi.h>
|
||||||
|
|
||||||
|
namespace D3dDdi
|
||||||
|
{
|
||||||
|
class Device;
|
||||||
|
|
||||||
|
class Resource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Resource create(Device& device, D3DDDIARG_CREATERESOURCE& data);
|
||||||
|
static Resource create(Device& device, D3DDDIARG_CREATERESOURCE2& data);
|
||||||
|
|
||||||
|
operator HANDLE() const { return m_handle; }
|
||||||
|
|
||||||
|
HRESULT blt(D3DDDIARG_BLT data);
|
||||||
|
HRESULT lock(D3DDDIARG_LOCK& data);
|
||||||
|
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Data : public D3DDDIARG_CREATERESOURCE2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Data();
|
||||||
|
Data(const D3DDDIARG_CREATERESOURCE& data);
|
||||||
|
Data(const D3DDDIARG_CREATERESOURCE2& data);
|
||||||
|
Data(const Data& other);
|
||||||
|
Data& operator=(const Data& other);
|
||||||
|
Data(Data&&) = default;
|
||||||
|
Data& operator=(Data&&) = default;
|
||||||
|
|
||||||
|
std::vector<D3DDDI_SURFACEINFO> surfaceData;
|
||||||
|
};
|
||||||
|
|
||||||
|
Resource(Device& device, const D3DDDIARG_CREATERESOURCE& data);
|
||||||
|
Resource(Device& device, const D3DDDIARG_CREATERESOURCE2& data);
|
||||||
|
|
||||||
|
template <typename Arg>
|
||||||
|
static Resource create(Device& device, Arg& data, HRESULT(APIENTRY *createResourceFunc)(HANDLE, Arg*));
|
||||||
|
|
||||||
|
bool isOversized() const;
|
||||||
|
HRESULT splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect);
|
||||||
|
|
||||||
|
template <typename Arg>
|
||||||
|
HRESULT splitLock(Arg& data, HRESULT(APIENTRY *lockFunc)(HANDLE, Arg*));
|
||||||
|
|
||||||
|
Device& m_device;
|
||||||
|
HANDLE m_handle;
|
||||||
|
Data m_origData;
|
||||||
|
Data m_fixedData;
|
||||||
|
};
|
||||||
|
}
|
@ -123,7 +123,9 @@ namespace
|
|||||||
|
|
||||||
if (!backBufferDc)
|
if (!backBufferDc)
|
||||||
{
|
{
|
||||||
|
D3dDdi::KernelModeThunks::setDcFormatOverride(D3DDDIFMT_X8R8G8B8);
|
||||||
backBuffer->GetDC(backBuffer, &backBufferDc);
|
backBuffer->GetDC(backBuffer, &backBufferDc);
|
||||||
|
D3dDdi::KernelModeThunks::setDcFormatOverride(D3DDDIFMT_UNKNOWN);
|
||||||
if (!backBufferDc)
|
if (!backBufferDc)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -234,6 +234,7 @@
|
|||||||
<ClInclude Include="Common\CompatVtableInstance.h" />
|
<ClInclude Include="Common\CompatVtableInstance.h" />
|
||||||
<ClInclude Include="Common\CompatWeakPtr.h" />
|
<ClInclude Include="Common\CompatWeakPtr.h" />
|
||||||
<ClInclude Include="Common\FuncNameVisitor.h" />
|
<ClInclude Include="Common\FuncNameVisitor.h" />
|
||||||
|
<ClInclude Include="Common\HResultException.h" />
|
||||||
<ClInclude Include="Common\Log.h" />
|
<ClInclude Include="Common\Log.h" />
|
||||||
<ClInclude Include="Common\LogWrapperVisitor.h" />
|
<ClInclude Include="Common\LogWrapperVisitor.h" />
|
||||||
<ClInclude Include="Common\VtableHookVisitor.h" />
|
<ClInclude Include="Common\VtableHookVisitor.h" />
|
||||||
@ -256,8 +257,8 @@
|
|||||||
<ClInclude Include="D3dDdi\Log\DeviceCallbacksLog.h" />
|
<ClInclude Include="D3dDdi\Log\DeviceCallbacksLog.h" />
|
||||||
<ClInclude Include="D3dDdi\Log\DeviceFuncsLog.h" />
|
<ClInclude Include="D3dDdi\Log\DeviceFuncsLog.h" />
|
||||||
<ClInclude Include="D3dDdi\Log\KernelModeThunksLog.h" />
|
<ClInclude Include="D3dDdi\Log\KernelModeThunksLog.h" />
|
||||||
<ClInclude Include="D3dDdi\OversizedResource.h" />
|
|
||||||
<ClInclude Include="D3dDdi\RenderTargetResource.h" />
|
<ClInclude Include="D3dDdi\RenderTargetResource.h" />
|
||||||
|
<ClInclude Include="D3dDdi\Resource.h" />
|
||||||
<ClInclude Include="D3dDdi\ScopedCriticalSection.h" />
|
<ClInclude Include="D3dDdi\ScopedCriticalSection.h" />
|
||||||
<ClInclude Include="D3dDdi\Visitors\AdapterCallbacksVisitor.h" />
|
<ClInclude Include="D3dDdi\Visitors\AdapterCallbacksVisitor.h" />
|
||||||
<ClInclude Include="D3dDdi\Visitors\AdapterFuncsVisitor.h" />
|
<ClInclude Include="D3dDdi\Visitors\AdapterFuncsVisitor.h" />
|
||||||
@ -333,8 +334,8 @@
|
|||||||
<ClCompile Include="D3dDdi\Log\DeviceCallbacksLog.cpp" />
|
<ClCompile Include="D3dDdi\Log\DeviceCallbacksLog.cpp" />
|
||||||
<ClCompile Include="D3dDdi\Log\DeviceFuncsLog.cpp" />
|
<ClCompile Include="D3dDdi\Log\DeviceFuncsLog.cpp" />
|
||||||
<ClCompile Include="D3dDdi\Log\KernelModeThunksLog.cpp" />
|
<ClCompile Include="D3dDdi\Log\KernelModeThunksLog.cpp" />
|
||||||
<ClCompile Include="D3dDdi\OversizedResource.cpp" />
|
|
||||||
<ClCompile Include="D3dDdi\RenderTargetResource.cpp" />
|
<ClCompile Include="D3dDdi\RenderTargetResource.cpp" />
|
||||||
|
<ClCompile Include="D3dDdi\Resource.cpp" />
|
||||||
<ClCompile Include="D3dDdi\ScopedCriticalSection.cpp" />
|
<ClCompile Include="D3dDdi\ScopedCriticalSection.cpp" />
|
||||||
<ClCompile Include="DDraw\ActivateAppHandler.cpp" />
|
<ClCompile Include="DDraw\ActivateAppHandler.cpp" />
|
||||||
<ClCompile Include="DDraw\DirectDraw.cpp" />
|
<ClCompile Include="DDraw\DirectDraw.cpp" />
|
||||||
|
@ -285,9 +285,6 @@
|
|||||||
<ClInclude Include="D3dDdi\Log\KernelModeThunksLog.h">
|
<ClInclude Include="D3dDdi\Log\KernelModeThunksLog.h">
|
||||||
<Filter>Header Files\D3dDdi\Log</Filter>
|
<Filter>Header Files\D3dDdi\Log</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="D3dDdi\OversizedResource.h">
|
|
||||||
<Filter>Header Files\D3dDdi</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="DDraw\Visitors\DirectDrawClipperVtblVisitor.h">
|
<ClInclude Include="DDraw\Visitors\DirectDrawClipperVtblVisitor.h">
|
||||||
<Filter>Header Files\DDraw\Visitors</Filter>
|
<Filter>Header Files\DDraw\Visitors</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -348,6 +345,12 @@
|
|||||||
<ClInclude Include="D3dDdi\Adapter.h">
|
<ClInclude Include="D3dDdi\Adapter.h">
|
||||||
<Filter>Header Files\D3dDdi</Filter>
|
<Filter>Header Files\D3dDdi</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="D3dDdi\Resource.h">
|
||||||
|
<Filter>Header Files\D3dDdi</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Common\HResultException.h">
|
||||||
|
<Filter>Header Files\Common</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Gdi\Gdi.cpp">
|
<ClCompile Include="Gdi\Gdi.cpp">
|
||||||
@ -491,9 +494,6 @@
|
|||||||
<ClCompile Include="D3dDdi\Log\KernelModeThunksLog.cpp">
|
<ClCompile Include="D3dDdi\Log\KernelModeThunksLog.cpp">
|
||||||
<Filter>Source Files\D3dDdi\Log</Filter>
|
<Filter>Source Files\D3dDdi\Log</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="D3dDdi\OversizedResource.cpp">
|
|
||||||
<Filter>Source Files\D3dDdi</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="DDraw\DirectDrawClipper.cpp">
|
<ClCompile Include="DDraw\DirectDrawClipper.cpp">
|
||||||
<Filter>Source Files\DDraw</Filter>
|
<Filter>Source Files\DDraw</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -530,6 +530,9 @@
|
|||||||
<ClCompile Include="D3dDdi\Adapter.cpp">
|
<ClCompile Include="D3dDdi\Adapter.cpp">
|
||||||
<Filter>Source Files\D3dDdi</Filter>
|
<Filter>Source Files\D3dDdi</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="D3dDdi\Resource.cpp">
|
||||||
|
<Filter>Source Files\D3dDdi</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Dll\DDrawCompat.def">
|
<None Include="Dll\DDrawCompat.def">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user