mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-22 16:54:27 +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 = { };
|
POINT currentPos = { };
|
||||||
::GetCursorPos(¤tPos);
|
::GetCursorPos(¤tPos);
|
||||||
|
|
||||||
m_sCursor.X = static_cast<UINT>(currentPos.x);
|
m_sCursor.X = static_cast<int32_t>(currentPos.x) - m_sCursor.XHotSpot;
|
||||||
m_sCursor.Y = static_cast<UINT>(currentPos.y);
|
m_sCursor.Y = static_cast<int32_t>(currentPos.y) - m_sCursor.YHotSpot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -97,8 +97,8 @@ namespace dxvk {
|
|||||||
|
|
||||||
m_sCursor.Width = Width;
|
m_sCursor.Width = Width;
|
||||||
m_sCursor.Height = Height;
|
m_sCursor.Height = Height;
|
||||||
m_sCursor.X = XHotSpot;
|
m_sCursor.XHotSpot = XHotSpot;
|
||||||
m_sCursor.Y = YHotSpot;
|
m_sCursor.YHotSpot = YHotSpot;
|
||||||
m_sCursor.ResetCursor = false;
|
m_sCursor.ResetCursor = false;
|
||||||
|
|
||||||
ShowCursor(m_visible);
|
ShowCursor(m_visible);
|
||||||
|
@ -10,8 +10,10 @@ namespace dxvk {
|
|||||||
struct D3D9_SOFTWARE_CURSOR {
|
struct D3D9_SOFTWARE_CURSOR {
|
||||||
UINT Width = 0;
|
UINT Width = 0;
|
||||||
UINT Height = 0;
|
UINT Height = 0;
|
||||||
UINT X = 0;
|
UINT XHotSpot = 0;
|
||||||
UINT Y = 0;
|
UINT YHotSpot = 0;
|
||||||
|
int32_t X = 0;
|
||||||
|
int32_t Y = 0;
|
||||||
bool DrawCursor = false;
|
bool DrawCursor = false;
|
||||||
bool ResetCursor = false;
|
bool ResetCursor = false;
|
||||||
};
|
};
|
||||||
|
@ -350,6 +350,11 @@ namespace dxvk {
|
|||||||
|| (inputHeight && (inputHeight & (inputHeight - 1))))
|
|| (inputHeight && (inputHeight & (inputHeight - 1))))
|
||||||
return D3DERR_INVALIDCALL;
|
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;
|
D3DPRESENT_PARAMETERS params;
|
||||||
m_implicitSwapchain->GetPresentParameters(¶ms);
|
m_implicitSwapchain->GetPresentParameters(¶ms);
|
||||||
|
|
||||||
@ -387,55 +392,17 @@ namespace dxvk {
|
|||||||
// Set this as our cursor.
|
// Set this as our cursor.
|
||||||
return m_cursor.SetHardwareCursor(XHotSpot, YHotSpot, bitmap);
|
return m_cursor.SetHardwareCursor(XHotSpot, YHotSpot, bitmap);
|
||||||
} else {
|
} else {
|
||||||
// The cursor bitmap passed by the application has the potential
|
size_t copyPitch = inputWidth * HardwareCursorFormatSize;
|
||||||
// to not be clipped to the correct dimensions, so we need to
|
std::vector<uint8_t> bitmap(inputHeight * copyPitch, 0);
|
||||||
// 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;
|
|
||||||
|
|
||||||
uint32_t rowPitch = inputWidth * HardwareCursorFormatSize;
|
for (uint32_t h = 0; h < inputHeight; h++)
|
||||||
|
std::memcpy(&bitmap[h * copyPitch], &data[h * lockedBox.RowPitch], copyPitch);
|
||||||
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);
|
|
||||||
|
|
||||||
UnlockImage(cursorTex, 0, 0);
|
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;
|
return D3D_OK;
|
||||||
@ -3929,6 +3896,8 @@ namespace dxvk {
|
|||||||
if (unlikely(pSoftwareCursor->ResetCursor)) {
|
if (unlikely(pSoftwareCursor->ResetCursor)) {
|
||||||
pSoftwareCursor->Width = 0;
|
pSoftwareCursor->Width = 0;
|
||||||
pSoftwareCursor->Height = 0;
|
pSoftwareCursor->Height = 0;
|
||||||
|
pSoftwareCursor->XHotSpot = 0;
|
||||||
|
pSoftwareCursor->YHotSpot = 0;
|
||||||
pSoftwareCursor->X = 0;
|
pSoftwareCursor->X = 0;
|
||||||
pSoftwareCursor->Y = 0;
|
pSoftwareCursor->Y = 0;
|
||||||
pSoftwareCursor->ResetCursor = false;
|
pSoftwareCursor->ResetCursor = false;
|
||||||
|
@ -758,8 +758,8 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void D3D9SwapChainEx::SetCursorPosition(UINT X, UINT Y, UINT Width, UINT Height) {
|
void D3D9SwapChainEx::SetCursorPosition(int32_t X, int32_t Y, UINT Width, UINT Height) {
|
||||||
VkOffset2D cursorPosition = { int32_t(X), int32_t(Y) };
|
VkOffset2D cursorPosition = { X, Y };
|
||||||
VkExtent2D cursorSize = { uint32_t(Width), uint32_t(Height) };
|
VkExtent2D cursorSize = { uint32_t(Width), uint32_t(Height) };
|
||||||
|
|
||||||
VkRect2D cursorRect = { cursorPosition, cursorSize };
|
VkRect2D cursorRect = { cursorPosition, cursorSize };
|
||||||
|
@ -120,7 +120,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
void SetCursorTexture(UINT Width, UINT Height, uint8_t* pCursorBitmap);
|
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);
|
HRESULT SetDialogBoxMode(bool bEnableDialogs);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user