1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Prefer color fills in system memory

This commit is contained in:
narzoul 2019-07-26 00:26:44 +02:00
parent c526cc2506
commit d23904afd2
9 changed files with 225 additions and 44 deletions

View File

@ -82,6 +82,11 @@ namespace D3dDdi
HRESULT Device::colorFill(const D3DDDIARG_COLORFILL& data)
{
auto it = m_resources.find(data.hResource);
if (it != m_resources.end())
{
return it->second.colorFill(data);
}
RenderGuard renderGuard(*this, Gdi::ACCESS_WRITE, data.hResource, data.SubResourceIndex);
return m_origVtable.pfnColorFill(m_device, &data);
}

View File

@ -0,0 +1,111 @@
#include "D3dDdi/FormatInfo.h"
namespace
{
struct ArgbFormatInfo : D3dDdi::FormatInfo
{
ArgbFormatInfo(BYTE alphaBitCount, BYTE redBitCount, BYTE greenBitCount, BYTE blueBitCount)
: FormatInfo(alphaBitCount, redBitCount, greenBitCount, blueBitCount)
{
redPos = greenBitCount + blueBitCount;
greenPos = blueBitCount;
}
};
struct AbgrFormatInfo : D3dDdi::FormatInfo
{
AbgrFormatInfo(BYTE alphaBitCount, BYTE blueBitCount, BYTE greenBitCount, BYTE redBitCount)
: FormatInfo(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;
}
};
}
namespace D3dDdi
{
FormatInfo::FormatInfo(BYTE alphaBitCount, BYTE redBitCount, BYTE greenBitCount, BYTE blueBitCount)
: bytesPerPixel((alphaBitCount + redBitCount + greenBitCount + blueBitCount + 7) / 8)
, alphaBitCount(alphaBitCount)
, alphaPos(redBitCount + greenBitCount + blueBitCount)
, redBitCount(redBitCount)
, redPos(0)
, greenBitCount(greenBitCount)
, greenPos(0)
, blueBitCount(blueBitCount)
, bluePos(0)
{
}
D3DCOLOR colorConvert(const FormatInfo& dstFormatInfo, D3DCOLOR srcRgbaColor)
{
struct ArgbColor
{
BYTE blue;
BYTE green;
BYTE red;
BYTE alpha;
};
auto& srcColor = *reinterpret_cast<ArgbColor*>(&srcRgbaColor);
BYTE alpha = srcColor.alpha >> (8 - dstFormatInfo.alphaBitCount);
BYTE red = srcColor.red >> (8 - dstFormatInfo.redBitCount);
BYTE green = srcColor.green >> (8 - dstFormatInfo.greenBitCount);
BYTE blue = srcColor.blue >> (8 - dstFormatInfo.blueBitCount);
return (alpha << dstFormatInfo.alphaPos) |
(red << dstFormatInfo.redPos) |
(green << dstFormatInfo.greenPos) |
(blue << dstFormatInfo.bluePos);
}
FormatInfo getFormatInfo(D3DDDIFORMAT format)
{
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_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_R8G8B8: return ArgbFormatInfo(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);
default:
return FormatInfo();
}
}
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <d3d.h>
#include <d3dumddi.h>
namespace D3dDdi
{
struct FormatInfo
{
BYTE bytesPerPixel;
BYTE alphaBitCount;
BYTE alphaPos;
BYTE redBitCount;
BYTE redPos;
BYTE greenBitCount;
BYTE greenPos;
BYTE blueBitCount;
BYTE bluePos;
FormatInfo(BYTE alphaBitCount = 0, BYTE redBitCount = 0, BYTE greenBitCount = 0, BYTE blueBitCount = 0);
};
D3DCOLOR colorConvert(const FormatInfo& dstFormatInfo, D3DCOLOR srcRgbaColor);
FormatInfo getFormatInfo(D3DDDIFORMAT format);
}

View File

@ -11,7 +11,6 @@
namespace
{
UINT getBytesPerPixel(D3DDDIFORMAT format);
D3DDDI_RESOURCEFLAGS getResourceTypeFlags();
void splitToTiles(D3DDDIARG_CREATERESOURCE& data, const UINT tileWidth, const UINT tileHeight);
@ -34,7 +33,7 @@ namespace
(isOffScreenPlain || data.Flags.Texture) &&
1 == data.SurfCount &&
0 == data.pSurfList[0].Depth &&
0 != getBytesPerPixel(data.Format))
0 != D3dDdi::getFormatInfo(data.Format).bytesPerPixel)
{
const auto& caps = device.getAdapter().getD3dExtendedCaps();
const auto& surfaceInfo = data.pSurfList[0];
@ -46,40 +45,6 @@ namespace
}
}
UINT getBytesPerPixel(D3DDDIFORMAT format)
{
switch (format)
{
case D3DDDIFMT_R3G3B2:
case D3DDDIFMT_A8:
case D3DDDIFMT_P8:
case D3DDDIFMT_R8:
return 1;
case D3DDDIFMT_R5G6B5:
case D3DDDIFMT_X1R5G5B5:
case D3DDDIFMT_A1R5G5B5:
case D3DDDIFMT_A4R4G4B4:
case D3DDDIFMT_A8R3G3B2:
case D3DDDIFMT_X4R4G4B4:
case D3DDDIFMT_A8P8:
case D3DDDIFMT_G8R8:
return 2;
case D3DDDIFMT_R8G8B8:
return 3;
case D3DDDIFMT_A8R8G8B8:
case D3DDDIFMT_X8R8G8B8:
case D3DDDIFMT_A8B8G8R8:
case D3DDDIFMT_X8B8G8R8:
return 4;
default:
return 0;
}
}
D3DDDI_RESOURCEFLAGS getResourceTypeFlags()
{
D3DDDI_RESOURCEFLAGS flags = {};
@ -109,7 +74,7 @@ namespace
static std::vector<D3DDDI_SURFACEINFO> tiles;
tiles.clear();
const UINT bytesPerPixel = getBytesPerPixel(data.Format);
const UINT bytesPerPixel = D3dDdi::getFormatInfo(data.Format).bytesPerPixel;
for (UINT y = 0; y < data.pSurfList[0].Height; y += tileHeight)
{
@ -216,7 +181,6 @@ namespace D3dDdi
: m_device(device)
, m_handle(nullptr)
, m_origData(data)
, m_bytesPerPixel(0)
, m_rootSurface(nullptr)
, m_lockResource(nullptr)
{
@ -279,7 +243,7 @@ namespace D3dDdi
unsigned char* ptr = static_cast<unsigned char*>(lockData.data);
if (data.Flags.AreaValid)
{
ptr += data.Area.top * lockData.pitch + data.Area.left * m_bytesPerPixel;
ptr += data.Area.top * lockData.pitch + data.Area.left * m_formatInfo.bytesPerPixel;
}
data.pSurfData = ptr;
@ -303,6 +267,32 @@ namespace D3dDdi
return LOG_RESULT(S_OK);
}
HRESULT Resource::colorFill(const D3DDDIARG_COLORFILL& data)
{
LOG_FUNC("Resource::colorFill", data);
if (data.SubResourceIndex < m_lockData.size() && 0 != m_formatInfo.bytesPerPixel)
{
auto& lockData = m_lockData[data.SubResourceIndex];
if (lockData.isSysMemUpToDate)
{
auto dstBuf = static_cast<BYTE*>(lockData.data) +
data.DstRect.top * lockData.pitch + data.DstRect.left * m_formatInfo.bytesPerPixel;
DDraw::Blitter::colorFill(dstBuf, lockData.pitch,
data.DstRect.right - data.DstRect.left, data.DstRect.bottom - data.DstRect.top,
m_formatInfo.bytesPerPixel, colorConvert(m_formatInfo, data.Color));
if (lockData.isVidMemUpToDate)
{
setVidMemUpToDate(data.SubResourceIndex, false);
}
return LOG_RESULT(S_OK);
}
}
prepareForRendering(data.SubResourceIndex, false);
return LOG_RESULT(m_device.getOrigVtable().pfnColorFill(m_device, &data));
}
HRESULT Resource::copySubResource(Resource& dstResource, Resource& srcResource, UINT subResourceIndex)
{
RECT rect = {};
@ -344,7 +334,7 @@ namespace D3dDdi
Arg origData = data;
fixResourceData(device, reinterpret_cast<D3DDDIARG_CREATERESOURCE&>(data));
resource.m_fixedData = data;
resource.m_bytesPerPixel = getBytesPerPixel(data.Format);
resource.m_formatInfo = getFormatInfo(data.Format);
HRESULT result = createResourceFunc(device, &data);
if (FAILED(result))
@ -625,9 +615,9 @@ namespace D3dDdi
if (dstGuard.data)
{
auto dstBuf = static_cast<BYTE*>(dstGuard.data) +
data.DstRect.top * dstGuard.pitch + data.DstRect.left * m_bytesPerPixel;
data.DstRect.top * dstGuard.pitch + data.DstRect.left * m_formatInfo.bytesPerPixel;
auto srcBuf = static_cast<const BYTE*>(srcGuard.data) +
data.SrcRect.top * srcGuard.pitch + data.SrcRect.left * m_bytesPerPixel;
data.SrcRect.top * srcGuard.pitch + data.SrcRect.left * m_formatInfo.bytesPerPixel;
DDraw::Blitter::blt(
dstBuf,
@ -638,7 +628,7 @@ namespace D3dDdi
srcGuard.pitch,
(1 - 2 * data.Flags.MirrorLeftRight) * (data.SrcRect.right - data.SrcRect.left),
(1 - 2 * data.Flags.MirrorUpDown) * (data.SrcRect.bottom - data.SrcRect.top),
m_bytesPerPixel,
m_formatInfo.bytesPerPixel,
data.Flags.DstColorKey ? reinterpret_cast<const DWORD*>(&data.ColorKey) : nullptr,
data.Flags.SrcColorKey ? reinterpret_cast<const DWORD*>(&data.ColorKey) : nullptr);

View File

@ -6,6 +6,8 @@
#include <d3dumddi.h>
#include <ddraw.h>
#include "D3dDdi/FormatInfo.h"
namespace DDraw
{
class Surface;
@ -24,6 +26,7 @@ namespace D3dDdi
operator HANDLE() const { return m_handle; }
HRESULT blt(D3DDDIARG_BLT data);
HRESULT colorFill(const D3DDDIARG_COLORFILL& data);
void destroy();
HRESULT lock(D3DDDIARG_LOCK& data);
void prepareForRendering(UINT subResourceIndex, bool isReadOnly);
@ -92,7 +95,7 @@ namespace D3dDdi
HANDLE m_handle;
Data m_origData;
Data m_fixedData;
UINT m_bytesPerPixel;
FormatInfo m_formatInfo;
DDraw::Surface* m_rootSurface;
Resource* m_lockResource;
std::vector<LockData> m_lockData;

View File

@ -636,6 +636,33 @@ namespace
vectorizedBltFunc(dst, dstPitch, dstWidth, dstHeight,
src, srcPitch, offsetX, deltaX, offsetY, deltaY, dstCk, srcCk);
}
template <typename Pixel>
void colorFill(BYTE* dst, DWORD dstPitch, DWORD dstWidth, DWORD dstHeight, DWORD color)
{
DWORD c = 0;
memset(&c, color, sizeof(Pixel));
if (c == color)
{
for (DWORD i = dstHeight; i != 0; --i)
{
memset(dst, color, dstWidth * sizeof(Pixel));
dst += dstPitch;
}
return;
}
for (DWORD i = 0; i < dstWidth; ++i)
{
reinterpret_cast<Pixel*>(dst)[i] = static_cast<Pixel>(color);
}
for (DWORD i = dstHeight - 1; i != 0; --i)
{
memcpy(dst + dstPitch, dst, dstWidth * sizeof(Pixel));
dst += dstPitch;
}
}
}
namespace DDraw
@ -650,5 +677,16 @@ namespace DDraw
static_cast<const BYTE*>(src), srcPitch, srcWidth, srcHeight,
bytesPerPixel, dstColorKey, srcColorKey);
}
void colorFill(void* dst, DWORD dstPitch, DWORD dstWidth, DWORD dstHeight, DWORD bytesPerPixel, DWORD color)
{
switch (bytesPerPixel)
{
case 1: return ::colorFill<BYTE>(static_cast<BYTE*>(dst), dstPitch, dstWidth, dstHeight, color);
case 2: return ::colorFill<WORD>(static_cast<BYTE*>(dst), dstPitch, dstWidth, dstHeight, color);
case 3: return ::colorFill<UInt24>(static_cast<BYTE*>(dst), dstPitch, dstWidth, dstHeight, color);
case 4: return ::colorFill<DWORD>(static_cast<BYTE*>(dst), dstPitch, dstWidth, dstHeight, color);
}
}
}
}

View File

@ -11,5 +11,6 @@ namespace DDraw
void blt(void* dst, DWORD dstPitch, DWORD dstWidth, DWORD dstHeight,
const void* src, DWORD srcPitch, LONG srcWidth, LONG srcHeight,
DWORD bytesPerPixel, const DWORD* dstColorKey, const DWORD* srcColorKey);
void colorFill(void* dst, DWORD dstPitch, DWORD dstWidth, DWORD dstHeight, DWORD bytesPerPixel, DWORD color);
}
}

View File

@ -157,6 +157,7 @@
<ClInclude Include="D3dDdi\Device.h" />
<ClInclude Include="D3dDdi\DeviceCallbacks.h" />
<ClInclude Include="D3dDdi\DeviceFuncs.h" />
<ClInclude Include="D3dDdi\FormatInfo.h" />
<ClInclude Include="D3dDdi\Hooks.h" />
<ClInclude Include="D3dDdi\KernelModeThunks.h" />
<ClInclude Include="D3dDdi\Log\AdapterFuncsLog.h" />
@ -234,6 +235,7 @@
<ClCompile Include="D3dDdi\Device.cpp" />
<ClCompile Include="D3dDdi\DeviceCallbacks.cpp" />
<ClCompile Include="D3dDdi\DeviceFuncs.cpp" />
<ClCompile Include="D3dDdi\FormatInfo.cpp" />
<ClCompile Include="D3dDdi\Hooks.cpp" />
<ClCompile Include="D3dDdi\KernelModeThunks.cpp" />
<ClCompile Include="D3dDdi\Log\AdapterFuncsLog.cpp" />

View File

@ -351,6 +351,9 @@
<ClInclude Include="DDraw\Blitter.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="D3dDdi\FormatInfo.h">
<Filter>Header Files\D3dDdi</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -533,6 +536,9 @@
<ClCompile Include="DDraw\Blitter.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="D3dDdi\FormatInfo.cpp">
<Filter>Source Files\D3dDdi</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="Dll\DDrawCompat.def">