mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Aggregate render target locks
This commit is contained in:
parent
60c3c4f153
commit
39d148e3ba
347
DDrawCompat/D3dDdi/Device.cpp
Normal file
347
DDrawCompat/D3dDdi/Device.cpp
Normal file
@ -0,0 +1,347 @@
|
||||
#include "D3dDdi/AdapterFuncs.h"
|
||||
#include "D3dDdi/Device.h"
|
||||
#include "D3dDdi/DeviceFuncs.h"
|
||||
#include "D3dDdi/KernelModeThunks.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
D3DDDI_RESOURCEFLAGS getResourceTypeFlags();
|
||||
|
||||
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
|
||||
|
||||
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
|
||||
{
|
||||
UINT getBytesPerPixel(D3DDDIFORMAT format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case D3DDDIFMT_A8:
|
||||
case D3DDDIFMT_P8:
|
||||
return 1;
|
||||
|
||||
case D3DDDIFMT_R5G6B5:
|
||||
case D3DDDIFMT_X1R5G5B5:
|
||||
case D3DDDIFMT_A1R5G5B5:
|
||||
case D3DDDIFMT_A8P8:
|
||||
return 2;
|
||||
|
||||
case D3DDDIFMT_R8G8B8:
|
||||
return 3;
|
||||
|
||||
case D3DDDIFMT_A8R8G8B8:
|
||||
case D3DDDIFMT_X8R8G8B8:
|
||||
case D3DDDIFMT_A8B8G8R8:
|
||||
case D3DDDIFMT_X8B8G8R8:
|
||||
return 4;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Device::Device(HANDLE adapter, HANDLE device)
|
||||
: m_origVtable(&DeviceFuncs::s_origVtables.at(device))
|
||||
, m_adapter(adapter)
|
||||
, m_device(device)
|
||||
, m_sharedPrimary(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT Device::blt(const D3DDDIARG_BLT& data)
|
||||
{
|
||||
prepareForRendering(data.hSrcResource, data.SrcSubResourceIndex);
|
||||
prepareForRendering(data.hDstResource, data.DstSubResourceIndex);
|
||||
|
||||
auto it = m_oversizedResources.find(data.hSrcResource);
|
||||
if (it != m_oversizedResources.end())
|
||||
{
|
||||
return it->second.bltFrom(data);
|
||||
}
|
||||
|
||||
it = m_oversizedResources.find(data.hDstResource);
|
||||
if (it != m_oversizedResources.end())
|
||||
{
|
||||
return it->second.bltTo(data);
|
||||
}
|
||||
|
||||
return m_origVtable->pfnBlt(m_device, &data);
|
||||
}
|
||||
|
||||
HRESULT Device::clear(const D3DDDIARG_CLEAR& data, UINT numRect, const RECT* rect)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable->pfnClear(m_device, &data, numRect, rect);
|
||||
}
|
||||
|
||||
HRESULT Device::colorFill(const D3DDDIARG_COLORFILL& data)
|
||||
{
|
||||
prepareForRendering(data.hResource, data.SubResourceIndex);
|
||||
return m_origVtable->pfnColorFill(m_device, &data);
|
||||
}
|
||||
|
||||
template <typename CreateResourceArg, typename CreateResourceFunc>
|
||||
HRESULT Device::createOversizedResource(
|
||||
CreateResourceArg& data,
|
||||
CreateResourceFunc origCreateResource,
|
||||
const D3DNTHAL_D3DEXTENDEDCAPS& caps)
|
||||
{
|
||||
D3DDDI_SURFACEINFO compatSurfaceInfo = data.pSurfList[0];
|
||||
if (0 != caps.dwMaxTextureWidth && compatSurfaceInfo.Width > caps.dwMaxTextureWidth)
|
||||
{
|
||||
compatSurfaceInfo.Width = caps.dwMaxTextureWidth;
|
||||
}
|
||||
if (0 != caps.dwMaxTextureHeight && compatSurfaceInfo.Height > caps.dwMaxTextureHeight)
|
||||
{
|
||||
compatSurfaceInfo.Height = caps.dwMaxTextureHeight;
|
||||
}
|
||||
|
||||
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(m_adapter, m_device, 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 &&
|
||||
m_adapter)
|
||||
{
|
||||
const auto& caps = AdapterFuncs::getD3dExtendedCaps(m_adapter);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT result = origCreateResource(m_device, &data);
|
||||
if (SUCCEEDED(result) && data.Flags.RenderTarget && !data.Flags.Primary && isVidMemPool(data.Pool))
|
||||
{
|
||||
m_renderTargetResources.emplace(data.hResource,
|
||||
RenderTargetResource(m_device, data.hResource, data.Format, data.SurfCount));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT Device::createResource(D3DDDIARG_CREATERESOURCE& data)
|
||||
{
|
||||
return createResourceImpl(data, m_origVtable->pfnCreateResource);
|
||||
}
|
||||
|
||||
HRESULT Device::createResource2(D3DDDIARG_CREATERESOURCE2& data)
|
||||
{
|
||||
return createResourceImpl(data, m_origVtable->pfnCreateResource2);
|
||||
}
|
||||
|
||||
HRESULT Device::destroyResource(HANDLE resource)
|
||||
{
|
||||
if (resource == m_sharedPrimary)
|
||||
{
|
||||
KernelModeThunks::releaseVidPnSources();
|
||||
}
|
||||
|
||||
HRESULT result = m_origVtable->pfnDestroyResource(m_device, resource);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
m_oversizedResources.erase(resource);
|
||||
m_renderTargetResources.erase(resource);
|
||||
m_lockedRenderTargetResources.erase(resource);
|
||||
|
||||
if (resource == m_sharedPrimary)
|
||||
{
|
||||
m_sharedPrimary = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT Device::drawIndexedPrimitive(const D3DDDIARG_DRAWINDEXEDPRIMITIVE& data)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable->pfnDrawIndexedPrimitive(m_device, &data);
|
||||
}
|
||||
|
||||
HRESULT Device::drawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2& data,
|
||||
UINT indicesSize, const void* indexBuffer, const UINT* flagBuffer)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable->pfnDrawIndexedPrimitive2(m_device, &data, indicesSize, indexBuffer, flagBuffer);
|
||||
}
|
||||
|
||||
HRESULT Device::drawPrimitive(const D3DDDIARG_DRAWPRIMITIVE& data, const UINT* flagBuffer)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable->pfnDrawPrimitive(m_device, &data, flagBuffer);
|
||||
}
|
||||
|
||||
HRESULT Device::drawPrimitive2(const D3DDDIARG_DRAWPRIMITIVE2& data)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable->pfnDrawPrimitive2(m_device, &data);
|
||||
}
|
||||
|
||||
HRESULT Device::drawRectPatch(const D3DDDIARG_DRAWRECTPATCH& data, const D3DDDIRECTPATCH_INFO* info,
|
||||
const FLOAT* patch)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable->pfnDrawRectPatch(m_device, &data, info, patch);
|
||||
}
|
||||
|
||||
HRESULT Device::drawTriPatch(const D3DDDIARG_DRAWTRIPATCH& data, const D3DDDITRIPATCH_INFO* info,
|
||||
const FLOAT* patch)
|
||||
{
|
||||
prepareForRendering();
|
||||
return m_origVtable->pfnDrawTriPatch(m_device, &data, info, patch);
|
||||
}
|
||||
|
||||
HRESULT Device::lock(D3DDDIARG_LOCK& data)
|
||||
{
|
||||
auto it = m_renderTargetResources.find(data.hResource);
|
||||
if (it != m_renderTargetResources.end())
|
||||
{
|
||||
HRESULT result = it->second.lock(data);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
m_lockedRenderTargetResources.emplace(it->first, it->second);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return m_origVtable->pfnLock(m_device, &data);
|
||||
}
|
||||
|
||||
HRESULT Device::openResource(D3DDDIARG_OPENRESOURCE& data)
|
||||
{
|
||||
HRESULT result = m_origVtable->pfnOpenResource(m_device, &data);
|
||||
if (SUCCEEDED(result) && data.Flags.Fullscreen)
|
||||
{
|
||||
m_sharedPrimary = data.hResource;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT Device::present(const D3DDDIARG_PRESENT& data)
|
||||
{
|
||||
prepareForRendering(data.hSrcResource, data.SrcSubResourceIndex);
|
||||
return m_origVtable->pfnPresent(m_device, &data);
|
||||
}
|
||||
|
||||
HRESULT Device::present1(D3DDDIARG_PRESENT1& data)
|
||||
{
|
||||
for (UINT i = 0; i < data.SrcResources; ++i)
|
||||
{
|
||||
prepareForRendering(data.phSrcResources[i].hResource, data.phSrcResources[i].SubResourceIndex);
|
||||
}
|
||||
return m_origVtable->pfnPresent1(m_device, &data);
|
||||
}
|
||||
|
||||
HRESULT Device::texBlt(const D3DDDIARG_TEXBLT& data)
|
||||
{
|
||||
prepareForRendering(data.hDstResource);
|
||||
prepareForRendering(data.hSrcResource);
|
||||
return m_origVtable->pfnTexBlt(m_device, &data);
|
||||
}
|
||||
|
||||
HRESULT Device::texBlt1(const D3DDDIARG_TEXBLT1& data)
|
||||
{
|
||||
prepareForRendering(data.hDstResource);
|
||||
prepareForRendering(data.hSrcResource);
|
||||
return m_origVtable->pfnTexBlt1(m_device, &data);
|
||||
}
|
||||
|
||||
HRESULT Device::unlock(const D3DDDIARG_UNLOCK& data)
|
||||
{
|
||||
auto it = m_renderTargetResources.find(data.hResource);
|
||||
if (it != m_renderTargetResources.end())
|
||||
{
|
||||
return it->second.unlock(data);
|
||||
}
|
||||
return m_origVtable->pfnUnlock(m_device, &data);
|
||||
}
|
||||
|
||||
HRESULT Device::updateWInfo(const D3DDDIARG_WINFO& data)
|
||||
{
|
||||
if (1.0f == data.WNear && 1.0f == data.WFar)
|
||||
{
|
||||
D3DDDIARG_WINFO wInfo = {};
|
||||
wInfo.WNear = 0.0f;
|
||||
wInfo.WFar = 1.0f;
|
||||
return m_origVtable->pfnUpdateWInfo(m_device, &wInfo);
|
||||
}
|
||||
return m_origVtable->pfnUpdateWInfo(m_device, &data);
|
||||
}
|
||||
|
||||
void Device::prepareForRendering(RenderTargetResource& resource, UINT subResourceIndex)
|
||||
{
|
||||
resource.prepareForRendering(subResourceIndex);
|
||||
if (!resource.hasLockedSubResources())
|
||||
{
|
||||
m_lockedRenderTargetResources.erase(resource.getHandle());
|
||||
}
|
||||
}
|
||||
|
||||
void Device::prepareForRendering(HANDLE resource, UINT subResourceIndex)
|
||||
{
|
||||
auto it = m_lockedRenderTargetResources.find(resource);
|
||||
if (it != m_lockedRenderTargetResources.end())
|
||||
{
|
||||
prepareForRendering(it->second, subResourceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void Device::prepareForRendering()
|
||||
{
|
||||
auto it = m_lockedRenderTargetResources.begin();
|
||||
while (it != m_lockedRenderTargetResources.end())
|
||||
{
|
||||
prepareForRendering((it++)->second);
|
||||
}
|
||||
}
|
||||
}
|
71
DDrawCompat/D3dDdi/Device.h
Normal file
71
DDrawCompat/D3dDdi/Device.h
Normal file
@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <d3d.h>
|
||||
#include <d3dnthal.h>
|
||||
#include <d3dumddi.h>
|
||||
|
||||
#include "D3dDdi/OversizedResource.h"
|
||||
#include "D3dDdi/RenderTargetResource.h"
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
UINT getBytesPerPixel(D3DDDIFORMAT format);
|
||||
|
||||
class Device
|
||||
{
|
||||
public:
|
||||
Device(HANDLE adapter, HANDLE device);
|
||||
|
||||
HRESULT blt(const D3DDDIARG_BLT& data);
|
||||
HRESULT clear(const D3DDDIARG_CLEAR& data, UINT numRect, const RECT* rect);
|
||||
HRESULT colorFill(const D3DDDIARG_COLORFILL& data);
|
||||
HRESULT createResource(D3DDDIARG_CREATERESOURCE& data);
|
||||
HRESULT createResource2(D3DDDIARG_CREATERESOURCE2& data);
|
||||
HRESULT destroyResource(HANDLE resource);
|
||||
HRESULT drawIndexedPrimitive(const D3DDDIARG_DRAWINDEXEDPRIMITIVE& data);
|
||||
HRESULT drawIndexedPrimitive2(const D3DDDIARG_DRAWINDEXEDPRIMITIVE2& data,
|
||||
UINT indicesSize, const void* indexBuffer, const UINT* flagBuffer);
|
||||
HRESULT drawPrimitive(const D3DDDIARG_DRAWPRIMITIVE& data, const UINT* flagBuffer);
|
||||
HRESULT drawPrimitive2(const D3DDDIARG_DRAWPRIMITIVE2& data);
|
||||
HRESULT drawRectPatch(const D3DDDIARG_DRAWRECTPATCH& data, const D3DDDIRECTPATCH_INFO* info,
|
||||
const FLOAT* patch);
|
||||
HRESULT drawTriPatch(const D3DDDIARG_DRAWTRIPATCH& data, const D3DDDITRIPATCH_INFO* info,
|
||||
const FLOAT* patch);
|
||||
HRESULT lock(D3DDDIARG_LOCK& data);
|
||||
HRESULT openResource(D3DDDIARG_OPENRESOURCE& data);
|
||||
HRESULT present(const D3DDDIARG_PRESENT& data);
|
||||
HRESULT present1(D3DDDIARG_PRESENT1& data);
|
||||
HRESULT texBlt(const D3DDDIARG_TEXBLT& data);
|
||||
HRESULT texBlt1(const D3DDDIARG_TEXBLT1& data);
|
||||
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
|
||||
HRESULT updateWInfo(const D3DDDIARG_WINFO& data);
|
||||
|
||||
void prepareForRendering(HANDLE resource, UINT subResourceIndex = UINT_MAX);
|
||||
void prepareForRendering();
|
||||
|
||||
private:
|
||||
template <typename CreateResourceArg, typename CreateResourceFunc>
|
||||
HRESULT createOversizedResource(
|
||||
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);
|
||||
|
||||
const D3DDDI_DEVICEFUNCS* m_origVtable;
|
||||
HANDLE m_adapter;
|
||||
HANDLE m_device;
|
||||
std::map<HANDLE, OversizedResource> m_oversizedResources;
|
||||
std::map<HANDLE, RenderTargetResource> m_renderTargetResources;
|
||||
std::map<HANDLE, RenderTargetResource&> m_lockedRenderTargetResources;
|
||||
HANDLE m_sharedPrimary;
|
||||
};
|
||||
}
|
@ -1,461 +1,77 @@
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
#include "D3dDdi/AdapterFuncs.h"
|
||||
#include "D3dDdi/Device.h"
|
||||
#include "D3dDdi/DeviceFuncs.h"
|
||||
#include "D3dDdi/LockResource.h"
|
||||
#include "D3dDdi/KernelModeThunks.h"
|
||||
#include "D3dDdi/OversizedResource.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Resource
|
||||
std::map<HANDLE, D3dDdi::Device> g_devices;
|
||||
|
||||
D3dDdi::Device& getDevice(HANDLE device)
|
||||
{
|
||||
HANDLE device;
|
||||
HANDLE resource;
|
||||
|
||||
Resource() : device(nullptr), resource(nullptr) {}
|
||||
Resource(HANDLE device, HANDLE resource) : device(device), resource(resource) {}
|
||||
|
||||
bool operator<(const Resource& rhs) const
|
||||
auto it = g_devices.find(device);
|
||||
if (it != g_devices.end())
|
||||
{
|
||||
return device < rhs.device || (device == rhs.device && resource < rhs.resource);
|
||||
return it->second;
|
||||
}
|
||||
};
|
||||
|
||||
class ResourceReplacer
|
||||
{
|
||||
public:
|
||||
ResourceReplacer(HANDLE device, const HANDLE& resource, UINT subResourceIndex);
|
||||
~ResourceReplacer();
|
||||
|
||||
D3dDdi::LockResource::SubResource* getSubResource() const { return m_subResource; }
|
||||
|
||||
private:
|
||||
HANDLE& m_resource;
|
||||
HANDLE m_origResource;
|
||||
D3dDdi::LockResource::SubResource* m_subResource;
|
||||
};
|
||||
|
||||
D3DDDI_DEVICEFUNCS& getOrigVtable(HANDLE device);
|
||||
D3DDDI_RESOURCEFLAGS getResourceTypeFlags();
|
||||
bool isVidMemPool(D3DDDI_POOL pool);
|
||||
D3dDdi::LockResource::SubResource* replaceWithActiveResource(
|
||||
HANDLE device, HANDLE& resource, UINT subResourceIndex);
|
||||
|
||||
std::map<HANDLE, HANDLE> g_deviceToAdapter;
|
||||
std::map<Resource, D3dDdi::LockResource> g_lockResources;
|
||||
std::map<Resource, D3dDdi::OversizedResource> g_oversizedResources;
|
||||
std::map<HANDLE, D3dDdi::LockResource::SubResource*> g_renderTargets;
|
||||
Resource g_sharedPrimary;
|
||||
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
|
||||
|
||||
ResourceReplacer::ResourceReplacer(HANDLE device, const HANDLE& resource, UINT subResourceIndex)
|
||||
: m_resource(const_cast<HANDLE&>(resource))
|
||||
, m_origResource(resource)
|
||||
{
|
||||
m_subResource = replaceWithActiveResource(device, m_resource, subResourceIndex);
|
||||
return g_devices.emplace(device, D3dDdi::Device(nullptr, device)).first->second;
|
||||
}
|
||||
|
||||
ResourceReplacer::~ResourceReplacer()
|
||||
template <typename DeviceMethodPtr, DeviceMethodPtr deviceMethod, typename Arg, typename... Params>
|
||||
HRESULT WINAPI deviceFunc(HANDLE device, Arg* data, Params... params)
|
||||
{
|
||||
m_resource = m_origResource;
|
||||
}
|
||||
|
||||
template <typename CreateResourceArg, typename CreateResourceFunc>
|
||||
HRESULT createOversizedResource(HANDLE device, CreateResourceArg& resourceData,
|
||||
CreateResourceFunc origCreateResource, const D3DNTHAL_D3DEXTENDEDCAPS& caps)
|
||||
{
|
||||
D3DDDI_SURFACEINFO compatSurfaceInfo = resourceData.pSurfList[0];
|
||||
if (0 != caps.dwMaxTextureWidth && compatSurfaceInfo.Width > caps.dwMaxTextureWidth)
|
||||
{
|
||||
compatSurfaceInfo.Width = caps.dwMaxTextureWidth;
|
||||
}
|
||||
if (0 != caps.dwMaxTextureHeight && compatSurfaceInfo.Height > caps.dwMaxTextureHeight)
|
||||
{
|
||||
compatSurfaceInfo.Height = caps.dwMaxTextureHeight;
|
||||
}
|
||||
|
||||
const D3DDDI_SURFACEINFO* origSurfList = resourceData.pSurfList;
|
||||
resourceData.pSurfList = &compatSurfaceInfo;
|
||||
HRESULT result = origCreateResource(device, &resourceData);
|
||||
resourceData.pSurfList = origSurfList;
|
||||
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
auto it = g_deviceToAdapter.find(device);
|
||||
if (it != g_deviceToAdapter.end())
|
||||
{
|
||||
D3dDdi::OversizedResource oversizedResource(
|
||||
it->second, device, resourceData.Format, origSurfList[0]);
|
||||
g_oversizedResources[Resource(device, resourceData.hResource)] = oversizedResource;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename CreateResourceArg, typename CreateResourceFunc>
|
||||
HRESULT createResource(HANDLE device, CreateResourceArg* resourceData,
|
||||
CreateResourceFunc origCreateResource)
|
||||
{
|
||||
const bool isOffScreenPlain = 0 == (resourceData->Flags.Value & g_resourceTypeFlags);
|
||||
if (D3DDDIPOOL_SYSTEMMEM == resourceData->Pool &&
|
||||
(isOffScreenPlain || resourceData->Flags.Texture) &&
|
||||
D3dDdi::OversizedResource::isSupportedFormat(resourceData->Format) &&
|
||||
1 == resourceData->SurfCount)
|
||||
{
|
||||
auto it = g_deviceToAdapter.find(device);
|
||||
if (it != g_deviceToAdapter.end())
|
||||
{
|
||||
const auto& caps = D3dDdi::AdapterFuncs::getD3dExtendedCaps(it->second);
|
||||
const auto& surfaceInfo = resourceData->pSurfList[0];
|
||||
if (0 != caps.dwMaxTextureWidth && surfaceInfo.Width > caps.dwMaxTextureWidth ||
|
||||
0 != caps.dwMaxTextureHeight && surfaceInfo.Height > caps.dwMaxTextureHeight)
|
||||
{
|
||||
return createOversizedResource(device, *resourceData, origCreateResource, caps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE origResourceHandle = resourceData->hResource;
|
||||
HRESULT result = origCreateResource(device, resourceData);
|
||||
if (SUCCEEDED(result) && resourceData->Flags.RenderTarget && !resourceData->Flags.Primary &&
|
||||
isVidMemPool(resourceData->Pool))
|
||||
{
|
||||
CreateResourceArg lockResourceData = {};
|
||||
lockResourceData.Format = resourceData->Format;
|
||||
lockResourceData.Pool = resourceData->Pool;
|
||||
lockResourceData.pSurfList = resourceData->pSurfList;
|
||||
lockResourceData.SurfCount = resourceData->SurfCount;
|
||||
lockResourceData.hResource = origResourceHandle;
|
||||
lockResourceData.Flags.CpuOptimized = 1;
|
||||
|
||||
if (SUCCEEDED(origCreateResource(device, &lockResourceData)))
|
||||
{
|
||||
g_lockResources.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(device, resourceData->hResource),
|
||||
std::forward_as_tuple(device, resourceData->hResource, lockResourceData.hResource,
|
||||
lockResourceData.pSurfList, lockResourceData.SurfCount));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
D3DDDI_DEVICEFUNCS& getOrigVtable(HANDLE device)
|
||||
{
|
||||
return D3dDdi::DeviceFuncs::s_origVtables.at(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;
|
||||
}
|
||||
|
||||
HRESULT renderFunc(HANDLE device, std::function<HRESULT()> origFunc)
|
||||
{
|
||||
auto it = g_renderTargets.find(device);
|
||||
if (it != g_renderTargets.end())
|
||||
{
|
||||
it->second->updateOrig();
|
||||
}
|
||||
|
||||
HRESULT result = origFunc();
|
||||
if (SUCCEEDED(result) && it != g_renderTargets.end())
|
||||
{
|
||||
it->second->m_isLockUpToDate = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
D3dDdi::LockResource::SubResource* replaceWithActiveResource(
|
||||
HANDLE device, HANDLE& resource, UINT subResourceIndex)
|
||||
{
|
||||
auto it = g_lockResources.find(Resource(device, resource));
|
||||
if (it == g_lockResources.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto& subResource = it->second.getSubResource(subResourceIndex);
|
||||
if (subResource.m_isLockUpToDate)
|
||||
{
|
||||
resource = it->second.getHandle();
|
||||
}
|
||||
return &subResource;
|
||||
}
|
||||
|
||||
HRESULT APIENTRY blt(HANDLE hDevice, const D3DDDIARG_BLT* pData)
|
||||
{
|
||||
ResourceReplacer srcReplacer(hDevice, pData->hSrcResource, pData->SrcSubResourceIndex);
|
||||
ResourceReplacer dstReplacer(hDevice, pData->hDstResource, pData->DstSubResourceIndex);
|
||||
auto dstSubResource = dstReplacer.getSubResource();
|
||||
|
||||
HRESULT result = S_OK;
|
||||
auto it = g_oversizedResources.find(Resource(hDevice, pData->hSrcResource));
|
||||
if (it != g_oversizedResources.end())
|
||||
{
|
||||
result = it->second.bltFrom(*pData);
|
||||
}
|
||||
else
|
||||
{
|
||||
it = g_oversizedResources.find(Resource(hDevice, pData->hDstResource));
|
||||
if (it != g_oversizedResources.end())
|
||||
{
|
||||
result = it->second.bltTo(*pData);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = getOrigVtable(hDevice).pfnBlt(hDevice, pData);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(result) && dstSubResource && dstSubResource->m_isLockUpToDate)
|
||||
{
|
||||
dstSubResource->m_isOrigUpToDate = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT APIENTRY colorFill(HANDLE hDevice, const D3DDDIARG_COLORFILL* pData)
|
||||
{
|
||||
ResourceReplacer replacer(hDevice, pData->hResource, pData->SubResourceIndex);
|
||||
auto subResource = replacer.getSubResource();
|
||||
|
||||
HRESULT result = getOrigVtable(hDevice).pfnColorFill(hDevice, pData);
|
||||
if (SUCCEEDED(result) && subResource && subResource->m_isLockUpToDate)
|
||||
{
|
||||
subResource->m_isOrigUpToDate = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT APIENTRY createResource(HANDLE hDevice, D3DDDIARG_CREATERESOURCE* pResource)
|
||||
{
|
||||
return createResource(hDevice, pResource, getOrigVtable(hDevice).pfnCreateResource);
|
||||
}
|
||||
|
||||
HRESULT APIENTRY createResource2(HANDLE hDevice, D3DDDIARG_CREATERESOURCE2* pResource2)
|
||||
{
|
||||
return createResource(hDevice, pResource2, getOrigVtable(hDevice).pfnCreateResource2);
|
||||
return (getDevice(device).*deviceMethod)(*data, params...);
|
||||
}
|
||||
|
||||
HRESULT APIENTRY destroyDevice(HANDLE hDevice)
|
||||
{
|
||||
HRESULT result = getOrigVtable(hDevice).pfnDestroyDevice(hDevice);
|
||||
HRESULT result = D3dDdi::DeviceFuncs::s_origVtables.at(hDevice).pfnDestroyDevice(hDevice);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
D3dDdi::DeviceFuncs::s_origVtables.erase(hDevice);
|
||||
g_deviceToAdapter.erase(hDevice);
|
||||
g_devices.erase(hDevice);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT APIENTRY destroyResource(HANDLE hDevice, HANDLE hResource)
|
||||
{
|
||||
const bool isSharedPrimary =
|
||||
hDevice == g_sharedPrimary.device && hResource == g_sharedPrimary.resource;
|
||||
if (isSharedPrimary)
|
||||
{
|
||||
D3dDdi::KernelModeThunks::releaseVidPnSources();
|
||||
}
|
||||
|
||||
HRESULT result = getOrigVtable(hDevice).pfnDestroyResource(hDevice, hResource);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
auto lockResourceIt = g_lockResources.find(Resource(hDevice, hResource));
|
||||
if (lockResourceIt != g_lockResources.end())
|
||||
{
|
||||
auto renderTarget = g_renderTargets.find(hDevice);
|
||||
if (renderTarget != g_renderTargets.end() &&
|
||||
&renderTarget->second->getParent() == &lockResourceIt->second)
|
||||
{
|
||||
g_renderTargets.erase(hDevice);
|
||||
}
|
||||
|
||||
getOrigVtable(hDevice).pfnDestroyResource(hDevice, lockResourceIt->second.getHandle());
|
||||
g_lockResources.erase(lockResourceIt);
|
||||
}
|
||||
|
||||
auto oversizedResourceIt = g_oversizedResources.find(Resource(hDevice, hResource));
|
||||
if (oversizedResourceIt != g_oversizedResources.end())
|
||||
{
|
||||
g_oversizedResources.erase(oversizedResourceIt);
|
||||
}
|
||||
|
||||
if (isSharedPrimary)
|
||||
{
|
||||
g_sharedPrimary = {};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT APIENTRY lock(HANDLE hDevice, D3DDDIARG_LOCK* pData)
|
||||
{
|
||||
auto it = g_lockResources.find(Resource(hDevice, pData->hResource));
|
||||
if (it != g_lockResources.end())
|
||||
{
|
||||
auto& subResource = it->second.getSubResource(pData->SubResourceIndex);
|
||||
subResource.updateLock();
|
||||
|
||||
HANDLE origResourceHandle = pData->hResource;
|
||||
pData->hResource = it->second.getHandle();
|
||||
HRESULT result = getOrigVtable(hDevice).pfnLock(hDevice, pData);
|
||||
pData->hResource = origResourceHandle;
|
||||
|
||||
if (SUCCEEDED(result) && !pData->Flags.ReadOnly)
|
||||
{
|
||||
subResource.m_isOrigUpToDate = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return getOrigVtable(hDevice).pfnLock(hDevice, pData);
|
||||
}
|
||||
|
||||
HRESULT APIENTRY openResource(HANDLE hDevice, D3DDDIARG_OPENRESOURCE* pResource)
|
||||
{
|
||||
HRESULT result = getOrigVtable(hDevice).pfnOpenResource(hDevice, pResource);
|
||||
if (SUCCEEDED(result) && pResource->Flags.Fullscreen)
|
||||
{
|
||||
g_sharedPrimary = Resource(hDevice, pResource->hResource);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT APIENTRY present(HANDLE hDevice, const D3DDDIARG_PRESENT* pData)
|
||||
{
|
||||
auto it = g_lockResources.find(Resource(hDevice, pData->hSrcResource));
|
||||
if (it != g_lockResources.end())
|
||||
{
|
||||
it->second.getSubResource(pData->SrcSubResourceIndex).updateOrig();
|
||||
}
|
||||
return getOrigVtable(hDevice).pfnPresent(hDevice, pData);
|
||||
}
|
||||
|
||||
HRESULT APIENTRY present1(HANDLE hDevice, D3DDDIARG_PRESENT1* pPresentData)
|
||||
{
|
||||
for (UINT i = 0; i < pPresentData->SrcResources; ++i)
|
||||
{
|
||||
auto it = g_lockResources.find(Resource(hDevice, pPresentData->phSrcResources[i].hResource));
|
||||
if (it != g_lockResources.end())
|
||||
{
|
||||
it->second.getSubResource(pPresentData->phSrcResources[i].SubResourceIndex).updateOrig();
|
||||
}
|
||||
}
|
||||
return getOrigVtable(hDevice).pfnPresent1(hDevice, pPresentData);
|
||||
}
|
||||
|
||||
template <typename DeviceFuncMemberPtr, DeviceFuncMemberPtr origFunc, typename... Params>
|
||||
HRESULT WINAPI renderFunc(HANDLE device, Params... params)
|
||||
{
|
||||
return renderFunc(device,
|
||||
[=]() { return (getOrigVtable(device).*origFunc)(device, params...); });
|
||||
}
|
||||
|
||||
HRESULT APIENTRY setRenderTarget(HANDLE hDevice, const D3DDDIARG_SETRENDERTARGET* pData)
|
||||
{
|
||||
HRESULT result = getOrigVtable(hDevice).pfnSetRenderTarget(hDevice, pData);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
auto it = g_lockResources.find(Resource(hDevice, pData->hRenderTarget));
|
||||
if (it != g_lockResources.end())
|
||||
{
|
||||
g_renderTargets[hDevice] = &it->second.getSubResource(pData->SubResourceIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_renderTargets.erase(hDevice);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT APIENTRY unlock(HANDLE hDevice, const D3DDDIARG_UNLOCK* pData)
|
||||
{
|
||||
auto it = g_lockResources.find(Resource(hDevice, pData->hResource));
|
||||
if (it != g_lockResources.end())
|
||||
{
|
||||
HANDLE origResource = pData->hResource;
|
||||
const_cast<HANDLE&>(pData->hResource) = it->second.getHandle();
|
||||
HRESULT result = getOrigVtable(hDevice).pfnUnlock(hDevice, pData);
|
||||
const_cast<HANDLE&>(pData->hResource) = origResource;
|
||||
return result;
|
||||
}
|
||||
return getOrigVtable(hDevice).pfnUnlock(hDevice, pData);
|
||||
}
|
||||
|
||||
HRESULT APIENTRY updateWInfo(HANDLE hDevice, const D3DDDIARG_WINFO* pData)
|
||||
{
|
||||
if (pData && 1.0f == pData->WNear && 1.0f == pData->WFar)
|
||||
{
|
||||
D3DDDIARG_WINFO wInfo = {};
|
||||
wInfo.WNear = 0.0f;
|
||||
wInfo.WFar = 1.0f;
|
||||
return getOrigVtable(hDevice).pfnUpdateWInfo(hDevice, &wInfo);
|
||||
}
|
||||
return getOrigVtable(hDevice).pfnUpdateWInfo(hDevice, pData);
|
||||
return getDevice(hDevice).destroyResource(hResource);
|
||||
}
|
||||
}
|
||||
|
||||
#define RENDER_FUNC(func) renderFunc<decltype(&D3DDDI_DEVICEFUNCS::func), &D3DDDI_DEVICEFUNCS::func>
|
||||
#define DEVICE_FUNC(func) deviceFunc<decltype(&Device::func), &Device::func>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
void DeviceFuncs::onCreateDevice(HANDLE adapter, HANDLE device)
|
||||
{
|
||||
g_deviceToAdapter[device] = adapter;
|
||||
g_devices.emplace(device, Device(adapter, device));
|
||||
}
|
||||
|
||||
void DeviceFuncs::setCompatVtable(D3DDDI_DEVICEFUNCS& vtable)
|
||||
{
|
||||
vtable.pfnBlt = &blt;
|
||||
vtable.pfnClear = &RENDER_FUNC(pfnClear);
|
||||
vtable.pfnColorFill = &colorFill;
|
||||
vtable.pfnCreateResource = &createResource;
|
||||
vtable.pfnCreateResource2 = &createResource2;
|
||||
vtable.pfnBlt = &DEVICE_FUNC(blt);
|
||||
vtable.pfnClear = &DEVICE_FUNC(clear);
|
||||
vtable.pfnColorFill = &DEVICE_FUNC(colorFill);
|
||||
vtable.pfnCreateResource = &DEVICE_FUNC(createResource);
|
||||
vtable.pfnCreateResource2 = &DEVICE_FUNC(createResource2);
|
||||
vtable.pfnDestroyDevice = &destroyDevice;
|
||||
vtable.pfnDestroyResource = &destroyResource;
|
||||
vtable.pfnDrawIndexedPrimitive = &RENDER_FUNC(pfnDrawIndexedPrimitive);
|
||||
vtable.pfnDrawIndexedPrimitive2 = &RENDER_FUNC(pfnDrawIndexedPrimitive2);
|
||||
vtable.pfnDrawPrimitive = &RENDER_FUNC(pfnDrawPrimitive);
|
||||
vtable.pfnDrawPrimitive2 = &RENDER_FUNC(pfnDrawPrimitive2);
|
||||
vtable.pfnDrawRectPatch = &RENDER_FUNC(pfnDrawRectPatch);
|
||||
vtable.pfnDrawTriPatch = &RENDER_FUNC(pfnDrawTriPatch);
|
||||
vtable.pfnLock = &lock;
|
||||
vtable.pfnOpenResource = &openResource;
|
||||
vtable.pfnPresent = &present;
|
||||
vtable.pfnPresent1 = &present1;
|
||||
vtable.pfnSetRenderTarget = &setRenderTarget;
|
||||
vtable.pfnUnlock = &unlock;
|
||||
vtable.pfnUpdateWInfo = &updateWInfo;
|
||||
vtable.pfnDrawIndexedPrimitive = &DEVICE_FUNC(drawIndexedPrimitive);
|
||||
vtable.pfnDrawIndexedPrimitive2 = &DEVICE_FUNC(drawIndexedPrimitive2);
|
||||
vtable.pfnDrawPrimitive = &DEVICE_FUNC(drawPrimitive);
|
||||
vtable.pfnDrawPrimitive2 = &DEVICE_FUNC(drawPrimitive2);
|
||||
vtable.pfnDrawRectPatch = &DEVICE_FUNC(drawRectPatch);
|
||||
vtable.pfnDrawTriPatch = &DEVICE_FUNC(drawTriPatch);
|
||||
vtable.pfnLock = &DEVICE_FUNC(lock);
|
||||
vtable.pfnOpenResource = &DEVICE_FUNC(openResource);
|
||||
vtable.pfnPresent = &DEVICE_FUNC(present);
|
||||
vtable.pfnPresent1 = &DEVICE_FUNC(present1);
|
||||
vtable.pfnTexBlt = &DEVICE_FUNC(texBlt);
|
||||
vtable.pfnTexBlt1 = &DEVICE_FUNC(texBlt1);
|
||||
vtable.pfnUnlock = &DEVICE_FUNC(unlock);
|
||||
vtable.pfnUpdateWInfo = &DEVICE_FUNC(updateWInfo);
|
||||
}
|
||||
}
|
||||
|
@ -1,73 +0,0 @@
|
||||
#include "D3dDdi/DeviceFuncs.h"
|
||||
#include "D3dDdi/LockResource.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
D3DDDI_DEVICEFUNCS& getOrigVtable(HANDLE device)
|
||||
{
|
||||
return D3dDdi::DeviceFuncs::s_origVtables.at(device);
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
LockResource::LockResource(HANDLE device, HANDLE origResource, HANDLE lockResource,
|
||||
const D3DDDI_SURFACEINFO* surfaceInfo, UINT surfaceInfoCount)
|
||||
: m_device(device)
|
||||
, m_origResource(origResource)
|
||||
, m_lockResource(lockResource)
|
||||
{
|
||||
for (UINT i = 0; i < surfaceInfoCount; ++i)
|
||||
{
|
||||
m_subResources.emplace_back(*this, i, surfaceInfo[i].Width, surfaceInfo[i].Height);
|
||||
}
|
||||
}
|
||||
|
||||
LockResource::~LockResource()
|
||||
{
|
||||
}
|
||||
|
||||
LockResource::SubResource::SubResource(LockResource& parent, UINT index, UINT width, UINT height)
|
||||
: m_isOrigUpToDate(true)
|
||||
, m_isLockUpToDate(true)
|
||||
, m_parent(&parent)
|
||||
, m_index(index)
|
||||
, m_width(width)
|
||||
, m_height(height)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT LockResource::SubResource::blt(HANDLE dstResource, HANDLE srcResource)
|
||||
{
|
||||
RECT rect = { 0, 0, static_cast<LONG>(m_width), static_cast<LONG>(m_height) };
|
||||
|
||||
D3DDDIARG_BLT bltData = {};
|
||||
bltData.hSrcResource = srcResource;
|
||||
bltData.SrcSubResourceIndex = m_index;
|
||||
bltData.SrcRect = rect;
|
||||
bltData.hDstResource = dstResource;
|
||||
bltData.DstSubResourceIndex = m_index;
|
||||
bltData.DstRect = rect;
|
||||
bltData.Flags.Point = 1;
|
||||
|
||||
return getOrigVtable(m_parent->m_device).pfnBlt(m_parent->m_device, &bltData);
|
||||
}
|
||||
|
||||
void LockResource::SubResource::updateLock()
|
||||
{
|
||||
if (!m_isLockUpToDate)
|
||||
{
|
||||
blt(m_parent->m_lockResource, m_parent->m_origResource);
|
||||
m_isLockUpToDate = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LockResource::SubResource::updateOrig()
|
||||
{
|
||||
if (!m_isOrigUpToDate)
|
||||
{
|
||||
blt(m_parent->m_origResource, m_parent->m_lockResource);
|
||||
m_isOrigUpToDate = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <d3d.h>
|
||||
#include <d3dumddi.h>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
class LockResource
|
||||
{
|
||||
public:
|
||||
struct SubResource
|
||||
{
|
||||
public:
|
||||
SubResource(LockResource& parent, UINT index, UINT width, UINT height);
|
||||
|
||||
LockResource& getParent() const { return *m_parent; }
|
||||
void updateLock();
|
||||
void updateOrig();
|
||||
|
||||
bool m_isOrigUpToDate;
|
||||
bool m_isLockUpToDate;
|
||||
|
||||
private:
|
||||
HRESULT blt(HANDLE dstResource, HANDLE srcResource);
|
||||
|
||||
LockResource* m_parent;
|
||||
UINT m_index;
|
||||
UINT m_width;
|
||||
UINT m_height;
|
||||
};
|
||||
|
||||
LockResource(HANDLE device, HANDLE origResource, HANDLE lockResource,
|
||||
const D3DDDI_SURFACEINFO* surfaceInfo, UINT surfaceInfoCount);
|
||||
~LockResource();
|
||||
LockResource(const LockResource&) = delete;
|
||||
|
||||
HANDLE getHandle() const { return m_lockResource; }
|
||||
SubResource& getSubResource(UINT index) { return m_subResources[index]; }
|
||||
|
||||
private:
|
||||
HANDLE m_device;
|
||||
HANDLE m_origResource;
|
||||
HANDLE m_lockResource;
|
||||
std::vector<SubResource> m_subResources;
|
||||
};
|
||||
}
|
@ -1,43 +1,10 @@
|
||||
#include "D3dDdi/AdapterFuncs.h"
|
||||
#include "D3dDdi/Device.h"
|
||||
#include "D3dDdi/DeviceFuncs.h"
|
||||
#include "D3dDdi/OversizedResource.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
UINT getBytesPerPixel(D3DDDIFORMAT format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case D3DDDIFMT_R5G6B5:
|
||||
case D3DDDIFMT_X1R5G5B5:
|
||||
case D3DDDIFMT_A1R5G5B5:
|
||||
return 2;
|
||||
|
||||
case D3DDDIFMT_R8G8B8:
|
||||
return 3;
|
||||
|
||||
case D3DDDIFMT_A8R8G8B8:
|
||||
case D3DDDIFMT_X8R8G8B8:
|
||||
case D3DDDIFMT_A8B8G8R8:
|
||||
case D3DDDIFMT_X8B8G8R8:
|
||||
return 4;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
OversizedResource::OversizedResource()
|
||||
: m_adapter(nullptr)
|
||||
, m_device(nullptr)
|
||||
, m_format(D3DDDIFMT_UNKNOWN)
|
||||
, m_surfaceInfo()
|
||||
{
|
||||
}
|
||||
|
||||
OversizedResource::OversizedResource(
|
||||
HANDLE adapter, HANDLE device, D3DDDIFORMAT format, const D3DDDI_SURFACEINFO& surfaceInfo)
|
||||
: m_adapter(adapter)
|
||||
|
@ -10,7 +10,6 @@ namespace D3dDdi
|
||||
class OversizedResource
|
||||
{
|
||||
public:
|
||||
OversizedResource();
|
||||
OversizedResource(HANDLE adapter, HANDLE device,
|
||||
D3DDDIFORMAT format, const D3DDDI_SURFACEINFO& surfaceInfo);
|
||||
|
||||
|
106
DDrawCompat/D3dDdi/RenderTargetResource.cpp
Normal file
106
DDrawCompat/D3dDdi/RenderTargetResource.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include "D3dDdi/Device.h"
|
||||
#include "D3dDdi/DeviceFuncs.h"
|
||||
#include "D3dDdi/RenderTargetResource.h"
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
RenderTargetResource::RenderTargetResource(
|
||||
HANDLE device, HANDLE resource, D3DDDIFORMAT format, UINT surfaceCount)
|
||||
: m_device(device)
|
||||
, m_resource(resource)
|
||||
, m_bytesPerPixel(getBytesPerPixel(format))
|
||||
, m_subResources(surfaceCount, SubResource(*this))
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT RenderTargetResource::lock(D3DDDIARG_LOCK& data)
|
||||
{
|
||||
if (data.SubResourceIndex >= m_subResources.size())
|
||||
{
|
||||
return D3dDdi::DeviceFuncs::s_origVtables.at(m_device).pfnLock(m_device, &data);
|
||||
}
|
||||
|
||||
auto& subResource = m_subResources[data.SubResourceIndex];
|
||||
if (subResource.surfacePtr)
|
||||
{
|
||||
auto surfacePtr = static_cast<unsigned char*>(subResource.surfacePtr);
|
||||
if (data.Flags.AreaValid)
|
||||
{
|
||||
surfacePtr += data.Area.top * subResource.pitch + data.Area.left * m_bytesPerPixel;
|
||||
}
|
||||
data.pSurfData = surfacePtr;
|
||||
data.Pitch = subResource.pitch;
|
||||
subResource.isLocked = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
const UINT origFlags = data.Flags.Value;
|
||||
data.Flags.Value = 0;
|
||||
const HRESULT result = D3dDdi::DeviceFuncs::s_origVtables.at(m_device).pfnLock(m_device, &data);
|
||||
data.Flags.Value = origFlags;
|
||||
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
subResource.surfacePtr = data.pSurfData;
|
||||
subResource.pitch = data.Pitch;
|
||||
subResource.isLocked = true;
|
||||
m_lockedSubResources.insert(data.SubResourceIndex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT RenderTargetResource::unlock(const D3DDDIARG_UNLOCK& data)
|
||||
{
|
||||
if (data.SubResourceIndex >= m_subResources.size())
|
||||
{
|
||||
return D3dDdi::DeviceFuncs::s_origVtables.at(m_device).pfnUnlock(m_device, &data);
|
||||
}
|
||||
|
||||
m_subResources[data.SubResourceIndex].isLocked = false;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void RenderTargetResource::prepareForRendering(UINT subResourceIndex)
|
||||
{
|
||||
if (UINT_MAX == subResourceIndex)
|
||||
{
|
||||
auto it = m_lockedSubResources.begin();
|
||||
while (it != m_lockedSubResources.end())
|
||||
{
|
||||
prepareSubResourceForRendering(*(it++));
|
||||
}
|
||||
}
|
||||
|
||||
if (subResourceIndex >= m_subResources.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
prepareSubResourceForRendering(subResourceIndex);
|
||||
}
|
||||
|
||||
void RenderTargetResource::prepareSubResourceForRendering(UINT subResourceIndex)
|
||||
{
|
||||
auto& subResource = m_subResources[subResourceIndex];
|
||||
if (subResource.surfacePtr && !subResource.isLocked)
|
||||
{
|
||||
D3DDDIARG_UNLOCK data = {};
|
||||
data.hResource = m_resource;
|
||||
data.SubResourceIndex = subResourceIndex;
|
||||
D3dDdi::DeviceFuncs::s_origVtables.at(m_device).pfnUnlock(m_device, &data);
|
||||
|
||||
subResource.surfacePtr = nullptr;
|
||||
subResource.pitch = 0;
|
||||
m_lockedSubResources.erase(subResourceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
RenderTargetResource::SubResource::SubResource(RenderTargetResource& parent)
|
||||
: parent(parent)
|
||||
, surfacePtr(nullptr)
|
||||
, pitch(0)
|
||||
, isLocked(false)
|
||||
{
|
||||
}
|
||||
}
|
44
DDrawCompat/D3dDdi/RenderTargetResource.h
Normal file
44
DDrawCompat/D3dDdi/RenderTargetResource.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
#include <d3d.h>
|
||||
#include <d3dumddi.h>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
class RenderTargetResource
|
||||
{
|
||||
public:
|
||||
RenderTargetResource(HANDLE device, HANDLE resource, D3DDDIFORMAT format, UINT surfaceCount);
|
||||
|
||||
HRESULT lock(D3DDDIARG_LOCK& data);
|
||||
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
|
||||
|
||||
HANDLE getHandle() const { return m_resource; }
|
||||
bool hasLockedSubResources() { return !m_lockedSubResources.empty(); }
|
||||
void prepareForRendering(UINT subResourceIndex = UINT_MAX);
|
||||
|
||||
private:
|
||||
struct SubResource
|
||||
{
|
||||
RenderTargetResource& parent;
|
||||
void* surfacePtr;
|
||||
UINT pitch;
|
||||
bool isLocked;
|
||||
|
||||
SubResource(RenderTargetResource& parent);
|
||||
};
|
||||
|
||||
void prepareSubResourceForRendering(UINT subResourceIndex);
|
||||
|
||||
HANDLE m_device;
|
||||
HANDLE m_resource;
|
||||
UINT m_bytesPerPixel;
|
||||
std::vector<SubResource> m_subResources;
|
||||
std::set<UINT> m_lockedSubResources;
|
||||
};
|
||||
}
|
@ -164,16 +164,17 @@
|
||||
<ClInclude Include="Config\Config.h" />
|
||||
<ClInclude Include="D3dDdi\AdapterCallbacks.h" />
|
||||
<ClInclude Include="D3dDdi\AdapterFuncs.h" />
|
||||
<ClInclude Include="D3dDdi\Device.h" />
|
||||
<ClInclude Include="D3dDdi\DeviceCallbacks.h" />
|
||||
<ClInclude Include="D3dDdi\DeviceFuncs.h" />
|
||||
<ClInclude Include="D3dDdi\Hooks.h" />
|
||||
<ClInclude Include="D3dDdi\KernelModeThunks.h" />
|
||||
<ClInclude Include="D3dDdi\LockResource.h" />
|
||||
<ClInclude Include="D3dDdi\Log\AdapterFuncsLog.h" />
|
||||
<ClInclude Include="D3dDdi\Log\DeviceCallbacksLog.h" />
|
||||
<ClInclude Include="D3dDdi\Log\DeviceFuncsLog.h" />
|
||||
<ClInclude Include="D3dDdi\Log\KernelModeThunksLog.h" />
|
||||
<ClInclude Include="D3dDdi\OversizedResource.h" />
|
||||
<ClInclude Include="D3dDdi\RenderTargetResource.h" />
|
||||
<ClInclude Include="D3dDdi\Visitors\AdapterCallbacksVisitor.h" />
|
||||
<ClInclude Include="D3dDdi\Visitors\AdapterFuncsVisitor.h" />
|
||||
<ClInclude Include="D3dDdi\Visitors\DeviceCallbacksVisitor.h" />
|
||||
@ -235,16 +236,17 @@
|
||||
<ClCompile Include="Common\Time.cpp" />
|
||||
<ClCompile Include="D3dDdi\AdapterCallbacks.cpp" />
|
||||
<ClCompile Include="D3dDdi\AdapterFuncs.cpp" />
|
||||
<ClCompile Include="D3dDdi\Device.cpp" />
|
||||
<ClCompile Include="D3dDdi\DeviceCallbacks.cpp" />
|
||||
<ClCompile Include="D3dDdi\DeviceFuncs.cpp" />
|
||||
<ClCompile Include="D3dDdi\Hooks.cpp" />
|
||||
<ClCompile Include="D3dDdi\KernelModeThunks.cpp" />
|
||||
<ClCompile Include="D3dDdi\LockResource.cpp" />
|
||||
<ClCompile Include="D3dDdi\Log\AdapterFuncsLog.cpp" />
|
||||
<ClCompile Include="D3dDdi\Log\DeviceCallbacksLog.cpp" />
|
||||
<ClCompile Include="D3dDdi\Log\DeviceFuncsLog.cpp" />
|
||||
<ClCompile Include="D3dDdi\Log\KernelModeThunksLog.cpp" />
|
||||
<ClCompile Include="D3dDdi\OversizedResource.cpp" />
|
||||
<ClCompile Include="D3dDdi\RenderTargetResource.cpp" />
|
||||
<ClCompile Include="DDraw\ActivateAppHandler.cpp" />
|
||||
<ClCompile Include="DDraw\DirectDraw.cpp" />
|
||||
<ClCompile Include="DDraw\DirectDrawClipper.cpp" />
|
||||
|
@ -282,9 +282,6 @@
|
||||
<ClInclude Include="D3dDdi\Log\DeviceCallbacksLog.h">
|
||||
<Filter>Header Files\D3dDdi\Log</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3dDdi\LockResource.h">
|
||||
<Filter>Header Files\D3dDdi</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3dDdi\Log\AdapterFuncsLog.h">
|
||||
<Filter>Header Files\D3dDdi\Log</Filter>
|
||||
</ClInclude>
|
||||
@ -312,6 +309,12 @@
|
||||
<ClInclude Include="DDraw\DirectDrawGammaControl.h">
|
||||
<Filter>Header Files\DDraw</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3dDdi\RenderTargetResource.h">
|
||||
<Filter>Header Files\D3dDdi</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="D3dDdi\Device.h">
|
||||
<Filter>Header Files\D3dDdi</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -452,9 +455,6 @@
|
||||
<ClCompile Include="D3dDdi\Log\DeviceCallbacksLog.cpp">
|
||||
<Filter>Source Files\D3dDdi\Log</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3dDdi\LockResource.cpp">
|
||||
<Filter>Source Files\D3dDdi</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3dDdi\Log\AdapterFuncsLog.cpp">
|
||||
<Filter>Source Files\D3dDdi\Log</Filter>
|
||||
</ClCompile>
|
||||
@ -476,6 +476,12 @@
|
||||
<ClCompile Include="DDraw\DirectDrawGammaControl.cpp">
|
||||
<Filter>Source Files\DDraw</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3dDdi\RenderTargetResource.cpp">
|
||||
<Filter>Source Files\D3dDdi</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="D3dDdi\Device.cpp">
|
||||
<Filter>Source Files\D3dDdi</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Dll\DDrawCompat.def">
|
||||
|
Loading…
x
Reference in New Issue
Block a user