diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/egl/qegl.cpp | 32 | ||||
-rw-r--r-- | src/gui/painting/qgraphicssystemex_symbian.cpp | 105 |
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() |