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:
parent
c526cc2506
commit
d23904afd2
@ -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);
|
||||
}
|
||||
|
111
DDrawCompat/D3dDdi/FormatInfo.cpp
Normal file
111
DDrawCompat/D3dDdi/FormatInfo.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
25
DDrawCompat/D3dDdi/FormatInfo.h
Normal file
25
DDrawCompat/D3dDdi/FormatInfo.h
Normal 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);
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
Loading…
x
Reference in New Issue
Block a user