summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/unix/openssl/openssl.pri12
-rw-r--r--dist/changes-4.6.067
-rw-r--r--examples/script/customclass/bytearrayclass.cpp9
-rw-r--r--examples/script/customclass/main.cpp4
-rw-r--r--src/gui/egl/qegl.cpp11
-rw-r--r--src/gui/egl/qegl_p.h3
-rw-r--r--src/gui/image/image.pri6
-rw-r--r--src/gui/image/qimage.cpp17
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks.cpp110
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks_p.h (renamed from src/gui/painting/qregion_wince.cpp)104
-rw-r--r--src/gui/image/qpixmap.cpp24
-rw-r--r--src/gui/image/qpixmap_x11.cpp23
-rw-r--r--src/gui/image/qpixmap_x11_p.h12
-rw-r--r--src/gui/image/qpixmapdata_p.h1
-rw-r--r--src/gui/kernel/qapplication.cpp12
-rw-r--r--src/gui/painting/painting.pri8
-rw-r--r--src/gui/painting/qregion.cpp28
-rw-r--r--src/gui/painting/qregion.h4
-rw-r--r--src/gui/painting/qregion_win.cpp514
-rw-r--r--src/gui/painting/qwindowsurface_x11.cpp4
-rw-r--r--src/gui/styles/qwindowsxpstyle.cpp18
-rw-r--r--src/opengl/qgl.cpp37
-rw-r--r--src/opengl/qgl_p.h14
-rw-r--r--src/opengl/qgl_x11.cpp199
-rw-r--r--src/opengl/qgl_x11egl.cpp173
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp5
-rw-r--r--src/tools/moc/moc.cpp2
-rw-r--r--tests/auto/moc/tst_moc.cpp7
28 files changed, 670 insertions, 758 deletions
diff --git a/config.tests/unix/openssl/openssl.pri b/config.tests/unix/openssl/openssl.pri
index bc95479..f069396 100644
--- a/config.tests/unix/openssl/openssl.pri
+++ b/config.tests/unix/openssl/openssl.pri
@@ -1,9 +1,3 @@
-!cross_compile {
- TRY_INCLUDEPATHS = /include /usr/include /usr/local/include $$QMAKE_INCDIR $$INCLUDEPATH
- # LSB doesn't allow using headers from /include or /usr/include
- linux-lsb-g++:TRY_INCLUDEPATHS = $$QMAKE_INCDIR $$INCLUDEPATH
- for(p, TRY_INCLUDEPATHS) {
- pp = $$join(p, "", "", "/openssl")
- exists($$pp):INCLUDEPATH *= $$p
- }
-}
+# Empty file since Qt 4.6
+# I'm too lazy to find all places where this file is included
+
diff --git a/dist/changes-4.6.0 b/dist/changes-4.6.0
index 383c6b7..7a6decf 100644
--- a/dist/changes-4.6.0
+++ b/dist/changes-4.6.0
@@ -34,9 +34,15 @@ information about a particular change.
- Significant external contribution from Milan Burda for planned removal
of (non-unicode) Windows 9x/ME support.
+ - QRegion is no longer a GDI object by default. This means it is no
+ longer subjuect to gui-thread only nor does it potentially impact
+ the 10.000 GDI object limit per process. By explicitly calling
+ .handle() a GDI object will be created and memory managed by
+ QRegion. The native handle is for reading out only. Any GDI calls
+ made on the HRGN handle will not affect the QRegion.
****************************************************************************
-* Important Behavior Changes *
+* Important Behavior Changes *
****************************************************************************
- The experimental Direct3D paint engine has been removed. The reason for
@@ -71,33 +77,32 @@ information about a particular change.
QGraphicsItem::ItemSendsGeometryChanges (which is enabled by default by
QGraphicsWidget and QGraphicsProxyWidget).
-- QDesktopWidget on X11 no longer emits the resized(int) signal when screens
- are added or removed. This was not done on other platforms. Use the
- screenCountChanged signal instead
-
-- QUrl's parser is more strict when for hostnames in URLs. QUrl now
- enforces STD 3 rules:
-
- * each individual hostname section (between dots) must be at most
- 63 ASCII characters in length;
-
- * only letters, digits, and the hyphen character are allowed in the
- ASCII range; letters outside the ASCII range follow the normal
- IDN rules
-
- That means QUrl no longer accepts some URLs that were invalid
- before, but weren't interpreted as such.
-
-- The Unix configure-time check for STL is stricter now in Qt
- 4.6.0. This means some legacy STL implementations may fail to pass
- the test and, therefore, Qt will automatically disable STL support.
-
- This is a binary-compatible change: existing code will continue to
- work without being recompiled. However, it affects the source code,
- since some STL-compatibility API will not be enabled.
-
- Platforms affected by this change:
- * solaris-cc-* with the default (Cstd) C++ STL library
- recommendation: use -library=stlport4
- See Sun Studio's documentation for the effects of this option
-
+ - QDesktopWidget on X11 no longer emits the resized(int) signal when screens
+ are added or removed. This was not done on other platforms. Use the
+ screenCountChanged signal instead
+
+ - QUrl's parser is more strict when for hostnames in URLs. QUrl now
+ enforces STD 3 rules:
+
+ * each individual hostname section (between dots) must be at most
+ 63 ASCII characters in length;
+
+ * only letters, digits, and the hyphen character are allowed in the
+ ASCII range; letters outside the ASCII range follow the normal
+ IDN rules
+
+ That means QUrl no longer accepts some URLs that were invalid
+ before, but weren't interpreted as such.
+
+ - The Unix configure-time check for STL is stricter now in Qt
+ 4.6.0. This means some legacy STL implementations may fail to pass
+ the test and, therefore, Qt will automatically disable STL support.
+
+ This is a binary-compatible change: existing code will continue to
+ work without being recompiled. However, it affects the source code,
+ since some STL-compatibility API will not be enabled.
+
+ Platforms affected by this change:
+ * solaris-cc-* with the default (Cstd) C++ STL library
+ recommendation: use -library=stlport4
+ See Sun Studio's documentation for the effects of this option
diff --git a/examples/script/customclass/bytearrayclass.cpp b/examples/script/customclass/bytearrayclass.cpp
index 81a0b8a..2044a16 100644
--- a/examples/script/customclass/bytearrayclass.cpp
+++ b/examples/script/customclass/bytearrayclass.cpp
@@ -100,7 +100,7 @@ ByteArrayClass::ByteArrayClass(QScriptEngine *engine)
QScriptValue global = engine->globalObject();
proto.setPrototype(global.property("Object").property("prototype"));
- ctor = engine->newFunction(construct);
+ ctor = engine->newFunction(construct, proto);
ctor.setData(qScriptValueFromValue(engine, this));
}
//! [0]
@@ -224,7 +224,10 @@ QScriptValue ByteArrayClass::construct(QScriptContext *ctx, QScriptEngine *)
ByteArrayClass *cls = qscriptvalue_cast<ByteArrayClass*>(ctx->callee().data());
if (!cls)
return QScriptValue();
- int size = ctx->argument(0).toInt32();
+ QScriptValue arg = ctx->argument(0);
+ if (arg.instanceOf(ctx->callee()))
+ return cls->newInstance(qscriptvalue_cast<QByteArray>(arg));
+ int size = arg.toInt32();
return cls->newInstance(size);
}
//! [2]
@@ -240,7 +243,7 @@ QScriptValue ByteArrayClass::toScriptValue(QScriptEngine *eng, const QByteArray
void ByteArrayClass::fromScriptValue(const QScriptValue &obj, QByteArray &ba)
{
- ba = qscriptvalue_cast<QByteArray>(obj.data());
+ ba = qvariant_cast<QByteArray>(obj.data().toVariant());
}
diff --git a/examples/script/customclass/main.cpp b/examples/script/customclass/main.cpp
index 05aefd5..3b98f5c 100644
--- a/examples/script/customclass/main.cpp
+++ b/examples/script/customclass/main.cpp
@@ -52,6 +52,7 @@ int main(int argc, char **argv)
eng.globalObject().setProperty("ByteArray", baClass->constructor());
qDebug() << "ba = new ByteArray(4):" << eng.evaluate("ba = new ByteArray(4)").toString();
+ qDebug() << "ba instanceof ByteArray:" << eng.evaluate("ba instanceof ByteArray").toBool();
qDebug() << "ba.length:" << eng.evaluate("ba.length").toNumber();
qDebug() << "ba[1] = 123; ba[1]:" << eng.evaluate("ba[1] = 123; ba[1]").toNumber();
qDebug() << "ba[7] = 224; ba.length:" << eng.evaluate("ba[7] = 224; ba.length").toNumber();
@@ -65,6 +66,9 @@ int main(int argc, char **argv)
qDebug() << "ba.toBase64().toLatin1String():" << eng.evaluate("b64.toLatin1String()").toString();
qDebug() << "ba.valueOf():" << eng.evaluate("ba.valueOf()").toString();
qDebug() << "ba.chop(2); ba.length:" << eng.evaluate("ba.chop(2); ba.length").toNumber();
+ qDebug() << "ba2 = new ByteArray(ba):" << eng.evaluate("ba2 = new ByteArray(ba)").toString();
+ qDebug() << "ba2.equals(ba):" << eng.evaluate("ba2.equals(ba)").toBool();
+ qDebug() << "ba2.equals(new ByteArray()):" << eng.evaluate("ba2.equals(new ByteArray())").toBool();
return 0;
}
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
index 89d9d1b..ebdac9a 100644
--- a/src/gui/egl/qegl.cpp
+++ b/src/gui/egl/qegl.cpp
@@ -400,4 +400,15 @@ void QEglContext::dumpAllConfigs()
delete [] configs;
}
+QString QEglContext::extensions()
+{
+ const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+ return QString(QLatin1String(exts));
+}
+
+bool QEglContext::hasExtension(const char* extensionName)
+{
+ return extensions().contains(QLatin1String(extensionName));
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h
index ddf7d27..3ae1489 100644
--- a/src/gui/egl/qegl_p.h
+++ b/src/gui/egl/qegl_p.h
@@ -122,6 +122,9 @@ public:
void dumpAllConfigs();
+ QString extensions();
+ bool hasExtension(const char* extensionName);
+
private:
QEgl::API apiType;
EGLDisplay dpy;
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index bf348af..b9c36dc 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -25,7 +25,9 @@ HEADERS += \
image/qpixmapcache_p.h \
image/qpixmapdata_p.h \
image/qpixmapdatafactory_p.h \
- image/qpixmapfilter_p.h
+ image/qpixmapfilter_p.h \
+ image/qimagepixmapcleanuphooks_p.h \
+
SOURCES += \
image/qbitmap.cpp \
@@ -47,6 +49,8 @@ SOURCES += \
image/qmovie.cpp \
image/qpixmap_raster.cpp \
image/qnativeimage.cpp \
+ image/qimagepixmapcleanuphooks.cpp \
+
win32 {
SOURCES += image/qpixmap_win.cpp
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index e8ca7a9..bb77fb5 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -49,6 +49,7 @@
#include "qimagewriter.h"
#include "qstringlist.h"
#include "qvariant.h"
+#include "qimagepixmapcleanuphooks_p.h"
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>
@@ -106,14 +107,6 @@ static inline bool checkPixelSize(const QImage::Format format)
}
-// ### Qt 5: remove
-typedef void (*_qt_image_cleanup_hook)(int);
-Q_GUI_EXPORT _qt_image_cleanup_hook qt_image_cleanup_hook = 0;
-
-// ### Qt 5: rename
-typedef void (*_qt_image_cleanup_hook_64)(qint64);
-Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64 = 0;
-
static QImage rotated90(const QImage &src);
static QImage rotated180(const QImage &src);
static QImage rotated270(const QImage &src);
@@ -257,8 +250,8 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu
QImageData::~QImageData()
{
- if (is_cached && qt_image_cleanup_hook_64)
- qt_image_cleanup_hook_64((((qint64) ser_no) << 32) | ((qint64) detach_no));
+ if (is_cached)
+ QImagePixmapCleanupHooks::executeImageHooks((((qint64) ser_no) << 32) | ((qint64) detach_no));
delete paintEngine;
if (data && own_data)
free(data);
@@ -1342,8 +1335,8 @@ QImage::operator QVariant() const
void QImage::detach()
{
if (d) {
- if (d->is_cached && qt_image_cleanup_hook_64 && d->ref == 1)
- qt_image_cleanup_hook_64(cacheKey());
+ if (d->is_cached && d->ref == 1)
+ QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
if (d->ref != 1 || d->ro_data)
*this = copy();
diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp
new file mode 100644
index 0000000..7d1c5fb
--- /dev/null
+++ b/src/gui/image/qimagepixmapcleanuphooks.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qimagepixmapcleanuphooks_p.h"
+#include "qpixmapdata_p.h"
+
+
+// Legacy, single instance hooks: ### Qt 5: remove
+typedef void (*_qt_pixmap_cleanup_hook)(int);
+typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
+typedef void (*_qt_image_cleanup_hook)(int);
+Q_GUI_EXPORT _qt_pixmap_cleanup_hook qt_pixmap_cleanup_hook = 0;
+Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64 = 0;
+Q_GUI_EXPORT _qt_image_cleanup_hook qt_image_cleanup_hook = 0;
+Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64 = 0;
+
+
+QImagePixmapCleanupHooks* qt_image_and_pixmap_cleanup_hooks = 0;
+
+
+QImagePixmapCleanupHooks::QImagePixmapCleanupHooks()
+{
+ qt_image_and_pixmap_cleanup_hooks = this;
+}
+
+QImagePixmapCleanupHooks *QImagePixmapCleanupHooks::instance()
+{
+ if (!qt_image_and_pixmap_cleanup_hooks)
+ qt_image_and_pixmap_cleanup_hooks = new QImagePixmapCleanupHooks;
+ return qt_image_and_pixmap_cleanup_hooks;
+}
+
+void QImagePixmapCleanupHooks::addPixmapHook(_qt_pixmap_cleanup_hook_pm hook)
+{
+ pixmapHooks.append(hook);
+}
+
+void QImagePixmapCleanupHooks::addImageHook(_qt_image_cleanup_hook_64 hook)
+{
+ imageHooks.append(hook);
+}
+
+void QImagePixmapCleanupHooks::removePixmapHook(_qt_pixmap_cleanup_hook_pm hook)
+{
+ pixmapHooks.removeAll(hook);
+}
+
+void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook)
+{
+ imageHooks.removeAll(hook);
+}
+
+
+void QImagePixmapCleanupHooks::executePixmapHooks(QPixmap* pm)
+{
+ for (int i = 0; i < qt_image_and_pixmap_cleanup_hooks->pixmapHooks.count(); ++i)
+ qt_image_and_pixmap_cleanup_hooks->pixmapHooks[i](pm);
+
+ if (qt_pixmap_cleanup_hook_64)
+ qt_pixmap_cleanup_hook_64(pm->cacheKey());
+}
+
+
+void QImagePixmapCleanupHooks::executeImageHooks(qint64 key)
+{
+ for (int i = 0; i < qt_image_and_pixmap_cleanup_hooks->imageHooks.count(); ++i)
+ qt_image_and_pixmap_cleanup_hooks->imageHooks[i](key);
+
+ if (qt_image_cleanup_hook_64)
+ qt_image_cleanup_hook_64(key);
+}
+
diff --git a/src/gui/painting/qregion_wince.cpp b/src/gui/image/qimagepixmapcleanuphooks_p.h
index 9c33123..e765e69 100644
--- a/src/gui/painting/qregion_wince.cpp
+++ b/src/gui/image/qimagepixmapcleanuphooks_p.h
@@ -39,81 +39,51 @@
**
****************************************************************************/
-#include "qatomic.h"
-#include "qbitmap.h"
-#include "qbuffer.h"
-#include "qimage.h"
-#include "qpolygon.h"
-#include "qregion.h"
-#include "qt_windows.h"
-#include "qpainterpath.h"
-#include "qguifunctions_wince.h"
+#ifndef QIMAGEPIXMAP_CLEANUPHOOKS_P_H
+#define QIMAGEPIXMAP_CLEANUPHOOKS_P_H
+
+//
+// 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.
+//
+
+#include <QtGui/qpixmap.h>
QT_BEGIN_NAMESPACE
-QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 };
+typedef void (*_qt_image_cleanup_hook_64)(qint64);
+typedef void (*_qt_pixmap_cleanup_hook_pm)(QPixmap*);
-HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom)
-{
- const int tries = 10;
- for (int i = 0; i < tries; ++i) {
- HRGN region;
- switch (type) {
- case QRegion::Rectangle:
- region = CreateRectRgn(left, top, right, bottom);
- break;
- case QRegion::Ellipse:
-#ifndef Q_OS_WINCE
- region = CreateEllipticRgn(left, top, right, bottom);
-#endif
- break;
- }
- if (region) {
- if (GetRegionData(region, 0, 0))
- return region;
- else
- DeleteObject(region);
- }
- }
- return 0;
-}
+class QImagePixmapCleanupHooks;
+extern QImagePixmapCleanupHooks* qt_image_and_pixmap_cleanup_hooks;
-void qt_win_dispose_rgn(HRGN r)
+class Q_GUI_EXPORT QImagePixmapCleanupHooks
{
- if (r)
- DeleteObject(r);
-}
+public:
+ QImagePixmapCleanupHooks();
-static void qt_add_rect(HRGN &winRegion, QRect r)
-{
- HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
- if (rgn) {
- HRGN dest = CreateRectRgn(0,0,0,0);
- int result = CombineRgn(dest, winRegion, rgn, RGN_OR);
- if (result) {
- DeleteObject(winRegion);
- winRegion = dest;
- }
- }
-}
+ static QImagePixmapCleanupHooks *instance();
-void QRegion::ensureHandle() const
-{
- if (d->rgn)
- DeleteObject(d->rgn);
- d->rgn = CreateRectRgn(0,0,0,0);
- if (d->qt_rgn) {
- if (d->qt_rgn->numRects == 1) {
- QRect r = d->qt_rgn->extents;
- qt_add_rect(d->rgn, r);
- return;
- }
- for (int i = 0;i < d->qt_rgn->numRects;i++) {
- QRect r = d->qt_rgn->rects.at(i);
- qt_add_rect(d->rgn, r);
- }
- }
-}
+ void addPixmapHook(_qt_pixmap_cleanup_hook_pm);
+ void addImageHook(_qt_image_cleanup_hook_64);
+
+ void removePixmapHook(_qt_pixmap_cleanup_hook_pm);
+ void removeImageHook(_qt_image_cleanup_hook_64);
+ static void executePixmapHooks(QPixmap*);
+ static void executeImageHooks(qint64 key);
+
+private:
+ QList<_qt_image_cleanup_hook_64> imageHooks;
+ QList<_qt_pixmap_cleanup_hook_pm> pixmapHooks;
+};
QT_END_NAMESPACE
+
+#endif // QIMAGEPIXMAP_CLEANUPHOOKS_P_H
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 18829f4..82835d5 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -43,6 +43,7 @@
#include "qpixmap.h"
#include "qpixmapdata_p.h"
+#include "qimagepixmapcleanuphooks_p.h"
#include "qbitmap.h"
#include "qcolormap.h"
@@ -81,14 +82,6 @@
QT_BEGIN_NAMESPACE
// ### Qt 5: remove
-typedef void (*_qt_pixmap_cleanup_hook)(int);
-Q_GUI_EXPORT _qt_pixmap_cleanup_hook qt_pixmap_cleanup_hook = 0;
-
-// ### Qt 5: rename
-typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
-Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64 = 0;
-
-// ### Qt 5: remove
Q_GUI_EXPORT qint64 qt_pixmap_id(const QPixmap &pixmap)
{
return pixmap.cacheKey();
@@ -656,7 +649,7 @@ void QPixmap::resize_helper(const QSize &s)
QX11PixmapData *x11Data = data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data) : 0;
if (x11Data) {
pm.x11SetScreen(x11Data->xinfo.screen());
- uninit = x11Data->uninit;
+ uninit = x11Data->flags & QX11PixmapData::Uninitialized;
}
#elif defined(Q_WS_MAC)
QMacPixmapData *macData = data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data) : 0;
@@ -1357,8 +1350,8 @@ bool QPixmap::isDetached() const
void QPixmap::deref()
{
if (data && !data->ref.deref()) { // Destroy image if last ref
- if (data->is_cached && qt_pixmap_cleanup_hook_64)
- qt_pixmap_cleanup_hook_64(cacheKey());
+ if (data->is_cached)
+ QImagePixmapCleanupHooks::executePixmapHooks(this);
delete data;
data = 0;
}
@@ -1897,9 +1890,6 @@ int QPixmap::defaultDepth()
#endif
}
-typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
-extern _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64;
-
/*!
Detaches the pixmap from shared pixmap data.
@@ -1925,8 +1915,8 @@ void QPixmap::detach()
rasterData->image.detach();
}
- if (data->is_cached && qt_pixmap_cleanup_hook_64 && data->ref == 1)
- qt_pixmap_cleanup_hook_64(cacheKey());
+ if (data->is_cached && data->ref == 1)
+ QImagePixmapCleanupHooks::executePixmapHooks(this);
#if defined(Q_WS_MAC)
QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data) : 0;
@@ -1946,7 +1936,7 @@ void QPixmap::detach()
#if defined(Q_WS_X11)
if (data->classId() == QPixmapData::X11Class) {
QX11PixmapData *d = static_cast<QX11PixmapData*>(data);
- d->uninit = false;
+ d->flags &= ~QX11PixmapData::Uninitialized;
// reset the cache data
if (d->hd2) {
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 86cf515..be3d070 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -313,7 +313,7 @@ int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0;
QX11PixmapData::QX11PixmapData(PixelType type)
: QPixmapData(type, X11Class), hd(0),
- uninit(true), read_only(false), x11_mask(0), picture(0), mask_picture(0), hd2(0),
+ flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0), gl_surface(0),
share_mode(QPixmap::ImplicitlyShared), pengine(0)
{
}
@@ -1217,7 +1217,7 @@ void QX11PixmapData::release()
XFreePixmap(xinfo.display(), hd2);
hd2 = 0;
}
- if (!read_only)
+ if (!(flags & Readonly))
XFreePixmap(xinfo.display(), hd);
hd = 0;
}
@@ -1876,7 +1876,7 @@ QPixmap QX11PixmapData::transformed(const QTransform &transform,
} else { // color pixmap
QPixmap pm;
QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(pm.data);
- x11Data->uninit = false;
+ x11Data->flags &= ~QX11PixmapData::Uninitialized;
x11Data->xinfo = xinfo;
x11Data->d = d;
x11Data->w = w;
@@ -2018,7 +2018,7 @@ QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
QPixmap pm(data);
- data->uninit = false;
+ data->flags &= ~QX11PixmapData::Uninitialized;
pm.x11SetScreen(scr);
GC gc = XCreateGC(dpy, pm.handle(), 0, 0);
@@ -2060,7 +2060,7 @@ QPaintEngine* QX11PixmapData::paintEngine() const
{
QX11PixmapData *that = const_cast<QX11PixmapData*>(this);
- if (read_only && share_mode == QPixmap::ImplicitlyShared) {
+ if ((flags & Readonly) && share_mode == QPixmap::ImplicitlyShared) {
// if someone wants to draw onto us, copy the shared contents
// and turn it into a fully fledged QPixmap
::Pixmap hd_copy = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()),
@@ -2082,7 +2082,7 @@ QPaintEngine* QX11PixmapData::paintEngine() const
XFreeGC(X11->display, gc);
}
that->hd = hd_copy;
- that->read_only = false;
+ that->flags &= ~QX11PixmapData::Readonly;
}
if (!that->pengine)
@@ -2133,7 +2133,7 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect)
setSerialNumber(++qt_pixmap_serial);
- uninit = false;
+ flags &= ~Uninitialized;
xinfo = x11Data->xinfo;
d = x11Data->d;
w = rect.width();
@@ -2201,7 +2201,7 @@ void QX11PixmapData::convertToARGB32(bool preserveContents)
return;
// Q_ASSERT(count == 1);
- if (read_only && share_mode == QPixmap::ExplicitlyShared)
+ if ((flags & Readonly) && share_mode == QPixmap::ExplicitlyShared)
return;
Pixmap pm = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()),
@@ -2211,10 +2211,10 @@ void QX11PixmapData::convertToARGB32(bool preserveContents)
if (picture) {
if (preserveContents)
XRenderComposite(X11->display, PictOpSrc, picture, 0, p, 0, 0, 0, 0, 0, 0, w, h);
- if (!read_only)
+ if (!(flags & Readonly))
XRenderFreePicture(X11->display, picture);
}
- if (hd && !read_only)
+ if (hd && !(flags & Readonly))
XFreePixmap(X11->display, hd);
if (x11_mask) {
XFreePixmap(X11->display, x11_mask);
@@ -2252,9 +2252,8 @@ QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode)
QX11PixmapData *data = new QX11PixmapData(depth == 1 ? QPixmapData::BitmapType : QPixmapData::PixmapType);
data->setSerialNumber(++qt_pixmap_serial);
- data->read_only = true;
+ data->flags = QX11PixmapData::Readonly;
data->share_mode = mode;
- data->uninit = false;
data->w = width;
data->h = height;
data->is_null = (width <= 0 || height <= 0);
diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h
index 3de9a0f..835fea4 100644
--- a/src/gui/image/qpixmap_x11_p.h
+++ b/src/gui/image/qpixmap_x11_p.h
@@ -99,6 +99,7 @@ private:
friend class QX11PaintEngine;
friend class QX11WindowSurface;
friend class QRasterWindowSurface;
+ friend class QGLContextPrivate; // Needs to access xinfo, gl_surface & flags
void release();
@@ -108,14 +109,21 @@ private:
Qt::HANDLE hd;
- uint uninit : 1;
- uint read_only : 1;
+ enum Flag {
+ NoFlags = 0x0,
+ Uninitialized = 0x1,
+ Readonly = 0x2,
+ InvertedWhenBoundToTexture = 0x4,
+ GlSurfaceCreatedWithAlpha = 0x8
+ };
+ uint flags;
QX11Info xinfo;
Qt::HANDLE x11_mask;
Qt::HANDLE picture;
Qt::HANDLE mask_picture;
Qt::HANDLE hd2; // sorted in the default display depth
+ Qt::HANDLE gl_surface;
#ifndef QT_NO_XRENDER
void convertToARGB32(bool preserveContents = true);
#endif
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 29dafaf..32b419e 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -116,6 +116,7 @@ private:
friend class QPixmap;
friend class QGLContextPrivate;
friend class QX11PixmapData;
+ friend class QGLTextureCache; //Needs to check the reference count
QAtomicInt ref;
int detach_no;
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 5181689..109ceb1 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -179,11 +179,11 @@ QApplicationPrivate::~QApplicationPrivate()
QApplication contains the main event loop, where all events from the window
system and other sources are processed and dispatched. It also handles the
- application's initialization and finalization, and provides session
- management. In addition, it handles most system-wide and application-wide
- settings.
+ application's initialization, finalization, and provides session
+ management. In addition, QApplication handles most of the system-wide and
+ application-wide settings.
- For any GUI application using Qt, there is precisely one QApplication
+ For any GUI application using Qt, there is precisely \bold one QApplication
object, no matter whether the application has 0, 1, 2 or more windows at
any given time. For non-GUI Qt applications, use QCoreApplication instead,
as it does not depend on the \l QtGui library.
@@ -239,9 +239,9 @@ QApplicationPrivate::~QApplicationPrivate()
saveState() for details.
\endlist
- The QApplication object does so much initialization. Hence, it \e{must} be
+ Since the QApplication object does so much initialization, it \e{must} be
created before any other objects related to the user interface are created.
- Since QApplication also deals with common command line arguments, it is
+ QApplication also deals with common command line arguments. Hence, it is
usually a good idea to create it \e before any interpretation or
modification of \c argv is done in the application itself.
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 34d1779..d226be2 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -100,8 +100,8 @@ win32 {
painting/qcolormap_win.cpp \
painting/qpaintdevice_win.cpp \
painting/qprintengine_win.cpp \
- painting/qprinterinfo_win.cpp \
- painting/qregion_win.cpp
+ painting/qprinterinfo_win.cpp
+
!win32-borland:!wince*:LIBS += -lmsimg32
}
@@ -126,10 +126,6 @@ embedded {
painting/qwindowsurface_raster.cpp \
}
-wince* {
- SOURCES -= painting/qregion_win.cpp
-}
-
unix:x11 {
HEADERS += \
painting/qpaintengine_x11_p.h
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 762e9e0..d59f3ff 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -49,7 +49,7 @@
#include <qdebug.h>
-#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE)
+#if defined(Q_OS_UNIX) || defined(Q_WS_WIN)
#include "qimage.h"
#include "qbitmap.h"
#include <stdlib.h>
@@ -545,7 +545,7 @@ QRegion& QRegion::operator|=(const QRegion &r)
\sa intersected()
*/
-#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE)
+#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN)
QRegion& QRegion::operator+=(const QRect &r)
{
return operator+=(QRegion(r));
@@ -561,16 +561,14 @@ QRegion& QRegion::operator+=(const QRect &r)
\sa intersected()
*/
-#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE)
QRegion& QRegion::operator&=(const QRegion &r)
{ return *this = *this & r; }
-#endif
/*!
\overload
\since 4.4
*/
-#if defined (Q_OS_UNIX) || defined (Q_OS_WINCE)
+#if defined (Q_OS_UNIX) || defined (Q_WS_WIN)
QRegion& QRegion::operator&=(const QRect &r)
{
return *this = *this & r;
@@ -591,10 +589,8 @@ QRegion& QRegion::operator&=(const QRect &r)
\sa subtracted()
*/
-#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE)
QRegion& QRegion::operator-=(const QRegion &r)
{ return *this = *this - r; }
-#endif
/*!
Applies the xored() function to this region and \a r and
@@ -731,7 +727,7 @@ bool QRegion::intersects(const QRect &rect) const
return false;
}
-#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE)
+#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN)
/*!
\overload
\since 4.4
@@ -1086,7 +1082,7 @@ Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion &region)
return result;
}
-#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE)
+#if defined(Q_OS_UNIX) || defined(Q_WS_WIN)
//#define QT_REGION_DEBUG
/*
@@ -1627,9 +1623,9 @@ QT_END_INCLUDE_NAMESPACE
QT_BEGIN_INCLUDE_NAMESPACE
# include "qregion_mac.cpp"
QT_END_INCLUDE_NAMESPACE
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
QT_BEGIN_INCLUDE_NAMESPACE
-# include "qregion_wince.cpp"
+# include "qregion_win.cpp"
QT_END_INCLUDE_NAMESPACE
#elif defined(Q_WS_QWS)
static QRegionPrivate qrp;
@@ -3829,7 +3825,7 @@ QRegion::QRegion(const QRect &r, RegionType t)
#if defined(Q_WS_X11)
d->rgn = 0;
d->xrectangles = 0;
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
d->rgn = 0;
#endif
if (t == Rectangle) {
@@ -3851,7 +3847,7 @@ QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
#if defined(Q_WS_X11)
d->rgn = 0;
d->xrectangles = 0;
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
d->rgn = 0;
#endif
d->qt_rgn = PolygonRegion(a.constData(), a.size(),
@@ -3881,7 +3877,7 @@ QRegion::QRegion(const QBitmap &bm)
#if defined(Q_WS_X11)
d->rgn = 0;
d->xrectangles = 0;
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
d->rgn = 0;
#endif
d->qt_rgn = qt_bitmapToRegion(bm);
@@ -3896,7 +3892,7 @@ void QRegion::cleanUp(QRegion::QRegionData *x)
XDestroyRegion(x->rgn);
if (x->xrectangles)
free(x->xrectangles);
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
if (x->rgn)
qt_win_dispose_rgn(x->rgn);
#endif
@@ -3932,7 +3928,7 @@ QRegion QRegion::copy() const
#if defined(Q_WS_X11)
x->rgn = 0;
x->xrectangles = 0;
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WIN)
x->rgn = 0;
#endif
if (d->qt_rgn)
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index 6dfdc83..84024ce 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -59,7 +59,7 @@ QT_MODULE(Gui)
template <class T> class QVector;
class QVariant;
-#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN)
struct QRegionPrivate;
#endif
@@ -200,7 +200,7 @@ private:
#elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
mutable RgnHandle unused; // Here for binary compatability reasons. ### Qt 5 remove.
#endif
-#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN)
QRegionPrivate *qt_rgn;
#endif
};
diff --git a/src/gui/painting/qregion_win.cpp b/src/gui/painting/qregion_win.cpp
index 249b1a6..2d5e76b 100644
--- a/src/gui/painting/qregion_win.cpp
+++ b/src/gui/painting/qregion_win.cpp
@@ -39,27 +39,25 @@
**
****************************************************************************/
+#include "qatomic.h"
#include "qbitmap.h"
#include "qbuffer.h"
#include "qimage.h"
#include "qpolygon.h"
#include "qregion.h"
#include "qt_windows.h"
+#include "qpainterpath.h"
+#include "qguifunctions_wince.h"
QT_BEGIN_NAMESPACE
+QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 };
-/*
- In Windows versions before Windows Vista CreateRectRgn - when called in a multi-threaded
- environment - might return an invalid handle. This function works around this limitation
- by verifying the handle with a quick GetRegionData() call and re-creates the region
- if necessary.
-*/
HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom)
{
const int tries = 10;
for (int i = 0; i < tries; ++i) {
- HRGN region = 0;
+ HRGN region;
switch (type) {
case QRegion::Rectangle:
region = CreateRectRgn(left, top, right, bottom);
@@ -80,497 +78,73 @@ HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right,
return 0;
}
-#ifndef Q_OS_WINCE
-HRGN qt_tryCreatePolygonRegion(const QPolygon &a, Qt::FillRule fillRule)
-{
- const int tries = 10;
- for (int i = 0; i < tries; ++i) {
- HRGN region = CreatePolygonRgn(reinterpret_cast<const POINT*>(a.data()), a.size(),
- fillRule == Qt::OddEvenFill ? ALTERNATE : WINDING);
- if (region) {
- if (GetRegionData(region, 0, 0))
- return region;
- else
- DeleteObject(region);
- }
- }
- return 0;
-}
-#endif
-
-QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 };
-
-QRegion::QRegion()
- : d(&shared_empty)
-{
- d->ref.ref();
-}
-
-#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp
-QRegion::QRegion(const QRect &r, RegionType t)
-{
- if (r.isEmpty()) {
- d = &shared_empty;
- d->ref.ref();
- } else {
- d = new QRegionData;
- d->ref = 1;
- if (t == Rectangle)
- d->rgn = qt_tryCreateRegion(t, r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
- else if (t == Ellipse) {
- // need to add 1 to width/height for the ellipse to have correct boundingrect.
- d->rgn = qt_tryCreateRegion(t, r.x(), r.y(), r.x() + r.width() + 1, r.y() + r.height() + 1);
- }
- }
-}
-#endif
-
-#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp
-QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
-{
- if (a.size() < 3) {
- d = &shared_empty;
- d->ref.ref();
- } else {
- d = new QRegionData;
- d->ref = 1;
- d->rgn = qt_tryCreatePolygonRegion(a, fillRule);
- }
-}
-#endif
-
-QRegion::QRegion(const QRegion &r)
-{
- d = r.d;
- d->ref.ref();
-}
-
-HRGN qt_win_bitmapToRegion(const QBitmap& bitmap)
-{
- HRGN region=0;
- QImage image = bitmap.toImage();
- const int MAXRECT = 256;
- struct RData {
- RGNDATAHEADER header;
- RECT rect[MAXRECT];
- };
- RData data;
-
-#define FlushSpans \
- { \
- data.header.dwSize = sizeof(RGNDATAHEADER); \
- data.header.iType = RDH_RECTANGLES; \
- data.header.nCount = n; \
- data.header.nRgnSize = 0; \
- data.header.rcBound.bottom = y; \
- HRGN r = ExtCreateRegion(0, \
- sizeof(RGNDATAHEADER)+n*sizeof(RECT),(RGNDATA*)&data); \
- if (region) { \
- CombineRgn(region, region, r, RGN_OR); \
- DeleteObject(r); \
- } else { \
- region = r; \
- } \
- data.header.rcBound.top = y; \
- }
-
-#define AddSpan \
- { \
- data.rect[n].left=prev1; \
- data.rect[n].top=y; \
- data.rect[n].right=x-1+1; \
- data.rect[n].bottom=y+1; \
- n++; \
- if (n == MAXRECT) { \
- FlushSpans \
- n=0; \
- } \
- }
-
- data.header.rcBound.top = 0;
- data.header.rcBound.left = 0;
- data.header.rcBound.right = image.width()-1;
- int n = 0;
-
- int zero = 0x00;
-
- int x, y;
- for (y = 0; y < image.height(); ++y) {
- uchar *line = image.scanLine(y);
- int w = image.width();
- uchar all=zero;
- int prev1 = -1;
- for (x = 0; x < w;) {
- uchar byte = line[x/8];
- if (x > w - 8 || byte != all) {
- for (int b = 8; b > 0 && x < w; --b) {
- if (!(byte & 0x01) == !all) {
- // More of the same
- } else {
- // A change.
- if (all != zero) {
- AddSpan;
- all = zero;
- } else {
- prev1 = x;
- all = ~zero;
- }
- }
- byte >>= 1;
- ++x;
- }
- } else {
- x += 8;
- }
- }
- if (all != zero) {
- AddSpan;
- }
- }
- if (n) {
- FlushSpans;
- }
-
- if (!region) {
- // Surely there is some better way.
- region = qt_tryCreateRegion(QRegion::Rectangle, 0,0,1,1);
- CombineRgn(region, region, region, RGN_XOR);
- }
- return region;
-}
-
-#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp
-QRegion::QRegion(const QBitmap &bm)
-{
- if (bm.isNull()) {
- d = &shared_empty;
- d->ref.ref();
- } else {
- d = new QRegionData;
- d->ref = 1;
- d->rgn = qt_win_bitmapToRegion(bm);
- }
-}
-#endif
-
-void QRegion::cleanUp(QRegion::QRegionData *x)
-{
- if (x->rgn)
- DeleteObject(x->rgn);
- delete x;
-}
-
-QRegion::~QRegion()
-{
- if (!d->ref.deref())
- cleanUp(d);
-}
-
-QRegion &QRegion::operator=(const QRegion &r)
-{
- r.d->ref.ref();
- if (!d->ref.deref())
- cleanUp(d);
- d = r.d;
- return *this;
-}
-
-
-QRegion QRegion::copy() const
-{
- QRegion r;
- QRegionData *x = new QRegionData;
- x->ref = 1;
- if (d->rgn) {
- x->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 2, 2);
- CombineRgn(x->rgn, d->rgn, 0, RGN_COPY);
- } else {
- x->rgn = 0;
- }
- if (!r.d->ref.deref())
- cleanUp(r.d);
- r.d = x;
- return r;
-}
-
-bool QRegion::isEmpty() const
-{
- return (d == &shared_empty || boundingRect().isEmpty());
-}
-
-
-bool QRegion::contains(const QPoint &p) const
-{
- return d->rgn ? PtInRegion(d->rgn, p.x(), p.y()) : false;
-}
-
-bool QRegion::contains(const QRect &r) const
-{
- if (!d->rgn)
- return false;
- RECT rect;
- SetRect(&rect, r.left(), r.top(), r.right(), r.bottom());
- return RectInRegion(d->rgn, &rect);
-}
-
-
-void QRegion::translate(int dx, int dy)
-{
- if (!d->rgn || (dx == 0 && dy == 0))
- return;
- detach();
- OffsetRgn(d->rgn, dx, dy);
-}
-
-
-#define RGN_NOP -1
-
-// Duplicates of those in qregion.cpp
-#define QRGN_OR 6
-#define QRGN_AND 7
-#define QRGN_SUB 8
-#define QRGN_XOR 9
-
-/*
- Performs the actual OR, AND, SUB and XOR operation between regions.
- Sets the resulting region handle to 0 to indicate an empty region.
-*/
-
-QRegion QRegion::winCombine(const QRegion &r, int op) const
+QRegion qt_region_from_HRGN(HRGN rgn)
{
- int both=RGN_NOP,
- left=RGN_NOP,
- right=RGN_NOP;
- switch (op) {
- case QRGN_OR:
- both = RGN_OR;
- left = right = RGN_COPY;
- break;
- case QRGN_AND:
- both = RGN_AND;
- break;
- case QRGN_SUB:
- both = RGN_DIFF;
- left = RGN_COPY;
- break;
- case QRGN_XOR:
- both = RGN_XOR;
- left = right = RGN_COPY;
- break;
- default:
- qWarning("QRegion: Internal error in winCombine");
- }
-
- int allCombineRgnResults = NULLREGION;
- QRegion result;
- result.detach();
- result.d->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 0, 0);
- if (d->rgn && r.d->rgn)
- allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, r.d->rgn, both);
- else if (d->rgn && left != RGN_NOP)
- allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, d->rgn, left);
- else if (r.d->rgn && right != RGN_NOP)
- allCombineRgnResults = CombineRgn(result.d->rgn, r.d->rgn, r.d->rgn, right);
-
- if (allCombineRgnResults == NULLREGION || allCombineRgnResults == ERROR)
- result = QRegion();
-
- //##### do not delete this. A null pointer is different from an empty region in SelectClipRgn in qpainter_win! (M)
-// if (allCombineRgnResults == NULLREGION) {
-// if (result.data->rgn)
-// DeleteObject(result.data->rgn);
-// result.data->rgn = 0; // empty region
-// }
- return result;
-}
-
-QRegion QRegion::unite(const QRegion &r) const
-{
- if (!d->rgn)
- return r;
- if (!r.d->rgn)
- return *this;
- return winCombine(r, QRGN_OR);
-}
-
-QRegion QRegion::unite(const QRect &r) const
-{
- return unite(QRegion(r));
-}
-
-QRegion QRegion::intersect(const QRegion &r) const
-{
- if (!r.d->rgn || !d->rgn)
- return QRegion();
- return winCombine(r, QRGN_AND);
-}
-
-QRegion QRegion::subtract(const QRegion &r) const
-{
- if (!r.d->rgn || !d->rgn)
- return *this;
- return winCombine(r, QRGN_SUB);
-}
-
-QRegion QRegion::eor(const QRegion &r) const
-{
- if (!d->rgn)
- return r;
- if (!r.d->rgn)
- return *this;
- return winCombine(r, QRGN_XOR);
-}
-
-
-QRect QRegion::boundingRect() const
-{
- if (!d->rgn)
- return QRect();
- RECT r;
- if (GetRgnBox(d->rgn, &r) == NULLREGION)
- return QRect();
- else
- return QRect(r.left, r.top, r.right - r.left, r.bottom - r.top);
-}
-
-QVector<QRect> QRegion::rects() const
-{
- if (d->rgn == 0)
- return QVector<QRect>();
-
- int numBytes = GetRegionData(d->rgn, 0, 0);
+ int numBytes = GetRegionData(rgn, 0, 0);
if (numBytes == 0)
- return QVector<QRect>();
+ return QRegion();
char *buf = new char[numBytes];
if (buf == 0)
- return QVector<QRect>();
+ return QRegion();
RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf);
- if (GetRegionData(d->rgn, numBytes, rd) == 0) {
+ if (GetRegionData(rgn, numBytes, rd) == 0) {
delete [] buf;
- return QVector<QRect>();
+ return QRegion();
}
- QVector<QRect> a(rd->rdh.nCount);
+ QRegion region;
RECT *r = reinterpret_cast<RECT*>(rd->Buffer);
- for (int i = 0; i < a.size(); ++i) {
- a[i].setCoords(r->left, r->top, r->right - 1, r->bottom - 1);
+ for (int i = 0; i < rd->rdh.nCount; ++i) {
+ QRect rect;
+ rect.setCoords(r->left, r->top, r->right - 1, r->bottom - 1);
++r;
+ region |= rect;
}
delete [] buf;
- return a;
-}
-
-void QRegion::setRects(const QRect *rects, int num)
-{
- *this = QRegion();
- if (!rects || num == 0 || (num == 1 && rects->isEmpty()))
- return;
- for (int i = 0; i < num; ++i)
- *this |= rects[i];
-}
-
-int QRegion::numRects() const
-{
- if (d->rgn == 0)
- return 0;
-
- const int numBytes = GetRegionData(d->rgn, 0, 0);
- if (numBytes == 0)
- return 0;
-
- char *buf = new char[numBytes];
- if (buf == 0)
- return 0;
-
- RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf);
- if (GetRegionData(d->rgn, numBytes, rd) == 0) {
- delete[] buf;
- return 0;
- }
-
- const int n = rd->rdh.nCount;
- delete[] buf;
- return n;
+ return region;
}
-bool QRegion::operator==(const QRegion &r) const
+void qt_win_dispose_rgn(HRGN r)
{
- if (d == r.d)
- return true;
- if ((d->rgn == 0) ^ (r.d->rgn == 0)) // one is empty, not both
- return false;
- return d->rgn == 0 ? true // both empty
- : EqualRgn(d->rgn, r.d->rgn); // both non-empty
+ if (r)
+ DeleteObject(r);
}
-QRegion& QRegion::operator+=(const QRegion &r)
+static void qt_add_rect(HRGN &winRegion, QRect r)
{
- if (!r.d->rgn)
- return *this;
-
- if (!d->rgn) {
- *this = r;
- return *this;
+ HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
+ if (rgn) {
+ HRGN dest = CreateRectRgn(0,0,0,0);
+ int result = CombineRgn(dest, winRegion, rgn, RGN_OR);
+ if (result) {
+ DeleteObject(winRegion);
+ winRegion = dest;
+ }
+ DeleteObject(rgn);
}
-
- detach();
-
- int result;
- result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_OR);
- if (result == NULLREGION || result == ERROR)
- *this = QRegion();
-
- return *this;
-}
-
-QRegion& QRegion::operator-=(const QRegion &r)
-{
- if (!r.d->rgn || !d->rgn)
- return *this;
-
- detach();
-
- int result;
- result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_DIFF);
- if (result == NULLREGION || result == ERROR)
- *this = QRegion();
-
- return *this;
}
-QRegion& QRegion::operator&=(const QRegion &r)
+void QRegion::ensureHandle() const
{
- if (!d->rgn)
- return *this;
-
- if (!r.d->rgn) {
- *this = QRegion();
- return *this;
+ if (d->rgn)
+ DeleteObject(d->rgn);
+ d->rgn = CreateRectRgn(0,0,0,0);
+ if (d->qt_rgn) {
+ if (d->qt_rgn->numRects == 1) {
+ QRect r = d->qt_rgn->extents;
+ qt_add_rect(d->rgn, r);
+ return;
+ }
+ for (int i = 0;i < d->qt_rgn->numRects;i++) {
+ QRect r = d->qt_rgn->rects.at(i);
+ qt_add_rect(d->rgn, r);
+ }
}
-
- detach();
-
- int result;
- result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_AND);
- if (result == NULLREGION || result == ERROR)
- *this = QRegion();
-
- return *this;
-}
-
-bool qt_region_strictContains(const QRegion &region, const QRect &rect)
-{
- Q_UNUSED(region);
- Q_UNUSED(rect);
- return false;
}
-void QRegion::ensureHandle() const
-{
-}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp
index d8b0d9e..95f6ce3 100644
--- a/src/gui/painting/qwindowsurface_x11.cpp
+++ b/src/gui/painting/qwindowsurface_x11.cpp
@@ -154,7 +154,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect)
QX11PixmapData *oldData = static_cast<QX11PixmapData *>(d_ptr->device.pixmapData());
Q_ASSERT(oldData);
- if (!oldData->uninit && hasStaticContents()) {
+ if (!(oldData->flags & QX11PixmapData::Uninitialized) && hasStaticContents()) {
// Copy the content of the old pixmap into the new one.
QX11PixmapData *newData = new QX11PixmapData(QPixmapData::PixmapType);
newData->resize(size.width(), size.height());
@@ -175,7 +175,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect)
dx, dy, qMin(boundingRect.width(), size.width()),
qMin(boundingRect.height(), size.height()), dx, dy);
XFreeGC(X11->display, tmpGc);
- newData->uninit = false;
+ newData->flags &= ~QX11PixmapData::Uninitialized;
d_ptr->device = QPixmap(newData);
} else {
diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp
index 9560c4b..ad87354 100644
--- a/src/gui/styles/qwindowsxpstyle.cpp
+++ b/src/gui/styles/qwindowsxpstyle.cpp
@@ -134,6 +134,7 @@ static const int windowsRightBorder = 12; // right border on windows
// External function calls
extern Q_GUI_EXPORT HDC qt_win_display_dc();
+extern QRegion qt_region_from_HRGN(HRGN rgn);
@@ -445,6 +446,7 @@ bool QWindowsXPStylePrivate::isTransparent(XPThemeData &themeData)
themeData.stateId);
}
+
/*! \internal
Returns a QRegion of the region of the part
*/
@@ -456,12 +458,18 @@ QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData)
themeData.stateId, &rect, &hRgn)))
return QRegion();
- QRegion rgn = QRegion(0,0,1,1);
- const bool success = CombineRgn(rgn.handle(), hRgn, 0, RGN_COPY) != ERROR;
- DeleteObject(hRgn);
+ HRGN dest = CreateRectRgn(0, 0, 0, 0);
+ const bool success = CombineRgn(dest, hRgn, 0, RGN_COPY) != ERROR;
+
+ QRegion region;
+
if (success)
- return rgn;
- return QRegion();
+ region = qt_region_from_HRGN(dest);
+
+ DeleteObject(hRgn);
+ DeleteObject(dest);
+
+ return region;
}
/*! \internal
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index f6bfcbe..48d09ce 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -86,6 +86,7 @@
#include <private/qpixmapdata_gl_p.h>
#include <private/qglpixelbuffer_p.h>
#include <private/qwindowsurface_gl_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
#include "qcolormap.h"
#include "qfile.h"
#include "qlibrary.h"
@@ -1407,15 +1408,17 @@ QGLTextureCache::QGLTextureCache()
{
Q_ASSERT(qt_gl_texture_cache == 0);
qt_gl_texture_cache = this;
- qt_pixmap_cleanup_hook_64 = cleanupHook;
- qt_image_cleanup_hook_64 = cleanupHook;
+
+ QImagePixmapCleanupHooks::instance()->addPixmapHook(pixmapCleanupHook);
+ QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook);
}
QGLTextureCache::~QGLTextureCache()
{
qt_gl_texture_cache = 0;
- qt_pixmap_cleanup_hook_64 = 0;
- qt_image_cleanup_hook_64 = 0;
+
+ QImagePixmapCleanupHooks::instance()->removePixmapHook(pixmapCleanupHook);
+ QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook);
}
void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
@@ -1471,7 +1474,7 @@ QGLTextureCache* QGLTextureCache::instance()
a hook that removes textures from the cache when a pixmap/image
is deref'ed
*/
-void QGLTextureCache::cleanupHook(qint64 cacheKey)
+void QGLTextureCache::imageCleanupHook(qint64 cacheKey)
{
// ### remove when the GL texture cache becomes thread-safe
if (qApp->thread() != QThread::currentThread())
@@ -1481,6 +1484,24 @@ void QGLTextureCache::cleanupHook(qint64 cacheKey)
instance()->remove(cacheKey);
}
+
+void QGLTextureCache::pixmapCleanupHook(QPixmap* pixmap)
+{
+ // ### remove when the GL texture cache becomes thread-safe
+ if (qApp->thread() == QThread::currentThread()) {
+ const qint64 cacheKey = pixmap->cacheKey();
+ QGLTexture *texture = instance()->getTexture(cacheKey);
+ if (texture && texture->clean)
+ instance()->remove(cacheKey);
+ }
+#if defined(Q_WS_X11)
+ QPixmapData *pd = pixmap->data_ptr();
+ // Only need to delete the gl surface if the pixmap is about to be deleted
+ if (pd->ref == 0)
+ QGLContextPrivate::destroyGlSurfaceForPixmap(pd);
+#endif
+}
+
void QGLTextureCache::deleteIfEmpty()
{
if (instance()->size() == 0)
@@ -2021,11 +2042,11 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target,
#if defined(Q_WS_X11)
// Try to use texture_from_pixmap
if (pd->classId() == QPixmapData::X11Class) {
- QPixmap *thatPixmap = const_cast<QPixmap*>(&pixmap);
- texture = bindTextureFromNativePixmap(thatPixmap, key, canInvert);
+ texture = bindTextureFromNativePixmap(pd, key, canInvert);
if (texture) {
texture->clean = clean;
- boundPixmaps.insert(thatPixmap->data_ptr(), QPixmap(pixmap));
+ texture->boundPixmap = pd;
+ boundPixmaps.insert(pd, QPixmap(pixmap));
}
}
#endif
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 85dae0d..f21ab93 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -241,7 +241,9 @@ public:
quint32 gpm;
int screen;
QHash<QPixmapData*, QPixmap> boundPixmaps;
- QGLTexture *bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool internal);
+ QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key, bool canInvert);
+ static void destroyGlSurfaceForPixmap(QPixmapData*);
+ static void unbindPixmapFromTexture(QPixmapData*);
#endif
#if defined(Q_WS_MAC)
bool update;
@@ -423,7 +425,8 @@ public:
// is a current context - the context the pixmap was bound to a texture in.
// Otherwise the release doesn't do anything and you get BadDrawable errors
// when you come to delete the context.
- deleteBoundPixmap();
+ if (boundPixmap)
+ QGLContextPrivate::unbindPixmapFromTexture(boundPixmap);
#endif
glDeleteTextures(1, &id);
if (switch_context && current)
@@ -437,9 +440,9 @@ public:
bool clean;
bool yInverted; // NOTE: Y-Inverted textures are for internal use only!
#if defined(Q_WS_X11)
- Qt::HANDLE boundPixmap;
- void deleteBoundPixmap(); // in qgl_x11.cpp/qgl_x11egl.cpp
+ QPixmapData* boundPixmap;
#endif
+
};
class QGLTextureCache {
@@ -458,7 +461,8 @@ public:
static QGLTextureCache *instance();
static void deleteIfEmpty();
- static void cleanupHook(qint64 cacheKey);
+ static void imageCleanupHook(qint64 cacheKey);
+ static void pixmapCleanupHook(QPixmap* pixmap);
private:
QCache<qint64, QGLTexture> m_cache;
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index cf70991..4509a64 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -58,11 +58,16 @@
#include <private/qglpixelbuffer_p.h>
#endif
+// We always define GLX_EXT_texture_from_pixmap ourselves because
+// we can't trust system headers to do it properly
+#define GLX_EXT_texture_from_pixmap 1
+
#define INT8 dummy_INT8
#define INT32 dummy_INT32
#include <GL/glx.h>
#undef INT8
#undef INT32
+
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
@@ -90,7 +95,7 @@ extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
#define GLX_SAMPLES_ARB 100001
#endif
-#ifndef GLX_EXT_texture_from_pixmap
+#ifndef GLX_TEXTURE_2D_BIT_EXT
#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
@@ -1548,38 +1553,26 @@ void QGLExtensions::init()
}
}
-#if !defined(glXBindTexImageEXT)
+// 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*);
-static qt_glXBindTexImageEXT glXBindTexImageEXT = 0;
-#endif
-#if !defined(glXReleaseTexImageEXT)
typedef void (*qt_glXReleaseTexImageEXT)(Display*, GLXDrawable, int);
+static qt_glXBindTexImageEXT glXBindTexImageEXT = 0;
static qt_glXReleaseTexImageEXT glXReleaseTexImageEXT = 0;
-#endif
-static bool qt_resolved_texture_from_pixmap = false;
-QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool canInvert)
+bool qt_resolveTextureFromPixmap()
{
-#if !defined(Q_OS_LINUX)
- return 0;
-#else
- Q_Q(QGLContext);
-
- if (pm->data_ptr()->classId() != QPixmapData::X11Class)
- return 0;
- QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pm->data_ptr());
- const QX11Info *x11Info = qt_x11Info(pm);
+ static bool resolvedTextureFromPixmap = false;
+ if (!resolvedTextureFromPixmap) {
+ resolvedTextureFromPixmap = true;
- // Check to see if we have NPOT texture support
- // TODO: Use GLX_TEXTURE_RECTANGLE_EXT texture target on systems without npot textures
- if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) &&
- !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0))
- return 0;
-
-
- if (!qt_resolved_texture_from_pixmap) {
- qt_resolved_texture_from_pixmap = true;
+ // Check to see if we have NPOT texture support
+ if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) &&
+ !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0))
+ {
+ return false; // Can't use TFP without NPOT
+ }
QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
if (glxExt.contains(QLatin1String("GLX_EXT_texture_from_pixmap"))) {
@@ -1601,81 +1594,139 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pm, const qi
}
}
- if (!glXBindTexImageEXT)
- return 0;
+ return glXBindTexImageEXT && glXReleaseTexImageEXT;
+}
+#endif //defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
+
+QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, const qint64 key, bool canInvert)
+{
#if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
return 0;
#else
- GLXFBConfig *configList = 0;
- GLXFBConfig glxPixmapConfig;
- int configCount = 0;
- bool hasAlpha = pixmapData->hasAlphaChannel();
-
- int configAttribs[] = {
- hasAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT, True,
- GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
- GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
- // QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can:
- GLX_Y_INVERTED_EXT, canInvert ? GLX_DONT_CARE : False,
- XNone
-// GLX_BIND_TO_MIPMAP_TEXTURE_EXT, False,
-// GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_1D_BIT_EXT or GLX_TEXTURE_2D_BIT_EXT or GLX_TEXTURE_RECTANGLE_BIT_EXT
- };
- configList = glXChooseFBConfig(x11Info->display(), x11Info->screen(), configAttribs, &configCount);
- if (!configList)
- return 0;
- glxPixmapConfig = configList[0];
- XFree(configList);
-
- GLXPixmap glxPixmap;
- int pixmapAttribs[] = {
- GLX_TEXTURE_FORMAT_EXT, hasAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT,
- GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
- GLX_MIPMAP_TEXTURE_EXT, False,
- XNone
-// GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT or GLX_TEXTURE_FORMAT_RGB_EXT or GLX_TEXTURE_FORMAT_NONE_EXT,
-// GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT or GLX_TEXTURE_RECTANGLE_EXT,
-// GLX_MIPMAP_TEXTURE_EXT, True or False,
- };
+ Q_Q(QGLContext);
- // Wrap the X Pixmap into a GLXPixmap:
- glxPixmap = glXCreatePixmap(x11Info->display(), glxPixmapConfig, pixmapData->handle(), pixmapAttribs);
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
- if (!glxPixmap)
+ if (!qt_resolveTextureFromPixmap())
return 0;
- int yInverted;
- glXGetFBConfigAttrib(x11Info->display(), glxPixmapConfig, GLX_Y_INVERTED_EXT, &yInverted);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ const QX11Info &x11Info = pixmapData->xinfo;
+
+ // Store the configs (Can be static because configs aren't dependent on current context)
+ static GLXFBConfig glxRGBPixmapConfig = 0;
+ static bool RGBConfigInverted = false;
+ static GLXFBConfig glxRGBAPixmapConfig = 0;
+ static bool RGBAConfigInverted = false;
+
+ bool hasAlpha = pixmapData->hasAlphaChannel();
+
+ // Check to see if we need a config
+ if ( (hasAlpha && !glxRGBAPixmapConfig) || (!hasAlpha && !glxRGBPixmapConfig) ) {
+ GLXFBConfig *configList = 0;
+ int configCount = 0;
+
+ int configAttribs[] = {
+ hasAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT, True,
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+ GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
+ // QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can:
+ GLX_Y_INVERTED_EXT, canInvert ? GLX_DONT_CARE : False,
+ XNone
+ };
+ configList = glXChooseFBConfig(x11Info.display(), x11Info.screen(), configAttribs, &configCount);
+ if (!configList)
+ return 0;
+
+ int yInv;
+ glXGetFBConfigAttrib(x11Info.display(), configList[0], GLX_Y_INVERTED_EXT, &yInv);
+
+ if (hasAlpha) {
+ glxRGBAPixmapConfig = configList[0];
+ RGBAConfigInverted = yInv;
+ }
+ else {
+ glxRGBPixmapConfig = configList[0];
+ RGBConfigInverted = yInv;
+ }
+
+ XFree(configList);
+ }
+
+ // Check to see if the surface is still valid
+ if (pixmapData->gl_surface &&
+ hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
+ {
+ // Surface is invalid!
+ destroyGlSurfaceForPixmap(pixmapData);
+ }
+
+ // Check to see if we need a surface
+ if (!pixmapData->gl_surface) {
+ GLXPixmap glxPixmap;
+ int pixmapAttribs[] = {
+ GLX_TEXTURE_FORMAT_EXT, hasAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT,
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+ GLX_MIPMAP_TEXTURE_EXT, False, // Maybe needs to be don't care
+ XNone
+ };
+
+ // Wrap the X Pixmap into a GLXPixmap:
+ glxPixmap = glXCreatePixmap(x11Info.display(),
+ hasAlpha ? glxRGBAPixmapConfig : glxRGBPixmapConfig,
+ pixmapData->handle(), pixmapAttribs);
+
+ if (!glxPixmap)
+ return 0;
+
+ pixmapData->gl_surface = (Qt::HANDLE)glxPixmap;
+
+ // Make sure the cleanup hook gets called so we can delete the glx pixmap
+ pixmapData->is_cached = true;
+ }
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
- glXBindTexImageEXT(x11Info->display(), glxPixmap, GLX_FRONT_LEFT_EXT, 0);
+ glXBindTexImageEXT(x11Info.display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT, 0);
glBindTexture(GL_TEXTURE_2D, textureId);
- QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, canInvert, yInverted);
- texture->boundPixmap = glxPixmap;
+ QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, canInvert, false);
+ texture->yInverted = (hasAlpha && RGBAConfigInverted) || (!hasAlpha && RGBConfigInverted);
+ if (texture->yInverted)
+ pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
// We assume the cost of bound pixmaps is zero
QGLTextureCache::instance()->insert(q, key, texture, 0);
return texture;
#endif //!defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX)
-#endif //!defined(Q_OS_LINUX
}
-void QGLTexture::deleteBoundPixmap()
+
+void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
{
-#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) && defined(Q_OS_LINUX)
- if (boundPixmap) {
- glXReleaseTexImageEXT(QX11Info::display(), boundPixmap, GLX_FRONT_LEFT_EXT);
- glXDestroyPixmap(QX11Info::display(), boundPixmap);
- boundPixmap = 0;
+#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ if (pixmapData->gl_surface) {
+ glXDestroyPixmap(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface);
+ pixmapData->gl_surface = 0;
}
#endif
}
+void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
+{
+#if defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX)
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
+ Q_ASSERT(QGLContext::currentContext());
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ if (pixmapData->gl_surface)
+ glXReleaseTexImageEXT(QX11Info::display(), (GLXPixmap)pixmapData->gl_surface, GLX_FRONT_LEFT_EXT);
+#endif
+}
QT_END_NAMESPACE
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
index c6904fe..5ab3647 100644
--- a/src/opengl/qgl_x11egl.cpp
+++ b/src/opengl/qgl_x11egl.cpp
@@ -41,15 +41,16 @@
#include "qgl.h"
#include <private/qt_x11_p.h>
+#include <private/qpixmap_x11_p.h>
#include <private/qgl_p.h>
#include <private/qpaintengine_opengl_p.h>
#include "qgl_egl_p.h"
#include "qcolormap.h"
+#include <QDebug>
QT_BEGIN_NAMESPACE
-
bool QGLFormat::hasOpenGL()
{
return true;
@@ -486,15 +487,175 @@ void QGLWidgetPrivate::recreateEglSurface(bool force)
}
}
-QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool canInvert)
+
+QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key, bool canInvert)
{
- // TODO
- return 0;
+ Q_Q(QGLContext);
+
+ Q_ASSERT(pd->classId() == QPixmapData::X11Class);
+
+ static bool checkedForTFP = false;
+ static bool haveTFP = false;
+
+ if (!checkedForTFP) {
+ // Check for texture_from_pixmap egl extension
+ checkedForTFP = true;
+ if (eglContext->hasExtension("EGL_NOKIA_texture_from_pixmap") ||
+ eglContext->hasExtension("EGL_EXT_texture_from_pixmap"))
+ {
+ qDebug("Found texture_from_pixmap EGL extension!");
+ haveTFP = true;
+ }
+ }
+
+ if (!haveTFP)
+ return 0;
+
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pd);
+
+ bool hasAlpha = pixmapData->hasAlphaChannel();
+
+ // Check to see if the surface is still valid
+ if (pixmapData->gl_surface &&
+ hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
+ {
+ // Surface is invalid!
+ destroyGlSurfaceForPixmap(pixmapData);
+ }
+
+ EGLint pixmapAttribs[] = {
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
+ EGL_TEXTURE_FORMAT, hasAlpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB,
+ EGL_NONE
+ };
+ Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure!
+ if (pixmapData->gl_surface == 0)
+ pixmapData->gl_surface = (Qt::HANDLE)EGL_NO_SURFACE;
+ EGLSurface pixmapSurface = (EGLSurface)pixmapData->gl_surface;
+ static EGLConfig pixmapRGBConfig = 0;
+ static EGLConfig pixmapRGBAConfig = 0;
+
+ // Check to see if we need to find a config
+ if ((hasAlpha && !pixmapRGBAConfig) || (!hasAlpha && !pixmapRGBConfig) ) {
+ const EGLint configAttribs[] = {
+ EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_DEPTH_SIZE, 0,
+ hasAlpha ? EGL_BIND_TO_TEXTURE_RGBA : EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE,
+ EGL_NONE
+ };
+
+ EGLint configCount = 0;
+ eglChooseConfig(eglContext->display(), configAttribs, 0, 256, &configCount);
+ if (configCount == 0) {
+ haveTFP = false;
+ qWarning("bindTextureFromNativePixmap() - Couldn't find a suitable config");
+ return 0;
+ }
+
+ EGLConfig *configList = new EGLConfig[configCount];
+ eglChooseConfig(eglContext->display(), configAttribs, configList, configCount, &configCount);
+ Q_ASSERT(configCount);
+
+ // Try to create a pixmap surface for each config until one works
+ for (int i = 0; i < configCount; ++i) {
+ pixmapSurface = eglCreatePixmapSurface(eglContext->display(), configList[i],
+ (EGLNativePixmapType) pixmapData->handle(),
+ pixmapAttribs);
+ if (pixmapSurface != EGL_NO_SURFACE) {
+ // Got one!
+ qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB")
+ << "config (" << int(configList[i]) << ") to create a pixmap surface";
+ if (hasAlpha)
+ pixmapRGBAConfig = configList[i];
+ else
+ pixmapRGBConfig = configList[i];
+ pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
+ break;
+ }
+ }
+ delete configList;
+
+ if ((hasAlpha && !pixmapRGBAConfig) || (!hasAlpha && !pixmapRGBConfig) ) {
+ qDebug("Couldn't create a pixmap surface with any of the provided configs");
+ haveTFP = false;
+ return 0;
+ }
+ }
+
+ if (pixmapSurface == EGL_NO_SURFACE) {
+ pixmapSurface = eglCreatePixmapSurface(eglContext->display(),
+ hasAlpha? pixmapRGBAConfig : pixmapRGBConfig,
+ (EGLNativePixmapType) pixmapData->handle(),
+ pixmapAttribs);
+ if (pixmapSurface == EGL_NO_SURFACE) {
+ qWarning("Failed to create a pixmap surface using config %d",
+ (int)(hasAlpha? pixmapRGBAConfig : pixmapRGBConfig));
+ haveTFP = false;
+ return 0;
+ }
+ pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface;
+ }
+
+ // Make sure the cleanup hook gets called so we can delete the glx pixmap
+ pixmapData->is_cached = true;
+ Q_ASSERT(pixmapData->gl_surface);
+
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
+ // bind the egl pixmap surface to a texture
+ EGLBoolean success;
+ success = eglBindTexImage(eglContext->display(), pixmapSurface, EGL_BACK_BUFFER);
+ if (success == EGL_FALSE) {
+ qWarning() << "eglBindTexImage() failed:" << eglContext->errorString(eglGetError());
+ eglDestroySurface(eglContext->display(), pixmapSurface);
+ pixmapData->gl_surface = (Qt::HANDLE)EGL_NO_SURFACE;
+ haveTFP = false;
+ return 0;
+ }
+
+ QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, canInvert, true);
+ pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
+
+ // We assume the cost of bound pixmaps is zero
+ QGLTextureCache::instance()->insert(q, key, texture, 0);
+
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ return texture;
}
-void QGLTexture::deleteBoundPixmap()
+void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
{
- //TODO
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ if (pixmapData->gl_surface) {
+ EGLBoolean success;
+ success = eglDestroySurface(QEglContext::defaultDisplay(0), (EGLSurface)pixmapData->gl_surface);
+ if (success == EGL_FALSE) {
+ qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: "
+ << QEglContext::errorString(eglGetError());
+ }
+ pixmapData->gl_surface = 0;
+ }
+}
+
+void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
+{
+ Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
+ QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
+ if (pixmapData->gl_surface) {
+ EGLBoolean success;
+ success = eglReleaseTexImage(QEglContext::defaultDisplay(0),
+ (EGLSurface)pixmapData->gl_surface,
+ EGL_BACK_BUFFER);
+ if (success == EGL_FALSE) {
+ qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: "
+ << QEglContext::errorString(eglGetError());
+ }
+ }
}
QT_END_NAMESPACE
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
index b264ac0..2ed890b 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
@@ -53,6 +53,7 @@
#include <qmath.h>
#include <private/qpixmapdata_p.h>
#include <private/qpixmap_raster_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
class SurfaceCache;
class QDirectFBPaintEnginePrivate : public QRasterPaintEnginePrivate
@@ -699,9 +700,7 @@ void QDirectFBPaintEngine::initImageCache(int size)
{
Q_ASSERT(size >= 0);
imageCache.setMaxCost(size);
- typedef void (*_qt_image_cleanup_hook_64)(qint64);
- extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
- qt_image_cleanup_hook_64 = ::cachedImageCleanupHook;
+ QImagePixmapCleanupHooks::instance()->addImageHook(cachedImageCleanupHook);
}
#endif // QT_DIRECTFB_IMAGECACHE
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 797595f..0ba7d53 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -429,7 +429,7 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
{
def->isVirtual = false;
//skip modifiers and attributes
- while (test(INLINE) || test(STATIC) ||
+ while (test(EXPLICIT) || test(INLINE) || test(STATIC) ||
(test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual
|| testFunctionAttribute(def)) {}
bool tilde = test(TILDE);
diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp
index d66791f..488f068 100644
--- a/tests/auto/moc/tst_moc.cpp
+++ b/tests/auto/moc/tst_moc.cpp
@@ -1157,6 +1157,13 @@ void tst_Moc::constructors()
QObject *o3 = mo->newInstance(Q_ARG(QString, str));
QVERIFY(o3 != 0);
QCOMPARE(qobject_cast<CtorTestClass*>(o3)->m_str, str);
+
+ {
+ //explicit constructor
+ QObject *o = QObject::staticMetaObject.newInstance();
+ QVERIFY(o);
+ delete o;
+ }
}
#include "task234909.h"