summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan-Arve Sæther <jan-arve.saether@nokia.com>2010-01-13 15:04:16 (GMT)
committerJan-Arve Sæther <jan-arve.saether@nokia.com>2010-01-13 15:04:16 (GMT)
commit06828a0ecb3f1e6c4bd3a17ef4a5cd37dd4d7dda (patch)
treee9ca15ab75b61fe2b74734bc66ecdee4f0fe4033
parentae5812ee793999f78f725e10cb8d531cbd51782f (diff)
parent7bfc32ca6a462b498b9f349454113cd37f64e89f (diff)
downloadQt-06828a0ecb3f1e6c4bd3a17ef4a5cd37dd4d7dda.zip
Qt-06828a0ecb3f1e6c4bd3a17ef4a5cd37dd4d7dda.tar.gz
Qt-06828a0ecb3f1e6c4bd3a17ef4a5cd37dd4d7dda.tar.bz2
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.6
-rw-r--r--dist/changes-4.6.12
-rw-r--r--src/gui/effects/qgraphicseffect.cpp5
-rw-r--r--src/gui/effects/qgraphicseffect_p.h2
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp44
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h1
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp25
-rw-r--r--src/gui/image/qpixmapfilter.cpp2
-rw-r--r--src/gui/widgets/qabstractspinbox.cpp2
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp2
-rw-r--r--src/opengl/qgl.cpp85
-rw-r--r--src/opengl/qgl.h1
-rw-r--r--src/opengl/qgl_mac.mm110
-rw-r--r--src/opengl/qgl_p.h95
-rw-r--r--src/opengl/qgl_qws.cpp54
-rw-r--r--src/opengl/qgl_win.cpp100
-rw-r--r--src/opengl/qgl_wince.cpp36
-rw-r--r--src/opengl/qgl_x11.cpp138
-rw-r--r--src/opengl/qgl_x11egl.cpp194
-rw-r--r--src/opengl/qglframebufferobject.cpp12
-rw-r--r--src/opengl/qglpixelbuffer_mac.mm4
-rw-r--r--src/opengl/qglpixelbuffer_p.h1
-rw-r--r--src/opengl/qglpixelbuffer_win.cpp14
-rw-r--r--src/opengl/qpaintengine_opengl.cpp46
-rw-r--r--src/opengl/qwindowsurface_gl.cpp7
-rw-r--r--tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp46
25 files changed, 579 insertions, 449 deletions
diff --git a/dist/changes-4.6.1 b/dist/changes-4.6.1
index 0971f40..e31fc7c 100644
--- a/dist/changes-4.6.1
+++ b/dist/changes-4.6.1
@@ -198,6 +198,8 @@ QtwebKit
- Fixed wrapping of QObjects with recurring identity (webkit.org/b/31681)
- Fixed compilation with ICC
- Fixed assertion when dragging SVG images (webkit.org/b/32511)
+ - Fixed crash with ACID3 test on Symbian
+ - Fixed security issue XSL stylesheets and security origins.
QtScript
--------
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp
index 90145fe..ad23df3 100644
--- a/src/gui/effects/qgraphicseffect.cpp
+++ b/src/gui/effects/qgraphicseffect.cpp
@@ -374,6 +374,11 @@ QGraphicsEffectSourcePrivate::~QGraphicsEffectSourcePrivate()
invalidateCache();
}
+void QGraphicsEffectSourcePrivate::setCachedOffset(const QPoint &offset)
+{
+ m_cachedOffset = offset;
+}
+
void QGraphicsEffectSourcePrivate::invalidateCache(InvalidateReason reason) const
{
if (m_cachedMode != QGraphicsEffect::PadToEffectiveBoundingRect
diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h
index 91ad74a..e34dbf9 100644
--- a/src/gui/effects/qgraphicseffect_p.h
+++ b/src/gui/effects/qgraphicseffect_p.h
@@ -129,8 +129,10 @@ public:
QGraphicsEffect::PixmapPadMode mode = QGraphicsEffect::PadToTransparentBorder) const = 0;
virtual void effectBoundingRectChanged() = 0;
+ void setCachedOffset(const QPoint &offset);
void invalidateCache(InvalidateReason reason = SourceChanged) const;
Qt::CoordinateSystem currentCachedSystem() const { return m_cachedSystem; }
+ QGraphicsEffect::PixmapPadMode currentCachedMode() const { return m_cachedMode; }
friend class QGraphicsScenePrivate;
friend class QGraphicsItem;
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 168a9a3..cae9660 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -10715,27 +10715,18 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
}
}
-QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
- QGraphicsEffect::PixmapPadMode mode) const
+QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
{
- const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
- if (!info && deviceCoordinates) {
- // Device coordinates without info not yet supported.
- qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
- return QPixmap();
- }
- if (!item->d_ptr->scene)
- return QPixmap();
- QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
-
- const QRectF sourceRect = boundingRect(system);
QRectF effectRectF;
- bool unpadded = false;
+ if (unpadded)
+ *unpadded = false;
+
if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) {
if (info) {
effectRectF = item->graphicsEffect()->boundingRectFor(boundingRect(Qt::DeviceCoordinates));
- unpadded = (effectRectF.size() == sourceRect.size());
+ if (unpadded)
+ *unpadded = (effectRectF.size() == sourceRect.size());
if (info && system == Qt::LogicalCoordinates)
effectRectF = info->painter->worldTransform().inverted().mapRect(effectRectF);
} else {
@@ -10747,10 +10738,29 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
effectRectF = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5);
} else {
effectRectF = sourceRect;
- unpadded = true;
+ if (unpadded)
+ *unpadded = true;
+ }
+
+ return effectRectF.toAlignedRect();
+}
+
+QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
+ QGraphicsEffect::PixmapPadMode mode) const
+{
+ const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
+ if (!info && deviceCoordinates) {
+ // Device coordinates without info not yet supported.
+ qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
+ return QPixmap();
}
+ if (!item->d_ptr->scene)
+ return QPixmap();
+ QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
- QRect effectRect = effectRectF.toAlignedRect();
+ bool unpadded;
+ const QRectF sourceRect = boundingRect(system);
+ QRect effectRect = paddedEffectRect(system, mode, sourceRect, &unpadded);
if (offset)
*offset = effectRect.topLeft();
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index c8d2061..2d34b80 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -609,6 +609,7 @@ public:
QPixmap pixmap(Qt::CoordinateSystem system,
QPoint *offset,
QGraphicsEffect::PixmapPadMode mode) const;
+ QRect paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = 0) const;
QGraphicsItem *item;
QGraphicsItemPaintInfo *info;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 5c6a8ae..cea723c 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -4686,8 +4686,31 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
&& sourced->lastEffectTransform != painter->worldTransform())
{
+ bool unclipped = false;
+ if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
+ && painter->worldTransform().type() <= QTransform::TxTranslate)
+ {
+ QRectF itemRect = item->boundingRect();
+ if (!item->d_ptr->children.isEmpty())
+ itemRect |= item->childrenBoundingRect();
+
+ QRectF oldSourceRect = sourced->lastEffectTransform.mapRect(itemRect);
+ QRectF newSourceRect = painter->worldTransform().mapRect(itemRect);
+
+ QRect oldEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), oldSourceRect);
+ QRect newEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), newSourceRect);
+
+ QRect deviceRect(0, 0, painter->device()->width(), painter->device()->height());
+ if (deviceRect.contains(oldEffectRect) && deviceRect.contains(newEffectRect)) {
+ sourced->setCachedOffset(newEffectRect.topLeft());
+ unclipped = true;
+ }
+ }
+
sourced->lastEffectTransform = painter->worldTransform();
- sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
+
+ if (!unclipped)
+ sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
}
item->d_ptr->graphicsEffect->draw(painter);
diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp
index 30fb7a3..37a6a18 100644
--- a/src/gui/image/qpixmapfilter.cpp
+++ b/src/gui/image/qpixmapfilter.cpp
@@ -953,7 +953,7 @@ static void grayscale(const QImage &image, QImage &dest, const QRect& rect = QRe
srcRect = dest.rect();
destRect = dest.rect();
}
- if (image != dest) {
+ if (&image != &dest) {
destRect.moveTo(QPoint(0, 0));
}
diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp
index 13e67e9..4a6235c 100644
--- a/src/gui/widgets/qabstractspinbox.cpp
+++ b/src/gui/widgets/qabstractspinbox.cpp
@@ -66,7 +66,7 @@
#endif
#if defined(Q_OS_SYMBIAN)
-#include <W32STD.H>
+#include <w32std.h>
#include <private/qt_s60_p.h>
#endif
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 2a33255..caa679b 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -1628,9 +1628,9 @@ void QGL2PaintEngineEx::ensureActive()
d->needsSync = false;
d->shaderManager->setDirty();
d->ctx->d_func()->syncGlState();
- setState(state());
for (int i = 0; i < 3; ++i)
d->vertexAttribPointers[i] = (GLfloat*)-1; // Assume the pointers are clobbered
+ setState(state());
}
}
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index a262ded..09ecfd1 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -124,9 +124,6 @@ public:
};
Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
-QGLExtensions::Extensions QGLExtensions::glExtensions = 0;
-bool QGLExtensions::nvidiaFboNeedsFinish = false;
-
Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
QGLSignalProxy *QGLSignalProxy::instance()
{
@@ -154,11 +151,9 @@ public:
// falling back to the GL 1 engine..
static bool mac_x1600_check_done = false;
if (!mac_x1600_check_done) {
- QGLWidget *tmp = 0;
- if (!QGLContext::currentContext()) {
- tmp = new QGLWidget();
- tmp->makeCurrent();
- }
+ QGLTemporaryContext *tmp = 0;
+ if (!QGLContext::currentContext())
+ tmp = new QGLTemporaryContext();
if (strstr((char *) glGetString(GL_RENDERER), "X1600"))
engineType = QPaintEngine::OpenGL;
if (tmp)
@@ -178,7 +173,7 @@ public:
// from an old GL 1.1 server to a GL 2.x client. In that case we can't
// use GL 2.0.
if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
- && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader)
+ && (QGLExtensions::glExtensions() & QGLExtensions::FragmentShader)
&& qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
engineType = QPaintEngine::OpenGL2;
else
@@ -1250,7 +1245,7 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
static bool cachedDefault = false;
static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None;
QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
- QGLWidget *dummy = 0;
+ QGLTemporaryContext *tmpContext = 0;
if (currentCtx && currentCtx->d_func()->version_flags_cached)
return currentCtx->d_func()->version_flags;
@@ -1261,8 +1256,7 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
} else {
if (!hasOpenGL())
return defaultVersionFlags;
- dummy = new QGLWidget;
- dummy->makeCurrent(); // glGetString() needs a current context
+ tmpContext = new QGLTemporaryContext;
cachedDefault = true;
}
}
@@ -1273,9 +1267,9 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
currentCtx->d_func()->version_flags_cached = true;
currentCtx->d_func()->version_flags = versionFlags;
}
- if (dummy) {
+ if (tmpContext) {
defaultVersionFlags = versionFlags;
- delete dummy;
+ delete tmpContext;
}
return versionFlags;
@@ -1493,6 +1487,8 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
max_texture_size = -1;
version_flags_cached = false;
version_flags = QGLFormat::OpenGL_Version_None;
+ extension_flags_cached = false;
+ extension_flags = 0;
current_fbo = 0;
default_fbo = 0;
active_engine = 0;
@@ -2147,7 +2143,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
int tx_h = qt_next_power_of_two(image.height());
QImage img = image;
- if (!(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures)
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures)
&& !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
&& (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
{
@@ -2169,7 +2165,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
bool genMipmap = false;
#endif
if (glFormat.directRendering()
- && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap)
+ && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap)
&& target == GL_TEXTURE_2D
&& (options & QGLContext::MipmapBindOption))
{
@@ -2197,7 +2193,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G
bool premul = options & QGLContext::PremultipliedAlphaBindOption;
GLenum externalFormat;
GLuint pixel_type;
- if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) {
+ if (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) {
externalFormat = GL_BGRA;
pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
} else {
@@ -4868,9 +4864,13 @@ QGLWidget::QGLWidget(QGLContext *context, QWidget *parent,
#endif // QT3_SUPPORT
-void QGLExtensions::init_extensions()
+/*
+ Returns the GL extensions for the current context.
+*/
+QGLExtensions::Extensions QGLExtensions::currentContextExtensions()
{
QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
+ Extensions glExtensions;
if (extensions.match("GL_ARB_texture_rectangle"))
glExtensions |= TextureRectangle;
@@ -4931,6 +4931,46 @@ void QGLExtensions::init_extensions()
if (extensions.match("GL_EXT_bgra"))
glExtensions |= BGRATextureFormat;
+
+ return glExtensions;
+}
+
+/*
+ Returns the GL extensions for the current QGLContext. If there is no
+ current QGLContext, a default context will be created and the extensions
+ for that context will be returned instead.
+*/
+QGLExtensions::Extensions QGLExtensions::glExtensions()
+{
+ QGLTemporaryContext *tmpContext = 0;
+ static bool cachedDefault = false;
+ static Extensions defaultExtensions = 0;
+ QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
+
+ if (currentCtx && currentCtx->d_func()->extension_flags_cached)
+ return currentCtx->d_func()->extension_flags;
+
+ if (!currentCtx) {
+ if (cachedDefault) {
+ return defaultExtensions;
+ } else {
+ tmpContext = new QGLTemporaryContext;
+ cachedDefault = true;
+ }
+ }
+
+ Extensions extensionFlags = currentContextExtensions();
+ if (currentCtx) {
+ currentCtx->d_func()->extension_flags_cached = true;
+ currentCtx->d_func()->extension_flags = extensionFlags;
+ } else {
+ defaultExtensions = extensionFlags;
+ }
+
+ if (tmpContext)
+ delete tmpContext;
+
+ return extensionFlags;
}
/*
@@ -4942,7 +4982,6 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi
glDevice.setWidget(q);
- QGLExtensions::init();
glcx = 0;
autoSwap = true;
@@ -5191,7 +5230,7 @@ QSize QGLTexture::bindCompressedTexture
}
#if !defined(QT_OPENGL_ES)
if (!glCompressedTexImage2D) {
- if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) {
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::TextureCompression)) {
qWarning("QGLContext::bindTexture(): The GL implementation does "
"not support texture compression extensions.");
return QSize();
@@ -5230,7 +5269,7 @@ QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len)
return QSize();
// Bail out if the necessary extension is not present.
- if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) {
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::DDSTextureCompression)) {
qWarning("QGLContext::bindTexture(): DDS texture compression is not supported.");
return QSize();
}
@@ -5340,13 +5379,13 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
// Bail out if the necessary extension is not present.
if (textureFormat == GL_ETC1_RGB8_OES) {
- if (!(QGLExtensions::glExtensions &
+ if (!(QGLExtensions::glExtensions() &
QGLExtensions::ETC1TextureCompression)) {
qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported.");
return QSize();
}
} else {
- if (!(QGLExtensions::glExtensions &
+ if (!(QGLExtensions::glExtensions() &
QGLExtensions::PVRTCTextureCompression)) {
qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported.");
return QSize();
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
index 374c6d6..1a04ff9 100644
--- a/src/opengl/qgl.h
+++ b/src/opengl/qgl.h
@@ -401,6 +401,7 @@ private:
friend class QGLContextGroup;
friend class QGLSharedResourceGuard;
friend class QGLPixmapBlurFilter;
+ friend class QGLExtensions;
friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags();
#ifdef Q_WS_MAC
public:
diff --git a/src/opengl/qgl_mac.mm b/src/opengl/qgl_mac.mm
index 6ed07e5..c01575b 100644
--- a/src/opengl/qgl_mac.mm
+++ b/src/opengl/qgl_mac.mm
@@ -116,6 +116,68 @@ extern void qt_mac_dispose_rgn(RgnHandle); //qregion_mac.cpp
extern QRegion qt_mac_convert_mac_region(RgnHandle); //qregion_mac.cpp
extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); //qglobal.cpp
+/*
+ QGLTemporaryContext implementation
+*/
+
+class QGLTemporaryContextPrivate
+{
+public:
+#ifndef QT_MAC_USE_COCOA
+ AGLContext ctx;
+#else
+ NSOpenGLContext *ctx;
+#endif
+};
+
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->ctx = 0;
+#ifndef QT_MAC_USE_COCOA
+ GLint attribs[] = {AGL_RGBA, AGL_NONE};
+ AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs);
+ if (!fmt) {
+ qDebug("QGLTemporaryContext: Couldn't find any RGB visuals");
+ return;
+ }
+ d->ctx = aglCreateContext(fmt, 0);
+ if (!d->ctx)
+ qDebug("QGLTemporaryContext: Unable to create context");
+ else
+ aglSetCurrentContext(d->ctx);
+ aglDestroyPixelFormat(fmt);
+#else
+ QMacCocoaAutoReleasePool pool;
+ NSOpenGLPixelFormatAttribute attribs[] = { 0 };
+ NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+ if (!fmt) {
+ qWarning("QGLTemporaryContext: Cannot find any visuals");
+ return;
+ }
+
+ d->ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0];
+ if (!d->ctx)
+ qWarning("QGLTemporaryContext: Cannot create context");
+ else
+ [d->ctx makeCurrentContext];
+ [fmt release];
+#endif
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ if (d->ctx) {
+#ifndef QT_MAC_USE_COCOA
+ aglSetCurrentContext(0);
+ aglDestroyContext(d->ctx);
+#else
+ [NSOpenGLContext clearCurrentContext];
+ [d->ctx release];
+#endif
+ }
+}
+
bool QGLFormat::hasOpenGL()
{
return true;
@@ -918,54 +980,6 @@ void QGLWidgetPrivate::updatePaintDevice()
q->update();
}
-
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
-#ifndef QT_MAC_USE_COCOA
- GLint attribs[] = { AGL_RGBA, AGL_NONE };
- AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs);
- if (!fmt) {
- qDebug("QGLExtensions: Couldn't find any RGB visuals");
- return;
- }
- AGLContext ctx = aglCreateContext(fmt, 0);
- if (!ctx) {
- qDebug("QGLExtensions: Unable to create context");
- } else {
- aglSetCurrentContext(ctx);
- init_extensions();
- aglSetCurrentContext(0);
- aglDestroyContext(ctx);
- }
- aglDestroyPixelFormat(fmt);
-#else
- QMacCocoaAutoReleasePool pool;
- NSOpenGLPixelFormatAttribute attribs[] = { 0 };
- NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
- if (!fmt) {
- qWarning("QGLExtensions: Cannot find any visuals");
- return;
- }
-
- NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0];
- if (!ctx) {
- qWarning("QGLExtensions: Cannot create context");
- } else {
- [ctx makeCurrentContext];
- init_extensions();
- [NSOpenGLContext clearCurrentContext];
- [ctx release];
- }
- [fmt release];
-#endif
-}
-
#endif
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 30f5591..0104f07 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -261,6 +261,60 @@ private:
// "ctx" is destroyed. Returns null if nothing is sharing with ctx.
Q_OPENGL_EXPORT const QGLContext *qt_gl_transfer_context(const QGLContext *);
+// GL extension definitions
+class QGLExtensions {
+public:
+ enum Extension {
+ TextureRectangle = 0x00000001,
+ SampleBuffers = 0x00000002,
+ GenerateMipmap = 0x00000004,
+ TextureCompression = 0x00000008,
+ FragmentProgram = 0x00000010,
+ MirroredRepeat = 0x00000020,
+ FramebufferObject = 0x00000040,
+ StencilTwoSide = 0x00000080,
+ StencilWrap = 0x00000100,
+ PackedDepthStencil = 0x00000200,
+ NVFloatBuffer = 0x00000400,
+ PixelBufferObject = 0x00000800,
+ FramebufferBlit = 0x00001000,
+ NPOTTextures = 0x00002000,
+ BGRATextureFormat = 0x00004000,
+ DDSTextureCompression = 0x00008000,
+ ETC1TextureCompression = 0x00010000,
+ PVRTCTextureCompression = 0x00020000,
+ FragmentShader = 0x00040000
+ };
+ Q_DECLARE_FLAGS(Extensions, Extension)
+
+ static Extensions glExtensions();
+
+private:
+ static Extensions currentContextExtensions();
+};
+
+/*
+ QGLTemporaryContext - the main objective of this class is to have a way of
+ creating a GL context and making it current, without going via QGLWidget
+ and friends. At certain points during GL initialization we need a current
+ context in order decide what GL features are available, and to resolve GL
+ extensions. Having a light-weight way of creating such a context saves
+ initial application startup time, and it doesn't wind up creating recursive
+ conflicts.
+ The class currently uses a private d pointer to hide the platform specific
+ types. This could possibly been done inline with #ifdef'ery, but it causes
+ major headaches on e.g. X11 due to namespace pollution.
+*/
+class QGLTemporaryContextPrivate;
+class QGLTemporaryContext {
+public:
+ QGLTemporaryContext(bool directRendering = true, QWidget *parent = 0);
+ ~QGLTemporaryContext();
+
+private:
+ QScopedPointer<QGLTemporaryContextPrivate> d;
+};
+
class QGLTexture;
// This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
@@ -333,10 +387,12 @@ public:
uint crWin : 1;
uint internal_context : 1;
uint version_flags_cached : 1;
+ uint extension_flags_cached : 1;
QPaintDevice *paintDevice;
QColor transpColor;
QGLContext *q_ptr;
QGLFormat::OpenGLVersionFlags version_flags;
+ QGLExtensions::Extensions extension_flags;
QGLContextGroup *group;
GLint max_texture_size;
@@ -375,41 +431,8 @@ Q_SIGNALS:
void aboutToDestroyContext(const QGLContext *context);
};
-// GL extension definitions
-class QGLExtensions {
-public:
- enum Extension {
- TextureRectangle = 0x00000001,
- SampleBuffers = 0x00000002,
- GenerateMipmap = 0x00000004,
- TextureCompression = 0x00000008,
- FragmentProgram = 0x00000010,
- MirroredRepeat = 0x00000020,
- FramebufferObject = 0x00000040,
- StencilTwoSide = 0x00000080,
- StencilWrap = 0x00000100,
- PackedDepthStencil = 0x00000200,
- NVFloatBuffer = 0x00000400,
- PixelBufferObject = 0x00000800,
- FramebufferBlit = 0x00001000,
- NPOTTextures = 0x00002000,
- BGRATextureFormat = 0x00004000,
- DDSTextureCompression = 0x00008000,
- ETC1TextureCompression = 0x00010000,
- PVRTCTextureCompression = 0x00020000,
- FragmentShader = 0x00040000
- };
- Q_DECLARE_FLAGS(Extensions, Extension)
-
- static Extensions glExtensions;
- static bool nvidiaFboNeedsFinish;
- static void init(); // sys dependent
- static void init_extensions(); // general: called by init()
-};
-
Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
-
// Temporarily make a context current if not already current or
// shared with the current contex. The previous context is made
// current when the object goes out of scope.
@@ -533,7 +556,7 @@ bool qt_gl_preferGL2Engine();
inline GLenum qt_gl_preferredTextureFormat()
{
- return (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
+ return (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
? GL_BGRA : GL_RGBA;
}
@@ -542,7 +565,7 @@ inline GLenum qt_gl_preferredTextureTarget()
#if defined(QT_OPENGL_ES_2)
return GL_TEXTURE_2D;
#else
- return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+ return (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
&& !qt_gl_preferGL2Engine()
? GL_TEXTURE_RECTANGLE_NV
: GL_TEXTURE_2D;
@@ -614,7 +637,7 @@ private:
};
-// This class can be used to match GL extensions with doing any mallocs. The
+// This class can be used to match GL extensions without doing any mallocs. The
// class assumes that the GL extension string ends with a space character,
// which it should do on all conformant platforms. Create the object and pass
// in a pointer to the extension string, then call match() on each extension
diff --git a/src/opengl/qgl_qws.cpp b/src/opengl/qgl_qws.cpp
index f69ad7b..d4adc8b 100644
--- a/src/opengl/qgl_qws.cpp
+++ b/src/opengl/qgl_qws.cpp
@@ -83,6 +83,28 @@ static QGLScreen *glScreenForDevice(QPaintDevice *device)
return 0;
}
+/*
+ QGLTemporaryContext implementation
+*/
+
+class QGLTemporaryContextPrivate
+{
+public:
+ QGLWidget *widget;
+};
+
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->widget = new QGLWidget;
+ d->widget->makeCurrent();
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ delete d->widget;
+}
+
/*****************************************************************************
QOpenGL debug facilities
*****************************************************************************/
@@ -311,36 +333,4 @@ void QGLWidget::setColormap(const QGLColormap &)
{
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
- // We need a context current to initialize the extensions,
- // but getting a valid EGLNativeWindowType this early can be
- // problematic under QWS. So use a pbuffer instead.
- //
- // Unfortunately OpenGL/ES 2.0 systems don't normally
- // support pbuffers, so we have no choice but to try
- // our luck with a window on those systems.
-#if defined(QT_OPENGL_ES_2)
- QGLWidget tmpWidget;
- tmpWidget.makeCurrent();
-
- init_extensions();
-
- tmpWidget.doneCurrent();
-#else
- QGLPixelBuffer pbuffer(16, 16);
- pbuffer.makeCurrent();
-
- init_extensions();
-
- pbuffer.doneCurrent();
-#endif
-}
-
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_win.cpp b/src/opengl/qgl_win.cpp
index 443fbf2..ed4814f 100644
--- a/src/opengl/qgl_win.cpp
+++ b/src/opengl/qgl_win.cpp
@@ -551,7 +551,7 @@ QGLFormat pfiToQGLFormat(HDC hdc, int pfi)
QVarLengthArray<int> iAttributes(40);
QVarLengthArray<int> iValues(40);
int i = 0;
- bool has_sample_buffers = QGLExtensions::glExtensions & QGLExtensions::SampleBuffers;
+ bool has_sample_buffers = QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers;
iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; // 0
iAttributes[i++] = WGL_DEPTH_BITS_ARB; // 1
@@ -628,52 +628,14 @@ QGLFormat pfiToQGLFormat(HDC hdc, int pfi)
/*
- Creates a temporary GL context and makes it current
- - cleans up when the object is destructed.
+ QGLTemporaryContext implementation
*/
Q_GUI_EXPORT const QString qt_getRegisteredWndClass();
-class QGLTempContext
+class QGLTemporaryContextPrivate
{
public:
- QGLTempContext(bool directRendering, QWidget *parent = 0)
- {
- QString windowClassName = qt_getRegisteredWndClass();
- if (parent && !parent->internalWinId())
- parent = parent->nativeParentWidget();
-
- dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(),
- 0, 0, 0, 0, 1, 1,
- parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
-
- dmy_pdc = GetDC(dmy_id);
- PIXELFORMATDESCRIPTOR dmy_pfd;
- memset(&dmy_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
- dmy_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
- dmy_pfd.nVersion = 1;
- dmy_pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
- dmy_pfd.iPixelType = PFD_TYPE_RGBA;
- if (!directRendering)
- dmy_pfd.dwFlags |= PFD_GENERIC_FORMAT;
-
- int dmy_pf = ChoosePixelFormat(dmy_pdc, &dmy_pfd);
- SetPixelFormat(dmy_pdc, dmy_pf, &dmy_pfd);
- dmy_rc = wglCreateContext(dmy_pdc);
- old_dc = wglGetCurrentDC();
- old_context = wglGetCurrentContext();
- wglMakeCurrent(dmy_pdc, dmy_rc);
- }
-
- ~QGLTempContext() {
- wglMakeCurrent(dmy_pdc, 0);
- wglDeleteContext(dmy_rc);
- ReleaseDC(dmy_id, dmy_pdc);
- DestroyWindow(dmy_id);
- if (old_dc && old_context)
- wglMakeCurrent(old_dc, old_context);
- }
-
HDC dmy_pdc;
HGLRC dmy_rc;
HDC old_dc;
@@ -681,6 +643,45 @@ public:
WId dmy_id;
};
+QGLTemporaryContext::QGLTemporaryContext(bool directRendering, QWidget *parent)
+ : d(new QGLTemporaryContextPrivate)
+{
+ QString windowClassName = qt_getRegisteredWndClass();
+ if (parent && !parent->internalWinId())
+ parent = parent->nativeParentWidget();
+
+ d->dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(),
+ 0, 0, 0, 0, 1, 1,
+ parent ? parent->winId() : 0, 0, qWinAppInst(), 0);
+
+ d->dmy_pdc = GetDC(d->dmy_id);
+ PIXELFORMATDESCRIPTOR dmy_pfd;
+ memset(&dmy_pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
+ dmy_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ dmy_pfd.nVersion = 1;
+ dmy_pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
+ dmy_pfd.iPixelType = PFD_TYPE_RGBA;
+ if (!directRendering)
+ dmy_pfd.dwFlags |= PFD_GENERIC_FORMAT;
+
+ int dmy_pf = ChoosePixelFormat(d->dmy_pdc, &dmy_pfd);
+ SetPixelFormat(d->dmy_pdc, dmy_pf, &dmy_pfd);
+ d->dmy_rc = wglCreateContext(d->dmy_pdc);
+ d->old_dc = wglGetCurrentDC();
+ d->old_context = wglGetCurrentContext();
+ wglMakeCurrent(d->dmy_pdc, d->dmy_rc);
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ wglMakeCurrent(d->dmy_pdc, 0);
+ wglDeleteContext(d->dmy_rc);
+ ReleaseDC(d->dmy_id, d->dmy_pdc);
+ DestroyWindow(d->dmy_id);
+ if (d->old_dc && d->old_context)
+ wglMakeCurrent(d->old_dc, d->old_context);
+}
+
bool QGLContext::chooseContext(const QGLContext* shareContext)
{
Q_D(QGLContext);
@@ -721,10 +722,10 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
myDc = GetDC(d->win);
}
- // NB! the QGLTempContext object is needed for the
+ // NB! the QGLTemporaryContext object is needed for the
// wglGetProcAddress() calls to succeed and are absolutely
// necessary - don't remove!
- QGLTempContext tmp_ctx(d->glFormat.directRendering(), widget);
+ QGLTemporaryContext tmp_ctx(d->glFormat.directRendering(), widget);
if (!myDc) {
qWarning("QGLContext::chooseContext(): Paint device cannot be null");
@@ -965,7 +966,7 @@ int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
iAttributes[i++] = 1;
}
int si = 0;
- bool trySampleBuffers = QGLExtensions::glExtensions & QGLExtensions::SampleBuffers;
+ bool trySampleBuffers = QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers;
if (trySampleBuffers && d->glFormat.sampleBuffers()) {
iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB;
iAttributes[i++] = TRUE;
@@ -1471,15 +1472,4 @@ void QGLWidget::setColormap(const QGLColormap & c)
}
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
- QGLTempContext temp_ctx(QGLFormat::defaultFormat().directRendering());
- init_extensions();
-}
-
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_wince.cpp b/src/opengl/qgl_wince.cpp
index 460f10d..00a125a 100644
--- a/src/opengl/qgl_wince.cpp
+++ b/src/opengl/qgl_wince.cpp
@@ -95,8 +95,27 @@ public:
#include <qcolor.h>
+/*
+ QGLTemporaryContext implementation
+*/
+class QGLTemporaryContextPrivate
+{
+public:
+ QGLWidget *widget;
+};
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->widget = new QGLWidget;
+ d->widget->makeCurrent();
+}
+
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ delete d->widget;
+}
/*****************************************************************************
QGLFormat Win32/WGL-specific code
@@ -627,21 +646,4 @@ void QGLWidget::setColormap(const QGLColormap & c)
}
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
- // We need a context current to initialize the extensions.
- QGLWidget tmpWidget;
- tmpWidget.makeCurrent();
-
- init_extensions();
-
- tmpWidget.doneCurrent();
-}
-
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index e883ddc..f4cc7c7 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -549,7 +549,7 @@ void *QGLContext::chooseVisual()
bool triedDouble = false;
bool triedSample = false;
if (fmt.sampleBuffers())
- fmt.setSampleBuffers(QGLExtensions::glExtensions & QGLExtensions::SampleBuffers);
+ fmt.setSampleBuffers(QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers);
while(!fail && !(vis = tryVisual(fmt, bufDepths[i]))) {
if (!fmt.rgba() && bufDepths[i] > 1) {
i++;
@@ -1132,71 +1132,70 @@ void *QGLContext::getProcAddress(const QString &proc) const
return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(proc.toLatin1().data()));
}
-//
-// This class is used to create a temporary, minimal GL context, which is used
-// to retrive GL version and extension info. It's significantly faster to
-// construct than a QGLWidget, and it doesn't have the recursive creation
-// problem that QGLWidget would have. E.g. creating a temporary QGLWidget to
-// retrieve GL info as part of the QGLWidget initialization.
-//
-class QGLTempContext
-{
+/*
+ QGLTemporaryContext implementation
+*/
+
+class QGLTemporaryContextPrivate {
public:
- QGLTempContext(int screen = 0) :
- initialized(false),
- old_drawable(0),
- old_context(0)
- {
- int attribs[] = {GLX_RGBA, XNone};
- XVisualInfo *vi = glXChooseVisual(X11->display, screen, attribs);
- if (!vi) {
- qWarning("QGLTempContext: No GL capable X visuals available.");
- return;
- }
+ bool initialized;
+ Window drawable;
+ GLXContext context;
+ GLXDrawable oldDrawable;
+ GLXContext oldContext;
+};
- int useGL;
- glXGetConfig(X11->display, vi, GLX_USE_GL, &useGL);
- if (!useGL) {
- XFree(vi);
- return;
- }
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->initialized = false;
+ d->oldDrawable = 0;
+ d->oldContext = 0;
+ int screen = 0;
+
+ int attribs[] = {GLX_RGBA, XNone};
+ XVisualInfo *vi = glXChooseVisual(X11->display, screen, attribs);
+ if (!vi) {
+ qWarning("QGLTempContext: No GL capable X visuals available.");
+ return;
+ }
- old_drawable = glXGetCurrentDrawable();
- old_context = glXGetCurrentContext();
-
- XSetWindowAttributes a;
- a.colormap = qt_gl_choose_cmap(X11->display, vi);
- drawable = XCreateWindow(X11->display, RootWindow(X11->display, screen),
- 0, 0, 1, 1, 0,
- vi->depth, InputOutput, vi->visual,
- CWColormap, &a);
- context = glXCreateContext(X11->display, vi, 0, True);
- if (context && glXMakeCurrent(X11->display, drawable, context)) {
- initialized = true;
- } else {
- qWarning("QGLTempContext: Unable to create GL context.");
- XDestroyWindow(X11->display, drawable);
- }
+ int useGL;
+ glXGetConfig(X11->display, vi, GLX_USE_GL, &useGL);
+ if (!useGL) {
XFree(vi);
+ return;
}
- ~QGLTempContext() {
- if (initialized) {
- glXMakeCurrent(X11->display, 0, 0);
- glXDestroyContext(X11->display, context);
- XDestroyWindow(X11->display, drawable);
- }
- if (old_drawable && old_context)
- glXMakeCurrent(X11->display, old_drawable, old_context);
+ d->oldDrawable = glXGetCurrentDrawable();
+ d->oldContext = glXGetCurrentContext();
+
+ XSetWindowAttributes a;
+ a.colormap = qt_gl_choose_cmap(X11->display, vi);
+ d->drawable = XCreateWindow(X11->display, RootWindow(X11->display, screen),
+ 0, 0, 1, 1, 0,
+ vi->depth, InputOutput, vi->visual,
+ CWColormap, &a);
+ d->context = glXCreateContext(X11->display, vi, 0, True);
+ if (d->context && glXMakeCurrent(X11->display, d->drawable, d->context)) {
+ d->initialized = true;
+ } else {
+ qWarning("QGLTempContext: Unable to create GL context.");
+ XDestroyWindow(X11->display, d->drawable);
}
+ XFree(vi);
+}
-private:
- bool initialized;
- Window drawable;
- GLXContext context;
- GLXDrawable old_drawable;
- GLXContext old_context;
-};
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ if (d->initialized) {
+ glXMakeCurrent(X11->display, 0, 0);
+ glXDestroyContext(X11->display, d->context);
+ XDestroyWindow(X11->display, d->drawable);
+ }
+ if (d->oldDrawable && d->oldContext)
+ glXMakeCurrent(X11->display, d->oldDrawable, d->oldContext);
+}
/*****************************************************************************
QGLOverlayWidget (Internal overlay class for X11)
@@ -1632,27 +1631,6 @@ void QGLWidget::setColormap(const QGLColormap & c)
delete [] cmw;
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
- QGLTempContext context;
- init_extensions();
-
- // nvidia 9x.xx unix drivers contain a bug which requires us to call glFinish before releasing an fbo
- // to avoid painting artifacts
- const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
- const int pos = versionString.indexOf("NVIDIA");
- if (pos >= 0) {
- const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat();
- nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0;
- }
-}
-
// Solaris defines glXBindTexImageEXT as part of the GL library
#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
typedef void (*qt_glXBindTexImageEXT)(Display*, GLXDrawable, int, const int*);
@@ -1668,7 +1646,7 @@ static bool qt_resolveTextureFromPixmap(QPaintDevice *paintDevice)
resolvedTextureFromPixmap = true;
// Check to see if we have NPOT texture support
- if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) &&
+ if ( !(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures) &&
!(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0))
{
return false; // Can't use TFP without NPOT
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
index 85daf95..572834b 100644
--- a/src/opengl/qgl_x11egl.cpp
+++ b/src/opengl/qgl_x11egl.cpp
@@ -55,112 +55,115 @@ QT_BEGIN_NAMESPACE
bool qt_egl_setup_x11_visual(XVisualInfo &vi, EGLDisplay display, EGLConfig config,
const QX11Info &x11Info, bool useArgbVisual);
-//
-// QGLTempContext is a class for creating a temporary GL context
-// (which is needed during QGLWidget initialization to retrieve GL
-// extension info). Faster to construct than a full QGLWidget.
-//
-class QGLTempContext
+
+/*
+ QGLTemporaryContext implementation
+*/
+
+class QGLTemporaryContextPrivate
{
public:
- QGLTempContext(int screen = 0) :
- initialized(false),
- window(0),
- context(0),
- surface(0)
- {
- display = eglGetDisplay(EGLNativeDisplayType(X11->display));
+ bool initialized;
+ Window window;
+ EGLContext context;
+ EGLSurface surface;
+ EGLDisplay display;
+};
- if (!eglInitialize(display, NULL, NULL)) {
- qWarning("QGLTempContext: Unable to initialize EGL display.");
- return;
- }
+QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
+ : d(new QGLTemporaryContextPrivate)
+{
+ d->initialized = false;
+ d->window = 0;
+ d->context = 0;
+ d->surface = 0;
+ int screen = 0;
+
+ d->display = eglGetDisplay(EGLNativeDisplayType(X11->display));
- EGLConfig config;
- int numConfigs = 0;
- EGLint attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ if (!eglInitialize(d->display, NULL, NULL)) {
+ qWarning("QGLTemporaryContext: Unable to initialize EGL display.");
+ return;
+ }
+
+ EGLConfig config;
+ int numConfigs = 0;
+ EGLint attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#ifdef QT_OPENGL_ES_2
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#endif
- EGL_NONE
- };
+ EGL_NONE
+ };
- eglChooseConfig(display, attribs, &config, 1, &numConfigs);
- if (!numConfigs) {
- qWarning("QGLTempContext: No EGL configurations available.");
- return;
- }
+ eglChooseConfig(d->display, attribs, &config, 1, &numConfigs);
+ if (!numConfigs) {
+ qWarning("QGLTemporaryContext: No EGL configurations available.");
+ return;
+ }
- XVisualInfo visualInfo;
- XVisualInfo *vi;
- int numVisuals;
- EGLint id = 0;
-
- eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &id);
- if (id == 0) {
- // EGL_NATIVE_VISUAL_ID is optional and might not be supported
- // on some implementations - we'll have to do it the hard way
- QX11Info xinfo;
- qt_egl_setup_x11_visual(visualInfo, display, config, xinfo, false);
- } else {
- visualInfo.visualid = id;
- }
- vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals);
- if (!vi || numVisuals < 1) {
- qWarning("QGLTempContext: Unable to get X11 visual info id.");
- return;
- }
+ XVisualInfo visualInfo;
+ XVisualInfo *vi;
+ int numVisuals;
+ EGLint id = 0;
+
+ eglGetConfigAttrib(d->display, config, EGL_NATIVE_VISUAL_ID, &id);
+ if (id == 0) {
+ // EGL_NATIVE_VISUAL_ID is optional and might not be supported
+ // on some implementations - we'll have to do it the hard way
+ QX11Info xinfo;
+ qt_egl_setup_x11_visual(visualInfo, d->display, config, xinfo, false);
+ } else {
+ visualInfo.visualid = id;
+ }
+ vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals);
+ if (!vi || numVisuals < 1) {
+ qWarning("QGLTemporaryContext: Unable to get X11 visual info id.");
+ return;
+ }
- window = XCreateWindow(X11->display, RootWindow(X11->display, screen),
- 0, 0, 1, 1, 0,
- vi->depth, InputOutput, vi->visual,
- 0, 0);
+ d->window = XCreateWindow(X11->display, RootWindow(X11->display, screen),
+ 0, 0, 1, 1, 0,
+ vi->depth, InputOutput, vi->visual,
+ 0, 0);
- surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType) window, NULL);
+ d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL);
- if (surface == EGL_NO_SURFACE) {
- qWarning("QGLTempContext: Error creating EGL surface.");
- XFree(vi);
- XDestroyWindow(X11->display, window);
- return;
- }
+ if (d->surface == EGL_NO_SURFACE) {
+ qWarning("QGLTemporaryContext: Error creating EGL surface.");
+ XFree(vi);
+ XDestroyWindow(X11->display, d->window);
+ return;
+ }
- EGLint contextAttribs[] = {
+ EGLint contextAttribs[] = {
#ifdef QT_OPENGL_ES_2
- EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_CONTEXT_CLIENT_VERSION, 2,
#endif
- EGL_NONE
- };
- context = eglCreateContext(display, config, 0, contextAttribs);
- if (context != EGL_NO_CONTEXT
- && eglMakeCurrent(display, surface, surface, context))
- {
- initialized = true;
- } else {
- qWarning("QGLTempContext: Error creating EGL context.");
- eglDestroySurface(display, surface);
- XDestroyWindow(X11->display, window);
- }
- XFree(vi);
+ EGL_NONE
+ };
+ d->context = eglCreateContext(d->display, config, 0, contextAttribs);
+ if (d->context != EGL_NO_CONTEXT
+ && eglMakeCurrent(d->display, d->surface, d->surface, d->context))
+ {
+ d->initialized = true;
+ } else {
+ qWarning("QGLTemporaryContext: Error creating EGL context.");
+ eglDestroySurface(d->display, d->surface);
+ XDestroyWindow(X11->display, d->window);
}
+ XFree(vi);
+}
- ~QGLTempContext() {
- if (initialized) {
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroyContext(display, context);
- eglDestroySurface(display, surface);
- XDestroyWindow(X11->display, window);
- }
+QGLTemporaryContext::~QGLTemporaryContext()
+{
+ if (d->initialized) {
+ eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(d->display, d->context);
+ eglDestroySurface(d->display, d->surface);
+ XDestroyWindow(X11->display, d->window);
}
-
-private:
- bool initialized;
- Window window;
- EGLContext context;
- EGLSurface surface;
- EGLDisplay display;
-};
+}
bool QGLFormat::hasOpenGLOverlays()
{
@@ -547,19 +550,6 @@ void QGLWidget::setColormap(const QGLColormap &)
{
}
-void QGLExtensions::init()
-{
- static bool init_done = false;
-
- if (init_done)
- return;
- init_done = true;
-
- // We need a context current to initialize the extensions.
- QGLTempContext context;
- init_extensions();
-}
-
// Re-creates the EGL surface if the window ID has changed or if force is true
void QGLWidgetPrivate::recreateEglSurface(bool force)
{
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index ed21923..ce80796 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -396,7 +396,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
fbo_guard.setContext(ctx);
- bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
+ bool ext_detected = (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject);
if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx)))
return;
@@ -466,7 +466,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
}
if (attachment == QGLFramebufferObject::CombinedDepthStencil
- && (QGLExtensions::glExtensions & QGLExtensions::PackedDepthStencil)) {
+ && (QGLExtensions::glExtensions() & QGLExtensions::PackedDepthStencil)) {
// depth and stencil buffer needs another extension
glGenRenderbuffers(1, &depth_stencil_buffer);
Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
@@ -1028,8 +1028,7 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const
*/
bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
{
- QGLExtensions::init();
- return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
+ return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject);
}
/*!
@@ -1188,8 +1187,7 @@ bool QGLFramebufferObject::isBound() const
*/
bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
{
- QGLExtensions::init();
- return (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit);
+ return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit);
}
/*!
@@ -1229,7 +1227,7 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q
GLbitfield buffers,
GLenum filter)
{
- if (!(QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit))
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit))
return;
const QGLContext *ctx = QGLContext::currentContext();
diff --git a/src/opengl/qglpixelbuffer_mac.mm b/src/opengl/qglpixelbuffer_mac.mm
index 49c1845..6731dd8 100644
--- a/src/opengl/qglpixelbuffer_mac.mm
+++ b/src/opengl/qglpixelbuffer_mac.mm
@@ -92,7 +92,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge
GLenum target = GL_TEXTURE_2D;
- if ((QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+ if ((QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
&& (size.width() != nearest_gl_texture_size(size.width())
|| size.height() != nearest_gl_texture_size(size.height())))
{
@@ -223,7 +223,7 @@ bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidge
GLenum target = GL_TEXTURE_2D;
- if ((QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+ if ((QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
&& (size.width() != nearest_gl_texture_size(size.width())
|| size.height() != nearest_gl_texture_size(size.height())))
{
diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h
index f40b7c5..c85dc5a 100644
--- a/src/opengl/qglpixelbuffer_p.h
+++ b/src/opengl/qglpixelbuffer_p.h
@@ -154,7 +154,6 @@ class QGLPixelBufferPrivate {
public:
QGLPixelBufferPrivate(QGLPixelBuffer *q) : q_ptr(q), invalid(true), qctx(0), pbuf(0), ctx(0)
{
- QGLExtensions::init();
#ifdef Q_WS_WIN
dc = 0;
#elif defined(Q_WS_MACX)
diff --git a/src/opengl/qglpixelbuffer_win.cpp b/src/opengl/qglpixelbuffer_win.cpp
index a986ccf..8d0d105 100644
--- a/src/opengl/qglpixelbuffer_win.cpp
+++ b/src/opengl/qglpixelbuffer_win.cpp
@@ -221,7 +221,7 @@ static void qt_format_to_attrib_list(bool has_render_texture, const QGLFormat &f
}
if ((f.redBufferSize() > 8 || f.greenBufferSize() > 8
|| f.blueBufferSize() > 8 || f.alphaBufferSize() > 8)
- && (QGLExtensions::glExtensions & QGLExtensions::NVFloatBuffer))
+ && (QGLExtensions::glExtensions() & QGLExtensions::NVFloatBuffer))
{
attribs[i++] = WGL_FLOAT_COMPONENTS_NV;
attribs[i++] = TRUE;
@@ -368,11 +368,9 @@ void QGLPixelBuffer::releaseFromDynamicTexture()
bool QGLPixelBuffer::hasOpenGLPbuffers()
{
bool ret = false;
- QGLWidget *dmy = 0;
- if (!QGLContext::currentContext()) {
- dmy = new QGLWidget;
- dmy->makeCurrent();
- }
+ QGLTemporaryContext *tmpContext = 0;
+ if (!QGLContext::currentContext())
+ tmpContext = new QGLTemporaryContext;
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB =
(PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB) {
@@ -382,8 +380,8 @@ bool QGLPixelBuffer::hasOpenGLPbuffers()
ret = true;
}
}
- if (dmy)
- delete dmy;
+ if (tmpContext)
+ delete tmpContext;
return ret;
}
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
index c823187..57918d0 100644
--- a/src/opengl/qpaintengine_opengl.cpp
+++ b/src/opengl/qpaintengine_opengl.cpp
@@ -108,6 +108,10 @@ static bool DEBUG_TEMP_FLAG;
#define DEBUG_ONCE_STR(str) DEBUG_ONCE qDebug() << (str);
#endif
+#ifdef Q_WS_X11
+static bool qt_nvidiaFboNeedsFinish = false;
+#endif
+
static inline void qt_glColor4ubv(unsigned char *col)
{
glColor4f(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, col[3]/255.0f);
@@ -423,7 +427,7 @@ inline void QGLOffscreen::release()
#ifdef Q_WS_X11
// workaround for bug in nvidia driver versions 9x.xx
- if (QGLExtensions::nvidiaFboNeedsFinish)
+ if (qt_nvidiaFboNeedsFinish)
glFinish();
#endif
@@ -477,7 +481,7 @@ inline QGLContext *QGLOffscreen::context() const
bool QGLOffscreen::isSupported()
{
- return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject); // for fbo
+ return (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject); // for fbo
}
struct QDrawQueueItem
@@ -1266,7 +1270,7 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev)
for (int j = 0; j < 4; ++j)
d->mv_matrix[i][j] = (i == j ? qreal(1) : qreal(0));
- bool has_frag_program = (QGLExtensions::glExtensions & QGLExtensions::FragmentProgram)
+ bool has_frag_program = (QGLExtensions::glExtensions() & QGLExtensions::FragmentProgram)
&& (pdev->devType() != QInternal::Pixmap);
QGLContext *ctx = const_cast<QGLContext *>(d->device->context());
@@ -1279,11 +1283,27 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev)
has_frag_program = qt_resolve_frag_program_extensions(ctx) && qt_resolve_version_1_3_functions(ctx);
d->use_stencil_method = d->device->format().stencil()
- && (QGLExtensions::glExtensions & QGLExtensions::StencilWrap);
+ && (QGLExtensions::glExtensions() & QGLExtensions::StencilWrap);
if (d->device->format().directRendering()
- && (d->use_stencil_method && QGLExtensions::glExtensions & QGLExtensions::StencilTwoSide))
+ && (d->use_stencil_method && QGLExtensions::glExtensions() & QGLExtensions::StencilTwoSide))
d->has_stencil_face_ext = qt_resolve_stencil_face_extension(ctx);
+#ifdef Q_WS_X11
+ static bool nvidia_workaround_needs_init = true;
+ if (nvidia_workaround_needs_init) {
+ // nvidia 9x.xx unix drivers contain a bug which requires us to
+ // call glFinish before releasing an fbo to avoid painting
+ // artifacts
+ const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
+ const int pos = versionString.indexOf("NVIDIA");
+ if (pos >= 0) {
+ const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat();
+ qt_nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0;
+ }
+ nvidia_workaround_needs_init = false;
+ }
+#endif
+
#ifndef QT_OPENGL_ES
if (!ctx->d_ptr->internal_context) {
glGetDoublev(GL_PROJECTION_MATRIX, &d->projection_matrix[0][0]);
@@ -1333,10 +1353,10 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev)
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
- if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)
+ if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)
glDisable(GL_MULTISAMPLE);
glDisable(GL_TEXTURE_2D);
- if (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+ if (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
glDisable(GL_TEXTURE_RECTANGLE_NV);
glDisable(GL_STENCIL_TEST);
glDisable(GL_CULL_FACE);
@@ -1534,7 +1554,7 @@ void QOpenGLPaintEnginePrivate::updateGradient(const QBrush &brush, const QRectF
#ifdef QT_OPENGL_ES
Q_UNUSED(brush);
#else
- bool has_mirrored_repeat = QGLExtensions::glExtensions & QGLExtensions::MirroredRepeat;
+ bool has_mirrored_repeat = QGLExtensions::glExtensions() & QGLExtensions::MirroredRepeat;
Qt::BrushStyle style = brush.style();
QTransform m = brush.transform();
@@ -2098,7 +2118,7 @@ static inline bool needsEmulation(Qt::BrushStyle style)
{
return !(style == Qt::SolidPattern
|| (style == Qt::LinearGradientPattern
- && (QGLExtensions::glExtensions & QGLExtensions::MirroredRepeat)));
+ && (QGLExtensions::glExtensions() & QGLExtensions::MirroredRepeat)));
}
void QOpenGLPaintEnginePrivate::updateUseEmulation()
@@ -2420,12 +2440,12 @@ void QOpenGLPaintEngine::updateRenderHints(QPainter::RenderHints hints)
d->high_quality_antialiasing = true;
} else {
d->high_quality_antialiasing = false;
- if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)
+ if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)
glEnable(GL_MULTISAMPLE);
}
} else {
d->high_quality_antialiasing = false;
- if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)
+ if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)
glDisable(GL_MULTISAMPLE);
}
@@ -2435,14 +2455,14 @@ void QOpenGLPaintEngine::updateRenderHints(QPainter::RenderHints hints)
if (!d->offscreen.isValid()) {
DEBUG_ONCE_STR("Unable to initialize offscreen, disabling high quality antialiasing");
d->high_quality_antialiasing = false;
- if (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers)
+ if (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers)
glEnable(GL_MULTISAMPLE);
}
}
d->has_antialiasing = d->high_quality_antialiasing
|| ((hints & QPainter::Antialiasing)
- && (QGLExtensions::glExtensions & QGLExtensions::SampleBuffers));
+ && (QGLExtensions::glExtensions() & QGLExtensions::SampleBuffers));
}
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index 8ee4361..7a565e6 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -295,7 +295,6 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window)
: QWindowSurface(window), d_ptr(new QGLWindowSurfacePrivate)
{
Q_ASSERT(window->isTopLevel());
- QGLExtensions::init();
d_ptr->pb = 0;
d_ptr->fbo = 0;
d_ptr->ctx = 0;
@@ -520,7 +519,7 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
glDisable(GL_SCISSOR_TEST);
- if (d_ptr->fbo && (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)) {
+ if (d_ptr->fbo && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit)) {
const int h = d_ptr->fbo->height();
const int sx0 = br.left();
@@ -698,7 +697,7 @@ void QGLWindowSurface::updateGeometry() {
}
if (d_ptr->destructive_swap_buffers
- && (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject)
+ && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject)
&& (d_ptr->fbo || !d_ptr->tried_fbo)
&& qt_gl_preferGL2Engine())
{
@@ -712,7 +711,7 @@ void QGLWindowSurface::updateGeometry() {
format.setInternalTextureFormat(GLenum(GL_RGBA));
format.setTextureTarget(target);
- if (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)
+ if (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit)
format.setSamples(8);
d_ptr->fbo = new QGLFramebufferObject(rect.size(), format);
diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp
index 95de70e..51e2a57 100644
--- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp
+++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp
@@ -70,6 +70,7 @@ private slots:
void grayscale();
void colorize();
void drawPixmapItem();
+ void deviceCoordinateTranslateCaching();
};
void tst_QGraphicsEffect::initTestCase()
@@ -514,6 +515,51 @@ void tst_QGraphicsEffect::drawPixmapItem()
QTRY_VERIFY(effect->repaints >= 2);
}
+class DeviceEffect : public QGraphicsEffect
+{
+public:
+ QRectF boundingRectFor(const QRectF &rect) const
+ { return rect; }
+
+ void draw(QPainter *painter)
+ {
+ QPoint offset;
+ QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, QGraphicsEffect::NoPad);
+
+ if (pixmap.isNull())
+ return;
+
+ painter->save();
+ painter->setWorldTransform(QTransform());
+ painter->drawPixmap(offset, pixmap);
+ painter->restore();
+ }
+};
+
+void tst_QGraphicsEffect::deviceCoordinateTranslateCaching()
+{
+ QGraphicsScene scene;
+ CustomItem *item = new CustomItem(0, 0, 10, 10);
+ scene.addItem(item);
+ scene.setSceneRect(0, 0, 50, 0);
+
+ item->setGraphicsEffect(new DeviceEffect);
+ item->setPen(Qt::NoPen);
+ item->setBrush(Qt::red);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QTRY_VERIFY(item->numRepaints >= 1);
+ int numRepaints = item->numRepaints;
+
+ item->translate(10, 0);
+ QTest::qWait(50);
+
+ QVERIFY(item->numRepaints == numRepaints);
+}
+
QTEST_MAIN(tst_QGraphicsEffect)
#include "tst_qgraphicseffect.moc"