summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-10-02 01:01:20 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2019-10-02 08:39:15 +0200
commit4c8814a341aace34f9a6011e9ec16048dc0f18b6 (patch)
tree3f3193c51c0883ae70de3ae3a3b225b3c7b9b8cc /src/plugins
parent009d86da2d5a928865819fe44b4d1c78d455bbb9 (diff)
parent8791a8398ac232a8daab98601f1bef88bdf7638f (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.cpp5
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm2
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm205
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp62
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp256
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp12
-rw-r--r--src/plugins/platforms/windows/windows.pri2
8 files changed, 214 insertions, 333 deletions
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp
index 7fc68c3d7c..d3a8a53241 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp
@@ -465,7 +465,8 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const
return QStringList(QLatin1String("android"));
}
return QStringList(QLatin1String("fusion"));
-
+ case DialogButtonBoxLayout:
+ return QVariant(QPlatformDialogHelper::AndroidLayout);
case MouseDoubleClickDistance:
{
int minimumDistance = qEnvironmentVariableIntValue("QT_ANDROID_MINIMUM_MOUSE_DOUBLE_CLICK_DISTANCE");
@@ -489,8 +490,6 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const
Q_FALLTHROUGH();
}
- case DialogButtonBoxLayout:
- return QVariant(QPlatformDialogHelper::AndroidLayout);
default:
return QPlatformTheme::themeHint(hint);
}
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index d3bb0711f0..e87fc39c42 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -881,7 +881,7 @@ void QCocoaEventDispatcherPrivate::processPostedEvents()
return;
}
- int serial = serialNumber.load();
+ int serial = serialNumber.loadRelaxed();
if (!threadData->canWait || (serial != lastSerial)) {
lastSerial = serial;
QCoreApplication::sendPostedEvents();
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
index e72142466b..ce5488ead0 100644
--- a/src/plugins/platforms/cocoa/qnsview_drawing.mm
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -43,9 +43,7 @@
- (void)initDrawing
{
- self.wantsLayer = [self layerExplicitlyRequested]
- || [self shouldUseMetalLayer]
- || [self layerEnabledByMacOS];
+ [self updateLayerBacking];
// Enable high-DPI OpenGL for retina displays. Enabling has the side
// effect that Cocoa will start calling glViewport(0, 0, width, height),
@@ -71,22 +69,13 @@
return YES;
}
-- (void)drawRect:(NSRect)dirtyRect
-{
- Q_UNUSED(dirtyRect);
-
- if (!m_platformWindow)
- return;
-
- QRegion exposedRegion;
- const NSRect *dirtyRects;
- NSInteger numDirtyRects;
- [self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
- for (int i = 0; i < numDirtyRects; ++i)
- exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
+// ----------------------- Layer setup -----------------------
- qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
- m_platformWindow->handleExposeEvent(exposedRegion);
+- (void)updateLayerBacking
+{
+ self.wantsLayer = [self layerEnabledByMacOS]
+ || [self layerExplicitlyRequested]
+ || [self shouldUseMetalLayer];
}
- (BOOL)layerEnabledByMacOS
@@ -123,40 +112,81 @@
return surfaceType == QWindow::MetalSurface || surfaceType == QWindow::VulkanSurface;
}
+/*
+ This method is called by AppKit when layer-backing is requested by
+ setting wantsLayer too YES (via -[NSView _updateLayerBackedness]),
+ or in cases where AppKit itself decides that a view should be
+ layer-backed.
+
+ Note however that some code paths in AppKit will not go via this
+ method for creating the backing layer, and will instead create the
+ layer manually, and just call setLayer. An example of this is when
+ an NSOpenGLContext is attached to a view, in which case AppKit will
+ create a new layer in NSOpenGLContextSetLayerOnViewIfNecessary.
+
+ For this reason we leave the implementation of this override as
+ minimal as possible, only focusing on creating the appropriate
+ layer type, and then leave it up to setLayer to do the work of
+ making sure the layer is set up correctly.
+*/
- (CALayer *)makeBackingLayer
{
if ([self shouldUseMetalLayer]) {
// Check if Metal is supported. If it isn't then it's most likely
// too late at this point and the QWindow will be non-functional,
// but we can at least print a warning.
- if (![MTLCreateSystemDefaultDevice() autorelease]) {
- qWarning() << "QWindow initialization error: Metal is not supported";
- return [super makeBackingLayer];
+ if ([MTLCreateSystemDefaultDevice() autorelease]) {
+ return [CAMetalLayer layer];
+ } else {
+ qCWarning(lcQpaDrawing) << "Failed to create QWindow::MetalSurface."
+ << "Metal is not supported by any of the GPUs in this system.";
}
-
- CAMetalLayer *layer = [CAMetalLayer layer];
-
- // Set the contentsScale for the layer. This is normally done in
- // viewDidChangeBackingProperties, however on startup that function
- // is called before the layer is created here. The layer's drawableSize
- // is updated from layoutSublayersOfLayer as usual.
- layer.contentsScale = self.window.backingScaleFactor;
-
- return layer;
}
return [super makeBackingLayer];
}
+/*
+ This method is called by AppKit whenever the view is asked to change
+ its layer, which can happen both as a result of enabling layer-backing,
+ or when a layer is set explicitly. The latter can happen both when a
+ view is layer-hosting, or when AppKit internals are switching out the
+ layer-backed view, as described above for makeBackingLayer.
+*/
- (void)setLayer:(CALayer *)layer
{
- qCDebug(lcQpaDrawing) << "Making" << self << "layer-backed with" << layer
- << "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
+ qCDebug(lcQpaDrawing) << "Making" << self
+ << (self.wantsLayer ? "layer-backed" : "layer-hosted")
+ << "with" << layer << "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
: [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS");
+
+ if (layer.delegate && layer.delegate != self) {
+ qCWarning(lcQpaDrawing) << "Layer already has delegate" << layer.delegate
+ << "This delegate is responsible for all view updates for" << self;
+ } else {
+ layer.delegate = self;
+ }
+
[super setLayer:layer];
- layer.delegate = self;
+
+ // When adding a view to a view hierarchy the backing properties will change
+ // which results in updating the contents scale, but in case of switching the
+ // layer on a view that's already in a view hierarchy we need to manually ensure
+ // the scale is up to date.
+ if (self.superview)
+ [self updateLayerContentsScale];
+
+ if (self.opaque && lcQpaDrawing().isDebugEnabled()) {
+ // If the view claims to be opaque we expect it to fill the entire
+ // layer with content, in which case we want to detect any areas
+ // where it doesn't.
+ layer.backgroundColor = NSColor.magentaColor.CGColor;
+ }
+
}
+// ----------------------- Layer updates -----------------------
+
- (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy
{
// We need to set this explicitly since the super implementation
@@ -164,17 +194,95 @@
return NSViewLayerContentsRedrawDuringViewResize;
}
-#if 0 // Disabled until we enable lazy backingstore resizing
- (NSViewLayerContentsPlacement)layerContentsPlacement
{
- // Always place the layer at top left without any automatic scaling,
- // so that we can re-use larger layers when resizing a window down.
+ // Always place the layer at top left without any automatic scaling.
+ // This will highlight situations where we're missing content for the
+ // layer by not responding to the displayLayer: request synchronously.
+ // It also allows us to re-use larger layers when resizing a window down.
return NSViewLayerContentsPlacementTopLeft;
}
-#endif
+- (void)viewDidChangeBackingProperties
+{
+ qCDebug(lcQpaDrawing) << "Backing properties changed for" << self;
+
+ if (self.layer)
+ [self updateLayerContentsScale];
+
+ // Ideally we would plumb this situation through QPA in a way that lets
+ // clients invalidate their own caches, recreate QBackingStore, etc.
+ // For now we trigger an expose, and let QCocoaBackingStore deal with
+ // buffer invalidation internally.
+ [self setNeedsDisplay:YES];
+}
+
+- (void)updateLayerContentsScale
+{
+ // We expect clients to fill the layer with retina aware content,
+ // based on the devicePixelRatio of the QWindow, so we set the
+ // layer's content scale to match that. By going via devicePixelRatio
+ // instead of applying the NSWindow's backingScaleFactor, we also take
+ // into account OpenGL views with wantsBestResolutionOpenGLSurface set
+ // to NO. In this case the window will have a backingScaleFactor of 2,
+ // but the QWindow will have a devicePixelRatio of 1.
+ auto devicePixelRatio = m_platformWindow->devicePixelRatio();
+ qCDebug(lcQpaDrawing) << "Updating" << self.layer << "content scale to" << devicePixelRatio;
+ self.layer.contentsScale = devicePixelRatio;
+}
+
+/*
+ This method is called by AppKit to determine whether it should update
+ the contentScale of the layer to match the window backing scale.
+
+ We always return NO since we're updating the contents scale manually.
+*/
+- (BOOL)layer:(CALayer *)layer shouldInheritContentsScale:(CGFloat)scale fromWindow:(NSWindow *)window
+{
+ Q_UNUSED(layer); Q_UNUSED(scale); Q_UNUSED(window);
+ return NO;
+}
+
+// ----------------------- Draw callbacks -----------------------
+
+/*
+ This method is called by AppKit for the non-layer case, where we are
+ drawing into the NSWindow's surface.
+*/
+- (void)drawRect:(NSRect)dirtyBoundingRect
+{
+ Q_ASSERT_X(!self.layer, "QNSView",
+ "The drawRect code path should not be hit when we are layer backed");
+
+ if (!m_platformWindow)
+ return;
+
+ QRegion exposedRegion;
+ const NSRect *dirtyRects;
+ NSInteger numDirtyRects;
+ [self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
+ for (int i = 0; i < numDirtyRects; ++i)
+ exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
+
+ if (exposedRegion.isEmpty())
+ exposedRegion = QRectF::fromCGRect(dirtyBoundingRect).toRect();
+
+ qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
+ m_platformWindow->handleExposeEvent(exposedRegion);
+}
+
+/*
+ This method is called by AppKit when we are layer-backed, where
+ we are drawing into the layer.
+*/
- (void)displayLayer:(CALayer *)layer
{
+ Q_ASSERT_X(self.layer && layer == self.layer, "QNSView",
+ "The displayLayer code path should only be hit for our own layer");
+
+ if (!m_platformWindow)
+ return;
+
if (!NSThread.isMainThread) {
// Qt is calling AppKit APIs such as -[NSOpenGLContext setView:] on secondary threads,
// which we shouldn't do. This may result in AppKit (wrongly) triggering a display on
@@ -184,29 +292,8 @@
return;
}
- Q_ASSERT(layer == self.layer);
-
- if (!m_platformWindow)
- return;
-
qCDebug(lcQpaDrawing) << "[QNSView displayLayer]" << m_platformWindow->window();
-
- // FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect());
}
-- (void)viewDidChangeBackingProperties
-{
- qCDebug(lcQpaDrawing) << "Backing properties changed for" << self;
-
- if (self.layer)
- self.layer.contentsScale = self.window.backingScaleFactor;
-
- // Ideally we would plumb this situation through QPA in a way that lets
- // clients invalidate their own caches, recreate QBackingStore, etc.
- // For now we trigger an expose, and let QCocoaBackingStore deal with
- // buffer invalidation internally.
- [self setNeedsDisplay:YES];
-}
-
@end
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 3591b2c505..d9521e7e08 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -891,13 +891,6 @@ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current()
result.profile = QSurfaceFormat::CoreProfile;
else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
result.profile = QSurfaceFormat::CompatibilityProfile;
- if (result.version < 0x0400)
- return result;
- // v4.0 onwards
- value = 0;
- QOpenGLStaticContext::opengl32.glGetIntegerv(RESET_NOTIFICATION_STRATEGY_ARB, &value);
- if (value == LOSE_CONTEXT_ON_RESET_ARB)
- result.options |= QSurfaceFormat::ResetNotification;
return result;
}
@@ -975,6 +968,7 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext()
*/
#define SAMPLE_BUFFER_EXTENSION "GL_ARB_multisample"
+#define ROBUSTNESS_EXTENSION "GL_ARB_robustness"
QOpenGLStaticContext::QOpenGLStaticContext() :
vendor(QOpenGLStaticContext::getGlString(GL_VENDOR)),
@@ -995,9 +989,31 @@ QOpenGLStaticContext::QOpenGLStaticContext() :
wglGetExtensionsStringARB(reinterpret_cast<WglGetExtensionsStringARB>(
reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetExtensionsStringARB"))))
{
- if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ")
- || extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1)
- extensions |= SampleBuffers;
+ if (defaultFormat.version < 0x0300) {
+ if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ")
+ || extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1)
+ extensions |= SampleBuffers;
+ if (extensionNames.startsWith(ROBUSTNESS_EXTENSION " ")
+ || extensionNames.indexOf(" " ROBUSTNESS_EXTENSION " ") != -1)
+ extensions |= Robustness;
+ } else {
+ typedef const GLubyte * (APIENTRY *glGetStringi_t)(GLenum, GLuint);
+ auto glGetStringi = reinterpret_cast<glGetStringi_t>(
+ reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetStringi")));
+ if (glGetStringi) {
+ GLint n = 0;
+ QOpenGLStaticContext::opengl32.glGetIntegerv(GL_NUM_EXTENSIONS, &n);
+ for (GLint i = 0; i < n; ++i) {
+ const char *p = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
+ if (p) {
+ if (!strcmp(p, SAMPLE_BUFFER_EXTENSION))
+ extensions |= SampleBuffers;
+ else if (!strcmp(p, ROBUSTNESS_EXTENSION))
+ extensions |= Robustness;
+ }
+ }
+ }
+ }
}
QByteArray QOpenGLStaticContext::getGlString(unsigned int which)
@@ -1236,27 +1252,11 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval)
if (m_staticContext->wglGetSwapInternalExt && obtainedSwapInterval)
*obtainedSwapInterval = m_staticContext->wglGetSwapInternalExt();
- bool hasRobustness = false;
- if (m_obtainedFormat.majorVersion() < 3) {
- const char *exts = reinterpret_cast<const char *>(QOpenGLStaticContext::opengl32.glGetString(GL_EXTENSIONS));
- hasRobustness = exts && strstr(exts, "GL_ARB_robustness");
- } else {
- typedef const GLubyte * (APIENTRY *glGetStringi_t)(GLenum, GLuint);
- auto glGetStringi = reinterpret_cast<glGetStringi_t>(
- reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetStringi")));
- if (glGetStringi) {
- GLint n = 0;
- QOpenGLStaticContext::opengl32.glGetIntegerv(GL_NUM_EXTENSIONS, &n);
- for (GLint i = 0; i < n; ++i) {
- const char *p = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
- if (p && !strcmp(p, "GL_ARB_robustness")) {
- hasRobustness = true;
- break;
- }
- }
- }
- }
- if (hasRobustness) {
+ if (testFlag(m_staticContext->extensions, QOpenGLStaticContext::Robustness)) {
+ GLint value = 0;
+ QOpenGLStaticContext::opengl32.glGetIntegerv(RESET_NOTIFICATION_STRATEGY_ARB, &value);
+ if (value == LOSE_CONTEXT_ON_RESET_ARB)
+ m_obtainedFormat.setOption(QSurfaceFormat::ResetNotification);
m_getGraphicsResetStatus = reinterpret_cast<GlGetGraphicsResetStatusArbType>(
reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetGraphicsResetStatusARB")));
}
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index e962af39c2..e5f6fefd5a 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -142,7 +142,8 @@ public:
enum Extensions
{
SampleBuffers = 0x1,
- sRGBCapableFramebuffer = 0x2
+ sRGBCapableFramebuffer = 0x2,
+ Robustness = 0x4,
};
typedef bool
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index 63ecbfe0ea..afc1991e2c 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -47,7 +47,6 @@
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qstandardpaths.h>
-#include <QtCore/qlibrary.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qhash.h>
@@ -58,8 +57,6 @@
#include <QtCore/qt_windows.h>
#include <private/qsystemlibrary_p.h>
#include <d3d9.h>
-#include <d3d10.h>
-#include <dxgi.h>
QT_BEGIN_NAMESPACE
@@ -83,259 +80,52 @@ static GpuDescription adapterIdentifierToGpuDescription(const D3DADAPTER_IDENTIF
return result;
}
-class QGraphicsAdapterInfo
+class QDirect3D9Handle
{
public:
- Q_DISABLE_COPY_MOVE(QGraphicsAdapterInfo)
+ Q_DISABLE_COPY_MOVE(QDirect3D9Handle)
- QGraphicsAdapterInfo();
- ~QGraphicsAdapterInfo();
+ QDirect3D9Handle();
+ ~QDirect3D9Handle();
- bool isValid() const;
+ bool isValid() const { return m_direct3D9 != nullptr; }
- UINT adapterCount() const;
+ UINT adapterCount() const { return m_direct3D9 ? m_direct3D9->GetAdapterCount() : 0u; }
bool retrieveAdapterIdentifier(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const;
private:
- QSystemLibrary m_dxgilib;
- IDXGIFactory1 *m_dxgiFactory1 = nullptr;
-
QSystemLibrary m_d3d9lib;
IDirect3D9 *m_direct3D9 = nullptr;
-
- /* This is a value from the DXGI_ADAPTER_FLAG enum.
- * However, it's not available in dxgi.h from MinGW,
- * so define it here in any case. */
- enum { DXGI_ADAPTER_FLAG_SOFTWARE = 2 };
-
- UINT adapterCountDXGI() const;
- bool retrieveAdapterIdentifierDXGI(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const;
-
- UINT adapterCountD3D9() const;
- bool retrieveAdapterIdentifierD3D9(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const;
};
-QGraphicsAdapterInfo::QGraphicsAdapterInfo() :
- m_dxgilib(QStringLiteral("dxgi")),
+QDirect3D9Handle::QDirect3D9Handle() :
m_d3d9lib(QStringLiteral("d3d9"))
{
- using PtrCreateDXGIFactory1 = HRESULT (WINAPI *)(REFIID, void**);
+ using PtrDirect3DCreate9 = IDirect3D9 *(WINAPI *)(UINT);
- if (m_dxgilib.load()) {
- if (auto createDXGIFactory1 = (PtrCreateDXGIFactory1)m_dxgilib.resolve("CreateDXGIFactory1"))
- createDXGIFactory1(IID_PPV_ARGS(&m_dxgiFactory1));
- }
-
- if (!m_dxgiFactory1) {
- using PtrDirect3DCreate9 = IDirect3D9 *(WINAPI *)(UINT);
-
- if (m_d3d9lib.load()) {
- if (auto direct3DCreate9 = (PtrDirect3DCreate9)m_d3d9lib.resolve("Direct3DCreate9"))
- m_direct3D9 = direct3DCreate9(D3D_SDK_VERSION);
- }
+ if (m_d3d9lib.load()) {
+ if (auto direct3DCreate9 = (PtrDirect3DCreate9)m_d3d9lib.resolve("Direct3DCreate9"))
+ m_direct3D9 = direct3DCreate9(D3D_SDK_VERSION);
}
}
-QGraphicsAdapterInfo::~QGraphicsAdapterInfo()
+QDirect3D9Handle::~QDirect3D9Handle()
{
- if (m_dxgiFactory1)
- m_dxgiFactory1->Release();
if (m_direct3D9)
m_direct3D9->Release();
}
-bool QGraphicsAdapterInfo::isValid() const
-{
- return m_dxgiFactory1 != nullptr || m_direct3D9 != nullptr;
-}
-
-UINT QGraphicsAdapterInfo::adapterCount() const
-{
- if (m_dxgiFactory1)
- return adapterCountDXGI();
- if (m_direct3D9)
- return adapterCountD3D9();
- return 0;
-}
-
-bool QGraphicsAdapterInfo::retrieveAdapterIdentifier(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const
-{
- if (m_dxgiFactory1)
- return retrieveAdapterIdentifierDXGI(n, adapterIdentifier);
- if (m_direct3D9)
- return retrieveAdapterIdentifierD3D9(n, adapterIdentifier);
- return false;
-}
-
-UINT QGraphicsAdapterInfo::adapterCountDXGI() const
-{
- /* DXGI doesn't have an adapterCount(), instead we have to call EnumAdapters1()
- * until DXGI_ERROR_NOT_FOUND is returned. */
- UINT n = 0;
-
- IDXGIAdapter1 *adapter;
- while (SUCCEEDED(m_dxgiFactory1->EnumAdapters1(n, &adapter))) {
- adapter->Release();
- ++n;
- }
-
- return n;
-}
-
-// Detect whether we are running under 64-bit Windows.
-static bool isWow64Process()
-{
- typedef BOOL (WINAPI *IsWow64ProcessPtr)(HANDLE hProcess, PBOOL Wow64Process);
- IsWow64ProcessPtr IsWow64Process = (IsWow64ProcessPtr)QLibrary::resolve(
- QStringLiteral("kernel32.dll"), "IsWow64Process");
-
- if (IsWow64Process) {
- BOOL IsWow64 = FALSE;
- if (IsWow64Process(GetCurrentProcess(), &IsWow64))
- return IsWow64;
- }
- return false;
-}
-
-// Read a string value from registry
-static QString regGetString(HKEY key, const wchar_t* valueName)
-{
- QVarLengthArray<wchar_t, MAX_PATH> buf (MAX_PATH);
- LRESULT res;
- DWORD bufSize = buf.size() * sizeof(wchar_t);
- res = RegGetValue(key, nullptr, valueName,
- RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ, nullptr,
- buf.data(), &bufSize);
- if (res == ERROR_MORE_DATA) {
- buf.resize(bufSize / sizeof(wchar_t));
- bufSize = buf.size() * sizeof(wchar_t);
- res = RegGetValue(key, nullptr, valueName,
- RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ, nullptr,
- buf.data(), &bufSize);
- }
- /* In case of REG_MULTI_SZ, this returns just the first string,
- * but that is sufficient for our purposes. */
- if (res == ERROR_SUCCESS)
- return QString::fromWCharArray(buf.data());
- return QString();
-}
-
-// Read driver name given a DeviceKey
-static QString retrieveDriverName(const wchar_t *driverKey)
-{
- /* Kernel-style prefix, maps to HKLM
- * (see https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/registry-key-object-routines) */
- static const wchar_t prefixMappingHKLM[] = L"\\Registry\\Machine\\";
- const size_t prefixMappingHKLMLen = wcslen(prefixMappingHKLM);
- if (wcsnicmp(driverKey, prefixMappingHKLM, prefixMappingHKLMLen) != 0)
- return QString();
-
- driverKey += prefixMappingHKLMLen;
- QString driverPath;
- HKEY key;
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, driverKey, 0, KEY_READ | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS) {
- const wchar_t *valueName =
- isWow64Process() ? L"UserModeDriverNameWow" : L"UserModeDriverName";
- driverPath = regGetString(key, valueName);
- RegCloseKey(key);
- }
- if (!driverPath.isEmpty()) {
- int fileNameSep = driverPath.lastIndexOf(QLatin1Char('\\'));
- if (fileNameSep >= 0)
- driverPath = driverPath.mid(fileNameSep + 1);
- return driverPath;
- }
- return QString();
-}
-
-// Retrieve driver name for a display device from registry.
-static QString driverNameForDevice(const wchar_t *displayDevice)
-{
- QString driverName;
- DISPLAY_DEVICE dd;
- memset(&dd, 0, sizeof(dd));
- dd.cb = sizeof(dd);
- for (int dev = 0; EnumDisplayDevices(nullptr, dev, &dd, 0); ++dev) {
- if (wcsicmp(displayDevice, dd.DeviceName) == 0) {
- // DeviceKey is documented as "internal", but it's a registry key in kernel format
- driverName = retrieveDriverName(dd.DeviceKey);
- break;
- }
- }
- if (driverName.isEmpty()) {
- /* Fall back to driver name from EnumDisplaySettings.
- * This is only a fallback as on Windows 10 this just returns an device-independent
- * name. OTOH, it's possible to recognize RDP connections from the driver name. */
- DEVMODE devMode;
- if (EnumDisplaySettings(displayDevice, ENUM_CURRENT_SETTINGS, &devMode))
- driverName = QString::fromWCharArray(devMode.dmDeviceName);
- }
- return driverName;
-}
-
-bool QGraphicsAdapterInfo::retrieveAdapterIdentifierDXGI(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const
-{
- IDXGIAdapter1 *adapter;
- if (FAILED(m_dxgiFactory1->EnumAdapters1(n, &adapter)))
- return false;
-
- bool result = false;
-
- DXGI_ADAPTER_DESC1 adapterDesc;
- if (SUCCEEDED(adapter->GetDesc1(&adapterDesc))) {
- if ((adapterDesc.VendorId != 0) && (adapterDesc.DeviceId != 0) // Don't use adapter description of Software Devices
- && ((adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0)) {
- memset(adapterIdentifier, 0, sizeof(*adapterIdentifier));
- WideCharToMultiByte(1252, 0, adapterDesc.Description, -1,
- adapterIdentifier->Description,
- sizeof(adapterIdentifier->Description), nullptr, nullptr);
- adapterIdentifier->Description[sizeof(adapterIdentifier->Description) - 1] = 0;
- adapterIdentifier->VendorId = adapterDesc.VendorId;
- adapterIdentifier->DeviceId = adapterDesc.DeviceId;
- adapterIdentifier->SubSysId = adapterDesc.SubSysId;
- adapterIdentifier->Revision = adapterDesc.Revision;
-
- LARGE_INTEGER umdVersion;
- if (SUCCEEDED(adapter->CheckInterfaceSupport(__uuidof(ID3D10Device), &umdVersion))) {
- adapterIdentifier->DriverVersion = umdVersion;
- result = true;
- }
-
- /* DXGI doesn't expose the driver name, but we can get it from the registry.
- * But we need a device name to follow. */
- IDXGIOutput *output = nullptr;
- if (SUCCEEDED(adapter->EnumOutputs (0, &output))) {
- DXGI_OUTPUT_DESC outputDesc;
- if (SUCCEEDED(output->GetDesc (&outputDesc))) {
- QString driverName = driverNameForDevice(outputDesc.DeviceName);
- qstrncpy(adapterIdentifier->Driver, driverName.toLatin1().constData(),
- sizeof(adapterIdentifier->Driver));
- }
- output->Release();
- }
- }
- }
-
- adapter->Release();
-
- return result;
-}
-
-UINT QGraphicsAdapterInfo::adapterCountD3D9() const
-{
- return m_direct3D9->GetAdapterCount();
-}
-
-bool QGraphicsAdapterInfo::retrieveAdapterIdentifierD3D9(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const
+bool QDirect3D9Handle::retrieveAdapterIdentifier(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const
{
- return SUCCEEDED(m_direct3D9->GetAdapterIdentifier(n, 0, adapterIdentifier));
+ return m_direct3D9
+ && SUCCEEDED(m_direct3D9->GetAdapterIdentifier(n, 0, adapterIdentifier));
}
GpuDescription GpuDescription::detect()
{
GpuDescription result;
- QGraphicsAdapterInfo adapterInfo;
- if (!adapterInfo.isValid())
+ QDirect3D9Handle direct3D9;
+ if (!direct3D9.isValid())
return result;
D3DADAPTER_IDENTIFIER9 adapterIdentifier;
@@ -346,7 +136,7 @@ GpuDescription GpuDescription::detect()
// and D3D uses by default. Therefore querying any additional adapters is
// futile and not useful for our purposes in general, except for
// identifying a few special cases later on.
- if (adapterInfo.retrieveAdapterIdentifier(0, &adapterIdentifier)) {
+ if (direct3D9.retrieveAdapterIdentifier(0, &adapterIdentifier)) {
result = adapterIdentifierToGpuDescription(adapterIdentifier);
isAMD = result.vendorId == VENDOR_ID_AMD;
}
@@ -355,9 +145,9 @@ GpuDescription GpuDescription::detect()
// when starting apps on a screen connected to the Intel card) by looking
// for a default AMD adapter and an additional non-AMD one.
if (isAMD) {
- const UINT adapterCount = adapterInfo.adapterCount();
+ const UINT adapterCount = direct3D9.adapterCount();
for (UINT adp = 1; adp < adapterCount; ++adp) {
- if (adapterInfo.retrieveAdapterIdentifier(adp, &adapterIdentifier)
+ if (direct3D9.retrieveAdapterIdentifier(adp, &adapterIdentifier)
&& adapterIdentifier.VendorId != VENDOR_ID_AMD) {
// Bingo. Now figure out the display for the AMD card.
DISPLAY_DEVICE dd;
@@ -382,11 +172,11 @@ GpuDescription GpuDescription::detect()
QVector<GpuDescription> GpuDescription::detectAll()
{
QVector<GpuDescription> result;
- QGraphicsAdapterInfo adapterInfo;
- if (const UINT adapterCount = adapterInfo.adapterCount()) {
+ QDirect3D9Handle direct3D9;
+ if (const UINT adapterCount = direct3D9.adapterCount()) {
for (UINT adp = 0; adp < adapterCount; ++adp) {
D3DADAPTER_IDENTIFIER9 adapterIdentifier;
- if (adapterInfo.retrieveAdapterIdentifier(adp, &adapterIdentifier))
+ if (direct3D9.retrieveAdapterIdentifier(adp, &adapterIdentifier))
result.append(adapterIdentifierToGpuDescription(adapterIdentifier));
}
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 1196190b81..5c13bd9650 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -2697,10 +2697,16 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
return true;
}
if (localPos.y() < 0) {
- const int topResizeBarPos = -frameMargins().top();
- if (localPos.y() >= topResizeBarPos)
+ // We want to return HTCAPTION/true only over the outer sizing frame, not the entire title bar,
+ // otherwise the title bar buttons (close, etc.) become unresponsive on Windows 7 (QTBUG-78262).
+ // However, neither frameMargins() nor GetSystemMetrics(SM_CYSIZEFRAME), etc., give the correct
+ // sizing frame height in all Windows versions/scales. This empirical constant seems to work, though.
+ const int sizingHeight = 9;
+ const int topResizeBarPos = sizingHeight - frameMargins().top();
+ if (localPos.y() < topResizeBarPos) {
*result = HTCAPTION; // Extend caption over top resize bar, let's user move the window.
- return true;
+ return true;
+ }
}
}
if (fixedWidth && (localPos.x() < 0 || localPos.x() >= size.width())) {
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index 7de6369541..95ba961df1 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -12,8 +12,6 @@ LIBS += -lshlwapi -lwtsapi32
QMAKE_USE_PRIVATE += \
advapi32 \
d3d9/nolink \
- d3d11/nolink \
- dxgi/nolink \
ole32 \
shell32 \
user32 \