diff options
author | Neil <nyamatongwe@gmail.com> | 2025-02-09 21:32:47 +1100 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2025-02-09 21:32:47 +1100 |
commit | 883a12357e66c08d9519671b278fd19cb5009570 (patch) | |
tree | 00974a9f42c8bd941b4a5aefacabcf10c9314c92 /win32 | |
parent | 4c032434c9e1181bb6a66348905f5e0f1c43f25a (diff) | |
download | scintilla-mirror-883a12357e66c08d9519671b278fd19cb5009570.tar.gz |
Add RenderTargets to hold one render target at a time, either Hwnd or DC.
Drawing code just needs one or the other but other calls need a particular type
with casting hiding potential problems. This will be more important in the
future when a third type of render target ID2D1DeviceContext will be added.
Use unique_ptr more for render targets to ensure they are freed correctly.
Diffstat (limited to 'win32')
-rw-r--r-- | win32/PlatWin.cxx | 26 | ||||
-rw-r--r-- | win32/PlatWin.h | 5 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 82 |
3 files changed, 74 insertions, 39 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 8a4724480..f593063f5 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -139,6 +139,16 @@ bool LoadD2D() noexcept { return pIDWriteFactory && pD2DFactory; } +HRESULT CreateDCRenderTarget(const D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties, DCRenderTarget &dcRT) noexcept { + dcRT.reset(); + ID2D1DCRenderTarget *pDCRT{}; + const HRESULT hr = pD2DFactory->CreateDCRenderTarget(renderTargetProperties, &pDCRT); + if (SUCCEEDED(hr) && pDCRT) { + dcRT.reset(pDCRT); + } + return hr; +} + constexpr D2D_COLOR_F ColorFromColourAlpha(ColourRGBA colour) noexcept { return D2D_COLOR_F{ colour.GetRedComponent(), @@ -2921,15 +2931,14 @@ public: D2D1_ALPHA_MODE_PREMULTIPLIED ); - ID2D1DCRenderTarget *pTarget_ = nullptr; - HRESULT hr = pD2DFactory->CreateDCRenderTarget(&drtp, &pTarget_); - if (FAILED(hr) || !pTarget_) { + DCRenderTarget pTarget; + HRESULT hr = CreateDCRenderTarget(&drtp, pTarget); + if (FAILED(hr) || !pTarget) { return false; } - const std::unique_ptr<ID2D1DCRenderTarget, UnknownReleaser> pTarget(pTarget_); const RECT rc = {0, 0, width, height}; - hr = pTarget_->BindDC(hMemDC, &rc); + hr = pTarget->BindDC(hMemDC, &rc); if (FAILED(hr)) { return false; } @@ -3509,8 +3518,8 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT ); - ID2D1DCRenderTarget *pDCRT = nullptr; - HRESULT hr = pD2DFactory->CreateDCRenderTarget(&props, &pDCRT); + DCRenderTarget pDCRT; + HRESULT hr = CreateDCRenderTarget(&props, pDCRT); if (SUCCEEDED(hr) && pDCRT) { const long left = pDrawItem->rcItem.left + static_cast<long>(ItemInset.x + ImageInset.x); @@ -3520,13 +3529,12 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { hr = pDCRT->BindDC(pDrawItem->hDC, &rcItem); if (SUCCEEDED(hr)) { - surfaceItem->Init(pDCRT, pDrawItem->hwndItem); + surfaceItem->Init(pDCRT.get(), pDrawItem->hwndItem); pDCRT->BeginDraw(); const PRectangle rcImage = PRectangle::FromInts(0, 0, images.GetWidth(), rcItem.bottom - rcItem.top); surfaceItem->DrawRGBAImage(rcImage, pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels()); pDCRT->EndDraw(); - ReleaseUnknown(pDCRT); } } #endif diff --git a/win32/PlatWin.h b/win32/PlatWin.h index ec1281979..8a651dd74 100644 --- a/win32/PlatWin.h +++ b/win32/PlatWin.h @@ -71,6 +71,11 @@ extern bool LoadD2D() noexcept; extern ID2D1Factory *pD2DFactory; extern IDWriteFactory *pIDWriteFactory; +using DCRenderTarget = std::unique_ptr<ID2D1DCRenderTarget, UnknownReleaser>; +using HwndRenderTarget = std::unique_ptr<ID2D1HwndRenderTarget, UnknownReleaser>; + +HRESULT CreateDCRenderTarget(const D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties, DCRenderTarget &dcRT) noexcept; + struct RenderingParams { std::unique_ptr<IDWriteRenderingParams, UnknownReleaser> defaultRenderingParams; std::unique_ptr<IDWriteRenderingParams, UnknownReleaser> customRenderingParams; diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 56ddbee56..2d0441fdd 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -361,6 +361,28 @@ D2D1_SIZE_U GetSizeUFromRect(const RECT &rc, const int scaleFactor) noexcept { namespace Scintilla::Internal { +#if defined(USE_D2D) + +// There may be either a Hwnd or DC render target +struct RenderTargets { + HwndRenderTarget pHwndRT; + DCRenderTarget pDCRT; + bool valid = true; + ID2D1RenderTarget *RenderTarget() const noexcept { + if (pHwndRT) + return pHwndRT.get(); + if (pDCRT) + return pDCRT.get(); + return nullptr; + } + void Release() noexcept { + pHwndRT.reset(); + pDCRT.reset(); + } +}; + +#endif + /** */ class ScintillaWin : @@ -408,8 +430,7 @@ class ScintillaWin : } #if defined(USE_D2D) - ID2D1RenderTarget *pRenderTarget; - bool renderTargetValid; + RenderTargets targets; // rendering parameters for current monitor HMONITOR hCurrentMonitor; std::shared_ptr<RenderingParams> renderingParams; @@ -631,8 +652,6 @@ ScintillaWin::ScintillaWin(HWND hwnd) { styleIdleInQueue = false; #if defined(USE_D2D) - pRenderTarget = nullptr; - renderTargetValid = true; hCurrentMonitor = {}; #endif @@ -678,6 +697,17 @@ void ScintillaWin::Finalise() { #if defined(USE_D2D) +HRESULT CreateHwndRenderTarget(const D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties, + const D2D1_HWND_RENDER_TARGET_PROPERTIES *hwndRenderTargetProperties, HwndRenderTarget &hwndRT) noexcept { + hwndRT.reset(); + ID2D1HwndRenderTarget *pHwndRT{}; + const HRESULT hr = pD2DFactory->CreateHwndRenderTarget(renderTargetProperties, hwndRenderTargetProperties, &pHwndRT); + if (SUCCEEDED(hr) && pHwndRT) { + hwndRT.reset(pHwndRT); + } + return hr; +} + bool ScintillaWin::UpdateRenderingParams(bool force) noexcept { if (!renderingParams) { try { @@ -716,11 +746,11 @@ bool ScintillaWin::UpdateRenderingParams(bool force) noexcept { } void ScintillaWin::EnsureRenderTarget(HDC hdc) { - if (!renderTargetValid) { + if (!targets.valid) { DropRenderTarget(); - renderTargetValid = true; + targets.valid = true; } - if (!pRenderTarget) { + if (!targets.RenderTarget()) { HWND hw = MainHWND(); const RECT rc = GetClientRect(hw); @@ -737,13 +767,10 @@ void ScintillaWin::EnsureRenderTarget(HDC hdc) { drtp.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE); - ID2D1DCRenderTarget *pDCRT = nullptr; - const HRESULT hr = pD2DFactory->CreateDCRenderTarget(&drtp, &pDCRT); - if (SUCCEEDED(hr)) { - pRenderTarget = pDCRT; - } else { + const HRESULT hr = CreateDCRenderTarget(&drtp, targets.pDCRT); + if (FAILED(hr)) { Platform::DebugPrintf("Failed CreateDCRenderTarget 0x%lx\n", hr); - pRenderTarget = nullptr; + targets.Release(); } } else { @@ -759,13 +786,10 @@ void ScintillaWin::EnsureRenderTarget(HDC hdc) { dhrtp.presentOptions = (technology == Technology::DirectWriteRetain) ? D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS : D2D1_PRESENT_OPTIONS_NONE; - ID2D1HwndRenderTarget *pHwndRenderTarget = nullptr; - const HRESULT hr = pD2DFactory->CreateHwndRenderTarget(drtp, dhrtp, &pHwndRenderTarget); - if (SUCCEEDED(hr)) { - pRenderTarget = pHwndRenderTarget; - } else { + const HRESULT hr = CreateHwndRenderTarget(&drtp, &dhrtp, targets.pHwndRT); + if (FAILED(hr)) { Platform::DebugPrintf("Failed CreateHwndRenderTarget 0x%lx\n", hr); - pRenderTarget = nullptr; + targets.Release(); } } // Pixmaps were created to be compatible with previous render target so @@ -773,9 +797,9 @@ void ScintillaWin::EnsureRenderTarget(HDC hdc) { DropGraphics(); } - if ((technology == Technology::DirectWriteDC) && pRenderTarget) { + if ((technology == Technology::DirectWriteDC) && targets.pDCRT) { const RECT rcWindow = GetClientRect(MainHWND()); - const HRESULT hr = static_cast<ID2D1DCRenderTarget*>(pRenderTarget)->BindDC(hdc, &rcWindow); + const HRESULT hr = targets.pDCRT->BindDC(hdc, &rcWindow); if (FAILED(hr)) { Platform::DebugPrintf("BindDC failed 0x%lx\n", hr); DropRenderTarget(); @@ -786,7 +810,7 @@ void ScintillaWin::EnsureRenderTarget(HDC hdc) { void ScintillaWin::DropRenderTarget() noexcept { #if defined(USE_D2D) - ReleaseUnknown(pRenderTarget); + targets.Release(); #endif } @@ -1031,7 +1055,7 @@ bool ScintillaWin::PaintDC(HDC hdc) { } else { #if defined(USE_D2D) EnsureRenderTarget(hdc); - if (pRenderTarget) { + if (ID2D1RenderTarget *pRenderTarget = targets.RenderTarget()) { AutoSurface surfaceWindow(pRenderTarget, this); if (surfaceWindow) { SetRenderingParams(surfaceWindow); @@ -1560,7 +1584,7 @@ void ScintillaWin::SizeWindow() { if (paintState == PaintState::notPainting) { DropRenderTarget(); } else { - renderTargetValid = false; + targets.valid = false; } #endif //Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam)); @@ -3694,7 +3718,7 @@ LRESULT PASCAL ScintillaWin::CTWndProc( ::BeginPaint(hWnd, &ps); std::unique_ptr<Surface> surfaceWindow(Surface::Allocate(sciThis->technology)); #if defined(USE_D2D) - ID2D1HwndRenderTarget *pCTRenderTarget = nullptr; + HwndRenderTarget pCTRenderTarget; #endif const RECT rc = GetClientRect(hWnd); if (sciThis->technology == Technology::Default) { @@ -3719,7 +3743,8 @@ LRESULT PASCAL ScintillaWin::CTWndProc( drtp.usage = D2D1_RENDER_TARGET_USAGE_NONE; drtp.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; - if (!SUCCEEDED(pD2DFactory->CreateHwndRenderTarget(drtp, dhrtp, &pCTRenderTarget))) { + const HRESULT hr = CreateHwndRenderTarget(&drtp, &dhrtp, pCTRenderTarget); + if (!SUCCEEDED(hr)) { surfaceWindow->Release(); ::EndPaint(hWnd, &ps); return 0; @@ -3727,7 +3752,7 @@ LRESULT PASCAL ScintillaWin::CTWndProc( // If above SUCCEEDED, then pCTRenderTarget not nullptr assert(pCTRenderTarget); if (pCTRenderTarget) { - surfaceWindow->Init(pCTRenderTarget, hWnd); + surfaceWindow->Init(pCTRenderTarget.get(), hWnd); pCTRenderTarget->BeginDraw(); } #endif @@ -3740,9 +3765,6 @@ LRESULT PASCAL ScintillaWin::CTWndProc( pCTRenderTarget->EndDraw(); #endif surfaceWindow->Release(); -#if defined(USE_D2D) - ReleaseUnknown(pCTRenderTarget); -#endif ::EndPaint(hWnd, &ps); return 0; } else if ((iMessage == WM_NCLBUTTONDOWN) || (iMessage == WM_NCLBUTTONDBLCLK)) { |