diff options
author | mread <qt-info@nokia.com> | 2012-01-09 15:04:18 (GMT) |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-01-13 15:32:52 (GMT) |
commit | 854e72538426b32f72acd6c6c76af04bc8b78994 (patch) | |
tree | 86edc947d0c4d9498d0b206688c74e8ee0c9c01c /src/gui | |
parent | 01ec128db5e2641a4fa0b8a8a9b6fc20ea1e02ba (diff) | |
download | Qt-854e72538426b32f72acd6c6c76af04bc8b78994.zip Qt-854e72538426b32f72acd6c6c76af04bc8b78994.tar.gz Qt-854e72538426b32f72acd6c6c76af04bc8b78994.tar.bz2 |
Recovering from draw failures after EGL surface creation failure
The Qt drawing system is not designed to handle failures in beginPaint
and endPaint. But the Symbian port is creating EGL contexts and surfaces
on demand in these functions. These can fail, eg in the defect reported
the app gets a visibile=true event for such a short period that it
fails to create the surface before it is invisible again. These failures
have to be coped with.
Brush image drawing is failing if the app is asked to draw
while in the background, because the EGL surface cannot be created.
After this, if the app comes to the foreground at the wrong time, the
failed drawing is shown on the screen as a flat colored area.
A failedToAlloc variable in the openvg paint engine was locking in this
failed drawing, so that it would never redraw. This is fixed by removing
all use of that variable.
Failed surface creation during a draw in response to a visibility
change event was also leaving the window backing store with bad content.
This is now cleared on a surface creation failure so that drawing
is retried when the next visibility change event arrives.
The retry mechanism for creating a surface on failure also
makes the problem circumstances more likely to occur and can block the
app unnecessarily. Now, instead of blocking for 1 second every time on
failed surface creation, it only blocks on the first failure in a
sequence thereby allowing other parts of the app to run freely while
it is in the background.
Task-number: ou1cimx1#951921
Change-Id: I1e27746957ff624b0d9a1cdc9b319d0a3477135d
Reviewed-by: Gareth Stockwell <gareth.stockwell@accenture.com>
Reviewed-by: Shane Kearns <ext-shane.2.kearns@nokia.com>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/egl/qegl.cpp | 19 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 3 | ||||
-rw-r--r-- | src/gui/kernel/qt_s60_p.h | 15 |
3 files changed, 24 insertions, 13 deletions
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 659757e..a84a6fb 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -48,6 +48,9 @@ #include "qegl_p.h" #include "qeglcontext_p.h" +#ifdef Q_OS_SYMBIAN +#include "private/qt_s60_p.h" +#endif QT_BEGIN_NAMESPACE @@ -398,6 +401,9 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties ctx = eglCreateContext(display(), cfg, EGL_NO_CONTEXT, contextProps.properties()); if (ctx == EGL_NO_CONTEXT) { qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString(); +#ifdef Q_OS_SYMBIAN + S60->eglSurfaceCreationError = true; +#endif return false; } } @@ -683,7 +689,7 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglPr props = properties->properties(); else props = 0; - EGLSurface surf; + EGLSurface surf = EGL_NO_SURFACE; #ifdef Q_OS_SYMBIAN // On Symbian there might be situations (especially on 32MB GPU devices) // where Qt is trying to create EGL surface while some other application @@ -695,8 +701,11 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglPr // alloc, let's try recreating it four times within ~1 second if needed. // This strategy gives some time for video recorder to tear down its stack // and a chance to Qt for creating a valid surface. - int tries = 4; - while(tries--) { + // If the surface is still failing however, we don't keep the app blocked. + static int tries = 4; + if (tries <= 0) + tries = 1; + while (tries-- > 0) { if (devType == QInternal::Widget) surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props); else @@ -704,13 +713,15 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglPr if (surf == EGL_NO_SURFACE) { EGLint error = eglGetError(); if (error == EGL_BAD_ALLOC) { - if (tries) { + if (tries > 0) { User::After(1000 * 250); // 250ms continue; } } qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", error); + S60->eglSurfaceCreationError = true; } else { + tries = 4; break; } } diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index abb3eae..511096d 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -246,10 +246,13 @@ void QS60Data::controlVisibilityChanged(CCoeControl *control, bool visible) if (backingStore.data()) { backingStore.registerWidget(widget); } else { + S60->eglSurfaceCreationError = false; backingStore.create(window); backingStore.registerWidget(widget); qt_widget_private(widget)->invalidateBuffer(widget->rect()); widget->repaint(); + if (S60->eglSurfaceCreationError) + backingStore.unregisterWidget(widget); } } else { QApplicationPrivate *d = QApplicationPrivate::instance(); diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 150bcf8..e9f63b8 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -168,6 +168,9 @@ public: int partialKeyboardOpen : 1; int handleStatusPaneResizeNotifications : 1; int screenFurnitureFullyCreated : 1; + int beginFullScreenCalled : 1; + int endFullScreenCalled : 1; + int eglSurfaceCreationError : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type QPointer<QWidget> splitViewLastWidget; @@ -208,9 +211,7 @@ public: static void controlVisibilityChanged(CCoeControl *control, bool visible); static TRect clientRect(); -#ifdef Q_OS_SYMBIAN TTrapHandler *s60InstalledTrapHandler; -#endif int screenWidthInPixelsForScreen[qt_symbian_max_screens]; int screenHeightInPixelsForScreen[qt_symbian_max_screens]; @@ -228,8 +229,6 @@ public: }; ScreenRotation screenRotation; - int beginFullScreenCalled : 1; - int endFullScreenCalled : 1; int editorFlags; }; @@ -386,12 +385,10 @@ inline QS60Data::QS60Data() partialKeyboardOpen(0), handleStatusPaneResizeNotifications(1), screenFurnitureFullyCreated(0), - s60ApplicationFactory(0) -#ifdef Q_OS_SYMBIAN - ,s60InstalledTrapHandler(0) -#endif - ,beginFullScreenCalled(0), + beginFullScreenCalled(0), endFullScreenCalled(0), + s60ApplicationFactory(0), + s60InstalledTrapHandler(0), editorFlags(0) { } |