summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gui/egl/qegl.cpp32
-rw-r--r--src/gui/painting/qgraphicssystemex_symbian.cpp105
2 files changed, 123 insertions, 14 deletions
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
index 4db4a6a..02adef8 100644
--- a/src/gui/egl/qegl.cpp
+++ b/src/gui/egl/qegl.cpp
@@ -684,6 +684,37 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglPr
else
props = 0;
EGLSurface surf;
+#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
+ // is still holding all available GPU memory but is about to release it
+ // soon. For an example when exiting native video recorder and going back to
+ // Qt application behind it. Video stack tear down takes some time and Qt
+ // app might be too quick in reserving its EGL surface and thus running out
+ // of GPU memory right away. So if EGL surface creation fails due to bad
+ // 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 (devType == QInternal::Widget)
+ surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props);
+ else
+ surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props);
+ if (surf == EGL_NO_SURFACE) {
+ EGLint error = eglGetError();
+ if (error == EGL_BAD_ALLOC) {
+ if (tries) {
+ User::After(1000 * 250); // 250ms
+ continue;
+ }
+ }
+ qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", error);
+ } else {
+ break;
+ }
+ }
+#else
if (devType == QInternal::Widget)
surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props);
else
@@ -691,6 +722,7 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglPr
if (surf == EGL_NO_SURFACE) {
qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
}
+#endif
return surf;
}
#endif
diff --git a/src/gui/painting/qgraphicssystemex_symbian.cpp b/src/gui/painting/qgraphicssystemex_symbian.cpp
index 4469704..46731d8 100644
--- a/src/gui/painting/qgraphicssystemex_symbian.cpp
+++ b/src/gui/painting/qgraphicssystemex_symbian.cpp
@@ -46,31 +46,106 @@
#include <e32property.h>
+#ifdef Q_SYMBIAN_SUPPORTS_SURFACES
+#include "private/qegl_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
static bool bcm2727Initialized = false;
static bool bcm2727 = false;
+typedef EGLBoolean (*NOK_resource_profiling)(EGLDisplay, EGLint, EGLint*, EGLint, EGLint*);
+#define EGL_PROF_TOTAL_MEMORY_NOK 0x3070
+
+// Detect if Qt is running on BCM2727 chip.
+// BCM2727 is a special case on Symbian because
+// it has only 32MB GPU memory which exposes
+// significant limitations to hw accelerated UI.
bool QSymbianGraphicsSystemEx::hasBCM2727()
{
if (bcm2727Initialized)
return bcm2727;
- const TUid KIvePropertyCat = {0x2726beef};
- enum TIvePropertyChipType {
- EVCBCM2727B1 = 0x00000000,
- EVCBCM2763A0 = 0x04000100,
- EVCBCM2763B0 = 0x04000102,
- EVCBCM2763C0 = 0x04000103,
- EVCBCM2763C1 = 0x04000104,
- EVCBCMUnknown = 0x7fffffff
- };
-
- TInt chipType = EVCBCMUnknown;
- if (RProperty::Get(KIvePropertyCat, 0, chipType) == KErrNone) {
- if (chipType == EVCBCM2727B1)
+#ifdef Q_SYMBIAN_SUPPORTS_SURFACES
+ EGLDisplay display = QEgl::display();
+#if 1
+ // Hacky but fast ~0ms.
+ const char* vendor = eglQueryString(display, EGL_VENDOR);
+ if (strstr(vendor, "Broadcom")) {
+ const TUid KIvePropertyCat = {0x2726beef};
+ enum TIvePropertyChipType {
+ EVCBCM2727B1 = 0x00000000,
+ EVCBCM2763A0 = 0x04000100,
+ EVCBCM2763B0 = 0x04000102,
+ EVCBCM2763C0 = 0x04000103,
+ EVCBCM2763C1 = 0x04000104,
+ EVCBCMUnknown = 0x7fffffff
+ };
+
+ // Broadcom driver publishes KIvePropertyCat PS key on
+ // devices which are running on BCM2727 chip and post Anna Symbian.
+ TInt chipType = EVCBCMUnknown;
+ if (RProperty::Get(KIvePropertyCat, 0, chipType) == KErrNone) {
+ if (chipType == EVCBCM2727B1)
+ bcm2727 = true;
+ } else if (QSysInfo::symbianVersion() <= QSysInfo::SV_SF_3) {
+ // Device is running on Symbian Anna or older Symbian^3 in which
+ // KIvePropertyCat is not published. These ones are always 32MB devices.
+ bcm2727 = true;
+ } else {
+ // We have some other Broadcom chip on post Anna Symbian.
+ // Should have > 32MB GPU memory.
+ }
+ }
+#else
+ // Fool proof but takes 15-20ms and we don't want this delay on app startup...
+
+ // All devices with <= 32MB GPU memory should be
+ // dealed in similar manner to BCM2727
+ // So let's query max GPU memory amount.
+ NOK_resource_profiling eglQueryProfilingData = (NOK_resource_profiling)eglGetProcAddress("eglQueryProfilingDataNOK");
+ if (eglQueryProfilingData) {
+ EGLint dataCount;
+ eglQueryProfilingData(display,
+ EGL_PROF_QUERY_GLOBAL_BIT_NOK |
+ EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
+ NULL,
+ 0,
+ (EGLint*)&dataCount);
+
+ // Allocate room for the profiling data
+ EGLint* profData = (EGLint*)malloc(dataCount * sizeof(EGLint));
+ memset(profData,0,dataCount * sizeof(EGLint));
+
+ // Retrieve the profiling data
+ eglQueryProfilingData(display,
+ EGL_PROF_QUERY_GLOBAL_BIT_NOK |
+ EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
+ profData,
+ dataCount,
+ (EGLint*)&dataCount);
+
+ int totalMemory;
+ EGLint i = 0;
+ while (profData && i < dataCount) {
+ switch (profData[i++]) {
+ case EGL_PROF_TOTAL_MEMORY_NOK:
+ totalMemory = profData[i++];
+ break;
+ default:
+ i++;
+ }
+ }
+
+ // ok, hasBCM2727() naming is a bit misleading but Qt must
+ // behave the same on all chips like BCM2727 (<= 32MB GPU memory)
+ // and our code (and others) are already using this function.
+ if (totalMemory <= 33554432)
bcm2727 = true;
}
+#endif
+#endif // Q_SYMBIAN_SUPPORTS_SURFACES
bcm2727Initialized = true;
@@ -80,7 +155,9 @@ bool QSymbianGraphicsSystemEx::hasBCM2727()
void QSymbianGraphicsSystemEx::releaseCachedGpuResources()
{
// Do nothing here
- // This is implemented in graphics system specific plugin
+
+ // This virtual function should be implemented in graphics system specific
+ // plugin
}
void QSymbianGraphicsSystemEx::releaseAllGpuResources()