Improve direct2d backing store implementation
Add a per-window swap chain to a QPlatformWindow subclass instead of tying it to the backing store. This is needed to support native widgets (as opposed to alien widgets). Change the backing store to draw to an intermediate pixmap and flush to the requested window by using the per-window swap chain. This also opens the door for faster window presentation later on by using the swap chain more intelligently. Also add a changelog entry for the direct2d plugin, which was omitted earlier. [ChangeLog][QtGui][Windows] Introduce experimental direct2d platform plugin for Windows. This plugin shares most code with the current windows plugin, but substitutes a direct2d-based paint engine for window backing stores and pixmaps. Change-Id: I5f54e7e4c1fb15b1639bd26b712fb40ac141e4ac Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
This commit is contained in:
parent
7d782d4cf9
commit
bd9e1f3915
@ -22,7 +22,8 @@ SOURCES += \
|
||||
qwindowsdirect2dintegration.cpp \
|
||||
qwindowsdirect2dplatformplugin.cpp \
|
||||
qwindowsdirect2ddevicecontext.cpp \
|
||||
qwindowsdirect2dnativeinterface.cpp
|
||||
qwindowsdirect2dnativeinterface.cpp \
|
||||
qwindowsdirect2dwindow.cpp
|
||||
|
||||
HEADERS += \
|
||||
qwindowsdirect2dpaintengine.h \
|
||||
@ -34,6 +35,7 @@ HEADERS += \
|
||||
qwindowsdirect2dbackingstore.h \
|
||||
qwindowsdirect2dintegration.h \
|
||||
qwindowsdirect2ddevicecontext.h \
|
||||
qwindowsdirect2dnativeinterface.h
|
||||
qwindowsdirect2dnativeinterface.h \
|
||||
qwindowsdirect2dwindow.h
|
||||
|
||||
OTHER_FILES += direct2d.json
|
||||
|
@ -45,108 +45,15 @@
|
||||
#include "qwindowsdirect2dpaintdevice.h"
|
||||
#include "qwindowsdirect2dbitmap.h"
|
||||
#include "qwindowsdirect2ddevicecontext.h"
|
||||
#include "qwindowsdirect2dwindow.h"
|
||||
|
||||
#include "qwindowswindow.h"
|
||||
#include "qwindowscontext.h"
|
||||
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <dxgi1_2.h>
|
||||
#include <d3d11.h>
|
||||
#include <wrl.h>
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QWindowsDirect2DBackingStorePrivate
|
||||
{
|
||||
public:
|
||||
QWindowsDirect2DBackingStorePrivate() {}
|
||||
|
||||
ComPtr<IDXGISwapChain1> swapChain;
|
||||
QSharedPointer<QWindowsDirect2DBitmap> backingStore;
|
||||
QScopedPointer<QWindowsDirect2DPaintDevice> nativePaintDevice;
|
||||
|
||||
bool init(HWND hwnd)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
||||
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
desc.BufferCount = 1;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
|
||||
|
||||
HRESULT hr = QWindowsDirect2DContext::instance()->dxgiFactory()->CreateSwapChainForHwnd(
|
||||
QWindowsDirect2DContext::instance()->d3dDevice(), // [in] IUnknown *pDevice
|
||||
hwnd, // [in] HWND hWnd
|
||||
&desc, // [in] const DXGI_SWAP_CHAIN_DESC1 *pDesc
|
||||
NULL, // [in] const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc
|
||||
NULL, // [in] IDXGIOutput *pRestrictToOutput
|
||||
swapChain.ReleaseAndGetAddressOf()); // [out] IDXGISwapChain1 **ppSwapChain
|
||||
|
||||
if (FAILED(hr))
|
||||
qWarning("%s: Could not create swap chain: %#x", __FUNCTION__, hr);
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
bool setupPaintDevice()
|
||||
{
|
||||
if (!backingStore) {
|
||||
ComPtr<ID2D1DeviceContext> deviceContext;
|
||||
ComPtr<IDXGISurface1> backBufferSurface;
|
||||
ComPtr<ID2D1Bitmap1> backBufferBitmap;
|
||||
|
||||
HRESULT hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext(
|
||||
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
|
||||
deviceContext.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
qWarning("%s: Couldn't create Direct2D Device context: %#x", __FUNCTION__, hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = swapChain->GetBuffer(0, IID_PPV_ARGS(&backBufferSurface));
|
||||
if (FAILED(hr)) {
|
||||
qWarning("%s: Could not query backbuffer for DXGI Surface: %#x", __FUNCTION__, hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = deviceContext->CreateBitmapFromDxgiSurface(backBufferSurface.Get(), NULL, backBufferBitmap.ReleaseAndGetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
qWarning("%s: Could not create Direct2D Bitmap from DXGI Surface: %#x", __FUNCTION__, hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
backingStore.reset(new QWindowsDirect2DBitmap(backBufferBitmap.Get(), deviceContext.Get()));
|
||||
}
|
||||
|
||||
if (!nativePaintDevice)
|
||||
nativePaintDevice.reset(new QWindowsDirect2DPaintDevice(backingStore.data(), QInternal::Widget));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void releaseBackingStore()
|
||||
{
|
||||
nativePaintDevice.reset();
|
||||
backingStore.reset();
|
||||
}
|
||||
|
||||
QPaintDevice *paintDevice()
|
||||
{
|
||||
setupPaintDevice();
|
||||
return nativePaintDevice.data();
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
swapChain->Present(1, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
\class QWindowsDirect2DBackingStore
|
||||
\brief Backing store for windows.
|
||||
@ -154,86 +61,43 @@ public:
|
||||
\ingroup qt-lighthouse-win
|
||||
*/
|
||||
|
||||
static inline QWindowsDirect2DPlatformPixmap *platformPixmap(QPixmap *p)
|
||||
{
|
||||
return static_cast<QWindowsDirect2DPlatformPixmap *>(p->handle());
|
||||
}
|
||||
|
||||
QWindowsDirect2DBackingStore::QWindowsDirect2DBackingStore(QWindow *window)
|
||||
: QPlatformBackingStore(window)
|
||||
, d_ptr(new QWindowsDirect2DBackingStorePrivate)
|
||||
{
|
||||
}
|
||||
|
||||
bool QWindowsDirect2DBackingStore::init()
|
||||
{
|
||||
if (window()->surfaceType() == QSurface::RasterSurface) {
|
||||
Q_D(QWindowsDirect2DBackingStore);
|
||||
return d->init(windowsWindow()->handle());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QWindowsDirect2DBackingStore *QWindowsDirect2DBackingStore::create(QWindow *window)
|
||||
{
|
||||
QWindowsDirect2DBackingStore *result = new QWindowsDirect2DBackingStore(window);
|
||||
|
||||
if (!result->init()) {
|
||||
delete result;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QWindowsDirect2DBackingStore::~QWindowsDirect2DBackingStore()
|
||||
{
|
||||
Q_D(QWindowsDirect2DBackingStore);
|
||||
d->releaseBackingStore();
|
||||
d->swapChain.Reset();
|
||||
}
|
||||
|
||||
QPaintDevice *QWindowsDirect2DBackingStore::paintDevice()
|
||||
{
|
||||
QPaintDevice *result = 0;
|
||||
|
||||
if (window()->surfaceType() == QSurface::RasterSurface) {
|
||||
Q_D(QWindowsDirect2DBackingStore);
|
||||
result = d->paintDevice();
|
||||
}
|
||||
|
||||
return result;
|
||||
return m_pixmap.data();
|
||||
}
|
||||
|
||||
void QWindowsDirect2DBackingStore::flush(QWindow *, const QRegion &, const QPoint &)
|
||||
void QWindowsDirect2DBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
if (window()->surfaceType() == QSurface::RasterSurface) {
|
||||
Q_D(QWindowsDirect2DBackingStore);
|
||||
d->flush();
|
||||
}
|
||||
QPlatformWindow *pw = window->handle();
|
||||
if (pw && m_pixmap)
|
||||
static_cast<QWindowsDirect2DWindow *>(pw)->flush(platformPixmap(m_pixmap.data())->bitmap(), region, offset);
|
||||
}
|
||||
|
||||
void QWindowsDirect2DBackingStore::resize(const QSize &size, const QRegion ®ion)
|
||||
{
|
||||
Q_UNUSED(region);
|
||||
|
||||
if (window()->surfaceType() != QSurface::RasterSurface)
|
||||
return;
|
||||
QScopedPointer<QPixmap> oldPixmap(m_pixmap.take());
|
||||
m_pixmap.reset(new QPixmap(size.width(), size.height()));
|
||||
|
||||
Q_D(QWindowsDirect2DBackingStore);
|
||||
d->releaseBackingStore();
|
||||
QWindowsDirect2DContext::instance()->d3dDeviceContext()->ClearState();
|
||||
|
||||
HRESULT hr = d->swapChain->ResizeBuffers(0,
|
||||
size.width(), size.height(),
|
||||
DXGI_FORMAT_UNKNOWN,
|
||||
0);
|
||||
if (FAILED(hr))
|
||||
qWarning("%s: Could not resize buffers: %#x", __FUNCTION__, hr);
|
||||
}
|
||||
|
||||
QWindowsWindow *QWindowsDirect2DBackingStore::windowsWindow() const
|
||||
{
|
||||
if (const QWindow *w = window())
|
||||
if (QPlatformWindow *pw = w->handle())
|
||||
return static_cast<QWindowsWindow *>(pw);
|
||||
return 0;
|
||||
if (oldPixmap) {
|
||||
foreach (const QRect &rect, region.rects())
|
||||
platformPixmap(m_pixmap.data())->copy(oldPixmap->handle(), rect);
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -42,33 +42,28 @@
|
||||
#ifndef QWINDOWSDIRECT2DBACKINGSTORE_H
|
||||
#define QWINDOWSDIRECT2DBACKINGSTORE_H
|
||||
|
||||
#include "qwindowsdirect2dplatformpixmap.h"
|
||||
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtGui/qpa/qplatformbackingstore.h>
|
||||
#include <QtGui/QPixmap>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QWindowsWindow;
|
||||
class QWindowsDirect2DBackingStorePrivate;
|
||||
|
||||
class QWindowsDirect2DBackingStore : public QPlatformBackingStore
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QWindowsDirect2DBackingStore)
|
||||
Q_DISABLE_COPY(QWindowsDirect2DBackingStore)
|
||||
|
||||
public:
|
||||
static QWindowsDirect2DBackingStore *create(QWindow *window);
|
||||
QWindowsDirect2DBackingStore(QWindow *window);
|
||||
~QWindowsDirect2DBackingStore();
|
||||
|
||||
QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
|
||||
void flush(QWindow *, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE;
|
||||
void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE;
|
||||
void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
QWindowsDirect2DBackingStore(QWindow *window);
|
||||
bool init();
|
||||
|
||||
QWindowsWindow *windowsWindow() const;
|
||||
QScopedPointer<QWindowsDirect2DBackingStorePrivate> d_ptr;
|
||||
QScopedPointer<QPixmap> m_pixmap;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -44,11 +44,13 @@
|
||||
#include "qwindowsdirect2dbackingstore.h"
|
||||
#include "qwindowsdirect2dplatformpixmap.h"
|
||||
#include "qwindowsdirect2dnativeinterface.h"
|
||||
#include "qwindowsdirect2dwindow.h"
|
||||
|
||||
#include "qwindowscontext.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtGui/private/qpixmap_raster_p.h>
|
||||
#include <QtGui/qpa/qwindowsysteminterface.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -81,6 +83,13 @@ QWindowsDirect2DIntegration::~QWindowsDirect2DIntegration()
|
||||
return static_cast<QWindowsDirect2DIntegration *>(QWindowsIntegration::instance());
|
||||
}
|
||||
|
||||
QPlatformWindow *QWindowsDirect2DIntegration::createPlatformWindow(QWindow *window) const
|
||||
{
|
||||
QWindowsWindowData data = createWindowData(window);
|
||||
return data.hwnd ? new QWindowsDirect2DWindow(window, data)
|
||||
: Q_NULLPTR;
|
||||
}
|
||||
|
||||
QPlatformNativeInterface *QWindowsDirect2DIntegration::nativeInterface() const
|
||||
{
|
||||
return &d->m_nativeInterface;
|
||||
@ -100,7 +109,7 @@ QPlatformPixmap *QWindowsDirect2DIntegration::createPlatformPixmap(QPlatformPixm
|
||||
|
||||
QPlatformBackingStore *QWindowsDirect2DIntegration::createPlatformBackingStore(QWindow *window) const
|
||||
{
|
||||
return QWindowsDirect2DBackingStore::create(window);
|
||||
return new QWindowsDirect2DBackingStore(window);
|
||||
}
|
||||
|
||||
QWindowsDirect2DContext *QWindowsDirect2DIntegration::direct2DContext() const
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
|
||||
static QWindowsDirect2DIntegration *instance();
|
||||
|
||||
QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
|
||||
QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE;
|
||||
QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const Q_DECL_OVERRIDE;
|
||||
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
|
||||
|
177
src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
Normal file
177
src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qwindowsdirect2dcontext.h"
|
||||
#include "qwindowsdirect2dwindow.h"
|
||||
#include "qwindowsdirect2ddevicecontext.h"
|
||||
#include "qwindowsdirect2dhelpers.h"
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <d2d1_1.h>
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QWindowsDirect2DWindow::QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data)
|
||||
: QWindowsWindow(window, data)
|
||||
, m_needsFullFlush(true)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
||||
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
desc.BufferCount = 1;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
|
||||
|
||||
HRESULT hr = QWindowsDirect2DContext::instance()->dxgiFactory()->CreateSwapChainForHwnd(
|
||||
QWindowsDirect2DContext::instance()->d3dDevice(), // [in] IUnknown *pDevice
|
||||
handle(), // [in] HWND hWnd
|
||||
&desc, // [in] const DXGI_SWAP_CHAIN_DESC1 *pDesc
|
||||
NULL, // [in] const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc
|
||||
NULL, // [in] IDXGIOutput *pRestrictToOutput
|
||||
m_swapChain.ReleaseAndGetAddressOf()); // [out] IDXGISwapChain1 **ppSwapChain
|
||||
|
||||
if (FAILED(hr))
|
||||
qWarning("%s: Could not create swap chain: %#x", __FUNCTION__, hr);
|
||||
|
||||
hr = QWindowsDirect2DContext::instance()->d2dDevice()->CreateDeviceContext(
|
||||
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
|
||||
m_deviceContext.GetAddressOf());
|
||||
if (FAILED(hr))
|
||||
qWarning("%s: Couldn't create Direct2D Device context: %#x", __FUNCTION__, hr);
|
||||
}
|
||||
|
||||
QWindowsDirect2DWindow::~QWindowsDirect2DWindow()
|
||||
{
|
||||
}
|
||||
|
||||
void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC1 desc;
|
||||
HRESULT hr = m_swapChain->GetDesc1(&desc);
|
||||
QRect geom = geometry();
|
||||
|
||||
if (FAILED(hr) || (desc.Width != geom.width()) || (desc.Height != geom.height())) {
|
||||
resizeSwapChain(geom.size());
|
||||
m_swapChain->GetDesc1(&desc);
|
||||
}
|
||||
|
||||
setupBitmap();
|
||||
if (!m_bitmap)
|
||||
return;
|
||||
|
||||
m_bitmap->deviceContext()->begin();
|
||||
|
||||
ID2D1DeviceContext *dc = m_bitmap->deviceContext()->get();
|
||||
if (!m_needsFullFlush) {
|
||||
QRegion clipped = region;
|
||||
clipped &= QRect(0, 0, desc.Width, desc.Height);
|
||||
|
||||
foreach (const QRect &rect, clipped.rects()) {
|
||||
QRectF rectF(rect);
|
||||
dc->DrawBitmap(bitmap->bitmap(),
|
||||
to_d2d_rect_f(rectF),
|
||||
1.0,
|
||||
D2D1_INTERPOLATION_MODE_LINEAR,
|
||||
to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
|
||||
}
|
||||
} else {
|
||||
QRectF rectF(0, 0, desc.Width, desc.Height);
|
||||
dc->DrawBitmap(bitmap->bitmap(),
|
||||
to_d2d_rect_f(rectF),
|
||||
1.0,
|
||||
D2D1_INTERPOLATION_MODE_LINEAR,
|
||||
to_d2d_rect_f(rectF.translated(offset.x(), offset.y())));
|
||||
m_needsFullFlush = false;
|
||||
}
|
||||
|
||||
m_bitmap->deviceContext()->end();
|
||||
m_swapChain->Present(1, 0);
|
||||
}
|
||||
|
||||
void QWindowsDirect2DWindow::resizeSwapChain(const QSize &size)
|
||||
{
|
||||
if (!m_swapChain)
|
||||
return;
|
||||
|
||||
m_bitmap.reset();
|
||||
m_deviceContext->SetTarget(Q_NULLPTR);
|
||||
|
||||
HRESULT hr = m_swapChain->ResizeBuffers(0,
|
||||
size.width(), size.height(),
|
||||
DXGI_FORMAT_UNKNOWN,
|
||||
0);
|
||||
if (FAILED(hr))
|
||||
qWarning("%s: Could not resize swap chain: %#x", __FUNCTION__, hr);
|
||||
|
||||
m_needsFullFlush = true;
|
||||
}
|
||||
|
||||
void QWindowsDirect2DWindow::setupBitmap()
|
||||
{
|
||||
if (m_bitmap)
|
||||
return;
|
||||
|
||||
if (!m_deviceContext)
|
||||
return;
|
||||
|
||||
if (!m_swapChain)
|
||||
return;
|
||||
|
||||
ComPtr<IDXGISurface1> backBufferSurface;
|
||||
HRESULT hr = m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBufferSurface));
|
||||
if (FAILED(hr)) {
|
||||
qWarning("%s: Could not query backbuffer for DXGI Surface: %#x", __FUNCTION__, hr);
|
||||
return;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1Bitmap1> backBufferBitmap;
|
||||
hr = m_deviceContext->CreateBitmapFromDxgiSurface(backBufferSurface.Get(), NULL, backBufferBitmap.GetAddressOf());
|
||||
if (FAILED(hr)) {
|
||||
qWarning("%s: Could not create Direct2D Bitmap from DXGI Surface: %#x", __FUNCTION__, hr);
|
||||
return;
|
||||
}
|
||||
|
||||
m_bitmap.reset(new QWindowsDirect2DBitmap(backBufferBitmap.Get(), m_deviceContext.Get()));
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
74
src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
Normal file
74
src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h
Normal file
@ -0,0 +1,74 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QWINDOWSDIRECT2DWINDOW_H
|
||||
#define QWINDOWSDIRECT2DWINDOW_H
|
||||
|
||||
#include "qwindowswindow.h"
|
||||
#include "qwindowsdirect2dbitmap.h"
|
||||
|
||||
#include <dxgi1_2.h>
|
||||
#include <wrl.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QWindowsDirect2DWindow : public QWindowsWindow
|
||||
{
|
||||
public:
|
||||
QWindowsDirect2DWindow(QWindow *window, const QWindowsWindowData &data);
|
||||
~QWindowsDirect2DWindow();
|
||||
|
||||
void flush(QWindowsDirect2DBitmap *bitmap, const QRegion ®ion, const QPoint &offset);
|
||||
|
||||
private:
|
||||
void resizeSwapChain(const QSize &size);
|
||||
void setupBitmap();
|
||||
|
||||
private:
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
|
||||
Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_deviceContext;
|
||||
QScopedPointer<QWindowsDirect2DBitmap> m_bitmap;
|
||||
bool m_needsFullFlush;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QWINDOWSDIRECT2DWINDOW_H
|
@ -234,9 +234,9 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
|
||||
return false;
|
||||
}
|
||||
|
||||
QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
|
||||
QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const
|
||||
{
|
||||
QWindowsWindow::WindowData requested;
|
||||
QWindowsWindowData requested;
|
||||
requested.flags = window->flags();
|
||||
requested.geometry = window->geometry();
|
||||
// Apply custom margins (see QWindowsWindow::setCustomMargins())).
|
||||
@ -244,8 +244,8 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
|
||||
if (customMarginsV.isValid())
|
||||
requested.customMargins = qvariant_cast<QMargins>(customMarginsV);
|
||||
|
||||
const QWindowsWindow::WindowData obtained
|
||||
= QWindowsWindow::WindowData::create(window, requested, window->title());
|
||||
const QWindowsWindowData obtained
|
||||
= QWindowsWindowData::create(window, requested, window->title());
|
||||
qCDebug(lcQpaWindows).nospace()
|
||||
<< __FUNCTION__ << '<' << window
|
||||
<< "\n Requested: " << requested.geometry << "frame incl.: "
|
||||
@ -254,14 +254,23 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
|
||||
<< "\n Obtained : " << obtained.geometry << " Margins "<< obtained.frame
|
||||
<< " Flags=" << QWindowsWindow::debugWindowFlags(obtained.flags)
|
||||
<< " Handle=" << obtained.hwnd << '\n';
|
||||
if (!obtained.hwnd)
|
||||
return 0;
|
||||
if (requested.flags != obtained.flags)
|
||||
window->setFlags(obtained.flags);
|
||||
// Trigger geometry change signals of QWindow.
|
||||
if ((obtained.flags & Qt::Desktop) != Qt::Desktop && requested.geometry != obtained.geometry)
|
||||
QWindowSystemInterface::handleGeometryChange(window, obtained.geometry);
|
||||
return new QWindowsWindow(window, obtained);
|
||||
|
||||
if (obtained.hwnd) {
|
||||
if (requested.flags != obtained.flags)
|
||||
window->setFlags(obtained.flags);
|
||||
// Trigger geometry change signals of QWindow.
|
||||
if ((obtained.flags & Qt::Desktop) != Qt::Desktop && requested.geometry != obtained.geometry)
|
||||
QWindowSystemInterface::handleGeometryChange(window, obtained.geometry);
|
||||
}
|
||||
|
||||
return obtained;
|
||||
}
|
||||
|
||||
QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
|
||||
{
|
||||
QWindowsWindowData data = createWindowData(window);
|
||||
return data.hwnd ? new QWindowsWindow(window, data)
|
||||
: Q_NULLPTR;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
|
@ -50,6 +50,8 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct QWindowsIntegrationPrivate;
|
||||
struct QWindowsWindowData;
|
||||
class QWindowsWindow;
|
||||
|
||||
class QWindowsIntegration : public QPlatformIntegration
|
||||
{
|
||||
@ -68,6 +70,7 @@ public:
|
||||
|
||||
bool hasCapability(QPlatformIntegration::Capability cap) const;
|
||||
|
||||
QWindowsWindowData createWindowData(QWindow *window) const;
|
||||
QPlatformWindow *createPlatformWindow(QWindow *window) const;
|
||||
#ifndef QT_NO_OPENGL
|
||||
virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
|
||||
|
@ -358,7 +358,7 @@ static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bo
|
||||
|
||||
struct WindowCreationData
|
||||
{
|
||||
typedef QWindowsWindow::WindowData WindowData;
|
||||
typedef QWindowsWindowData WindowData;
|
||||
enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 };
|
||||
|
||||
WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0),
|
||||
@ -534,7 +534,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
|
||||
}
|
||||
}
|
||||
|
||||
QWindowsWindow::WindowData
|
||||
QWindowsWindowData
|
||||
WindowCreationData::create(const QWindow *w, const WindowData &data, QString title) const
|
||||
{
|
||||
typedef QSharedPointer<QWindowCreationContext> QWindowCreationContextPtr;
|
||||
@ -851,7 +851,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
|
||||
\ingroup qt-lighthouse-win
|
||||
*/
|
||||
|
||||
QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
|
||||
QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) :
|
||||
QPlatformWindow(aWindow),
|
||||
m_data(data),
|
||||
m_flags(WithinCreate),
|
||||
@ -1017,14 +1017,14 @@ QWindow *QWindowsWindow::topLevelOf(QWindow *w)
|
||||
return w;
|
||||
}
|
||||
|
||||
QWindowsWindow::WindowData
|
||||
QWindowsWindow::WindowData::create(const QWindow *w,
|
||||
const WindowData ¶meters,
|
||||
QWindowsWindowData
|
||||
QWindowsWindowData::create(const QWindow *w,
|
||||
const QWindowsWindowData ¶meters,
|
||||
const QString &title)
|
||||
{
|
||||
WindowCreationData creationData;
|
||||
creationData.fromWindow(w, parameters.flags);
|
||||
WindowData result = creationData.create(w, parameters, title);
|
||||
QWindowsWindowData result = creationData.create(w, parameters, title);
|
||||
// Force WM_NCCALCSIZE (with wParam=1) via SWP_FRAMECHANGED for custom margin.
|
||||
creationData.initialize(result.hwnd, !parameters.customMargins.isNull(), 1);
|
||||
return result;
|
||||
@ -1452,7 +1452,7 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
|
||||
<< " geometry " << oldGeometry << "->" << newGeometry;
|
||||
}
|
||||
|
||||
QWindowsWindow::WindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
|
||||
QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
|
||||
unsigned flags) const
|
||||
{
|
||||
WindowCreationData creationData;
|
||||
@ -1460,7 +1460,7 @@ QWindowsWindow::WindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt
|
||||
creationData.applyWindowFlags(m_data.hwnd);
|
||||
creationData.initialize(m_data.hwnd, true, m_opacity);
|
||||
|
||||
WindowData result = m_data;
|
||||
QWindowsWindowData result = m_data;
|
||||
result.flags = creationData.flags;
|
||||
result.embedded = creationData.embedded;
|
||||
setFlag(FrameDirty);
|
||||
|
@ -111,6 +111,22 @@ struct QWindowCreationContext
|
||||
int frameHeight;
|
||||
};
|
||||
|
||||
struct QWindowsWindowData
|
||||
{
|
||||
QWindowsWindowData() : hwnd(0), embedded(false) {}
|
||||
|
||||
Qt::WindowFlags flags;
|
||||
QRect geometry;
|
||||
QMargins frame; // Do not use directly for windows, see FrameDirty.
|
||||
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
|
||||
HWND hwnd;
|
||||
bool embedded;
|
||||
|
||||
static QWindowsWindowData create(const QWindow *w,
|
||||
const QWindowsWindowData ¶meters,
|
||||
const QString &title);
|
||||
};
|
||||
|
||||
class QWindowsWindow : public QPlatformWindow
|
||||
{
|
||||
public:
|
||||
@ -140,23 +156,7 @@ public:
|
||||
WithinMaximize = 0x40000
|
||||
};
|
||||
|
||||
struct WindowData
|
||||
{
|
||||
WindowData() : hwnd(0) {}
|
||||
|
||||
Qt::WindowFlags flags;
|
||||
QRect geometry;
|
||||
QMargins frame; // Do not use directly for windows, see FrameDirty.
|
||||
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
|
||||
HWND hwnd;
|
||||
bool embedded;
|
||||
|
||||
static WindowData create(const QWindow *w,
|
||||
const WindowData ¶meters,
|
||||
const QString &title);
|
||||
};
|
||||
|
||||
QWindowsWindow(QWindow *window, const WindowData &data);
|
||||
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
|
||||
~QWindowsWindow();
|
||||
|
||||
virtual QSurfaceFormat format() const { return m_format; }
|
||||
@ -274,7 +274,7 @@ private:
|
||||
inline void setGeometry_sys(const QRect &rect) const;
|
||||
inline QRect frameGeometry_sys() const;
|
||||
inline QRect geometry_sys() const;
|
||||
inline WindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
|
||||
inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
|
||||
inline bool isFullScreen_sys() const;
|
||||
inline void setWindowState_sys(Qt::WindowState newState);
|
||||
inline void setParent_sys(const QPlatformWindow *parent) const;
|
||||
@ -287,7 +287,7 @@ private:
|
||||
inline void destroyIcon();
|
||||
void fireExpose(const QRegion ®ion, bool force=false);
|
||||
|
||||
mutable WindowData m_data;
|
||||
mutable QWindowsWindowData m_data;
|
||||
mutable unsigned m_flags;
|
||||
HDC m_hdc;
|
||||
Qt::WindowState m_windowState;
|
||||
|
Loading…
Reference in New Issue
Block a user