From c34b93f00f3da9811b91e1850ac21ff7de962dcc Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 30 Nov 2015 14:33:14 -1000 Subject: [PATCH] Windows bug fixes --- include/boo/IWindow.hpp | 8 ++ .../boo/graphicsdev/IGraphicsCommandQueue.hpp | 1 - lib/graphicsdev/D3D11.cpp | 29 +++--- lib/graphicsdev/D3D12.cpp | 95 +++++++++++++++---- lib/graphicsdev/GL.cpp | 6 +- lib/win/ApplicationWin32.cpp | 10 ++ lib/win/Win32Common.hpp | 12 +++ lib/win/WindowWin32.cpp | 73 +++++++++++--- 8 files changed, 181 insertions(+), 53 deletions(-) diff --git a/include/boo/IWindow.hpp b/include/boo/IWindow.hpp index 0c74431..34292e6 100644 --- a/include/boo/IWindow.hpp +++ b/include/boo/IWindow.hpp @@ -22,6 +22,14 @@ struct SWindowRect { int location[2]; int size[2]; + bool operator !=(const SWindowRect& other) const + { + return location[0] != other.location[0] || + location[1] != other.location[1] || + size[0] != other.size[0] || + size[1] != other.size[1]; + } + bool operator ==(const SWindowRect& other) const {return !(*this != other);} }; struct SWindowCoord diff --git a/include/boo/graphicsdev/IGraphicsCommandQueue.hpp b/include/boo/graphicsdev/IGraphicsCommandQueue.hpp index f3c0c72..584f5fe 100644 --- a/include/boo/graphicsdev/IGraphicsCommandQueue.hpp +++ b/include/boo/graphicsdev/IGraphicsCommandQueue.hpp @@ -32,7 +32,6 @@ struct IGraphicsCommandQueue virtual int pendingDynamicSlot()=0; virtual void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)=0; - virtual void flushBufferUpdates()=0; virtual void setClearColor(const float rgba[4])=0; virtual void clearTarget(bool render=true, bool depth=true)=0; diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index 390a9f6..21d5acc 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -563,6 +563,8 @@ struct D3D11CommandQueue : IGraphicsCommandQueue D3D11Context::Window* m_windowCtx; IGraphicsContext* m_parent; ComPtr m_deferredCtx; + ComPtr m_dynamicCtx; + ComPtr m_dynamicList; size_t m_fillBuf = 0; size_t m_completeBuf = 0; @@ -594,6 +596,10 @@ struct D3D11CommandQueue : IGraphicsCommandQueue break; self->m_drawBuf = self->m_completeBuf; + ID3D11CommandList* list = self->m_dynamicList.Get(); + self->m_ctx->m_devCtx->ExecuteCommandList(list, false); + self->m_dynamicList.Reset(); + if (self->m_texResizes.size()) { for (const auto& resize : self->m_texResizes) @@ -620,7 +626,8 @@ struct D3D11CommandQueue : IGraphicsCommandQueue if (self->m_windowCtx->m_needsResize) { - self->m_windowCtx->m_swapChain->ResizeBuffers(2, self->m_windowCtx->width, self->m_windowCtx->height, + self->m_windowCtx->m_swapChain->ResizeBuffers(2, + self->m_windowCtx->width, self->m_windowCtx->height, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); self->m_windowCtx->m_needsResize = false; self->m_cmdLists[self->m_drawBuf].Reset(); @@ -663,6 +670,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue m_initcv.wait(m_initlk); m_initlk.unlock(); ThrowIfFailed(ctx->m_dev->CreateDeferredContext1(0, &m_deferredCtx)); + ThrowIfFailed(ctx->m_dev->CreateDeferredContext1(0, &m_dynamicCtx)); } ~D3D11CommandQueue() @@ -704,8 +712,6 @@ struct D3D11CommandQueue : IGraphicsCommandQueue int pendingDynamicSlot() {return m_fillBuf;} - void flushBufferUpdates() {} - std::unordered_map> m_texResizes; void resizeRenderTexture(ITextureR* tex, size_t width, size_t height) { @@ -773,6 +779,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue m_workDoPresent[m_fillBuf] = m_doPresent; m_doPresent = nullptr; std::unique_lock lk(m_mt); + ThrowIfFailed(m_dynamicCtx->FinishCommandList(false, &m_dynamicList)); m_completeBuf = m_fillBuf; for (size_t i=0 ; i<3 ; ++i) { @@ -790,42 +797,42 @@ void D3D11GraphicsBufferD::load(const void* data, size_t sz) { ID3D11Buffer* res = m_bufs[m_q->m_fillBuf].Get(); D3D11_MAPPED_SUBRESOURCE d; - m_q->m_deferredCtx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d); + m_q->m_dynamicCtx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d); memcpy(d.pData, data, sz); - m_q->m_deferredCtx->Unmap(res, 0); + m_q->m_dynamicCtx->Unmap(res, 0); } void* D3D11GraphicsBufferD::map(size_t sz) { ID3D11Buffer* res = m_bufs[m_q->m_fillBuf].Get(); D3D11_MAPPED_SUBRESOURCE d; - m_q->m_deferredCtx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d); + m_q->m_dynamicCtx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d); return d.pData; } void D3D11GraphicsBufferD::unmap() { ID3D11Buffer* res = m_bufs[m_q->m_fillBuf].Get(); - m_q->m_deferredCtx->Unmap(res, 0); + m_q->m_dynamicCtx->Unmap(res, 0); } void D3D11TextureD::load(const void* data, size_t sz) { ID3D11Texture2D* res = m_texs[m_q->m_fillBuf].Get(); D3D11_MAPPED_SUBRESOURCE d; - m_q->m_deferredCtx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d); + m_q->m_dynamicCtx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d); memcpy(d.pData, data, sz); - m_q->m_deferredCtx->Unmap(res, 0); + m_q->m_dynamicCtx->Unmap(res, 0); } void* D3D11TextureD::map(size_t sz) { ID3D11Texture2D* res = m_texs[m_q->m_fillBuf].Get(); D3D11_MAPPED_SUBRESOURCE d; - m_q->m_deferredCtx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d); + m_q->m_dynamicCtx->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &d); return d.pData; } void D3D11TextureD::unmap() { ID3D11Texture2D* res = m_texs[m_q->m_fillBuf].Get(); - m_q->m_deferredCtx->Unmap(res, 0); + m_q->m_dynamicCtx->Unmap(res, 0); } class D3D11DataFactory : public ID3DDataFactory diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index d1a0949..ae49a90 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -109,6 +109,7 @@ class D3D12GraphicsBufferD : public IGraphicsBufferD D3D12_RESOURCE_STATES m_state; size_t m_mappedSz; void* m_mappedBuf = nullptr; + unsigned m_loaded[2] = {}; D3D12GraphicsBufferD(D3D12CommandQueue* q, BufferUse use, D3D12Context* ctx, size_t stride, size_t count) : m_state(USE_TABLE[int(use)]), m_q(q), m_stride(stride), m_count(count) { @@ -527,6 +528,7 @@ class D3D12ShaderPipeline : public IShaderPipeline if (!backfaceCulling) desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; desc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; if (!depthTest) desc.DepthStencilState.DepthEnable = false; if (!depthWrite) @@ -840,10 +842,6 @@ static ID3D12GraphicsCommandList* WaitForLoadList(D3D12Context* ctx) { ThrowIfFailed(ctx->m_loadfence->SetEventOnCompletion(ctx->m_loadfenceval, ctx->m_loadfencehandle)); WaitForSingleObject(ctx->m_loadfencehandle, INFINITE); - - /* Reset allocator and list */ - ThrowIfFailed(ctx->m_loadqalloc->Reset()); - ThrowIfFailed(ctx->m_loadlist->Reset(ctx->m_loadqalloc.Get(), nullptr)); } return ctx->m_loadlist.Get(); } @@ -858,6 +856,14 @@ struct D3D12CommandQueue : IGraphicsCommandQueue ComPtr m_cmdList; ComPtr m_fence; + ComPtr m_dynamicCmdAlloc[2]; + ComPtr m_dynamicCmdQueue; + ComPtr m_dynamicCmdList; + UINT64 m_dynamicBufFenceVal = 0; + ComPtr m_dynamicBufFence; + HANDLE m_dynamicBufFenceHandle; + bool m_dynamicNeedsReset = false; + size_t m_fillBuf = 0; size_t m_drawBuf = 0; @@ -868,6 +874,27 @@ struct D3D12CommandQueue : IGraphicsCommandQueue m_cmdList->SetGraphicsRootSignature(m_ctx->m_rs.Get()); } + void resetDynamicCommandList() + { + ThrowIfFailed(m_dynamicCmdAlloc[m_fillBuf]->Reset()); + ThrowIfFailed(m_dynamicCmdList->Reset(m_dynamicCmdAlloc[m_fillBuf].Get(), nullptr)); + m_dynamicNeedsReset = false; + } + + void stallDynamicUpload() + { + if (m_dynamicNeedsReset) + { + if (m_dynamicBufFence->GetCompletedValue() < m_dynamicBufFenceVal) + { + ThrowIfFailed(m_dynamicBufFence->SetEventOnCompletion(m_dynamicBufFenceVal, + m_dynamicBufFenceHandle)); + WaitForSingleObject(m_dynamicBufFenceHandle, INFINITE); + } + resetDynamicCommandList(); + } + } + D3D12CommandQueue(D3D12Context* ctx, D3D12Context::Window* windowCtx, IGraphicsContext* parent, ID3D12CommandQueue** cmdQueueOut) : m_ctx(ctx), m_windowCtx(windowCtx), m_parent(parent) @@ -890,6 +917,15 @@ struct D3D12CommandQueue : IGraphicsCommandQueue ThrowIfFailed(ctx->m_dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, ctx->m_qalloc[0].Get(), nullptr, __uuidof(ID3D12GraphicsCommandList), &m_cmdList)); m_cmdList->SetGraphicsRootSignature(m_ctx->m_rs.Get()); + + ThrowIfFailed(ctx->m_dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), &m_dynamicBufFence)); + m_dynamicBufFenceHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); + ThrowIfFailed(ctx->m_dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, + __uuidof(ID3D12CommandAllocator), &m_dynamicCmdAlloc[0])); + ThrowIfFailed(ctx->m_dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, + __uuidof(ID3D12CommandAllocator), &m_dynamicCmdAlloc[1])); + ThrowIfFailed(ctx->m_dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_dynamicCmdAlloc[0].Get(), + nullptr, __uuidof(ID3D12GraphicsCommandList), &m_dynamicCmdList)); } void setShaderDataBinding(IShaderDataBinding* binding) @@ -931,8 +967,6 @@ struct D3D12CommandQueue : IGraphicsCommandQueue int pendingDynamicSlot() {return m_fillBuf;} - void flushBufferUpdates() {} - std::unordered_map> m_texResizes; void resizeRenderTexture(ITextureR* tex, size_t width, size_t height) { @@ -1065,12 +1099,23 @@ struct D3D12CommandQueue : IGraphicsCommandQueue UINT64 m_submittedFenceVal = 0; void execute() { + /* Perform dynamic uploads */ + if (!m_dynamicNeedsReset) + { + m_dynamicCmdList->Close(); + ID3D12CommandList* dcl[] = {m_dynamicCmdList.Get()}; + m_ctx->m_q->ExecuteCommandLists(1, dcl); + ++m_dynamicBufFenceVal; + ThrowIfFailed(m_ctx->m_q->Signal(m_dynamicBufFence.Get(), m_dynamicBufFenceVal)); + } + /* Check on fence */ if (m_fence->GetCompletedValue() < m_submittedFenceVal) { /* Abandon this list (renderer too slow) */ m_cmdList->Close(); resetCommandList(); + m_dynamicNeedsReset = true; m_doPresent = false; return; } @@ -1083,14 +1128,13 @@ struct D3D12CommandQueue : IGraphicsCommandQueue m_texResizes.clear(); m_cmdList->Close(); resetCommandList(); + m_dynamicNeedsReset = true; m_doPresent = false; return; } m_drawBuf = m_fillBuf; - ++m_fillBuf; - if (m_fillBuf == 2) - m_fillBuf = 0; + m_fillBuf ^= 1; m_cmdList->Close(); ID3D12CommandList* cl[] = {m_cmdList.Get()}; @@ -1107,19 +1151,21 @@ struct D3D12CommandQueue : IGraphicsCommandQueue ThrowIfFailed(m_ctx->m_q->Signal(m_fence.Get(), m_submittedFenceVal)); resetCommandList(); + resetDynamicCommandList(); } }; void D3D12GraphicsBufferD::load(const void* data, size_t sz) { + m_q->stallDynamicUpload(); ID3D12Resource* res = m_bufs[m_q->m_fillBuf].Get(); ID3D12Resource* gpuRes = m_gpuBufs[m_q->m_fillBuf].Get(); D3D12_SUBRESOURCE_DATA d = {data, LONG_PTR(sz), LONG_PTR(sz)}; - m_q->m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, m_state, D3D12_RESOURCE_STATE_COPY_DEST)); - if (!UpdateSubresources<1>(m_q->m_cmdList.Get(), gpuRes, res, 0, 0, 1, &d)) + if (!UpdateSubresources<1>(m_q->m_dynamicCmdList.Get(), gpuRes, res, 0, 0, 1, &d)) Log.report(LogVisor::FatalError, "unable to update dynamic buffer data"); - m_q->m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, D3D12_RESOURCE_STATE_COPY_DEST, m_state)); } void* D3D12GraphicsBufferD::map(size_t sz) @@ -1132,29 +1178,31 @@ void* D3D12GraphicsBufferD::map(size_t sz) } void D3D12GraphicsBufferD::unmap() { + m_q->stallDynamicUpload(); ID3D12Resource* res = m_bufs[m_q->m_fillBuf].Get(); ID3D12Resource* gpuRes = m_gpuBufs[m_q->m_fillBuf].Get(); D3D12_SUBRESOURCE_DATA data = {m_mappedBuf, LONG_PTR(m_mappedSz), LONG_PTR(m_mappedSz)}; - m_q->m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, m_state, D3D12_RESOURCE_STATE_COPY_DEST)); - if (!UpdateSubresources<1>(m_q->m_cmdList.Get(), gpuRes, res, 0, 0, 1, &data)) + if (!UpdateSubresources<1>(m_q->m_dynamicCmdList.Get(), gpuRes, res, 0, 0, 1, &data)) Log.report(LogVisor::FatalError, "unable to update dynamic buffer data"); free(m_mappedBuf); m_mappedBuf = nullptr; - m_q->m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, D3D12_RESOURCE_STATE_COPY_DEST, m_state)); } void D3D12TextureD::load(const void* data, size_t sz) { + m_q->stallDynamicUpload(); ID3D12Resource* res = m_texs[m_q->m_fillBuf].Get(); ID3D12Resource* gpuRes = m_gpuTexs[m_q->m_fillBuf].Get(); D3D12_SUBRESOURCE_DATA d = {data, LONG_PTR(m_width * 4), LONG_PTR(sz)}; - m_q->m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_DEST)); - if (!UpdateSubresources<1>(m_q->m_cmdList.Get(), gpuRes, res, 0, 0, 1, &d)) + if (!UpdateSubresources<1>(m_q->m_dynamicCmdList.Get(), gpuRes, res, 0, 0, 1, &d)) Log.report(LogVisor::FatalError, "unable to update dynamic texture data"); - m_q->m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); } void* D3D12TextureD::map(size_t sz) @@ -1167,16 +1215,17 @@ void* D3D12TextureD::map(size_t sz) } void D3D12TextureD::unmap() { + m_q->stallDynamicUpload(); ID3D12Resource* res = m_texs[m_q->m_fillBuf].Get(); ID3D12Resource* gpuRes = m_gpuTexs[m_q->m_fillBuf].Get(); D3D12_SUBRESOURCE_DATA data = {m_mappedBuf, LONG_PTR(m_width * 4), LONG_PTR(m_mappedSz)}; - m_q->m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_DEST)); - if (!UpdateSubresources<1>(m_q->m_cmdList.Get(), gpuRes, res, 0, 0, 1, &data)) + if (!UpdateSubresources<1>(m_q->m_dynamicCmdList.Get(), gpuRes, res, 0, 0, 1, &data)) Log.report(LogVisor::FatalError, "unable to update dynamic buffer data"); free(m_mappedBuf); m_mappedBuf = nullptr; - m_q->m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, + m_q->m_dynamicCmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(gpuRes, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); } @@ -1430,6 +1479,10 @@ public: /* Block handle return until data is ready on GPU */ WaitForLoadList(m_ctx); + /* Reset allocator and list */ + ThrowIfFailed(m_ctx->m_loadqalloc->Reset()); + ThrowIfFailed(m_ctx->m_loadlist->Reset(m_ctx->m_loadqalloc.Get(), nullptr)); + /* Delete static upload heaps */ for (std::unique_ptr& buf : retval->m_SBufs) buf->m_buf.Reset(); diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index 6d7e432..da0e393 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -924,11 +924,6 @@ struct GLCommandQueue : IGraphicsCommandQueue m_pendingResizes.push_back({texgl, width, height}); } - void flushBufferUpdates() - { - glFlush(); - } - void setClearColor(const float rgba[4]) { std::vector& cmds = m_cmdBufs[m_fillBuf]; @@ -1027,6 +1022,7 @@ struct GLCommandQueue : IGraphicsCommandQueue void execute() { + glFlush(); std::unique_lock lk(m_mt); m_completeBuf = m_fillBuf; for (size_t i=0 ; i<3 ; ++i) diff --git a/lib/win/ApplicationWin32.cpp b/lib/win/ApplicationWin32.cpp index be0ec62..411d6d0 100644 --- a/lib/win/ApplicationWin32.cpp +++ b/lib/win/ApplicationWin32.cpp @@ -57,6 +57,7 @@ static bool FindBestD3DCompile() namespace boo { static LogVisor::LogModule Log("boo::ApplicationWin32"); +Win32Cursors WIN32_CURSORS; IWindow* _WindowWin32New(const SystemString& title, Boo3DAppContext& d3dCtx); @@ -92,6 +93,11 @@ public: m_args(args), m_singleInstance(singleInstance) { + WIN32_CURSORS.m_arrow = LoadCursor(nullptr, IDC_ARROW); + WIN32_CURSORS.m_hResize = LoadCursor(nullptr, IDC_SIZEWE); + WIN32_CURSORS.m_vResize = LoadCursor(nullptr, IDC_SIZENS); + WIN32_CURSORS.m_wait = LoadCursor(nullptr, IDC_WAIT); + HMODULE dxgilib = LoadLibraryW(L"dxgi.dll"); if (!dxgilib) Log.report(LogVisor::FatalError, "unable to load dxgi.dll"); @@ -299,6 +305,10 @@ public: /* Quit message from client thread */ PostQuitMessage(0); continue; + case WM_USER+2: + /* SetCursor call from client thread */ + SetCursor(HCURSOR(msg.wParam)); + continue; default: TranslateMessage(&msg); DispatchMessage(&msg); diff --git a/lib/win/Win32Common.hpp b/lib/win/Win32Common.hpp index dac8c28..d30c867 100644 --- a/lib/win/Win32Common.hpp +++ b/lib/win/Win32Common.hpp @@ -255,4 +255,16 @@ struct HWNDEvent : uMsg(m), wParam(w), lParam(l) {} }; +struct Win32Cursors +{ + HCURSOR m_arrow; + HCURSOR m_hResize; + HCURSOR m_vResize; + HCURSOR m_wait; +}; +namespace boo +{ +extern Win32Cursors WIN32_CURSORS; +} + #endif // BOO_WIN32COMMON_HPP diff --git a/lib/win/WindowWin32.cpp b/lib/win/WindowWin32.cpp index 480aefa..bedab27 100644 --- a/lib/win/WindowWin32.cpp +++ b/lib/win/WindowWin32.cpp @@ -442,6 +442,22 @@ class WindowWin32 : public IWindow HWND m_hwnd; std::unique_ptr m_gfxCtx; IWindowCallback* m_callback = nullptr; + EMouseCursor m_cursor = EMouseCursor::None; + bool m_cursorWait = false; + static HCURSOR GetWin32Cursor(EMouseCursor cur) + { + switch (cur) + { + case EMouseCursor::Pointer: + return WIN32_CURSORS.m_arrow; + case EMouseCursor::HorizontalArrow: + return WIN32_CURSORS.m_hResize; + case EMouseCursor::VerticalArrow: + return WIN32_CURSORS.m_vResize; + default: break; + } + return WIN32_CURSORS.m_arrow; + } public: @@ -495,6 +511,33 @@ public: SetWindowTextW(m_hwnd, title.c_str()); } + static void _setCursor(HCURSOR cur) + { + PostThreadMessageW(g_mainThreadId, WM_USER+2, WPARAM(cur), 0); + } + + void setCursor(EMouseCursor cursor) + { + if (cursor == m_cursor && !m_cursorWait) + return; + m_cursor = cursor; + _setCursor(GetWin32Cursor(cursor)); + } + + void setWaitCursor(bool wait) + { + if (wait && !m_cursorWait) + { + _setCursor(WIN32_CURSORS.m_wait); + m_cursorWait = true; + } + else if (!wait && m_cursorWait) + { + setCursor(m_cursor); + m_cursorWait = false; + } + } + void setWindowFrameDefault() { MONITORINFO monInfo; @@ -576,9 +619,9 @@ public: EModifierKey modifierMask = translateModifiers(e.uMsg); SWindowCoord coord = { - {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)}, - {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)}, - {float(GET_X_LPARAM(e.lParam)) / float(w), float(GET_Y_LPARAM(e.lParam)) / float(h)} + {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam))}, + {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam))}, + {float(GET_X_LPARAM(e.lParam)) / float(w), float(h-GET_Y_LPARAM(e.lParam)) / float(h)} }; m_callback->mouseDown(coord, button, modifierMask); } @@ -593,9 +636,9 @@ public: EModifierKey modifierMask = translateModifiers(e.uMsg); SWindowCoord coord = { - {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)}, - {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)}, - {float(GET_X_LPARAM(e.lParam)) / float(w), float(GET_Y_LPARAM(e.lParam)) / float(h)} + {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam))}, + {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam))}, + {float(GET_X_LPARAM(e.lParam)) / float(w), float(h-GET_Y_LPARAM(e.lParam)) / float(h)} }; m_callback->mouseUp(coord, button, modifierMask); } @@ -732,9 +775,9 @@ public: getWindowFrame(x, y, w, h); SWindowCoord coord = { - {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)}, - {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)}, - {float(GET_X_LPARAM(e.lParam)) / float(w), float(GET_Y_LPARAM(e.lParam)) / float(h)} + {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam))}, + {(unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam))}, + {float(GET_X_LPARAM(e.lParam)) / float(w), float(h-GET_Y_LPARAM(e.lParam)) / float(h)} }; if (!mouseTracking) { @@ -757,9 +800,9 @@ public: getWindowFrame(x, y, w, h); SWindowCoord coord = { - { (unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam) }, - { (unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam) }, - { float(GET_X_LPARAM(e.lParam)) / float(w), float(GET_Y_LPARAM(e.lParam)) / float(h) } + { (unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam)) }, + { (unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam)) }, + { float(GET_X_LPARAM(e.lParam)) / float(w), float(h-GET_Y_LPARAM(e.lParam)) / float(h) } }; m_callback->mouseLeave(coord); mouseTracking = false; @@ -775,9 +818,9 @@ public: getWindowFrame(x, y, w, h); SWindowCoord coord = { - { (unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam) }, - { (unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam) }, - { float(GET_X_LPARAM(e.lParam)) / float(w), float(GET_Y_LPARAM(e.lParam)) / float(h) } + { (unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam)) }, + { (unsigned)GET_X_LPARAM(e.lParam), (unsigned)(h-GET_Y_LPARAM(e.lParam)) }, + { float(GET_X_LPARAM(e.lParam)) / float(w), float(h-GET_Y_LPARAM(e.lParam)) / float(h) } }; m_callback->mouseEnter(coord); }