summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPauli Jarvinen <ext-pauli.p.jarvinen@nokia.com>2012-02-03 14:14:05 +0200
committerPasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com>2012-02-09 12:31:57 +0100
commita717c3853306f71c21d081a2ae861bc153c9700e (patch)
treec65f8f3a8f5446ce92f374735890af113e7ae49f
parent26ed6707f3249ac3410643fde32b0698aaf7dcfa (diff)
downloadqt4-tools-a717c3853306f71c21d081a2ae861bc153c9700e.tar.gz
Prevent crashing on Symbian in case EGL surface creation fails.
It is possible in environment with limited resources, that EGL surface creation fails. When this happens, the QPainter doesn't get properly activated, which in turn caused a crash later in the drawing code. Now, a check has been added into qapplication_s60.cpp to abort window drawing immediately, if surface creation has failed. The EGL surface is then tried to be recreated on the next time when the window becomes visible, which usually allows the application to recover. In most cases, the crash happened in the function qDrawBorderPixmap, which didn't check the validity of the QPaintEngine pointer before accessing it. This method is analogous with the public methods of the class QPainter where, on the other hand, availability of QPaintEngine was always checked. To be in line, and to prevent ptential crashes, a similar safety check and warning message have now been added to method qDrawBorderPixmap. Furthermore, a null-check was added to qwindowsurface_gl.cpp for the QGLContext pointer. The same pointer was already previously null-checked in the other branch of the same function, indicating that the null-check is probably necessary. Task-number: ou1cimx1#969923 Change-Id: I6d78be72b9c2308ef74b1119d8c8ec34ec015195 Reviewed-by: Jaakko Helanti <ext-jaakko.helanti@nokia.com> Reviewed-by: Pasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com> (cherry picked from commit f0d703557322d1b536e72bbba8209f6a615f6dc1)
-rw-r--r--src/gui/kernel/qapplication_s60.cpp11
-rw-r--r--src/gui/kernel/qt_s60_p.h1
-rw-r--r--src/gui/painting/qdrawutil.cpp5
-rw-r--r--src/opengl/qwindowsurface_gl.cpp5
4 files changed, 21 insertions, 1 deletions
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 67cb6bd4a2..9b191dc9ec 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -243,7 +243,9 @@ void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible)
QApplicationPrivate *d = QApplicationPrivate::instance();
d->emitAboutToUseGpuResources();
- if (backingStore.data()) {
+ // (Re)create the backing store and force repaint if we have no
+ // backing store already, or EGL surface cration failed on last attempt.
+ if (backingStore.data() && !S60->eglSurfaceCreationError) {
backingStore.registerWidget(widget);
} else {
S60->eglSurfaceCreationError = false;
@@ -1348,6 +1350,13 @@ void QSymbianControl::Draw(const TRect& aRect) const
void QSymbianControl::doDraw(const TRect& controlRect) const
{
+ // Bail out immediately, if we don't have a drawing surface. Surface is attempted to be recreated
+ // when this application becomes visible for the next time.
+ if (S60->eglSurfaceCreationError) {
+ qWarning() << "QSymbianControl::doDraw: EGL surface creation has failed, abort";
+ return;
+ }
+
// Set flag to avoid calling DrawNow in window surface
QWidget *window = qwidget->window();
Q_ASSERT(window);
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
index 4fd194625b..7363f4b3e1 100644
--- a/src/gui/kernel/qt_s60_p.h
+++ b/src/gui/kernel/qt_s60_p.h
@@ -388,6 +388,7 @@ inline QS60Data::QS60Data()
screenFurnitureFullyCreated(0),
beginFullScreenCalled(0),
endFullScreenCalled(0),
+ eglSurfaceCreationError(0),
s60ApplicationFactory(0),
s60InstalledTrapHandler(0),
editorFlags(0)
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index 1e98b05ba5..3d8e2ed775 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1105,6 +1105,11 @@ void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargin
const QPixmap &pixmap, const QRect &sourceRect,const QMargins &sourceMargins,
const QTileRules &rules, QDrawBorderPixmap::DrawingHints hints)
{
+ if (!painter->isActive()) {
+ qWarning("qDrawBorderPixmap: Painter not active");
+ return;
+ }
+
QRectFArray sourceData[2];
QRectFArray targetData[2];
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index d512946c01..67c8c2930c 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -693,6 +693,11 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
}
QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext);
+#ifdef Q_OS_SYMBIAN
+ if (!ctx)
+ return;
+#endif
+
if (widget != window()) {
if (initializeOffscreenTexture(window()->size()))
qWarning() << "QGLWindowSurface: Flushing to native child widget, may lead to significant performance loss";