mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Handle mirroring and color keying via Direct3D
This commit is contained in:
parent
c1e654de7d
commit
436a8184bb
@ -190,9 +190,13 @@ namespace D3dDdi
|
||||
switch (pData->Type)
|
||||
{
|
||||
case D3DDDICAPS_DDRAW:
|
||||
static_cast<DDRAW_CAPS*>(pData->pData)->FxCaps =
|
||||
DDRAW_FXCAPS_BLTMIRRORLEFTRIGHT | DDRAW_FXCAPS_BLTMIRRORUPDOWN;
|
||||
{
|
||||
auto& caps = *static_cast<DDRAW_CAPS*>(pData->pData);
|
||||
caps.Caps |= DDRAW_CAPS_COLORKEY;
|
||||
caps.CKeyCaps = DDRAW_CKEYCAPS_SRCBLT;
|
||||
caps.FxCaps = DDRAW_FXCAPS_BLTMIRRORLEFTRIGHT | DDRAW_FXCAPS_BLTMIRRORUPDOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
case D3DDDICAPS_GETD3D3CAPS:
|
||||
{
|
||||
@ -208,7 +212,7 @@ namespace D3dDdi
|
||||
return result;
|
||||
}
|
||||
|
||||
void Adapter::setRepository(LUID luid, const DDraw::DirectDraw::Repository& repository)
|
||||
void Adapter::setRepository(LUID luid, CompatWeakPtr<IDirectDraw7> repository)
|
||||
{
|
||||
for (auto& adapter : s_adapters)
|
||||
{
|
||||
|
@ -34,8 +34,7 @@ namespace D3dDdi
|
||||
LUID getLuid() const { return m_luid; }
|
||||
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(D3DDDIFORMAT format) const;
|
||||
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
|
||||
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository.repo; }
|
||||
bool isSrcColorKeySupported() const { return m_repository.isSrcColorKeySupported; }
|
||||
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
|
||||
|
||||
HRESULT pfnCloseAdapter();
|
||||
HRESULT pfnCreateDevice(D3DDDIARG_CREATEDEVICE* pCreateData);
|
||||
@ -43,7 +42,7 @@ namespace D3dDdi
|
||||
|
||||
static void add(const D3DDDIARG_OPENADAPTER& data) { s_adapters.emplace(data.hAdapter, data); }
|
||||
static Adapter& get(HANDLE adapter) { return s_adapters.find(adapter)->second; }
|
||||
static void setRepository(LUID luid, const DDraw::DirectDraw::Repository& repository);
|
||||
static void setRepository(LUID luid, CompatWeakPtr<IDirectDraw7> repository);
|
||||
|
||||
private:
|
||||
template <typename Data>
|
||||
@ -58,7 +57,7 @@ namespace D3dDdi
|
||||
UINT m_runtimeVersion;
|
||||
UINT m_driverVersion;
|
||||
LUID m_luid;
|
||||
DDraw::DirectDraw::Repository m_repository;
|
||||
CompatWeakPtr<IDirectDraw7> m_repository;
|
||||
|
||||
static std::map<HANDLE, Adapter> s_adapters;
|
||||
static std::map<LUID, AdapterInfo> s_adapterInfos;
|
||||
|
@ -2,49 +2,33 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ArgbFormatInfo : D3dDdi::FormatInfo
|
||||
struct RgbFormatInfo : D3dDdi::FormatInfo
|
||||
{
|
||||
ArgbFormatInfo(BYTE alphaBitCount, BYTE redBitCount, BYTE greenBitCount, BYTE blueBitCount)
|
||||
: FormatInfo(alphaBitCount, redBitCount, greenBitCount, blueBitCount)
|
||||
RgbFormatInfo(BYTE unusedBitCount, BYTE alphaBitCount, BYTE redBitCount, BYTE greenBitCount, BYTE blueBitCount)
|
||||
: FormatInfo(unusedBitCount, alphaBitCount, redBitCount, greenBitCount, blueBitCount)
|
||||
{
|
||||
redPos = greenBitCount + blueBitCount;
|
||||
greenPos = blueBitCount;
|
||||
}
|
||||
};
|
||||
|
||||
struct AbgrFormatInfo : D3dDdi::FormatInfo
|
||||
struct BgrFormatInfo : D3dDdi::FormatInfo
|
||||
{
|
||||
AbgrFormatInfo(BYTE alphaBitCount, BYTE blueBitCount, BYTE greenBitCount, BYTE redBitCount)
|
||||
: FormatInfo(alphaBitCount, redBitCount, greenBitCount, blueBitCount)
|
||||
BgrFormatInfo(BYTE unusedBitCount, BYTE alphaBitCount, BYTE blueBitCount, BYTE greenBitCount, BYTE redBitCount)
|
||||
: FormatInfo(unusedBitCount, alphaBitCount, redBitCount, greenBitCount, blueBitCount)
|
||||
{
|
||||
bluePos = redBitCount + greenBitCount;
|
||||
greenPos = redBitCount;
|
||||
}
|
||||
};
|
||||
|
||||
struct XrgbFormatInfo : ArgbFormatInfo
|
||||
{
|
||||
XrgbFormatInfo(BYTE unusedBitCount, BYTE redBitCount, BYTE greenBitCount, BYTE blueBitCount)
|
||||
: ArgbFormatInfo(0, redBitCount, greenBitCount, blueBitCount)
|
||||
{
|
||||
bytesPerPixel = (unusedBitCount + redBitCount + greenBitCount + blueBitCount + 7) / 8;
|
||||
}
|
||||
};
|
||||
|
||||
struct XbgrFormatInfo : AbgrFormatInfo
|
||||
{
|
||||
XbgrFormatInfo(BYTE unusedBitCount, BYTE blueBitCount, BYTE greenBitCount, BYTE redBitCount)
|
||||
: AbgrFormatInfo(0, redBitCount, greenBitCount, blueBitCount)
|
||||
{
|
||||
bytesPerPixel = (unusedBitCount + redBitCount + greenBitCount + blueBitCount + 7) / 8;
|
||||
bluePos = redBitCount + greenBitCount;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
FormatInfo::FormatInfo(BYTE alphaBitCount, BYTE redBitCount, BYTE greenBitCount, BYTE blueBitCount)
|
||||
: bytesPerPixel((alphaBitCount + redBitCount + greenBitCount + blueBitCount + 7) / 8)
|
||||
FormatInfo::FormatInfo(BYTE unusedBitCount, BYTE alphaBitCount, BYTE redBitCount, BYTE greenBitCount, BYTE blueBitCount)
|
||||
: bitsPerPixel(unusedBitCount + alphaBitCount + redBitCount + greenBitCount + blueBitCount)
|
||||
, bytesPerPixel((bitsPerPixel + 7) / 8)
|
||||
, unusedBitCount(unusedBitCount)
|
||||
, alphaBitCount(alphaBitCount)
|
||||
, alphaPos(redBitCount + greenBitCount + blueBitCount)
|
||||
, redBitCount(redBitCount)
|
||||
@ -83,29 +67,55 @@ namespace D3dDdi
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case D3DDDIFMT_R3G3B2: return ArgbFormatInfo(0, 3, 3, 2);
|
||||
case D3DDDIFMT_A8: return ArgbFormatInfo(8, 0, 0, 0);
|
||||
case D3DDDIFMT_P8: return ArgbFormatInfo(0, 0, 0, 8);
|
||||
case D3DDDIFMT_R8: return ArgbFormatInfo(0, 8, 0, 0);
|
||||
case D3DDDIFMT_R3G3B2: return RgbFormatInfo(0, 0, 3, 3, 2);
|
||||
case D3DDDIFMT_A8: return RgbFormatInfo(0, 8, 0, 0, 0);
|
||||
case D3DDDIFMT_P8: return RgbFormatInfo(0, 0, 0, 0, 8);
|
||||
case D3DDDIFMT_R8: return RgbFormatInfo(0, 0, 8, 0, 0);
|
||||
|
||||
case D3DDDIFMT_R5G6B5: return ArgbFormatInfo(0, 5, 6, 5);
|
||||
case D3DDDIFMT_X1R5G5B5: return XrgbFormatInfo(1, 5, 5, 5);
|
||||
case D3DDDIFMT_A1R5G5B5: return ArgbFormatInfo(1, 5, 5, 5);
|
||||
case D3DDDIFMT_A4R4G4B4: return ArgbFormatInfo(4, 4, 4, 4);
|
||||
case D3DDDIFMT_A8R3G3B2: return ArgbFormatInfo(8, 3, 3, 2);
|
||||
case D3DDDIFMT_X4R4G4B4: return XrgbFormatInfo(4, 4, 4, 4);
|
||||
case D3DDDIFMT_A8P8: return ArgbFormatInfo(8, 0, 0, 8);
|
||||
case D3DDDIFMT_G8R8: return AbgrFormatInfo(0, 0, 8, 8);
|
||||
case D3DDDIFMT_R5G6B5: return RgbFormatInfo(0, 0, 5, 6, 5);
|
||||
case D3DDDIFMT_X1R5G5B5: return RgbFormatInfo(1, 0, 5, 5, 5);
|
||||
case D3DDDIFMT_A1R5G5B5: return RgbFormatInfo(0, 1, 5, 5, 5);
|
||||
case D3DDDIFMT_A4R4G4B4: return RgbFormatInfo(0, 4, 4, 4, 4);
|
||||
case D3DDDIFMT_A8R3G3B2: return RgbFormatInfo(0, 8, 3, 3, 2);
|
||||
case D3DDDIFMT_X4R4G4B4: return RgbFormatInfo(4, 0, 4, 4, 4);
|
||||
case D3DDDIFMT_A8P8: return RgbFormatInfo(0, 8, 0, 0, 8);
|
||||
case D3DDDIFMT_G8R8: return BgrFormatInfo(0, 0, 0, 8, 8);
|
||||
|
||||
case D3DDDIFMT_R8G8B8: return ArgbFormatInfo(0, 8, 8, 8);
|
||||
case D3DDDIFMT_R8G8B8: return RgbFormatInfo(0, 0, 8, 8, 8);
|
||||
|
||||
case D3DDDIFMT_A8R8G8B8: return ArgbFormatInfo(8, 8, 8, 8);
|
||||
case D3DDDIFMT_X8R8G8B8: return XrgbFormatInfo(8, 8, 8, 8);
|
||||
case D3DDDIFMT_A8B8G8R8: return AbgrFormatInfo(8, 8, 8, 8);
|
||||
case D3DDDIFMT_X8B8G8R8: return XbgrFormatInfo(8, 8, 8, 8);
|
||||
case D3DDDIFMT_A8R8G8B8: return RgbFormatInfo(0, 8, 8, 8, 8);
|
||||
case D3DDDIFMT_X8R8G8B8: return RgbFormatInfo(8, 0, 8, 8, 8);
|
||||
case D3DDDIFMT_A8B8G8R8: return BgrFormatInfo(0, 8, 8, 8, 8);
|
||||
case D3DDDIFMT_X8B8G8R8: return BgrFormatInfo(8, 0, 8, 8, 8);
|
||||
|
||||
default:
|
||||
return FormatInfo();
|
||||
}
|
||||
}
|
||||
|
||||
DDPIXELFORMAT getPixelFormat(D3DDDIFORMAT format)
|
||||
{
|
||||
auto info = getFormatInfo(format);
|
||||
if (0 == info.bytesPerPixel)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
DDPIXELFORMAT pf = {};
|
||||
pf.dwSize = sizeof(pf);
|
||||
pf.dwRGBBitCount = info.bitsPerPixel;
|
||||
if (0 != pf.dwRGBBitCount)
|
||||
{
|
||||
pf.dwFlags = DDPF_RGB;
|
||||
pf.dwRBitMask = (0xFF >> (8 - info.redBitCount)) << info.redPos;
|
||||
pf.dwGBitMask = (0xFF >> (8 - info.greenBitCount)) << info.greenPos;
|
||||
pf.dwBBitMask = (0xFF >> (8 - info.blueBitCount)) << info.bluePos;
|
||||
}
|
||||
if (0 != info.alphaBitCount)
|
||||
{
|
||||
pf.dwFlags |= (0 == pf.dwFlags) ? DDPF_ALPHA : DDPF_ALPHAPIXELS;
|
||||
pf.dwRGBAlphaBitMask = (0xFF >> (8 - info.alphaBitCount)) << info.alphaPos;
|
||||
}
|
||||
return pf;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,9 @@ namespace D3dDdi
|
||||
{
|
||||
struct FormatInfo
|
||||
{
|
||||
BYTE bitsPerPixel;
|
||||
BYTE bytesPerPixel;
|
||||
BYTE unusedBitCount;
|
||||
BYTE alphaBitCount;
|
||||
BYTE alphaPos;
|
||||
BYTE redBitCount;
|
||||
@ -17,9 +19,11 @@ namespace D3dDdi
|
||||
BYTE blueBitCount;
|
||||
BYTE bluePos;
|
||||
|
||||
FormatInfo(BYTE alphaBitCount = 0, BYTE redBitCount = 0, BYTE greenBitCount = 0, BYTE blueBitCount = 0);
|
||||
FormatInfo(BYTE unusedBitCount = 0, BYTE alphaBitCount = 0,
|
||||
BYTE redBitCount = 0, BYTE greenBitCount = 0, BYTE blueBitCount = 0);
|
||||
};
|
||||
|
||||
D3DCOLOR colorConvert(const FormatInfo& dstFormatInfo, D3DCOLOR srcRgbaColor);
|
||||
FormatInfo getFormatInfo(D3DDDIFORMAT format);
|
||||
DDPIXELFORMAT getPixelFormat(D3DDDIFORMAT format);
|
||||
}
|
||||
|
@ -172,6 +172,13 @@ namespace D3dDdi
|
||||
Gdi::Cursor::setEmulated(false);
|
||||
Gdi::Cursor::setMonitorClipRect({});
|
||||
}
|
||||
|
||||
if (m_msaaSurface.surface || m_msaaResolvedSurface.surface)
|
||||
{
|
||||
auto& repo = SurfaceRepository::get(m_device.getAdapter());
|
||||
repo.release(m_msaaSurface);
|
||||
repo.release(m_msaaResolvedSurface);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Resource::blt(D3DDDIARG_BLT data)
|
||||
@ -319,25 +326,32 @@ namespace D3dDdi
|
||||
|
||||
HRESULT Resource::copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex)
|
||||
{
|
||||
LOG_FUNC("Resource::copySubResource", dstResource, srcResource, subResourceIndex);
|
||||
RECT rect = {};
|
||||
rect.right = m_fixedData.pSurfList[subResourceIndex].Width;
|
||||
rect.bottom = m_fixedData.pSurfList[subResourceIndex].Height;
|
||||
|
||||
D3DDDIARG_BLT data = {};
|
||||
data.hSrcResource = srcResource;
|
||||
data.SrcSubResourceIndex = subResourceIndex;
|
||||
data.SrcRect = rect;
|
||||
data.hDstResource = dstResource;
|
||||
data.DstSubResourceIndex = subResourceIndex;
|
||||
data.DstRect = rect;
|
||||
return copySubResourceRegion(dstResource, subResourceIndex, rect, srcResource, subResourceIndex, rect);
|
||||
}
|
||||
|
||||
HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data);
|
||||
HRESULT Resource::copySubResourceRegion(HANDLE dst, UINT dstIndex, const RECT& dstRect,
|
||||
HANDLE src, UINT srcIndex, const RECT& srcRect)
|
||||
{
|
||||
LOG_FUNC("Resource::copySubResourceRegion", dst, dstIndex, dstRect, src, srcIndex, srcRect);
|
||||
D3DDDIARG_BLT data = {};
|
||||
data.hDstResource = dst;
|
||||
data.DstSubResourceIndex = dstIndex;
|
||||
data.DstRect = dstRect;
|
||||
data.hSrcResource = src;
|
||||
data.SrcSubResourceIndex = srcIndex;
|
||||
data.SrcRect = srcRect;
|
||||
data.Flags.Point = 1;
|
||||
|
||||
HRESULT result = LOG_RESULT(m_device.getOrigVtable().pfnBlt(m_device, &data));
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_ONCE("ERROR: Resource::copySubResource failed: " << Compat::hex(result));
|
||||
LOG_ONCE("ERROR: Resource::copySubResourceRegion failed: " << Compat::hex(result));
|
||||
}
|
||||
return LOG_RESULT(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Resource::createGdiLockResource()
|
||||
@ -373,6 +387,7 @@ namespace D3dDdi
|
||||
flags.Value = g_resourceTypeFlags;
|
||||
flags.RenderTarget = 0;
|
||||
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool ||
|
||||
m_isSurfaceRepoResource ||
|
||||
0 == m_formatInfo.bytesPerPixel ||
|
||||
0 != (m_fixedData.Flags.Value & flags.Value))
|
||||
{
|
||||
@ -642,15 +657,16 @@ namespace D3dDdi
|
||||
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
|
||||
}
|
||||
|
||||
void Resource::prepareForBltSrc(const D3DDDIARG_BLT& data)
|
||||
Resource& Resource::prepareForBltSrc(const D3DDDIARG_BLT& data)
|
||||
{
|
||||
if (m_lockResource)
|
||||
{
|
||||
loadVidMemResource(data.SrcSubResourceIndex);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Resource::prepareForBltDst(D3DDDIARG_BLT& data)
|
||||
Resource& Resource::prepareForBltDst(D3DDDIARG_BLT& data)
|
||||
{
|
||||
if (m_lockResource)
|
||||
{
|
||||
@ -659,12 +675,14 @@ namespace D3dDdi
|
||||
data.hDstResource = *m_msaaSurface.resource;
|
||||
clearUpToDateFlags(data.DstSubResourceIndex);
|
||||
m_lockData[data.DstSubResourceIndex].isMsaaUpToDate = true;
|
||||
return *m_msaaSurface.resource;
|
||||
}
|
||||
else if (m_lockData[data.DstSubResourceIndex].isMsaaResolvedUpToDate)
|
||||
{
|
||||
data.hDstResource = *m_msaaResolvedSurface.resource;
|
||||
clearUpToDateFlags(data.DstSubResourceIndex);
|
||||
m_lockData[data.DstSubResourceIndex].isMsaaResolvedUpToDate = true;
|
||||
return *m_msaaResolvedSurface.resource;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -673,6 +691,7 @@ namespace D3dDdi
|
||||
m_lockData[data.DstSubResourceIndex].isVidMemUpToDate = true;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Resource::prepareForCpuRead(UINT subResourceIndex)
|
||||
@ -771,7 +790,7 @@ namespace D3dDdi
|
||||
Config::Settings::DisplayFilter::POINT != presentationFilter)
|
||||
{
|
||||
const auto& si = srcResource->m_fixedData.pSurfList[0];
|
||||
const auto& dst(SurfaceRepository::get(m_device.getAdapter()).getRenderTarget(si.Width, si.Height));
|
||||
const auto& dst(SurfaceRepository::get(m_device.getAdapter()).getTempRenderTarget(si.Width, si.Height));
|
||||
if (!dst.resource)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
@ -791,13 +810,7 @@ namespace D3dDdi
|
||||
}
|
||||
else
|
||||
{
|
||||
D3DDDIARG_BLT blt = {};
|
||||
blt.hSrcResource = data.hSrcResource;
|
||||
blt.SrcRect = data.SrcRect;
|
||||
blt.hDstResource = *dst.resource;
|
||||
blt.DstRect = data.SrcRect;
|
||||
blt.Flags.Point = 1;
|
||||
m_device.getOrigVtable().pfnBlt(m_device, &blt);
|
||||
copySubResourceRegion(*dst.resource, 0, data.SrcRect, data.hSrcResource, 0, data.SrcRect);
|
||||
}
|
||||
|
||||
if (isLayeredPresentNeeded)
|
||||
@ -842,6 +855,97 @@ namespace D3dDdi
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Resource::shaderBlt(D3DDDIARG_BLT& data, Resource& srcResource)
|
||||
{
|
||||
LOG_FUNC("Resource::shaderBlt", data, srcResource);
|
||||
auto& repo = SurfaceRepository::get(m_device.getAdapter());
|
||||
|
||||
Resource* srcRes = &srcResource.prepareForBltSrc(data);
|
||||
UINT srcIndex = data.SrcSubResourceIndex;
|
||||
RECT srcRect = data.SrcRect;
|
||||
|
||||
Resource* dstRes = &prepareForBltDst(data);
|
||||
UINT dstIndex = data.DstSubResourceIndex;
|
||||
RECT dstRect = data.DstRect;
|
||||
|
||||
if (!srcResource.m_fixedData.Flags.Texture)
|
||||
{
|
||||
DWORD width = data.SrcRect.right - data.SrcRect.left;
|
||||
DWORD height = data.SrcRect.bottom - data.SrcRect.top;
|
||||
auto& texture = repo.getTempTexture(width, height, getPixelFormat(srcResource.m_fixedData.Format));
|
||||
if (!texture.resource)
|
||||
{
|
||||
return LOG_RESULT(E_OUTOFMEMORY);
|
||||
}
|
||||
|
||||
srcRes = texture.resource;
|
||||
srcIndex = 0;
|
||||
srcRect = { 0, 0, static_cast<LONG>(width), static_cast<LONG>(height) };
|
||||
|
||||
HRESULT result = copySubResourceRegion(*srcRes, srcIndex, srcRect,
|
||||
data.hSrcResource, data.SrcSubResourceIndex, data.SrcRect);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
|
||||
if (D3DDDIPOOL_SYSTEMMEM == srcResource.m_fixedData.Pool)
|
||||
{
|
||||
srcResource.notifyLock(data.SrcSubResourceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_fixedData.Flags.RenderTarget)
|
||||
{
|
||||
LONG width = data.DstRect.right - data.DstRect.left;
|
||||
LONG height = data.DstRect.bottom - data.DstRect.top;
|
||||
auto& rt = repo.getTempRenderTarget(width, height);
|
||||
if (!rt.resource)
|
||||
{
|
||||
return LOG_RESULT(E_OUTOFMEMORY);
|
||||
}
|
||||
|
||||
dstRes = rt.resource;
|
||||
dstIndex = 0;
|
||||
dstRect = { 0, 0, width, height };
|
||||
|
||||
if (data.Flags.SrcColorKey)
|
||||
{
|
||||
HRESULT result = copySubResourceRegion(*dstRes, dstIndex, dstRect,
|
||||
data.hDstResource, data.DstSubResourceIndex, data.DstRect);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data.Flags.MirrorLeftRight)
|
||||
{
|
||||
std::swap(srcRect.left, srcRect.right);
|
||||
}
|
||||
|
||||
if (data.Flags.MirrorUpDown)
|
||||
{
|
||||
std::swap(srcRect.top, srcRect.bottom);
|
||||
}
|
||||
|
||||
m_device.getShaderBlitter().textureBlt(*dstRes, dstIndex, dstRect, *srcRes, srcIndex, srcRect,
|
||||
D3DTEXF_POINT, data.Flags.SrcColorKey ? &data.ColorKey : nullptr);
|
||||
|
||||
if (!m_fixedData.Flags.RenderTarget)
|
||||
{
|
||||
HRESULT result = copySubResourceRegion(data.hDstResource, data.DstSubResourceIndex, data.DstRect,
|
||||
*dstRes, dstIndex, dstRect);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
}
|
||||
|
||||
return LOG_RESULT(S_OK);
|
||||
}
|
||||
|
||||
HRESULT Resource::splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect)
|
||||
{
|
||||
LOG_FUNC("Resource::splitBlt", data, subResourceIndex, rect, otherRect);
|
||||
@ -942,17 +1046,8 @@ namespace D3dDdi
|
||||
auto now = Time::queryPerformanceCounter();
|
||||
if (D3DDDIFMT_P8 != m_fixedData.Format)
|
||||
{
|
||||
if (data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown ||
|
||||
(data.Flags.SrcColorKey && !m_device.getAdapter().isSrcColorKeySupported()))
|
||||
{
|
||||
dstLockData.qpcLastForcedLock = now;
|
||||
srcLockData.qpcLastForcedLock = now;
|
||||
}
|
||||
else
|
||||
{
|
||||
isSysMemBltPreferred = dstLockData.isSysMemUpToDate &&
|
||||
Time::qpcToMs(now - dstLockData.qpcLastForcedLock) <= Config::evictionTimeout;
|
||||
}
|
||||
isSysMemBltPreferred = dstLockData.isSysMemUpToDate &&
|
||||
Time::qpcToMs(now - dstLockData.qpcLastForcedLock) <= Config::evictionTimeout;
|
||||
}
|
||||
|
||||
if (isSysMemBltPreferred)
|
||||
@ -983,8 +1078,18 @@ namespace D3dDdi
|
||||
}
|
||||
}
|
||||
|
||||
srcResource.prepareForBltSrc(data);
|
||||
prepareForBltDst(data);
|
||||
if (m_fixedData.Flags.RenderTarget || data.Flags.SrcColorKey || data.Flags.MirrorLeftRight || data.Flags.MirrorUpDown)
|
||||
{
|
||||
if (SUCCEEDED(shaderBlt(data, srcResource)))
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
srcResource.prepareForBltSrc(data);
|
||||
prepareForBltDst(data);
|
||||
}
|
||||
|
||||
HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data);
|
||||
if (D3DDDIPOOL_SYSTEMMEM == m_fixedData.Pool)
|
||||
@ -1060,9 +1165,8 @@ namespace D3dDdi
|
||||
}
|
||||
}
|
||||
|
||||
auto& surfaceRepo(SurfaceRepository::get(m_device.getAdapter()));
|
||||
surfaceRepo.release(m_msaaSurface);
|
||||
surfaceRepo.release(m_msaaResolvedSurface);
|
||||
m_msaaSurface = {};
|
||||
m_msaaResolvedSurface = {};
|
||||
|
||||
if (D3DDDIMULTISAMPLE_NONE != msaa.first || m_fixedData.Format != formatConfig)
|
||||
{
|
||||
|
@ -34,8 +34,8 @@ namespace D3dDdi
|
||||
HRESULT colorFill(D3DDDIARG_COLORFILL data);
|
||||
void* getLockPtr(UINT subResourceIndex);
|
||||
HRESULT lock(D3DDDIARG_LOCK& data);
|
||||
void prepareForBltSrc(const D3DDDIARG_BLT& data);
|
||||
void prepareForBltDst(D3DDDIARG_BLT& data);
|
||||
Resource& prepareForBltSrc(const D3DDDIARG_BLT& data);
|
||||
Resource& prepareForBltDst(D3DDDIARG_BLT& data);
|
||||
void prepareForCpuRead(UINT subResourceIndex);
|
||||
void prepareForCpuWrite(UINT subResourceIndex);
|
||||
Resource& prepareForGpuRead(UINT subResourceIndex);
|
||||
@ -74,6 +74,8 @@ namespace D3dDdi
|
||||
void clearUpToDateFlags(UINT subResourceIndex);
|
||||
void clipRect(UINT subResourceIndex, RECT& rect);
|
||||
HRESULT copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex);
|
||||
HRESULT copySubResourceRegion(HANDLE dst, UINT dstIndex, const RECT& dstRect,
|
||||
HANDLE src, UINT srcIndex, const RECT& srcRect);
|
||||
void createGdiLockResource();
|
||||
void createLockResource();
|
||||
void createSysMemResource(const std::vector<D3DDDI_SURFACEINFO>& surfaceInfo);
|
||||
@ -88,6 +90,7 @@ namespace D3dDdi
|
||||
void loadVidMemResource(UINT subResourceIndex);
|
||||
void notifyLock(UINT subResourceIndex);
|
||||
HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource);
|
||||
HRESULT shaderBlt(D3DDDIARG_BLT& data, Resource& srcResource);
|
||||
HRESULT splitBlt(D3DDDIARG_BLT& data, UINT& subResourceIndex, RECT& rect, RECT& otherRect);
|
||||
|
||||
template <typename Arg>
|
||||
|
@ -26,18 +26,18 @@ namespace D3dDdi
|
||||
}
|
||||
|
||||
void ShaderBlitter::blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, const RECT& srcRect, HANDLE pixelShader, UINT filter)
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
HANDLE pixelShader, UINT filter, const UINT* srcColorKey)
|
||||
{
|
||||
LOG_FUNC("ShaderBlitter::blt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
|
||||
static_cast<HANDLE>(srcResource), srcRect, pixelShader, filter);
|
||||
static_cast<HANDLE>(srcResource), srcRect, srcSubResourceIndex, pixelShader, filter, srcColorKey);
|
||||
|
||||
if (!m_vertexShaderDecl || !pixelShader)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
|
||||
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[0];
|
||||
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[srcSubResourceIndex];
|
||||
|
||||
auto& state = m_device.getState();
|
||||
state.setTempRenderState({ D3DDDIRS_SCENECAPTURE, TRUE });
|
||||
@ -45,7 +45,8 @@ namespace D3dDdi
|
||||
state.setTempPixelShader(pixelShader);
|
||||
state.setTempRenderTarget({ 0, dstResource, dstSubResourceIndex });
|
||||
state.setTempDepthStencil({ nullptr });
|
||||
state.setTempViewport({ 0, 0, dstSurface.Width, dstSurface.Height });
|
||||
state.setTempViewport({ static_cast<DWORD>(dstRect.left), static_cast<DWORD>(dstRect.top),
|
||||
static_cast<DWORD>(dstRect.right - dstRect.left), static_cast<DWORD>(dstRect.bottom - dstRect.top) });
|
||||
state.setTempZRange({ 0, 1 });
|
||||
|
||||
state.setTempRenderState({ D3DDDIRS_ZENABLE, D3DZB_FALSE });
|
||||
@ -56,7 +57,7 @@ namespace D3dDdi
|
||||
state.setTempRenderState({ D3DDDIRS_DITHERENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_ALPHABLENDENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_FOGENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_COLORKEYENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_COLORKEYENABLE, nullptr != srcColorKey });
|
||||
state.setTempRenderState({ D3DDDIRS_STENCILENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_CLIPPING, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_CLIPPLANEENABLE, 0 });
|
||||
@ -65,6 +66,10 @@ namespace D3dDdi
|
||||
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, D3DTEXF_LINEAR == filter });
|
||||
|
||||
setTempTextureStage(0, srcResource, filter);
|
||||
if (srcColorKey)
|
||||
{
|
||||
state.setTempTextureStageState({ 0, D3DDDITSS_TEXTURECOLORKEYVAL, *srcColorKey });
|
||||
}
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
@ -82,8 +87,8 @@ namespace D3dDdi
|
||||
Vertex vertices[4] = {
|
||||
{ dstRect.left - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.top / srcHeight },
|
||||
{ dstRect.right - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.top / srcHeight },
|
||||
{ dstRect.right - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.bottom / srcHeight },
|
||||
{ dstRect.left - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.bottom / srcHeight }
|
||||
{ dstRect.left - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.bottom / srcHeight },
|
||||
{ dstRect.right - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.bottom / srcHeight }
|
||||
};
|
||||
|
||||
state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, vertices);
|
||||
@ -91,7 +96,7 @@ namespace D3dDdi
|
||||
DeviceState::TempStateLock lock(state);
|
||||
|
||||
D3DDDIARG_DRAWPRIMITIVE dp = {};
|
||||
dp.PrimitiveType = D3DPT_TRIANGLEFAN;
|
||||
dp.PrimitiveType = D3DPT_TRIANGLESTRIP;
|
||||
dp.VStart = 0;
|
||||
dp.PrimitiveCount = 2;
|
||||
m_device.pfnDrawPrimitive(&dp, nullptr);
|
||||
@ -169,7 +174,8 @@ namespace D3dDdi
|
||||
setTempTextureStage(1, *cur.maskTexture, D3DTEXF_POINT);
|
||||
setTempTextureStage(2, *cur.colorTexture, D3DTEXF_POINT);
|
||||
setTempTextureStage(3, *xorTexture, D3DTEXF_POINT);
|
||||
blt(dstResource, dstSubResourceIndex, clippedDstRect, *cur.tempTexture, clippedSrcRect, m_psDrawCursor.get(), D3DTEXF_POINT);
|
||||
blt(dstResource, dstSubResourceIndex, clippedDstRect, *cur.tempTexture, 0, clippedSrcRect,
|
||||
m_psDrawCursor.get(), D3DTEXF_POINT);
|
||||
}
|
||||
|
||||
void ShaderBlitter::genBilinearBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
@ -177,7 +183,8 @@ namespace D3dDdi
|
||||
{
|
||||
if (100 == blurPercent)
|
||||
{
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psTextureSampler.get(), D3DTEXF_LINEAR);
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect,
|
||||
m_psTextureSampler.get(), D3DTEXF_LINEAR);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -195,7 +202,7 @@ namespace D3dDdi
|
||||
} };
|
||||
|
||||
DeviceState::TempPixelShaderConst tempPsConst(m_device.getState(), { 0, registers.size() }, registers.data());
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psGenBilinear.get(), D3DTEXF_LINEAR);
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psGenBilinear.get(), D3DTEXF_LINEAR);
|
||||
}
|
||||
|
||||
void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
|
||||
@ -231,7 +238,7 @@ namespace D3dDdi
|
||||
const RECT srcRect = { 0, 0, static_cast<LONG>(srcSurface.Width), static_cast<LONG>(srcSurface.Height) };
|
||||
|
||||
setTempTextureStage(1, *paletteTexture, D3DTEXF_POINT);
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcRect, m_psPaletteLookup.get(), D3DTEXF_POINT);
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psPaletteLookup.get(), D3DTEXF_POINT);
|
||||
}
|
||||
|
||||
void ShaderBlitter::setTempTextureStage(UINT stage, HANDLE texture, UINT filter)
|
||||
@ -246,4 +253,12 @@ namespace D3dDdi
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_SRGBTEXTURE, D3DTEXF_LINEAR == filter });
|
||||
state.setTempRenderState({ static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 });
|
||||
}
|
||||
|
||||
void ShaderBlitter::textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
UINT filter, const UINT* srcColorKey)
|
||||
{
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
||||
m_psTextureSampler.get(), filter, srcColorKey);
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,14 @@ namespace D3dDdi
|
||||
const Resource& srcResource, const RECT& srcRect, UINT blurPercent);
|
||||
void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
|
||||
const Resource& srcResource, RGBQUAD palette[256]);
|
||||
void textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
UINT filter, const UINT* srcColorKey = nullptr);
|
||||
|
||||
private:
|
||||
void blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, const RECT& srcRect, HANDLE pixelShader, UINT filter);
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
HANDLE pixelShader, UINT filter, const UINT* srcColorKey = nullptr);
|
||||
|
||||
template <int N>
|
||||
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE(&code)[N])
|
||||
|
@ -28,7 +28,7 @@ namespace D3dDdi
|
||||
{
|
||||
}
|
||||
|
||||
CompatWeakPtr<IDirectDrawSurface7> SurfaceRepository::createSurface(
|
||||
CompatPtr<IDirectDrawSurface7> SurfaceRepository::createSurface(
|
||||
DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount)
|
||||
{
|
||||
auto dd(m_adapter.getRepository());
|
||||
@ -38,6 +38,7 @@ namespace D3dDdi
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_releasedSurfaces.clear();
|
||||
CompatPtr<IDirectDrawSurface7> surface;
|
||||
|
||||
DDSURFACEDESC2 desc = {};
|
||||
@ -62,7 +63,7 @@ namespace D3dDdi
|
||||
LOG_ONCE("ERROR: Failed to create repository surface: " << Compat::hex(result) << " " << desc);
|
||||
return nullptr;
|
||||
}
|
||||
return surface.detach();
|
||||
return surface;
|
||||
}
|
||||
|
||||
SurfaceRepository& SurfaceRepository::get(const Adapter& adapter)
|
||||
@ -108,8 +109,8 @@ namespace D3dDdi
|
||||
if (isLost(m_cursorMaskTexture) || isLost(m_cursorColorTexture))
|
||||
{
|
||||
m_cursor = nullptr;
|
||||
release(m_cursorMaskTexture);
|
||||
release(m_cursorColorTexture);
|
||||
m_cursorMaskTexture = {};
|
||||
m_cursorColorTexture = {};
|
||||
}
|
||||
|
||||
if (cursor != m_cursor)
|
||||
@ -213,19 +214,13 @@ namespace D3dDdi
|
||||
DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY).resource;
|
||||
}
|
||||
|
||||
const SurfaceRepository::Surface& SurfaceRepository::getRenderTarget(DWORD width, DWORD height)
|
||||
{
|
||||
return getSurface(m_renderTarget, width, height, DDraw::DirectDraw::getRgbPixelFormat(32),
|
||||
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
||||
}
|
||||
|
||||
SurfaceRepository::Surface& SurfaceRepository::getSurface(Surface& surface, DWORD width, DWORD height,
|
||||
const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount)
|
||||
{
|
||||
if (surface.surface && (surface.width != width || surface.height != height ||
|
||||
0 != memcmp(&surface.pixelFormat, &pf, sizeof(pf)) || isLost(surface)))
|
||||
{
|
||||
release(surface);
|
||||
surface = {};
|
||||
}
|
||||
|
||||
if (!surface.surface)
|
||||
@ -244,6 +239,23 @@ namespace D3dDdi
|
||||
return surface;
|
||||
}
|
||||
|
||||
const SurfaceRepository::Surface& SurfaceRepository::getTempRenderTarget(DWORD width, DWORD height)
|
||||
{
|
||||
return getTempSurface(m_renderTarget, width, height, DDraw::DirectDraw::getRgbPixelFormat(32),
|
||||
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
||||
}
|
||||
|
||||
SurfaceRepository::Surface& SurfaceRepository::getTempSurface(Surface& surface, DWORD width, DWORD height,
|
||||
const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount)
|
||||
{
|
||||
return getSurface(surface, max(width, surface.width), max(height, surface.height), pf, caps, surfaceCount);
|
||||
}
|
||||
|
||||
const SurfaceRepository::Surface& SurfaceRepository::getTempTexture(DWORD width, DWORD height, const DDPIXELFORMAT& pf)
|
||||
{
|
||||
return getTempSurface(m_textures[pf], width, height, pf, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
||||
}
|
||||
|
||||
bool SurfaceRepository::isLost(Surface& surface)
|
||||
{
|
||||
return !surface.surface || FAILED(surface.surface->IsLost(surface.surface));
|
||||
@ -253,7 +265,7 @@ namespace D3dDdi
|
||||
{
|
||||
if (surface.surface)
|
||||
{
|
||||
surface.surface->Release(surface.surface);
|
||||
m_releasedSurfaces.push_back(surface);
|
||||
surface = {};
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include <Common/CompatWeakPtr.h>
|
||||
#include <Common/CompatPtr.h>
|
||||
#include <DDraw/Comparison.h>
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
@ -16,29 +18,32 @@ namespace D3dDdi
|
||||
public:
|
||||
struct Cursor
|
||||
{
|
||||
HCURSOR cursor;
|
||||
SIZE size;
|
||||
POINT hotspot;
|
||||
Resource* maskTexture;
|
||||
Resource* colorTexture;
|
||||
Resource* tempTexture;
|
||||
HCURSOR cursor = nullptr;
|
||||
SIZE size = {};
|
||||
POINT hotspot = {};
|
||||
Resource* maskTexture = nullptr;
|
||||
Resource* colorTexture = nullptr;
|
||||
Resource* tempTexture = nullptr;
|
||||
};
|
||||
|
||||
struct Surface
|
||||
{
|
||||
CompatWeakPtr<IDirectDrawSurface7> surface;
|
||||
Resource* resource;
|
||||
DWORD width;
|
||||
DWORD height;
|
||||
DDPIXELFORMAT pixelFormat;
|
||||
CompatPtr<IDirectDrawSurface7> surface;
|
||||
Resource* resource = nullptr;
|
||||
DWORD width = 0;
|
||||
DWORD height = 0;
|
||||
DDPIXELFORMAT pixelFormat = {};
|
||||
};
|
||||
|
||||
Cursor getCursor(HCURSOR cursor);
|
||||
Resource* getLogicalXorTexture();
|
||||
Resource* getPaletteTexture();
|
||||
const Surface& getRenderTarget(DWORD width, DWORD height);
|
||||
Surface& getSurface(Surface& surface, DWORD width, DWORD height,
|
||||
const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount = 1);
|
||||
const Surface& getTempRenderTarget(DWORD width, DWORD height);
|
||||
Surface& getTempSurface(Surface& surface, DWORD width, DWORD height,
|
||||
const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount = 1);
|
||||
const Surface& getTempTexture(DWORD width, DWORD height, const DDPIXELFORMAT& pf);
|
||||
void release(Surface& surface);
|
||||
|
||||
static SurfaceRepository& get(const Adapter& adapter);
|
||||
@ -47,7 +52,7 @@ namespace D3dDdi
|
||||
private:
|
||||
SurfaceRepository(const Adapter& adapter);
|
||||
|
||||
CompatWeakPtr<IDirectDrawSurface7> createSurface(DWORD width, DWORD height,
|
||||
CompatPtr<IDirectDrawSurface7> createSurface(DWORD width, DWORD height,
|
||||
const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount);
|
||||
Resource* getBitmapResource(Surface& surface, HBITMAP bitmap, const RECT& rect, const DDPIXELFORMAT& pf, DWORD caps);
|
||||
Resource* getInitializedResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps,
|
||||
@ -64,6 +69,8 @@ namespace D3dDdi
|
||||
Surface m_logicalXorTexture;
|
||||
Surface m_paletteTexture;
|
||||
Surface m_renderTarget;
|
||||
std::map<DDPIXELFORMAT, Surface> m_textures;
|
||||
std::vector<Surface> m_releasedSurfaces;
|
||||
|
||||
static bool s_inCreateSurface;
|
||||
};
|
||||
|
11
DDrawCompat/DDraw/Comparison.h
Normal file
11
DDrawCompat/DDraw/Comparison.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <Common/Comparison.h>
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
inline auto toTuple(const DDPIXELFORMAT& pf)
|
||||
{
|
||||
return std::make_tuple(pf.dwFlags, pf.dwFourCC, pf.dwRGBBitCount,
|
||||
pf.dwRBitMask, pf.dwGBitMask, pf.dwBBitMask, pf.dwRGBAlphaBitMask);
|
||||
}
|
@ -14,105 +14,6 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
void logSrcColorKeySupportFailure(const char* reason, UINT32 resultCode);
|
||||
|
||||
bool checkSrcColorKeySupport(CompatRef<IDirectDraw7> dd)
|
||||
{
|
||||
DDCAPS caps = {};
|
||||
caps.dwSize = sizeof(caps);
|
||||
dd->GetCaps(&dd, &caps, nullptr);
|
||||
if (!(caps.dwCaps & DDCAPS_COLORKEY) || !(caps.dwCKeyCaps & DDCKEYCAPS_SRCBLT))
|
||||
{
|
||||
logSrcColorKeySupportFailure("driver indicates no support", 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
DDSURFACEDESC2 desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
|
||||
desc.dwWidth = 2;
|
||||
desc.dwHeight = 1;
|
||||
desc.ddpfPixelFormat = DDraw::DirectDraw::getRgbPixelFormat(16);
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> src;
|
||||
HRESULT result = dd->CreateSurface(&dd, &desc, &src.getRef(), nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
logSrcColorKeySupportFailure("error creating source surface", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> dst;
|
||||
result = dd->CreateSurface(&dd, &desc, &dst.getRef(), nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
logSrcColorKeySupportFailure("error creating destination surface", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = src->Lock(src, nullptr, &desc, DDLOCK_WAIT, nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
logSrcColorKeySupportFailure("error locking source surface", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
const UINT16 colorKey = 0xFA9F;
|
||||
*static_cast<UINT32*>(desc.lpSurface) = colorKey;
|
||||
src->Unlock(src, nullptr);
|
||||
|
||||
result = dst->Lock(dst, nullptr, &desc, DDLOCK_WAIT, nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
logSrcColorKeySupportFailure("error locking destination surface", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
*static_cast<UINT32*>(desc.lpSurface) = 0xFFFFFFFF;
|
||||
dst->Unlock(dst, nullptr);
|
||||
|
||||
DDBLTFX fx = {};
|
||||
fx.dwSize = sizeof(fx);
|
||||
fx.ddckSrcColorkey.dwColorSpaceLowValue = colorKey;
|
||||
fx.ddckSrcColorkey.dwColorSpaceHighValue = colorKey;
|
||||
result = dst->Blt(dst, nullptr, src, nullptr, DDBLT_KEYSRCOVERRIDE | DDBLT_WAIT, &fx);
|
||||
if (FAILED(result))
|
||||
{
|
||||
logSrcColorKeySupportFailure("blt error", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = dst->Lock(dst, nullptr, &desc, DDLOCK_WAIT, nullptr);
|
||||
if (FAILED(result))
|
||||
{
|
||||
logSrcColorKeySupportFailure("error locking destination resource after blt", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
const UINT32 dstPixels = *static_cast<UINT32*>(desc.lpSurface);
|
||||
dst->Unlock(dst, nullptr);
|
||||
|
||||
if (dstPixels != 0xFFFF)
|
||||
{
|
||||
logSrcColorKeySupportFailure("test result pattern is incorrect", dstPixels);
|
||||
return false;
|
||||
}
|
||||
|
||||
Compat::Log() << "Source color key support: yes";
|
||||
return true;
|
||||
}
|
||||
|
||||
void logSrcColorKeySupportFailure(const char* reason, UINT32 resultCode)
|
||||
{
|
||||
Compat::Log log;
|
||||
log << "Source color key support: no (" << reason;
|
||||
if (resultCode)
|
||||
{
|
||||
log << ": " << Compat::hex(resultCode);
|
||||
}
|
||||
log << ')';
|
||||
}
|
||||
|
||||
template <typename TDirectDraw, typename TSurfaceDesc, typename TSurface>
|
||||
HRESULT STDMETHODCALLTYPE CreateSurface(
|
||||
@ -242,7 +143,7 @@ namespace DDraw
|
||||
|
||||
void onCreate(GUID* guid, CompatRef<IDirectDraw7> dd)
|
||||
{
|
||||
static std::map<LUID, Repository> repositories;
|
||||
static std::map<LUID, CompatWeakPtr<IDirectDraw7>> repositories;
|
||||
auto adapterInfo = D3dDdi::KernelModeThunks::getAdapterInfo(dd);
|
||||
auto it = repositories.find(adapterInfo.luid);
|
||||
if (it == repositories.end())
|
||||
@ -254,7 +155,7 @@ namespace DDraw
|
||||
return;
|
||||
}
|
||||
repo->SetCooperativeLevel(repo, nullptr, DDSCL_NORMAL);
|
||||
it = repositories.insert({ adapterInfo.luid, { repo, checkSrcColorKeySupport(*repo) } }).first;
|
||||
it = repositories.insert({ adapterInfo.luid, repo }).first;
|
||||
repo.detach();
|
||||
}
|
||||
D3dDdi::Adapter::setRepository(adapterInfo.luid, it->second);
|
||||
|
@ -9,12 +9,6 @@ namespace DDraw
|
||||
{
|
||||
namespace DirectDraw
|
||||
{
|
||||
struct Repository
|
||||
{
|
||||
CompatWeakPtr<IDirectDraw7> repo;
|
||||
bool isSrcColorKeySupported;
|
||||
};
|
||||
|
||||
DDSURFACEDESC2 getDisplayMode(CompatRef<IDirectDraw7> dd);
|
||||
DDPIXELFORMAT getRgbPixelFormat(DWORD bpp);
|
||||
void onCreate(GUID* guid, CompatRef<IDirectDraw7> dd);
|
||||
|
@ -3,6 +3,28 @@
|
||||
#include <Common/Log.h>
|
||||
#include <DDraw/Log.h>
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const DDBLTFX& fx)
|
||||
{
|
||||
return Compat::LogStruct(os)
|
||||
<< Compat::hex(fx.dwDDFX)
|
||||
<< Compat::hex(fx.dwROP)
|
||||
<< Compat::hex(fx.dwDDROP)
|
||||
<< fx.dwRotationAngle
|
||||
<< Compat::hex(fx.dwFillColor)
|
||||
<< fx.dwFillDepth
|
||||
<< Compat::hex(fx.dwFillPixel)
|
||||
<< fx.lpDDSPattern
|
||||
<< fx.ddckDestColorkey
|
||||
<< fx.ddckSrcColorkey;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const DDCOLORKEY& ck)
|
||||
{
|
||||
return Compat::LogStruct(os)
|
||||
<< Compat::hex(ck.dwColorSpaceLowValue)
|
||||
<< Compat::hex(ck.dwColorSpaceHighValue);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const DDSCAPS& caps)
|
||||
{
|
||||
return Compat::LogStruct(os)
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const DDBLTFX& fx);
|
||||
std::ostream& operator<<(std::ostream& os, const DDCOLORKEY& ck);
|
||||
std::ostream& operator<<(std::ostream& os, const DDSCAPS& caps);
|
||||
std::ostream& operator<<(std::ostream& os, const DDSCAPS2& caps);
|
||||
std::ostream& operator<<(std::ostream& os, const DDPIXELFORMAT& pf);
|
||||
|
@ -252,6 +252,7 @@
|
||||
<ClInclude Include="D3dDdi\Visitors\DeviceCallbacksVisitor.h" />
|
||||
<ClInclude Include="D3dDdi\Visitors\DeviceFuncsVisitor.h" />
|
||||
<ClInclude Include="DDraw\Blitter.h" />
|
||||
<ClInclude Include="DDraw\Comparison.h" />
|
||||
<ClInclude Include="DDraw\DirectDraw.h" />
|
||||
<ClInclude Include="DDraw\DirectDrawClipper.h" />
|
||||
<ClInclude Include="DDraw\DirectDrawGammaControl.h" />
|
||||
|
@ -504,6 +504,9 @@
|
||||
<ClInclude Include="Config\Settings\RenderColorDepth.h">
|
||||
<Filter>Header Files\Config\Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DDraw\Comparison.h">
|
||||
<Filter>Header Files\DDraw</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
|
Loading…
x
Reference in New Issue
Block a user