summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorTrond Kjernåsen <trond.kjernasen@nokia.com>2010-05-14 13:42:43 (GMT)
committerTrond Kjernåsen <trond.kjernasen@nokia.com>2010-05-14 13:42:43 (GMT)
commit9a69656bd64016933124813ea5403e7e5d454719 (patch)
tree220e31e08e11bfa3a76627b53f303880e065f8e0 /src/opengl
parentb2e15281d56415e6ef8d4f1604d25b198d449f06 (diff)
downloadQt-9a69656bd64016933124813ea5403e7e5d454719.zip
Qt-9a69656bd64016933124813ea5403e7e5d454719.tar.gz
Qt-9a69656bd64016933124813ea5403e7e5d454719.tar.bz2
Added workarounds for two MBX/SGX specific GL ES bugs/problems.
The workaround flags are put into the platform independent section for now, since there might be a general need for these as we expand our GL and GL ES usage. The workaround_needsFullClearOnEveryFrame flag covers the case where you get a performance penalty on PowerVR hw if all rendering buffers are not cleared. The workaround_brokenFBOReadBack flag covers the case where copying pixels from a texture (e.g. via glCopyTexSubImage2d()) bound in an FBO doesn't work. Task-number: QTBUG-10670 Reviewed-by: Gunnar
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp18
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h2
-rw-r--r--src/opengl/qgl.cpp3
-rw-r--r--src/opengl/qgl.h1
-rw-r--r--src/opengl/qgl_egl.cpp20
-rw-r--r--src/opengl/qgl_p.h8
-rw-r--r--src/opengl/qglpaintdevice.cpp5
7 files changed, 39 insertions, 18 deletions
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 452d37d..cc42c63 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -57,21 +57,13 @@ QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyph
, ctx(context)
, m_width(0)
, m_height(0)
- , m_broken_fbo_readback(false)
{
// broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where
// copying between FBO's is broken if the texture is either GL_ALPHA or POT. The
// workaround is to use a system-memory copy of the glyph cache for this device.
// Switching to NPOT and GL_RGBA would both cost a lot more graphics memory and
// be slower, so that is not desireable.
-#if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL)
- if (QByteArray((char*) glGetString(GL_RENDERER)).contains("SGX")) {
- QGLContextPrivate *ctxd = context->d_func();
- m_broken_fbo_readback = QByteArray((char *) eglQueryString(ctxd->eglContext->display(), EGL_VERSION)).contains("1.3");
- }
-#endif
-
- if (!m_broken_fbo_readback)
+ if (!ctx->d_ptr->workaround_brokenFBOReadBack)
glGenFramebuffers(1, &m_fbo);
connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext*)),
@@ -83,7 +75,7 @@ QGLTextureGlyphCache::~QGLTextureGlyphCache()
if (ctx) {
QGLShareContextScope scope(ctx);
- if (!m_broken_fbo_readback)
+ if (!ctx->d_ptr->workaround_brokenFBOReadBack)
glDeleteFramebuffers(1, &m_fbo);
if (m_width || m_height)
@@ -96,7 +88,7 @@ void QGLTextureGlyphCache::createTextureData(int width, int height)
// create in QImageTextureGlyphCache baseclass is meant to be called
// only to create the initial image and does not preserve the content,
// so we don't call when this function is called from resize.
- if (m_broken_fbo_readback && image().isNull())
+ if (ctx->d_ptr->workaround_brokenFBOReadBack && image().isNull())
QImageTextureGlyphCache::createTextureData(width, height);
glGenTextures(1, &m_texture);
@@ -126,7 +118,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
GLuint oldTexture = m_texture;
createTextureData(width, height);
- if (m_broken_fbo_readback) {
+ if (ctx->d_ptr->workaround_brokenFBOReadBack) {
QImageTextureGlyphCache::resizeTextureData(width, height);
Q_ASSERT(image().depth() == 8);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits());
@@ -209,7 +201,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
{
- if (m_broken_fbo_readback) {
+ if (ctx->d_ptr->workaround_brokenFBOReadBack) {
QImageTextureGlyphCache::fillTexture(c, glyph);
glBindTexture(GL_TEXTURE_2D, m_texture);
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
index efb7435..6bcd655 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
@@ -115,8 +115,6 @@ private:
int m_height;
QGLShaderProgram *m_program;
-
- bool m_broken_fbo_readback;
};
QT_END_NAMESPACE
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 7c457de..922a96c 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -1612,6 +1612,9 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
current_fbo = 0;
default_fbo = 0;
active_engine = 0;
+ workaround_needsFullClearOnEveryFrame = false;
+ workaround_brokenFBOReadBack = false;
+ workaroundsCached = false;
for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
vertexAttributeArraysEnabledState[i] = false;
}
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
index 92a064f..f297009 100644
--- a/src/opengl/qgl.h
+++ b/src/opengl/qgl.h
@@ -431,6 +431,7 @@ private:
friend class QGLFramebufferObjectPrivate;
friend class QGLFBOGLPaintDevice;
friend class QGLPaintDevice;
+ friend class QGLWidgetGLPaintDevice;
friend class QX11GLPixmapData;
friend class QX11GLSharedContexts;
private:
diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp
index 0fbbbf9..44e8ae9 100644
--- a/src/opengl/qgl_egl.cpp
+++ b/src/opengl/qgl_egl.cpp
@@ -185,8 +185,26 @@ void QGLContext::makeCurrent()
return;
}
- if (d->eglContext->makeCurrent(d->eglSurfaceForDevice()))
+ if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) {
QGLContextPrivate::setCurrentContext(this);
+ if (!d->workaroundsCached) {
+ d->workaroundsCached = true;
+ const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
+ if (strstr(renderer, "SGX") || strstr(renderer, "MBX")) {
+ // PowerVR MBX/SGX chips needs to clear all buffers when starting to render
+ // a new frame, otherwise there will be a performance penalty to pay for
+ // each frame.
+ d->workaround_needsFullClearOnEveryFrame = true;
+
+ // Older PowerVR SGX drivers (like the one in the N900) have a
+ // bug which prevents glCopyTexSubImage2D() to work with a POT
+ // or GL_ALPHA texture bound to an FBO. The only way to
+ // identify that driver is to check the EGL version number for it.
+ if (strstr(eglQueryString(d->eglContext->display(), EGL_VERSION), "1.3"))
+ d->workaround_brokenFBOReadBack = true;
+ }
+ }
+ }
}
void QGLContext::doneCurrent()
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index f19e394..d92f963 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -345,7 +345,7 @@ public:
HDC hbitmap_hdc;
#endif
#ifndef QT_NO_EGL
- bool ownsEglContext;
+ uint ownsEglContext : 1;
QEglContext *eglContext;
EGLSurface eglSurface;
void destroyEglSurfaceForDevice();
@@ -382,6 +382,12 @@ public:
uint internal_context : 1;
uint version_flags_cached : 1;
uint extension_flags_cached : 1;
+
+ // workarounds for driver/hw bugs on different platforms
+ uint workaround_needsFullClearOnEveryFrame : 1;
+ uint workaround_brokenFBOReadBack : 1;
+ uint workaroundsCached : 1;
+
QPaintDevice *paintDevice;
QColor transpColor;
QGLContext *q_ptr;
diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
index e874e85..e1dcbfd 100644
--- a/src/opengl/qglpaintdevice.cpp
+++ b/src/opengl/qglpaintdevice.cpp
@@ -175,7 +175,10 @@ void QGLWidgetGLPaintDevice::beginPaint()
float alpha = c.alphaF();
glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
}
- glClear(GL_COLOR_BUFFER_BIT);
+ if (context()->d_func()->workaround_needsFullClearOnEveryFrame)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ else
+ glClear(GL_COLOR_BUFFER_BIT);
}
}