aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2019-12-16 00:09:52 +0800
committercrupest <crupest@outlook.com>2019-12-16 00:09:52 +0800
commit6ad6638adf64d958cdae44ce1df6a8a3787fed84 (patch)
tree030af9ca6e19bebc6250a8d278e46af7065fcd2f /src
parent221c62de313ad811ca2b3ae8ba43996c96c347bc (diff)
downloadcru-6ad6638adf64d958cdae44ce1df6a8a3787fed84.tar.gz
cru-6ad6638adf64d958cdae44ce1df6a8a3787fed84.tar.bz2
cru-6ad6638adf64d958cdae44ce1df6a8a3787fed84.zip
...
Diffstat (limited to 'src')
-rw-r--r--src/win/exception.cpp26
-rw-r--r--src/win/graph/direct/brush.cpp2
-rw-r--r--src/win/graph/direct/factory.cpp36
-rw-r--r--src/win/native/ui_application.cpp3
-rw-r--r--src/win/native/window.cpp2
-rw-r--r--src/win/native/window_d2d_painter.cpp21
-rw-r--r--src/win/native/window_d2d_painter.hpp8
-rw-r--r--src/win/native/window_render_target.cpp25
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