aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2025-02-12 13:19:09 +1100
committerNeil <nyamatongwe@gmail.com>2025-02-12 13:19:09 +1100
commit1ff212a46192cb86fcb6451848b200898a28f6ff (patch)
treed3083f62f7c814c28fa73a57c3f2465e80259ab4
parent876871f0391de2730ac7562491d5cffb5fdd9ed1 (diff)
downloadscintilla-mirror-1ff212a46192cb86fcb6451848b200898a28f6ff.tar.gz
Implement Direct2D/DirectWrite 1.1. Add SC_TECHNOLOGY_DIRECT_WRITE_1 to use an
explicit swap chain and ID2D1DeviceContext. Stop supporting DirectWrite on Windows Vista.
-rw-r--r--doc/ScintillaHistory.html6
-rw-r--r--include/Scintilla.h1
-rw-r--r--include/Scintilla.iface1
-rw-r--r--include/ScintillaTypes.h1
-rw-r--r--scripts/HeaderOrder.txt1
-rw-r--r--win32/PlatWin.cxx78
-rw-r--r--win32/PlatWin.h5
-rw-r--r--win32/ScintillaWin.cxx303
8 files changed, 347 insertions, 49 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index 5bcc93dfb..c9f423488 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -605,6 +605,12 @@
Serialize selection type and ranges with SCI_GETSELECTIONSERIALIZED and SCI_SETSELECTIONSERIALIZED.
</li>
<li>
+ For Win32, update Direct2D and DirectWrite interfaces used to 1.1 and add a lower-level approach to calling DirectWrite 1.1
+ by specifying SC_TECHNOLOGY_DIRECT_WRITE_1.
+ Since Windows Vista does not support these API versions, Scintilla o longer supports DirectWrite on Windows Vista and will
+ fall back to using GDI.
+ </li>
+ <li>
Fix segmentation of long lexemes to avoid breaking before modifiers like accents that must be drawn with their base letters.
</li>
<li>
diff --git a/include/Scintilla.h b/include/Scintilla.h
index 4de92e1b8..c976af1ea 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -1127,6 +1127,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SC_TECHNOLOGY_DIRECTWRITE 1
#define SC_TECHNOLOGY_DIRECTWRITERETAIN 2
#define SC_TECHNOLOGY_DIRECTWRITEDC 3
+#define SC_TECHNOLOGY_DIRECT_WRITE_1 4
#define SCI_SETTECHNOLOGY 2630
#define SCI_GETTECHNOLOGY 2631
#define SCI_CREATELOADER 2632
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index 4ce9d5703..f32148b69 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -3092,6 +3092,7 @@ val SC_TECHNOLOGY_DEFAULT=0
val SC_TECHNOLOGY_DIRECTWRITE=1
val SC_TECHNOLOGY_DIRECTWRITERETAIN=2
val SC_TECHNOLOGY_DIRECTWRITEDC=3
+val SC_TECHNOLOGY_DIRECT_WRITE_1=4
ali SC_TECHNOLOGY_DIRECTWRITE=DIRECT_WRITE
ali SC_TECHNOLOGY_DIRECTWRITERETAIN=DIRECT_WRITE_RETAIN
diff --git a/include/ScintillaTypes.h b/include/ScintillaTypes.h
index af726b2ab..71e2be398 100644
--- a/include/ScintillaTypes.h
+++ b/include/ScintillaTypes.h
@@ -515,6 +515,7 @@ enum class Technology {
DirectWrite = 1,
DirectWriteRetain = 2,
DirectWriteDC = 3,
+ DirectWrite1 = 4,
};
enum class LineEndType {
diff --git a/scripts/HeaderOrder.txt b/scripts/HeaderOrder.txt
index 8ac8c3c48..eb0a16dd1 100644
--- a/scripts/HeaderOrder.txt
+++ b/scripts/HeaderOrder.txt
@@ -81,6 +81,7 @@
#include <zmouse.h>
#include <ole2.h>
#include <d2d1_1.h>
+#include <d3d11_1.h>
#include <dwrite_1.h>
// Cocoa headers
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index 4f54f4496..79a5f151f 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -45,6 +45,7 @@
#if defined(USE_D2D)
#include <d2d1_1.h>
+#include <d3d11_1.h>
#include <dwrite_1.h>
#endif
@@ -79,8 +80,11 @@ D2D1_DRAW_TEXT_OPTIONS d2dDrawTextOptions = D2D1_DRAW_TEXT_OPTIONS_NONE;
namespace {
HMODULE hDLLD2D{};
+HMODULE hDLLD3D{};
HMODULE hDLLDWrite{};
+PFN_D3D11_CREATE_DEVICE fnDCD {};
+
}
void LoadD2DOnce() noexcept {
@@ -128,6 +132,77 @@ void LoadD2DOnce() noexcept {
reinterpret_cast<IUnknown**>(&pIDWriteFactory));
}
}
+
+ hDLLD3D = ::LoadLibraryEx(TEXT("D3D11.DLL"), 0, loadLibraryFlags);
+ if (!hDLLD3D) {
+ Platform::DebugPrintf("Direct3D not loaded\n");
+ }
+ fnDCD = DLLFunction<PFN_D3D11_CREATE_DEVICE>(hDLLD3D, "D3D11CreateDevice");
+ if (!fnDCD) {
+ Platform::DebugPrintf("Direct3D does not have D3D11CreateDevice\n");
+ }
+}
+
+HRESULT CreateD3D(D3D11Device &device, D3D11DeviceContext &context) noexcept {
+ device.reset();
+ context.reset();
+ if (!fnDCD) {
+ return E_FAIL;
+ }
+
+ const D3D_FEATURE_LEVEL featureLevels[] = {
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ D3D_FEATURE_LEVEL_9_3,
+ D3D_FEATURE_LEVEL_9_2,
+ D3D_FEATURE_LEVEL_9_1
+ };
+
+ // Create device and context.
+ // Try for a hardware device but, if that fails, fall back to the Warp software rasterizer.
+ D3D_FEATURE_LEVEL returnedFeatureLevel{};
+ ID3D11Device *pDevice{};
+ ID3D11DeviceContext *pContext{};
+ HRESULT hr = S_OK;
+ const D3D_DRIVER_TYPE typesToTry[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP };
+ for (const D3D_DRIVER_TYPE type : typesToTry) {
+ hr = fnDCD(nullptr,
+ type,
+ 0,
+ D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+ featureLevels,
+ ARRAYSIZE(featureLevels),
+ D3D11_SDK_VERSION,
+ &pDevice,
+ &returnedFeatureLevel,
+ &pContext);
+ if (SUCCEEDED(hr))
+ break;
+ }
+ if (FAILED(hr)) {
+ Platform::DebugPrintf("Failed to create D3D11 device and context 0x%lx\n", hr);
+ return hr;
+ }
+
+ // Ensure released
+ std::unique_ptr<ID3D11Device, UnknownReleaser> upDevice(pDevice);
+ std::unique_ptr<ID3D11DeviceContext, UnknownReleaser> upContext(pContext);
+
+ // Convert from D3D11 to D3D11.1
+ hr = UniquePtrFromQI(upDevice.get(), __uuidof(ID3D11Device1), device);
+ if (FAILED(hr)) {
+ Platform::DebugPrintf("Failed to create D3D11.1 device 0x%lx\n", hr);
+ return hr;
+ }
+ hr = UniquePtrFromQI(upContext.get(), __uuidof(ID3D11DeviceContext1), context);
+ if (FAILED(hr)) {
+ // Either both device and context or neither
+ device.reset();
+ Platform::DebugPrintf("Failed to create D3D11.1 device context 0x%lx\n", hr);
+ }
+ return hr;
}
bool LoadD2D() noexcept {
@@ -4112,7 +4187,7 @@ void Platform::DebugDisplay(const char *s) noexcept {
::OutputDebugStringA(s);
}
-//#define TRACE
+#define TRACE
#ifdef TRACE
void Platform::DebugPrintf(const char *format, ...) noexcept {
@@ -4179,6 +4254,7 @@ void Platform_Finalise(bool fromDllMain) noexcept {
ReleaseUnknown(pIDWriteFactory);
ReleaseUnknown(pD2DFactory);
ReleaseLibrary(hDLLDWrite);
+ ReleaseLibrary(hDLLD3D);
ReleaseLibrary(hDLLD2D);
#endif
ReleaseLibrary(hDLLShcore);
diff --git a/win32/PlatWin.h b/win32/PlatWin.h
index f24689799..1b5b7b1b9 100644
--- a/win32/PlatWin.h
+++ b/win32/PlatWin.h
@@ -73,8 +73,13 @@ extern IDWriteFactory1 *pIDWriteFactory;
using DCRenderTarget = std::unique_ptr<ID2D1DCRenderTarget, UnknownReleaser>;
using HwndRenderTarget = std::unique_ptr<ID2D1HwndRenderTarget, UnknownReleaser>;
+using D2DeviceContext = std::unique_ptr<ID2D1DeviceContext, UnknownReleaser>;
+
+using D3D11Device = std::unique_ptr<ID3D11Device1, UnknownReleaser>;
+using D3D11DeviceContext = std::unique_ptr<ID3D11DeviceContext1, UnknownReleaser>;
HRESULT CreateDCRenderTarget(const D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties, DCRenderTarget &dcRT) noexcept;
+extern HRESULT CreateD3D(D3D11Device &device, D3D11DeviceContext &context) noexcept;
using WriteRenderingParams = std::unique_ptr<IDWriteRenderingParams1, UnknownReleaser>;
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index 4411f54ef..dcfcde2f6 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -49,6 +49,7 @@
#if defined(USE_D2D)
#include <d2d1_1.h>
+#include <d3d11_1.h>
#include <dwrite_1.h>
#endif
@@ -372,20 +373,75 @@ namespace Scintilla::Internal {
struct RenderTargets {
HwndRenderTarget pHwndRT;
DCRenderTarget pDCRT;
+ D2DeviceContext pDeviceContext;
bool valid = true;
ID2D1RenderTarget *RenderTarget() const noexcept {
if (pHwndRT)
return pHwndRT.get();
if (pDCRT)
return pDCRT.get();
+ if (pDeviceContext)
+ return pDeviceContext.get();
return nullptr;
}
void Release() noexcept {
pHwndRT.reset();
pDCRT.reset();
+ pDeviceContext.reset();
}
};
+using D2D1Device = std::unique_ptr<ID2D1Device, UnknownReleaser>;
+using DXGIDevice = std::unique_ptr<IDXGIDevice, UnknownReleaser>;
+
+// These resources are device-dependent but not window-dependent
+struct DirectDevice {
+ D3D11Device pDirect3DDevice;
+ D3D11DeviceContext pDirect3DContext;
+ D2D1Device pDirect2DDevice;
+ DXGIDevice pDXGIDevice;
+
+ void Release() noexcept;
+ HRESULT CreateDevice() noexcept;
+};
+
+void DirectDevice::Release() noexcept {
+ pDirect3DDevice.reset();
+ pDirect3DContext.reset();
+ pDirect2DDevice.reset();
+ pDXGIDevice.reset();
+}
+
+HRESULT DirectDevice::CreateDevice() noexcept {
+ if (pDirect2DDevice) { // Must be released before creation
+ return E_FAIL;
+ }
+
+ HRESULT hr = CreateD3D(pDirect3DDevice, pDirect3DContext);
+ if (FAILED(hr)) {
+ Platform::DebugPrintf("Failed to create D3D device 0x%lx\n", hr);
+ return hr;
+ }
+
+ hr = UniquePtrFromQI(pDirect3DDevice.get(), __uuidof(IDXGIDevice), pDXGIDevice);
+ if (FAILED(hr)) {
+ Platform::DebugPrintf("Failed to create DXGI device 0x%lx\n", hr);
+ return hr;
+ }
+
+ ID2D1Device *pDirect2DDevice_{};
+ hr = pD2DFactory->CreateDevice(pDXGIDevice.get(), &pDirect2DDevice_);
+ if (FAILED(hr)) {
+ Platform::DebugPrintf("Failed to create D2D device 0x%lx\n", hr);
+ return hr;
+ }
+ pDirect2DDevice.reset(pDirect2DDevice_);
+
+ return S_OK;
+}
+
+using DXGISwapChain = std::unique_ptr<IDXGISwapChain1, UnknownReleaser>;
+
#endif
/**
@@ -435,6 +491,8 @@ class ScintillaWin :
}
#if defined(USE_D2D)
+ DirectDevice device;
+ DXGISwapChain pDXGISwapChain;
RenderTargets targets;
// rendering parameters for current monitor
HMONITOR hCurrentMonitor;
@@ -452,6 +510,10 @@ class ScintillaWin :
void Finalise() override;
#if defined(USE_D2D)
bool UpdateRenderingParams(bool force) noexcept;
+ HRESULT Create3D() noexcept;
+ void CreateRenderTarget();
+ HRESULT SetBackBuffer(HWND hwnd, IDXGISwapChain1 *pSwapChain);
+ HRESULT CreateSwapChain(HWND hwnd);
void EnsureRenderTarget(HDC hdc);
#endif
void DropRenderTarget() noexcept;
@@ -713,6 +775,16 @@ HRESULT CreateHwndRenderTarget(const D2D1_RENDER_TARGET_PROPERTIES *renderTarget
return hr;
}
+HRESULT CreateDeviceContext(ID2D1Device *pDirect2DDevice, D2DeviceContext &deviceContext) noexcept {
+ deviceContext.reset();
+ ID2D1DeviceContext *pD2DC{};
+ const HRESULT hr = pDirect2DDevice->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &pD2DC);
+ if (SUCCEEDED(hr) && pD2DC) {
+ deviceContext.reset(pD2DC);
+ }
+ return hr;
+}
+
bool ScintillaWin::UpdateRenderingParams(bool force) noexcept {
if (!renderingParams) {
try {
@@ -761,59 +833,171 @@ bool ScintillaWin::UpdateRenderingParams(bool force) noexcept {
return true;
}
-void ScintillaWin::EnsureRenderTarget(HDC hdc) {
- if (!targets.valid) {
- DropRenderTarget();
- targets.valid = true;
+HRESULT ScintillaWin::Create3D() noexcept {
+ if (device.pDirect2DDevice) {
+ return S_OK;
}
- if (!targets.RenderTarget()) {
- HWND hw = MainHWND();
- const RECT rc = GetClientRect(hw);
-
- // Create a Direct2D render target.
- D2D1_RENDER_TARGET_PROPERTIES drtp {};
- drtp.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
- drtp.usage = D2D1_RENDER_TARGET_USAGE_NONE;
- drtp.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
-
- if (technology == Technology::DirectWriteDC) {
- drtp.dpiX = 96.f;
- drtp.dpiY = 96.f;
- // Explicit pixel format needed.
- drtp.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
- D2D1_ALPHA_MODE_IGNORE);
-
- const HRESULT hr = CreateDCRenderTarget(&drtp, targets.pDCRT);
+ targets.Release();
+ pDXGISwapChain.reset();
+ device.Release();
+ const HRESULT hr = device.CreateDevice();
+ if (FAILED(hr)) {
+ device.Release();
+ }
+ return hr;
+}
+
+void ScintillaWin::CreateRenderTarget() {
+ HWND hw = MainHWND();
+ const RECT rc = GetClientRect(hw);
+
+ // Create a Direct2D render target.
+ D2D1_RENDER_TARGET_PROPERTIES drtp{};
+ drtp.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
+ drtp.usage = D2D1_RENDER_TARGET_USAGE_NONE;
+ drtp.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
+
+ if (technology == Technology::DirectWriteDC) {
+ drtp.dpiX = 96.f;
+ drtp.dpiY = 96.f;
+ // Explicit pixel format needed.
+ drtp.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_IGNORE);
+
+ const HRESULT hr = CreateDCRenderTarget(&drtp, targets.pDCRT);
+ if (FAILED(hr)) {
+ Platform::DebugPrintf("Failed CreateDCRenderTarget 0x%lx\n", hr);
+ targets.Release();
+ }
+
+ } else if (technology == Technology::DirectWrite1) {
+ HRESULT hr = Create3D(); // Need pDirect2DDevice
+ if (SUCCEEDED(hr)) {
+ hr = CreateDeviceContext(device.pDirect2DDevice.get(), targets.pDeviceContext);
if (FAILED(hr)) {
- Platform::DebugPrintf("Failed CreateDCRenderTarget 0x%lx\n", hr);
- targets.Release();
+ Platform::DebugPrintf("Failed CreateDeviceContext 0x%lx\n", hr);
+ } else {
+ hr = CreateSwapChain(hw);
+ if (FAILED(hr)) {
+ Platform::DebugPrintf("Failed CreateSwapChain 0x%lx\n", hr);
+ targets.Release();
+ }
}
+ }
- } else {
- const int integralDeviceScaleFactor = GetFirstIntegralMultipleDeviceScaleFactor();
- drtp.dpiX = 96.f * integralDeviceScaleFactor;
- drtp.dpiY = 96.f * integralDeviceScaleFactor;
- drtp.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN,
- D2D1_ALPHA_MODE_UNKNOWN);
-
- D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp {};
- dhrtp.hwnd = hw;
- dhrtp.pixelSize = ::GetSizeUFromRect(rc, integralDeviceScaleFactor);
- dhrtp.presentOptions = (technology == Technology::DirectWriteRetain) ?
+ } else { // DirectWrite or DirectWriteRetain
+ const int integralDeviceScaleFactor = GetFirstIntegralMultipleDeviceScaleFactor();
+ drtp.dpiX = 96.f * integralDeviceScaleFactor;
+ drtp.dpiY = 96.f * integralDeviceScaleFactor;
+ drtp.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN,
+ D2D1_ALPHA_MODE_UNKNOWN);
+
+ D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp{};
+ dhrtp.hwnd = hw;
+ dhrtp.pixelSize = ::GetSizeUFromRect(rc, integralDeviceScaleFactor);
+ dhrtp.presentOptions = (technology == Technology::DirectWriteRetain) ?
D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS : D2D1_PRESENT_OPTIONS_NONE;
- const HRESULT hr = CreateHwndRenderTarget(&drtp, &dhrtp, targets.pHwndRT);
- if (FAILED(hr)) {
- Platform::DebugPrintf("Failed CreateHwndRenderTarget 0x%lx\n", hr);
- targets.Release();
- }
+ const HRESULT hr = CreateHwndRenderTarget(&drtp, &dhrtp, targets.pHwndRT);
+ if (FAILED(hr)) {
+ Platform::DebugPrintf("Failed CreateHwndRenderTarget 0x%lx\n", hr);
+ targets.Release();
}
+
+ }
+}
+
+HRESULT ScintillaWin::SetBackBuffer(HWND hwnd, IDXGISwapChain1 *pSwapChain) {
+ assert(targets.pDeviceContext);
+ // Back buffer as an IDXGISurface
+ IDXGISurface *dxgiBackBuffer_{};
+ HRESULT hr = pSwapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer_));
+ if (FAILED(hr))
+ return hr;
+ std::unique_ptr<IDXGISurface, UnknownReleaser> dxgiBackBuffer(dxgiBackBuffer_);
+
+ const FLOAT dpiX = static_cast<FLOAT>(DpiForWindow(hwnd));
+ const FLOAT dpiY = dpiX;
+
+ // Direct2D bitmap linked to Direct3D texture through DXGI back buffer
+ const D2D1_BITMAP_PROPERTIES1 bitmapProperties =
+ D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
+ D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE), dpiX, dpiY);
+ ID2D1Bitmap1 *pDirect2DBackBuffer{};
+ hr = targets.pDeviceContext->CreateBitmapFromDxgiSurface(dxgiBackBuffer.get(), &bitmapProperties, &pDirect2DBackBuffer);
+ if (FAILED(hr))
+ return hr;
+
+ // Bitmap is render target
+ targets.pDeviceContext->SetTarget(pDirect2DBackBuffer);
+ ReleaseUnknown(pDirect2DBackBuffer);
+
+ return S_OK;
+}
+
+HRESULT ScintillaWin::CreateSwapChain(HWND hwnd) {
+ // Sets pDXGISwapChain but only when each call succeeds
+ // Needs pDXGIDevice, pDirect3DDevice
+ pDXGISwapChain.reset();
+ assert(device.pDXGIDevice);
+
+ // At each stage, place object in a unique_ptr to ensure release occurs
+
+ IDXGIAdapter *dxgiAdapter_{};
+ HRESULT hr = device.pDXGIDevice->GetAdapter(&dxgiAdapter_);
+ if (FAILED(hr))
+ return hr;
+ std::unique_ptr<IDXGIAdapter, UnknownReleaser> dxgiAdapter(dxgiAdapter_);
+
+ IDXGIFactory2 *dxgiFactory_{};
+ hr = dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory_));
+ if (FAILED(hr))
+ return hr;
+ std::unique_ptr<IDXGIFactory2, UnknownReleaser> dxgiFactory(dxgiFactory_);
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc{};
+ swapChainDesc.Width = 0;
+ swapChainDesc.Height = 0;
+ swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ swapChainDesc.Stereo = false;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+ swapChainDesc.Flags = 0;
+
+ // DXGI swap chain for window
+ IDXGISwapChain1 *pSwapChain_{};
+ hr = dxgiFactory->CreateSwapChainForHwnd(device.pDirect3DDevice.get(), hwnd, &swapChainDesc,
+ nullptr, nullptr, &pSwapChain_);
+ if (FAILED(hr))
+ return hr;
+ DXGISwapChain pSwapChain(pSwapChain_);
+
+ hr = SetBackBuffer(hwnd, pSwapChain.get());
+ if (FAILED(hr))
+ return hr;
+
+ // All successful so export swap chain for later presentation
+ pDXGISwapChain = std::move(pSwapChain);
+ return S_OK;
+}
+
+void ScintillaWin::EnsureRenderTarget(HDC hdc) {
+ if (!targets.valid) {
+ DropRenderTarget();
+ targets.valid = true;
+ }
+ if (!targets.RenderTarget()) {
+ CreateRenderTarget();
// Pixmaps were created to be compatible with previous render target so
// need to be recreated.
DropGraphics();
}
- if ((technology == Technology::DirectWriteDC) && targets.pDCRT) {
+ if ((technology == Technology::DirectWriteDC) && targets.pDCRT) { // DC RenderTarget needs binding
const RECT rcWindow = GetClientRect(MainHWND());
const HRESULT hr = targets.pDCRT->BindDC(hdc, &rcWindow);
if (FAILED(hr)) {
@@ -1070,6 +1254,11 @@ bool ScintillaWin::PaintDC(HDC hdc) {
}
} else {
#if defined(USE_D2D)
+ // RefreshStyleData may set scroll bars and resize the window.
+ // Avoid issues resizing inside Paint when calling IDXGISwapChain1->ResizeBuffers
+ // with committed resources by refreshing the style data first.
+ RefreshStyleData();
+
EnsureRenderTarget(hdc);
if (ID2D1RenderTarget *pRenderTarget = targets.RenderTarget()) {
AutoSurface surfaceWindow(pRenderTarget, this);
@@ -1083,6 +1272,14 @@ bool ScintillaWin::PaintDC(HDC hdc) {
DropRenderTarget();
return false;
}
+ if ((technology == Technology::DirectWrite1) && pDXGISwapChain) {
+ const DXGI_PRESENT_PARAMETERS parameters{};
+ const HRESULT hrPresent = pDXGISwapChain->Present1(1, 0, &parameters);
+ if (FAILED(hrPresent)) {
+ DropRenderTarget();
+ return false;
+ }
+ }
}
}
#endif
@@ -1596,9 +1793,9 @@ PRectangle ScintillaWin::GetClientRectangle() const {
}
void ScintillaWin::SizeWindow() {
+ rectangleClient = wMain.GetClientPosition();
#if defined(USE_D2D)
HRESULT hrResize = E_FAIL;
-
if (((technology == Technology::DirectWrite) || (technology == Technology::DirectWriteRetain)) && targets.pHwndRT) {
// May be able to just resize the HWND render target
const int scaleFactor = GetFirstIntegralMultipleDeviceScaleFactor();
@@ -1608,16 +1805,25 @@ void ScintillaWin::SizeWindow() {
Platform::DebugPrintf("Failed to Resize ID2D1HwndRenderTarget 0x%lx\n", hrResize);
}
}
- if (paintState == PaintState::notPainting) {
- if (FAILED(hrResize)) {
+ if ((technology == Technology::DirectWrite1) && pDXGISwapChain && targets.pDeviceContext &&
+ (paintState == PaintState::notPainting)) {
+ targets.pDeviceContext->SetTarget(NULL); // ResizeBuffers fails if bitmap still owned by swap chain
+ hrResize = pDXGISwapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
+ if (SUCCEEDED(hrResize)) {
+ hrResize = SetBackBuffer(MainHWND(), pDXGISwapChain.get());
+ } else {
+ Platform::DebugPrintf("Failed ResizeBuffers 0x%lx\n", hrResize);
+ }
+ }
+ if (FAILED(hrResize)) {
+ if (paintState == PaintState::notPainting) {
DropRenderTarget();
+ } else {
+ targets.valid = false;
}
- } else {
- targets.valid = false;
}
#endif
//Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam));
- rectangleClient = wMain.GetClientPosition();
ChangeSize();
}
@@ -2032,7 +2238,8 @@ sptr_t ScintillaWin::SciMessage(Message iMessage, uptr_t wParam, sptr_t lParam)
(technologyNew == Technology::Default) ||
(technologyNew == Technology::DirectWriteRetain) ||
(technologyNew == Technology::DirectWriteDC) ||
- (technologyNew == Technology::DirectWrite)) {
+ (technologyNew == Technology::DirectWrite) ||
+ (technologyNew == Technology::DirectWrite1)) {
if (technology != technologyNew) {
if (technologyNew > Technology::Default) {
#if defined(USE_D2D)