mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-20 19:54:19 +01:00
[d3d9] Make proper use of X/YHotSpot for software cursors
This commit is contained in:
parent
44b682051b
commit
48c57c11e9
@ -41,8 +41,8 @@ namespace dxvk {
|
||||
POINT currentPos = { };
|
||||
::GetCursorPos(¤tPos);
|
||||
|
||||
m_sCursor.X = static_cast<UINT>(currentPos.x);
|
||||
m_sCursor.Y = static_cast<UINT>(currentPos.y);
|
||||
m_sCursor.X = static_cast<int32_t>(currentPos.x) - m_sCursor.XHotSpot;
|
||||
m_sCursor.Y = static_cast<int32_t>(currentPos.y) - m_sCursor.YHotSpot;
|
||||
}
|
||||
|
||||
|
||||
@ -97,8 +97,8 @@ namespace dxvk {
|
||||
|
||||
m_sCursor.Width = Width;
|
||||
m_sCursor.Height = Height;
|
||||
m_sCursor.X = XHotSpot;
|
||||
m_sCursor.Y = YHotSpot;
|
||||
m_sCursor.XHotSpot = XHotSpot;
|
||||
m_sCursor.YHotSpot = YHotSpot;
|
||||
m_sCursor.ResetCursor = false;
|
||||
|
||||
ShowCursor(m_visible);
|
||||
|
@ -10,8 +10,10 @@ namespace dxvk {
|
||||
struct D3D9_SOFTWARE_CURSOR {
|
||||
UINT Width = 0;
|
||||
UINT Height = 0;
|
||||
UINT X = 0;
|
||||
UINT Y = 0;
|
||||
UINT XHotSpot = 0;
|
||||
UINT YHotSpot = 0;
|
||||
int32_t X = 0;
|
||||
int32_t Y = 0;
|
||||
bool DrawCursor = false;
|
||||
bool ResetCursor = false;
|
||||
};
|
||||
|
@ -350,6 +350,11 @@ namespace dxvk {
|
||||
|| (inputHeight && (inputHeight & (inputHeight - 1))))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
// It makes no sense to have a hotspot outside of the bitmap.
|
||||
if (XHotSpot > std::max(inputWidth - 1, 0u)
|
||||
|| YHotSpot > std::max(inputHeight - 1, 0u))
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
D3DPRESENT_PARAMETERS params;
|
||||
m_implicitSwapchain->GetPresentParameters(¶ms);
|
||||
|
||||
@ -387,55 +392,17 @@ namespace dxvk {
|
||||
// Set this as our cursor.
|
||||
return m_cursor.SetHardwareCursor(XHotSpot, YHotSpot, bitmap);
|
||||
} else {
|
||||
// The cursor bitmap passed by the application has the potential
|
||||
// to not be clipped to the correct dimensions, so we need to
|
||||
// discard any transparent edges and keep only a tight rectangle
|
||||
// bounded by the cursor's visible edge pixels
|
||||
uint32_t leftEdge = inputWidth * HardwareCursorFormatSize;
|
||||
uint32_t topEdge = inputHeight;
|
||||
uint32_t rightEdge = 0;
|
||||
uint32_t bottomEdge = 0;
|
||||
size_t copyPitch = inputWidth * HardwareCursorFormatSize;
|
||||
std::vector<uint8_t> bitmap(inputHeight * copyPitch, 0);
|
||||
|
||||
uint32_t rowPitch = inputWidth * HardwareCursorFormatSize;
|
||||
|
||||
for (uint32_t h = 0; h < inputHeight; h++) {
|
||||
uint32_t rowOffset = h * rowPitch;
|
||||
for (uint32_t w = 0; w < rowPitch; w += HardwareCursorFormatSize) {
|
||||
// Examine only pixels with non-zero alpha
|
||||
if (data[rowOffset + w + 3] != 0) {
|
||||
if (leftEdge > w) leftEdge = w;
|
||||
if (topEdge > h) topEdge = h;
|
||||
if (rightEdge < w) rightEdge = w;
|
||||
if (bottomEdge < h) bottomEdge = h;
|
||||
}
|
||||
}
|
||||
}
|
||||
leftEdge /= HardwareCursorFormatSize;
|
||||
rightEdge /= HardwareCursorFormatSize;
|
||||
|
||||
if (leftEdge > rightEdge || topEdge > bottomEdge) {
|
||||
UnlockImage(cursorTex, 0, 0);
|
||||
|
||||
return D3DERR_INVALIDCALL;
|
||||
}
|
||||
|
||||
// Calculate clipped bitmap dimensions
|
||||
uint32_t clippedInputWidth = rightEdge + 1 - leftEdge + 1;
|
||||
uint32_t clippedInputHeight = bottomEdge + 1 - topEdge + 1;
|
||||
// Windows works with a stride of 128, lets respect that.
|
||||
uint32_t clippedCopyPitch = clippedInputWidth * HardwareCursorFormatSize;
|
||||
|
||||
std::vector<uint8_t> clippedBitmap(clippedInputHeight * clippedCopyPitch, 0);
|
||||
|
||||
for (uint32_t h = 0; h < clippedInputHeight; h++)
|
||||
std::memcpy(&clippedBitmap[h * clippedCopyPitch],
|
||||
&data[(h + topEdge) * lockedBox.RowPitch + leftEdge * HardwareCursorFormatSize], clippedCopyPitch);
|
||||
for (uint32_t h = 0; h < inputHeight; h++)
|
||||
std::memcpy(&bitmap[h * copyPitch], &data[h * lockedBox.RowPitch], copyPitch);
|
||||
|
||||
UnlockImage(cursorTex, 0, 0);
|
||||
|
||||
m_implicitSwapchain->SetCursorTexture(clippedInputWidth, clippedInputHeight, &clippedBitmap[0]);
|
||||
m_implicitSwapchain->SetCursorTexture(inputWidth, inputHeight, &bitmap[0]);
|
||||
|
||||
return m_cursor.SetSoftwareCursor(clippedInputWidth, clippedInputHeight, XHotSpot, YHotSpot);
|
||||
return m_cursor.SetSoftwareCursor(inputWidth, inputHeight, XHotSpot, YHotSpot);
|
||||
}
|
||||
|
||||
return D3D_OK;
|
||||
@ -3929,6 +3896,8 @@ namespace dxvk {
|
||||
if (unlikely(pSoftwareCursor->ResetCursor)) {
|
||||
pSoftwareCursor->Width = 0;
|
||||
pSoftwareCursor->Height = 0;
|
||||
pSoftwareCursor->XHotSpot = 0;
|
||||
pSoftwareCursor->YHotSpot = 0;
|
||||
pSoftwareCursor->X = 0;
|
||||
pSoftwareCursor->Y = 0;
|
||||
pSoftwareCursor->ResetCursor = false;
|
||||
|
@ -758,8 +758,8 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void D3D9SwapChainEx::SetCursorPosition(UINT X, UINT Y, UINT Width, UINT Height) {
|
||||
VkOffset2D cursorPosition = { int32_t(X), int32_t(Y) };
|
||||
void D3D9SwapChainEx::SetCursorPosition(int32_t X, int32_t Y, UINT Width, UINT Height) {
|
||||
VkOffset2D cursorPosition = { X, Y };
|
||||
VkExtent2D cursorSize = { uint32_t(Width), uint32_t(Height) };
|
||||
|
||||
VkRect2D cursorRect = { cursorPosition, cursorSize };
|
||||
|
@ -120,7 +120,7 @@ namespace dxvk {
|
||||
|
||||
void SetCursorTexture(UINT Width, UINT Height, uint8_t* pCursorBitmap);
|
||||
|
||||
void SetCursorPosition(UINT X, UINT Y, UINT Width, UINT Height);
|
||||
void SetCursorPosition(int32_t X, int32_t Y, UINT Width, UINT Height);
|
||||
|
||||
HRESULT SetDialogBoxMode(bool bEnableDialogs);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user