From 9afc8096fb5395216cd5813fb1859ff45b087d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Sun, 27 Oct 2013 17:46:41 +0100 Subject: Optimize macDisplayColorSpace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On 10.9, getting the display based on the rect is slow(er). Use a window -> color space cache instead of a display -> color space cache. Change-Id: If40a6d089019a54ceb724b8007adaffea89c96fb Task-number: QTBUG-34358 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qcocoawindowdelegate_mac.mm | 7 +++++ src/gui/kernel/qcocoawindowdelegate_mac_p.h | 1 + src/gui/kernel/qwidget_mac.mm | 4 +++ src/gui/painting/qpaintengine_mac.cpp | 44 ++++++++++++++++++----------- src/gui/painting/qpaintengine_mac_p.h | 3 +- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index 355f9bf..f81e788 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -51,6 +51,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE extern QWidgetData *qt_qwidget_data(QWidget *); // qwidget.cpp @@ -392,6 +393,12 @@ static void cleanupCocoaWindowDelegate() m_drawerHash->remove(drawer); } +- (void)windowDidChangeScreen:(NSNotification*)notification +{ + QWidget *qwidget = m_windowHash->value([notification object]); + QCoreGraphicsPaintEngine::clearColorSpace(qwidget); +} + - (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu { Q_UNUSED(menu); diff --git a/src/gui/kernel/qcocoawindowdelegate_mac_p.h b/src/gui/kernel/qcocoawindowdelegate_mac_p.h index 2598b77..c1fa2be 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac_p.h +++ b/src/gui/kernel/qcocoawindowdelegate_mac_p.h @@ -76,6 +76,7 @@ QT_FORWARD_DECLARE_CLASS(QWidgetData) - (void)windowDidResignMain:(NSNotification*)notification; - (void)windowDidBecomeKey:(NSNotification*)notification; - (void)windowDidResignKey:(NSNotification*)notification; +- (void)windowDidChangeScreen:(NSNotification*)notification; - (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu; - (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard; - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame; diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index efd2ff2..e99dabf 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2803,6 +2803,10 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) if (window) qt_mac_destructWindow(window); } +#ifdef QT_MAC_USE_COCOA + if (isWindow()) + QCoreGraphicsPaintEngine::clearColorSpace(this); +#endif } QT_TRY { d->setWinId(0); diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp index 5194ce9..47e51b4 100644 --- a/src/gui/painting/qpaintengine_mac.cpp +++ b/src/gui/painting/qpaintengine_mac.cpp @@ -289,7 +289,7 @@ static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0) } CGColorSpaceRef QCoreGraphicsPaintEngine::m_genericColorSpace = 0; -QHash QCoreGraphicsPaintEngine::m_displayColorSpaceHash; +QHash QCoreGraphicsPaintEngine::m_displayColorSpaceHash; // window -> color space bool QCoreGraphicsPaintEngine::m_postRoutineRegistered = false; CGColorSpaceRef QCoreGraphicsPaintEngine::macGenericColorSpace() @@ -316,45 +316,50 @@ CGColorSpaceRef QCoreGraphicsPaintEngine::macGenericColorSpace() #endif } -/* - Ideally, we should pass the widget in here, and use CGGetDisplaysWithRect() etc. - to support multiple displays correctly. -*/ CGColorSpaceRef QCoreGraphicsPaintEngine::macDisplayColorSpace(const QWidget *widget) { - CGColorSpaceRef colorSpace; + // The color space depends on which screen the widget's window is on. + // widget == 0 is a spacial case where we use the main display. + QWidget *window = widget ? widget->window() : 0; + + // Check for cached color space and return if found. + if (m_displayColorSpaceHash.contains(window)) + return m_displayColorSpaceHash.value(window); + // Find which display the window is on. CGDirectDisplayID displayID; - CMProfileRef displayProfile = 0; - if (widget == 0) { + if (window == 0) { displayID = CGMainDisplayID(); } else { - const QRect &qrect = widget->window()->geometry(); + const QRect &qrect = window->geometry(); CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height()); CGDisplayCount throwAway; CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway); if (dErr != kCGErrorSuccess) - return macDisplayColorSpace(0); // fall back on main display + displayID = CGMainDisplayID(); } - if ((colorSpace = m_displayColorSpaceHash.value(displayID))) - return colorSpace; + // Get the color space from the display profile. + CGColorSpaceRef colorSpace = 0; + CMProfileRef displayProfile = 0; CMError err = CMGetProfileByAVID((CMDisplayIDType)displayID, &displayProfile); if (err == noErr) { colorSpace = CGColorSpaceCreateWithPlatformColorSpace(displayProfile); - } else if (widget) { - return macDisplayColorSpace(0); // fall back on main display + CMCloseProfile(displayProfile); } + // Fallback: use generic DeviceRGB if (colorSpace == 0) colorSpace = CGColorSpaceCreateDeviceRGB(); - m_displayColorSpaceHash.insert(displayID, colorSpace); - CMCloseProfile(displayProfile); + // Install cleanup routines if (!m_postRoutineRegistered) { m_postRoutineRegistered = true; qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); } + + // Cache and return. + m_displayColorSpaceHash.insert(window, colorSpace); return colorSpace; } @@ -364,7 +369,7 @@ void QCoreGraphicsPaintEngine::cleanUpMacColorSpaces() CFRelease(m_genericColorSpace); m_genericColorSpace = 0; } - QHash::const_iterator it = m_displayColorSpaceHash.constBegin(); + QHash::const_iterator it = m_displayColorSpaceHash.constBegin(); while (it != m_displayColorSpaceHash.constEnd()) { if (it.value()) CFRelease(it.value()); @@ -1062,6 +1067,11 @@ void QCoreGraphicsPaintEngine::cleanup() { } +void QCoreGraphicsPaintEngine::clearColorSpace(QWidget* w) +{ + m_displayColorSpaceHash.remove(w); +} + CGContextRef QCoreGraphicsPaintEngine::handle() const { diff --git a/src/gui/painting/qpaintengine_mac_p.h b/src/gui/painting/qpaintengine_mac_p.h index 7a23472..04696af 100644 --- a/src/gui/painting/qpaintengine_mac_p.h +++ b/src/gui/painting/qpaintengine_mac_p.h @@ -110,6 +110,7 @@ public: static void initialize(); static void cleanup(); + static void clearColorSpace(QWidget* w); QPainter::RenderHints supportedRenderHints() const; @@ -134,7 +135,7 @@ protected: private: static bool m_postRoutineRegistered; static CGColorSpaceRef m_genericColorSpace; - static QHash m_displayColorSpaceHash; + static QHash m_displayColorSpaceHash; // window -> color space static void cleanUpMacColorSpaces(); Q_DISABLE_COPY(QCoreGraphicsPaintEngine) }; -- cgit v0.12