Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[d3d9] Update software cursor position using SetCursorPosition #7

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions src/d3d9/d3d9_cursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,19 @@ namespace dxvk {
m_sCursor.Bitmap = nullptr;
m_sCursor.XHotSpot = 0;
m_sCursor.YHotSpot = 0;
m_sCursor.X = 0.0f;
m_sCursor.Y = 0.0f;
}


void D3D9Cursor::UpdateCursor(int X, int Y) {
// SetCursorPosition is used to directly update the position of software cursors,
// but keep track of the cursor position even when using hardware cursors, in order
// to ensure a smooth transition/overlap from one type to the other.
m_sCursor.X = static_cast<float>(X);
m_sCursor.Y = static_cast<float>(Y);

if (unlikely(m_sCursor.Bitmap != nullptr))
return;

POINT currentPos = { };
if (::GetCursorPos(&currentPos) && currentPos == POINT{ X, Y })
return;
Expand All @@ -40,15 +47,6 @@ namespace dxvk {
}


void D3D9Cursor::RefreshSoftwareCursorPosition() {
POINT currentPos = { };
::GetCursorPos(&currentPos);

m_sCursor.X = static_cast<float>(currentPos.x) - static_cast<float>(m_sCursor.XHotSpot);
m_sCursor.Y = static_cast<float>(currentPos.y) - static_cast<float>(m_sCursor.YHotSpot);
}


BOOL D3D9Cursor::ShowCursor(BOOL bShow) {
// Cursor visibility remains unchanged (typically FALSE) if the cursor isn't set.
if (unlikely(m_hCursor == nullptr && m_sCursor.Bitmap == nullptr))
Expand Down
2 changes: 0 additions & 2 deletions src/d3d9/d3d9_cursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ namespace dxvk {

void UpdateCursor(int X, int Y);

void RefreshSoftwareCursorPosition();

BOOL ShowCursor(BOOL bShow);

HRESULT SetHardwareCursor(UINT XHotSpot, UINT YHotSpot, const CursorBitmap& bitmap);
Expand Down
51 changes: 22 additions & 29 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3538,34 +3538,27 @@ namespace dxvk {
D3DSURFACE_DESC dstDesc;
m_state.renderTargets[0]->GetDesc(&dstDesc);

m_cursor.RefreshSoftwareCursorPosition();

// Calculate cursor quad vertex coordinates based on render target edges and the win32 cursor position
float dstLeft = pSoftwareCursor->X;
float dstTop = pSoftwareCursor->Y;
float dstRight = std::min(pSoftwareCursor->X + static_cast<float>(srcDesc.Width), static_cast<float>(dstDesc.Width));
float dstBottom = std::min(pSoftwareCursor->Y + static_cast<float>(srcDesc.Height), static_cast<float>(dstDesc.Height));
const float dstLeft = pSoftwareCursor->X - static_cast<float>(pSoftwareCursor->XHotSpot);
const float dstTop = pSoftwareCursor->Y - static_cast<float>(pSoftwareCursor->YHotSpot);
const float dstRight = std::min(dstLeft + static_cast<float>(srcDesc.Width), static_cast<float>(dstDesc.Width));
const float dstBottom = std::min(dstTop + static_cast<float>(srcDesc.Height), static_cast<float>(dstDesc.Height));
// Calculate cursor texture coordinates based on quad rendering coordinates and render target edges
float srcRight = dstRight == static_cast<float>(dstDesc.Width) ?
dstRight - pSoftwareCursor->X : static_cast<float>(srcDesc.Width);
float srcBottom = dstBottom == static_cast<float>(dstDesc.Height) ?
dstBottom - pSoftwareCursor->Y : static_cast<float>(srcDesc.Height);
const float srcRight = dstRight == static_cast<float>(dstDesc.Width) ?
dstRight - dstLeft : static_cast<float>(srcDesc.Width);
const float srcBottom = dstBottom == static_cast<float>(dstDesc.Height) ?
dstBottom - dstTop : static_cast<float>(srcDesc.Height);
// Calculate normalized texture coordinates (will be < 1.0f to handle right/bottom edge cursor clipping)
srcRight /= static_cast<float>(srcDesc.Width);
srcBottom /= static_cast<float>(srcDesc.Height);

struct SWCURSORVERTEX {
FLOAT x, y, z, rhw;
FLOAT u, v;
};
const float normSrcRight = srcRight / static_cast<float>(srcDesc.Width);
const float normSrcBottom = srcBottom / static_cast<float>(srcDesc.Height);

std::array<SWCURSORVERTEX, 4> quadVertices = {{
std::array<SWCursorVertex, 4> quadVertices = {{
{ dstLeft, dstTop, 0.0f, 1.0f, 0.0f, 0.0f },
{ dstRight, dstTop, 0.0f, 1.0f, srcRight, 0.0f },
{ dstLeft, dstBottom, 0.0f, 1.0f, 0.0f, srcBottom },
{ dstRight, dstBottom, 0.0f, 1.0f, srcRight, srcBottom },
{ dstRight, dstTop, 0.0f, 1.0f, normSrcRight, 0.0f },
{ dstLeft, dstBottom, 0.0f, 1.0f, 0.0f, normSrcBottom },
{ dstRight, dstBottom, 0.0f, 1.0f, normSrcRight, normSrcBottom },
}};
const size_t quadVerticesSize = quadVertices.size() * sizeof(SWCURSORVERTEX);
const size_t quadVerticesSize = quadVertices.size() * sizeof(SWCursorVertex);

Com<IDirect3DVertexBuffer9> pVertexBuffer;
CreateVertexBuffer(quadVerticesSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
Expand All @@ -3592,21 +3585,21 @@ namespace dxvk {

// Temporarily enable alpha blending for the cursor texture
SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
// Temporarily disable culling while drawing the cursor quad, as some
// games may not render it at all otherwise, due to their own preset
// Temporarily disable culling while drawing the cursor quad,
// as some games may not render it at all otherwise
SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
// Filtering is not needed since our dimensions are exact
// and it only makes the cursor look more blurry
// Filtering is not needed since the dimensions are
// exact and it only makes the cursor look blurry
SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE);
SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
HRESULT hr = SetTexture(0, pSoftwareCursor->Bitmap.ptr());
if (FAILED(hr))
Logger::warn("D3D9DeviceEx::PresentEx: Failed to set software cursor bitmap texture");
Logger::err("D3D9DeviceEx::PresentEx: Failed setting software cursor texture");

hr = DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(SWCURSORVERTEX));
hr = DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pVertices, sizeof(SWCursorVertex));
if (FAILED(hr))
Logger::warn("D3D9DeviceEx::PresentEx: Failed on software cursor draw call");
Logger::err("D3D9DeviceEx::PresentEx: Failed software cursor draw call");

// Reinstate pre-cursor draw state
SetTexture(0, tex.ptr());
Expand Down
5 changes: 5 additions & 0 deletions src/d3d9/d3d9_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ namespace dxvk {
void* mapPtr = nullptr;
};

struct SWCursorVertex {
float x, y, z, rhw;
float u, v;
};

class D3D9DeviceEx final : public ComObjectClamp<IDirect3DDevice9Ex> {
constexpr static uint32_t DefaultFrameLatency = 3;
constexpr static uint32_t MaxFrameLatency = 20;
Expand Down