aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2014-03-10 10:53:49 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-13 13:39:54 +0100
commitb8afc009afcca84a3fd3d5617dfe96c729c531aa (patch)
tree10bdbfb63b3aee36da0344cd8f05184b06b47f37 /src
parentd6e932b3682c7f8cd610d7554a52c9856d7e67c1 (diff)
Consolidate context creation failure handling in Quick.
Add QQuickWidget::sceneGraphError() equivalent to QQuickWindow::sceneGraphError(), move message formatting code to QQuickWindowPrivate. Change-Id: I18cd4d7e0f6ee1011c29375218dc6a044b0d2cf2 Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/quick/items/qquickwindow.cpp31
-rw-r--r--src/quick/items/qquickwindow_p.h5
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp43
-rw-r--r--src/quick/scenegraph/qsgrenderloop_p.h3
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp13
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp29
-rw-r--r--src/quickwidgets/qquickwidget.cpp45
-rw-r--r--src/quickwidgets/qquickwidget.h1
-rw-r--r--src/quickwidgets/qquickwidget_p.h1
9 files changed, 122 insertions, 49 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index d7a6f071c6..6a56a5dc82 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -65,6 +65,7 @@
#include <QtGui/qstylehints.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qabstractanimation.h>
+#include <QtCore/QLibraryInfo>
#include <QtQml/qqmlincubator.h>
#include <QtQuick/private/qquickpixmapcache_p.h>
@@ -2303,6 +2304,36 @@ bool QQuickWindowPrivate::isRenderable() const
return ((q->isExposed() && q->isVisible())) && q->geometry().isValid();
}
+void QQuickWindowPrivate::contextCreationFailureMessage(const QSurfaceFormat &format,
+ QString *translatedMessage,
+ QString *untranslatedMessage,
+ bool isEs)
+{
+ const QString contextType = QLatin1String(isEs ? "EGL" : "OpenGL");
+ QString formatStr;
+ QDebug(&formatStr) << format;
+#if defined(Q_OS_WIN32)
+ const bool isDebug = QLibraryInfo::isDebugBuild();
+ const QString eglLibName = QLatin1String(isDebug ? "libEGLd.dll" : "libEGL.dll");
+ const QString glesLibName = QLatin1String(isDebug ? "libGLESv2d.dll" : "libGLESv2.dll");
+ //: %1 Context type (Open GL, EGL), ANGLE %2, %3 library names
+ const char msg[] = QT_TRANSLATE_NOOP("QQuickWindow",
+ "Failed to create %1 context for format %2."
+ "This is most likely caused by not having the necessary graphics drivers installed.\n\n"
+ "Install a driver providing OpenGL 2.0 or higher, or, if this is not possible, "
+ "make sure the ANGLE Open GL ES 2.0 emulation libraries (%3, %4 and d3dcompiler_*.dll) "
+ "are available in the application executable's directory or in a location listed in PATH.");
+ *translatedMessage = QQuickWindow::tr(msg).arg(contextType, formatStr, eglLibName, glesLibName);
+ *untranslatedMessage = QString::fromLatin1(msg).arg(contextType, formatStr, eglLibName, glesLibName);
+#else // Q_OS_WIN32
+ //: %1 Context type (Open GL, EGL), %2 format specification
+ const char msg[] = QT_TRANSLATE_NOOP("QQuickWindow",
+ "Failed to create %1 context for format %2");
+ *translatedMessage = QQuickWindow::tr(msg).arg(contextType, formatStr);
+ *untranslatedMessage = QString::fromLatin1(msg).arg(contextType, formatStr);
+#endif // !Q_OS_WIN32
+}
+
/*!
Propagates an event \a e to a QQuickItem \a item on the window.
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index e78f00c22f..421651b483 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -242,6 +242,11 @@ public:
static QObject *data_at(QQmlListProperty<QObject> *, int);
static void data_clear(QQmlListProperty<QObject> *);
+ static void contextCreationFailureMessage(const QSurfaceFormat &format,
+ QString *translatedMessage,
+ QString *untranslatedMessage,
+ bool isEs);
+
private:
static void cleanupNodesOnShutdown(QQuickItem *);
};
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 644a674749..6647ec83d0 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -46,6 +46,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QTime>
#include <QtCore/QScopedPointer>
+#include <QtCore/QLibraryInfo>
#include <QtCore/private/qabstractanimation_p.h>
#include <QtGui/QOpenGLContext>
@@ -59,6 +60,10 @@
#include <QtQuick/private/qsgcontext_p.h>
#include <private/qquickprofiler_p.h>
+#ifdef Q_OS_WIN
+# include <QtCore/qt_windows.h>
+#endif
+
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qsg_render_timing, QSG_RENDER_TIMING)
@@ -208,6 +213,32 @@ void QSGRenderLoop::setInstance(QSGRenderLoop *instance)
s_renderLoopInstance->reset(instance);
}
+void QSGRenderLoop::handleContextCreationFailure(QQuickWindow *window,
+ bool isEs)
+{
+ QString translatedMessage;
+ QString untranslatedMessage;
+ QQuickWindowPrivate::contextCreationFailureMessage(window->requestedFormat(),
+ &translatedMessage,
+ &untranslatedMessage,
+ isEs);
+ // If there is a slot connected to the error signal, emit it and leave it to
+ // the application to do something with the message. If nothing is connected,
+ // show a message on our own and terminate.
+ const bool signalEmitted =
+ QQuickWindowPrivate::get(window)->emitError(QQuickWindow::ContextNotAvailable,
+ translatedMessage);
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+ if (!signalEmitted && !QLibraryInfo::isDebugBuild() && !GetConsoleWindow()) {
+ MessageBox(0, (LPCTSTR) translatedMessage.utf16(),
+ (LPCTSTR)(QCoreApplication::applicationName().utf16()),
+ MB_OK | MB_ICONERROR);
+ }
+#endif // Q_OS_WIN && !Q_OS_WINCE && !Q_OS_WINRT
+ if (!signalEmitted)
+ qFatal("%s", qPrintable(untranslatedMessage));
+}
+
QSGGuiThreadRenderLoop::QSGGuiThreadRenderLoop()
: gl(0)
, eventPending(false)
@@ -283,18 +314,10 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
if (QSGContext::sharedOpenGLContext())
gl->setShareContext(QSGContext::sharedOpenGLContext());
if (!gl->create()) {
+ const bool isEs = gl->isES();
delete gl;
gl = 0;
- QString formatStr;
- QDebug(&formatStr) << window->requestedFormat();
- QString contextType = QLatin1String("OpenGL");
- const char *msg = QT_TRANSLATE_NOOP("QSGGuiThreadRenderLoop", "Failed to create %1 context for format %2");
- QString translatedMsg = tr(msg).arg(contextType).arg(formatStr);
- QString nonTranslatedMsg = QString(QLatin1String(msg)).arg(contextType).arg(formatStr);
- bool signalEmitted = QQuickWindowPrivate::get(window)->emitError(QQuickWindow::ContextNotAvailable,
- translatedMsg);
- if (!signalEmitted)
- qFatal("%s", qPrintable(nonTranslatedMsg));
+ handleContextCreationFailure(window, isEs);
} else {
cd->fireOpenGLContextCreated(gl);
current = gl->makeCurrent(window);
diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h
index 46edd77eda..2418af4157 100644
--- a/src/quick/scenegraph/qsgrenderloop_p.h
+++ b/src/quick/scenegraph/qsgrenderloop_p.h
@@ -88,6 +88,9 @@ public:
Q_SIGNALS:
void timeToIncubate();
+
+protected:
+ void handleContextCreationFailure(QQuickWindow *window, bool isEs);
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index f639841588..ba8c3a7fce 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -946,19 +946,10 @@ void QSGThreadedRenderLoop::handleExposure(Window *w)
w->thread->gl->setShareContext(QSGContext::sharedOpenGLContext());
w->thread->gl->setFormat(w->window->requestedFormat());
if (!w->thread->gl->create()) {
+ const bool isEs = w->thread->gl->isES();
delete w->thread->gl;
w->thread->gl = 0;
- QString formatStr;
- QDebug(&formatStr) << w->window->requestedFormat();
- QString contextType = QLatin1String("OpenGL");
- const char *msg = QT_TRANSLATE_NOOP("QSGThreadedRenderLoop",
- "Failed to create %1 context for format %2");
- QString translatedMsg = tr(msg).arg(contextType).arg(formatStr);
- QString nonTranslatedMsg = QString(QLatin1String(msg)).arg(contextType).arg(formatStr);
- bool signalEmitted = QQuickWindowPrivate::get(w->window)->emitError(QQuickWindow::ContextNotAvailable,
- translatedMsg);
- if (!signalEmitted)
- qFatal("%s", qPrintable(nonTranslatedMsg));
+ handleContextCreationFailure(w->window, isEs);
return;
}
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 31012c7589..913b737798 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -183,35 +183,10 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window)
m_gl->setShareContext(QSGContext::sharedOpenGLContext());
bool created = m_gl->create();
if (!created) {
- const bool isDebug = QLibraryInfo::isDebugBuild();
- QString eglLibName = QLatin1String(isDebug ? "libEGLd.dll" : "libEGL.dll");
- QString glesLibName = QLatin1String(isDebug ? "libGLESv2d.dll" : "libGLESv2.dll");
- QString contextType = QLatin1String("OpenGL");
- const char *msg = QT_TRANSLATE_NOOP(
- "QSGWindowsRenderLoop",
- "Failed to create %1 context. "
- "This is most likely caused by not having the necessary graphics drivers installed.\n\n"
- "Install a driver providing OpenGL 2.0 or higher, or, if this is not possible, "
- "make sure the Angle Open GL ES 2.0 emulation libraries (%2, %3 and d3dcompiler_*.dll) "
- "are available in the application executable's directory or in a location listed in PATH.");
- QString translatedMsg = tr(msg).arg(contextType).arg(eglLibName).arg(glesLibName);
- QString nonTranslatedMsg = QString(QLatin1String(msg)).arg(contextType).arg(eglLibName).arg(glesLibName);
- // If there is a slot connected to the error signal, emit it and leave it to
- // the application to do something with the message. If nothing is connected,
- // show a message on our own and terminate.
- bool signalEmitted = QQuickWindowPrivate::get(window)->emitError(QQuickWindow::ContextNotAvailable,
- translatedMsg);
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
- if (!signalEmitted && !isDebug && !GetConsoleWindow()) {
- MessageBox(0, (LPCTSTR) translatedMsg.utf16(),
- (LPCTSTR)(QCoreApplication::applicationName().utf16()),
- MB_OK | MB_ICONERROR);
- }
-#endif // !Q_OS_WINCE && !Q_OS_WINRT
+ const bool isEs = m_gl->isES();
delete m_gl;
m_gl = 0;
- if (!signalEmitted)
- qFatal("%s", qPrintable(nonTranslatedMsg));
+ handleContextCreationFailure(window, isEs);
return;
}
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index dbc7d6c21a..46db2ddfeb 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -56,6 +56,12 @@
#include <QtCore/qbasictimer.h>
#include <QtGui/QOffscreenSurface>
+#ifdef Q_OS_WIN
+# include <QtWidgets/QMessageBox>
+# include <QtCore/QLibraryInfo>
+# include <QtCore/qt_windows.h>
+#endif
+
QT_BEGIN_NAMESPACE
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
@@ -387,6 +393,21 @@ QQmlContext* QQuickWidget::rootContext() const
*/
/*!
+ \fn void QQuickWidget::sceneGraphError(QQuickWindow::SceneGraphError error, const QString &message)
+
+ This signal is emitted when an error occurred during scene graph initialization.
+
+ Applications should connect to this signal if they wish to handle errors,
+ like OpenGL context creation failures, in a custom way. When no slot is
+ connected to the signal, the behavior will be different: Quick will print
+ the message, or show a message box, and terminate the application.
+
+ This signal will be emitted from the gui thread.
+
+ \sa QQuickWindow::sceneGraphError()
+ */
+
+/*!
\property QQuickWidget::status
The component's current \l{QQuickWidget::Status} {status}.
*/
@@ -510,6 +531,27 @@ QSize QQuickWidgetPrivate::rootObjectSize() const
return rootObjectSize;
}
+void QQuickWidgetPrivate::handleContextCreationFailure(const QSurfaceFormat &format, bool isEs)
+{
+ Q_Q(QQuickWidget);
+
+ QString translatedMessage;
+ QString untranslatedMessage;
+ QQuickWindowPrivate::contextCreationFailureMessage(format, &translatedMessage, &untranslatedMessage, isEs);
+
+ static const QMetaMethod errorSignal = QMetaMethod::fromSignal(&QQuickWidget::sceneGraphError);
+ const bool signalConnected = q->isSignalConnected(errorSignal);
+ if (signalConnected)
+ emit q->sceneGraphError(QQuickWindow::ContextNotAvailable, translatedMessage);
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
+ if (!signalConnected && !QLibraryInfo::isDebugBuild() && !GetConsoleWindow())
+ QMessageBox::critical(q, QCoreApplication::applicationName(), translatedMessage);
+#endif // Q_OS_WIN && !Q_OS_WINCE && !Q_OS_WINRT
+ if (!signalConnected)
+ qFatal("%s", qPrintable(untranslatedMessage));
+}
+
void QQuickWidgetPrivate::createContext()
{
if (context)
@@ -521,9 +563,10 @@ void QQuickWidgetPrivate::createContext()
if (QSGContext::sharedOpenGLContext())
context->setShareContext(QSGContext::sharedOpenGLContext()); // ??? is this correct
if (!context->create()) {
- qWarning("QQuickWidget: failed to create OpenGL context");
+ const bool isEs = context->isES();
delete context;
context = 0;
+ handleContextCreationFailure(offscreenWindow->requestedFormat(), isEs);
return;
}
diff --git a/src/quickwidgets/qquickwidget.h b/src/quickwidgets/qquickwidget.h
index 614d5b82a6..2c021c85fb 100644
--- a/src/quickwidgets/qquickwidget.h
+++ b/src/quickwidgets/qquickwidget.h
@@ -95,6 +95,7 @@ public Q_SLOTS:
Q_SIGNALS:
void statusChanged(QQuickWidget::Status);
+ void sceneGraphError(QQuickWindow::SceneGraphError error, const QString &message);
private Q_SLOTS:
void continueExecute();
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index 2d2d6500b2..1ba06162f9 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -86,6 +86,7 @@ public:
void renderSceneGraph();
void createContext();
void destroyContext();
+ void handleContextCreationFailure(const QSurfaceFormat &format, bool isEs);
GLuint textureId() const Q_DECL_OVERRIDE;