Skip to content

Commit c8b04da

Browse files
committedFeb 24, 2025·
feat: use DirectComposition to render the QCefView
1 parent c22a7c2 commit c8b04da

File tree

6 files changed

+143
-50
lines changed

6 files changed

+143
-50
lines changed
 

‎CMakeLists.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
122122
# Disable the sandbox on Windows, because the sandbox.lib is MT which is conflict with Qt
123123
set(USE_SANDBOX OFF CACHE BOOL "Disable sandbox on Windows" FORCE)
124124
add_definitions(-DOS_WINDOWS=1)
125-
add_compile_options("/M$<IF:$<BOOL:${STATIC_CRT}>,T,D>$<$<CONFIG:Debug>:d>")
125+
add_compile_options(
126+
/W3
127+
/WX
128+
/M$<IF:$<BOOL:${STATIC_CRT}>,T,D>$<$<CONFIG:Debug>:d>
129+
)
126130
add_link_options(/DEBUG)
127131
endif()
128132

‎example/QCefViewTest/MainWindow.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ MainWindow::createRightCefView()
105105
// m_pRightCefViewWidget = new QCefView(RIGHT_INDEX_URL, &setting, this);
106106
m_pRightCefViewWidget = new QCefView("https://www.testufo.com/", &setting, this);
107107

108+
auto vl = new QVBoxLayout(m_pRightCefViewWidget);
109+
auto btn = new QPushButton("TEST BUTTON OVERLAY", m_pRightCefViewWidget);
110+
vl->setAlignment(Qt::AlignTop);
111+
vl->addWidget(btn);
112+
m_pRightCefViewWidget->setLayout(vl);
113+
108114
// all the following values will disable the context menu for both NCW and OSR mode
109115
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::NoContextMenu);
110116
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::ActionsContextMenu);

‎src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ if(OS_WINDOWS)
7575
PRIVATE
7676
d3d11
7777
d3dcompiler
78+
dcomp
7879
)
7980

8081
add_custom_command(TARGET QCefView

‎src/win/details/render/hardware/DX11RenderBackend.cpp

+120-46
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
#include <DirectXMath.h>
44
#include <d3dcompiler.h>
55

6+
#define HR_CHECK(exp) \
7+
if (!(exp)) { \
8+
return false; \
9+
}
10+
611
using namespace DirectX;
712
using namespace Microsoft::WRL;
813

@@ -56,36 +61,83 @@ float4 main(VS_OUTPUT input) : SV_Target
5661
bool
5762
DX11RenderBackend::CreateDeviceAndSwapchain()
5863
{
59-
// create device and swapchain
60-
DXGI_SWAP_CHAIN_DESC sd = {};
61-
sd.BufferCount = 1;
62-
sd.BufferDesc.Width = m_width;
63-
sd.BufferDesc.Height = m_height;
64-
sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
65-
sd.BufferDesc.RefreshRate.Numerator = 60;
66-
sd.BufferDesc.RefreshRate.Denominator = 1;
64+
// we don't render directly to the window, but we
65+
// use the DirectComposition to render the CefView
66+
67+
// Create D3D11 device and context
68+
ComPtr<ID3D11Device> pD3dDevice;
69+
ComPtr<ID3D11DeviceContext> pD3dContext;
70+
HR_CHECK(S_OK == ::D3D11CreateDevice(nullptr,
71+
D3D_DRIVER_TYPE_HARDWARE,
72+
nullptr,
73+
0,
74+
nullptr,
75+
0,
76+
D3D11_SDK_VERSION,
77+
pD3dDevice.ReleaseAndGetAddressOf(),
78+
nullptr,
79+
pD3dContext.ReleaseAndGetAddressOf()));
80+
81+
// Get DXGI device
82+
ComPtr<IDXGIDevice1> pDxgiDevice;
83+
HR_CHECK(S_OK == pD3dDevice.As(&pDxgiDevice));
84+
85+
// Get DXGI adapter
86+
ComPtr<IDXGIAdapter> pDxgiAdapter;
87+
HR_CHECK(S_OK == pDxgiDevice->GetAdapter(pDxgiAdapter.GetAddressOf()));
88+
89+
// Get DXGI factory
90+
ComPtr<IDXGIFactory2> pDxgiFactory2;
91+
HR_CHECK(S_OK == pDxgiAdapter->GetParent(IID_PPV_ARGS(pDxgiFactory2.ReleaseAndGetAddressOf())));
92+
93+
// Create swapchain description
94+
DXGI_SWAP_CHAIN_DESC1 sd;
95+
ZeroMemory(&sd, sizeof(sd));
96+
sd.BufferCount = 2;
97+
sd.Width = (UINT)m_width;
98+
sd.Height = (UINT)m_height;
99+
sd.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
67100
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
68-
sd.OutputWindow = m_hWnd;
69101
sd.SampleDesc.Count = 1;
70102
sd.SampleDesc.Quality = 0;
71-
sd.Windowed = TRUE;
72-
73-
HRESULT hr = ::D3D11CreateDeviceAndSwapChain(nullptr,
74-
D3D_DRIVER_TYPE_HARDWARE,
75-
nullptr,
76-
0,
77-
nullptr,
78-
0,
79-
D3D11_SDK_VERSION,
80-
&sd,
81-
m_swapChain.ReleaseAndGetAddressOf(),
82-
m_d3dDevice.ReleaseAndGetAddressOf(),
83-
nullptr,
84-
m_d3dContext.ReleaseAndGetAddressOf());
85-
if (FAILED(hr)) {
86-
return false;
87-
}
88-
103+
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
104+
sd.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
105+
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
106+
107+
// Create swapchain
108+
ComPtr<IDXGISwapChain1> pSwapChain;
109+
HR_CHECK(S_OK == pDxgiFactory2->CreateSwapChainForComposition(
110+
pD3dDevice.Get(), &sd, nullptr, pSwapChain.ReleaseAndGetAddressOf()));
111+
112+
// Create DComposition device
113+
ComPtr<IDCompositionDevice> pDecompositionDevice;
114+
HR_CHECK(S_OK ==
115+
::DCompositionCreateDevice(pDxgiDevice.Get(), IID_PPV_ARGS(pDecompositionDevice.ReleaseAndGetAddressOf())));
116+
117+
// Create DComposition visual
118+
ComPtr<IDCompositionVisual> pDCompositionVisual;
119+
HR_CHECK(S_OK == pDecompositionDevice->CreateVisual(pDCompositionVisual.ReleaseAndGetAddressOf()));
120+
121+
// Set swapchain to visual
122+
HR_CHECK(S_OK == pDCompositionVisual->SetContent(pSwapChain.Get()));
123+
124+
// Create DComposition target
125+
ComPtr<IDCompositionTarget> pDCompositionTarget;
126+
HR_CHECK(S_OK ==
127+
pDecompositionDevice->CreateTargetForHwnd(m_hWnd, FALSE, pDCompositionTarget.ReleaseAndGetAddressOf()));
128+
129+
// Set root to target
130+
HR_CHECK(S_OK == pDCompositionTarget->SetRoot(pDCompositionVisual.Get()));
131+
132+
// Commit
133+
HR_CHECK(S_OK == pDecompositionDevice->Commit());
134+
135+
// Save
136+
m_dcompositionTarget = pDCompositionTarget;
137+
m_dcompositionDevice = pDecompositionDevice;
138+
m_swapChain = pSwapChain;
139+
m_d3dContext = pD3dContext;
140+
m_d3dDevice = pD3dDevice;
89141
return true;
90142
}
91143

@@ -123,8 +175,9 @@ DX11RenderBackend::CreateShaderResource()
123175
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
124176
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
125177
};
178+
ComPtr<ID3D11InputLayout> pInputLayout;
126179
hr = m_d3dDevice->CreateInputLayout(
127-
id, ARRAYSIZE(id), vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), m_inputLayout.ReleaseAndGetAddressOf());
180+
id, ARRAYSIZE(id), vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), pInputLayout.ReleaseAndGetAddressOf());
128181
if (FAILED(hr)) {
129182
return false;
130183
}
@@ -146,12 +199,15 @@ DX11RenderBackend::CreateShaderResource()
146199
return false;
147200
}
148201

202+
ComPtr<ID3D11PixelShader> pPixelShader;
149203
hr = m_d3dDevice->CreatePixelShader(
150-
psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, m_pixelShader.ReleaseAndGetAddressOf());
204+
psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, pPixelShader.ReleaseAndGetAddressOf());
151205
if (FAILED(hr)) {
152206
return false;
153207
}
154208

209+
m_inputLayout = pInputLayout;
210+
m_pixelShader = pPixelShader;
155211
return true;
156212
}
157213

@@ -225,18 +281,26 @@ DX11RenderBackend::CreateRenderTarget()
225281
vdesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
226282
vdesc.Texture2D.MipSlice = 0;
227283
vdesc.Format = desc.BufferDesc.Format;
228-
hr = m_d3dDevice->CreateRenderTargetView(pBackBuffer.Get(), &vdesc, m_renderTargetView.ReleaseAndGetAddressOf());
284+
ComPtr<ID3D11RenderTargetView> pRenderTargetView;
285+
hr = m_d3dDevice->CreateRenderTargetView(pBackBuffer.Get(), nullptr, pRenderTargetView.ReleaseAndGetAddressOf());
229286
if (FAILED(hr)) {
230287
return false;
231288
}
232289

233290
// create vertex buffer
234-
return CreateQuadVertexBuffer(0.0f, //
235-
0.0f, //
236-
m_width, //
237-
m_height, //
238-
m_viewVertexBuffer.ReleaseAndGetAddressOf() //
239-
);
291+
ComPtr<ID3D11Buffer> pViewVertexBuffer;
292+
if (!CreateQuadVertexBuffer(0.0f, //
293+
0.0f, //
294+
static_cast<float>(m_width), //
295+
static_cast<float>(m_height), //
296+
pViewVertexBuffer.ReleaseAndGetAddressOf() //
297+
)) {
298+
return false;
299+
}
300+
301+
m_renderTargetView = pRenderTargetView;
302+
m_viewVertexBuffer = pViewVertexBuffer;
303+
return true;
240304
}
241305

242306
void
@@ -393,6 +457,13 @@ DX11RenderBackend::UpdateTextureResource(Microsoft::WRL::ComPtr<ID3D11Texture2D>
393457
targetTextureDesc = sharedTextureDesc;
394458
}
395459

460+
void
461+
DX11RenderBackend::SetTargetView()
462+
{
463+
ID3D11RenderTargetView* rtvList[] = { m_renderTargetView.Get() };
464+
m_d3dContext->OMSetRenderTargets(ARRAYSIZE(rtvList), rtvList, nullptr);
465+
}
466+
396467
void
397468
DX11RenderBackend::ClearTargetView()
398469
{
@@ -545,8 +616,8 @@ DX11RenderBackend::resize(int width, int height, float scale)
545616

546617
// update size
547618
m_scale = scale;
548-
m_width = width * scale;
549-
m_height = height * scale;
619+
m_width = static_cast<int>(width * scale);
620+
m_height = static_cast<int>(height * scale);
550621

551622
// remove current render target
552623
m_d3dContext->OMSetRenderTargets(0, nullptr, nullptr);
@@ -589,10 +660,11 @@ void
589660
DX11RenderBackend::updatePopupRect(const CefRect& rect)
590661
{
591662
CefRect newRect = rect;
592-
newRect.x *= m_scale;
593-
newRect.y *= m_scale;
594-
newRect.width *= m_scale;
595-
newRect.height *= m_scale;
663+
newRect.x = static_cast<int>(newRect.x * m_scale);
664+
newRect.y = static_cast<int>(newRect.y * m_scale);
665+
newRect.width = static_cast<int>(newRect.width * m_scale);
666+
newRect.height = static_cast<int>(newRect.height * m_scale);
667+
596668
if (newRect == m_popupRect) {
597669
return;
598670
}
@@ -601,10 +673,10 @@ DX11RenderBackend::updatePopupRect(const CefRect& rect)
601673
m_popupRect = newRect;
602674

603675
// create vertex buffer
604-
CreateQuadVertexBuffer(m_popupRect.x, //
605-
m_popupRect.y, //
606-
m_popupRect.width, //
607-
m_popupRect.height, //
676+
CreateQuadVertexBuffer(static_cast<float>(m_popupRect.x), //
677+
static_cast<float>(m_popupRect.y), //
678+
static_cast<float>(m_popupRect.width), //
679+
static_cast<float>(m_popupRect.height), //
608680
m_popupVertexBuffer.ReleaseAndGetAddressOf() //
609681
);
610682
}
@@ -650,6 +722,8 @@ DX11RenderBackend::render(void* painter)
650722
{
651723
std::lock_guard<std::mutex> l(m_d3dContextLock);
652724

725+
SetTargetView();
726+
653727
ClearTargetView();
654728

655729
DrawCefView();

‎src/win/details/render/hardware/DX11RenderBackend.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
#include <d3d11.h>
77
#include <d3d11_1.h>
88
#include <d3d11_2.h>
9+
#include <dcomp.h>
10+
#include <dxgi.h>
11+
#include <dxgi1_2.h>
912
#include <wrl.h>
1013

1114
#include <mutex>
@@ -27,11 +30,15 @@ class DX11RenderBackend : public ICefViewRenderer
2730
int m_width = 800;
2831
int m_height = 600;
2932

33+
// lock
34+
std::mutex m_d3dContextLock;
35+
3036
// device/context/swapchain
3137
Microsoft::WRL::ComPtr<ID3D11Device> m_d3dDevice;
3238
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_d3dContext;
33-
Microsoft::WRL::ComPtr<IDXGISwapChain> m_swapChain;
34-
std::mutex m_d3dContextLock;
39+
Microsoft::WRL::ComPtr<IDCompositionDevice> m_dcompositionDevice;
40+
Microsoft::WRL::ComPtr<IDCompositionTarget> m_dcompositionTarget;
41+
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
3542

3643
// IA stage
3744
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_inputLayout;
@@ -82,6 +89,7 @@ class DX11RenderBackend : public ICefViewRenderer
8289
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>& pTargetSRV,
8390
D3D11_TEXTURE2D_DESC& targetTextureDesc);
8491

92+
void SetTargetView();
8593
void ClearTargetView();
8694
void DrawCefView();
8795
void DrawCefPopup();

‎thirdparty/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
include(FetchContent)
22

33
if(NOT CEFVIEW_CORE_VERSION)
4-
set(DEFAULT_CEFVIEW_CORE_VERSION "bb1cbae4bce755e88bb89fea3c5ab31e47b44b65")
4+
set(DEFAULT_CEFVIEW_CORE_VERSION "ca9f2c009a6a248a13ff0a2e33bbf46e7a044581")
55
set(CEFVIEW_CORE_VERSION ${DEFAULT_CEFVIEW_CORE_VERSION})
66
message(STATUS "CEFVIEW_CORE_VERSION not set, use default value:${CEFVIEW_CORE_VERSION}")
77
endif()

0 commit comments

Comments
 (0)
Please sign in to comment.