From 39422838b7478c4b7818b395c19d283e480627d0 Mon Sep 17 00:00:00 2001 From: jmsgrogan Date: Sun, 8 Jan 2023 12:41:09 +0000 Subject: [PATCH] Fix some window messaging bugs for dx. --- src/graphics/DrawingSurface.cpp | 2 +- src/graphics/DrawingSurface.h | 2 +- src/ui_elements/CMakeLists.txt | 12 ++- .../desktop_elements/DisplayState.h | 12 +++ src/ui_elements/desktop_elements/Window.cpp | 72 +++++++++++++++- src/ui_elements/desktop_elements/Window.h | 86 +++++++++---------- .../ui_interfaces/win32/Win32Window.cpp | 58 +++++++++++++ src/windows/ui_interfaces/win32/Win32Window.h | 2 +- .../win32/directx/DirectX2dIntegration.cpp | 3 + .../win32/directx/DirectXBuffers.cpp | 14 ++- .../win32/directx/DirectXBuffers.h | 3 + .../win32/directx/DirectXCommandList.cpp | 2 +- .../win32/directx/Win32DxWindowInterface.cpp | 37 ++++++-- 13 files changed, 237 insertions(+), 68 deletions(-) create mode 100644 src/ui_elements/desktop_elements/DisplayState.h diff --git a/src/graphics/DrawingSurface.cpp b/src/graphics/DrawingSurface.cpp index 5f7dd38..b1f00e6 100644 --- a/src/graphics/DrawingSurface.cpp +++ b/src/graphics/DrawingSurface.cpp @@ -15,7 +15,7 @@ std::unique_ptr DrawingSurface::Create() return std::make_unique(); } -void DrawingSurface::setSize(unsigned width, unsigned height) +void DrawingSurface::setSize(unsigned width, unsigned height, bool triggerResize) { mWidth = width; mHeight = height; diff --git a/src/graphics/DrawingSurface.h b/src/graphics/DrawingSurface.h index 07b9c44..c4babf4 100644 --- a/src/graphics/DrawingSurface.h +++ b/src/graphics/DrawingSurface.h @@ -15,7 +15,7 @@ public: static std::unique_ptr Create(); - virtual void setSize(unsigned width, unsigned height); + virtual void setSize(unsigned width, unsigned height, bool triggerResize = true); unsigned getWidth() const; diff --git a/src/ui_elements/CMakeLists.txt b/src/ui_elements/CMakeLists.txt index c3a7619..ef6bbee 100644 --- a/src/ui_elements/CMakeLists.txt +++ b/src/ui_elements/CMakeLists.txt @@ -1,19 +1,23 @@ list(APPEND ui_elements_LIB_INCLUDES + desktop_elements/Keyboard.h desktop_elements/Keyboard.cpp desktop_elements/IPlatformScreen.h + desktop_elements/Screen.h desktop_elements/Screen.cpp desktop_elements/IPlatformWindow.h + desktop_elements/Window.h desktop_elements/Window.cpp - ui_events/KeyboardEvent.cpp - ui_events/MouseEvent.cpp - ui_events/UiEvent.cpp - ui_events/PaintEvent.cpp ui_events/KeyboardEvent.h + ui_events/KeyboardEvent.cpp ui_events/MouseEvent.h + ui_events/MouseEvent.cpp ui_events/UiEvent.h + ui_events/UiEvent.cpp ui_events/PaintEvent.h + ui_events/PaintEvent.cpp ui_events/ResizeEvent.h ui_events/ResizeEvent.cpp + widgets/Widget.h widgets/Widget.cpp widgets/Button.cpp widgets/ButtonGroup.cpp diff --git a/src/ui_elements/desktop_elements/DisplayState.h b/src/ui_elements/desktop_elements/DisplayState.h new file mode 100644 index 0000000..1db3935 --- /dev/null +++ b/src/ui_elements/desktop_elements/DisplayState.h @@ -0,0 +1,12 @@ +#pragma once + +namespace WindowState +{ + enum class Display + { + NORMAL, + MINIMIZED, + MAXIMIZED, + FULL_SCREEN + }; +} diff --git a/src/ui_elements/desktop_elements/Window.cpp b/src/ui_elements/desktop_elements/Window.cpp index c1cbece..a6874cf 100644 --- a/src/ui_elements/desktop_elements/Window.cpp +++ b/src/ui_elements/desktop_elements/Window.cpp @@ -43,14 +43,37 @@ std::unique_ptr Window::Create() return std::make_unique(); } -void Window::setSize(unsigned width, unsigned height) +void Window::setIsSizingOnGoing(bool sizingOngoing) { + mSizingOngoing = sizingOngoing; +} + +bool Window::getIsSizingOnGoing() const +{ + return mSizingOngoing; +} + +void Window::setSize(unsigned width, unsigned height, bool triggerResize) +{ + if (width == mWidth && height == mHeight) + { + return; + } + DrawingSurface::setSize(width, height); - mWidget->setBounds(width, height); + if (triggerResize && !mSizingOngoing) + { + onResize(); + } +} + +void Window::onResize() +{ + mWidget->setBounds(mWidth, mHeight); if (mPlatformWindow) { - mPlatformWindow->onResize(width, height); + mPlatformWindow->onResize(mWidth, mHeight); } } @@ -151,4 +174,47 @@ bool Window::isDirty() const return mWidget->needsUpdate(); } +void Window::setDisplayState(WindowState::Display state) +{ + mDisplayState = state; +} + +WindowState::Display Window::getDisplayState() const +{ + return mDisplayState; +} + +void Window::setTitle(const std::string& title) +{ + mTitle = title; +} + +const std::string& Window::getTitle() const +{ + return mTitle; +} + +void Window::addPopup(std::unique_ptr popupWidget) +{ + if (mPopupFunc) + { + mPopupFunc(this, std::move(popupWidget)); + } +} + +void Window::setPopupHandler(onPopupFunc func) +{ + mPopupFunc = func; +} + +void Window::setParent(Window* parent) +{ + mParent = parent; +} + +Window* Window::getParent() const +{ + return mParent; +} + } diff --git a/src/ui_elements/desktop_elements/Window.h b/src/ui_elements/desktop_elements/Window.h index a31371b..38c9c66 100644 --- a/src/ui_elements/desktop_elements/Window.h +++ b/src/ui_elements/desktop_elements/Window.h @@ -1,6 +1,7 @@ #pragma once #include "DrawingSurface.h" +#include "DisplayState.h" #include #include @@ -30,7 +31,6 @@ class Window : public DrawingSurface { public: - using onPopupFunc = std::function popup)>; Window(); @@ -39,66 +39,55 @@ public: static std::unique_ptr Create(); - void setWidget(WidgetPtr widget); - - void onPaint(const PaintEvent* event); - - void onMouseEvent(const MouseEvent* event); - - void onKeyboardEvent(const KeyboardEvent* event); - - IPlatformWindow* getPlatformWindow() const; - - void setPlatformWindow(IPlatformWindowPtr window, FontsManager* fontsManager, DrawingMode drawingMode); - - void map(); - - void show(); - - void doPaint(mt::Screen* screen); + void addPopup(std::unique_ptr popupWidget); void clear(); void clearPlatformWindow(); - void setSize(unsigned width, unsigned height) override; + void doPaint(mt::Screen* screen); + + IPlatformWindow* getPlatformWindow() const; + + const std::string& getTitle() const; + + Window* getParent() const; + + DrawingContext* getDrawingContent() const; + + WindowState::Display getDisplayState() const; + + bool getIsSizingOnGoing() const; bool isDirty() const; - void setTitle(const std::string& title) - { - mTitle = title; - } + void map(); - const std::string& getTitle() const - { - return mTitle; - } + void onPaint(const PaintEvent* event); - void addPopup(std::unique_ptr popupWidget) - { - if (mPopupFunc) - { - mPopupFunc(this, std::move(popupWidget)); - } - } + void onMouseEvent(const MouseEvent* event); - void setPopupHandler(onPopupFunc func) - { - mPopupFunc = func; - } + void onResize(); - void setParent(Window* parent) - { - mParent = parent; - } + void onKeyboardEvent(const KeyboardEvent* event); - Window* getParent() const - { - return mParent; - } + void setPlatformWindow(IPlatformWindowPtr window, FontsManager* fontsManager, DrawingMode drawingMode); - DrawingContext* getDrawingContent() const; + void setPopupHandler(onPopupFunc func); + + void setParent(Window* parent); + + void show(); + + void setIsSizingOnGoing(bool sizingOngoing); + + void setSize(unsigned width, unsigned height, bool triggerResize = true) override; + + void setTitle(const std::string& title); + + void setWidget(WidgetPtr widget); + + void setDisplayState(WindowState::Display state); private: WidgetPtr mWidget {nullptr}; @@ -108,6 +97,9 @@ private: onPopupFunc mPopupFunc; Window* mParent{nullptr}; + + bool mSizingOngoing{ false }; + WindowState::Display mDisplayState{ WindowState::Display::NORMAL }; }; } diff --git a/src/windows/ui_interfaces/win32/Win32Window.cpp b/src/windows/ui_interfaces/win32/Win32Window.cpp index 252e04c..a43f3a1 100644 --- a/src/windows/ui_interfaces/win32/Win32Window.cpp +++ b/src/windows/ui_interfaces/win32/Win32Window.cpp @@ -104,10 +104,60 @@ LRESULT CALLBACK Win32Window::WindowProc(UINT message, WPARAM wParam, LPARAM lPa auto keyChar = (wchar_t)wParam; key_event->setKeyString(StringUtils::convert(std::wstring(1, keyChar))); mDesktopManager->onUiEvent(std::move(key_event)); + return 0; } case WM_PAINT: { onPaintMessage(); + return 0; + } + case WM_SIZE: + { + auto width = LOWORD(lParam); + auto height = HIWORD(lParam); + MLOG_INFO("WM_SIZE: " << width << " | " << height); + + mWindow->setSize(width, height, false); + if (wParam == SIZE_MINIMIZED) + { + mWindow->setDisplayState(WindowState::Display::MINIMIZED); + } + else if (wParam == SIZE_MAXIMIZED) + { + mWindow->setDisplayState(WindowState::Display::MAXIMIZED); + mWindow->onResize(); + } + else if (wParam == SIZE_RESTORED) + { + if (mWindow->getDisplayState() == WindowState::Display::MINIMIZED) + { + mWindow->setDisplayState(WindowState::Display::NORMAL); + mWindow->onResize(); + } + else if (mWindow->getDisplayState() == WindowState::Display::MAXIMIZED) + { + mWindow->setDisplayState(WindowState::Display::NORMAL); + mWindow->onResize(); + } + else if (!mWindow->getIsSizingOnGoing()) + { + mWindow->onResize(); + } + } + return 0; + } + case WM_ENTERSIZEMOVE: + { + MLOG_INFO("WM_ENTERSIZEMOVE"); + mWindow->setIsSizingOnGoing(true); + return 0; + } + case WM_EXITSIZEMOVE: + { + MLOG_INFO("WM_EXITSIZEMOVE"); + mWindow->setIsSizingOnGoing(false); + mWindow->onResize(); + return 0; } } return DefWindowProc(mHandle, message, wParam, lParam); @@ -171,4 +221,12 @@ void Win32Window::afterPaint(mt::Screen* screen) EndPaint(mHandle, &ps); } +} + +void Win32Window::onResize(unsigned width, unsigned height) +{ + if (mDxInterface) + { + mDxInterface->onResize(); + } } \ No newline at end of file diff --git a/src/windows/ui_interfaces/win32/Win32Window.h b/src/windows/ui_interfaces/win32/Win32Window.h index 9559180..4149128 100644 --- a/src/windows/ui_interfaces/win32/Win32Window.h +++ b/src/windows/ui_interfaces/win32/Win32Window.h @@ -43,7 +43,7 @@ public: void clear() {}; - void onResize(unsigned width, unsigned height) {}; + void onResize(unsigned width, unsigned height); void beforePaint(mt::Screen* screen); diff --git a/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp b/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp index a1c711d..cf96044 100644 --- a/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp +++ b/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp @@ -63,6 +63,9 @@ void DirectX2dIntegration::clearBuffers() buffer.Reset(); } mD2dRenderTargets.clear(); + + mDxInterface->getD2dContext()->SetTarget(nullptr); + mDxInterface->getD3d11DeviceContext()->Flush(); } void DirectX2dIntegration::wrapBuffer(ID3D12Resource* renderTarget) diff --git a/src/windows/ui_interfaces/win32/directx/DirectXBuffers.cpp b/src/windows/ui_interfaces/win32/directx/DirectXBuffers.cpp index e8fe2cf..c26d50d 100644 --- a/src/windows/ui_interfaces/win32/directx/DirectXBuffers.cpp +++ b/src/windows/ui_interfaces/win32/directx/DirectXBuffers.cpp @@ -2,6 +2,8 @@ #include "DirectXDescriptors.h" +#include "FileLogger.h" + #include #include #include @@ -17,10 +19,17 @@ void DirectXBuffers::clear() { for (auto& buffer : mBackBuffers) { - buffer.Reset(); + auto count = buffer.Reset(); } mBackBuffers.clear(); mDepthStencilBuffer.Reset(); + + mInitialized = false; +} + +bool DirectXBuffers::isInitialized() +{ + return mInitialized; } UINT DirectXBuffers::getCurrentBackBufferIndex() const @@ -57,8 +66,11 @@ void DirectXBuffers::setupBackBuffers(ID3D12Device* device, IDXGISwapChain4* swa swapChain->GetBuffer(i, IID_PPV_ARGS(&mBackBuffers[mBackBuffers.size()-1])); device->CreateRenderTargetView(mBackBuffers[mBackBuffers.size() - 1].Get(), nullptr, rtv_heap_handle); + rtv_heap_handle.Offset(1, descriptors->getRtvDescriptorSize()); + } + mInitialized = true; } void DirectXBuffers::setupDepthStencilHeap(ID3D12Device* device, unsigned width, unsigned height) diff --git a/src/windows/ui_interfaces/win32/directx/DirectXBuffers.h b/src/windows/ui_interfaces/win32/directx/DirectXBuffers.h index 71d3dd8..02785b6 100644 --- a/src/windows/ui_interfaces/win32/directx/DirectXBuffers.h +++ b/src/windows/ui_interfaces/win32/directx/DirectXBuffers.h @@ -23,6 +23,8 @@ public: ID3D12Resource* getDepthStencilBuffer() const; + bool isInitialized(); + void setupBackBuffers(ID3D12Device* device, IDXGISwapChain4* swapChain, DirectXDescriptors* descriptors); void setupDepthStencilHeap(ID3D12Device* device, unsigned width, unsigned height); @@ -32,6 +34,7 @@ public: void updateBackbufferIndex(UINT index); private: + bool mInitialized{ false }; UINT mFrameCount{ 2 }; UINT mBackBufferIndex{ 0 }; std::vector > mBackBuffers; diff --git a/src/windows/ui_interfaces/win32/directx/DirectXCommandList.cpp b/src/windows/ui_interfaces/win32/directx/DirectXCommandList.cpp index 01c3e04..e26a287 100644 --- a/src/windows/ui_interfaces/win32/directx/DirectXCommandList.cpp +++ b/src/windows/ui_interfaces/win32/directx/DirectXCommandList.cpp @@ -32,6 +32,6 @@ void DirectXCommandList::reset(ID3D12PipelineState* pso) void DirectXCommandList::resetAllocator() { - mCommandAllocator.Reset(); + mCommandAllocator->Reset(); } diff --git a/src/windows/ui_interfaces/win32/directx/Win32DxWindowInterface.cpp b/src/windows/ui_interfaces/win32/directx/Win32DxWindowInterface.cpp index 96142f6..69edcdb 100644 --- a/src/windows/ui_interfaces/win32/directx/Win32DxWindowInterface.cpp +++ b/src/windows/ui_interfaces/win32/directx/Win32DxWindowInterface.cpp @@ -46,6 +46,13 @@ void Win32DxWindowInterface::onRender() { if (!mIsValid) { + MLOG_INFO("Invalid state - returning"); + return; + } + + if (!mBuffers->isInitialized()) + { + MLOG_INFO("Buffer not initialized - returning"); return; } @@ -89,8 +96,8 @@ void Win32DxWindowInterface::updateCommandList() painter->paintMesh(mCommandList->get()); // Indicate that the back buffer will now be used to present. (Exclude as handled by D2D integration later) - //barrier = CD3DX12_RESOURCE_BARRIER::Transition(mRenderTargets[mFrameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); - //mCommandList->ResourceBarrier(1, &barrier); + //barrier = CD3DX12_RESOURCE_BARRIER::Transition(mBuffers->getCurrentBackBuffer(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); + //mCommandList->get()->ResourceBarrier(1, &barrier); mCommandList->close(); } @@ -102,6 +109,10 @@ bool Win32DxWindowInterface::initialize() return true; } mInitialized = true; + MLOG_INFO("D3D Win init"); + + mD2dIntegration = std::make_unique(mWindow, mDxInterface, FrameCount); + mBuffers = std::make_unique(FrameCount); if (!createSwapChain()) { @@ -115,8 +126,6 @@ bool Win32DxWindowInterface::initialize() mDescriptors = std::make_unique(); mDescriptors->setupDefaultDescriptorHeaps(mDxInterface->getD3dDevice()); - mD2dIntegration = std::make_unique(mWindow, mDxInterface, FrameCount); - mBuffers = std::make_unique(FrameCount); onResize(); @@ -133,6 +142,9 @@ bool Win32DxWindowInterface::initialize() void Win32DxWindowInterface::onResize() { + MLOG_INFO("On resize"); + mIsValid = false; + flushCommandQueue(); mCommandList->reset(getPipelineState()); @@ -150,12 +162,15 @@ void Win32DxWindowInterface::onResize() flushCommandQueue(); updateViewport(); + + mIsValid = true; } void Win32DxWindowInterface::resizeSwapChain() { const auto width = mWindow->getWidth(); const auto height = mWindow->getHeight(); + MLOG_INFO("Resizing swap chain to: " << width << " | " << height); mSwapChain->ResizeBuffers(FrameCount, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); updateBackbufferIndex(0); } @@ -170,8 +185,8 @@ void Win32DxWindowInterface::updateViewport() void Win32DxWindowInterface::clearBuffers() { - mBuffers->clear(); mD2dIntegration->clearBuffers(); + mBuffers->clear(); } ID3D12PipelineState* Win32DxWindowInterface::getPipelineState() const @@ -182,6 +197,7 @@ ID3D12PipelineState* Win32DxWindowInterface::getPipelineState() const void Win32DxWindowInterface::populateBuffers() { + MLOG_INFO("Populating buffers"); auto d3d_device = mDxInterface->getD3dDevice(); mBuffers->setupBackBuffers(d3d_device, mSwapChain.Get(), mDescriptors.get()); for (UINT idx = 0; idx < FrameCount; idx++) @@ -191,11 +207,14 @@ void Win32DxWindowInterface::populateBuffers() const auto width = mWindow->getWidth(); const auto height = mWindow->getHeight(); - mBuffers->setupDepthStencilHeap(mDxInterface->getD3dDevice(), width, height); - mBuffers->setupDepthStencilView(mDxInterface->getD3dDevice(), mDescriptors.get()); + if (width > 0 and height > 0) + { + mBuffers->setupDepthStencilHeap(mDxInterface->getD3dDevice(), width, height); + mBuffers->setupDepthStencilView(mDxInterface->getD3dDevice(), mDescriptors.get()); - auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(mBuffers->getDepthStencilBuffer(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_DEPTH_WRITE); - mCommandList->get()->ResourceBarrier(1, &barrier); + auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(mBuffers->getDepthStencilBuffer(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_DEPTH_WRITE); + mCommandList->get()->ResourceBarrier(1, &barrier); + } } bool Win32DxWindowInterface::createSwapChain()