16using Microsoft::WRL::ComPtr;
20QWindowsDirect2DWindow::QWindowsDirect2DWindow(QWindow *window,
const QWindowsWindowData &data)
21 : QWindowsWindow(window, data)
22 , m_directRendering(!(data.flags & Qt::FramelessWindowHint && window->format().hasAlpha()))
24 if (m_directRendering)
27 HRESULT hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext(
28 D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
29 m_deviceContext.GetAddressOf());
31 qWarning(
"%s: Couldn't create Direct2D Device context: %#lx",
__FUNCTION__, hr);
40 m_directRendering = !(flags & Qt::FramelessWindowHint && window()->format().hasAlpha());
41 if (!m_directRendering)
43 else if (!m_swapChain)
46 QWindowsWindow::setWindowFlags(flags);
53 return m_pixmap.data();
59 if (m_directRendering) {
60 DXGI_SWAP_CHAIN_DESC1 desc;
61 HRESULT hr = m_swapChain->GetDesc1(&desc);
62 QRect geom = geometry();
64 if (FAILED(hr) || (desc.Width != UINT(geom.width()) || (desc.Height != UINT(geom.height())))) {
66 m_swapChain->GetDesc1(&desc);
68 size.setWidth(
int(desc.Width));
69 size.setHeight(
int(desc.Height));
71 size = geometry().size();
78 if (bitmap != m_bitmap.data()) {
79 m_bitmap->deviceContext()->begin();
81 ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get();
82 if (!m_needsFullFlush) {
83 QRegion clipped = region;
84 clipped &= QRect(QPoint(), size);
86 for (
const QRect &rect : clipped) {
88 dc->DrawBitmap(bitmap->bitmap(),
91 D2D1_INTERPOLATION_MODE_LINEAR,
92 to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
95 QRectF rectF(QPoint(), size);
99 D2D1_INTERPOLATION_MODE_LINEAR,
100 to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
101 m_needsFullFlush =
false;
104 m_bitmap->deviceContext()->end();
110 if (m_directRendering) {
111 m_swapChain->Present(0, 0);
115 ComPtr<IDXGISurface> bitmapSurface;
116 HRESULT hr = m_bitmap->bitmap()->GetSurface(&bitmapSurface);
117 Q_ASSERT(SUCCEEDED(hr));
118 ComPtr<IDXGISurface1> dxgiSurface;
119 hr = bitmapSurface.As(&dxgiSurface);
120 Q_ASSERT(SUCCEEDED(hr));
123 hr = dxgiSurface->GetDC(FALSE, &hdc);
125 qErrnoWarning(hr,
"Failed to get DC for presenting the surface");
129 const QRect bounds = window()->geometry();
130 const SIZE size = { bounds.width(), bounds.height() };
131 const POINT ptDst = { bounds.x(), bounds.y() };
132 const POINT ptSrc = { 0, 0 };
133 const BLENDFUNCTION blend = { AC_SRC_OVER, 0, BYTE(255.0 * opacity()), AC_SRC_ALPHA };
134 const QRect r = region.boundingRect();
135 const RECT dirty = { r.left(), r.top(), r.left() + r.width(), r.top() + r.height() };
136 UPDATELAYEREDWINDOWINFO info = {
sizeof(UPDATELAYEREDWINDOWINFO),
nullptr,
137 &ptDst, &size, hdc, &ptSrc, 0, &blend, ULW_ALPHA, &dirty };
138 if (!UpdateLayeredWindowIndirect(handle(), &info))
139 qErrnoWarning(
int(GetLastError()),
"Failed to update the layered window");
141 hr = dxgiSurface->ReleaseDC(
nullptr);
143 qErrnoWarning(hr,
"Failed to release the DC for presentation");
148 DXGI_SWAP_CHAIN_DESC1 desc = {};
150 desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
151 desc.SampleDesc.Count = 1;
152 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
153 desc.BufferCount = 1;
154 desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
162 m_swapChain.ReleaseAndGetAddressOf());
165 qWarning(
"%s: Could not create swap chain: %#lx",
__FUNCTION__, hr);
167 m_needsFullFlush =
true;
174 m_deviceContext->SetTarget(
nullptr);
175 m_needsFullFlush =
true;
180 HRESULT hr = m_swapChain->ResizeBuffers(0,
181 UINT(size.width()), UINT(size.height()),
185 qWarning(
"%s: Could not resize swap chain: %#lx",
__FUNCTION__, hr);
190 const QSharedPointer<QWindowsDirect2DBitmap> null_result;
195 D2D1_PIXEL_FORMAT format = m_bitmap->bitmap()->GetPixelFormat();
196 D2D1_SIZE_U size = m_bitmap->bitmap()->GetPixelSize();
199 m_bitmap->bitmap()->GetDpi(&dpiX, &dpiY);
201 D2D1_BITMAP_PROPERTIES1 properties = {
205 D2D1_BITMAP_OPTIONS_TARGET,
208 ComPtr<ID2D1Bitmap1> copy;
209 HRESULT hr = m_deviceContext.Get()->CreateBitmap(size,
nullptr, 0, properties, ©);
212 qWarning(
"%s: Could not create staging bitmap: %#lx",
__FUNCTION__, hr);
216 hr = copy.Get()->CopyFromBitmap(
nullptr, m_bitmap->bitmap(),
nullptr);
218 qWarning(
"%s: Could not copy from bitmap! %#lx",
__FUNCTION__, hr);
230 if (!m_deviceContext)
233 if (m_directRendering && !m_swapChain)
237 ComPtr<IDXGISurface1> backBufferSurface;
238 if (m_directRendering) {
239 hr = m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBufferSurface));
241 qWarning(
"%s: Could not query backbuffer for DXGI Surface: %#lx",
__FUNCTION__, hr);
245 const QRect rect = geometry();
246 CD3D11_TEXTURE2D_DESC backBufferDesc(DXGI_FORMAT_B8G8R8A8_UNORM, UINT(rect.width()), UINT(rect.height()), 1, 1);
247 backBufferDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
248 backBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
249 ComPtr<ID3D11Texture2D> backBufferTexture;
252 qErrnoWarning(hr,
"Failed to create backing texture for indirect rendering");
256 hr = backBufferTexture.As(&backBufferSurface);
258 qErrnoWarning(hr,
"Failed to cast back buffer surface to DXGI surface");
263 ComPtr<ID2D1Bitmap1> backBufferBitmap;
264 hr = m_deviceContext->CreateBitmapFromDxgiSurface(backBufferSurface.Get(),
nullptr, backBufferBitmap.GetAddressOf());
266 qWarning(
"%s: Could not create Direct2D Bitmap from DXGI Surface: %#lx",
__FUNCTION__, hr);
270 m_bitmap.reset(
new QWindowsDirect2DBitmap(backBufferBitmap.Get(), m_deviceContext.Get()));
272 QWindowsDirect2DPaintEngine::Flags flags = QWindowsDirect2DPaintEngine::NoFlag;
273 if (!m_directRendering)
274 flags |= QWindowsDirect2DPaintEngine::TranslucentTopLevelWindow;
275 auto *pp =
new QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixmapType,
278 m_pixmap.reset(
new QPixmap(pp));
ID2D1Bitmap1 * bitmap() const
ID3D11Device * d3dDevice() const
IDXGIFactory2 * dxgiFactory() const
static QWindowsDirect2DContext * instance()
void setWindowFlags(Qt::WindowFlags flags) override
Requests setting the window flags of this surface to flags.
~QWindowsDirect2DWindow()
void present(const QRegion ®ion)
QSharedPointer< QWindowsDirect2DBitmap > copyBackBuffer() const
void flush(QWindowsDirect2DBitmap *bitmap, const QRegion ®ion, const QPoint &offset)
void resizeSwapChain(const QSize &size)