From 17555ab77041d5b68972eab608fe98799e0789e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Fri, 21 May 2010 13:24:54 +0200 Subject: Call eglTerminate() when the last QEglContext is destroyed to free mem. We never called eglTerminate() to free memory allocated by eglInitialize() since it was a fixed allocation that would be used for the lifetime of an application. The new behavior is to call eglTerminate() when the last EGL context in the app is destroyed. Task-number: QT-3383 Reviewed-by: Rhys Weatherley --- src/gui/egl/qegl.cpp | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index ee19216..c16aeb1 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -42,11 +42,40 @@ #include #include #include +#include #include #include "qegl_p.h" QT_BEGIN_NAMESPACE + +/* + QEglContextTracker is used to track the EGL contexts that we + create internally in Qt, so that we can call eglTerminate() to + free additional EGL resources when the last context is destroyed. +*/ + +class QEglContextTracker +{ +public: + static void ref() { contexts.ref(); } + static void deref() { + if (!contexts.deref()) { + eglTerminate(QEglContext::display()); + displayOpen = 0; + } + } + static void setDisplayOpened() { displayOpen = 1; } + static bool displayOpened() { return displayOpen; } + +private: + static QAtomicInt contexts; + static QAtomicInt displayOpen; +}; + +QAtomicInt QEglContextTracker::contexts = 0; +QAtomicInt QEglContextTracker::displayOpen = 0; + // Current GL and VG contexts. These are used to determine if // we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent(). // If a background thread modifies the value, the worst that will @@ -65,6 +94,7 @@ QEglContext::QEglContext() , ownsContext(true) , sharing(false) { + QEglContextTracker::ref(); } QEglContext::~QEglContext() @@ -75,6 +105,7 @@ QEglContext::~QEglContext() currentGLContext = 0; if (currentVGContext == this) currentVGContext = 0; + QEglContextTracker::deref(); } bool QEglContext::isValid() const @@ -361,11 +392,9 @@ QEglProperties QEglContext::configProperties(EGLConfig cfg) const EGLDisplay QEglContext::display() { - static bool openedDisplay = false; - - if (!openedDisplay) { + if (!QEglContextTracker::displayOpened()) { dpy = eglGetDisplay(nativeDisplay()); - openedDisplay = true; + QEglContextTracker::setDisplayOpened(); if (dpy == EGL_NO_DISPLAY) { qWarning("QEglContext::display(): Falling back to EGL_DEFAULT_DISPLAY"); dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); -- cgit v0.12 From 832b1a48050df80515353d9887976f364913ff8e Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 21 May 2010 14:10:53 +0200 Subject: Fixed an assert in QMenu The code was changed and changed the behaviour. This is basically a kind of revert. Reviewed-By: gabi Task-Number: QTBUG-10735 --- src/gui/widgets/qmenu.cpp | 12 +--------- tests/auto/qmenu/tst_qmenu.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 879ba2a..c05829a 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -992,19 +992,9 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e) return false; } -class ExceptionGuard -{ -public: - inline ExceptionGuard(bool *w = 0) : watched(w) { Q_ASSERT(!(*watched)); *watched = true; } - inline ~ExceptionGuard() { *watched = false; } - inline operator bool() { return *watched; } -private: - bool *watched; -}; - void QMenuPrivate::activateCausedStack(const QList > &causedStack, QAction *action, QAction::ActionEvent action_e, bool self) { - ExceptionGuard guard(&activationRecursionGuard); + QBoolBlocker guard(activationRecursionGuard); #ifdef QT3_SUPPORT const int actionId = q_func()->findIdForAction(action); #endif diff --git a/tests/auto/qmenu/tst_qmenu.cpp b/tests/auto/qmenu/tst_qmenu.cpp index 9dc18e0..63e7310 100644 --- a/tests/auto/qmenu/tst_qmenu.cpp +++ b/tests/auto/qmenu/tst_qmenu.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -104,6 +105,7 @@ private slots: void setFixedWidth(); void deleteActionInTriggered(); void pushButtonPopulateOnAboutToShow(); + void QTBUG_10735_crashWithDialog(); protected slots: void onActivated(QAction*); void onHighlighted(QAction*); @@ -932,5 +934,57 @@ void tst_QMenu::pushButtonPopulateOnAboutToShow() } +class MyMenu : public QMenu +{ + Q_OBJECT +public: + MyMenu() : m_currentIndex(0) + { + for (int i = 0; i < 2; ++i) + dialogActions[i] = addAction( QString("dialog %1").arg(i), dialogs + i, SLOT(exec())); + } + + + void activateAction(int index) + { + m_currentIndex = index; + popup(QPoint()); + QTest::qWaitForWindowShown(this); + setActiveAction(dialogActions[index]); + QTimer::singleShot(500, this, SLOT(checkVisibility())); + QTest::keyClick(this, Qt::Key_Enter); //activation + } + +public slots: + void activateLastAction() + { + activateAction(1); + } + + void checkVisibility() + { + QTRY_VERIFY(dialogs[m_currentIndex].isVisible()); + if (m_currentIndex == 1) { + QApplication::closeAllWindows(); //this is the end of the test + } + } + + +private: + QAction *dialogActions[2]; + QDialog dialogs[2]; + int m_currentIndex; +}; + +void tst_QMenu::QTBUG_10735_crashWithDialog() +{ + MyMenu menu; + + QTimer::singleShot(1000, &menu, SLOT(activateLastAction())); + menu.activateAction(0); + +} + + QTEST_MAIN(tst_QMenu) #include "tst_qmenu.moc" -- cgit v0.12