mirror of https://github.com/doitsujin/dxvk
[d3d9] Add a software cursor emulation config option
This commit is contained in:
parent
037d0fa1ad
commit
1299ad050f
11
dxvk.conf
11
dxvk.conf
|
@ -625,6 +625,17 @@
|
||||||
|
|
||||||
# d3d9.seamlessCubes = False
|
# d3d9.seamlessCubes = False
|
||||||
|
|
||||||
|
# Software Cursor Emulation
|
||||||
|
#
|
||||||
|
# Will atempt to emulate a software cursor by using a hardware cursor. This is useful
|
||||||
|
# for applications that rely on d3d9 API calls to create the cursor and potentially use
|
||||||
|
# bitmap sizes in excess of 32 x 32.
|
||||||
|
#
|
||||||
|
# Supported values:
|
||||||
|
# - True/False
|
||||||
|
|
||||||
|
# d3d9.softwareCursorEmulation = False
|
||||||
|
|
||||||
# Debug Utils
|
# Debug Utils
|
||||||
#
|
#
|
||||||
# Enables debug utils as this is off by default, this enables user annotations like BeginEvent()/EndEvent().
|
# Enables debug utils as this is off by default, this enables user annotations like BeginEvent()/EndEvent().
|
||||||
|
|
|
@ -25,25 +25,53 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT D3D9Cursor::SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap) {
|
HRESULT D3D9Cursor::SetHardwareCursor(
|
||||||
DWORD mask[32];
|
UINT XHotSpot,
|
||||||
std::memset(mask, ~0, sizeof(mask));
|
UINT YHotSpot,
|
||||||
|
const std::vector<uint8_t>& bitmap,
|
||||||
|
bool cursorEmulation,
|
||||||
|
UINT width,
|
||||||
|
UINT height,
|
||||||
|
HWND window) {
|
||||||
|
bool noPreviousHardwareCursor = false;
|
||||||
|
|
||||||
|
uint32_t cursorWidth = cursorEmulation ? width : HardwareCursorWidth;
|
||||||
|
uint32_t cursorHeight = cursorEmulation ? height : HardwareCursorHeight;
|
||||||
|
|
||||||
|
// For color icons, the hbmMask and hbmColor bitmaps
|
||||||
|
// are the same size, each of which is the size of the icon.
|
||||||
|
std::vector<DWORD> mask(cursorWidth * cursorHeight, ~0);
|
||||||
|
|
||||||
ICONINFO info;
|
ICONINFO info;
|
||||||
info.fIcon = FALSE;
|
info.fIcon = FALSE;
|
||||||
info.xHotspot = XHotSpot;
|
info.xHotspot = XHotSpot;
|
||||||
info.yHotspot = YHotSpot;
|
info.yHotspot = YHotSpot;
|
||||||
info.hbmMask = ::CreateBitmap(HardwareCursorWidth, HardwareCursorHeight, 1, 1, mask);
|
info.hbmMask = ::CreateBitmap(cursorWidth, cursorHeight, 1, 1, &mask[0]);
|
||||||
info.hbmColor = ::CreateBitmap(HardwareCursorWidth, HardwareCursorHeight, 1, 32, &bitmap[0]);
|
info.hbmColor = ::CreateBitmap(cursorWidth, cursorHeight, 1, 32, &bitmap[0]);
|
||||||
|
|
||||||
if (m_hCursor != nullptr)
|
if (m_hCursor != nullptr)
|
||||||
::DestroyCursor(m_hCursor);
|
::DestroyCursor(m_hCursor);
|
||||||
|
else
|
||||||
|
noPreviousHardwareCursor = true;
|
||||||
|
|
||||||
m_hCursor = ::CreateIconIndirect(&info);
|
m_hCursor = ::CreateIconIndirect(&info);
|
||||||
|
|
||||||
::DeleteObject(info.hbmMask);
|
::DeleteObject(info.hbmMask);
|
||||||
::DeleteObject(info.hbmColor);
|
::DeleteObject(info.hbmColor);
|
||||||
|
|
||||||
|
if (cursorEmulation) {
|
||||||
|
::SetClassLongPtr(window, GCLP_HCURSOR, reinterpret_cast<LONG_PTR>(m_hCursor));
|
||||||
|
|
||||||
|
CURSORINFO ci;
|
||||||
|
while (::GetCursorInfo(&ci) && ci.flags == 0u)
|
||||||
|
::ShowCursor(TRUE);
|
||||||
|
|
||||||
|
// Castle Strike needs one extra initial increment
|
||||||
|
// to display the emulated cursor on its menu
|
||||||
|
if (noPreviousHardwareCursor)
|
||||||
|
::ShowCursor(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
ShowCursor(m_visible);
|
ShowCursor(m_visible);
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
@ -60,7 +88,14 @@ namespace dxvk {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HRESULT D3D9Cursor::SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap) {
|
HRESULT D3D9Cursor::SetHardwareCursor(
|
||||||
|
UINT XHotSpot,
|
||||||
|
UINT YHotSpot,
|
||||||
|
const std::vector<uint8_t>& bitmap,
|
||||||
|
bool cursorEmulation,
|
||||||
|
UINT width,
|
||||||
|
UINT height,
|
||||||
|
HWND window) {
|
||||||
Logger::warn("D3D9Cursor::SetHardwareCursor: Not supported on current platform.");
|
Logger::warn("D3D9Cursor::SetHardwareCursor: Not supported on current platform.");
|
||||||
|
|
||||||
return D3D_OK;
|
return D3D_OK;
|
||||||
|
|
|
@ -9,9 +9,6 @@ namespace dxvk {
|
||||||
constexpr uint32_t HardwareCursorFormatSize = 4u;
|
constexpr uint32_t HardwareCursorFormatSize = 4u;
|
||||||
constexpr uint32_t HardwareCursorPitch = HardwareCursorWidth * HardwareCursorFormatSize;
|
constexpr uint32_t HardwareCursorPitch = HardwareCursorWidth * HardwareCursorFormatSize;
|
||||||
|
|
||||||
// Format Size of 4 bytes (ARGB)
|
|
||||||
using CursorBitmap = uint8_t[HardwareCursorHeight * HardwareCursorPitch];
|
|
||||||
|
|
||||||
class D3D9Cursor {
|
class D3D9Cursor {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -20,7 +17,14 @@ namespace dxvk {
|
||||||
|
|
||||||
BOOL ShowCursor(BOOL bShow);
|
BOOL ShowCursor(BOOL bShow);
|
||||||
|
|
||||||
HRESULT SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap);
|
HRESULT SetHardwareCursor(
|
||||||
|
UINT XHotSpot,
|
||||||
|
UINT YHotSpot,
|
||||||
|
const std::vector<uint8_t>& bitmap,
|
||||||
|
bool cursorEmulation,
|
||||||
|
UINT width,
|
||||||
|
UINT height,
|
||||||
|
HWND window);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -345,7 +345,7 @@ namespace dxvk {
|
||||||
// Always use a hardware cursor when windowed.
|
// Always use a hardware cursor when windowed.
|
||||||
D3DPRESENT_PARAMETERS params;
|
D3DPRESENT_PARAMETERS params;
|
||||||
m_implicitSwapchain->GetPresentParameters(¶ms);
|
m_implicitSwapchain->GetPresentParameters(¶ms);
|
||||||
bool hwCursor = params.Windowed;
|
bool hwCursor = params.Windowed || m_d3d9Options.softwareCursorEmulation;
|
||||||
|
|
||||||
// Always use a hardware cursor w/h <= 32 px
|
// Always use a hardware cursor w/h <= 32 px
|
||||||
hwCursor |= inputWidth <= HardwareCursorWidth
|
hwCursor |= inputWidth <= HardwareCursorWidth
|
||||||
|
@ -359,20 +359,32 @@ namespace dxvk {
|
||||||
|
|
||||||
const uint8_t* data = reinterpret_cast<const uint8_t*>(lockedBox.pBits);
|
const uint8_t* data = reinterpret_cast<const uint8_t*>(lockedBox.pBits);
|
||||||
|
|
||||||
|
uint32_t emulatedCursorPitch = inputWidth * HardwareCursorFormatSize;
|
||||||
|
|
||||||
|
uint32_t cursorHeight = m_d3d9Options.softwareCursorEmulation ? inputHeight : HardwareCursorHeight;
|
||||||
|
uint32_t cursorPitch = m_d3d9Options.softwareCursorEmulation ? emulatedCursorPitch : HardwareCursorPitch;
|
||||||
|
|
||||||
// Windows works with a stride of 128, lets respect that.
|
// Windows works with a stride of 128, lets respect that.
|
||||||
// Copy data to the bitmap...
|
// Copy data to the bitmap...
|
||||||
CursorBitmap bitmap = { 0 };
|
// Format Size of 4 bytes (ARGB)
|
||||||
|
std::vector<uint8_t> bitmap(cursorHeight * cursorPitch, 0);
|
||||||
size_t copyPitch = std::min<size_t>(
|
size_t copyPitch = std::min<size_t>(
|
||||||
HardwareCursorPitch,
|
cursorPitch,
|
||||||
inputWidth * inputHeight * HardwareCursorFormatSize);
|
inputWidth * inputHeight * HardwareCursorFormatSize);
|
||||||
|
|
||||||
for (uint32_t h = 0; h < HardwareCursorHeight; h++)
|
for (uint32_t h = 0; h < cursorHeight; h++)
|
||||||
std::memcpy(&bitmap[h * HardwareCursorPitch], &data[h * lockedBox.RowPitch], copyPitch);
|
std::memcpy(&bitmap[h * cursorPitch], &data[h * lockedBox.RowPitch], copyPitch);
|
||||||
|
|
||||||
UnlockImage(cursorTex, 0, 0);
|
UnlockImage(cursorTex, 0, 0);
|
||||||
|
|
||||||
// Set this as our cursor.
|
// Set this as our cursor.
|
||||||
return m_cursor.SetHardwareCursor(XHotSpot, YHotSpot, bitmap);
|
return m_cursor.SetHardwareCursor(XHotSpot,
|
||||||
|
YHotSpot,
|
||||||
|
bitmap,
|
||||||
|
m_d3d9Options.softwareCursorEmulation,
|
||||||
|
inputWidth,
|
||||||
|
inputHeight,
|
||||||
|
m_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Software Cursor...
|
// Software Cursor...
|
||||||
|
|
|
@ -77,6 +77,7 @@ namespace dxvk {
|
||||||
this->samplerLodBias = config.getOption<float> ("d3d9.samplerLodBias", 0.0f);
|
this->samplerLodBias = config.getOption<float> ("d3d9.samplerLodBias", 0.0f);
|
||||||
this->clampNegativeLodBias = config.getOption<bool> ("d3d9.clampNegativeLodBias", false);
|
this->clampNegativeLodBias = config.getOption<bool> ("d3d9.clampNegativeLodBias", false);
|
||||||
this->countLosableResources = config.getOption<bool> ("d3d9.countLosableResources", true);
|
this->countLosableResources = config.getOption<bool> ("d3d9.countLosableResources", true);
|
||||||
|
this->softwareCursorEmulation = config.getOption<bool> ("d3d9.softwareCursorEmulation", false);
|
||||||
|
|
||||||
// Clamp LOD bias so that people don't abuse this in unintended ways
|
// Clamp LOD bias so that people don't abuse this in unintended ways
|
||||||
this->samplerLodBias = dxvk::fclamp(this->samplerLodBias, -2.0f, 1.0f);
|
this->samplerLodBias = dxvk::fclamp(this->samplerLodBias, -2.0f, 1.0f);
|
||||||
|
|
|
@ -144,6 +144,9 @@ namespace dxvk {
|
||||||
/// Clamps negative LOD bias
|
/// Clamps negative LOD bias
|
||||||
bool clampNegativeLodBias;
|
bool clampNegativeLodBias;
|
||||||
|
|
||||||
|
/// Emulate a software cursor using a hardware cursor
|
||||||
|
bool softwareCursorEmulation;
|
||||||
|
|
||||||
/// How much virtual memory will be used for textures (in MB).
|
/// How much virtual memory will be used for textures (in MB).
|
||||||
int32_t textureMemory;
|
int32_t textureMemory;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue