diff options
author | crupest <crupest@outlook.com> | 2019-12-16 00:09:52 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-12-16 00:09:52 +0800 |
commit | 6ad6638adf64d958cdae44ce1df6a8a3787fed84 (patch) | |
tree | 030af9ca6e19bebc6250a8d278e46af7065fcd2f /src | |
parent | 221c62de313ad811ca2b3ae8ba43996c96c347bc (diff) | |
download | cru-6ad6638adf64d958cdae44ce1df6a8a3787fed84.tar.gz cru-6ad6638adf64d958cdae44ce1df6a8a3787fed84.tar.bz2 cru-6ad6638adf64d958cdae44ce1df6a8a3787fed84.zip |
...
Diffstat (limited to 'src')
-rw-r--r-- | src/win/exception.cpp | 26 | ||||
-rw-r--r-- | src/win/graph/direct/brush.cpp | 2 | ||||
-rw-r--r-- | src/win/graph/direct/factory.cpp | 36 | ||||
-rw-r--r-- | src/win/native/ui_application.cpp | 3 | ||||
-rw-r--r-- | src/win/native/window.cpp | 2 | ||||
-rw-r--r-- | src/win/native/window_d2d_painter.cpp | 21 | ||||
-rw-r--r-- | src/win/native/window_d2d_painter.hpp | 8 | ||||
-rw-r--r-- | src/win/native/window_render_target.cpp | 25 |
8 files changed, 61 insertions, 62 deletions
diff --git a/src/win/exception.cpp b/src/win/exception.cpp index 271067fc..e0f114b5 100644 --- a/src/win/exception.cpp +++ b/src/win/exception.cpp @@ -11,11 +11,9 @@ inline std::string HResultMakeMessage(HRESULT h_result, sprintf_s(buffer, "%#08x", h_result); if (message) - return Format( - "An HResultError is thrown. HRESULT: {}.\nAdditional message: {}\n", - buffer, *message); + return Format("HRESULT: {}.\nMessage: {}\n", buffer, *message); else - return Format("An HResultError is thrown. HRESULT: {}.\n", buffer); + return Format("HRESULT: {}.\n", buffer); } HResultError::HResultError(HRESULT h_result) @@ -28,23 +26,17 @@ HResultError::HResultError(HRESULT h_result, h_result_(h_result) {} inline std::string Win32MakeMessage(DWORD error_code, - const std::string_view* message) { + const std::string_view& message) { char buffer[20]; sprintf_s(buffer, "%#04x", error_code); - if (message) - return Format("Last error code: {}.\nAdditional message: {}\n", buffer, - *message); - else - return Format("Last error code: {}.\n", buffer); + return Format("Last error code: {}.\nMessage: {}\n", buffer, message); } -Win32Error::Win32Error(DWORD error_code) - : PlatformException(Win32MakeMessage(error_code, nullptr)), - error_code_(error_code) {} +Win32Error::Win32Error(const std::string_view& message) + : Win32Error(::GetLastError(), message) {} -Win32Error::Win32Error(DWORD error_code, - const std::string_view& additional_message) - : PlatformException(Win32MakeMessage(error_code, &additional_message)), +Win32Error::Win32Error(DWORD error_code, const std::string_view& message) + : PlatformException(Win32MakeMessage(error_code, message)), error_code_(error_code) {} -} // namespace cru::win +} // namespace cru::platform::win diff --git a/src/win/graph/direct/brush.cpp b/src/win/graph/direct/brush.cpp index 17024a66..b30d8c24 100644 --- a/src/win/graph/direct/brush.cpp +++ b/src/win/graph/direct/brush.cpp @@ -9,7 +9,7 @@ namespace cru::platform::graph::win::direct { D2DSolidColorBrush::D2DSolidColorBrush(DirectGraphFactory* factory) : DirectGraphResource(factory) { - ThrowIfFailed(factory->GetD2D1DeviceContext()->CreateSolidColorBrush( + ThrowIfFailed(factory->GetDefaultD2D1DeviceContext()->CreateSolidColorBrush( Convert(color_), &brush_)); } diff --git a/src/win/graph/direct/factory.cpp b/src/win/graph/direct/factory.cpp index 1fff9fa9..e67bdafe 100644 --- a/src/win/graph/direct/factory.cpp +++ b/src/win/graph/direct/factory.cpp @@ -1,5 +1,6 @@ #include "cru/win/graph/direct/factory.hpp" +#include "cru/common/logger.hpp" #include "cru/win/graph/direct/brush.hpp" #include "cru/win/graph/direct/exception.hpp" #include "cru/win/graph/direct/font.hpp" @@ -11,10 +12,28 @@ #include <utility> namespace cru::platform::graph::win::direct { +namespace { +void InitializeCom() { + const auto hresult = ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (FAILED(hresult)) { + throw HResultError(hresult, "Failed to call CoInitializeEx."); + } + if (hresult == S_FALSE) { + log::Debug( + "Try to call CoInitializeEx, but it seems COM is already " + "initialized."); + } +} + +void UninitializeCom() { ::CoUninitialize(); } +} // namespace + DirectGraphFactory::DirectGraphFactory() { // TODO! Detect repeated creation. Because I don't think we can create two d2d // and dwrite factory so we need to prevent the "probably dangerous" behavior. + InitializeCom(); + UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #ifdef CRU_DEBUG @@ -39,12 +58,9 @@ DirectGraphFactory::DirectGraphFactory() { ThrowIfFailed(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, IID_PPV_ARGS(&d2d1_factory_))); - Microsoft::WRL::ComPtr<ID2D1Device> d2d1_device; + ThrowIfFailed(d2d1_factory_->CreateDevice(dxgi_device.Get(), &d2d1_device_)); - ThrowIfFailed(d2d1_factory_->CreateDevice(dxgi_device.Get(), &d2d1_device)); - - ThrowIfFailed(d2d1_device->CreateDeviceContext( - D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &d2d1_device_context_)); + d2d1_device_context_ = CreateD2D1DeviceContext(); // Identify the physical adapter (GPU or card) this device is runs on. Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter; @@ -61,6 +77,16 @@ DirectGraphFactory::DirectGraphFactory() { &dwrite_system_font_collection_)); } +DirectGraphFactory::~DirectGraphFactory() { UninitializeCom(); } + +Microsoft::WRL::ComPtr<ID2D1DeviceContext> +DirectGraphFactory::CreateD2D1DeviceContext() { + Microsoft::WRL::ComPtr<ID2D1DeviceContext> d2d1_device_context; + ThrowIfFailed(d2d1_device_->CreateDeviceContext( + D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &d2d1_device_context)); + return d2d1_device_context; +} + std::unique_ptr<ISolidColorBrush> DirectGraphFactory::CreateSolidColorBrush() { return std::make_unique<D2DSolidColorBrush>(this); } diff --git a/src/win/native/ui_application.cpp b/src/win/native/ui_application.cpp index 0ae8ee81..75fce6ce 100644 --- a/src/win/native/ui_application.cpp +++ b/src/win/native/ui_application.cpp @@ -28,8 +28,7 @@ WinUiApplication::WinUiApplication() { instance_handle_ = ::GetModuleHandleW(nullptr); if (!instance_handle_) - throw Win32Error(::GetLastError(), - "Failed to get module(instance) handle."); + throw Win32Error("Failed to get module(instance) handle."); log::Logger::GetInstance()->AddSource( std::make_unique<::cru::platform::win::WinDebugLoggerSource>()); diff --git a/src/win/native/window.cpp b/src/win/native/window.cpp index f996af02..d3c12a44 100644 --- a/src/win/native/window.cpp +++ b/src/win/native/window.cpp @@ -163,7 +163,7 @@ void WinNativeWindow::RequestRepaint() { } std::unique_ptr<graph::IPainter> WinNativeWindow::BeginPaint() { - return std::make_unique<WindowD2DPainter>(this); + return std::make_unique<WindowD2DPainter>(window_render_target_.get()); } void WinNativeWindow::SetCursor(std::shared_ptr<ICursor> cursor) { diff --git a/src/win/native/window_d2d_painter.cpp b/src/win/native/window_d2d_painter.cpp index ab74a964..023559f4 100644 --- a/src/win/native/window_d2d_painter.cpp +++ b/src/win/native/window_d2d_painter.cpp @@ -9,25 +9,16 @@ namespace cru::platform::native::win { using namespace cru::platform::graph::win::direct; -WindowD2DPainter::WindowD2DPainter(WinNativeWindow* window) - : D2DPainter(window->GetWindowRenderTarget() - ->GetDirectFactory() - ->GetD2D1DeviceContext()), - window_(window) { - window->GetWindowRenderTarget()->SetAsTarget(); - window->GetWindowRenderTarget() - ->GetDirectFactory() - ->GetD2D1DeviceContext() - ->BeginDraw(); +WindowD2DPainter::WindowD2DPainter(WindowRenderTarget* render_target) + : D2DPainter(render_target->GetD2D1DeviceContext()), + render_target_(render_target) { + render_target_->GetD2D1DeviceContext()->BeginDraw(); } WindowD2DPainter::~WindowD2DPainter() { EndDraw(); } void WindowD2DPainter::DoEndDraw() { - ThrowIfFailed(window_->GetWindowRenderTarget() - ->GetDirectFactory() - ->GetD2D1DeviceContext() - ->EndDraw()); - window_->GetWindowRenderTarget()->Present(); + ThrowIfFailed(render_target_->GetD2D1DeviceContext()->EndDraw()); + render_target_->Present(); } } // namespace cru::platform::native::win diff --git a/src/win/native/window_d2d_painter.hpp b/src/win/native/window_d2d_painter.hpp index 6877babd..40a5dee6 100644 --- a/src/win/native/window_d2d_painter.hpp +++ b/src/win/native/window_d2d_painter.hpp @@ -1,19 +1,21 @@ #pragma once #include "cru/win/graph/direct/painter.hpp" -#include "cru/win/native/window.hpp" +#include "cru/win/native/window_render_target.hpp" namespace cru::platform::native::win { class WindowD2DPainter : public graph::win::direct::D2DPainter { public: - explicit WindowD2DPainter(WinNativeWindow* window); + explicit WindowD2DPainter(WindowRenderTarget* window); + CRU_DELETE_COPY(WindowD2DPainter) CRU_DELETE_MOVE(WindowD2DPainter) + ~WindowD2DPainter() override; protected: void DoEndDraw() override; private: - WinNativeWindow* window_; + WindowRenderTarget* render_target_; }; } // namespace cru::platform::native::win diff --git a/src/win/native/window_render_target.cpp b/src/win/native/window_render_target.cpp index f15aeb6e..23ad2afa 100644 --- a/src/win/native/window_render_target.cpp +++ b/src/win/native/window_render_target.cpp @@ -15,6 +15,8 @@ WindowRenderTarget::WindowRenderTarget(DirectGraphFactory* factory, HWND hwnd) const auto d3d11_device = factory->GetD3D11Device(); const auto dxgi_factory = factory->GetDxgiFactory(); + d2d1_device_context_ = factory->CreateD2D1DeviceContext(); + // Allocate a descriptor. DXGI_SWAP_CHAIN_DESC1 swap_chain_desc; swap_chain_desc.Width = 0; // use automatic sizing @@ -41,27 +43,12 @@ WindowRenderTarget::WindowRenderTarget(DirectGraphFactory* factory, HWND hwnd) } void WindowRenderTarget::ResizeBuffer(const int width, const int height) { - const auto factory = factory_; - const auto d2d1_device_context = factory->GetD2D1DeviceContext(); - - Microsoft::WRL::ComPtr<ID2D1Image> old_target; - d2d1_device_context->GetTarget(&old_target); - const auto target_this = old_target == this->target_bitmap_; - if (target_this) d2d1_device_context->SetTarget(nullptr); - - old_target = nullptr; + // In order to resize buffer, we need to untarget the buffer first. + d2d1_device_context_->SetTarget(nullptr); target_bitmap_ = nullptr; - ThrowIfFailed(dxgi_swap_chain_->ResizeBuffers(0, width, height, DXGI_FORMAT_UNKNOWN, 0)); - CreateTargetBitmap(); - - if (target_this) d2d1_device_context->SetTarget(target_bitmap_.Get()); -} - -void WindowRenderTarget::SetAsTarget() { - factory_->GetD2D1DeviceContext()->SetTarget(target_bitmap_.Get()); } void WindowRenderTarget::Present() { @@ -85,7 +72,9 @@ void WindowRenderTarget::CreateTargetBitmap() { // Get a D2D surface from the DXGI back buffer to use as the D2D render // target. - ThrowIfFailed(factory_->GetD2D1DeviceContext()->CreateBitmapFromDxgiSurface( + ThrowIfFailed(d2d1_device_context_->CreateBitmapFromDxgiSurface( dxgi_back_buffer.Get(), &bitmap_properties, &target_bitmap_)); + + d2d1_device_context_->SetTarget(target_bitmap_.Get()); } } // namespace cru::platform::native::win |