summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qopenglcontext.cpp11
-rw-r--r--src/gui/kernel/qopenglcontext_p.h2
-rw-r--r--src/gui/opengl/opengl.pri2
-rw-r--r--src/gui/opengl/qopengl_p.h93
-rw-r--r--src/gui/opengl/qopenglpaintengine.cpp35
-rw-r--r--src/gui/opengl/qopengltexturecache.cpp215
-rw-r--r--src/gui/opengl/qopengltexturecache_p.h102
-rw-r--r--tests/auto/qopengl/tst_qopengl.cpp10
8 files changed, 350 insertions, 120 deletions
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index d5b34c2f9b..22d003d4e9 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -566,6 +566,17 @@ QOpenGLSharedResource *QOpenGLMultiGroupSharedResource::value(QOpenGLContext *co
return group->d_func()->m_resources.value(this, 0);
}
+QList<QOpenGLSharedResource *> QOpenGLMultiGroupSharedResource::resources() const
+{
+ QList<QOpenGLSharedResource *> result;
+ for (QList<QOpenGLContextGroup *>::const_iterator it = m_groups.constBegin(); it != m_groups.constEnd(); ++it) {
+ QOpenGLSharedResource *resource = (*it)->d_func()->m_resources.value(const_cast<QOpenGLMultiGroupSharedResource *>(this), 0);
+ if (resource)
+ result << resource;
+ }
+ return result;
+}
+
void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContext *ctx)
{
QOpenGLSharedResource *resource = value(ctx);
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index bfe0f9dedf..059872c09f 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -154,6 +154,8 @@ public:
QOpenGLSharedResource *value(QOpenGLContext *context);
+ QList<QOpenGLSharedResource *> resources() const;
+
template <typename T>
T *value(QOpenGLContext *context) {
QOpenGLContextGroup *group = context->shareGroup();
diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri
index 22fc05e56a..4ee7af4569 100644
--- a/src/gui/opengl/opengl.pri
+++ b/src/gui/opengl/opengl.pri
@@ -14,6 +14,7 @@ HEADERS += opengl/qopengl.h \
opengl/qopenglshaderprogram.h \
opengl/qopenglextensions_p.h \
opengl/qopenglgradientcache_p.h \
+ opengl/qopengltexturecache_p.h \
opengl/qopenglengineshadermanager_p.h \
opengl/qopengl2pexvertexarray_p.h \
opengl/qopenglpaintengine_p.h \
@@ -34,6 +35,7 @@ SOURCES += opengl/qopengl.cpp \
opengl/qopenglbuffer.cpp \
opengl/qopenglshaderprogram.cpp \
opengl/qopenglgradientcache.cpp \
+ opengl/qopengltexturecache.cpp \
opengl/qopenglengineshadermanager.cpp \
opengl/qopengl2pexvertexarray.cpp \
opengl/qopenglpaintengine.cpp \
diff --git a/src/gui/opengl/qopengl_p.h b/src/gui/opengl/qopengl_p.h
index 59368f1a7b..b09f9447db 100644
--- a/src/gui/opengl/qopengl_p.h
+++ b/src/gui/opengl/qopengl_p.h
@@ -80,99 +80,6 @@ private:
QVector<int> m_offsets;
};
-class QOpenGLTexture : public QOpenGLSharedResource {
-public:
- QOpenGLTexture(QOpenGLContext *ctx, GLuint id, bool inverted)
- : QOpenGLSharedResource(ctx->shareGroup())
- , m_id(id)
- , m_inverted(inverted)
- {
- }
-
- GLuint id() const { return m_id; }
- bool invertedY() const { return m_inverted; }
-
-protected:
- void invalidateResource()
- {
- m_id = 0;
- }
-
- void freeResource(QOpenGLContext *)
- {
- glDeleteTextures(1, &m_id);
- }
-
-private:
- GLuint m_id;
- bool m_inverted;
-};
-
-struct QOpenGLTextureCacheKey {
- qint64 key;
- QOpenGLContextGroup *group;
-};
-
-inline bool operator==(const QOpenGLTextureCacheKey &a, const QOpenGLTextureCacheKey &b)
-{
- return a.key == b.key && a.group == b.group;
-}
-
-inline uint qHash(const QOpenGLTextureCacheKey &key)
-{
- return qHash(key.key) ^ qHash(key.group);
-}
-
-class QPlatformPixmap;
-
-class QOpenGLTextureCache {
-public:
- QOpenGLTextureCache();
- ~QOpenGLTextureCache();
-
- void insert(QOpenGLContext *ctx, qint64 key, QOpenGLTexture *texture, int cost);
- void remove(qint64 key);
- inline int size();
- inline void setMaxCost(int newMax);
- inline int maxCost();
- inline QOpenGLTexture* getTexture(QOpenGLContext *ctx, qint64 key);
-
- bool remove(QOpenGLContext *ctx, GLuint textureId);
- void removeContextTextures(QOpenGLContext *ctx);
- static QOpenGLTextureCache *instance();
- static void cleanupTexturesForCacheKey(qint64 cacheKey);
- static void cleanupTexturesForPixampData(QPlatformPixmap* pixmap);
- static void cleanupBeforePixmapDestruction(QPlatformPixmap* pixmap);
-
-private:
- QCache<QOpenGLTextureCacheKey, QOpenGLTexture> m_cache;
- QReadWriteLock m_lock;
-};
-
-int QOpenGLTextureCache::size() {
- QReadLocker locker(&m_lock);
- return m_cache.size();
-}
-
-void QOpenGLTextureCache::setMaxCost(int newMax)
-{
- QWriteLocker locker(&m_lock);
- m_cache.setMaxCost(newMax);
-}
-
-int QOpenGLTextureCache::maxCost()
-{
- QReadLocker locker(&m_lock);
- return m_cache.maxCost();
-}
-
-QOpenGLTexture* QOpenGLTextureCache::getTexture(QOpenGLContext *ctx, qint64 key)
-{
- QReadLocker locker(&m_lock);
- const QOpenGLTextureCacheKey cacheKey = { key, ctx->shareGroup() };
- return m_cache.object(cacheKey);
-}
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp
index 519dd3b893..b29cedcdf9 100644
--- a/src/gui/opengl/qopenglpaintengine.cpp
+++ b/src/gui/opengl/qopenglpaintengine.cpp
@@ -65,6 +65,7 @@
// #define QT_OPENGL_CACHE_AS_VBOS
#include "qopenglgradientcache_p.h"
+#include "qopengltexturecache_p.h"
#include "qopenglpaintengine_p.h"
#include <string.h> //for memcpy
@@ -197,7 +198,7 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
QImage texImage = qt_imageForBrush(style, false);
funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- //ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, QOpenGLContext::InternalBindOption);
+ QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, texImage);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
}
else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
@@ -227,11 +228,9 @@ void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
currentBrushPixmap = currentBrushPixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio);
funcs.glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- QOpenGLTexture *tex = 0;//ctx->d_func()->bindTexture(currentBrushPixmap, GL_TEXTURE_2D, GL_RGBA,
- // QOpenGLContext::InternalBindOption |
- // QOpenGLContext::CanFlipNativePixmapBindOption);
+ QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, currentBrushPixmap);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
- textureInvertedY = tex->invertedY();
+ textureInvertedY = false;
}
brushTextureDirty = false;
}
@@ -1360,18 +1359,15 @@ void QOpenGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixma
d->transferMode(ImageDrawingMode);
d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QOpenGLTexture *texture = 0;
-// ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, bindOptions);
+ GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap);
- GLfloat top = texture->invertedY() ? (pixmap.height() - src.top()) : src.top();
- GLfloat bottom = texture->invertedY() ? (pixmap.height() - src.bottom()) : src.bottom();
- QOpenGLRect srcRect(src.left(), top, src.right(), bottom);
+ QOpenGLRect srcRect(src.left(), src.top(), src.right(), src.bottom());
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && !pixmap.hasAlpha();
d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- state()->renderHints & QPainter::SmoothPixmapTransform, texture->id());
+ state()->renderHints & QPainter::SmoothPixmapTransform, id);
d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap);
}
@@ -1397,8 +1393,7 @@ void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, c
d->funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QOpenGLTexture *texture = 0;//ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, bindOptions);
- GLuint id = texture->id();
+ GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, image);
d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
state()->renderHints & QPainter::SmoothPixmapTransform, id);
@@ -1907,24 +1902,14 @@ void QOpenGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFra
}
funcs.glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QOpenGLTexture *texture = 0;//ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA,
- // QOpenGLContext::InternalBindOption
- // | QOpenGLContext::CanFlipNativePixmapBindOption);
-
- if (texture->invertedY()) {
- // Flip texture y-coordinate.
- QOpenGLPoint *data = textureCoordinateArray.data();
- for (int i = 0; i < 6 * fragmentCount; ++i)
- data[i].y = 1 - data[i].y;
- }
-
+ GLuint id = QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap);
transferMode(ImageArrayDrawingMode);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque;
updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id());
+ q->state()->renderHints & QPainter::SmoothPixmapTransform, id);
// Setup for texture drawing
currentBrush = noBrush;
diff --git a/src/gui/opengl/qopengltexturecache.cpp b/src/gui/opengl/qopengltexturecache.cpp
new file mode 100644
index 0000000000..067b7a9e20
--- /dev/null
+++ b/src/gui/opengl/qopengltexturecache.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopengltexturecache_p.h"
+#include <private/qopenglcontext_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
+#include <qplatformpixmap_qpa.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLTextureCacheWrapper
+{
+public:
+ QOpenGLTextureCacheWrapper()
+ {
+ QImagePixmapCleanupHooks::instance()->addPlatformPixmapModificationHook(cleanupTexturesForPixmapData);
+ QImagePixmapCleanupHooks::instance()->addPlatformPixmapDestructionHook(cleanupTexturesForPixmapData);
+ QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey);
+ }
+
+ ~QOpenGLTextureCacheWrapper()
+ {
+ QImagePixmapCleanupHooks::instance()->removePlatformPixmapModificationHook(cleanupTexturesForPixmapData);
+ QImagePixmapCleanupHooks::instance()->removePlatformPixmapDestructionHook(cleanupTexturesForPixmapData);
+ QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);
+ }
+
+ QOpenGLTextureCache *cacheForContext(QOpenGLContext *context) {
+ QMutexLocker lock(&m_mutex);
+ return m_resource.value<QOpenGLTextureCache>(context);
+ }
+
+ static void cleanupTexturesForCacheKey(qint64 key);
+ static void cleanupTexturesForPixmapData(QPlatformPixmap *pmd);
+
+private:
+ QOpenGLMultiGroupSharedResource m_resource;
+ QMutex m_mutex;
+};
+
+Q_GLOBAL_STATIC(QOpenGLTextureCacheWrapper, qt_texture_caches)
+
+QOpenGLTextureCache *QOpenGLTextureCache::cacheForContext(QOpenGLContext *context)
+{
+ return qt_texture_caches()->cacheForContext(context);
+}
+
+void QOpenGLTextureCacheWrapper::cleanupTexturesForCacheKey(qint64 key)
+{
+ QList<QOpenGLSharedResource *> resources = qt_texture_caches()->m_resource.resources();
+ for (QList<QOpenGLSharedResource *>::iterator it = resources.begin(); it != resources.end(); ++it)
+ static_cast<QOpenGLTextureCache *>(*it)->invalidate(key);
+}
+
+void QOpenGLTextureCacheWrapper::cleanupTexturesForPixmapData(QPlatformPixmap *pmd)
+{
+ cleanupTexturesForCacheKey(pmd->cacheKey());
+}
+
+QOpenGLTextureCache::QOpenGLTextureCache(QOpenGLContext *ctx)
+ : QOpenGLSharedResource(ctx->shareGroup())
+ , m_cache(64 * 1024) // 64 MB cache
+{
+}
+
+QOpenGLTextureCache::~QOpenGLTextureCache()
+{
+}
+
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &pixmap)
+{
+ QMutexLocker locker(&m_mutex);
+ qint64 key = pixmap.cacheKey();
+
+ // A QPainter is active on the image - take the safe route and replace the texture.
+ if (!pixmap.paintingActive()) {
+ QOpenGLCachedTexture *entry = m_cache.object(key);
+ if (entry) {
+ glBindTexture(GL_TEXTURE_2D, entry->id());
+ return entry->id();
+ }
+ }
+
+ GLuint id = bindTexture(context, key, pixmap.toImage());
+ if (id > 0)
+ QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
+
+ return id;
+}
+
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image)
+{
+ QMutexLocker locker(&m_mutex);
+ qint64 key = image.cacheKey();
+
+ // A QPainter is active on the image - take the safe route and replace the texture.
+ if (!image.paintingActive()) {
+ QOpenGLCachedTexture *entry = m_cache.object(key);
+ if (entry) {
+ glBindTexture(GL_TEXTURE_2D, entry->id());
+ return entry->id();
+ }
+ }
+
+ GLuint id = bindTexture(context, key, image);
+ if (id > 0)
+ QImagePixmapCleanupHooks::enableCleanupHooks(image);
+
+ return id;
+}
+
+static inline void qgl_byteSwapImage(QImage &img)
+{
+ const int width = img.width();
+ const int height = img.height();
+
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
+ {
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) img.scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
+ }
+ } else {
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) img.scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = (p[x] << 8) | (p[x] >> 24);
+ }
+ }
+}
+
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image)
+{
+ GLuint id;
+ glGenTextures(1, &id);
+ glBindTexture(GL_TEXTURE_2D, id);
+
+ QImage tx = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
+ qgl_byteSwapImage(tx);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tx.width(), tx.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, const_cast<const QImage &>(tx).bits());
+
+ int cost = tx.width() * tx.height() * 4 / 1024;
+ m_cache.insert(key, new QOpenGLCachedTexture(id, context), cost);
+
+ return id;
+}
+
+void QOpenGLTextureCache::invalidate(qint64 key)
+{
+ QMutexLocker locker(&m_mutex);
+ m_cache.remove(key);
+}
+
+void QOpenGLTextureCache::invalidateResource()
+{
+ m_cache.clear();
+}
+
+void QOpenGLTextureCache::freeResource(QOpenGLContext *)
+{
+ Q_ASSERT(false); // the texture cache lives until the context group disappears
+}
+
+static void freeTexture(QOpenGLFunctions *, GLuint id)
+{
+ glDeleteTextures(1, &id);
+}
+
+QOpenGLCachedTexture::QOpenGLCachedTexture(GLuint id, QOpenGLContext *context)
+{
+ m_resource = new QOpenGLSharedResourceGuard(context, id, freeTexture);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopengltexturecache_p.h b/src/gui/opengl/qopengltexturecache_p.h
new file mode 100644
index 0000000000..bdee9f4e83
--- /dev/null
+++ b/src/gui/opengl/qopengltexturecache_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QOPENGLTEXTURECACHE_P_H
+#define QOPENGLTEXTURECACHE_P_H
+
+#include <QHash>
+#include <QObject>
+#include <QtGui/QtGui>
+#include <private/qopenglcontext_p.h>
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLCachedTexture
+{
+public:
+ QOpenGLCachedTexture(GLuint id, QOpenGLContext *context);
+ ~QOpenGLCachedTexture() { m_resource->free(); }
+
+ GLuint id() const { return m_resource->id(); }
+
+private:
+ QOpenGLSharedResourceGuard *m_resource;
+};
+
+class QOpenGLTextureCache : public QOpenGLSharedResource
+{
+public:
+ static QOpenGLTextureCache *cacheForContext(QOpenGLContext *context);
+
+ QOpenGLTextureCache(QOpenGLContext *);
+ ~QOpenGLTextureCache();
+
+ GLuint bindTexture(QOpenGLContext *context, const QPixmap &pixmap);
+ GLuint bindTexture(QOpenGLContext *context, const QImage &image);
+
+ void invalidate(qint64 key);
+
+ void invalidateResource();
+ void freeResource(QOpenGLContext *ctx);
+
+private:
+ GLuint bindTexture(QOpenGLContext *context, qint64 key, const QImage &image);
+
+ QMutex m_mutex;
+ QCache<quint64, QOpenGLCachedTexture> m_cache;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/tests/auto/qopengl/tst_qopengl.cpp b/tests/auto/qopengl/tst_qopengl.cpp
index 18e7e07d94..577fbafe4a 100644
--- a/tests/auto/qopengl/tst_qopengl.cpp
+++ b/tests/auto/qopengl/tst_qopengl.cpp
@@ -418,14 +418,20 @@ void tst_QOpenGL::openGLPaintDevice()
QCOMPARE(image, fbo.toImage().convertToFormat(QImage::Format_RGB32));
- QSKIP("Image / pixmap painting needs to be implemented", SkipSingle);
p.begin(&device);
+ p.fillRect(0, 0, image.width(), image.height(), Qt::black);
p.drawImage(0, 0, image);
p.end();
QCOMPARE(image, fbo.toImage().convertToFormat(QImage::Format_RGB32));
-}
+ p.begin(&device);
+ p.fillRect(0, 0, image.width(), image.height(), Qt::black);
+ p.fillRect(0, 0, image.width(), image.height(), QBrush(image));
+ p.end();
+
+ QCOMPARE(image, fbo.toImage().convertToFormat(QImage::Format_RGB32));
+}
QTEST_MAIN(tst_QOpenGL)
#include "tst_qopengl.moc"