diff options
Diffstat (limited to 'src/gui')
86 files changed, 2604 insertions, 21718 deletions
diff --git a/src/gui/configure.json b/src/gui/configure.json index 4de159d97a..9d9d312048 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -1638,15 +1638,9 @@ "condition": "features.imageformat_xpm", "output": [ "publicFeature", "feature" ] }, - "shortcut": { - "label": "QShortcut", - "purpose": "Provides keyboard accelerators and shortcuts.", - "section": "Kernel", - "output": [ "publicFeature", "feature" ] - }, "action": { - "label": "QAction", - "purpose": "Provides widget actions.", + "label": "Q(Gui)Action(Group)", + "purpose": "Provides abstract user interface actions.", "section": "Kernel", "output": [ "publicFeature", "feature" ] }, diff --git a/src/gui/doc/snippets/picture/picture.cpp b/src/gui/doc/snippets/picture/picture.cpp index 863476fdbf..807c263b19 100644 --- a/src/gui/doc/snippets/picture/picture.cpp +++ b/src/gui/doc/snippets/picture/picture.cpp @@ -80,82 +80,3 @@ int main() painter.end(); // painting done //! [1] } - - QPicture myPicture; - { - // FORMATS -//! [2] - const QStringList list = QPicture::inputFormatList(); - for (const QString &string : list) - myProcessing(string); -//! [2] - } - - { - // OUTPUT -//! [3] - const QStringList list = QPicture::outputFormatList(); - for (const QString &string : list) - myProcessing(string); -//! [3] - } - - { - // PIC READ -//! [4] - QPictureIO iio; - QPixmap pixmap; - iio.setFileName("vegeburger.pic"); - if (iio.read()) { // OK - QPicture picture = iio.picture(); - QPainter painter(&pixmap); - painter.drawPicture(0, 0, picture); - } -//! [4] - } - - { - QPixmap pixmap; - // PIC WRITE -//! [5] - QPictureIO iio; - QPicture picture; - QPainter painter(&picture); - painter.drawPixmap(0, 0, pixmap); - iio.setPicture(picture); - iio.setFileName("vegeburger.pic"); - iio.setFormat("PIC"); - if (iio.write()) - return true; // returned true if written successfully -//! [5] - } - -} - -// SVG READ -//! [6] -void readSVG(QPictureIO *picture) -{ - // read the picture using the picture->ioDevice() -} -//! [6] - -// SVG WRITE -//! [7] -void writeSVG(QPictureIO *picture) -{ - // write the picture using the picture->ioDevice() -} -//! [7] - -// USE SVG -void foo() { - -//! [8] - // add the SVG picture handler - // ... -//! [8] - QPictureIO::defineIOHandler("SVG", 0, 0, readSVG, writeSVG); - // ... - -} diff --git a/src/gui/doc/src/dontdocument.qdoc b/src/gui/doc/src/dontdocument.qdoc index b360acefc1..6b50daba88 100644 --- a/src/gui/doc/src/dontdocument.qdoc +++ b/src/gui/doc/src/dontdocument.qdoc @@ -27,7 +27,7 @@ /*! \dontdocument (QTypeInfo QScreenOrientationChangeEvent QApplicationStateChangeEvent - QImageTextKeyLang QMetaTypeId QAbstractUndoItem + QMetaTypeId QAbstractUndoItem QOpenGLVersionStatus QOpenGLVersionFunctionsBackend QOpenGLVersionFunctionsStorage diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index 1f42f28d1e..760b737ec3 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -14,7 +14,6 @@ HEADERS += \ image/qpaintengine_pic_p.h \ image/qpicture.h \ image/qpicture_p.h \ - image/qpictureformatplugin.h \ image/qpixmap.h \ image/qpixmap_raster_p.h \ image/qpixmap_blitter_p.h \ @@ -38,7 +37,6 @@ SOURCES += \ image/qimagewriter.cpp \ image/qpaintengine_pic.cpp \ image/qpicture.cpp \ - image/qpictureformatplugin.cpp \ image/qpixmap.cpp \ image/qpixmapcache.cpp \ image/qplatformpixmap.cpp \ @@ -59,9 +57,6 @@ win32:!winrt: SOURCES += image/qpixmap_win.cpp darwin: OBJECTIVE_SOURCES += image/qimage_darwin.mm -NO_PCH_SOURCES += image/qimage_compat.cpp -false: SOURCES += $$NO_PCH_SOURCES # Hack for QtCreator - # Built-in image format support HEADERS += \ image/qbmphandler_p.h \ diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 1166eb5023..74dc81e365 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1381,11 +1381,7 @@ int QImage::colorCount() const \sa colorTable(), setColor(), {QImage#Image Transformations}{Image Transformations} */ -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) void QImage::setColorTable(const QVector<QRgb> &colors) -#else -void QImage::setColorTable(const QVector<QRgb> colors) -#endif { if (!d) return; @@ -1395,11 +1391,7 @@ void QImage::setColorTable(const QVector<QRgb> colors) if (!d) return; -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) d->colortable = colors; -#else - d->colortable = std::move(const_cast<QVector<QRgb>&>(colors)); -#endif d->has_alpha_clut = false; for (int i = 0; i < d->colortable.size(); ++i) { if (qAlpha(d->colortable.at(i)) != 255) { @@ -1472,25 +1464,6 @@ void QImage::setDevicePixelRatio(qreal scaleFactor) d->devicePixelRatio = scaleFactor; } -#if QT_DEPRECATED_SINCE(5, 10) -/*! - \since 4.6 - \obsolete - Returns the number of bytes occupied by the image data. - - Note this method should never be called on an image larger than 2 gigabytes. - Instead use sizeInBytes(). - - \sa sizeInBytes(), bytesPerLine(), bits(), {QImage#Image Information}{Image - Information} -*/ -int QImage::byteCount() const -{ - Q_ASSERT(!d || d->nbytes < std::numeric_limits<int>::max()); - return d ? int(d->nbytes) : 0; -} -#endif - /*! \since 5.10 Returns the image data size in bytes. @@ -1510,17 +1483,10 @@ qsizetype QImage::sizeInBytes() const \sa scanLine() */ -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) qsizetype QImage::bytesPerLine() const { return d ? d->bytes_per_line : 0; } -#else -int QImage::bytesPerLine() const -{ - return d ? d->bytes_per_line : 0; -} -#endif /*! @@ -4054,71 +4020,10 @@ void QImage::setText(const QString &key, const QString &value) } /*! - \fn QString QImage::text(const char* key, const char* language) const - \obsolete - - Returns the text recorded for the given \a key in the given \a - language, or in a default language if \a language is \nullptr. - - Use text() instead. - - The language the text is recorded in is no longer relevant since - the text is always set using QString and UTF-8 representation. -*/ - -/*! - \fn QString QImage::text(const QImageTextKeyLang& keywordAndLanguage) const - \overload - \obsolete - - Returns the text recorded for the given \a keywordAndLanguage. - - Use text() instead. - - The language the text is recorded in is no longer relevant since - the text is always set using QString and UTF-8 representation. -*/ - -/*! - \fn void QImage::setText(const char* key, const char* language, const QString& text) - \obsolete - - Sets the image text to the given \a text and associate it with the - given \a key. The text is recorded in the specified \a language, - or in a default language if \a language is \nullptr. - - Use setText() instead. - - The language the text is recorded in is no longer relevant since - the text is always set using QString and UTF-8 representation. - - \omit - Records string \a for the keyword \a key. The \a key should be - a portable keyword recognizable by other software - some suggested - values can be found in - \l{http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html#C.Anc-text} - {the PNG specification}. \a s can be any text. \a lang should - specify the language code (see - \l{http://www.rfc-editor.org/rfc/rfc1766.txt}{RFC 1766}) or \nullptr. - \endomit -*/ - -/* - Sets the image bits to the \a pixmap contents and returns a - reference to the image. - - If the image shares data with other images, it will first - dereference the shared data. - - Makes a call to QPixmap::convertToImage(). -*/ - -/*! \internal Used by QPainter to retrieve a paint engine for the image. */ - QPaintEngine *QImage::paintEngine() const { if (!d) @@ -4364,22 +4269,6 @@ bool qt_xForm_helper(const QTransform &trueMat, int xoffset, int type, int depth #undef IWX_LSB #undef IWX_PIX -/*! \fn int QImage::serialNumber() const - \obsolete - Returns a number that identifies the contents of this - QImage object. Distinct QImage objects can only have the same - serial number if they refer to the same contents (but they don't - have to). - - Use cacheKey() instead. - - \warning The serial number doesn't necessarily change when the - image is altered. This means that it may be dangerous to use - it as a cache key. - - \sa operator==() -*/ - /*! Returns a number that identifies the contents of this QImage object. Distinct QImage objects can only have the same key if they @@ -5085,50 +4974,6 @@ QDebug operator<<(QDebug dbg, const QImage &i) } #endif -/*! - \fn void QImage::setNumColors(int n) - \obsolete - - Resizes the color table to contain \a n entries. - - \sa setColorCount() - */ - -/*! - \fn int QImage::numBytes() const - \obsolete - - Returns the number of bytes occupied by the image data. - - \sa sizeInBytes() - */ - -/*! - \fn QStringList QImage::textLanguages() const - \obsolete - - Returns the language identifiers for which some texts are recorded. - Note that if you want to iterate over the list, you should iterate over a copy. - - The language the text is recorded in is no longer relevant since the text is - always set using QString and UTF-8 representation. - - \sa textKeys() - */ - -/*! - \fn QList<QImageTextKeyLang> QImage::textList() const - \obsolete - - Returns a list of QImageTextKeyLang objects that enumerate all the texts - key/language pairs set for this image. - - The language the text is recorded in is no longer relevant since the text - is always set using QString and UTF-8 representation. - - \sa textKeys() - */ - static Q_CONSTEXPR QPixelFormat pixelformats[] = { //QImage::Format_Invalid: QPixelFormat(), diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 115071c16e..b8df4b83d1 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -50,10 +50,6 @@ #include <QtCore/qrect.h> #include <QtCore/qstring.h> -#if QT_DEPRECATED_SINCE(5, 0) -#include <QtCore/qstringlist.h> -#endif - #if defined(Q_OS_DARWIN) || defined(Q_QDOC) Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGImage); #endif @@ -68,31 +64,9 @@ class QMatrix; class QStringList; class QTransform; class QVariant; -template <class T> class QList; template <class T> class QVector; struct QImageData; -class QImageDataMisc; // internal -#if QT_DEPRECATED_SINCE(5, 0) -class QImageTextKeyLang { -public: - QT_DEPRECATED QImageTextKeyLang(const char* k, const char* l) : key(k), lang(l) { } - QT_DEPRECATED QImageTextKeyLang() { } - - QByteArray key; - QByteArray lang; - - bool operator< (const QImageTextKeyLang& other) const - { return key < other.key || (key==other.key && lang < other.lang); } - bool operator== (const QImageTextKeyLang& other) const - { return key==other.key && lang==other.lang; } - inline bool operator!= (const QImageTextKeyLang &other) const - { return !operator==(other); } -private: - friend class QImage; - QImageTextKeyLang(bool /*dummy*/) {} -}; -#endif typedef void (*QImageCleanupFunction)(void*); @@ -179,7 +153,6 @@ public: Format format() const; -#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QIMAGE_COMPAT_CPP) Q_REQUIRED_RESULT Q_ALWAYS_INLINE QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) const & { return convertToFormat_helper(f, flags); } Q_REQUIRED_RESULT Q_ALWAYS_INLINE QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) && @@ -189,9 +162,6 @@ public: else return convertToFormat_helper(f, flags); } -#else - Q_REQUIRED_RESULT QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) const; -#endif Q_REQUIRED_RESULT QImage convertToFormat(Format f, const QVector<QRgb> &colorTable, Qt::ImageConversionFlags flags = Qt::AutoColor) const; bool reinterpretAsFormat(Format f); @@ -217,19 +187,12 @@ public: const uchar *bits() const; const uchar *constBits() const; -#if QT_DEPRECATED_SINCE(5, 10) - QT_DEPRECATED_X("Use sizeInBytes") int byteCount() const; -#endif qsizetype sizeInBytes() const; uchar *scanLine(int); const uchar *scanLine(int) const; const uchar *constScanLine(int) const; -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) qsizetype bytesPerLine() const; -#else - int bytesPerLine() const; -#endif bool valid(int x, int y) const; bool valid(const QPoint &pt) const; @@ -250,11 +213,7 @@ public: void setPixelColor(const QPoint &pt, const QColor &c); QVector<QRgb> colorTable() const; -#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) void setColorTable(const QVector<QRgb> &colors); -#else - void setColorTable(const QVector<QRgb> colors); -#endif qreal devicePixelRatio() const; void setDevicePixelRatio(qreal scaleFactor); @@ -286,7 +245,6 @@ public: static QMatrix trueMatrix(const QMatrix &, int w, int h); QImage transformed(const QTransform &matrix, Qt::TransformationMode mode = Qt::FastTransformation) const; static QTransform trueMatrix(const QTransform &, int w, int h); -#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QIMAGE_COMPAT_CPP) QImage mirrored(bool horizontally = false, bool vertically = true) const & { return mirrored_helper(horizontally, vertically); } QImage &&mirrored(bool horizontally = false, bool vertically = true) && @@ -295,10 +253,6 @@ public: { return rgbSwapped_helper(); } QImage &&rgbSwapped() && { rgbSwapped_inplace(); return std::move(*this); } -#else - QImage mirrored(bool horizontally = false, bool vertically = true) const; - QImage rgbSwapped() const; -#endif void invertPixels(InvertMode = InvertRgb); QColorSpace colorSpace() const; @@ -321,9 +275,6 @@ public: inline static QImage fromData(const QByteArray &data, const char *format = nullptr) { return fromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), format); } -#if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED inline int serialNumber() const { return cacheKey() >> 32; } -#endif qint64 cacheKey() const; QPaintEngine *paintEngine() const override; @@ -349,20 +300,6 @@ public: CGImageRef toCGImage() const Q_DECL_CF_RETURNS_RETAINED; #endif -#if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED inline QString text(const char *key, const char *lang = nullptr) const; - QT_DEPRECATED inline QList<QImageTextKeyLang> textList() const; - QT_DEPRECATED inline QStringList textLanguages() const; - QT_DEPRECATED inline QString text(const QImageTextKeyLang&) const; - QT_DEPRECATED inline void setText(const char* key, const char* lang, const QString&); -#endif - -#if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED inline int numColors() const; - QT_DEPRECATED inline void setNumColors(int); - QT_DEPRECATED inline int numBytes() const; -#endif - protected: virtual int metric(PaintDeviceMetric metric) const override; QImage mirrored_helper(bool horizontal, bool vertical) const; @@ -397,99 +334,6 @@ inline void QImage::setPixel(const QPoint &pt, uint index_or_rgb) { setPixel(pt. inline QColor QImage::pixelColor(const QPoint &pt) const { return pixelColor(pt.x(), pt.y()); } inline void QImage::setPixelColor(const QPoint &pt, const QColor &c) { setPixelColor(pt.x(), pt.y(), c); } -#if QT_DEPRECATED_SINCE(5, 0) - -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - -inline QString QImage::text(const char* key, const char* lang) const -{ - if (!d) - return QString(); - QString k = QString::fromLatin1(key); - if (lang && *lang) - k += QLatin1Char('/') + QString::fromLatin1(lang); - return text(k); -} - -inline QList<QImageTextKeyLang> QImage::textList() const -{ - QList<QImageTextKeyLang> imageTextKeys; - if (!d) - return imageTextKeys; - QStringList keys = textKeys(); - for (int i = 0; i < keys.size(); ++i) { - int index = keys.at(i).indexOf(QLatin1Char('/')); - if (index > 0) { - QImageTextKeyLang tkl(true); - tkl.key = keys.at(i).left(index).toLatin1(); - tkl.lang = keys.at(i).mid(index+1).toLatin1(); - imageTextKeys += tkl; - } - } - - return imageTextKeys; -} - -inline QStringList QImage::textLanguages() const -{ - if (!d) - return QStringList(); - QStringList keys = textKeys(); - QStringList languages; - for (int i = 0; i < keys.size(); ++i) { - int index = keys.at(i).indexOf(QLatin1Char('/')); - if (index > 0) - languages += keys.at(i).mid(index+1); - } - - return languages; -} - -inline QString QImage::text(const QImageTextKeyLang&kl) const -{ - if (!d) - return QString(); - QString k = QString::fromLatin1(kl.key.constData()); - if (!kl.lang.isEmpty()) - k += QLatin1Char('/') + QString::fromLatin1(kl.lang.constData()); - return text(k); -} - -inline void QImage::setText(const char* key, const char* lang, const QString &s) -{ - if (!d) - return; - detach(); - - // In case detach() ran out of memory - if (!d) - return; - - QString k = QString::fromLatin1(key); - if (lang && *lang) - k += QLatin1Char('/') + QString::fromLatin1(lang); - setText(k, s); -} - -QT_WARNING_POP - -inline int QImage::numColors() const -{ - return colorCount(); -} - -inline void QImage::setNumColors(int n) -{ - setColorCount(n); -} - -inline int QImage::numBytes() const -{ - return int(sizeInBytes()); -} -#endif - // QImage stream functions #if !defined(QT_NO_DATASTREAM) diff --git a/src/gui/image/qimage_compat.cpp b/src/gui/image/qimage_compat.cpp deleted file mode 100644 index ba31a9ac9b..0000000000 --- a/src/gui/image/qimage_compat.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifdef QIMAGE_H -# error "This file cannot be used with precompiled headers" -#endif -#define QT_COMPILING_QIMAGE_COMPAT_CPP - -#include "qimage.h" - -QT_BEGIN_NAMESPACE - -// These implementations must be the same as the inline versions in qimage.h - -QImage QImage::convertToFormat(Format f, Qt::ImageConversionFlags flags) const -{ - return convertToFormat_helper(f, flags); -} - -QImage QImage::mirrored(bool horizontally, bool vertically) const -{ - return mirrored_helper(horizontally, vertically); -} - -QImage QImage::rgbSwapped() const -{ - return rgbSwapped_helper(); -} - -QT_END_NAMESPACE diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index 0930955f5a..9277472c3c 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -140,7 +140,7 @@ QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetyp qsizetype dummy; if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy)) return invalid; // why is this here? -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) +#if 1 || QT_VERSION < QT_VERSION_CHECK(6,0,0) // ### can only fix this if QImage dimensions are not int anymore // Disallow images where width * depth calculations might overflow if (width > (INT_MAX - 31) / depth) return invalid; diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index 3a32cc7f15..d469ac8aae 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -264,14 +264,14 @@ void QPicture::setData(const char* data, uint size) \sa save() */ -bool QPicture::load(const QString &fileName, const char *format) +bool QPicture::load(const QString &fileName) { QFile f(fileName); if (!f.open(QIODevice::ReadOnly)) { operator=(QPicture()); return false; } - return load(&f, format); + return load(&f); } /*! @@ -280,21 +280,8 @@ bool QPicture::load(const QString &fileName, const char *format) \a dev is the device to use for loading. */ -bool QPicture::load(QIODevice *dev, const char *format) +bool QPicture::load(QIODevice *dev) { - if(format) { -#ifndef QT_NO_PICTUREIO - QPictureIO io(dev, format); - if (io.read()) { - operator=(io.picture()); - return true; - } -#endif - qWarning("QPicture::load: No such picture format: %s", format); - operator=(QPicture()); - return false; - } - detach(); QByteArray a = dev->readAll(); @@ -312,7 +299,7 @@ bool QPicture::load(QIODevice *dev, const char *format) \sa load() */ -bool QPicture::save(const QString &fileName, const char *format) +bool QPicture::save(const QString &fileName) { if (paintingActive()) { qWarning("QPicture::save: still being painted on. " @@ -320,27 +307,10 @@ bool QPicture::save(const QString &fileName, const char *format) return false; } - - if(format) { -#ifndef QT_NO_PICTUREIO - QPictureIO io(fileName, format); - bool result = io.write(); - if (result) { - operator=(io.picture()); - } else if (format) -#else - bool result = false; -#endif - { - qWarning("QPicture::save: No such picture format: %s", format); - } - return result; - } - QFile f(fileName); if (!f.open(QIODevice::WriteOnly)) return false; - return save(&f, format); + return save(&f); } /*! @@ -349,7 +319,7 @@ bool QPicture::save(const QString &fileName, const char *format) \a dev is the device to use for saving. */ -bool QPicture::save(QIODevice *dev, const char *format) +bool QPicture::save(QIODevice *dev) { if (paintingActive()) { qWarning("QPicture::save: still being painted on. " @@ -357,22 +327,6 @@ bool QPicture::save(QIODevice *dev, const char *format) return false; } - if(format) { -#ifndef QT_NO_PICTUREIO - QPictureIO io(dev, format); - bool result = io.write(); - if (result) { - operator=(io.picture()); - } else if (format) -#else - bool result = false; -#endif - { - qWarning("QPicture::save: No such picture format: %s", format); - } - return result; - } - dev->write(d_func()->pictb.buffer(), d_func()->pictb.buffer().size()); return true; } @@ -1189,780 +1143,6 @@ QDataStream &operator>>(QDataStream &s, QPicture &r) } #endif // QT_NO_DATASTREAM - -#ifndef QT_NO_PICTUREIO - -QT_BEGIN_INCLUDE_NAMESPACE -#include "qregexp.h" -#include "qpictureformatplugin.h" -QT_END_INCLUDE_NAMESPACE - -#if QT_DEPRECATED_SINCE(5, 10) -/*! - \obsolete - - Returns a string that specifies the picture format of the file \a - fileName, or \nullptr if the file cannot be read or if the format - is not recognized. - - \sa load(), save() -*/ - -const char* QPicture::pictureFormat(const QString &fileName) -{ - const QByteArray format = QPictureIO::pictureFormat(fileName); - // This function returns a const char * from a QByteArray. - // Double check that the QByteArray is not detached, otherwise - // we would return a dangling pointer. - Q_ASSERT(!format.isDetached()); - return format; -} - -/*! - \obsolete - - Returns a list of picture formats that are supported for picture - input. - - \sa outputFormats(), inputFormatList(), QPictureIO -*/ -QList<QByteArray> QPicture::inputFormats() -{ - return QPictureIO::inputFormats(); -} - -static QStringList qToStringList(const QList<QByteArray> &arr) -{ - QStringList list; - const int count = arr.count(); - list.reserve(count); - for (int i = 0; i < count; ++i) - list.append(QString::fromLatin1(arr.at(i))); - return list; -} - -/*! - \obsolete - - Returns a list of picture formats that are supported for picture - input. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet picture/picture.cpp 2 - - \sa outputFormatList(), inputFormats(), QPictureIO -*/ -QStringList QPicture::inputFormatList() -{ - return qToStringList(QPictureIO::inputFormats()); -} - - -/*! - \obsolete - - Returns a list of picture formats that are supported for picture - output. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet picture/picture.cpp 3 - - \sa inputFormatList(), outputFormats(), QPictureIO -*/ -QStringList QPicture::outputFormatList() -{ - return qToStringList(QPictureIO::outputFormats()); -} - -/*! - \obsolete - - Returns a list of picture formats that are supported for picture - output. - - \sa inputFormats(), outputFormatList(), QPictureIO -*/ -QList<QByteArray> QPicture::outputFormats() -{ - return QPictureIO::outputFormats(); -} -#endif // QT_DEPRECATED_SINCE(5, 10) - -/***************************************************************************** - QPictureIO member functions - *****************************************************************************/ - -/*! - \obsolete - - \class QPictureIO - - \brief The QPictureIO class contains parameters for loading and - saving pictures. - - \ingroup painting - \ingroup io - \inmodule QtGui - - QPictureIO contains a QIODevice object that is used for picture data - I/O. The programmer can install new picture file formats in addition - to those that Qt provides. - - You don't normally need to use this class; QPicture::load(), - QPicture::save(). - - \sa QPicture, QPixmap, QFile -*/ - -struct QPictureIOData -{ - QPicture pi; // picture - int iostat; // IO status - QByteArray frmt; // picture format - QIODevice *iodev; // IO device - QString fname; // file name - QString descr; // picture description - const char *parameters; - int quality; - float gamma; -}; - -/*! - Constructs a QPictureIO object with all parameters set to zero. -*/ - -QPictureIO::QPictureIO() -{ - init(); -} - -/*! - Constructs a QPictureIO object with the I/O device \a ioDevice and a - \a format tag. -*/ - -QPictureIO::QPictureIO(QIODevice *ioDevice, const char *format) -{ - init(); - d->iodev = ioDevice; - d->frmt = format; -} - -/*! - Constructs a QPictureIO object with the file name \a fileName and a - \a format tag. -*/ - -QPictureIO::QPictureIO(const QString &fileName, const char* format) -{ - init(); - d->frmt = format; - d->fname = fileName; -} - -/*! - Contains initialization common to all QPictureIO constructors. -*/ - -void QPictureIO::init() -{ - d = new QPictureIOData(); - d->parameters = nullptr; - d->quality = -1; // default quality of the current format - d->gamma=0.0f; - d->iostat = 0; - d->iodev = nullptr; -} - -/*! - Destroys the object and all related data. -*/ - -QPictureIO::~QPictureIO() -{ - if (d->parameters) - delete [] d->parameters; - delete d; -} - - -/***************************************************************************** - QPictureIO picture handler functions - *****************************************************************************/ - -class QPictureHandler -{ -public: - QPictureHandler(const char *f, const char *h, const QByteArray& fl, - picture_io_handler r, picture_io_handler w); - QByteArray format; // picture format - QRegExp header; // picture header pattern - enum TMode { Untranslated=0, TranslateIn, TranslateInOut } text_mode; - picture_io_handler read_picture; // picture read function - picture_io_handler write_picture; // picture write function - bool obsolete; // support not "published" -}; - -QPictureHandler::QPictureHandler(const char *f, const char *h, const QByteArray& fl, - picture_io_handler r, picture_io_handler w) - : format(f), header(QString::fromLatin1(h)) -{ - text_mode = Untranslated; - if (fl.contains('t')) - text_mode = TranslateIn; - else if (fl.contains('T')) - text_mode = TranslateInOut; - obsolete = fl.contains('O'); - read_picture = r; - write_picture = w; -} - -typedef QList<QPictureHandler *> QPHList; -Q_GLOBAL_STATIC(QPHList, pictureHandlers) - -void qt_init_picture_plugins() -{ - typedef QMultiMap<int, QString> PluginKeyMap; - typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator; - - static QBasicMutex mutex; - const auto locker = qt_scoped_lock(mutex); - static QFactoryLoader loader(QPictureFormatInterface_iid, - QStringLiteral("/pictureformats")); - - const PluginKeyMap keyMap = loader.keyMap(); - const PluginKeyMapConstIterator cend = keyMap.constEnd(); - for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it) { - if (QPictureFormatPlugin *format = qobject_cast<QPictureFormatPlugin*>(loader.instance(it.key()))) - format->installIOHandler(it.value()); - } -} - -static void cleanup() -{ - // make sure that picture handlers are delete before plugin manager - if (QPHList *list = pictureHandlers()) { - qDeleteAll(*list); - list->clear(); - } -} - -void qt_init_picture_handlers() // initialize picture handlers -{ - static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0); - if (done.testAndSetRelaxed(0, 1)) { - qAddPostRoutine(cleanup); - } -} - -static QPictureHandler *get_picture_handler(const char *format) -{ // get pointer to handler - qt_init_picture_handlers(); - qt_init_picture_plugins(); - if (QPHList *list = pictureHandlers()) { - for (int i = 0; i < list->size(); ++i) { - if (list->at(i)->format == format) - return list->at(i); - } - } - return nullptr; // no such handler -} - - -/*! - Defines a picture I/O handler for the picture format called \a - format, which is recognized using the regular - expression defined in \a header, read using \a readPicture and - written using \a writePicture. - - \a flags is a string of single-character flags for this format. - The only flag defined currently is T (upper case), so the only - legal value for \a flags are "T" and the empty string. The "T" - flag means that the picture file is a text file, and Qt should treat - all newline conventions as equivalent. (XPM files and some PPM - files are text files for example.) - - \a format is used to select a handler to write a QPicture; \a header - is used to select a handler to read an picture file. - - If \a readPicture is \nullptr, the QPictureIO will not be able - to read pictures in \a format. If \a writePicture is \nullptr, - the QPictureIO will not be able to write pictures in \a format. If - both are null, the QPictureIO object is valid but useless. - - Example: - \snippet picture/picture.cpp 6 - \codeline - \snippet picture/picture.cpp 7 - \codeline - \snippet picture/picture.cpp 8 - - Before the regular expression test, all the 0 bytes in the file header are - converted to 1 bytes. This is done because when Qt was ASCII-based, QRegExp - could not handle 0 bytes in strings. - - The regexp is only applied on the first 14 bytes of the file. - - (Note that if one handlerIO supports writing a format and another - supports reading it, Qt supports both reading and writing. If two - handlers support the same operation, Qt chooses one arbitrarily.) -*/ - -void QPictureIO::defineIOHandler(const char *format, - const char *header, - const char *flags, - picture_io_handler readPicture, - picture_io_handler writePicture) -{ - qt_init_picture_handlers(); - if (QPHList *list = pictureHandlers()) { - QPictureHandler *p; - p = new QPictureHandler(format, header, QByteArray(flags), readPicture, writePicture); - list->prepend(p); - } -} - - -/***************************************************************************** - QPictureIO normal member functions - *****************************************************************************/ - -/*! - Returns the picture currently set. - - \sa setPicture() -*/ -const QPicture &QPictureIO::picture() const { return d->pi; } - -/*! - Returns the picture's IO status. A non-zero value indicates an - error, whereas 0 means that the IO operation was successful. - - \sa setStatus() -*/ -int QPictureIO::status() const { return d->iostat; } - -/*! - Returns the picture format string or \nullptr if no format has been - explicitly set. -*/ -const char *QPictureIO::format() const { return d->frmt; } - -/*! - Returns the IO device currently set. - - \sa setIODevice() -*/ -QIODevice *QPictureIO::ioDevice() const { return d->iodev; } - -/*! - Returns the file name currently set. - - \sa setFileName() -*/ -QString QPictureIO::fileName() const { return d->fname; } - - -/*! - Returns the picture description string. - - \sa setDescription() -*/ -QString QPictureIO::description() const { return d->descr; } - -/*! - Sets the picture to \a picture. - - \sa picture() -*/ -void QPictureIO::setPicture(const QPicture &picture) -{ - d->pi = picture; -} - -/*! - Sets the picture IO status to \a status. A non-zero value indicates - an error, whereas 0 means that the IO operation was successful. - - \sa status() -*/ -void QPictureIO::setStatus(int status) -{ - d->iostat = status; -} - -/*! - Sets the picture format to \a format for the picture to be read or - written. - - It is necessary to specify a format before writing an picture, but - it is not necessary to specify a format before reading an picture. - - If no format has been set, Qt guesses the picture format before - reading it. If a format is set the picture will only be read if it - has that format. - - \sa read(), write(), format() -*/ -void QPictureIO::setFormat(const char *format) -{ - d->frmt = format; -} - -/*! - Sets the IO device to be used for reading or writing an picture. - - Setting the IO device allows pictures to be read/written to any - block-oriented QIODevice. - - If \a ioDevice is not null, this IO device will override file name - settings. - - \sa setFileName() -*/ -void QPictureIO::setIODevice(QIODevice *ioDevice) -{ - d->iodev = ioDevice; -} - -/*! - Sets the name of the file to read or write an picture from to \a - fileName. - - \sa setIODevice() -*/ -void QPictureIO::setFileName(const QString &fileName) -{ - d->fname = fileName; -} - -/*! - Returns the quality of the written picture, related to the - compression ratio. - - \sa setQuality(), QPicture::save() -*/ -int QPictureIO::quality() const -{ - return d->quality; -} - -/*! - Sets the quality of the written picture to \a q, related to the - compression ratio. - - \a q must be in the range -1..100. Specify 0 to obtain small - compressed files, 100 for large uncompressed files. (-1 signifies - the default compression.) - - \sa quality(), QPicture::save() -*/ - -void QPictureIO::setQuality(int q) -{ - d->quality = q; -} - -/*! - Returns the picture's parameters string. - - \sa setParameters() -*/ - -const char *QPictureIO::parameters() const -{ - return d->parameters; -} - -/*! - Sets the picture's parameter string to \a parameters. This is for - picture handlers that require special parameters. - - Although the current picture formats supported by Qt ignore the - parameters string, it may be used in future extensions or by - contributions (for example, JPEG). - - \sa parameters() -*/ - -void QPictureIO::setParameters(const char *parameters) -{ - if (d->parameters) - delete [] d->parameters; - d->parameters = qstrdup(parameters); -} - -/*! - Sets the gamma value at which the picture will be viewed to \a - gamma. If the picture format stores a gamma value for which the - picture is intended to be used, then this setting will be used to - modify the picture. Setting to 0.0 will disable gamma correction - (i.e. any specification in the file will be ignored). - - The default value is 0.0. - - \sa gamma() -*/ -void QPictureIO::setGamma(float gamma) -{ - d->gamma=gamma; -} - -/*! - Returns the gamma value at which the picture will be viewed. - - \sa setGamma() -*/ -float QPictureIO::gamma() const -{ - return d->gamma; -} - -/*! - Sets the picture description string for picture handlers that support - picture descriptions to \a description. - - Currently, no picture format supported by Qt uses the description - string. -*/ - -void QPictureIO::setDescription(const QString &description) -{ - d->descr = description; -} - - -/*! - Returns a string that specifies the picture format of the file \a - fileName, or null if the file cannot be read or if the format is - not recognized. -*/ - -QByteArray QPictureIO::pictureFormat(const QString &fileName) -{ - QFile file(fileName); - QByteArray format; - if (!file.open(QIODevice::ReadOnly)) - return format; - format = pictureFormat(&file); - file.close(); - return format; -} - -/*! - \overload - - Returns a string that specifies the picture format of the picture read - from IO device \a d, or 0 if the device cannot be read or if the - format is not recognized. - - Make sure that \a d is at the right position in the device (for - example, at the beginning of the file). - - \sa QIODevice::pos() -*/ - -QByteArray QPictureIO::pictureFormat(QIODevice *d) -{ - // if you change this change the documentation for defineIOHandler() - const int buflen = 14; - - char buf[buflen]; - char buf2[buflen]; - qt_init_picture_handlers(); - qt_init_picture_plugins(); - int pos = d->pos(); // save position - int rdlen = d->read(buf, buflen); // read a few bytes - - QByteArray format; - if (rdlen != buflen) - return format; - - memcpy(buf2, buf, buflen); - - for (int n = 0; n < rdlen; n++) - if (buf[n] == '\0') - buf[n] = '\001'; - if (rdlen > 0) { - buf[rdlen - 1] = '\0'; - QString bufStr = QString::fromLatin1(buf); - if (QPHList *list = pictureHandlers()) { - for (int i = 0; i < list->size(); ++i) { - if (list->at(i)->header.indexIn(bufStr) != -1) { // try match with headers - format = list->at(i)->format; - break; - } - } - } - } - d->seek(pos); // restore position - return format; -} - -/*! - Returns a sorted list of picture formats that are supported for - picture input. -*/ -QList<QByteArray> QPictureIO::inputFormats() -{ - QList<QByteArray> result; - - qt_init_picture_handlers(); - qt_init_picture_plugins(); - - if (QPHList *list = pictureHandlers()) { - for (int i = 0; i < list->size(); ++i) { - QPictureHandler *p = list->at(i); - if (p->read_picture && !p->obsolete && !result.contains(p->format)) - result.append(p->format); - } - } - std::sort(result.begin(), result.end()); - - return result; -} - -/*! - Returns a sorted list of picture formats that are supported for - picture output. -*/ -QList<QByteArray> QPictureIO::outputFormats() -{ - qt_init_picture_handlers(); - qt_init_picture_plugins(); - - QList<QByteArray> result; - if (QPHList *list = pictureHandlers()) { - for (int i = 0; i < list->size(); ++i) { - QPictureHandler *p = list->at(i); - if (p->write_picture && !p->obsolete && !result.contains(p->format)) - result.append(p->format); - } - } - return result; -} - - - -/*! - Reads an picture into memory and returns \c true if the picture was - successfully read; otherwise returns \c false. - - Before reading an picture you must set an IO device or a file name. - If both an IO device and a file name have been set, the IO device - will be used. - - Setting the picture file format string is optional. - - Note that this function does \e not set the \l{format()}{format} used to read the picture. If you need that - information, use the pictureFormat() static functions. - - Example: - - \snippet picture/picture.cpp 4 - - \sa setIODevice(), setFileName(), setFormat(), write(), QPixmap::load() -*/ -bool QPictureIO::read() -{ - QFile file; - QByteArray picture_format; - QPictureHandler *h; - - if (d->iodev) { // read from io device - // ok, already open - } else if (!d->fname.isEmpty()) { // read from file - file.setFileName(d->fname); - if (!file.open(QIODevice::ReadOnly)) - return false; // cannot open file - d->iodev = &file; - } else { // no file name or io device - return false; - } - if (d->frmt.isEmpty()) { - // Try to guess format - picture_format = pictureFormat(d->iodev); // get picture format - if (picture_format.isEmpty()) { - if (file.isOpen()) { // unknown format - file.close(); - d->iodev = nullptr; - } - return false; - } - } else { - picture_format = d->frmt; - } - - h = get_picture_handler(picture_format); - if (file.isOpen()) { -#if !defined(Q_OS_UNIX) - if (h && h->text_mode) { // reopen in translated mode - file.close(); - file.open(QIODevice::ReadOnly | QIODevice::Text); - } - else -#endif - file.seek(0); // position to start - } - d->iostat = 1; // assume error - - if (h && h->read_picture) - (*h->read_picture)(this); - - if (file.isOpen()) { // picture was read using file - file.close(); - d->iodev = nullptr; - } - return d->iostat == 0; // picture successfully read? -} - - -/*! - Writes an picture to an IO device and returns \c true if the picture was - successfully written; otherwise returns \c false. - - Before writing an picture you must set an IO device or a file name. - If both an IO device and a file name have been set, the IO device - will be used. - - The picture will be written using the specified picture format. - - Example: - \snippet picture/picture.cpp 5 - - \sa setIODevice(), setFileName(), setFormat(), read(), QPixmap::save() -*/ -bool QPictureIO::write() -{ - if (d->frmt.isEmpty()) - return false; - QPictureHandler *h = get_picture_handler(d->frmt); - if (!h || !h->write_picture) { - qWarning("QPictureIO::write: No such picture format handler: %s", - format()); - return false; - } - QFile file; - if (!d->iodev && !d->fname.isEmpty()) { - file.setFileName(d->fname); - bool translate = h->text_mode==QPictureHandler::TranslateInOut; - QIODevice::OpenMode fmode = translate ? QIODevice::WriteOnly | QIODevice::Text : QIODevice::OpenMode(QIODevice::WriteOnly); - if (!file.open(fmode)) // couldn't create file - return false; - d->iodev = &file; - } - d->iostat = 1; - (*h->write_picture)(this); - if (file.isOpen()) { // picture was written using file - file.close(); - d->iodev = nullptr; - } - return d->iostat == 0; // picture successfully written? -} -#endif //QT_NO_PICTUREIO - QT_END_NAMESPACE #endif // QT_NO_PICTURE diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h index 189e57b9a3..34860985ed 100644 --- a/src/gui/image/qpicture.h +++ b/src/gui/image/qpicture.h @@ -48,7 +48,6 @@ QT_BEGIN_NAMESPACE - #ifndef QT_NO_PICTURE class QPicturePrivate; @@ -69,10 +68,10 @@ public: bool play(QPainter *p); - bool load(QIODevice *dev, const char *format = nullptr); - bool load(const QString &fileName, const char *format = nullptr); - bool save(QIODevice *dev, const char *format = nullptr); - bool save(const QString &fileName, const char *format = nullptr); + bool load(QIODevice *dev); + bool load(const QString &fileName); + bool save(QIODevice *dev); + bool save(const QString &fileName); QRect boundingRect() const; void setBoundingRect(const QRect &r); @@ -88,14 +87,6 @@ public: friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QPicture &p); friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &in, QPicture &p); -#if QT_DEPRECATED_SINCE(5, 10) - static QT_DEPRECATED const char* pictureFormat(const QString &fileName); - static QT_DEPRECATED QList<QByteArray> inputFormats(); - static QT_DEPRECATED QList<QByteArray> outputFormats(); - static QT_DEPRECATED QStringList inputFormatList(); - static QT_DEPRECATED QStringList outputFormatList(); -#endif // QT_DEPRECATED_SINCE(5, 10) - QPaintEngine *paintEngine() const override; protected: @@ -118,67 +109,6 @@ public: Q_DECLARE_SHARED(QPicture) - -#ifndef QT_NO_PICTUREIO -class QIODevice; -class QPictureIO; -typedef void (*picture_io_handler)(QPictureIO *); // picture IO handler - -struct QPictureIOData; - -class Q_GUI_EXPORT QPictureIO -{ -public: - QPictureIO(); - QPictureIO(QIODevice *ioDevice, const char *format); - QPictureIO(const QString &fileName, const char *format); - ~QPictureIO(); - - const QPicture &picture() const; - int status() const; - const char *format() const; - QIODevice *ioDevice() const; - QString fileName() const; - int quality() const; - QString description() const; - const char *parameters() const; - float gamma() const; - - void setPicture(const QPicture &); - void setStatus(int); - void setFormat(const char *); - void setIODevice(QIODevice *); - void setFileName(const QString &); - void setQuality(int); - void setDescription(const QString &); - void setParameters(const char *); - void setGamma(float); - - bool read(); - bool write(); - - static QByteArray pictureFormat(const QString &fileName); - static QByteArray pictureFormat(QIODevice *); - static QList<QByteArray> inputFormats(); - static QList<QByteArray> outputFormats(); - - static void defineIOHandler(const char *format, - const char *header, - const char *flags, - picture_io_handler read_picture, - picture_io_handler write_picture); - -private: - Q_DISABLE_COPY(QPictureIO) - - void init(); - - QPictureIOData *d; -}; - -#endif //QT_NO_PICTUREIO - - /***************************************************************************** QPicture stream functions *****************************************************************************/ diff --git a/src/gui/image/qpictureformatplugin.cpp b/src/gui/image/qpictureformatplugin.cpp deleted file mode 100644 index ef57ad720f..0000000000 --- a/src/gui/image/qpictureformatplugin.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qpictureformatplugin.h" -#if !defined(QT_NO_PICTURE) -#include "qpicture.h" - -QT_BEGIN_NAMESPACE - -/*! - \obsolete - - \class QPictureFormatPlugin - \brief The QPictureFormatPlugin class provides an abstract base - for custom picture format plugins. - - \ingroup plugins - \inmodule QtGui - - The picture format plugin is a simple plugin interface that makes - it easy to create custom picture formats that can be used - transparently by applications. - - Writing an picture format plugin is achieved by subclassing this - base class, reimplementing the pure virtual functions - loadPicture(), savePicture(), and installIOHandler(), and - exporting the class with the Q_PLUGIN_METADATA() macro. - - The json file containing the metadata should contain one entry - with the list of picture formats supported by the plugin: - - \code - { "Keys": [ "mypictureformat" ] } - \endcode - - \sa {How to Create Qt Plugins} -*/ - -/*! - \fn bool QPictureFormatPlugin::installIOHandler(const QString &format) - - Installs a QPictureIO picture I/O handler for the picture format \a - format. Returns \c true on success. -*/ - - -/*! - Constructs an picture format plugin with the given \a parent. - This is invoked automatically by the moc generated code that exports the plugin. -*/ -QPictureFormatPlugin::QPictureFormatPlugin(QObject *parent) - : QObject(parent) -{ -} - -/*! - Destroys the picture format plugin. - - You never have to call this explicitly. Qt destroys a plugin - automatically when it is no longer used. -*/ -QPictureFormatPlugin::~QPictureFormatPlugin() -{ -} - - -/*! - Loads the picture stored in the file called \a fileName, with the - given \a format, into *\a picture. Returns \c true on success; - otherwise returns \c false. - - \sa savePicture() -*/ -bool QPictureFormatPlugin::loadPicture(const QString &format, const QString &fileName, QPicture *picture) -{ - Q_UNUSED(format) - Q_UNUSED(fileName) - Q_UNUSED(picture) - return false; -} - -/*! - Saves the given \a picture into the file called \a fileName, - using the specified \a format. Returns \c true on success; otherwise - returns \c false. - - \sa loadPicture() -*/ -bool QPictureFormatPlugin::savePicture(const QString &format, const QString &fileName, const QPicture &picture) -{ - Q_UNUSED(format) - Q_UNUSED(fileName) - Q_UNUSED(picture) - return false; -} - -#endif // QT_NO_PICTURE - -QT_END_NAMESPACE diff --git a/src/gui/image/qpictureformatplugin.h b/src/gui/image/qpictureformatplugin.h deleted file mode 100644 index 3f59c04d79..0000000000 --- a/src/gui/image/qpictureformatplugin.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPICTUREFORMATPLUGIN_H -#define QPICTUREFORMATPLUGIN_H - -#include <QtGui/qtguiglobal.h> -#include <QtCore/qplugin.h> -#include <QtCore/qfactoryinterface.h> - -QT_BEGIN_NAMESPACE - - -#if !defined(QT_NO_PICTURE) - -class QPicture; -class QImage; -class QString; -class QStringList; - -#define QPictureFormatInterface_iid "org.qt-project.Qt.QPictureFormatInterface" - -class Q_GUI_EXPORT QPictureFormatPlugin : public QObject -{ - Q_OBJECT -public: - explicit QPictureFormatPlugin(QObject *parent = nullptr); - ~QPictureFormatPlugin(); - - virtual bool loadPicture(const QString &format, const QString &filename, QPicture *pic); - virtual bool savePicture(const QString &format, const QString &filename, const QPicture &pic); - virtual bool installIOHandler(const QString &format) = 0; - -}; - -#endif // QT_NO_PICTURE - -QT_END_NAMESPACE - -#endif // QPICTUREFORMATPLUGIN_H diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h index a9ee25da75..f1c6e6df5c 100644 --- a/src/gui/itemmodels/qstandarditemmodel.h +++ b/src/gui/itemmodels/qstandarditemmodel.h @@ -53,8 +53,6 @@ QT_REQUIRE_CONFIG(standarditemmodel); QT_BEGIN_NAMESPACE -template <class T> class QList; - class QStandardItemModel; class QStandardItemPrivate; @@ -344,8 +342,11 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - // Qt 6: add override keyword - bool clearItemData(const QModelIndex &index); + bool clearItemData(const QModelIndex &index) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + override +#endif + ; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 9c80f1e2cc..d47fd6e4e4 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -48,11 +48,8 @@ HEADERS += \ kernel/qinputmethod.h \ kernel/qinputmethod_p.h \ kernel/qinternalmimedata_p.h \ - kernel/qkeysequence.h \ - kernel/qkeysequence_p.h \ kernel/qkeymapper_p.h \ kernel/qpalette.h \ - kernel/qshortcutmap_p.h \ kernel/qsessionmanager.h \ kernel/qsessionmanager_p.h \ kernel/qwindowdefs.h \ @@ -108,12 +105,10 @@ SOURCES += \ kernel/qevent.cpp \ kernel/qinputmethod.cpp \ kernel/qinternalmimedata.cpp \ - kernel/qkeysequence.cpp \ kernel/qkeymapper.cpp \ kernel/qpalette.cpp \ kernel/qguivariant.cpp \ kernel/qscreen.cpp \ - kernel/qshortcutmap.cpp \ kernel/qstylehints.cpp \ kernel/qtouchdevice.cpp \ kernel/qplatformsharedgraphicscache.cpp \ @@ -131,6 +126,18 @@ SOURCES += \ kernel/qhighdpiscaling.cpp \ kernel/qtestsupport_gui.cpp +qtConfig(action) { + HEADERS += \ + kernel/qguiaction.h \ + kernel/qguiaction_p.h \ + kernel/qguiactiongroup.h \ + kernel/qguiactiongroup_p.h + + SOURCES += \ + kernel/qguiactiongroup.cpp \ + kernel/qguiaction.cpp +} + qtConfig(draganddrop) { HEADERS += \ kernel/qdnd_p.h \ @@ -151,13 +158,24 @@ qtConfig(opengl) { HEADERS += \ kernel/qplatformopenglcontext.h \ kernel/qopenglcontext.h \ - kernel/qopenglcontext_p.h \ - kernel/qopenglwindow.h + kernel/qopenglcontext_p.h SOURCES += \ kernel/qplatformopenglcontext.cpp \ - kernel/qopenglcontext.cpp \ - kernel/qopenglwindow.cpp + kernel/qopenglcontext.cpp +} + +qtConfig(shortcut) { + HEADERS += \ + kernel/qguishortcut.h \ + kernel/qguishortcut_p.h \ + kernel/qshortcutmap_p.h \ + kernel/qkeysequence.h \ + kernel/qkeysequence_p.h + SOURCES += \ + kernel/qguishortcut.cpp \ + kernel/qshortcutmap.cpp \ + kernel/qkeysequence.cpp } win32:HEADERS+=kernel/qwindowdefs_win.h diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 04970a942b..5a71475dc9 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -1235,7 +1235,7 @@ Qt::KeyboardModifiers QKeyEvent::modifiers() const return QInputEvent::modifiers(); } -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) /*! \fn bool QKeyEvent::matches(QKeySequence::StandardKey key) const \since 4.2 @@ -1251,7 +1251,7 @@ bool QKeyEvent::matches(QKeySequence::StandardKey matchKey) const const QList<QKeySequence> bindings = QKeySequence::keyBindings(matchKey); return bindings.contains(QKeySequence(searchkey)); } -#endif // QT_NO_SHORTCUT +#endif // QT_CONFIG(shortcut) /*! @@ -2706,10 +2706,6 @@ QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QPoin { } #endif -typedef QHash<const QNativeGestureEvent*, const QTouchDevice*> NativeGestureEventDataHash; -// ### Qt6: move this to a member in QNativeGestureEvent -Q_GLOBAL_STATIC(NativeGestureEventDataHash, g_nativeGestureEventDataHash) - /*! Constructs a native gesture event of type \a type originating from \a device. @@ -2724,27 +2720,20 @@ QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QTouc const QPointF &screenPos, qreal realValue, ulong sequenceId, quint64 intValue) : QInputEvent(QEvent::NativeGesture), mGestureType(type), mLocalPos(localPos), mWindowPos(windowPos), mScreenPos(screenPos), mRealValue(realValue), - mSequenceId(sequenceId), mIntValue(intValue) + mSequenceId(sequenceId), mIntValue(intValue), mDevice(device) { - g_nativeGestureEventDataHash->insert(this, device); } QNativeGestureEvent::~QNativeGestureEvent() -{ - g_nativeGestureEventDataHash->remove(this); -} + = default; /*! + \fn const QTouchDevice *QNativeGestureEvent::device() const \since 5.10 Returns the device. */ -const QTouchDevice *QNativeGestureEvent::device() const -{ - return g_nativeGestureEventDataHash->value(this); -} - /*! \fn QNativeGestureEvent::gestureType() const \since 5.2 @@ -3346,18 +3335,18 @@ QWhatsThisClickedEvent::~QWhatsThisClickedEvent() /*! \class QActionEvent \brief The QActionEvent class provides an event that is generated - when a QAction is added, removed, or changed. + when a QGuiAction is added, removed, or changed. \ingroup events \inmodule QtGui - Actions can be added to widgets using QWidget::addAction(). This - generates an \l ActionAdded event, which you can handle to provide + Actions can be added to controls, for example by using QWidget::addAction(). + This generates an \l ActionAdded event, which you can handle to provide custom behavior. For example, QToolBar reimplements QWidget::actionEvent() to create \l{QToolButton}s for the actions. - \sa QAction, QWidget::addAction(), QWidget::removeAction(), QWidget::actions() + \sa QGuiAction, QWidget::addAction(), QWidget::removeAction(), QWidget::actions() */ /*! @@ -3368,7 +3357,7 @@ QWhatsThisClickedEvent::~QWhatsThisClickedEvent() type is ActionAdded, the action is to be inserted before the action \a before. If \a before is \nullptr, the action is appended. */ -QActionEvent::QActionEvent(int type, QAction *action, QAction *before) +QActionEvent::QActionEvent(int type, QGuiAction *action, QGuiAction *before) : QEvent(static_cast<QEvent::Type>(type)), act(action), bef(before) {} @@ -3603,7 +3592,7 @@ QToolBarChangeEvent::~QToolBarChangeEvent() #endif // QT_NO_TOOLBAR -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) /*! Constructs a shortcut event for the given \a key press, @@ -3624,7 +3613,7 @@ QShortcutEvent::~QShortcutEvent() { } -#endif // QT_NO_SHORTCUT +#endif // QT_CONFIG(shortcut) #ifndef QT_NO_DEBUG_STREAM @@ -3978,7 +3967,7 @@ QT_WARNING_POP dbg << ')'; } break; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) case QEvent::Shortcut: { const QShortcutEvent *se = static_cast<const QShortcutEvent *>(e); dbg << "QShortcutEvent(" << se->key().toString() << ", id=" << se->shortcutId(); diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index f363ece48b..6f3215652b 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -45,7 +45,9 @@ #include <QtGui/qregion.h> #include <QtCore/qnamespace.h> #include <QtCore/qstring.h> -#include <QtGui/qkeysequence.h> +#if QT_CONFIG(shortcut) +# include <QtGui/qkeysequence.h> +#endif #include <QtCore/qcoreevent.h> #include <QtCore/qvariant.h> #include <QtCore/qmap.h> // ### Qt 6: Remove @@ -59,7 +61,7 @@ QT_BEGIN_NAMESPACE -class QAction; +class QGuiAction; #ifndef QT_NO_GESTURES class QGesture; #endif @@ -350,7 +352,7 @@ public: const QPointF &windowPos() const { return mWindowPos; } const QPointF &screenPos() const { return mScreenPos; } - const QTouchDevice *device() const; + const QTouchDevice *device() const { return mDevice; } protected: Qt::NativeGestureType mGestureType; @@ -360,6 +362,7 @@ protected: qreal mRealValue; ulong mSequenceId; quint64 mIntValue; + const QTouchDevice *mDevice; }; #endif // QT_NO_GESTURES @@ -374,7 +377,7 @@ public: ~QKeyEvent(); int key() const { return k; } -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) bool matches(QKeySequence::StandardKey key) const; #endif Qt::KeyboardModifiers modifiers() const; @@ -750,18 +753,18 @@ private: }; #endif -#ifndef QT_NO_ACTION +#if QT_CONFIG(action) class Q_GUI_EXPORT QActionEvent : public QEvent { - QAction *act, *bef; + QGuiAction *act, *bef; public: - QActionEvent(int type, QAction *action, QAction *before = nullptr); + QActionEvent(int type, QGuiAction *action, QGuiAction *before = nullptr); ~QActionEvent(); - inline QAction *action() const { return act; } - inline QAction *before() const { return bef; } + inline QGuiAction *action() const { return act; } + inline QGuiAction *before() const { return bef; } }; -#endif +#endif // QT_CONFIG(action) class Q_GUI_EXPORT QFileOpenEvent : public QEvent { @@ -791,7 +794,7 @@ private: }; #endif -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) class Q_GUI_EXPORT QShortcutEvent : public QEvent { public: @@ -826,10 +829,10 @@ private: Q_GUI_EXPORT QDebug operator<<(QDebug, const QEvent *); #endif -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ? e->matches(key) : false);} inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);} -#endif // QT_NO_SHORTCUT +#endif // QT_CONFIG(shortcut) class Q_GUI_EXPORT QPointingDeviceUniqueId { @@ -854,14 +857,6 @@ private: }; Q_DECLARE_TYPEINFO(QPointingDeviceUniqueId, Q_MOVABLE_TYPE); -#if 0 -#pragma qt_sync_suspend_processing -#endif -template <> class QList<QPointingDeviceUniqueId> {}; // to prevent instantiation: use QVector instead -#if 0 -#pragma qt_sync_resume_processing -#endif - Q_GUI_EXPORT bool operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) noexcept; inline bool operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) noexcept { return !operator==(lhs, rhs); } diff --git a/src/gui/kernel/qguiaction.cpp b/src/gui/kernel/qguiaction.cpp new file mode 100644 index 0000000000..7c7d86f5ab --- /dev/null +++ b/src/gui/kernel/qguiaction.cpp @@ -0,0 +1,1214 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qguiaction.h" +#include "qguiactiongroup.h" + +#include "qguiaction_p.h" +#include "qguiapplication.h" +#include "qevent.h" +#include "qlist.h" +#include "qstylehints.h" +#if QT_CONFIG(shortcut) +# include <private/qshortcutmap_p.h> +#endif +#include <private/qguiapplication_p.h> +#include <private/qdebug_p.h> + +#define QAPP_CHECK(functionName) \ + if (Q_UNLIKELY(!QCoreApplication::instance())) { \ + qWarning("QAction: Initialize Q(Gui)Application before calling '" functionName "'."); \ + return; \ + } + +QT_BEGIN_NAMESPACE + +/* + internal: guesses a descriptive text from a text suited for a menu entry + */ +static QString qt_strippedText(QString s) +{ + s.remove(QLatin1String("...")); + for (int i = 0; i < s.size(); ++i) { + if (s.at(i) == QLatin1Char('&')) + s.remove(i, 1); + } + return s.trimmed(); +} + +QGuiActionPrivate::QGuiActionPrivate() : +#if QT_CONFIG(shortcut) + autorepeat(1), +#endif + enabled(1), forceDisabled(0), visible(1), forceInvisible(0), checkable(0), + checked(0), separator(0), fontSet(false), + iconVisibleInMenu(-1), shortcutVisibleInContextMenu(-1) +{ +} + +#if QT_CONFIG(shortcut) +static bool dummy(QObject *, Qt::ShortcutContext) { return false; } // only for GUI testing. + +QShortcutMap::ContextMatcher QGuiActionPrivate::contextMatcher() const +{ + return dummy; +} +#endif // QT_CONFIG(shortcut) + +QGuiActionPrivate::~QGuiActionPrivate() = default; + +void QGuiActionPrivate::sendDataChanged() +{ + Q_Q(QGuiAction); + QActionEvent e(QEvent::ActionChanged, q); + QCoreApplication::sendEvent(q, &e); + + emit q->changed(); +} + +#if QT_CONFIG(shortcut) +void QGuiActionPrivate::redoGrab(QShortcutMap &map) +{ + Q_Q(QGuiAction); + if (shortcutId) + map.removeShortcut(shortcutId, q); + if (shortcut.isEmpty()) + return; + shortcutId = map.addShortcut(q, shortcut, shortcutContext, contextMatcher()); + if (!enabled) + map.setShortcutEnabled(false, shortcutId, q); + if (!autorepeat) + map.setShortcutAutoRepeat(false, shortcutId, q); +} + +void QGuiActionPrivate::redoGrabAlternate(QShortcutMap &map) +{ + Q_Q(QGuiAction); + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + if (const int id = alternateShortcutIds.at(i)) + map.removeShortcut(id, q); + } + alternateShortcutIds.clear(); + if (alternateShortcuts.isEmpty()) + return; + for(int i = 0; i < alternateShortcuts.count(); ++i) { + const QKeySequence& alternate = alternateShortcuts.at(i); + if (!alternate.isEmpty()) + alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext, contextMatcher())); + else + alternateShortcutIds.append(0); + } + if (!enabled) { + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + const int id = alternateShortcutIds.at(i); + map.setShortcutEnabled(false, id, q); + } + } + if (!autorepeat) { + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + const int id = alternateShortcutIds.at(i); + map.setShortcutAutoRepeat(false, id, q); + } + } +} + +void QGuiActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) +{ + Q_Q(QGuiAction); + if (shortcutId) + map.setShortcutEnabled(enable, shortcutId, q); + for(int i = 0; i < alternateShortcutIds.count(); ++i) { + if (const int id = alternateShortcutIds.at(i)) + map.setShortcutEnabled(enable, id, q); + } +} +#endif // QT_NO_SHORTCUT + + +/*! + \class QGuiAction + \brief QGuiAction is the base class for actions, an abstract user interface + action that can be inserted into widgets. + \since 6.0 + + \inmodule QtGui + + In applications many common commands can be invoked via menus, + toolbar buttons, and keyboard shortcuts. Since the user expects + each command to be performed in the same way, regardless of the + user interface used, it is useful to represent each command as + an \e action. + + Actions can be added to menus and toolbars, and will + automatically keep them in sync. For example, in a word processor, + if the user presses a Bold toolbar button, the Bold menu item + will automatically be checked. + + Actions can be created as independent objects, but they may + also be created during the construction of menus; the QMenu class + contains convenience functions for creating actions suitable for + use as menu items. + + A QGuiAction may contain an icon, menu text, a shortcut, status text, + "What's This?" text, and a tooltip. Most of these can be set in + the constructor. They can also be set independently with + setIcon(), setText(), setIconText(), setShortcut(), + setStatusTip(), setWhatsThis(), and setToolTip(). For menu items, + it is possible to set an individual font with setFont(). + + We recommend that actions are created as children of the window + they are used in. In most cases actions will be children of + the application's main window. + + \sa QMenu, QToolBar, {Application Example} +*/ + +/*! + \fn void QGuiAction::trigger() + + This is a convenience slot that calls activate(Trigger). +*/ + +/*! + \fn void QGuiAction::hover() + + This is a convenience slot that calls activate(Hover). +*/ + +/*! + \enum QGuiAction::MenuRole + + This enum describes how an action should be moved into the application menu on \macos. + + \value NoRole This action should not be put into the application menu + \value TextHeuristicRole This action should be put in the application menu based on the action's text + as described in the QMenuBar documentation. + \value ApplicationSpecificRole This action should be put in the application menu with an application specific role + \value AboutQtRole This action handles the "About Qt" menu item. + \value AboutRole This action should be placed where the "About" menu item is in the application menu. The text of + the menu item will be set to "About <application name>". The application name is fetched from the + \c{Info.plist} file in the application's bundle (See \l{Qt for macOS - Deployment}). + \value PreferencesRole This action should be placed where the "Preferences..." menu item is in the application menu. + \value QuitRole This action should be placed where the Quit menu item is in the application menu. + + Setting this value only has effect on items that are in the immediate menus + of the menubar, not the submenus of those menus. For example, if you have + File menu in your menubar and the File menu has a submenu, setting the + MenuRole for the actions in that submenu have no effect. They will never be moved. +*/ + +/*! + Constructs an action with \a parent. If \a parent is an action + group the action will be automatically inserted into the group. + + \note The \a parent argument is optional since Qt 5.7. +*/ +QGuiAction::QGuiAction(QObject *parent) + : QGuiAction(*new QGuiActionPrivate, parent) +{ +} + +/*! + Constructs an action with some \a text and \a parent. If \a + parent is an action group the action will be automatically + inserted into the group. + + The action uses a stripped version of \a text (e.g. "\&Menu + Option..." becomes "Menu Option") as descriptive text for + tool buttons. You can override this by setting a specific + description with setText(). The same text will be used for + tooltips unless you specify a different text using + setToolTip(). + +*/ +QGuiAction::QGuiAction(const QString &text, QObject *parent) + : QGuiAction(parent) +{ + Q_D(QGuiAction); + d->text = text; +} + +/*! + Constructs an action with an \a icon and some \a text and \a + parent. If \a parent is an action group the action will be + automatically inserted into the group. + + The action uses a stripped version of \a text (e.g. "\&Menu + Option..." becomes "Menu Option") as descriptive text for + tool buttons. You can override this by setting a specific + description with setText(). The same text will be used for + tooltips unless you specify a different text using + setToolTip(). +*/ +QGuiAction::QGuiAction(const QIcon &icon, const QString &text, QObject *parent) + : QGuiAction(text, parent) +{ + Q_D(QGuiAction); + d->icon = icon; +} + +/*! + \internal +*/ +QGuiAction::QGuiAction(QGuiActionPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ + Q_D(QGuiAction); + d->group = qobject_cast<QGuiActionGroup *>(parent); + if (d->group) + d->group->addAction(this); +} + +#if QT_CONFIG(shortcut) +/*! + \property QGuiAction::shortcut + \brief the action's primary shortcut key + + Valid keycodes for this property can be found in \l Qt::Key and + \l Qt::Modifier. There is no default shortcut key. +*/ +void QGuiAction::setShortcut(const QKeySequence &shortcut) +{ + QAPP_CHECK("setShortcut"); + + Q_D(QGuiAction); + if (d->shortcut == shortcut) + return; + + d->shortcut = shortcut; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->sendDataChanged(); +} + +/*! + Sets \a shortcuts as the list of shortcuts that trigger the + action. The first element of the list is the primary shortcut. + + \sa shortcut +*/ +void QGuiAction::setShortcuts(const QList<QKeySequence> &shortcuts) +{ + Q_D(QGuiAction); + + QList <QKeySequence> listCopy = shortcuts; + + QKeySequence primary; + if (!listCopy.isEmpty()) + primary = listCopy.takeFirst(); + + if (d->shortcut == primary && d->alternateShortcuts == listCopy) + return; + + QAPP_CHECK("setShortcuts"); + + d->shortcut = primary; + d->alternateShortcuts = listCopy; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap); + d->sendDataChanged(); +} + +/*! + Sets a platform dependent list of shortcuts based on the \a key. + The result of calling this function will depend on the currently running platform. + Note that more than one shortcut can assigned by this action. + If only the primary shortcut is required, use setShortcut instead. + + \sa QKeySequence::keyBindings() +*/ +void QGuiAction::setShortcuts(QKeySequence::StandardKey key) +{ + QList <QKeySequence> list = QKeySequence::keyBindings(key); + setShortcuts(list); +} + +/*! + Returns the primary shortcut. + + \sa setShortcuts() +*/ +QKeySequence QGuiAction::shortcut() const +{ + Q_D(const QGuiAction); + return d->shortcut; +} + +/*! + Returns the list of shortcuts, with the primary shortcut as + the first element of the list. + + \sa setShortcuts() +*/ +QList<QKeySequence> QGuiAction::shortcuts() const +{ + Q_D(const QGuiAction); + QList <QKeySequence> shortcuts; + if (!d->shortcut.isEmpty()) + shortcuts << d->shortcut; + if (!d->alternateShortcuts.isEmpty()) + shortcuts << d->alternateShortcuts; + return shortcuts; +} + +/*! + \property QGuiAction::shortcutContext + \brief the context for the action's shortcut + + Valid values for this property can be found in \l Qt::ShortcutContext. + The default value is Qt::WindowShortcut. +*/ +void QGuiAction::setShortcutContext(Qt::ShortcutContext context) +{ + Q_D(QGuiAction); + if (d->shortcutContext == context) + return; + QAPP_CHECK("setShortcutContext"); + d->shortcutContext = context; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap); + d->sendDataChanged(); +} + +Qt::ShortcutContext QGuiAction::shortcutContext() const +{ + Q_D(const QGuiAction); + return d->shortcutContext; +} + +/*! + \property QGuiAction::autoRepeat + \brief whether the action can auto repeat + + If true, the action will auto repeat when the keyboard shortcut + combination is held down, provided that keyboard auto repeat is + enabled on the system. + The default value is true. +*/ +void QGuiAction::setAutoRepeat(bool on) +{ + Q_D(QGuiAction); + if (d->autorepeat == on) + return; + QAPP_CHECK("setAutoRepeat"); + d->autorepeat = on; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap); + d->sendDataChanged(); +} + +bool QGuiAction::autoRepeat() const +{ + Q_D(const QGuiAction); + return d->autorepeat; +} +#endif // QT_CONFIG(shortcut) + +/*! + \property QGuiAction::font + \brief the action's font + + The font property is used to render the text set on the + QAction. The font will can be considered a hint as it will not be + consulted in all cases based upon application and style. + + By default, this property contains the application's default font. + + \sa setText() +*/ +void QGuiAction::setFont(const QFont &font) +{ + Q_D(QGuiAction); + if (d->font == font) + return; + + d->fontSet = true; + d->font = font; + d->sendDataChanged(); +} + +QFont QGuiAction::font() const +{ + Q_D(const QGuiAction); + return d->font; +} + + +/*! + Destroys the object and frees allocated resources. +*/ +QGuiAction::~QGuiAction() +{ + Q_D(QGuiAction); + if (d->group) + d->group->removeAction(this); +#if QT_CONFIG(shortcut) + if (d->shortcutId && qApp) { + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->shortcutId, this); + for (int id : qAsConst(d->alternateShortcutIds)) + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this); + } +#endif +} + +/*! + Sets this action group to \a group. The action will be automatically + added to the group's list of actions. + + Actions within the group will be mutually exclusive. + + \sa QGuiActionGroup, guiActionGroup() +*/ +void QGuiAction::setActionGroup(QGuiActionGroup *group) +{ + Q_D(QGuiAction); + if(group == d->group) + return; + + if(d->group) + d->group->removeAction(this); + d->group = group; + if(group) + group->addAction(this); + d->sendDataChanged(); +} + +/*! + Returns the action group for this action. If no action group manages + this action, then \nullptr will be returned. + + \sa QGuiActionGroup, setActionGroup() +*/ +QGuiActionGroup *QGuiAction::guiActionGroup() const +{ + Q_D(const QGuiAction); + return d->group; +} + + +/*! + \property QGuiAction::icon + \brief the action's icon + + In toolbars, the icon is used as the tool button icon; in menus, + it is displayed to the left of the menu text. There is no default + icon. + + If a null icon (QIcon::isNull()) is passed into this function, + the icon of the action is cleared. +*/ +void QGuiAction::setIcon(const QIcon &icon) +{ + Q_D(QGuiAction); + d->icon = icon; + d->sendDataChanged(); +} + +QIcon QGuiAction::icon() const +{ + Q_D(const QGuiAction); + return d->icon; +} + +/*! + If \a b is true then this action will be considered a separator. + + How a separator is represented depends on the widget it is inserted + into. Under most circumstances the text, submenu, and icon will be + ignored for separator actions. + + \sa isSeparator() +*/ +void QGuiAction::setSeparator(bool b) +{ + Q_D(QGuiAction); + if (d->separator == b) + return; + + d->separator = b; + d->sendDataChanged(); +} + +/*! + Returns \c true if this action is a separator action; otherwise it + returns \c false. + + \sa setSeparator() +*/ +bool QGuiAction::isSeparator() const +{ + Q_D(const QGuiAction); + return d->separator; +} + +/*! + \property QGuiAction::text + \brief the action's descriptive text + + If the action is added to a menu, the menu option will consist of + the icon (if there is one), the text, and the shortcut (if there + is one). If the text is not explicitly set in the constructor, or + by using setText(), the action's description icon text will be + used as text. There is no default text. + + \sa iconText +*/ +void QGuiAction::setText(const QString &text) +{ + Q_D(QGuiAction); + if (d->text == text) + return; + + d->text = text; + d->sendDataChanged(); +} + +QString QGuiAction::text() const +{ + Q_D(const QGuiAction); + QString s = d->text; + if(s.isEmpty()) { + s = d->iconText; + s.replace(QLatin1Char('&'), QLatin1String("&&")); + } + return s; +} + +/*! + \property QGuiAction::iconText + \brief the action's descriptive icon text + + If QToolBar::toolButtonStyle is set to a value that permits text to + be displayed, the text defined held in this property appears as a + label in the relevant tool button. + + It also serves as the default text in menus and tooltips if the action + has not been defined with setText() or setToolTip(), and will + also be used in toolbar buttons if no icon has been defined using setIcon(). + + If the icon text is not explicitly set, the action's normal text will be + used for the icon text. + + By default, this property contains an empty string. + + \sa setToolTip(), setStatusTip() +*/ +void QGuiAction::setIconText(const QString &text) +{ + Q_D(QGuiAction); + if (d->iconText == text) + return; + + d->iconText = text; + d->sendDataChanged(); +} + +QString QGuiAction::iconText() const +{ + Q_D(const QGuiAction); + if (d->iconText.isEmpty()) + return qt_strippedText(d->text); + return d->iconText; +} + +/*! + \property QGuiAction::toolTip + \brief the action's tooltip + + This text is used for the tooltip. If no tooltip is specified, + the action's text is used. + + By default, this property contains the action's text. + + \sa setStatusTip(), setShortcut() +*/ +void QGuiAction::setToolTip(const QString &tooltip) +{ + Q_D(QGuiAction); + if (d->tooltip == tooltip) + return; + + d->tooltip = tooltip; + d->sendDataChanged(); +} + +QString QGuiAction::toolTip() const +{ + Q_D(const QGuiAction); + if (d->tooltip.isEmpty()) { + if (!d->text.isEmpty()) + return qt_strippedText(d->text); + return qt_strippedText(d->iconText); + } + return d->tooltip; +} + +/*! + \property QGuiAction::statusTip + \brief the action's status tip + + The status tip is displayed on all status bars provided by the + action's top-level parent widget. + + By default, this property contains an empty string. + + \sa setToolTip(), showStatusText() +*/ +void QGuiAction::setStatusTip(const QString &statustip) +{ + Q_D(QGuiAction); + if (d->statustip == statustip) + return; + + d->statustip = statustip; + d->sendDataChanged(); +} + +QString QGuiAction::statusTip() const +{ + Q_D(const QGuiAction); + return d->statustip; +} + +/*! + \property QGuiAction::whatsThis + \brief the action's "What's This?" help text + + The "What's This?" text is used to provide a brief description of + the action. The text may contain rich text. There is no default + "What's This?" text. + + \sa QWhatsThis +*/ +void QGuiAction::setWhatsThis(const QString &whatsthis) +{ + Q_D(QGuiAction); + if (d->whatsthis == whatsthis) + return; + + d->whatsthis = whatsthis; + d->sendDataChanged(); +} + +QString QGuiAction::whatsThis() const +{ + Q_D(const QGuiAction); + return d->whatsthis; +} + +/*! + \enum QGuiAction::Priority + + This enum defines priorities for actions in user interface. + + \value LowPriority The action should not be prioritized in + the user interface. + + \value NormalPriority + + \value HighPriority The action should be prioritized in + the user interface. + + \sa priority +*/ + + +/*! + \property QGuiAction::priority + + \brief the actions's priority in the user interface. + + This property can be set to indicate how the action should be prioritized + in the user interface. + + For instance, when toolbars have the Qt::ToolButtonTextBesideIcon + mode set, then actions with LowPriority will not show the text + labels. +*/ +void QGuiAction::setPriority(Priority priority) +{ + Q_D(QGuiAction); + if (d->priority == priority) + return; + + d->priority = priority; + d->sendDataChanged(); +} + +QGuiAction::Priority QGuiAction::priority() const +{ + Q_D(const QGuiAction); + return d->priority; +} + +/*! + \property QGuiAction::checkable + \brief whether the action is a checkable action + + A checkable action is one which has an on/off state. For example, + in a word processor, a Bold toolbar button may be either on or + off. An action which is not a toggle action is a command action; + a command action is simply executed, e.g. file save. + By default, this property is \c false. + + In some situations, the state of one toggle action should depend + on the state of others. For example, "Left Align", "Center" and + "Right Align" toggle actions are mutually exclusive. To achieve + exclusive toggling, add the relevant toggle actions to a + QGuiActionGroup with the QGuiActionGroup::exclusive property set to + true. + + \sa setChecked() +*/ +void QGuiAction::setCheckable(bool b) +{ + Q_D(QGuiAction); + if (d->checkable == b) + return; + + d->checkable = b; + d->checked = false; + d->sendDataChanged(); +} + +bool QGuiAction::isCheckable() const +{ + Q_D(const QGuiAction); + return d->checkable; +} + +/*! + \fn void QGuiAction::toggle() + + This is a convenience function for the \l checked property. + Connect to it to change the checked state to its opposite state. +*/ +void QGuiAction::toggle() +{ + Q_D(QGuiAction); + setChecked(!d->checked); +} + +/*! + \property QGuiAction::checked + \brief whether the action is checked. + + Only checkable actions can be checked. By default, this is false + (the action is unchecked). + + \note The notifier signal for this property is toggled(). As toggling + a QAction changes its state, it will also emit a changed() signal. + + \sa checkable, toggled() +*/ +void QGuiAction::setChecked(bool b) +{ + Q_D(QGuiAction); + if (!d->checkable || d->checked == b) + return; + + QPointer<QGuiAction> guard(this); + d->checked = b; + d->sendDataChanged(); + if (guard) + emit toggled(b); +} + +bool QGuiAction::isChecked() const +{ + Q_D(const QGuiAction); + return d->checked; +} + +/*! + \fn void QGuiAction::setDisabled(bool b) + + This is a convenience function for the \l enabled property, that + is useful for signals--slots connections. If \a b is true the + action is disabled; otherwise it is enabled. +*/ + +/*! + \property QGuiAction::enabled + \brief whether the action is enabled + + Disabled actions cannot be chosen by the user. They do not + disappear from menus or toolbars, but they are displayed in a way + which indicates that they are unavailable. For example, they might + be displayed using only shades of gray. + + \uicontrol{What's This?} help on disabled actions is still available, provided + that the QAction::whatsThis property is set. + + An action will be disabled when all widgets to which it is added + (with QWidget::addAction()) are disabled or not visible. When an + action is disabled, it is not possible to trigger it through its + shortcut. + + By default, this property is \c true (actions are enabled). + + \sa text +*/ +void QGuiAction::setEnabled(bool b) +{ + Q_D(QGuiAction); + if (b == d->enabled && b != d->forceDisabled) + return; + d->forceDisabled = !b; + if (b && (!d->visible || (d->group && !d->group->isEnabled()))) + return; + QAPP_CHECK("setEnabled"); + d->enabled = b; +#if QT_CONFIG(shortcut) + d->setShortcutEnabled(b, QGuiApplicationPrivate::instance()->shortcutMap); +#endif + d->sendDataChanged(); +} + +bool QGuiAction::isEnabled() const +{ + Q_D(const QGuiAction); + return d->enabled; +} + +/*! + \property QGuiAction::visible + \brief whether the action can be seen (e.g. in menus and toolbars) + + If \e visible is true the action can be seen (e.g. in menus and + toolbars) and chosen by the user; if \e visible is false the + action cannot be seen or chosen by the user. + + Actions which are not visible are \e not grayed out; they do not + appear at all. + + By default, this property is \c true (actions are visible). +*/ +void QGuiAction::setVisible(bool b) +{ + Q_D(QGuiAction); + if (b == d->visible && b != d->forceInvisible) + return; + QAPP_CHECK("setVisible"); + d->forceInvisible = !b; + d->visible = b; + d->enabled = b && !d->forceDisabled && (!d->group || d->group->isEnabled()) ; +#if QT_CONFIG(shortcut) + d->setShortcutEnabled(d->enabled, QGuiApplicationPrivate::instance()->shortcutMap); +#endif + d->sendDataChanged(); +} + + +bool QGuiAction::isVisible() const +{ + Q_D(const QGuiAction); + return d->visible; +} + +/*! + \reimp +*/ +bool QGuiAction::event(QEvent *e) +{ +#if QT_CONFIG(shortcut) + if (e->type() == QEvent::Shortcut) { + QShortcutEvent *se = static_cast<QShortcutEvent *>(e); + Q_ASSERT_X(se->key() == d_func()->shortcut || d_func()->alternateShortcuts.contains(se->key()), + "QAction::event", + "Received shortcut event from incorrect shortcut"); + if (se->isAmbiguous()) + qWarning("QAction::event: Ambiguous shortcut overload: %s", se->key().toString(QKeySequence::NativeText).toLatin1().constData()); + else + activate(Trigger); + return true; + } +#endif // QT_CONFIG(shortcut) + return QObject::event(e); +} + +/*! + Returns the user data as set in QAction::setData. + + \sa setData() +*/ +QVariant QGuiAction::data() const +{ + Q_D(const QGuiAction); + return d->userData; +} + +/*! + Sets the action's internal data to the given \a userData. + + \sa data() +*/ +void QGuiAction::setData(const QVariant &data) +{ + Q_D(QGuiAction); + if (d->userData == data) + return; + d->userData = data; + d->sendDataChanged(); +} + +/*! + Sends the relevant signals for ActionEvent \a event. + + Action based widgets use this API to cause the QAction + to emit signals as well as emitting their own. +*/ +void QGuiAction::activate(ActionEvent event) +{ + Q_D(QGuiAction); + if(event == Trigger) { + QPointer<QObject> guard = this; + if(d->checkable) { + // the checked action of an exclusive group may not be unchecked + if (d->checked && (d->group + && d->group->exclusionPolicy() == QGuiActionGroup::ExclusionPolicy::Exclusive + && d->group->checkedGuiAction() == this)) { + if (!guard.isNull()) + emit triggered(true); + return; + } + setChecked(!d->checked); + } + if (!guard.isNull()) + emit triggered(d->checked); + } else if(event == Hover) { + emit hovered(); + } +} + +/*! + \fn void QGuiAction::triggered(bool checked) + + This signal is emitted when an action is activated by the user; + for example, when the user clicks a menu option, toolbar button, + or presses an action's shortcut key combination, or when trigger() + was called. Notably, it is \e not emitted when setChecked() or + toggle() is called. + + If the action is checkable, \a checked is true if the action is + checked, or false if the action is unchecked. + + \sa activate(), toggled(), checked +*/ + +/*! + \fn void QGuiAction::toggled(bool checked) + + This signal is emitted whenever a checkable action changes its + isChecked() status. This can be the result of a user interaction, + or because setChecked() was called. As setChecked() changes the + QAction, it emits changed() in addition to toggled(). + + \a checked is true if the action is checked, or false if the + action is unchecked. + + \sa activate(), triggered(), checked +*/ + +/*! + \fn void QGuiAction::hovered() + + This signal is emitted when an action is highlighted by the user; + for example, when the user pauses with the cursor over a menu option, + toolbar button, or presses an action's shortcut key combination. + + \sa activate() +*/ + +/*! + \fn void QGuiAction::changed() + + This signal is emitted when an action has changed. If you + are only interested in actions in a given widget, you can + watch for QWidget::actionEvent() sent with an + QEvent::ActionChanged. + + \sa QWidget::actionEvent() +*/ + +/*! + \enum QGuiAction::ActionEvent + + This enum type is used when calling QAction::activate() + + \value Trigger this will cause the QAction::triggered() signal to be emitted. + + \value Hover this will cause the QAction::hovered() signal to be emitted. +*/ + +/*! + \property QGuiAction::menuRole + \brief the action's menu role + + This indicates what role the action serves in the application menu on + \macos. By default all actions have the TextHeuristicRole, which means that + the action is added based on its text (see QMenuBar for more information). + + The menu role can only be changed before the actions are put into the menu + bar in \macos (usually just before the first application window is + shown). +*/ +void QGuiAction::setMenuRole(MenuRole menuRole) +{ + Q_D(QGuiAction); + if (d->menuRole == menuRole) + return; + + d->menuRole = menuRole; + d->sendDataChanged(); +} + +QGuiAction::MenuRole QGuiAction::menuRole() const +{ + Q_D(const QGuiAction); + return d->menuRole; +} + +/*! + \property QGuiAction::iconVisibleInMenu + \brief Whether or not an action should show an icon in a menu + + In some applications, it may make sense to have actions with icons in the + toolbar, but not in menus. If true, the icon (if valid) is shown in the menu, when it + is false, it is not shown. + + The default is to follow whether the Qt::AA_DontShowIconsInMenus attribute + is set for the application. Explicitly settings this property overrides + the presence (or abscence) of the attribute. + + For example: + \snippet code/src_gui_kernel_qaction.cpp 0 + + \sa icon, QCoreApplication::setAttribute() +*/ +void QGuiAction::setIconVisibleInMenu(bool visible) +{ + Q_D(QGuiAction); + if (d->iconVisibleInMenu == -1 || visible != bool(d->iconVisibleInMenu)) { + int oldValue = d->iconVisibleInMenu; + d->iconVisibleInMenu = visible; + // Only send data changed if we really need to. + if (oldValue != -1 + || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus)) { + d->sendDataChanged(); + } + } +} + +bool QGuiAction::isIconVisibleInMenu() const +{ + Q_D(const QGuiAction); + if (d->iconVisibleInMenu == -1) { + return !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus); + } + return d->iconVisibleInMenu; +} + +/*! + \property QGuiAction::shortcutVisibleInContextMenu + \brief Whether or not an action should show a shortcut in a context menu + + In some applications, it may make sense to have actions with shortcuts in + context menus. If true, the shortcut (if valid) is shown when the action is + shown via a context menu, when it is false, it is not shown. + + The default is to follow whether the Qt::AA_DontShowShortcutsInContextMenus attribute + is set for the application, falling back to the widget style hint. + Explicitly setting this property overrides the presence (or abscence) of the attribute. + + \sa shortcut, QCoreApplication::setAttribute() +*/ +void QGuiAction::setShortcutVisibleInContextMenu(bool visible) +{ + Q_D(QGuiAction); + if (d->shortcutVisibleInContextMenu == -1 || visible != bool(d->shortcutVisibleInContextMenu)) { + int oldValue = d->shortcutVisibleInContextMenu; + d->shortcutVisibleInContextMenu = visible; + // Only send data changed if we really need to. + if (oldValue != -1 + || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) { + d->sendDataChanged(); + } + } +} + +bool QGuiAction::isShortcutVisibleInContextMenu() const +{ + Q_D(const QGuiAction); + if (d->shortcutVisibleInContextMenu == -1) { + return !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus) + && QGuiApplication::styleHints()->showShortcutsInContextMenus(); + } + return d->shortcutVisibleInContextMenu; +} + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug d, const QGuiAction *action) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "QAction(" << static_cast<const void *>(action); + if (action) { + d << " text=" << action->text(); + if (!action->toolTip().isEmpty()) + d << " toolTip=" << action->toolTip(); + if (action->isCheckable()) + d << " checked=" << action->isChecked(); +#if QT_CONFIG(shortcut) + if (!action->shortcut().isEmpty()) + d << " shortcut=" << action->shortcut(); +#endif + d << " menuRole="; + QtDebugUtils::formatQEnum(d, action->menuRole()); + d << " visible=" << action->isVisible(); + } else { + d << '0'; + } + d << ')'; + return d; +} +#endif // QT_NO_DEBUG_STREAM + +QT_END_NAMESPACE + +#include "moc_qguiaction.cpp" diff --git a/src/gui/kernel/qguiaction.h b/src/gui/kernel/qguiaction.h new file mode 100644 index 0000000000..454f66893f --- /dev/null +++ b/src/gui/kernel/qguiaction.h @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGUIACTION_H +#define QGUIACTION_H + +#include <QtGui/qtguiglobal.h> +#if QT_CONFIG(shortcut) +# include <QtGui/qkeysequence.h> +#endif +#include <QtGui/qicon.h> +#include <QtCore/qstring.h> +#include <QtCore/qvariant.h> + +QT_REQUIRE_CONFIG(action); + +QT_BEGIN_NAMESPACE + +class QActionEvent; +class QGuiActionGroup; +class QGuiActionPrivate; + +class Q_GUI_EXPORT QGuiAction : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QGuiAction) + + Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed) + Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY toggled) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed) + Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed) + Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed) + Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed) + Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed) + Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed) + Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed) +#if QT_CONFIG(shortcut) + Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed) + Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed) + Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed) +#endif // QT_CONFIG(shortcut) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed) + Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed) + Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed) + Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed) + Q_PROPERTY(Priority priority READ priority WRITE setPriority) + +public: + // note this is copied into qplatformmenu.h, which must stay in sync + enum MenuRole { NoRole = 0, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole, + AboutRole, PreferencesRole, QuitRole }; + Q_ENUM(MenuRole) + enum Priority { LowPriority = 0, + NormalPriority = 128, + HighPriority = 256}; + Q_ENUM(Priority) + explicit QGuiAction(QObject *parent = nullptr); + explicit QGuiAction(const QString &text, QObject *parent = nullptr); + explicit QGuiAction(const QIcon &icon, const QString &text, QObject *parent = nullptr); + + ~QGuiAction(); + + void setActionGroup(QGuiActionGroup *group); + QGuiActionGroup *guiActionGroup() const; + void setIcon(const QIcon &icon); + QIcon icon() const; + + void setText(const QString &text); + QString text() const; + + void setIconText(const QString &text); + QString iconText() const; + + void setToolTip(const QString &tip); + QString toolTip() const; + + void setStatusTip(const QString &statusTip); + QString statusTip() const; + + void setWhatsThis(const QString &what); + QString whatsThis() const; + + void setPriority(Priority priority); + Priority priority() const; + + void setSeparator(bool b); + bool isSeparator() const; + +#if QT_CONFIG(shortcut) + void setShortcut(const QKeySequence &shortcut); + QKeySequence shortcut() const; + + void setShortcuts(const QList<QKeySequence> &shortcuts); + void setShortcuts(QKeySequence::StandardKey); + QList<QKeySequence> shortcuts() const; + + void setShortcutContext(Qt::ShortcutContext context); + Qt::ShortcutContext shortcutContext() const; + + void setAutoRepeat(bool); + bool autoRepeat() const; +#endif // QT_CONFIG(shortcut) + + void setFont(const QFont &font); + QFont font() const; + + void setCheckable(bool); + bool isCheckable() const; + + QVariant data() const; + void setData(const QVariant &var); + + bool isChecked() const; + + bool isEnabled() const; + + bool isVisible() const; + + enum ActionEvent { Trigger, Hover }; + void activate(ActionEvent event); + + void setMenuRole(MenuRole menuRole); + MenuRole menuRole() const; + + void setIconVisibleInMenu(bool visible); + bool isIconVisibleInMenu() const; + + void setShortcutVisibleInContextMenu(bool show); + bool isShortcutVisibleInContextMenu() const; + +protected: + bool event(QEvent *) override; + QGuiAction(QGuiActionPrivate &dd, QObject *parent); + +public Q_SLOTS: + void trigger() { activate(Trigger); } + void hover() { activate(Hover); } + void setChecked(bool); + void toggle(); + void setEnabled(bool); + inline void setDisabled(bool b) { setEnabled(!b); } + void setVisible(bool); + +Q_SIGNALS: + void changed(); + void triggered(bool checked = false); + void hovered(); + void toggled(bool); + +private: + Q_DISABLE_COPY(QGuiAction) + friend class QGuiActionGroup; +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QGuiAction *); +#endif + +QT_END_NAMESPACE + +#endif // QGUIACTION_H diff --git a/src/gui/opengl/qopenglpaintdevice_p.h b/src/gui/kernel/qguiaction_p.h index 3683ebebac..3358ed1070 100644 --- a/src/gui/opengl/qopenglpaintdevice_p.h +++ b/src/gui/kernel/qguiaction_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -37,52 +37,92 @@ ** ****************************************************************************/ -#ifndef QOPENGL_PAINTDEVICE_P_H -#define QOPENGL_PAINTDEVICE_P_H +#ifndef QGUIACTION_P_H +#define QGUIACTION_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience -// of the Qt OpenGL classes. This header file may change from -// version to version without notice, or even be removed. +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. // // We mean it. // #include <QtGui/private/qtguiglobal_p.h> -#include <qopenglpaintdevice.h> +#include <QtGui/qguiaction.h> +#include <QtGui/qfont.h> +#if QT_CONFIG(shortcut) +# include <QtGui/private/qshortcutmap_p.h> +#endif +#include "private/qobject_p.h" + +QT_REQUIRE_CONFIG(action); QT_BEGIN_NAMESPACE -class QOpenGLContext; -class QPaintEngine; +class QShortcutMap; -class Q_GUI_EXPORT QOpenGLPaintDevicePrivate +class Q_GUI_EXPORT QGuiActionPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QGuiAction) public: - QOpenGLPaintDevicePrivate(const QSize &size); - virtual ~QOpenGLPaintDevicePrivate(); + QGuiActionPrivate(); + ~QGuiActionPrivate(); - static QOpenGLPaintDevicePrivate *get(QOpenGLPaintDevice *dev) { return dev->d_func(); } +#if QT_CONFIG(shortcut) + virtual QShortcutMap::ContextMatcher contextMatcher() const; +#endif - virtual void beginPaint() { } - virtual void endPaint() { } + static QGuiActionPrivate *get(QGuiAction *q) + { + return q->d_func(); + } -public: - QSize size; - QOpenGLContext *ctx; - qreal dpmx; - qreal dpmy; - qreal devicePixelRatio; + QPointer<QGuiActionGroup> group; + QString text; + QString iconText; + QIcon icon; + QString tooltip; + QString statustip; + QString whatsthis; +#if QT_CONFIG(shortcut) + QKeySequence shortcut; + QList<QKeySequence> alternateShortcuts; +#endif + QVariant userData; +#if QT_CONFIG(shortcut) + int shortcutId = 0; + QVector<int> alternateShortcutIds; + Qt::ShortcutContext shortcutContext = Qt::WindowShortcut; + uint autorepeat : 1; +#endif + QFont font; + uint enabled : 1, forceDisabled : 1; + uint visible : 1, forceInvisible : 1; + uint checkable : 1; + uint checked : 1; + uint separator : 1; + uint fontSet : 1; + + int iconVisibleInMenu : 2; // Only has values -1, 0, and 1 + int shortcutVisibleInContextMenu : 2; // Only has values -1, 0, and 1 + + QGuiAction::MenuRole menuRole = QGuiAction::TextHeuristicRole; + QGuiAction::Priority priority = QGuiAction::NormalPriority; - bool flipped; +#if QT_CONFIG(shortcut) + void redoGrab(QShortcutMap &map); + void redoGrabAlternate(QShortcutMap &map); + void setShortcutEnabled(bool enable, QShortcutMap &map); +#endif // QT_NO_SHORTCUT - QPaintEngine *engine; + void sendDataChanged(); }; QT_END_NAMESPACE -#endif // QOPENGL_PAINTDEVICE_P_H +#endif // QACTION_P_H diff --git a/src/gui/kernel/qguiactiongroup.cpp b/src/gui/kernel/qguiactiongroup.cpp new file mode 100644 index 0000000000..7360214aad --- /dev/null +++ b/src/gui/kernel/qguiactiongroup.cpp @@ -0,0 +1,346 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qguiactiongroup.h" + +#include "qguiaction.h" +#include "qguiaction_p.h" +#include "qguiactiongroup_p.h" +#include "qevent.h" +#include "qlist.h" + +QT_BEGIN_NAMESPACE + +QGuiActionGroupPrivate::QGuiActionGroupPrivate() : + enabled(1), visible(1) +{ +} + +QGuiActionGroupPrivate::~QGuiActionGroupPrivate() = default; + +void QGuiActionGroup::_q_actionChanged() +{ + Q_D(QGuiActionGroup); + auto action = qobject_cast<QGuiAction*>(sender()); + Q_ASSERT_X(action != nullptr, "QGuiActionGroup::_q_actionChanged", "internal error"); + if (d->exclusionPolicy != QGuiActionGroup::ExclusionPolicy::None) { + if (action->isChecked()) { + if (action != d->current) { + if (!d->current.isNull()) + d->current->setChecked(false); + d->current = action; + } + } else if (action == d->current) { + d->current = nullptr; + } + } +} + +void QGuiActionGroup::_q_actionTriggered() +{ + Q_D(QGuiActionGroup); + auto action = qobject_cast<QGuiAction*>(sender()); + Q_ASSERT_X(action != nullptr, "QGuiActionGroup::_q_actionTriggered", "internal error"); + d->emitSignal(QGuiActionGroupPrivate::Triggered, action); +} + +void QGuiActionGroup::_q_actionHovered() +{ + Q_D(QGuiActionGroup); + auto action = qobject_cast<QGuiAction*>(sender()); + Q_ASSERT_X(action != nullptr, "QGuiActionGroup::_q_actionHovered", "internal error"); + d->emitSignal(QGuiActionGroupPrivate::Hovered, action); +} + +/*! + \class QGuiActionGroup + \brief The QGuiActionGroup class groups actions together. + \since 6.0 + + \inmodule QtGui + + QGuiActionGroup is a base class for classes grouping + classes inhheriting QGuiAction objects together. + + In some situations it is useful to group QGuiAction objects together. + For example, if you have a \uicontrol{Left Align} action, a \uicontrol{Right + Align} action, a \uicontrol{Justify} action, and a \uicontrol{Center} action, + only one of these actions should be active at any one time. One + simple way of achieving this is to group the actions together in + an action group, inheriting QGuiActionGroup. + + \sa QGuiAction +*/ + +/*! + \enum QGuiActionGroup::ExclusionPolicy + + This enum specifies the different policies that can be used to + control how the group performs exclusive checking on checkable actions. + + \value None + The actions in the group can be checked independently of each other. + + \value Exclusive + Exactly one action can be checked at any one time. + This is the default policy. + + \value ExclusiveOptional + At most one action can be checked at any one time. The actions + can also be all unchecked. + + \sa exclusionPolicy +*/ + +/*! + Constructs an action group for the \a parent object. + + The action group is exclusive by default. Call setExclusive(false) + to make the action group non-exclusive. To make the group exclusive + but allow unchecking the active action call instead + setExclusionPolicy(QGuiActionGroup::ExclusionPolicy::ExclusiveOptional) +*/ +QGuiActionGroup::QGuiActionGroup(QObject* parent) : + QGuiActionGroup(*new QGuiActionGroupPrivate, parent) +{ +} + +QGuiActionGroup::QGuiActionGroup(QGuiActionGroupPrivate &dd, QObject *parent) : + QObject(dd, parent) +{ +} + +/*! + Destroys the action group. +*/ +QGuiActionGroup::~QGuiActionGroup() = default; + +/*! + \fn QGuiAction *QGuiActionGroup::addAction(QGuiAction *action) + + Adds the \a action to this group, and returns it. + + Normally an action is added to a group by creating it with the + group as its parent, so this function is not usually used. + + \sa QGuiAction::setActionGroup() +*/ +QGuiAction *QGuiActionGroup::addAction(QGuiAction* a) +{ + Q_D(QGuiActionGroup); + if (!d->actions.contains(a)) { + d->actions.append(a); + QObject::connect(a, &QGuiAction::triggered, this, &QGuiActionGroup::_q_actionTriggered); + QObject::connect(a, &QGuiAction::changed, this, &QGuiActionGroup::_q_actionChanged); + QObject::connect(a, &QGuiAction::hovered, this, &QGuiActionGroup::_q_actionHovered); + } + if (!a->d_func()->forceDisabled) { + a->setEnabled(d->enabled); + a->d_func()->forceDisabled = false; + } + if (!a->d_func()->forceInvisible) { + a->setVisible(d->visible); + a->d_func()->forceInvisible = false; + } + if (a->isChecked()) + d->current = a; + QGuiActionGroup *oldGroup = a->d_func()->group; + if (oldGroup != this) { + if (oldGroup) + oldGroup->removeAction(a); + a->d_func()->group = this; + a->d_func()->sendDataChanged(); + } + return a; +} + +/*! + Removes the \a action from this group. The action will have no + parent as a result. + + \sa QGuiAction::setActionGroup() +*/ +void QGuiActionGroup::removeAction(QGuiAction *action) +{ + Q_D(QGuiActionGroup); + if (d->actions.removeAll(action)) { + if (action == d->current) + d->current = nullptr; + QObject::disconnect(action, &QGuiAction::triggered, this, &QGuiActionGroup::_q_actionTriggered); + QObject::disconnect(action, &QGuiAction::changed, this, &QGuiActionGroup::_q_actionChanged); + QObject::disconnect(action, &QGuiAction::hovered, this, &QGuiActionGroup::_q_actionHovered); + action->d_func()->group = nullptr; + } +} + +/*! + Returns the list of this groups's actions. This may be empty. +*/ +QList<QGuiAction*> QGuiActionGroup::guiActions() const +{ + Q_D(const QGuiActionGroup); + return d->actions; +} + +/*! + \brief Enable or disable the group exclusion checking + + This is a convenience method that calls + setExclusionPolicy(ExclusionPolicy::Exclusive) when \a b is true, + else setExclusionPolicy(QActionGroup::ExclusionPolicy::None). + + \sa QGuiActionGroup::exclusionPolicy +*/ +void QGuiActionGroup::setExclusive(bool b) +{ + setExclusionPolicy(b ? QGuiActionGroup::ExclusionPolicy::Exclusive + : QGuiActionGroup::ExclusionPolicy::None); +} + +/*! + \brief Returns true if the group is exclusive + + The group is exclusive if the ExclusionPolicy is either Exclusive + or ExclusionOptional. + +*/ +bool QGuiActionGroup::isExclusive() const +{ + return exclusionPolicy() != QGuiActionGroup::ExclusionPolicy::None; +} + +/*! + \property QGuiActionGroup::exclusionPolicy + \brief This property holds the group exclusive checking policy + + If exclusionPolicy is set to Exclusive, only one checkable + action in the action group can ever be active at any time. If the user + chooses another checkable action in the group, the one they chose becomes + active and the one that was active becomes inactive. If exclusionPolicy is + set to ExclusionOptional the group is exclusive but the active checkable + action in the group can be unchecked leaving the group with no actions + checked. + + \sa QGuiAction::checkable +*/ +void QGuiActionGroup::setExclusionPolicy(QGuiActionGroup::ExclusionPolicy policy) +{ + Q_D(QGuiActionGroup); + d->exclusionPolicy = policy; +} + +QGuiActionGroup::ExclusionPolicy QGuiActionGroup::exclusionPolicy() const +{ + Q_D(const QGuiActionGroup); + return d->exclusionPolicy; +} + +/*! + \fn void QGuiActionGroup::setDisabled(bool b) + + This is a convenience function for the \l enabled property, that + is useful for signals--slots connections. If \a b is true the + action group is disabled; otherwise it is enabled. +*/ + +/*! + \property QGuiActionGroup::enabled + \brief whether the action group is enabled + + Each action in the group will be enabled or disabled unless it + has been explicitly disabled. + + \sa QGuiAction::setEnabled() +*/ +void QGuiActionGroup::setEnabled(bool b) +{ + Q_D(QGuiActionGroup); + d->enabled = b; + for (auto action : qAsConst(d->actions)) { + if (!action->d_func()->forceDisabled) { + action->setEnabled(b); + action->d_func()->forceDisabled = false; + } + } +} + +bool QGuiActionGroup::isEnabled() const +{ + Q_D(const QGuiActionGroup); + return d->enabled; +} + +/*! + Returns the currently checked action in the group, or \nullptr if + none are checked. +*/ +QGuiAction *QGuiActionGroup::checkedGuiAction() const +{ + Q_D(const QGuiActionGroup); + return d->current.data(); +} + +/*! + \property QGuiActionGroup::visible + \brief whether the action group is visible + + Each action in the action group will match the visible state of + this group unless it has been explicitly hidden. + + \sa QGuiAction::setEnabled() +*/ +void QGuiActionGroup::setVisible(bool b) +{ + Q_D(QGuiActionGroup); + d->visible = b; + for (auto action : qAsConst(d->actions)) { + if (!action->d_func()->forceInvisible) { + action->setVisible(b); + action->d_func()->forceInvisible = false; + } + } +} + +bool QGuiActionGroup::isVisible() const +{ + Q_D(const QGuiActionGroup); + return d->visible; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qopenglwindow.h b/src/gui/kernel/qguiactiongroup.h index 7b3bf004a3..ef08fb2e04 100644 --- a/src/gui/kernel/qopenglwindow.h +++ b/src/gui/kernel/qguiactiongroup.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -37,71 +37,68 @@ ** ****************************************************************************/ -#ifndef QOPENGLWINDOW_H -#define QOPENGLWINDOW_H +#ifndef QGUIACTIONGROUP_H +#define QGUIACTIONGROUP_H #include <QtGui/qtguiglobal.h> +#include <QtGui/qguiaction.h> -#ifndef QT_NO_OPENGL - -#include <QtGui/QPaintDeviceWindow> -#include <QtGui/QOpenGLContext> -#include <QtGui/QImage> +QT_REQUIRE_CONFIG(action); QT_BEGIN_NAMESPACE -class QOpenGLWindowPrivate; +class QGuiActionGroupPrivate; -class Q_GUI_EXPORT QOpenGLWindow : public QPaintDeviceWindow +class Q_GUI_EXPORT QGuiActionGroup : public QObject { Q_OBJECT - Q_DECLARE_PRIVATE(QOpenGLWindow) + Q_DECLARE_PRIVATE(QGuiActionGroup) + + Q_PROPERTY(QGuiActionGroup::ExclusionPolicy exclusionPolicy READ exclusionPolicy WRITE setExclusionPolicy) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible) public: - enum UpdateBehavior { - NoPartialUpdate, - PartialUpdateBlit, - PartialUpdateBlend + enum class ExclusionPolicy { + None, + Exclusive, + ExclusiveOptional }; + Q_ENUM(ExclusionPolicy) - explicit QOpenGLWindow(UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr); - explicit QOpenGLWindow(QOpenGLContext *shareContext, UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr); - ~QOpenGLWindow(); - - UpdateBehavior updateBehavior() const; - bool isValid() const; + explicit QGuiActionGroup(QObject *parent); + ~QGuiActionGroup(); - void makeCurrent(); - void doneCurrent(); + QGuiAction *addAction(QGuiAction *a); + void removeAction(QGuiAction *a); + QList<QGuiAction*> guiActions() const; + QGuiAction *checkedGuiAction() const; - QOpenGLContext *context() const; - QOpenGLContext *shareContext() const; + bool isExclusive() const; + bool isEnabled() const; + bool isVisible() const; + ExclusionPolicy exclusionPolicy() const; - GLuint defaultFramebufferObject() const; - QImage grabFramebuffer(); +public Q_SLOTS: + void setEnabled(bool); + inline void setDisabled(bool b) { setEnabled(!b); } + void setVisible(bool); + void setExclusive(bool); + void setExclusionPolicy(ExclusionPolicy policy); -Q_SIGNALS: - void frameSwapped(); +private Q_SLOTS: + void _q_actionTriggered(); + void _q_actionHovered(); + void _q_actionChanged(); protected: - virtual void initializeGL(); - virtual void resizeGL(int w, int h); - virtual void paintGL(); - virtual void paintUnderGL(); - virtual void paintOverGL(); - - void paintEvent(QPaintEvent *event) override; - void resizeEvent(QResizeEvent *event) override; - int metric(PaintDeviceMetric metric) const override; - QPaintDevice *redirected(QPoint *) const override; + QGuiActionGroup(QGuiActionGroupPrivate &dd, QObject *parent); private: - Q_DISABLE_COPY(QOpenGLWindow) + Q_DISABLE_COPY(QGuiActionGroup) }; QT_END_NAMESPACE -#endif // QT_NO_OPENGL - -#endif +#endif // QGUIACTIONGROUP_H diff --git a/src/gui/opengl/qopenglshadercache_p.h b/src/gui/kernel/qguiactiongroup_p.h index 0f730602b0..99a58262c9 100644 --- a/src/gui/opengl/qopenglshadercache_p.h +++ b/src/gui/kernel/qguiactiongroup_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -37,50 +37,55 @@ ** ****************************************************************************/ +#ifndef QGUIACTIONGROUP_P_H +#define QGUIACTIONGROUP_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 +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to // version without notice, or even be removed. // // We mean it. // -#ifndef QOPENGLSHADERCACHE_P_H -#define QOPENGLSHADERCACHE_P_H - #include <QtGui/private/qtguiglobal_p.h> +#include <QtGui/qguiactiongroup.h> +#include <QtGui/qfont.h> +#if QT_CONFIG(shortcut) +# include <QtGui/private/qshortcutmap_p.h> +#endif +#include "private/qobject_p.h" -QT_BEGIN_NAMESPACE - +QT_REQUIRE_CONFIG(action); -class QOpenGLShaderProgram; -class QOpenGLContext; +QT_BEGIN_NAMESPACE -class CachedShader +class Q_GUI_EXPORT QGuiActionGroupPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QGuiActionGroup) public: - inline CachedShader(const QByteArray &, const QByteArray &) - {} + enum Signal { Triggered, Hovered }; - inline bool isCached() - { - return false; - } + QGuiActionGroupPrivate(); + ~QGuiActionGroupPrivate(); - inline bool load(QOpenGLShaderProgram *, QOpenGLContext *) - { - return false; - } + virtual void emitSignal(Signal, QGuiAction *) {} - inline bool store(QOpenGLShaderProgram *, QOpenGLContext *) - { - return false; - } + QList<QGuiAction *> actions; + QPointer<QGuiAction> current; + uint enabled : 1; + uint visible : 1; + QGuiActionGroup::ExclusionPolicy exclusionPolicy = QGuiActionGroup::ExclusionPolicy::Exclusive; + +private: + void _q_actionTriggered(); //private slot + void _q_actionChanged(); //private slot + void _q_actionHovered(); //private slot }; QT_END_NAMESPACE -#endif +#endif // QACTIONGROUP_P_H diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 1190bd1936..a723ca6e7f 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1205,14 +1205,18 @@ Q_LOGGING_CATEGORY(lcQpaPluginLoading, "qt.qpa.plugin"); static void init_platform(const QString &pluginNamesWithArguments, const QString &platformPluginPath, const QString &platformThemeName, int &argc, char **argv) { - QStringList plugins = pluginNamesWithArguments.split(QLatin1Char(';')); + QStringList plugins = pluginNamesWithArguments.split(QLatin1Char(';'), QString::SkipEmptyParts); QStringList platformArguments; QStringList availablePlugins = QPlatformIntegrationFactory::keys(platformPluginPath); for (const auto &pluginArgument : plugins) { // Split into platform name and arguments - QStringList arguments = pluginArgument.split(QLatin1Char(':')); + QStringList arguments = pluginArgument.split(QLatin1Char(':'), QString::SkipEmptyParts); + if (arguments.isEmpty()) + continue; const QString name = arguments.takeFirst().toLower(); QString argumentsKey = name; + if (name.isEmpty()) + continue; argumentsKey[0] = argumentsKey.at(0).toUpper(); arguments.append(QLibraryInfo::platformPluginArguments(argumentsKey)); diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 5239b58c97..dc2963aee7 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -62,7 +62,10 @@ #include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface_p.h> -#include "private/qshortcutmap_p.h" +#if QT_CONFIG(shortcut) +# include "private/qshortcutmap_p.h" +#endif + #include <qicon.h> QT_BEGIN_NAMESPACE @@ -263,7 +266,7 @@ public: QIcon forcedWindowIcon; static QList<QObject *> generic_plugin_list; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) QShortcutMap shortcutMap; #endif diff --git a/src/gui/kernel/qguishortcut.cpp b/src/gui/kernel/qguishortcut.cpp new file mode 100644 index 0000000000..add1dce12e --- /dev/null +++ b/src/gui/kernel/qguishortcut.cpp @@ -0,0 +1,354 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qguishortcut.h" +#include "qguishortcut_p.h" + +#include <qevent.h> +#include <qguiapplication.h> +#include <qwindow.h> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformmenu.h> + +QT_BEGIN_NAMESPACE + +#define QAPP_CHECK(functionName) \ + if (Q_UNLIKELY(!qApp)) { \ + qWarning("QGuiShortcut: Initialize QGuiApplication before calling '" functionName "'."); \ + return; \ + } + +/*! + \class QGuiShortcut + \brief The QGuiShortcut class is a base class for handling keyboard shortcuts. + + \ingroup events + \inmodule QtGui + \since 6.0 + + The QGuiShortcut class is a base class for classes providing a way of + connecting keyboard shortcuts to Qt's \l{signals and slots} mechanism, + so that objects can be informed when a shortcut is executed. The shortcut + can be set up to contain all the key presses necessary to + describe a keyboard shortcut, including the states of modifier + keys such as \uicontrol Shift, \uicontrol Ctrl, and \uicontrol Alt. + + \target mnemonic + + \sa QShortcutEvent, QKeySequence, QAction +*/ + +/*! + \fn void QGuiShortcut::activated() + + This signal is emitted when the user types the shortcut's key + sequence. + + \sa activatedAmbiguously() +*/ + +/*! + \fn void QGuiShortcut::activatedAmbiguously() + + When a key sequence is being typed at the keyboard, it is said to + be ambiguous as long as it matches the start of more than one + shortcut. + + When a shortcut's key sequence is completed, + activatedAmbiguously() is emitted if the key sequence is still + ambiguous (i.e., it is the start of one or more other shortcuts). + The activated() signal is not emitted in this case. + + \sa activated() +*/ + +static bool simpleContextMatcher(QObject *object, Qt::ShortcutContext context) +{ + auto guiShortcut = qobject_cast<QGuiShortcut *>(object); + if (QGuiApplication::applicationState() != Qt::ApplicationActive || guiShortcut == nullptr) + return false; + if (context == Qt::ApplicationShortcut) + return true; + auto focusWindow = QGuiApplication::focusWindow(); + if (!focusWindow) + return false; + auto window = qobject_cast<const QWindow *>(guiShortcut->parent()); + if (!window) + return false; + if (focusWindow == window && focusWindow->isTopLevel()) + return context == Qt::WindowShortcut || context == Qt::WidgetWithChildrenShortcut; + return focusWindow->isAncestorOf(window, QWindow::ExcludeTransients); +} + +QShortcutMap::ContextMatcher QGuiShortcutPrivate::contextMatcher() const +{ + return simpleContextMatcher; +} + +void QGuiShortcutPrivate::redoGrab(QShortcutMap &map) +{ + Q_Q(QGuiShortcut); + if (Q_UNLIKELY(!parent)) { + qWarning("QGuiShortcut: No window parent defined"); + return; + } + + if (sc_id) + map.removeShortcut(sc_id, q); + if (sc_sequence.isEmpty()) + return; + sc_id = map.addShortcut(q, sc_sequence, sc_context, contextMatcher()); + if (!sc_enabled) + map.setShortcutEnabled(false, sc_id, q); + if (!sc_autorepeat) + map.setShortcutAutoRepeat(false, sc_id, q); +} + +/*! + Constructs a QGuiShortcut object for the \a parent window. Since no + shortcut key sequence is specified, the shortcut will not emit any + signals. + + \sa setKey() +*/ +QGuiShortcut::QGuiShortcut(QWindow *parent) + : QGuiShortcut(*new QGuiShortcutPrivate, parent) +{ +} + +/*! + Constructs a QGuiShortcut object for the \a parent window. The shortcut + operates on its parent, listening for \l{QShortcutEvent}s that + match the \a key sequence. Depending on the ambiguity of the + event, the shortcut will call the \a member function, or the \a + ambiguousMember function, if the key press was in the shortcut's + \a context. +*/ +QGuiShortcut::QGuiShortcut(const QKeySequence &key, QWindow *parent, + const char *member, const char *ambiguousMember, + Qt::ShortcutContext context) + : QGuiShortcut(*new QGuiShortcutPrivate, key, parent, member, ambiguousMember, context) +{ +} + +/*! + \internal +*/ +QGuiShortcut::QGuiShortcut(QGuiShortcutPrivate &dd, QObject *parent) + : QObject(dd, parent) +{ + Q_ASSERT(parent != nullptr); +} + +/*! + \internal +*/ +QGuiShortcut::QGuiShortcut(QGuiShortcutPrivate &dd, + const QKeySequence &key, QObject *parent, + const char *member, const char *ambiguousMember, + Qt::ShortcutContext context) + : QGuiShortcut(dd, parent) +{ + QAPP_CHECK("QGuiShortcut"); + + Q_D(QGuiShortcut); + d->sc_context = context; + d->sc_sequence = key; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + if (member) + connect(this, SIGNAL(activated()), parent, member); + if (ambiguousMember) + connect(this, SIGNAL(activatedAmbiguously()), parent, ambiguousMember); +} + +/*! + Destroys the shortcut. +*/ +QGuiShortcut::~QGuiShortcut() +{ + Q_D(QGuiShortcut); + if (qApp) + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->sc_id, this); +} + +/*! + \property QGuiShortcut::key + \brief the shortcut's key sequence + + This is a key sequence with an optional combination of Shift, Ctrl, + and Alt. The key sequence may be supplied in a number of ways: + + \snippet code/src_gui_kernel_qshortcut.cpp 1 + + By default, this property contains an empty key sequence. +*/ +void QGuiShortcut::setKey(const QKeySequence &key) +{ + Q_D(QGuiShortcut); + if (d->sc_sequence == key) + return; + QAPP_CHECK("setKey"); + d->sc_sequence = key; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); +} + +QKeySequence QGuiShortcut::key() const +{ + Q_D(const QGuiShortcut); + return d->sc_sequence; +} + +/*! + \property QGuiShortcut::enabled + \brief whether the shortcut is enabled + + An enabled shortcut emits the activated() or activatedAmbiguously() + signal when a QShortcutEvent occurs that matches the shortcut's + key() sequence. + + If the application is in \c WhatsThis mode the shortcut will not emit + the signals, but will show the "What's This?" text instead. + + By default, this property is \c true. + + \sa whatsThis +*/ +void QGuiShortcut::setEnabled(bool enable) +{ + Q_D(QGuiShortcut); + if (d->sc_enabled == enable) + return; + QAPP_CHECK("setEnabled"); + d->sc_enabled = enable; + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this); +} + +bool QGuiShortcut::isEnabled() const +{ + Q_D(const QGuiShortcut); + return d->sc_enabled; +} + +/*! + \property QGuiShortcut::context + \brief the context in which the shortcut is valid + + A shortcut's context decides in which circumstances a shortcut is + allowed to be triggered. The normal context is Qt::WindowShortcut, + which allows the shortcut to trigger if the parent (the widget + containing the shortcut) is a subwidget of the active top-level + window. + + By default, this property is set to Qt::WindowShortcut. +*/ +void QGuiShortcut::setContext(Qt::ShortcutContext context) +{ + Q_D(QGuiShortcut); + if (d->sc_context == context) + return; + QAPP_CHECK("setContext"); + d->sc_context = context; + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); +} + +Qt::ShortcutContext QGuiShortcut::context() const +{ + Q_D(const QGuiShortcut); + return d->sc_context; +} + +/*! + \property QGuiShortcut::autoRepeat + \brief whether the shortcut can auto repeat + + If true, the shortcut will auto repeat when the keyboard shortcut + combination is held down, provided that keyboard auto repeat is + enabled on the system. + The default value is true. +*/ +void QGuiShortcut::setAutoRepeat(bool on) +{ + Q_D(QGuiShortcut); + if (d->sc_autorepeat == on) + return; + QAPP_CHECK("setAutoRepeat"); + d->sc_autorepeat = on; + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this); +} + +bool QGuiShortcut::autoRepeat() const +{ + Q_D(const QGuiShortcut); + return d->sc_autorepeat; +} + +/*! + Returns the shortcut's ID. + + \sa QShortcutEvent::shortcutId() +*/ +int QGuiShortcut::id() const +{ + Q_D(const QGuiShortcut); + return d->sc_id; +} + +/*! + \internal +*/ +bool QGuiShortcut::event(QEvent *e) +{ + Q_D(QGuiShortcut); + if (d->sc_enabled && e->type() == QEvent::Shortcut) { + auto se = static_cast<QShortcutEvent *>(e); + if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence + && !d->handleWhatsThis()) { + if (se->isAmbiguous()) + emit activatedAmbiguously(); + else + emit activated(); + return true; + } + } + return QObject::event(e); +} + +QT_END_NAMESPACE + +#include "moc_qguishortcut.cpp" diff --git a/src/gui/opengl/qopengltimerquery.h b/src/gui/kernel/qguishortcut.h index 27da74a3fb..fb64f10c84 100644 --- a/src/gui/opengl/qopengltimerquery.h +++ b/src/gui/kernel/qguishortcut.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -37,80 +37,62 @@ ** ****************************************************************************/ -#ifndef QOPENGLTIMERQUERY_H -#define QOPENGLTIMERQUERY_H +#ifndef QGUISHORTCUT_H +#define QGUISHORTCUT_H #include <QtGui/qtguiglobal.h> +#include <QtGui/qkeysequence.h> +#include <QtCore/qobject.h> -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) - -#include <QtCore/QObject> -#include <QtGui/qopengl.h> +QT_REQUIRE_CONFIG(shortcut); QT_BEGIN_NAMESPACE -class QOpenGLTimerQueryPrivate; +class QGuiShortcutPrivate; +class QWindow; -class Q_GUI_EXPORT QOpenGLTimerQuery : public QObject +class Q_GUI_EXPORT QGuiShortcut : public QObject { Q_OBJECT - + Q_DECLARE_PRIVATE(QGuiShortcut) + Q_PROPERTY(QKeySequence key READ key WRITE setKey) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) + Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat) + Q_PROPERTY(Qt::ShortcutContext context READ context WRITE setContext) public: - explicit QOpenGLTimerQuery(QObject *parent = nullptr); - ~QOpenGLTimerQuery(); - - bool create(); - void destroy(); - bool isCreated() const; - GLuint objectId() const; - - void begin(); - void end(); - GLuint64 waitForTimestamp() const; - void recordTimestamp(); - bool isResultAvailable() const; - GLuint64 waitForResult() const; - -private: - Q_DECLARE_PRIVATE(QOpenGLTimerQuery) - Q_DISABLE_COPY(QOpenGLTimerQuery) -}; - - -class QOpenGLTimeMonitorPrivate; + explicit QGuiShortcut(QWindow *parent); + explicit QGuiShortcut(const QKeySequence& key, QWindow *parent, + const char *member = nullptr, const char *ambiguousMember = nullptr, + Qt::ShortcutContext context = Qt::WindowShortcut); + ~QGuiShortcut(); -class Q_GUI_EXPORT QOpenGLTimeMonitor : public QObject -{ - Q_OBJECT + void setKey(const QKeySequence& key); + QKeySequence key() const; -public: - explicit QOpenGLTimeMonitor(QObject *parent = nullptr); - ~QOpenGLTimeMonitor(); + void setEnabled(bool enable); + bool isEnabled() const; - void setSampleCount(int sampleCount); - int sampleCount() const; + void setContext(Qt::ShortcutContext context); + Qt::ShortcutContext context() const; - bool create(); - void destroy(); - bool isCreated() const; - QVector<GLuint> objectIds() const; + void setAutoRepeat(bool on); + bool autoRepeat() const; - int recordSample(); + int id() const; - bool isResultAvailable() const; +Q_SIGNALS: + void activated(); + void activatedAmbiguously(); - QVector<GLuint64> waitForSamples() const; - QVector<GLuint64> waitForIntervals() const; +protected: + QGuiShortcut(QGuiShortcutPrivate &dd, QObject *parent); + QGuiShortcut(QGuiShortcutPrivate &dd, const QKeySequence& key, QObject *parent, + const char *member, const char *ambiguousMember, + Qt::ShortcutContext context); - void reset(); - -private: - Q_DECLARE_PRIVATE(QOpenGLTimeMonitor) - Q_DISABLE_COPY(QOpenGLTimeMonitor) + bool event(QEvent *e) override; }; QT_END_NAMESPACE -#endif // QT_NO_OPENGL - -#endif // QOPENGLTIMERQUERY_H +#endif // QGUISHORTCUT_H diff --git a/src/gui/opengl/qopenglcustomshaderstage_p.h b/src/gui/kernel/qguishortcut_p.h index ce3e9efd23..420b02ef1a 100644 --- a/src/gui/opengl/qopenglcustomshaderstage_p.h +++ b/src/gui/kernel/qguishortcut_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -37,54 +37,56 @@ ** ****************************************************************************/ -#ifndef QOPENGL_CUSTOM_SHADER_STAGE_H -#define QOPENGL_CUSTOM_SHADER_STAGE_H +#ifndef QGUISHORTCUT_P_H +#define QGUISHORTCUT_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 +// 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/private/qtguiglobal_p.h> -#include <QOpenGLShaderProgram> +#include "qguishortcut.h" +#include <QtGui/qkeysequence.h> -QT_BEGIN_NAMESPACE +#include <QtCore/qstring.h> +#include <QtCore/private/qobject_p.h> +#include <private/qshortcutmap_p.h> -class QPainter; -class QOpenGLCustomShaderStagePrivate; -class Q_GUI_EXPORT QOpenGLCustomShaderStage -{ - Q_DECLARE_PRIVATE(QOpenGLCustomShaderStage) -public: - QOpenGLCustomShaderStage(); - virtual ~QOpenGLCustomShaderStage(); - virtual void setUniforms(QOpenGLShaderProgram*) {} - void setUniformsDirty(); - bool setOnPainter(QPainter*); - void removeFromPainter(QPainter*); - QByteArray source() const; +QT_BEGIN_NAMESPACE - void setInactive(); -protected: - void setSource(const QByteArray&); +class QShortcutMap; -private: - QOpenGLCustomShaderStagePrivate* d_ptr; +/* + \internal + Private data accessed through d-pointer. +*/ +class Q_GUI_EXPORT QGuiShortcutPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGuiShortcut) +public: + QGuiShortcutPrivate() = default; - Q_DISABLE_COPY_MOVE(QOpenGLCustomShaderStage) -}; + virtual QShortcutMap::ContextMatcher contextMatcher() const; + virtual bool handleWhatsThis() { return false; } + QKeySequence sc_sequence; + Qt::ShortcutContext sc_context = Qt::WindowShortcut; + bool sc_enabled = true; + bool sc_autorepeat = true; + int sc_id = 0; + void redoGrab(QShortcutMap &map); +}; QT_END_NAMESPACE - -#endif +#endif // QGUISHORTCUT_P_H diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp index 215b2b1d74..94296dd6fc 100644 --- a/src/gui/kernel/qguivariant.cpp +++ b/src/gui/kernel/qguivariant.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -45,7 +45,9 @@ #include "qcursor.h" #include "qfont.h" #include "qimage.h" -#include "qkeysequence.h" +#if QT_CONFIG(shortcut) +# include "qkeysequence.h" +#endif #include "qtransform.h" #include "qmatrix.h" #include "qpalette.h" @@ -189,7 +191,7 @@ static bool convert(const QVariant::Private *d, int t, case QMetaType::QString: { QString *str = static_cast<QString *>(result); switch (d->type) { -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) case QMetaType::QKeySequence: *str = (*v_cast<QKeySequence>(d)).toString(QKeySequence::NativeText); return true; @@ -239,7 +241,7 @@ static bool convert(const QVariant::Private *d, int t, return true; } break; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) case QMetaType::Int: if (d->type == QMetaType::QKeySequence) { const QKeySequence &seq = *v_cast<QKeySequence>(d); @@ -278,7 +280,7 @@ static bool convert(const QVariant::Private *d, int t, return true; } break; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) case QMetaType::QKeySequence: { QKeySequence *seq = static_cast<QKeySequence *>(result); switch (d->type) { diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h index 8364557020..fd53747fdd 100644 --- a/src/gui/kernel/qkeymapper_p.h +++ b/src/gui/kernel/qkeymapper_p.h @@ -53,7 +53,6 @@ #include <QtGui/private/qtguiglobal_p.h> #include <qobject.h> #include <private/qobject_p.h> -#include <qkeysequence.h> #include <qlist.h> #include <qlocale.h> #include <qevent.h> diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 3a3dd42cae..57a89bb8c2 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -42,8 +42,6 @@ #include <qpa/qplatformtheme.h> #include "private/qguiapplication_p.h" -#if !defined(QT_NO_SHORTCUT) || defined(Q_CLANG_QDOC) - #include "qdebug.h" #include <QtCore/qhashfunctions.h> #ifndef QT_NO_DATASTREAM @@ -1679,9 +1677,6 @@ QDebug operator<<(QDebug dbg, const QKeySequence &p) } #endif -#endif // QT_NO_SHORTCUT - - /*! \typedef QKeySequence::DataPtr \internal diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index 3dcbbe5941..68f256c37a 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -44,10 +44,9 @@ #include <QtCore/qstring.h> #include <QtCore/qobjectdefs.h> -QT_BEGIN_NAMESPACE - +QT_REQUIRE_CONFIG(shortcut); -#if !defined(QT_NO_SHORTCUT) || defined(Q_CLANG_QDOC) +QT_BEGIN_NAMESPACE class QKeySequence; @@ -227,17 +226,6 @@ Q_DECLARE_SHARED(QKeySequence) Q_GUI_EXPORT QDebug operator<<(QDebug, const QKeySequence &); #endif -#else - -class Q_GUI_EXPORT QKeySequence -{ -public: - QKeySequence() {} - QKeySequence(int) {} -}; - -#endif // QT_NO_SHORTCUT - QT_END_NAMESPACE #endif // QKEYSEQUENCE_H diff --git a/src/gui/kernel/qkeysequence_p.h b/src/gui/kernel/qkeysequence_p.h index fbcab5d34e..8c59505561 100644 --- a/src/gui/kernel/qkeysequence_p.h +++ b/src/gui/kernel/qkeysequence_p.h @@ -56,9 +56,10 @@ #include <algorithm> +QT_REQUIRE_CONFIG(shortcut); + QT_BEGIN_NAMESPACE -#ifndef QT_NO_SHORTCUT struct QKeyBinding { QKeySequence::StandardKey standardKey; @@ -87,7 +88,6 @@ public: Q_GUI_EXPORT static QString keyName(int key, QKeySequence::SequenceFormat format); static int decodeString(QString accel, QKeySequence::SequenceFormat format); }; -#endif // QT_NO_SHORTCUT QT_END_NAMESPACE diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index ac5e279a79..fbaff74561 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -56,8 +56,6 @@ #include <private/qopenglextensions_p.h> #include <private/qopenglversionfunctionsfactory_p.h> -#include <private/qopengltexturehelper_p.h> - #include <QDebug> #ifndef QT_OPENGL_ES_2 @@ -664,7 +662,10 @@ void QOpenGLContext::destroy() qDeleteAll(d->versionFunctions); d->versionFunctions.clear(); - delete d->textureFunctions; + if (d->textureFunctionsDestroyCallback) { + d->textureFunctionsDestroyCallback(); + d->textureFunctionsDestroyCallback = nullptr; + } d->textureFunctions = nullptr; d->nativeHandle = QVariant(); @@ -1388,10 +1389,11 @@ QOpenGLTextureHelper* QOpenGLContext::textureFunctions() const /*! \internal */ -void QOpenGLContext::setTextureFunctions(QOpenGLTextureHelper* textureFuncs) +void QOpenGLContext::setTextureFunctions(QOpenGLTextureHelper* textureFuncs, std::function<void()> destroyCallback) { Q_D(QOpenGLContext); d->textureFunctions = textureFuncs; + d->textureFunctionsDestroyCallback = destroyCallback; } /*! diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index 9cfaa52f17..f19dde465a 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -243,7 +243,7 @@ private: void removeExternalFunctions(QAbstractOpenGLFunctions *f); QOpenGLTextureHelper* textureFunctions() const; - void setTextureFunctions(QOpenGLTextureHelper* textureFuncs); + void setTextureFunctions(QOpenGLTextureHelper* textureFuncs, std::function<void()> destroyCallback); void destroy(); diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index 833cfb20c3..7770b1ce02 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -240,6 +240,7 @@ public: QOpenGLFunctions *functions; mutable QSet<QByteArray> extensionNames; QOpenGLTextureHelper* textureFunctions; + std::function<void()> textureFunctionsDestroyCallback; GLint max_texture_size; diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp deleted file mode 100644 index 2ea8f43711..0000000000 --- a/src/gui/kernel/qopenglwindow.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopenglwindow.h" -#include "qpaintdevicewindow_p.h" -#include <QtGui/QOpenGLFramebufferObject> -#include <QtGui/QOpenGLPaintDevice> -#include <QtGui/QOpenGLFunctions> -#include <QtGui/QOpenGLTextureBlitter> -#include <QtGui/private/qopenglextensions_p.h> -#include <QtGui/private/qopenglcontext_p.h> -#include <QtGui/QMatrix4x4> -#include <QtGui/QOffscreenSurface> - -QT_BEGIN_NAMESPACE - -/*! - \class QOpenGLWindow - \inmodule QtGui - \since 5.4 - \brief The QOpenGLWindow class is a convenience subclass of QWindow to perform OpenGL painting. - - QOpenGLWindow is an enhanced QWindow that allows easily creating windows that - perform OpenGL rendering using an API that is compatible with QOpenGLWidget - and is similar to the legacy QGLWidget. Unlike QOpenGLWidget, QOpenGLWindow - has no dependency on the widgets module and offers better performance. - - A typical application will subclass QOpenGLWindow and reimplement the following - virtual functions: - - \list - - \li initializeGL() to perform OpenGL resource initialization - - \li resizeGL() to set up the transformation matrices and other window size dependent resources - - \li paintGL() to issue OpenGL commands or draw using QPainter - - \endlist - - To schedule a repaint, call the update() function. Note that this will not - immediately result in a call to paintGL(). Calling update() multiple times in - a row will not change the behavior in any way. - - This is a slot so it can be connected to a \l QTimer::timeout() signal to - perform animation. Note however that in the modern OpenGL world it is a much - better choice to rely on synchronization to the vertical refresh rate of the - display. See \l{QSurfaceFormat::setSwapInterval()}{setSwapInterval()} on a - description of the swap interval. With a swap interval of \c 1, which is the - case on most systems by default, the - \l{QOpenGLContext::swapBuffers()}{swapBuffers()} call, that is executed - internally by QOpenGLWindow after each repaint, will block and wait for - vsync. This means that whenever the swap is done, an update can be scheduled - again by calling update(), without relying on timers. - - To request a specific configuration for the context, use setFormat() - like for any other QWindow. This allows, among others, requesting a - given OpenGL version and profile, or enabling depth and stencil - buffers. - - Unlike QWindow, QOpenGLWindow allows opening a painter on itself and perform - QPainter-based drawing. - - QOpenGLWindow supports multiple update behaviors. The default, - \c NoPartialUpdate is equivalent to a regular, OpenGL-based QWindow or the - legacy QGLWidget. In contrast, \c PartialUpdateBlit and \c PartialUpdateBlend are - more in line with QOpenGLWidget's way of working, where there is always an - extra, dedicated framebuffer object present. These modes allow, by - sacrificing some performance, redrawing only a smaller area on each paint and - having the rest of the content preserved from of the previous frame. This is - useful for applications than render incrementally using QPainter, because - this way they do not have to redraw the entire window content on each - paintGL() call. - - Similarly to QOpenGLWidget, QOpenGLWindow supports the Qt::AA_ShareOpenGLContexts - attribute. When enabled, the OpenGL contexts of all QOpenGLWindow instances will share - with each other. This allows accessing each other's shareable OpenGL resources. - - For more information on graphics in Qt, see \l {Graphics}. - */ - -/*! - \enum QOpenGLWindow::UpdateBehavior - - This enum describes the update strategy of the QOpenGLWindow. - - \value NoPartialUpdate Indicates that the entire window surface will - redrawn on each update and so no additional framebuffers are needed. - This is the setting used in most cases and is equivalent to how drawing - directly via QWindow would function. - - \value PartialUpdateBlit Indicates that the drawing performed in paintGL() - does not cover the entire window. In this case an extra framebuffer object - is created under the hood, and rendering performed in paintGL() will target - this framebuffer. This framebuffer is then blitted onto the window surface's - default framebuffer after each paint. This allows having QPainter-based drawing - code in paintGL() which only repaints a smaller area at a time, because, unlike - NoPartialUpdate, the previous content is preserved. - - \value PartialUpdateBlend Similar to PartialUpdateBlit, but instead of using - framebuffer blits, the contents of the extra framebuffer is rendered by - drawing a textured quad with blending enabled. This, unlike PartialUpdateBlit, - allows alpha blended content and works even when the glBlitFramebuffer is - not available. Performance-wise this setting is likely to be somewhat slower - than PartialUpdateBlit. - */ - -/*! - \fn void QOpenGLWindow::frameSwapped() - - This signal is emitted after the potentially blocking - \l{QOpenGLContext::swapBuffers()}{buffer swap} has been done. Applications - that wish to continuously repaint synchronized to the vertical refresh, - should issue an update() upon this signal. This allows for a much smoother - experience compared to the traditional usage of timers. -*/ - -// GLES2 builds won't have these constants with the suffixless names -#ifndef GL_READ_FRAMEBUFFER -#define GL_READ_FRAMEBUFFER 0x8CA8 -#endif -#ifndef GL_DRAW_FRAMEBUFFER -#define GL_DRAW_FRAMEBUFFER 0x8CA9 -#endif - -class QOpenGLWindowPaintDevice : public QOpenGLPaintDevice -{ -public: - QOpenGLWindowPaintDevice(QOpenGLWindow *window) : m_window(window) { } - void ensureActiveTarget() override; - - QOpenGLWindow *m_window; -}; - -class QOpenGLWindowPrivate : public QPaintDeviceWindowPrivate -{ - Q_DECLARE_PUBLIC(QOpenGLWindow) -public: - QOpenGLWindowPrivate(QOpenGLContext *shareContext, QOpenGLWindow::UpdateBehavior updateBehavior) - : updateBehavior(updateBehavior) - , hasFboBlit(false) - , shareContext(shareContext) - { - if (!shareContext) - this->shareContext = qt_gl_global_share_context(); - } - - ~QOpenGLWindowPrivate(); - - static QOpenGLWindowPrivate *get(QOpenGLWindow *w) { return w->d_func(); } - - void bindFBO(); - void initialize(); - - void beginPaint(const QRegion ®ion) override; - void endPaint() override; - void flush(const QRegion ®ion) override; - - QOpenGLWindow::UpdateBehavior updateBehavior; - bool hasFboBlit; - QScopedPointer<QOpenGLContext> context; - QOpenGLContext *shareContext; - QScopedPointer<QOpenGLFramebufferObject> fbo; - QScopedPointer<QOpenGLWindowPaintDevice> paintDevice; - QOpenGLTextureBlitter blitter; - QColor backgroundColor; - QScopedPointer<QOffscreenSurface> offscreenSurface; -}; - -QOpenGLWindowPrivate::~QOpenGLWindowPrivate() -{ - Q_Q(QOpenGLWindow); - if (q->isValid()) { - q->makeCurrent(); // this works even when the platformwindow is destroyed - paintDevice.reset(nullptr); - fbo.reset(nullptr); - blitter.destroy(); - q->doneCurrent(); - } -} - -void QOpenGLWindowPrivate::initialize() -{ - Q_Q(QOpenGLWindow); - - if (context) - return; - - if (!q->handle()) - qWarning("Attempted to initialize QOpenGLWindow without a platform window"); - - context.reset(new QOpenGLContext); - context->setShareContext(shareContext); - context->setFormat(q->requestedFormat()); - if (!context->create()) - qWarning("QOpenGLWindow::beginPaint: Failed to create context"); - if (!context->makeCurrent(q)) - qWarning("QOpenGLWindow::beginPaint: Failed to make context current"); - - paintDevice.reset(new QOpenGLWindowPaintDevice(q)); - if (updateBehavior == QOpenGLWindow::PartialUpdateBlit) - hasFboBlit = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit(); - - q->initializeGL(); -} - -void QOpenGLWindowPrivate::beginPaint(const QRegion ®ion) -{ - Q_UNUSED(region); - Q_Q(QOpenGLWindow); - - initialize(); - context->makeCurrent(q); - - const int deviceWidth = q->width() * q->devicePixelRatio(); - const int deviceHeight = q->height() * q->devicePixelRatio(); - const QSize deviceSize(deviceWidth, deviceHeight); - if (updateBehavior > QOpenGLWindow::NoPartialUpdate) { - if (!fbo || fbo->size() != deviceSize) { - QOpenGLFramebufferObjectFormat fboFormat; - fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); - const int samples = q->requestedFormat().samples(); - if (samples > 0) { - if (updateBehavior != QOpenGLWindow::PartialUpdateBlend) - fboFormat.setSamples(samples); - else - qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling"); - } - fbo.reset(new QOpenGLFramebufferObject(deviceSize, fboFormat)); - markWindowAsDirty(); - } - } else { - markWindowAsDirty(); - } - - paintDevice->setSize(QSize(deviceWidth, deviceHeight)); - paintDevice->setDevicePixelRatio(q->devicePixelRatio()); - context->functions()->glViewport(0, 0, deviceWidth, deviceHeight); - - context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject()); - - q->paintUnderGL(); - - if (updateBehavior > QOpenGLWindow::NoPartialUpdate) - fbo->bind(); -} - -void QOpenGLWindowPrivate::endPaint() -{ - Q_Q(QOpenGLWindow); - - if (updateBehavior > QOpenGLWindow::NoPartialUpdate) - fbo->release(); - - context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject()); - - if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) { - const int deviceWidth = q->width() * q->devicePixelRatio(); - const int deviceHeight = q->height() * q->devicePixelRatio(); - QOpenGLExtensions extensions(context.data()); - extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle()); - extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject()); - extensions.glBlitFramebuffer(0, 0, deviceWidth, deviceHeight, - 0, 0, deviceWidth, deviceHeight, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - } else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) { - if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) { - context->functions()->glEnable(GL_BLEND); - context->functions()->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - if (!blitter.isCreated()) - blitter.create(); - - QRect windowRect(QPoint(0, 0), fbo->size()); - QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect); - blitter.bind(); - blitter.blit(fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft); - blitter.release(); - - if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) - context->functions()->glDisable(GL_BLEND); - } - - q->paintOverGL(); -} - -void QOpenGLWindowPrivate::bindFBO() -{ - if (updateBehavior > QOpenGLWindow::NoPartialUpdate) - fbo->bind(); - else - QOpenGLFramebufferObject::bindDefault(); -} - -void QOpenGLWindowPrivate::flush(const QRegion ®ion) -{ - Q_UNUSED(region); - Q_Q(QOpenGLWindow); - context->swapBuffers(q); - emit q->frameSwapped(); -} - -void QOpenGLWindowPaintDevice::ensureActiveTarget() -{ - QOpenGLWindowPrivate::get(m_window)->bindFBO(); -} - -/*! - Constructs a new QOpenGLWindow with the given \a parent and \a updateBehavior. - - \sa QOpenGLWindow::UpdateBehavior - */ -QOpenGLWindow::QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior, QWindow *parent) - : QPaintDeviceWindow(*(new QOpenGLWindowPrivate(nullptr, updateBehavior)), parent) -{ - setSurfaceType(QSurface::OpenGLSurface); -} - -/*! - Constructs a new QOpenGLWindow with the given \a parent and \a updateBehavior. The QOpenGLWindow's context will share with \a shareContext. - - \sa QOpenGLWindow::UpdateBehavior shareContext -*/ -QOpenGLWindow::QOpenGLWindow(QOpenGLContext *shareContext, UpdateBehavior updateBehavior, QWindow *parent) - : QPaintDeviceWindow(*(new QOpenGLWindowPrivate(shareContext, updateBehavior)), parent) -{ - setSurfaceType(QSurface::OpenGLSurface); -} - -/*! - Destroys the QOpenGLWindow instance, freeing its resources. - - The OpenGLWindow's context is made current in the destructor, allowing for - safe destruction of any child object that may need to release OpenGL - resources belonging to the context provided by this window. - - \warning if you have objects wrapping OpenGL resources (such as - QOpenGLBuffer, QOpenGLShaderProgram, etc.) as members of a QOpenGLWindow - subclass, you may need to add a call to makeCurrent() in that subclass' - destructor as well. Due to the rules of C++ object destruction, those objects - will be destroyed \e{before} calling this function (but after that the - destructor of the subclass has run), therefore making the OpenGL context - current in this function happens too late for their safe disposal. - - \sa makeCurrent - - \since 5.5 -*/ -QOpenGLWindow::~QOpenGLWindow() -{ - makeCurrent(); -} - -/*! - \return the update behavior for this QOpenGLWindow. -*/ -QOpenGLWindow::UpdateBehavior QOpenGLWindow::updateBehavior() const -{ - Q_D(const QOpenGLWindow); - return d->updateBehavior; -} - -/*! - \return \c true if the window's OpenGL resources, like the context, have - been successfully initialized. Note that the return value is always \c false - until the window becomes exposed (shown). -*/ -bool QOpenGLWindow::isValid() const -{ - Q_D(const QOpenGLWindow); - return d->context && d->context->isValid(); -} - -/*! - Prepares for rendering OpenGL content for this window by making the - corresponding context current and binding the framebuffer object, if there is - one, in that context context. - - It is not necessary to call this function in most cases, because it is called - automatically before invoking paintGL(). It is provided nonetheless to support - advanced, multi-threaded scenarios where a thread different than the GUI or main - thread may want to update the surface or framebuffer contents. See QOpenGLContext - for more information on threading related issues. - - This function is suitable for calling also when the underlying platform window - is already destroyed. This means that it is safe to call this function from - a QOpenGLWindow subclass' destructor. If there is no native window anymore, - an offscreen surface is used instead. This ensures that OpenGL resource - cleanup operations in the destructor will always work, as long as - this function is called first. - - \sa QOpenGLContext, context(), paintGL(), doneCurrent() - */ -void QOpenGLWindow::makeCurrent() -{ - Q_D(QOpenGLWindow); - - if (!isValid()) - return; - - // The platform window may be destroyed at this stage and therefore - // makeCurrent() may not safely be called with 'this'. - if (handle()) { - d->context->makeCurrent(this); - } else { - if (!d->offscreenSurface) { - d->offscreenSurface.reset(new QOffscreenSurface(screen())); - d->offscreenSurface->setFormat(d->context->format()); - d->offscreenSurface->create(); - } - d->context->makeCurrent(d->offscreenSurface.data()); - } - - d->bindFBO(); -} - -/*! - Releases the context. - - It is not necessary to call this function in most cases, since the widget - will make sure the context is bound and released properly when invoking - paintGL(). - - \sa makeCurrent() - */ -void QOpenGLWindow::doneCurrent() -{ - Q_D(QOpenGLWindow); - - if (!isValid()) - return; - - d->context->doneCurrent(); -} - -/*! - \return The QOpenGLContext used by this window or \c 0 if not yet initialized. - */ -QOpenGLContext *QOpenGLWindow::context() const -{ - Q_D(const QOpenGLWindow); - return d->context.data(); -} - -/*! - \return The QOpenGLContext requested to be shared with this window's QOpenGLContext. -*/ -QOpenGLContext *QOpenGLWindow::shareContext() const -{ - Q_D(const QOpenGLWindow); - return d->shareContext; -} - -/*! - The framebuffer object handle used by this window. - - When the update behavior is set to \c NoPartialUpdate, there is no separate - framebuffer object. In this case the returned value is the ID of the - default framebuffer. - - Otherwise the value of the ID of the framebuffer object or \c 0 if not - yet initialized. - */ -GLuint QOpenGLWindow::defaultFramebufferObject() const -{ - Q_D(const QOpenGLWindow); - if (d->updateBehavior > NoPartialUpdate && d->fbo) - return d->fbo->handle(); - else if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) - return ctx->defaultFramebufferObject(); - else - return 0; -} - -extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); - -/*! - Returns a copy of the framebuffer. - - \note This is a potentially expensive operation because it relies on - glReadPixels() to read back the pixels. This may be slow and can stall the - GPU pipeline. - - \note When used together with update behavior \c NoPartialUpdate, the returned - image may not contain the desired content when called after the front and back - buffers have been swapped (unless preserved swap is enabled in the underlying - windowing system interface). In this mode the function reads from the back - buffer and the contents of that may not match the content on the screen (the - front buffer). In this case the only place where this function can safely be - used is paintGL() or paintOverGL(). - */ -QImage QOpenGLWindow::grabFramebuffer() -{ - if (!isValid()) - return QImage(); - - makeCurrent(); - - const bool hasAlpha = format().hasAlpha(); - QImage img = qt_gl_read_framebuffer(size() * devicePixelRatio(), hasAlpha, hasAlpha); - img.setDevicePixelRatio(devicePixelRatio()); - return img; -} - -/*! - This virtual function is called once before the first call to paintGL() or - resizeGL(). Reimplement it in a subclass. - - This function should set up any required OpenGL resources and state. - - There is no need to call makeCurrent() because this has already been done - when this function is called. Note however that the framebuffer, in case - partial update mode is used, is not yet available at this stage, so avoid - issuing draw calls from here. Defer such calls to paintGL() instead. - - \sa paintGL(), resizeGL() - */ -void QOpenGLWindow::initializeGL() -{ -} - -/*! - This virtual function is called whenever the widget has been resized. - Reimplement it in a subclass. The new size is passed in \a w and \a h. - - \note This is merely a convenience function in order to provide an API that is - compatible with QOpenGLWidget. Unlike with QOpenGLWidget, derived classes are - free to choose to override resizeEvent() instead of this function. - - \note Avoid issuing OpenGL commands from this function as there may not be a - context current when it is invoked. If it cannot be avoided, call makeCurrent(). - - \note Scheduling updates from here is not necessary. The windowing systems - will send expose events that trigger an update automatically. - - \sa initializeGL(), paintGL() - */ -void QOpenGLWindow::resizeGL(int w, int h) -{ - Q_UNUSED(w); - Q_UNUSED(h); -} - -/*! - This virtual function is called whenever the window contents needs to be - painted. Reimplement it in a subclass. - - There is no need to call makeCurrent() because this has already - been done when this function is called. - - Before invoking this function, the context and the framebuffer, if there is - one, are bound, and the viewport is set up by a call to glViewport(). No - other state is set and no clearing or drawing is performed by the framework. - - \note When using a partial update behavior, like \c PartialUpdateBlend, the - output of the previous paintGL() call is preserved and, after the additional - drawing perfomed in the current invocation of the function, the content is - blitted or blended over the content drawn directly to the window in - paintUnderGL(). - - \sa initializeGL(), resizeGL(), paintUnderGL(), paintOverGL(), UpdateBehavior - */ -void QOpenGLWindow::paintGL() -{ -} - -/*! - The virtual function is called before each invocation of paintGL(). - - When the update mode is set to \c NoPartialUpdate, there is no difference - between this function and paintGL(), performing rendering in either of them - leads to the same result. - - The difference becomes significant when using \c PartialUpdateBlend, where an - extra framebuffer object is used. There, paintGL() targets this additional - framebuffer object, which preserves its contents, while paintUnderGL() and - paintOverGL() target the default framebuffer, i.e. directly the window - surface, the contents of which is lost after each displayed frame. - - \note Avoid relying on this function when the update behavior is - \c PartialUpdateBlit. This mode involves blitting the extra framebuffer used by - paintGL() onto the default framebuffer after each invocation of paintGL(), - thus overwriting all drawing generated in this function. - - \sa paintGL(), paintOverGL(), UpdateBehavior - */ -void QOpenGLWindow::paintUnderGL() -{ -} - -/*! - This virtual function is called after each invocation of paintGL(). - - When the update mode is set to NoPartialUpdate, there is no difference - between this function and paintGL(), performing rendering in either of them - leads to the same result. - - Like paintUnderGL(), rendering in this function targets the default - framebuffer of the window, regardless of the update behavior. It gets called - after paintGL() has returned and the blit (PartialUpdateBlit) or quad drawing - (PartialUpdateBlend) has been done. - - \sa paintGL(), paintUnderGL(), UpdateBehavior - */ -void QOpenGLWindow::paintOverGL() -{ -} - -/*! - Paint \a event handler. Calls paintGL(). - - \sa paintGL() - */ -void QOpenGLWindow::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); - paintGL(); -} - -/*! - Resize \a event handler. Calls resizeGL(). - - \sa resizeGL() - */ -void QOpenGLWindow::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - Q_D(QOpenGLWindow); - d->initialize(); - resizeGL(width(), height()); -} - -/*! - \internal - */ -int QOpenGLWindow::metric(PaintDeviceMetric metric) const -{ - Q_D(const QOpenGLWindow); - - switch (metric) { - case PdmDepth: - if (d->paintDevice) - return d->paintDevice->depth(); - break; - default: - break; - } - return QPaintDeviceWindow::metric(metric); -} - -/*! - \internal - */ -QPaintDevice *QOpenGLWindow::redirected(QPoint *) const -{ - Q_D(const QOpenGLWindow); - if (QOpenGLContext::currentContext() == d->context.data()) - return d->paintDevice.data(); - return nullptr; -} - -QT_END_NAMESPACE diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp index 397c50f3dc..f6180be8a8 100644 --- a/src/gui/kernel/qpalette.cpp +++ b/src/gui/kernel/qpalette.cpp @@ -44,10 +44,28 @@ #include "qvariant.h" #include "qdebug.h" +#include <QtCore/qmetaobject.h> + QT_BEGIN_NAMESPACE static int qt_palette_count = 1; +static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colorGroup) +{ + return QPalette::NColorRoles * colorGroup; +} + +static constexpr QPalette::ResolveMask bitPosition(QPalette::ColorGroup colorGroup, + QPalette::ColorRole colorRole) +{ + return colorRole + colorRoleOffset(colorGroup); +} + +Q_STATIC_ASSERT_X(bitPosition(QPalette::ColorGroup(QPalette::NColorGroups - 1), + QPalette::ColorRole(QPalette::NColorRoles - 1)) + < sizeof(QPalette::ResolveMask) * CHAR_BIT, + "The resolve mask type is not wide enough to fit the entire bit mask."); + class QPalettePrivate { public: QPalettePrivate() : ref(1), ser_no(qt_palette_count++), detach_no(0) { } @@ -321,11 +339,8 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button) Returns the placeholder text brush of the current color group. - \note Before Qt 5.12, the placeholder text color was hard-coded in the code as - QPalette::text().color() where an alpha of 128 was applied. - We continue to support this behavior by default, unless you set your own brush. - One can get back the original placeholder color setting the special QBrush default - constructor as placeholder brush. + \note Before Qt 5.12, the placeholder text color was hard-coded as QPalette::text().color() + with an alpha of 128 applied. In Qt 6, it is an independent color. \sa ColorRole, brush() */ @@ -538,8 +553,6 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button) QPalette::QPalette() : d(nullptr) { - data.current_group = Active; - data.resolve_mask = 0; // Initialize to application palette if present, else default to black. // This makes it possible to instantiate QPalette outside QGuiApplication, // for example in the platform plugins. @@ -549,7 +562,7 @@ QPalette::QPalette() } else { init(); qt_palette_from_color(*this, Qt::black); - data.resolve_mask = 0; + data.resolveMask = 0; } } @@ -681,8 +694,6 @@ QPalette::~QPalette() /*!\internal*/ void QPalette::init() { d = new QPalettePrivate; - data.resolve_mask = 0; - data.current_group = Active; //as a default.. } /*! @@ -739,7 +750,7 @@ const QBrush &QPalette::brush(ColorGroup gr, ColorRole cr) const Q_ASSERT(cr < NColorRoles); if(gr >= (int)NColorGroups) { if(gr == Current) { - gr = (ColorGroup)data.current_group; + gr = data.currentGroup; } else { qWarning("QPalette::brush: Unknown ColorGroup: %d", (int)gr); gr = Active; @@ -777,38 +788,18 @@ void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b) } if (cg == Current) { - cg = ColorGroup(data.current_group); + cg = data.currentGroup; } else if (cg >= NColorGroups) { qWarning("QPalette::setBrush: Unknown ColorGroup: %d", cg); cg = Active; } - // For placeholder we want to continue to respect the original behavior, which is - // derivating the text color, but only if user has not yet set his own brush. - // We then use Qt::NoBrush as an inernal way to know if the brush is customized or not. - - // ### Qt 6 - remove this special case - // Part 1 - Restore initial color to the given color group - if (cr == PlaceholderText && b == QBrush()) { - QColor col = brush(Text).color(); - col.setAlpha(128); - setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush)); - return; - } - if (d->br[cg][cr] != b) { detach(); d->br[cg][cr] = b; } - data.resolve_mask |= (1<<cr); - - // ### Qt 6 - remove this special case - // Part 2 - Update initial color to the given color group - if (cr == Text && d->br[cg][PlaceholderText].style() == Qt::NoBrush) { - QColor col = brush(Text).color(); - col.setAlpha(128); - setBrush(cg, PlaceholderText, QBrush(col, Qt::NoBrush)); - } + + data.resolveMask |= ResolveMask(1) << bitPosition(cg, cr); } /*! @@ -817,12 +808,30 @@ void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b) Returns \c true if the ColorGroup \a cg and ColorRole \a cr has been set previously on this palette; otherwise returns \c false. - \sa setBrush() + The ColorGroup \a cg should be less than QPalette::NColorGroups, + but you can use QPalette::Current. In this case, the previously + set current color group will be used. + + The ColorRole \a cr should be less than QPalette::NColorRoles. + + \sa setBrush(), currentColorGroup() */ bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const { - Q_UNUSED(cg); - return (data.resolve_mask & (1<<cr)); + if (cg == Current) + cg = data.currentGroup; + + if (cg >= NColorGroups) { + qWarning() << "Wrong color group:" << cg; + return false; + } + + if (cr >= NColorRoles) { + qWarning() << "Wrong color role:" << cr; + return false; + } + + return data.resolveMask & (ResolveMask(1) << bitPosition(cg, cr)); } /*! @@ -887,7 +896,7 @@ bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) { if(group1 >= (int)NColorGroups) { if(group1 == Current) { - group1 = (ColorGroup)data.current_group; + group1 = data.currentGroup; } else { qWarning("QPalette::brush: Unknown ColorGroup(1): %d", (int)group1); group1 = Active; @@ -895,7 +904,7 @@ bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) } if(group2 >= (int)NColorGroups) { if(group2 == Current) { - group2 = (ColorGroup)data.current_group; + group2 = data.currentGroup; } else { qWarning("QPalette::brush: Unknown ColorGroup(2): %d", (int)group2); group2 = Active; @@ -946,21 +955,25 @@ qint64 QPalette::cacheKey() const */ QPalette QPalette::resolve(const QPalette &other) const { - if ((*this == other && data.resolve_mask == other.data.resolve_mask) - || data.resolve_mask == 0) { + if ((*this == other && data.resolveMask == other.data.resolveMask) + || data.resolveMask == 0) { QPalette o = other; - o.data.resolve_mask = data.resolve_mask; + o.data.resolveMask = data.resolveMask; return o; } QPalette palette(*this); palette.detach(); - for(int role = 0; role < (int)NColorRoles; role++) - if (!(data.resolve_mask & (1<<role))) - for(int grp = 0; grp < (int)NColorGroups; grp++) + for (int role = 0; role < int(NColorRoles); ++role) { + for (int grp = 0; grp < int(NColorGroups); ++grp) { + if (!(data.resolveMask & (ResolveMask(1) << bitPosition(ColorGroup(grp), ColorRole(role))))) { palette.d->br[grp][role] = other.d->br[grp][role]; - palette.data.resolve_mask |= other.data.resolve_mask; + } + } + } + + palette.data.resolveMask |= other.data.resolveMask; return palette; } @@ -971,7 +984,12 @@ QPalette QPalette::resolve(const QPalette &other) const */ /*! - \fn void QPalette::resolve(uint mask) + \typedef ResolveMaskType + \internal + */ + +/*! + \fn void QPalette::resolve(ResolveMaskType mask) \internal */ @@ -1105,10 +1123,15 @@ void QPalette::setColorGroup(ColorGroup cg, const QBrush &windowText, const QBru QBrush(Qt::blue), QBrush(Qt::magenta), QBrush(toolTipBase), QBrush(toolTipText)); - data.resolve_mask &= ~(1 << Highlight); - data.resolve_mask &= ~(1 << HighlightedText); - data.resolve_mask &= ~(1 << LinkVisited); - data.resolve_mask &= ~(1 << Link); + for (int cr = Highlight; cr <= LinkVisited; ++cr) { + if (cg == All) { + for (int group = Active; group < NColorGroups; ++group) { + data.resolveMask &= ~(ResolveMask(1) << bitPosition(ColorGroup(group), ColorRole(cr))); + } + } else { + data.resolveMask &= ~(ResolveMask(1) << bitPosition(ColorGroup(cg), ColorRole(cr))); + } + } } @@ -1177,6 +1200,8 @@ Q_GUI_EXPORT QPalette qt_fusionPalette() QColor button = backGround; QColor shadow = dark.darker(135); QColor disabledShadow = shadow.lighter(150); + QColor placeholder = text; + placeholder.setAlpha(128); QPalette fusionPalette(Qt::black,backGround,light,dark,mid,text,base); fusionPalette.setBrush(QPalette::Midlight, midLight); @@ -1194,40 +1219,65 @@ Q_GUI_EXPORT QPalette qt_fusionPalette() fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, QColor(48, 140, 198)); fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(48, 140, 198)); fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 145, 145)); + + fusionPalette.setBrush(QPalette::PlaceholderText, placeholder); + return fusionPalette; } #ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const QPalette &p) +static QString groupsToString(const QPalette &p, QPalette::ColorRole cr) { - const char *colorGroupNames[] = {"Active", "Disabled", "Inactive"}; - const char *colorRoleNames[] = - {"WindowText", "Button", "Light", "Midlight", "Dark", "Mid", "Text", - "BrightText", "ButtonText", "Base", "Window", "Shadow", "Highlight", - "HighlightedText", "Link", "LinkVisited", "AlternateBase", "NoRole", - "ToolTipBase","ToolTipText", "PlaceholderText" }; - QDebugStateSaver saver(dbg); - QDebug nospace = dbg.nospace(); - const uint mask = p.resolve(); - nospace << "QPalette(resolve=" << Qt::hex << Qt::showbase << mask << ','; - for (int role = 0; role < (int)QPalette::NColorRoles; ++role) { - if (mask & (1<<role)) { - if (role) - nospace << ','; - nospace << colorRoleNames[role] << ":["; - for (int group = 0; group < (int)QPalette::NColorGroups; ++group) { - if (group) - nospace << ','; - const QRgb color = p.color(static_cast<QPalette::ColorGroup>(group), - static_cast<QPalette::ColorRole>(role)).rgba(); - nospace << colorGroupNames[group] << ':' << color; - } - nospace << ']'; + const auto groupEnum = QMetaEnum::fromType<QPalette::ColorGroup>(); + + QString groupString; + for (int group = 0; group < QPalette::NColorGroups; ++group) { + const auto cg = QPalette::ColorGroup(group); + + if (p.isBrushSet(cg, cr)) { + const auto &color = p.color(cg, cr); + groupString += QString::fromUtf8(groupEnum.valueToKey(cg)) + QLatin1Char(':') + + color.name(QColor::HexArgb) + QLatin1Char(','); } } - nospace << ')' << Qt::noshowbase << Qt::dec; - return dbg; + groupString.chop(1); + + return groupString; } + +static QString rolesToString(const QPalette &p) +{ + const auto roleEnum = QMetaEnum::fromType<QPalette::ColorRole>(); + + QString roleString; + for (int role = 0; role < QPalette::NColorRoles; ++role) { + const auto cr = QPalette::ColorRole(role); + + auto groupString = groupsToString(p, cr); + if (!groupString.isEmpty()) + roleString += QString::fromUtf8(roleEnum.valueToKey(cr)) + QStringLiteral(":[") + + groupString + QStringLiteral("],"); + } + roleString.chop(1); + + return roleString; +} + +QDebug operator<<(QDebug dbg, const QPalette &p) +{ + QDebugStateSaver saver(dbg); + dbg.nospace(); + + dbg << "QPalette(resolve=" << Qt::hex << Qt::showbase << p.resolve(); + + auto roleString = rolesToString(p); + if (!roleString.isEmpty()) + dbg << ',' << roleString; + + dbg << ')'; + + return dbg; + } #endif QT_END_NAMESPACE diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h index d3a840d9ad..fd0ef2e2d9 100644 --- a/src/gui/kernel/qpalette.h +++ b/src/gui/kernel/qpalette.h @@ -72,14 +72,13 @@ public: { other.d = nullptr; } inline QPalette &operator=(QPalette &&other) noexcept { - for_faster_swapping_dont_use = other.for_faster_swapping_dont_use; - qSwap(d, other.d); return *this; + swap(other); return *this; } void swap(QPalette &other) noexcept { + qSwap(data, other.data); qSwap(d, other.d); - qSwap(for_faster_swapping_dont_use, other.for_faster_swapping_dont_use); } operator QVariant() const; @@ -103,8 +102,8 @@ public: }; Q_ENUM(ColorRole) - inline ColorGroup currentColorGroup() const { return static_cast<ColorGroup>(data.current_group); } - inline void setCurrentColorGroup(ColorGroup cg) { data.current_group = cg; } + inline ColorGroup currentColorGroup() const { return data.currentGroup; } + inline void setCurrentColorGroup(ColorGroup cg) { data.currentGroup = cg; } inline const QColor &color(ColorGroup cg, ColorRole cr) const { return brush(cg, cr).color(); } @@ -158,9 +157,11 @@ public: #endif qint64 cacheKey() const; - QPalette resolve(const QPalette &) const; - inline uint resolve() const { return data.resolve_mask; } - inline void resolve(uint mask) { data.resolve_mask = mask; } + QPalette resolve(const QPalette &other) const; + + using ResolveMask = quint64; + inline ResolveMask resolve() const { return data.resolveMask; } + inline void resolve(ResolveMask mask) { data.resolveMask = mask; } private: void setColorGroup(ColorGroup cr, const QBrush &windowText, const QBrush &button, @@ -185,13 +186,11 @@ private: QPalettePrivate *d; struct Data { - uint current_group : 4; - uint resolve_mask : 28; - }; - union { - Data data; - quint32 for_faster_swapping_dont_use; + ResolveMask resolveMask{0}; + ColorGroup currentGroup{Active}; }; + Data data; + friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &s, const QPalette &p); }; diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h index 28c29a704c..8e470aefd3 100644 --- a/src/gui/kernel/qplatformmenu.h +++ b/src/gui/kernel/qplatformmenu.h @@ -52,7 +52,9 @@ #include <QtGui/qtguiglobal.h> #include <QtCore/qpointer.h> #include <QtGui/QFont> -#include <QtGui/QKeySequence> +#if QT_CONFIG(shortcut) +# include <QtGui/QKeySequence> +#endif #include <QtGui/QIcon> QT_BEGIN_NAMESPACE @@ -85,7 +87,7 @@ public: virtual void setRole(MenuRole role) = 0; virtual void setCheckable(bool checkable) = 0; virtual void setChecked(bool isChecked) = 0; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) virtual void setShortcut(const QKeySequence& shortcut) = 0; #endif virtual void setEnabled(bool enabled) = 0; diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index 71521c0339..93fd59e53f 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -167,7 +167,7 @@ QT_BEGIN_NAMESPACE */ -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) // Table of key bindings. It must be sorted on key sequence: // The integer value of VK_KEY | Modifier Keys (e.g., VK_META, and etc.) // A priority of 1 indicates that this is the primary key binding when multiple are defined. @@ -623,7 +623,7 @@ static inline int maybeSwapShortcut(int shortcut) } #endif -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) // mixed-mode predicate: all of these overloads are actually needed (but not all for every compiler) struct ByStandardKey { typedef bool result_type; @@ -688,6 +688,7 @@ QString QPlatformTheme::standardButtonText(int button) const return QPlatformTheme::defaultStandardButtonText(button); } +#if QT_CONFIG(shortcut) /*! Returns the mnemonic that should be used for a standard \a button. @@ -700,6 +701,7 @@ QKeySequence QPlatformTheme::standardButtonShortcut(int button) const Q_UNUSED(button) return QKeySequence(); } +#endif // QT_CONFIG(shortcut) QString QPlatformTheme::defaultStandardButtonText(int button) { @@ -784,7 +786,7 @@ unsigned QPlatformThemePrivate::currentKeyPlatforms() { const uint keyboardScheme = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::KeyboardScheme).toInt(); unsigned result = 1u << keyboardScheme; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) if (keyboardScheme == QPlatformTheme::KdeKeyboardScheme || keyboardScheme == QPlatformTheme::GnomeKeyboardScheme || keyboardScheme == QPlatformTheme::CdeKeyboardScheme) diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h index 3185fc4541..6ed612b785 100644 --- a/src/gui/kernel/qplatformtheme.h +++ b/src/gui/kernel/qplatformtheme.h @@ -51,7 +51,9 @@ #include <QtGui/qtguiglobal.h> #include <QtCore/QScopedPointer> -#include <QtGui/QKeySequence> +#if QT_CONFIG(shortcut) +# include <QtGui/QKeySequence> +#endif QT_BEGIN_NAMESPACE @@ -312,12 +314,14 @@ public: QPlatformTheme::IconOptions iconOptions = { }) const; virtual QIconEngine *createIconEngine(const QString &iconName) const; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) virtual QList<QKeySequence> keyBindings(QKeySequence::StandardKey key) const; #endif virtual QString standardButtonText(int button) const; +#if QT_CONFIG(shortcut) virtual QKeySequence standardButtonShortcut(int button) const; +#endif static QVariant defaultThemeHint(ThemeHint hint); static QString defaultStandardButtonText(int button); diff --git a/src/gui/kernel/qplatformtheme_p.h b/src/gui/kernel/qplatformtheme_p.h index 73deb890bb..2c16fec141 100644 --- a/src/gui/kernel/qplatformtheme_p.h +++ b/src/gui/kernel/qplatformtheme_p.h @@ -52,7 +52,9 @@ // #include <QtGui/private/qtguiglobal_p.h> -#include "private/qkeysequence_p.h" +#if QT_CONFIG(shortcut) +# include "private/qkeysequence_p.h" +#endif QT_BEGIN_NAMESPACE @@ -67,7 +69,7 @@ public: void initializeSystemPalette(); -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) static const QKeyBinding keyBindings[]; static const uint numberOfKeyBindings; #endif diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index a7ea20266b..6039101cf4 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -49,8 +49,6 @@ #include <algorithm> -#ifndef QT_NO_SHORTCUT - QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcShortcutMap, "qt.gui.shortcutmap") @@ -689,5 +687,3 @@ void QShortcutMap::dumpMap() const #endif QT_END_NAMESPACE - -#endif // QT_NO_SHORTCUT diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h index 8fc68229fb..aa3dd969f0 100644 --- a/src/gui/kernel/qshortcutmap_p.h +++ b/src/gui/kernel/qshortcutmap_p.h @@ -56,9 +56,9 @@ #include "QtCore/qvector.h" #include "QtCore/qscopedpointer.h" -QT_BEGIN_NAMESPACE +QT_REQUIRE_CONFIG(shortcut); -#ifndef QT_NO_SHORTCUT +QT_BEGIN_NAMESPACE // To enable dump output uncomment below //#define Dump_QShortcutMap @@ -106,8 +106,6 @@ private: QScopedPointer<QShortcutMapPrivate> d_ptr; }; -#endif // QT_NO_SHORTCUT - QT_END_NAMESPACE #endif // QSHORTCUTMAP_P_H diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h index b4f3ed4712..cb0842da8c 100644 --- a/src/gui/kernel/qwindowdefs.h +++ b/src/gui/kernel/qwindowdefs.h @@ -43,6 +43,7 @@ #include <QtGui/qtguiglobal.h> #include <QtCore/qobjectdefs.h> #include <QtCore/qnamespace.h> +#include <QtCore/qcontainerfwd.h> QT_BEGIN_NAMESPACE @@ -80,7 +81,6 @@ class QString; class QByteArray; class QApplication; -template<typename T> class QList; typedef QList<QWidget *> QWidgetList; typedef QList<QWindow *> QWindowList; diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 3e7d592016..2de0131640 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -442,7 +442,7 @@ void QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, ulong t bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestamp, int keyCode, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString &text, bool autorepeat, ushort count) { -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) if (!window) window = QGuiApplication::focusWindow(); @@ -1247,7 +1247,7 @@ Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *window, QEvent::Type t, int k, Qt:: Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1) { -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) // FIXME: This method should not allow targeting a specific object, but should // instead forward the event to a window, which then takes care of normal event diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index 1439bfac59..4ad6cceaea 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -187,6 +187,7 @@ public: friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m); #endif + void projectedRotate(float angle, float x, float y, float z); private: float m[4][4]; // Column-major order to match OpenGL. int flagBits; // Flag bits from the enum below. @@ -206,10 +207,6 @@ private: explicit QMatrix4x4(int) { } QMatrix4x4 orthonormalInverse() const; - - void projectedRotate(float angle, float x, float y, float z); - - friend class QGraphicsRotation; }; QT_WARNING_PUSH diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri index 24758afdeb..f1e2019417 100644 --- a/src/gui/opengl/opengl.pri +++ b/src/gui/opengl/opengl.pri @@ -10,55 +10,25 @@ qtConfig(opengl) { opengl/qopenglfunctions.h \ opengl/qopenglframebufferobject.h \ opengl/qopenglframebufferobject_p.h \ - opengl/qopenglpaintdevice.h \ - opengl/qopenglpaintdevice_p.h \ opengl/qopenglbuffer.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 \ - opengl/qopenglengineshadersource_p.h \ - opengl/qopenglcustomshaderstage_p.h \ - opengl/qopengltextureglyphcache_p.h \ - opengl/qopenglshadercache_p.h \ opengl/qopenglversionfunctions.h \ opengl/qopenglversionfunctionsfactory_p.h \ opengl/qopenglvertexarrayobject.h \ - opengl/qopengldebug.h \ opengl/qopengltextureblitter.h \ - opengl/qopengltexture.h \ - opengl/qopengltexture_p.h \ - opengl/qopengltexturehelper_p.h \ - opengl/qopengltextureuploader_p.h \ - opengl/qopenglpixeltransferoptions.h \ opengl/qopenglextrafunctions.h \ opengl/qopenglprogrambinarycache_p.h SOURCES += opengl/qopengl.cpp \ opengl/qopenglfunctions.cpp \ opengl/qopenglframebufferobject.cpp \ - opengl/qopenglpaintdevice.cpp \ opengl/qopenglbuffer.cpp \ opengl/qopenglshaderprogram.cpp \ - opengl/qopenglgradientcache.cpp \ - opengl/qopengltexturecache.cpp \ - opengl/qopenglengineshadermanager.cpp \ - opengl/qopengl2pexvertexarray.cpp \ - opengl/qopenglpaintengine.cpp \ - opengl/qopenglcustomshaderstage.cpp \ - opengl/qopengltextureglyphcache.cpp \ opengl/qopenglversionfunctions.cpp \ opengl/qopenglversionfunctionsfactory.cpp \ opengl/qopenglvertexarrayobject.cpp \ - opengl/qopengldebug.cpp \ opengl/qopengltextureblitter.cpp \ - opengl/qopengltexture.cpp \ - opengl/qopengltexturehelper.cpp \ - opengl/qopengltextureuploader.cpp \ - opengl/qopenglpixeltransferoptions.cpp \ opengl/qopenglprogrambinarycache.cpp !qtConfig(opengles2) { @@ -87,9 +57,7 @@ qtConfig(opengl) { opengl/qopenglfunctions_4_2_compatibility.h \ opengl/qopenglfunctions_4_3_compatibility.h \ opengl/qopenglfunctions_4_4_compatibility.h \ - opengl/qopenglfunctions_4_5_compatibility.h \ - opengl/qopenglqueryhelper_p.h \ - opengl/qopengltimerquery.h + opengl/qopenglfunctions_4_5_compatibility.h SOURCES += opengl/qopenglfunctions_1_0.cpp \ opengl/qopenglfunctions_1_1.cpp \ @@ -116,8 +84,7 @@ qtConfig(opengl) { opengl/qopenglfunctions_4_2_compatibility.cpp \ opengl/qopenglfunctions_4_3_compatibility.cpp \ opengl/qopenglfunctions_4_4_compatibility.cpp \ - opengl/qopenglfunctions_4_5_compatibility.cpp \ - opengl/qopengltimerquery.cpp + opengl/qopenglfunctions_4_5_compatibility.cpp } qtConfig(opengles2) { diff --git a/src/gui/opengl/qopengl2pexvertexarray.cpp b/src/gui/opengl/qopengl2pexvertexarray.cpp deleted file mode 100644 index 04781f63c7..0000000000 --- a/src/gui/opengl/qopengl2pexvertexarray.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopengl2pexvertexarray_p.h" - -#include <private/qbezier_p.h> - -QT_BEGIN_NAMESPACE - -void QOpenGL2PEXVertexArray::clear() -{ - vertexArray.reset(); - vertexArrayStops.reset(); - boundingRectDirty = true; -} - - -QOpenGLRect QOpenGL2PEXVertexArray::boundingRect() const -{ - if (boundingRectDirty) - return QOpenGLRect(0.0, 0.0, 0.0, 0.0); - else - return QOpenGLRect(minX, minY, maxX, maxY); -} - -void QOpenGL2PEXVertexArray::addClosingLine(int index) -{ - QPointF point(vertexArray.at(index)); - if (point != QPointF(vertexArray.last())) - vertexArray.add(point); -} - -void QOpenGL2PEXVertexArray::addCentroid(const QVectorPath &path, int subPathIndex) -{ - const QPointF *const points = reinterpret_cast<const QPointF *>(path.points()); - const QPainterPath::ElementType *const elements = path.elements(); - - QPointF sum = points[subPathIndex]; - int count = 1; - - for (int i = subPathIndex + 1; i < path.elementCount() && (!elements || elements[i] != QPainterPath::MoveToElement); ++i) { - sum += points[i]; - ++count; - } - - const QPointF centroid = sum / qreal(count); - vertexArray.add(centroid); -} - -void QOpenGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline) -{ - const QPointF* const points = reinterpret_cast<const QPointF*>(path.points()); - const QPainterPath::ElementType* const elements = path.elements(); - - if (boundingRectDirty) { - minX = maxX = points[0].x(); - minY = maxY = points[0].y(); - boundingRectDirty = false; - } - - if (!outline && !path.isConvex()) - addCentroid(path, 0); - - int lastMoveTo = vertexArray.size(); - vertexArray.add(points[0]); // The first element is always a moveTo - - do { - if (!elements) { -// qDebug("QVectorPath has no elements"); - // If the path has a null elements pointer, the elements implicitly - // start with a moveTo (already added) and continue with lineTos: - for (int i=1; i<path.elementCount(); ++i) - lineToArray(points[i].x(), points[i].y()); - - break; - } -// qDebug("QVectorPath has element types"); - - for (int i=1; i<path.elementCount(); ++i) { - switch (elements[i]) { - case QPainterPath::MoveToElement: - if (!outline) - addClosingLine(lastMoveTo); -// qDebug("element[%d] is a MoveToElement", i); - vertexArrayStops.add(vertexArray.size()); - if (!outline) { - if (!path.isConvex()) addCentroid(path, i); - lastMoveTo = vertexArray.size(); - } - lineToArray(points[i].x(), points[i].y()); // Add the moveTo as a new vertex - break; - case QPainterPath::LineToElement: -// qDebug("element[%d] is a LineToElement", i); - lineToArray(points[i].x(), points[i].y()); - break; - case QPainterPath::CurveToElement: { - QBezier b = QBezier::fromPoints(*(((const QPointF *) points) + i - 1), - points[i], - points[i+1], - points[i+2]); - QRectF bounds = b.bounds(); - // threshold based on same algorithm as in qtriangulatingstroker.cpp - int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * 3.14f / (curveInverseScale * 6)); - if (threshold < 3) threshold = 3; - qreal one_over_threshold_minus_1 = qreal(1) / (threshold - 1); - for (int t=0; t<threshold; ++t) { - QPointF pt = b.pointAt(t * one_over_threshold_minus_1); - lineToArray(pt.x(), pt.y()); - } - i += 2; - break; } - default: - break; - } - } - } while (0); - - if (!outline) - addClosingLine(lastMoveTo); - vertexArrayStops.add(vertexArray.size()); -} - -void QOpenGL2PEXVertexArray::lineToArray(const GLfloat x, const GLfloat y) -{ - vertexArray.add(QOpenGLPoint(x, y)); - - if (x > maxX) - maxX = x; - else if (x < minX) - minX = x; - if (y > maxY) - maxY = y; - else if (y < minY) - minY = y; -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengl2pexvertexarray_p.h b/src/gui/opengl/qopengl2pexvertexarray_p.h deleted file mode 100644 index 5dc060ff3d..0000000000 --- a/src/gui/opengl/qopengl2pexvertexarray_p.h +++ /dev/null @@ -1,168 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $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 QOPENGL2PEXVERTEXARRAY_P_H -#define QOPENGL2PEXVERTEXARRAY_P_H - -#include <QtGui/private/qtguiglobal_p.h> -#include <QRectF> - -#include <private/qdatabuffer_p.h> -#include <private/qvectorpath_p.h> -#include <private/qopenglcontext_p.h> - -QT_BEGIN_NAMESPACE - -class QOpenGLPoint -{ -public: - QOpenGLPoint(GLfloat new_x, GLfloat new_y) : - x(new_x), y(new_y) {}; - - QOpenGLPoint(const QPointF &p) : - x(p.x()), y(p.y()) {}; - - QOpenGLPoint(const QPointF* p) : - x(p->x()), y(p->y()) {}; - - GLfloat x; - GLfloat y; - - operator QPointF() {return QPointF(x,y);} - operator QPointF() const {return QPointF(x,y);} -}; - -struct QOpenGLRect -{ - QOpenGLRect(const QRectF &r) - : left(r.left()), top(r.top()), right(r.right()), bottom(r.bottom()) {} - - QOpenGLRect(GLfloat l, GLfloat t, GLfloat r, GLfloat b) - : left(l), top(t), right(r), bottom(b) {} - - GLfloat left; - GLfloat top; - GLfloat right; - GLfloat bottom; - - operator QRectF() const {return QRectF(left, top, right-left, bottom-top);} -}; - -class QOpenGL2PEXVertexArray -{ -public: - QOpenGL2PEXVertexArray() : - vertexArray(0), vertexArrayStops(0), - maxX(-2e10), maxY(-2e10), minX(2e10), minY(2e10), - boundingRectDirty(true) - { } - - inline void addRect(const QRectF &rect) - { - qreal top = rect.top(); - qreal left = rect.left(); - qreal bottom = rect.bottom(); - qreal right = rect.right(); - - vertexArray << QOpenGLPoint(left, top) - << QOpenGLPoint(right, top) - << QOpenGLPoint(right, bottom) - << QOpenGLPoint(right, bottom) - << QOpenGLPoint(left, bottom) - << QOpenGLPoint(left, top); - } - - inline void addQuad(const QRectF &rect) - { - qreal top = rect.top(); - qreal left = rect.left(); - qreal bottom = rect.bottom(); - qreal right = rect.right(); - - vertexArray << QOpenGLPoint(left, top) - << QOpenGLPoint(right, top) - << QOpenGLPoint(left, bottom) - << QOpenGLPoint(right, bottom); - - } - - inline void addVertex(const GLfloat x, const GLfloat y) - { - vertexArray.add(QOpenGLPoint(x, y)); - } - - void addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline = true); - void clear(); - - QOpenGLPoint* data() {return vertexArray.data();} - int *stops() const { return vertexArrayStops.data(); } - int stopCount() const { return vertexArrayStops.size(); } - QOpenGLRect boundingRect() const; - - int vertexCount() const { return vertexArray.size(); } - - void lineToArray(const GLfloat x, const GLfloat y); - -private: - QDataBuffer<QOpenGLPoint> vertexArray; - QDataBuffer<int> vertexArrayStops; - - GLfloat maxX; - GLfloat maxY; - GLfloat minX; - GLfloat minY; - bool boundingRectDirty; - void addClosingLine(int index); - void addCentroid(const QVectorPath &path, int subPathIndex); -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/opengl/qopenglcustomshaderstage.cpp b/src/gui/opengl/qopenglcustomshaderstage.cpp deleted file mode 100644 index a95a0a5767..0000000000 --- a/src/gui/opengl/qopenglcustomshaderstage.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopenglcustomshaderstage_p.h" -#include "qopenglengineshadermanager_p.h" -#include "qopenglpaintengine_p.h" -#include <private/qpainter_p.h> - -QT_BEGIN_NAMESPACE - -class QOpenGLCustomShaderStagePrivate -{ -public: - QOpenGLCustomShaderStagePrivate() : - m_manager(nullptr) {} - - QPointer<QOpenGLEngineShaderManager> m_manager; - QByteArray m_source; -}; - - - - -QOpenGLCustomShaderStage::QOpenGLCustomShaderStage() - : d_ptr(new QOpenGLCustomShaderStagePrivate) -{ -} - -QOpenGLCustomShaderStage::~QOpenGLCustomShaderStage() -{ - Q_D(QOpenGLCustomShaderStage); - if (d->m_manager) { - d->m_manager->removeCustomStage(); - d->m_manager->sharedShaders->cleanupCustomStage(this); - } - delete d_ptr; -} - -void QOpenGLCustomShaderStage::setUniformsDirty() -{ - Q_D(QOpenGLCustomShaderStage); - if (d->m_manager) - d->m_manager->setDirty(); // ### Probably a bit overkill! -} - -bool QOpenGLCustomShaderStage::setOnPainter(QPainter* p) -{ - Q_D(QOpenGLCustomShaderStage); - if (p->paintEngine()->type() != QPaintEngine::OpenGL2) { - qWarning("QOpenGLCustomShaderStage::setOnPainter() - paint engine not OpenGL2"); - return false; - } - if (d->m_manager) - qWarning("Custom shader is already set on a painter"); - - QOpenGL2PaintEngineEx *engine = static_cast<QOpenGL2PaintEngineEx*>(p->paintEngine()); - d->m_manager = QOpenGL2PaintEngineExPrivate::shaderManagerForEngine(engine); - Q_ASSERT(d->m_manager); - - d->m_manager->setCustomStage(this); - return true; -} - -void QOpenGLCustomShaderStage::removeFromPainter(QPainter* p) -{ - Q_D(QOpenGLCustomShaderStage); - if (p->paintEngine()->type() != QPaintEngine::OpenGL2) - return; - - QOpenGL2PaintEngineEx *engine = static_cast<QOpenGL2PaintEngineEx*>(p->paintEngine()); - d->m_manager = QOpenGL2PaintEngineExPrivate::shaderManagerForEngine(engine); - Q_ASSERT(d->m_manager); - - // Just set the stage to null, don't call removeCustomStage(). - // This should leave the program in a compiled/linked state - // if the next custom shader stage is this one again. - d->m_manager->setCustomStage(nullptr); - d->m_manager = nullptr; -} - -QByteArray QOpenGLCustomShaderStage::source() const -{ - Q_D(const QOpenGLCustomShaderStage); - return d->m_source; -} - -// Called by the shader manager if another custom shader is attached or -// the manager is deleted -void QOpenGLCustomShaderStage::setInactive() -{ - Q_D(QOpenGLCustomShaderStage); - d->m_manager = nullptr; -} - -void QOpenGLCustomShaderStage::setSource(const QByteArray& s) -{ - Q_D(QOpenGLCustomShaderStage); - d->m_source = s; -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengldebug.cpp b/src/gui/opengl/qopengldebug.cpp deleted file mode 100644 index 310006feaf..0000000000 --- a/src/gui/opengl/qopengldebug.cpp +++ /dev/null @@ -1,1826 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/private/qobject_p.h> -#include <QtCore/qglobal.h> -#include <QtCore/qvarlengtharray.h> -#include <QtGui/qopengl.h> -#include <QtGui/qopenglfunctions.h> -#include <QtGui/qoffscreensurface.h> - -#include "qopengldebug.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QOpenGLDebugMessage - \brief The QOpenGLDebugMessage class wraps an OpenGL debug message. - \inmodule QtGui - \reentrant - \since 5.1 - \ingroup shared - \ingroup painting-3D - - Debug messages are usually created by the OpenGL server and then read by - OpenGL clients (either from the OpenGL internal debug log, or logged in real-time). - A debug message has a textual representation, a vendor-specific numeric id, - a source, a type and a severity. - - It's also possible for applications or third-party libraries and toolkits - to create and insert messages in the debug log. In order to do so, you can use - the createApplicationMessage() or the createThirdPartyMessage() static functions. - - \sa QOpenGLDebugLogger -*/ - -/*! - \class QOpenGLDebugLogger - \brief The QOpenGLDebugLogger enables logging of OpenGL debugging messages. - \inmodule QtGui - \since 5.1 - \ingroup painting-3D - - \tableofcontents - - \section1 Introduction - - OpenGL programming can be very error prone. Most of the time, a single - failing call to OpenGL can cause an entire portion of an application to - stop working, with nothing being drawn on the screen. - - The only way to be sure that no errors are being returned from the OpenGL - implementation is checking with \c{glGetError} after each and every API - call. Moreover, OpenGL errors stack up, therefore glGetError should always - be used in a loop like this: - - \snippet code/src_gui_opengl_qopengldebug.cpp 0 - - If you try to clear the error stack, make sure not just keep going until - GL_NO_ERROR is returned but also break on GL_CONTEXT_LOST as that error - value will keep repeating. - - There are also many other information we are interested in (as application - developers), for instance performance issues, or warnings about using - deprecated APIs. Those kind of messages are not reported through the - ordinary OpenGL error reporting mechanisms. - - QOpenGLDebugLogger aims at addressing these issues by providing access to - the \e{OpenGL debug log}. If your OpenGL implementation supports it (by - exposing the \c{GL_KHR_debug} extension), messages from the OpenGL server - will be either logged in an internal OpenGL log, or passed in "real-time" - to listeners as they're generated from OpenGL. - - QOpenGLDebugLogger supports both these modes of operation. Refer to the - following sections to find out the differences between them. - - \section1 Creating an OpenGL Debug Context - - For efficiency reasons, OpenGL implementations are allowed not to create - any debug output at all, unless the OpenGL context is a debug context. In order - to create a debug context from Qt, you must set the QSurfaceFormat::DebugContext - format option on the QSurfaceFormat used to create the QOpenGLContext object: - - \snippet code/src_gui_opengl_qopengldebug.cpp 1 - - Note that requesting a 3.2 OpenGL Core Profile is just for the example's - purposes; this class is not tied to any specific OpenGL or OpenGL ES - version, as it relies on the availability of the \c{GL_KHR_debug} extension - (see below). - - \section1 Creating and Initializing a QOpenGLDebugLogger - - QOpenGLDebugLogger is a simple QObject-derived class. Just like all QObject - subclasses, you create an instance (and optionally specify a parent - object), and like the other OpenGL functions in Qt you \e{must} initialize - it before usage by calling initialize() whilst there is a current OpenGL context: - - \snippet code/src_gui_opengl_qopengldebug.cpp 2 - - Note that the \c{GL_KHR_debug} extension \e{must} be available in the context - in order to access the messages logged by OpenGL. You can check the - presence of this extension by calling: - - \snippet code/src_gui_opengl_qopengldebug.cpp 3 - - where \c{ctx} is a valid QOpenGLContext. If the extension is not available, - initialize() will return false. - - \section1 Reading the Internal OpenGL Debug Log - - OpenGL implementations keep an internal log of debug messages. Messages - stored in this log can be retrieved by using the loggedMessages() function: - - \snippet code/src_gui_opengl_qopengldebug.cpp 4 - - The internal log has a limited size; when it fills up, older messages will - get discarded to make room for the new incoming messages. When you call - loggedMessages(), the internal log will be emptied as well. - - If you want to be sure not to lose any debug message, you must use real-time - logging instead of calling this function. However, debug messages might - still be generated in the timespan between context creation and activation - of real-time logging (or, in general, when the real-time logging is disabled). - - \section1 Real-time logging of messages - - It is also possible to receive a stream of debug messages from the OpenGL - server \e{as they are generated} by the implementation. In order to do so, - you need to connect a suitable slot to the messageLogged() signal, and - start logging by calling startLogging(): - - \snippet code/src_gui_opengl_qopengldebug.cpp 5 - - Similarly, logging can be disabled at any time by calling the stopLogging() - function. - - Real-time logging can be either asynchronous or synchronous, depending on - the parameter passed to startLogging(). When logging in asynchronous mode - (the default, as it has a very small overhead), the OpenGL implementation - can generate messages at any time, and/or in an order which is different from the - order of the OpenGL commands which caused those messages to be logged. - The messages could also be generated from a thread that it's different from - the thread the context is currently bound to. This is because OpenGL - implementations are usually highly threaded and asynchronous, and therefore - no warranties are made about the relative order and the timings of the - debug messages. - - On the other hand, logging in synchronous mode has a high overhead, but - the OpenGL implementation guarantees that all the messages caused by a - certain command are received in order, before the command returns, - and from the same thread the OpenGL context is bound to. - - This means that when logging in synchronous mode you will be able to run - your OpenGL application in a debugger, put a breakpoint on a slot connected - to the messageLogged() signal, and see in the backtrace the exact call - that caused the logged message. This can be extremely useful to debug - an OpenGL problem. Note that if OpenGL rendering is happening in another - thread, you must force the signal/slot connection type to Qt::DirectConnection - in order to be able to see the actual backtrace. - - Refer to the LoggingMode enum documentation for more information about - logging modes. - - \note When real-time logging is enabled, debug messages will \e{not} be - inserted in the internal OpenGL debug log any more; messages already - present in the internal log will not be deleted, nor they will be emitted - through the messageLogged() signal. Since some messages might be generated - before real-time logging is started (and therefore be kept in the internal - OpenGL log), it is important to always check if it contains any message - after calling startLogging(). - - \section1 Inserting Messages in the Debug Log - - It is possible for applications and libraries to insert custom messages in - the debug log, for instance for marking a group of related OpenGL commands - and therefore being then able to identify eventual messages coming from them. - - In order to do so, you can create a QOpenGLDebugMessage object by calling - \l{QOpenGLDebugMessage::}{createApplicationMessage()} or - \l{QOpenGLDebugMessage::}{createThirdPartyMessage()}, and then inserting it - into the log by calling logMessage(): - - \snippet code/src_gui_opengl_qopengldebug.cpp 6 - - Note that OpenGL implementations have a vendor-specific limit to the length - of the messages that can be inserted in the debug log. You can retrieve - this length by calling the maximumMessageLength() method; messages longer - than the limit will automatically get truncated. - - \section1 Controlling the Debug Output - - QOpenGLDebugMessage is also able to apply filters to the debug messages, and - therefore limit the amount of messages logged. You can enable or disable - logging of messages by calling enableMessages() and disableMessages() - respectively. By default, all messages are logged. - - It is possible to enable or disable messages by selecting them by: - - \list - \li source, type and severity (and including all ids in the selection); - \li id, source and type (and including all severities in the selection). - \endlist - - Note that the "enabled" status for a given message is a property of the - (id, source, type, severity) tuple; the message attributes \e{do not} form - a hierarchy of any kind. You should be careful about the order of the calls - to enableMessages() and disableMessages(), as it will change which - messages will are enabled / disabled. - - It's not possible to filter by the message text itself; applications - have to do that on their own (in slots connected to the messageLogged() - signal, or after fetching the messages in the internal debug log - through loggedMessages()). - - In order to simplify the management of the enabled / disabled statuses, - QOpenGLDebugMessage also supports the concept of \c{debug groups}. A debug - group contains the group of enabled / disabled configurations of debug - messages. Moreover, debug groups are organized in a stack: it is possible - to push and pop groups by calling pushGroup() and popGroup() respectively. - (When an OpenGL context is created, there is already a group in the stack). - - The enableMessages() and disableMessages() functions will modify the - configuration in the current debug group, that is, the one at the top of - the debug groups stack. - - When a new group is pushed onto the debug groups stack, it will inherit - the configuration of the group that was previously on the top of the stack. - Vice versa, popping a debug group will restore the configuration of - the debug group that becomes the new top. - - Pushing (respectively popping) debug groups will also automatically generate - a debug message of type QOpenGLDebugMessage::GroupPushType (respectively - \l{QOpenGLDebugMessage::}{GroupPopType}). - - \sa QOpenGLDebugMessage -*/ - -/*! - \enum QOpenGLDebugMessage::Source - - The Source enum defines the source of the debug message. - - \value InvalidSource - The source of the message is invalid; this is the source of a - default-constructed QOpenGLDebugMessage object. - - \value APISource - The message was generated in response to OpenGL API calls. - - \value WindowSystemSource - The message was generated by the window system. - - \value ShaderCompilerSource - The message was generated by the shader compiler. - - \value ThirdPartySource - The message was generated by a third party, for instance an OpenGL - framework a or debugging toolkit. - - \value ApplicationSource - The message was generated by the application itself. - - \value OtherSource - The message was generated by a source not included in this - enumeration. - - \omitvalue LastSource - - \value AnySource - This value corresponds to a mask of all possible message sources. -*/ - -/*! - \enum QOpenGLDebugMessage::Type - - The Type enum defines the type of the debug message. - - \value InvalidType - The type of the message is invalid; this is the type of a - default-constructed QOpenGLDebugMessage object. - - \value ErrorType - The message represents an error. - - \value DeprecatedBehaviorType - The message represents an usage of deprecated behavior. - - \value UndefinedBehaviorType - The message represents an usage of undefined behavior. - - \value PortabilityType - The message represents an usage of vendor-specific behavior, - that might pose portability concerns. - - \value PerformanceType - The message represents a performance issue. - - \value OtherType - The message represents a type not included in this - enumeration. - - \value MarkerType - The message represents a marker in the debug log. - - \value GroupPushType - The message represents a debug group push operation. - - \value GroupPopType - The message represents a debug group pop operation. - - \omitvalue LastType - - \value AnyType - This value corresponds to a mask of all possible message types. -*/ - -/*! - \enum QOpenGLDebugMessage::Severity - - The Severity enum defines the severity of the debug message. - - \value InvalidSeverity - The severity of the message is invalid; this is the severity of a - default-constructed QOpenGLDebugMessage object. - - \value HighSeverity - The message has a high severity. - - \value MediumSeverity - The message has a medium severity. - - \value LowSeverity - The message has a low severity. - - \value NotificationSeverity - The message is a notification. - - \omitvalue LastSeverity - - \value AnySeverity - This value corresponds to a mask of all possible message severities. -*/ - -/*! - \property QOpenGLDebugLogger::loggingMode - - \brief the logging mode passed to startLogging(). - - Note that logging must have been started or the value of this property - will be meaningless. - - \sa startLogging(), isLogging() -*/ -/*! - \enum QOpenGLDebugLogger::LoggingMode - - The LoggingMode enum defines the logging mode of the logger object. - - \value AsynchronousLogging - Messages from the OpenGL server are logged asynchronously. This means - that messages can be logged some time after the corresponding OpenGL - actions that caused them, and even be received in an out-of-order - fashion, depending on the OpenGL implementation. This mode has a very low - performance penalty, as OpenGL implementations are heavily threaded - and asynchronous by nature. - - \value SynchronousLogging - Messages from the OpenGL server are logged synchronously and - sequentially. This has a severe performance hit, as OpenGL - implementations are very asynchronous by nature; but it's very useful - to debug OpenGL problems, as OpenGL guarantees that the messages - generated by a OpenGL command will be logged before the corresponding - command execution has returned. Therefore, you can install a breakpoint - on the messageLogged() signal and see in the backtrace which OpenGL - command caused it; the only caveat is that if you are using OpenGL from - multiple threads you may need to force direct connection when - connecting to the messageLogged() signal. -*/ - -// When using OpenGL ES 2.0, all the necessary GL_KHR_debug constants are -// provided in qopengles2ext.h. Unfortunately, newer versions of that file -// suffix everything with _KHR which causes extra headache when the goal is -// to have a single piece of code that builds in all our target -// environments. Therefore, try to detect this and use our custom defines -// instead, which we anyway need for OS X. - -#if defined(GL_KHR_debug) && defined(GL_DEBUG_SOURCE_API_KHR) -#define USE_MANUAL_DEFS -#endif - -// Under OSX (at least up to 10.8) we cannot include our copy of glext.h, -// but we use the system-wide one, which unfortunately lacks all the needed -// defines/typedefs. In order to make the code compile, we just add here -// the GL_KHR_debug defines. - -#ifndef GL_KHR_debug -#define GL_KHR_debug 1 -#define USE_MANUAL_DEFS -#endif - -#ifdef USE_MANUAL_DEFS - -#ifndef GL_DEBUG_OUTPUT_SYNCHRONOUS -#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 -#endif -#ifndef GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH -#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 -#endif -#ifndef GL_DEBUG_CALLBACK_FUNCTION -#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 -#endif -#ifndef GL_DEBUG_CALLBACK_USER_PARAM -#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 -#endif -#ifndef GL_DEBUG_SOURCE_API -#define GL_DEBUG_SOURCE_API 0x8246 -#endif -#ifndef GL_DEBUG_SOURCE_WINDOW_SYSTEM -#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 -#endif -#ifndef GL_DEBUG_SOURCE_SHADER_COMPILER -#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 -#endif -#ifndef GL_DEBUG_SOURCE_THIRD_PARTY -#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 -#endif -#ifndef GL_DEBUG_SOURCE_APPLICATION -#define GL_DEBUG_SOURCE_APPLICATION 0x824A -#endif -#ifndef GL_DEBUG_SOURCE_OTHER -#define GL_DEBUG_SOURCE_OTHER 0x824B -#endif -#ifndef GL_DEBUG_TYPE_ERROR -#define GL_DEBUG_TYPE_ERROR 0x824C -#endif -#ifndef GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR -#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D -#endif -#ifndef GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR -#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E -#endif -#ifndef GL_DEBUG_TYPE_PORTABILITY -#define GL_DEBUG_TYPE_PORTABILITY 0x824F -#endif -#ifndef GL_DEBUG_TYPE_PERFORMANCE -#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 -#endif -#ifndef GL_DEBUG_TYPE_OTHER -#define GL_DEBUG_TYPE_OTHER 0x8251 -#endif -#ifndef GL_DEBUG_TYPE_MARKER -#define GL_DEBUG_TYPE_MARKER 0x8268 -#endif -#ifndef GL_DEBUG_TYPE_PUSH_GROUP -#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 -#endif -#ifndef GL_DEBUG_TYPE_POP_GROUP -#define GL_DEBUG_TYPE_POP_GROUP 0x826A -#endif -#ifndef GL_DEBUG_SEVERITY_NOTIFICATION -#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B -#endif -#ifndef GL_MAX_DEBUG_GROUP_STACK_DEPTH -#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C -#endif -#ifndef GL_DEBUG_GROUP_STACK_DEPTH -#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D -#endif -#ifndef GL_BUFFER -#define GL_BUFFER 0x82E0 -#endif -#ifndef GL_SHADER -#define GL_SHADER 0x82E1 -#endif -#ifndef GL_PROGRAM -#define GL_PROGRAM 0x82E2 -#endif -#ifndef GL_QUERY -#define GL_QUERY 0x82E3 -#endif -#ifndef GL_PROGRAM_PIPELINE -#define GL_PROGRAM_PIPELINE 0x82E4 -#endif -#ifndef GL_SAMPLER -#define GL_SAMPLER 0x82E6 -#endif -#ifndef GL_DISPLAY_LIST -#define GL_DISPLAY_LIST 0x82E7 -#endif -#ifndef GL_MAX_LABEL_LENGTH -#define GL_MAX_LABEL_LENGTH 0x82E8 -#endif -#ifndef GL_MAX_DEBUG_MESSAGE_LENGTH -#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 -#endif -#ifndef GL_MAX_DEBUG_LOGGED_MESSAGES -#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 -#endif -#ifndef GL_DEBUG_LOGGED_MESSAGES -#define GL_DEBUG_LOGGED_MESSAGES 0x9145 -#endif -#ifndef GL_DEBUG_SEVERITY_HIGH -#define GL_DEBUG_SEVERITY_HIGH 0x9146 -#endif -#ifndef GL_DEBUG_SEVERITY_MEDIUM -#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 -#endif -#ifndef GL_DEBUG_SEVERITY_LOW -#define GL_DEBUG_SEVERITY_LOW 0x9148 -#endif -#ifndef GL_DEBUG_OUTPUT -#define GL_DEBUG_OUTPUT 0x92E0 -#endif -#ifndef GL_CONTEXT_FLAG_DEBUG_BIT -#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 -#endif -#ifndef GL_STACK_OVERFLOW -#define GL_STACK_OVERFLOW 0x0503 -#endif -#ifndef GL_STACK_UNDERFLOW -#define GL_STACK_UNDERFLOW 0x0504 -#endif - -typedef void (QOPENGLF_APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const GLvoid *userParam); - -#endif /* USE_MANUAL_DEFS */ - - -/*! - \internal -*/ -static QOpenGLDebugMessage::Source qt_messageSourceFromGL(GLenum source) -{ - switch (source) { - case GL_DEBUG_SOURCE_API: - return QOpenGLDebugMessage::APISource; - case GL_DEBUG_SOURCE_WINDOW_SYSTEM: - return QOpenGLDebugMessage::WindowSystemSource; - case GL_DEBUG_SOURCE_SHADER_COMPILER: - return QOpenGLDebugMessage::ShaderCompilerSource; - case GL_DEBUG_SOURCE_THIRD_PARTY: - return QOpenGLDebugMessage::ThirdPartySource; - case GL_DEBUG_SOURCE_APPLICATION: - return QOpenGLDebugMessage::ApplicationSource; - case GL_DEBUG_SOURCE_OTHER: - return QOpenGLDebugMessage::OtherSource; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message source from GL"); - return QOpenGLDebugMessage::OtherSource; -} - -/*! - \internal -*/ -static GLenum qt_messageSourceToGL(QOpenGLDebugMessage::Source source) -{ - switch (source) { - case QOpenGLDebugMessage::InvalidSource: - break; - case QOpenGLDebugMessage::APISource: - return GL_DEBUG_SOURCE_API; - case QOpenGLDebugMessage::WindowSystemSource: - return GL_DEBUG_SOURCE_WINDOW_SYSTEM; - case QOpenGLDebugMessage::ShaderCompilerSource: - return GL_DEBUG_SOURCE_SHADER_COMPILER; - case QOpenGLDebugMessage::ThirdPartySource: - return GL_DEBUG_SOURCE_THIRD_PARTY; - case QOpenGLDebugMessage::ApplicationSource: - return GL_DEBUG_SOURCE_APPLICATION; - case QOpenGLDebugMessage::OtherSource: - return GL_DEBUG_SOURCE_OTHER; - case QOpenGLDebugMessage::AnySource: - break; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message source"); - return GL_DEBUG_SOURCE_OTHER; -} - -/*! - \internal -*/ -static QString qt_messageSourceToString(QOpenGLDebugMessage::Source source) -{ - switch (source) { - case QOpenGLDebugMessage::InvalidSource: - return QStringLiteral("InvalidSource"); - case QOpenGLDebugMessage::APISource: - return QStringLiteral("APISource"); - case QOpenGLDebugMessage::WindowSystemSource: - return QStringLiteral("WindowSystemSource"); - case QOpenGLDebugMessage::ShaderCompilerSource: - return QStringLiteral("ShaderCompilerSource"); - case QOpenGLDebugMessage::ThirdPartySource: - return QStringLiteral("ThirdPartySource"); - case QOpenGLDebugMessage::ApplicationSource: - return QStringLiteral("ApplicationSource"); - case QOpenGLDebugMessage::OtherSource: - return QStringLiteral("OtherSource"); - case QOpenGLDebugMessage::AnySource: - return QStringLiteral("AnySource"); - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message source"); - return QString(); -} - -/*! - \internal -*/ -static QOpenGLDebugMessage::Type qt_messageTypeFromGL(GLenum type) -{ - switch (type) { - case GL_DEBUG_TYPE_ERROR: - return QOpenGLDebugMessage::ErrorType; - case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - return QOpenGLDebugMessage::DeprecatedBehaviorType; - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: - return QOpenGLDebugMessage::UndefinedBehaviorType; - case GL_DEBUG_TYPE_PORTABILITY: - return QOpenGLDebugMessage::PortabilityType; - case GL_DEBUG_TYPE_PERFORMANCE: - return QOpenGLDebugMessage::PerformanceType; - case GL_DEBUG_TYPE_OTHER: - return QOpenGLDebugMessage::OtherType; - case GL_DEBUG_TYPE_MARKER: - return QOpenGLDebugMessage::MarkerType; - case GL_DEBUG_TYPE_PUSH_GROUP: - return QOpenGLDebugMessage::GroupPushType; - case GL_DEBUG_TYPE_POP_GROUP: - return QOpenGLDebugMessage::GroupPopType; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message type from GL"); - return QOpenGLDebugMessage::OtherType; -} - -/*! - \internal -*/ -static GLenum qt_messageTypeToGL(QOpenGLDebugMessage::Type type) -{ - switch (type) { - case QOpenGLDebugMessage::InvalidType: - break; - case QOpenGLDebugMessage::ErrorType: - return GL_DEBUG_TYPE_ERROR; - case QOpenGLDebugMessage::DeprecatedBehaviorType: - return GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR; - case QOpenGLDebugMessage::UndefinedBehaviorType: - return GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR; - case QOpenGLDebugMessage::PortabilityType: - return GL_DEBUG_TYPE_PORTABILITY; - case QOpenGLDebugMessage::PerformanceType: - return GL_DEBUG_TYPE_PERFORMANCE; - case QOpenGLDebugMessage::OtherType: - return GL_DEBUG_TYPE_OTHER; - case QOpenGLDebugMessage::MarkerType: - return GL_DEBUG_TYPE_MARKER; - case QOpenGLDebugMessage::GroupPushType: - return GL_DEBUG_TYPE_PUSH_GROUP; - case QOpenGLDebugMessage::GroupPopType: - return GL_DEBUG_TYPE_POP_GROUP; - case QOpenGLDebugMessage::AnyType: - break; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type"); - return GL_DEBUG_TYPE_OTHER; -} - -/*! - \internal -*/ -static QString qt_messageTypeToString(QOpenGLDebugMessage::Type type) -{ - switch (type) { - case QOpenGLDebugMessage::InvalidType: - return QStringLiteral("InvalidType"); - case QOpenGLDebugMessage::ErrorType: - return QStringLiteral("ErrorType"); - case QOpenGLDebugMessage::DeprecatedBehaviorType: - return QStringLiteral("DeprecatedBehaviorType"); - case QOpenGLDebugMessage::UndefinedBehaviorType: - return QStringLiteral("UndefinedBehaviorType"); - case QOpenGLDebugMessage::PortabilityType: - return QStringLiteral("PortabilityType"); - case QOpenGLDebugMessage::PerformanceType: - return QStringLiteral("PerformanceType"); - case QOpenGLDebugMessage::OtherType: - return QStringLiteral("OtherType"); - case QOpenGLDebugMessage::MarkerType: - return QStringLiteral("MarkerType"); - case QOpenGLDebugMessage::GroupPushType: - return QStringLiteral("GroupPushType"); - case QOpenGLDebugMessage::GroupPopType: - return QStringLiteral("GroupPopType"); - case QOpenGLDebugMessage::AnyType: - return QStringLiteral("AnyType"); - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message type"); - return QString(); -} - -/*! - \internal -*/ -static QOpenGLDebugMessage::Severity qt_messageSeverityFromGL(GLenum severity) -{ - switch (severity) { - case GL_DEBUG_SEVERITY_HIGH: - return QOpenGLDebugMessage::HighSeverity; - case GL_DEBUG_SEVERITY_MEDIUM: - return QOpenGLDebugMessage::MediumSeverity; - case GL_DEBUG_SEVERITY_LOW: - return QOpenGLDebugMessage::LowSeverity; - case GL_DEBUG_SEVERITY_NOTIFICATION: - return QOpenGLDebugMessage::NotificationSeverity; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message severity from GL"); - return QOpenGLDebugMessage::NotificationSeverity; -} - -/*! - \internal -*/ -static GLenum qt_messageSeverityToGL(QOpenGLDebugMessage::Severity severity) -{ - switch (severity) { - case QOpenGLDebugMessage::InvalidSeverity: - break; - case QOpenGLDebugMessage::HighSeverity: - return GL_DEBUG_SEVERITY_HIGH; - case QOpenGLDebugMessage::MediumSeverity: - return GL_DEBUG_SEVERITY_MEDIUM; - case QOpenGLDebugMessage::LowSeverity: - return GL_DEBUG_SEVERITY_LOW; - case QOpenGLDebugMessage::NotificationSeverity: - return GL_DEBUG_SEVERITY_NOTIFICATION; - case QOpenGLDebugMessage::AnySeverity: - break; - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message severity"); - return GL_DEBUG_SEVERITY_NOTIFICATION; -} - -/*! - \internal -*/ -static QString qt_messageSeverityToString(QOpenGLDebugMessage::Severity severity) -{ - switch (severity) { - case QOpenGLDebugMessage::InvalidSeverity: - return QStringLiteral("InvalidSeverity"); - case QOpenGLDebugMessage::HighSeverity: - return QStringLiteral("HighSeverity"); - case QOpenGLDebugMessage::MediumSeverity: - return QStringLiteral("MediumSeverity"); - case QOpenGLDebugMessage::LowSeverity: - return QStringLiteral("LowSeverity"); - case QOpenGLDebugMessage::NotificationSeverity: - return QStringLiteral("NotificationSeverity"); - case QOpenGLDebugMessage::AnySeverity: - return QStringLiteral("AnySeverity"); - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message severity"); - return QString(); -} - -class QOpenGLDebugMessagePrivate : public QSharedData -{ -public: - QOpenGLDebugMessagePrivate(); - - QString message; - GLuint id; - QOpenGLDebugMessage::Source source; - QOpenGLDebugMessage::Type type; - QOpenGLDebugMessage::Severity severity; -}; - -/*! - \internal -*/ -QOpenGLDebugMessagePrivate::QOpenGLDebugMessagePrivate() - : message(), - id(0), - source(QOpenGLDebugMessage::InvalidSource), - type(QOpenGLDebugMessage::InvalidType), - severity(QOpenGLDebugMessage::InvalidSeverity) -{ -} - - -/*! - Constructs a debug message with an empty message string, id set to 0, - source set to InvalidSource, type set to InvalidType, and severity set to - InvalidSeverity. - - \note This constructor should not be used to create a debug message; - instead, use the createApplicationMessage() or the createThirdPartyMessage() - static functions. - - \sa createApplicationMessage(), createThirdPartyMessage() -*/ -QOpenGLDebugMessage::QOpenGLDebugMessage() - : d(new QOpenGLDebugMessagePrivate) -{ -} - -/*! - Constructs a debug message as a copy of \a debugMessage. - - \sa operator=() -*/ -QOpenGLDebugMessage::QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage) - : d(debugMessage.d) -{ -} - -/*! - Destroys this debug message. -*/ -QOpenGLDebugMessage::~QOpenGLDebugMessage() -{ -} - -/*! - Assigns the message \a debugMessage to this object, and returns a reference - to the copy. -*/ -QOpenGLDebugMessage &QOpenGLDebugMessage::operator=(const QOpenGLDebugMessage &debugMessage) -{ - d = debugMessage.d; - return *this; -} - -/*! - \fn QOpenGLDebugMessage &QOpenGLDebugMessage::operator=(QOpenGLDebugMessage &&debugMessage) - - Move-assigns \a debugMessage to this object. -*/ - -/*! - \fn void QOpenGLDebugMessage::swap(QOpenGLDebugMessage &debugMessage) - - Swaps the message \a debugMessage with this message. This operation is very - fast and never fails. -*/ - -/*! - Returns the source of the debug message. -*/ -QOpenGLDebugMessage::Source QOpenGLDebugMessage::source() const -{ - return d->source; -} - -/*! - Returns the type of the debug message. -*/ -QOpenGLDebugMessage::Type QOpenGLDebugMessage::type() const -{ - return d->type; -} - -/*! - Returns the severity of the debug message. -*/ -QOpenGLDebugMessage::Severity QOpenGLDebugMessage::severity() const -{ - return d->severity; -} - -/*! - Returns the id of the debug message. Ids are generally vendor-specific. -*/ -GLuint QOpenGLDebugMessage::id() const -{ - return d->id; -} - -/*! - Returns the textual message contained by this debug message. -*/ -QString QOpenGLDebugMessage::message() const -{ - return d->message; -} - -/*! - Constructs and returns a debug message with \a text as its text, \a id - as id, \a severity as severity, and \a type as type. The message source - will be set to ApplicationSource. - - \sa QOpenGLDebugLogger::logMessage(), createThirdPartyMessage() -*/ -QOpenGLDebugMessage QOpenGLDebugMessage::createApplicationMessage(const QString &text, - GLuint id, - QOpenGLDebugMessage::Severity severity, - QOpenGLDebugMessage::Type type) -{ - QOpenGLDebugMessage m; - m.d->message = text; - m.d->id = id; - m.d->severity = severity; - m.d->type = type; - m.d->source = ApplicationSource; - return m; -} - -/*! - Constructs and returns a debug message with \a text as its text, \a id - as id, \a severity as severity, and \a type as type. The message source - will be set to ThirdPartySource. - - \sa QOpenGLDebugLogger::logMessage(), createApplicationMessage() -*/ -QOpenGLDebugMessage QOpenGLDebugMessage::createThirdPartyMessage(const QString &text, - GLuint id, - QOpenGLDebugMessage::Severity severity, - QOpenGLDebugMessage::Type type) -{ - QOpenGLDebugMessage m; - m.d->message = text; - m.d->id = id; - m.d->severity = severity; - m.d->type = type; - m.d->source = ThirdPartySource; - return m; -} - -/*! - Returns \c true if this debug message is equal to \a debugMessage, or false - otherwise. Two debugging messages are equal if they have the same textual - message, the same id, the same source, the same type and the same severity. - - \sa operator!=() -*/ -bool QOpenGLDebugMessage::operator==(const QOpenGLDebugMessage &debugMessage) const -{ - return (d == debugMessage.d) - || (d->id == debugMessage.d->id - && d->source == debugMessage.d->source - && d->type == debugMessage.d->type - && d->severity == debugMessage.d->severity - && d->message == debugMessage.d->message); -} - -/*! - \fn bool QOpenGLDebugMessage::operator!=(const QOpenGLDebugMessage &debugMessage) const - - Returns \c true if this message is different from \a debugMessage, or false - otherwise. - - \sa operator==() -*/ - -#ifndef QT_NO_DEBUG_STREAM -/*! - \relates QOpenGLDebugMessage - - Writes the source \a source into the debug object \a debug for debugging - purposes. -*/ -QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Source source) -{ - QDebugStateSaver saver(debug); - debug.nospace() << "QOpenGLDebugMessage::Source(" - << qt_messageSourceToString(source) - << ')'; - return debug; -} - -/*! - \relates QOpenGLDebugMessage - - Writes the type \a type into the debug object \a debug for debugging - purposes. -*/ -QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Type type) -{ - QDebugStateSaver saver(debug); - debug.nospace() << "QOpenGLDebugMessage::Type(" - << qt_messageTypeToString(type) - << ')'; - return debug; -} - -/*! - \relates QOpenGLDebugMessage - - Writes the severity \a severity into the debug object \a debug for debugging - purposes. -*/ -QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Severity severity) -{ - QDebugStateSaver saver(debug); - debug.nospace() << "QOpenGLDebugMessage::Severity(" - << qt_messageSeverityToString(severity) - << ')'; - return debug; -} - -/*! - \relates QOpenGLDebugMessage - - Writes the message \a message into the debug object \a debug for debugging - purposes. -*/ -QDebug operator<<(QDebug debug, const QOpenGLDebugMessage &message) -{ - QDebugStateSaver saver(debug); - debug.nospace() << "QOpenGLDebugMessage(" - << qt_messageSourceToString(message.source()) << ", " - << message.id() << ", " - << message.message() << ", " - << qt_messageSeverityToString(message.severity()) << ", " - << qt_messageTypeToString(message.type()) << ')'; - return debug; - -} -#endif // QT_NO_DEBUG_STREAM - -typedef void (QOPENGLF_APIENTRYP qt_glDebugMessageControl_t)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -typedef void (QOPENGLF_APIENTRYP qt_glDebugMessageInsert_t)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -typedef void (QOPENGLF_APIENTRYP qt_glDebugMessageCallback_t)(GLDEBUGPROC callback, const void *userParam); -typedef GLuint (QOPENGLF_APIENTRYP qt_glGetDebugMessageLog_t)(GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -typedef void (QOPENGLF_APIENTRYP qt_glPushDebugGroup_t)(GLenum source, GLuint id, GLsizei length, const GLchar *message); -typedef void (QOPENGLF_APIENTRYP qt_glPopDebugGroup_t)(); -typedef void (QOPENGLF_APIENTRYP qt_glGetPointerv_t)(GLenum pname, GLvoid **params); - -class QOpenGLDebugLoggerPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QOpenGLDebugLogger) -public: - QOpenGLDebugLoggerPrivate(); - - void handleMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *rawMessage); - void controlDebugMessages(QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types, - QOpenGLDebugMessage::Severities severities, - const QVector<GLuint> &ids, - const QByteArray &callerName, - bool enable); - void _q_contextAboutToBeDestroyed(); - - qt_glDebugMessageControl_t glDebugMessageControl; - qt_glDebugMessageInsert_t glDebugMessageInsert; - qt_glDebugMessageCallback_t glDebugMessageCallback; - qt_glGetDebugMessageLog_t glGetDebugMessageLog; - qt_glPushDebugGroup_t glPushDebugGroup; - qt_glPopDebugGroup_t glPopDebugGroup; - qt_glGetPointerv_t glGetPointerv; - - GLDEBUGPROC oldDebugCallbackFunction; - void *oldDebugCallbackParameter; - QOpenGLContext *context; - GLint maxMessageLength; - QOpenGLDebugLogger::LoggingMode loggingMode; - bool initialized : 1; - bool isLogging : 1; - bool debugWasEnabled : 1; - bool syncDebugWasEnabled : 1; -}; - -/*! - \internal -*/ -QOpenGLDebugLoggerPrivate::QOpenGLDebugLoggerPrivate() - : glDebugMessageControl(nullptr), - glDebugMessageInsert(nullptr), - glDebugMessageCallback(nullptr), - glGetDebugMessageLog(nullptr), - glPushDebugGroup(nullptr), - glPopDebugGroup(nullptr), - oldDebugCallbackFunction(nullptr), - context(nullptr), - maxMessageLength(0), - loggingMode(QOpenGLDebugLogger::AsynchronousLogging), - initialized(false), - isLogging(false), - debugWasEnabled(false), - syncDebugWasEnabled(false) -{ -} - -/*! - \internal -*/ -void QOpenGLDebugLoggerPrivate::handleMessage(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar *rawMessage) -{ - if (oldDebugCallbackFunction) - oldDebugCallbackFunction(source, type, id, severity, length, rawMessage, oldDebugCallbackParameter); - - QOpenGLDebugMessage message; - - QOpenGLDebugMessagePrivate *messagePrivate = message.d.data(); - messagePrivate->source = qt_messageSourceFromGL(source); - messagePrivate->type = qt_messageTypeFromGL(type); - messagePrivate->id = id; - messagePrivate->severity = qt_messageSeverityFromGL(severity); - // not passing the length to fromUtf8, as some bugged OpenGL drivers - // do not handle the length correctly. Just rely on the message to be NUL terminated. - messagePrivate->message = QString::fromUtf8(rawMessage); - - Q_Q(QOpenGLDebugLogger); - emit q->messageLogged(message); -} - -/*! - \internal -*/ -void QOpenGLDebugLoggerPrivate::controlDebugMessages(QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types, - QOpenGLDebugMessage::Severities severities, - const QVector<GLuint> &ids, - const QByteArray &callerName, - bool enable) -{ - if (!initialized) { - qWarning("QOpenGLDebugLogger::%s(): object must be initialized before enabling/disabling messages", callerName.constData()); - return; - } - if (sources == QOpenGLDebugMessage::InvalidSource) { - qWarning("QOpenGLDebugLogger::%s(): invalid source specified", callerName.constData()); - return; - } - if (types == QOpenGLDebugMessage::InvalidType) { - qWarning("QOpenGLDebugLogger::%s(): invalid type specified", callerName.constData()); - return; - } - if (severities == QOpenGLDebugMessage::InvalidSeverity) { - qWarning("QOpenGLDebugLogger::%s(): invalid severity specified", callerName.constData()); - return; - } - - QVarLengthArray<GLenum, 8> glSources; - QVarLengthArray<GLenum, 8> glTypes; - QVarLengthArray<GLenum, 8> glSeverities; - - if (ids.count() > 0) { - Q_ASSERT(severities == QOpenGLDebugMessage::AnySeverity); - - // The GL_KHR_debug extension says: - // - // - If <count> is greater than zero, then <ids> is an array of <count> - // message IDs for the specified combination of <source> and <type>. In - // this case, if <source> or <type> is DONT_CARE, or <severity> is not - // DONT_CARE, the error INVALID_OPERATION is generated. If <count> is - // zero, the value if <ids> is ignored. - // - // This means we can't convert AnySource or AnyType into DONT_CARE, but we have to roll - // them into individual sources/types. - - if (sources == QOpenGLDebugMessage::AnySource) { - sources = QOpenGLDebugMessage::InvalidSource; - for (uint i = 1; i <= QOpenGLDebugMessage::LastSource; i = i << 1) - sources |= QOpenGLDebugMessage::Source(i); - } - - if (types == QOpenGLDebugMessage::AnyType) { - types = QOpenGLDebugMessage::InvalidType; - for (uint i = 1; i <= QOpenGLDebugMessage::LastType; i = i << 1) - types |= QOpenGLDebugMessage::Type(i); - } - } - -#define CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(type, source, target) \ - if (source == QOpenGLDebugMessage::Any ## type) { \ - target << GL_DONT_CARE; \ - } else { \ - for (uint i = 1; i <= QOpenGLDebugMessage::Last ## type; i = i << 1) \ - if (source.testFlag(QOpenGLDebugMessage:: type (i))) \ - target << qt_message ## type ## ToGL (QOpenGLDebugMessage:: type (i)); \ - } - - CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(Source, sources, glSources) - CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(Type, types, glTypes) - CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(Severity, severities, glSeverities) -#undef CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS - - const GLsizei idCount = ids.count(); - // The GL_KHR_debug extension says that if idCount is 0, idPtr must be ignored. - // Unfortunately, some bugged drivers do NOT ignore it, so pass NULL in case. - const GLuint * const idPtr = idCount ? ids.constData() : nullptr; - - for (GLenum source : glSources) - for (GLenum type : glTypes) - for (GLenum severity : glSeverities) - glDebugMessageControl(source, type, severity, idCount, idPtr, GLboolean(enable)); -} - -/*! - \internal -*/ -void QOpenGLDebugLoggerPrivate::_q_contextAboutToBeDestroyed() -{ - Q_ASSERT(context); - - // Re-make our context current somehow, otherwise stopLogging will fail. - - // Save the current context and its surface in case we need to set them back - QOpenGLContext *currentContext = QOpenGLContext::currentContext(); - QSurface *currentSurface = nullptr; - - QScopedPointer<QOffscreenSurface> offscreenSurface; - - if (context != currentContext) { - // Make our old context current on a temporary surface - if (currentContext) - currentSurface = currentContext->surface(); - - offscreenSurface.reset(new QOffscreenSurface); - offscreenSurface->setFormat(context->format()); - offscreenSurface->create(); - if (!context->makeCurrent(offscreenSurface.data())) - qWarning("QOpenGLDebugLoggerPrivate::_q_contextAboutToBeDestroyed(): could not make the owning GL context current for cleanup"); - } - - Q_Q(QOpenGLDebugLogger); - q->stopLogging(); - - if (offscreenSurface) { - // We did change the current context: set it back - if (currentContext) - currentContext->makeCurrent(currentSurface); - else - context->doneCurrent(); - } - - QObject::disconnect(context, SIGNAL(aboutToBeDestroyed()), q, SLOT(_q_contextAboutToBeDestroyed())); - context = nullptr; - initialized = false; -} - -extern "C" { -static void QOPENGLF_APIENTRY qt_opengl_debug_callback(GLenum source, - GLenum type, - GLuint id, - GLenum severity, - GLsizei length, - const GLchar *rawMessage, - const GLvoid *userParam) -{ - QOpenGLDebugLoggerPrivate *loggerPrivate = static_cast<QOpenGLDebugLoggerPrivate *>(const_cast<GLvoid *>(userParam)); - loggerPrivate->handleMessage(source, type, id, severity, length, rawMessage); -} -} - -/*! - Constructs a new logger object with the given \a parent. - - \note The object must be initialized before logging can happen. - - \sa initialize() -*/ -QOpenGLDebugLogger::QOpenGLDebugLogger(QObject *parent) - : QObject(*new QOpenGLDebugLoggerPrivate, parent) -{ - // QOpenGLDebugMessage is going to be mostly used as an argument - // of a cross thread connection, therefore let's ease the life for the users - // and register the type for them. - qRegisterMetaType<QOpenGLDebugMessage>(); -} - -/*! - Destroys the logger object. -*/ -QOpenGLDebugLogger::~QOpenGLDebugLogger() -{ - stopLogging(); -} - -/*! - Initializes the object in the current OpenGL context. The context must - support the \c{GL_KHR_debug} extension for the initialization to succeed. - The object must be initialized before any logging can happen. - - It is safe to call this function multiple times from the same context. - - This function can also be used to change the context of a previously - initialized object; note that in this case the object must not be logging - when you call this function. - - Returns \c true if the logger is successfully initialized; false otherwise. - - \sa QOpenGLContext -*/ -bool QOpenGLDebugLogger::initialize() -{ - QOpenGLContext *context = QOpenGLContext::currentContext(); - if (!context) { - qWarning("QOpenGLDebugLogger::initialize(): no current OpenGL context found."); - return false; - } - - Q_D(QOpenGLDebugLogger); - if (d->context == context) { - // context is non-NULL, d->context is non NULL only on successful initialization. - Q_ASSERT(d->initialized); - return true; - } - - if (d->isLogging) { - qWarning("QOpenGLDebugLogger::initialize(): cannot initialize the object while logging. Please stop the logging first."); - return false; - } - - if (d->context) - disconnect(d->context, SIGNAL(aboutToBeDestroyed()), this, SLOT(_q_contextAboutToBeDestroyed())); - - d->initialized = false; - d->context = nullptr; - - if (!context->hasExtension(QByteArrayLiteral("GL_KHR_debug"))) - return false; - - d->context = context; - connect(d->context, SIGNAL(aboutToBeDestroyed()), this, SLOT(_q_contextAboutToBeDestroyed())); - -#define GET_DEBUG_PROC_ADDRESS(procName) \ - d->procName = reinterpret_cast< qt_ ## procName ## _t >( \ - d->context->getProcAddress(d->context->isOpenGLES() ? (#procName "KHR") : (#procName)) \ - ); - - GET_DEBUG_PROC_ADDRESS(glDebugMessageControl); - GET_DEBUG_PROC_ADDRESS(glDebugMessageInsert); - GET_DEBUG_PROC_ADDRESS(glDebugMessageCallback); - GET_DEBUG_PROC_ADDRESS(glGetDebugMessageLog); - GET_DEBUG_PROC_ADDRESS(glPushDebugGroup); - GET_DEBUG_PROC_ADDRESS(glPopDebugGroup); - GET_DEBUG_PROC_ADDRESS(glGetPointerv) - -#undef GET_DEBUG_PROC_ADDRESS - - QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH, &d->maxMessageLength); - -#ifndef QT_NO_DEBUG - if (!d->context->format().testOption(QSurfaceFormat::DebugContext)) { - qWarning("QOpenGLDebugLogger::initialize(): the current context is not a debug context:\n" - " this means that the GL may not generate any debug output at all.\n" - " To avoid this warning, try creating the context with the\n" - " QSurfaceFormat::DebugContext surface format option."); - } -#endif // QT_NO_DEBUG - - d->initialized = true; - return true; -} - -/*! - Returns \c true if this object is currently logging, false otherwise. - - \sa startLogging() -*/ -bool QOpenGLDebugLogger::isLogging() const -{ - Q_D(const QOpenGLDebugLogger); - return d->isLogging; -} - -/*! - Starts logging messages coming from the OpenGL server. When a new message - is received, the signal messageLogged() is emitted, carrying the logged - message as argument. - - \a loggingMode specifies whether the logging must be asynchronous (the default) - or synchronous. - - QOpenGLDebugLogger will record the values of \c{GL_DEBUG_OUTPUT} and - \c{GL_DEBUG_OUTPUT_SYNCHRONOUS} when logging is started, and set them back - when logging is stopped. Moreover, any user-defined OpenGL debug callback - installed when this function is invoked will be restored when logging is - stopped; QOpenGLDebugLogger will ensure that the pre-existing callback will - still be invoked when logging. - - \note It's not possible to change the logging mode without stopping and - starting logging again. This might change in a future version of Qt. - - \note The object must be initialized before logging can happen. - - \sa stopLogging(), initialize() -*/ -void QOpenGLDebugLogger::startLogging(QOpenGLDebugLogger::LoggingMode loggingMode) -{ - Q_D(QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::startLogging(): object must be initialized before logging can start"); - return; - } - if (d->isLogging) { - qWarning("QOpenGLDebugLogger::startLogging(): this object is already logging"); - return; - } - - d->isLogging = true; - d->loggingMode = loggingMode; - - d->glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION, reinterpret_cast<void **>(&d->oldDebugCallbackFunction)); - d->glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM, &d->oldDebugCallbackParameter); - - d->glDebugMessageCallback(&qt_opengl_debug_callback, d); - - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - d->debugWasEnabled = funcs->glIsEnabled(GL_DEBUG_OUTPUT); - d->syncDebugWasEnabled = funcs->glIsEnabled(GL_DEBUG_OUTPUT_SYNCHRONOUS); - - if (d->loggingMode == SynchronousLogging) - funcs->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - else - funcs->glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - - funcs->glEnable(GL_DEBUG_OUTPUT); -} - -/*! - Returns the logging mode of the object. - - \sa startLogging() -*/ -QOpenGLDebugLogger::LoggingMode QOpenGLDebugLogger::loggingMode() const -{ - Q_D(const QOpenGLDebugLogger); - return d->loggingMode; -} - -/*! - Stops logging messages from the OpenGL server. - - \sa startLogging() -*/ -void QOpenGLDebugLogger::stopLogging() -{ - Q_D(QOpenGLDebugLogger); - if (!d->isLogging) - return; - - QOpenGLContext *currentContext = QOpenGLContext::currentContext(); - if (!currentContext || currentContext != d->context) { - qWarning("QOpenGLDebugLogger::stopLogging(): attempting to stop logging with the wrong OpenGL context current"); - return; - } - - d->isLogging = false; - - d->glDebugMessageCallback(d->oldDebugCallbackFunction, d->oldDebugCallbackParameter); - - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - if (!d->debugWasEnabled) - funcs->glDisable(GL_DEBUG_OUTPUT); - - if (d->syncDebugWasEnabled) - funcs->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - else - funcs->glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS); -} - -/*! - Inserts the message \a debugMessage into the OpenGL debug log. This provides - a way for applications or libraries to insert custom messages that can - ease the debugging of OpenGL applications. - - \note \a debugMessage must have QOpenGLDebugMessage::ApplicationSource or - QOpenGLDebugMessage::ThirdPartySource as its source, and a valid - type and severity, otherwise it will not be inserted into the log. - - \note The object must be initialized before logging can happen. - - \sa initialize() -*/ -void QOpenGLDebugLogger::logMessage(const QOpenGLDebugMessage &debugMessage) -{ - Q_D(QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::logMessage(): object must be initialized before logging messages"); - return; - } - if (debugMessage.source() != QOpenGLDebugMessage::ApplicationSource - && debugMessage.source() != QOpenGLDebugMessage::ThirdPartySource) { - qWarning("QOpenGLDebugLogger::logMessage(): using a message source different from ApplicationSource\n" - " or ThirdPartySource is not supported by GL_KHR_debug. The message will not be logged."); - return; - } - if (debugMessage.type() == QOpenGLDebugMessage::InvalidType - || debugMessage.type() == QOpenGLDebugMessage::AnyType - || debugMessage.severity() == QOpenGLDebugMessage::InvalidSeverity - || debugMessage.severity() == QOpenGLDebugMessage::AnySeverity) { - qWarning("QOpenGLDebugLogger::logMessage(): the message has a non-valid type and/or severity. The message will not be logged."); - return; - } - - const GLenum source = qt_messageSourceToGL(debugMessage.source()); - const GLenum type = qt_messageTypeToGL(debugMessage.type()); - const GLenum severity = qt_messageSeverityToGL(debugMessage.severity()); - QByteArray rawMessage = debugMessage.message().toUtf8(); - rawMessage.append('\0'); - - if (rawMessage.length() > d->maxMessageLength) { - qWarning("QOpenGLDebugLogger::logMessage(): message too long, truncating it\n" - " (%d bytes long, but the GL accepts up to %d bytes)", rawMessage.length(), d->maxMessageLength); - rawMessage.resize(d->maxMessageLength - 1); - rawMessage.append('\0'); - } - - // Don't pass rawMessage.length(), as unfortunately bugged - // OpenGL drivers will eat the trailing NUL in the message. Just rely - // on the message being NUL terminated. - d->glDebugMessageInsert(source, - type, - debugMessage.id(), - severity, - -1, - rawMessage.constData()); -} - -/*! - Pushes a debug group with name \a name, id \a id, and source \a source onto - the debug groups stack. If the group is successfully pushed, OpenGL will - automatically log a message with message \a name, id \a id, source \a - source, type QOpenGLDebugMessage::GroupPushType and severity - QOpenGLDebugMessage::NotificationSeverity. - - The newly pushed group will inherit the same filtering settings of the - group that was on the top of the stack; that is, the filtering will not be - changed by pushing a new group. - - \note The \a source must either be QOpenGLDebugMessage::ApplicationSource or - QOpenGLDebugMessage::ThirdPartySource, otherwise the group will not be pushed. - - \note The object must be initialized before managing debug groups. - - \sa popGroup(), enableMessages(), disableMessages() -*/ -void QOpenGLDebugLogger::pushGroup(const QString &name, GLuint id, QOpenGLDebugMessage::Source source) -{ - Q_D(QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::pushGroup(): object must be initialized before pushing a debug group"); - return; - } - if (source != QOpenGLDebugMessage::ApplicationSource - && source != QOpenGLDebugMessage::ThirdPartySource) { - qWarning("QOpenGLDebugLogger::pushGroup(): using a source different from ApplicationSource\n" - " or ThirdPartySource is not supported by GL_KHR_debug. The group will not be pushed."); - return; - } - - QByteArray rawName = name.toUtf8(); - rawName.append('\0'); - if (rawName.length() > d->maxMessageLength) { - qWarning("QOpenGLDebugLogger::pushGroup(): group name too long, truncating it\n" - " (%d bytes long, but the GL accepts up to %d bytes)", rawName.length(), d->maxMessageLength); - rawName.resize(d->maxMessageLength - 1); - rawName.append('\0'); - } - - // Don't pass rawMessage.length(), as unfortunately bugged - // OpenGL drivers will eat the trailing NUL in the name. Just rely - // on the name being NUL terminated. - d->glPushDebugGroup(qt_messageSourceToGL(source), id, -1, rawName.constData()); -} - -/*! - Pops the topmost debug group from the debug groups stack. If the group is - successfully popped, OpenGL will automatically log a message with message, - id and source matching those of the popped group, type - QOpenGLDebugMessage::GroupPopType and severity - QOpenGLDebugMessage::NotificationSeverity. - - Popping a debug group will restore the message filtering settings of the - group that becomes the top of the debug groups stack. - - \note The object must be initialized before managing debug groups. - - \sa pushGroup() -*/ -void QOpenGLDebugLogger::popGroup() -{ - Q_D(QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::pushGroup(): object must be initialized before popping a debug group"); - return; - } - - d->glPopDebugGroup(); -} - -/*! - Enables the logging of messages from the given \a sources, of the given \a - types and with the given \a severities and any message id. - - The logging will be enabled in the current control group. - - \sa disableMessages(), pushGroup(), popGroup() -*/ -void QOpenGLDebugLogger::enableMessages(QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types, - QOpenGLDebugMessage::Severities severities) -{ - Q_D(QOpenGLDebugLogger); - d->controlDebugMessages(sources, - types, - severities, - QVector<GLuint>(), - QByteArrayLiteral("enableMessages"), - true); -} - -/*! - Enables the logging of messages with the given \a ids, from the given \a - sources and of the given \a types and any severity. - - The logging will be enabled in the current control group. - - \sa disableMessages(), pushGroup(), popGroup() -*/ -void QOpenGLDebugLogger::enableMessages(const QVector<GLuint> &ids, - QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types) -{ - Q_D(QOpenGLDebugLogger); - d->controlDebugMessages(sources, - types, - QOpenGLDebugMessage::AnySeverity, - ids, - QByteArrayLiteral("enableMessages"), - true); -} - -/*! - Disables the logging of messages with the given \a sources, of the given \a - types and with the given \a severities and any message id. - - The logging will be disabled in the current control group. - - \sa enableMessages(), pushGroup(), popGroup() -*/ -void QOpenGLDebugLogger::disableMessages(QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types, - QOpenGLDebugMessage::Severities severities) -{ - Q_D(QOpenGLDebugLogger); - d->controlDebugMessages(sources, - types, - severities, - QVector<GLuint>(), - QByteArrayLiteral("disableMessages"), - false); -} - -/*! - Disables the logging of messages with the given \a ids, from the given \a - sources and of the given \a types and any severity. - - The logging will be disabled in the current control group. - - \sa enableMessages(), pushGroup(), popGroup() -*/ -void QOpenGLDebugLogger::disableMessages(const QVector<GLuint> &ids, - QOpenGLDebugMessage::Sources sources, - QOpenGLDebugMessage::Types types) -{ - Q_D(QOpenGLDebugLogger); - d->controlDebugMessages(sources, - types, - QOpenGLDebugMessage::AnySeverity, - ids, - QByteArrayLiteral("disableMessages"), - false); -} - -/*! - Reads all the available messages in the OpenGL internal debug log and - returns them. Moreover, this function will clear the internal debug log, - so that subsequent invocations will not return messages that were - already returned. - - \sa startLogging() -*/ -QList<QOpenGLDebugMessage> QOpenGLDebugLogger::loggedMessages() const -{ - Q_D(const QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::loggedMessages(): object must be initialized before reading logged messages"); - return QList<QOpenGLDebugMessage>(); - } - - static const GLuint maxMessageCount = 128; - GLuint messagesRead; - GLenum messageSources[maxMessageCount]; - GLenum messageTypes[maxMessageCount]; - GLuint messageIds[maxMessageCount]; - GLenum messageSeverities[maxMessageCount]; - GLsizei messageLengths[maxMessageCount]; - - QByteArray messagesBuffer; - messagesBuffer.resize(maxMessageCount * d->maxMessageLength); - - QList<QOpenGLDebugMessage> messages; - do { - messagesRead = d->glGetDebugMessageLog(maxMessageCount, - GLsizei(messagesBuffer.size()), - messageSources, - messageTypes, - messageIds, - messageSeverities, - messageLengths, - messagesBuffer.data()); - - const char *messagesBufferPtr = messagesBuffer.constData(); - for (GLuint i = 0; i < messagesRead; ++i) { - QOpenGLDebugMessage message; - - QOpenGLDebugMessagePrivate *messagePrivate = message.d.data(); - messagePrivate->source = qt_messageSourceFromGL(messageSources[i]); - messagePrivate->type = qt_messageTypeFromGL(messageTypes[i]); - messagePrivate->id = messageIds[i]; - messagePrivate->severity = qt_messageSeverityFromGL(messageSeverities[i]); - messagePrivate->message = QString::fromUtf8(messagesBufferPtr, messageLengths[i] - 1); - - messagesBufferPtr += messageLengths[i]; - messages << message; - } - } while (messagesRead == maxMessageCount); - - return messages; -} - -/*! - \fn void QOpenGLDebugLogger::messageLogged(const QOpenGLDebugMessage &debugMessage) - - This signal is emitted when a debug message (wrapped by the \a debugMessage - argument) is logged from the OpenGL server. - - Depending on the OpenGL implementation, this signal can be emitted - from other threads than the one(s) the receiver(s) lives in, and even - different from the thread the QOpenGLContext in which this object has - been initialized lives in. Moreover, the signal could be emitted from - multiple threads at the same time. This is normally not a problem, - as Qt will utilize a queued connection for cross-thread signal emissions, - but if you force the connection type to Direct then you must be aware of - the potential races in the slots connected to this signal. - - If logging have been started in SynchronousLogging mode, OpenGL guarantees - that this signal will be emitted from the same thread the QOpenGLContext - has been bound to, and no concurrent invocations will ever happen. - - \note Logging must have been started, or this signal will not be emitted. - - \sa startLogging() -*/ - -/*! - Returns the maximum supported length, in bytes, for the text of the messages - passed to logMessage(). This is also the maximum length of a debug group - name, as pushing or popping groups will automatically log a message with - the debug group name as the message text. - - If a message text is too long, it will be automatically truncated by - QOpenGLDebugLogger. - - \note Message texts are encoded in UTF-8 when they get passed to OpenGL, so - their size in bytes does not usually match the amount of UTF-16 code units, - as returned, for instance, by QString::length(). (It does if the message contains - 7-bit ASCII only data, which is typical for debug messages.) -*/ -qint64 QOpenGLDebugLogger::maximumMessageLength() const -{ - Q_D(const QOpenGLDebugLogger); - if (!d->initialized) { - qWarning("QOpenGLDebugLogger::maximumMessageLength(): object must be initialized before reading the maximum message length"); - return -1; - } - return d->maxMessageLength; -} - - -QT_END_NAMESPACE - -#include "moc_qopengldebug.cpp" diff --git a/src/gui/opengl/qopengldebug.h b/src/gui/opengl/qopengldebug.h deleted file mode 100644 index 7363985d60..0000000000 --- a/src/gui/opengl/qopengldebug.h +++ /dev/null @@ -1,221 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLDEBUG_H -#define QOPENGLDEBUG_H - -#include <QtGui/qtguiglobal.h> - -#ifndef QT_NO_OPENGL - -#include <QtCore/qshareddata.h> -#include <QtCore/qflags.h> -#include <QtCore/qlist.h> -#include <QtCore/qvector.h> -#include <QtCore/qmetatype.h> -#include <QtCore/qdebug.h> -#include <QtGui/qopenglcontext.h> - -#if defined(Q_CLANG_QDOC) -#undef GLuint -typedef unsigned int GLuint; -#endif - -QT_BEGIN_NAMESPACE - -class QOpenGLDebugLogger; -class QOpenGLDebugLoggerPrivate; -class QOpenGLDebugMessagePrivate; - -class Q_GUI_EXPORT QOpenGLDebugMessage -{ -public: - enum Source { - InvalidSource = 0x00000000, - APISource = 0x00000001, - WindowSystemSource = 0x00000002, - ShaderCompilerSource = 0x00000004, - ThirdPartySource = 0x00000008, - ApplicationSource = 0x00000010, - OtherSource = 0x00000020, - LastSource = OtherSource, // private API - AnySource = 0xffffffff - }; - Q_DECLARE_FLAGS(Sources, Source) - - enum Type { - InvalidType = 0x00000000, - ErrorType = 0x00000001, - DeprecatedBehaviorType = 0x00000002, - UndefinedBehaviorType = 0x00000004, - PortabilityType = 0x00000008, - PerformanceType = 0x00000010, - OtherType = 0x00000020, - MarkerType = 0x00000040, - GroupPushType = 0x00000080, - GroupPopType = 0x00000100, - LastType = GroupPopType, // private API - AnyType = 0xffffffff - }; - Q_DECLARE_FLAGS(Types, Type) - - enum Severity { - InvalidSeverity = 0x00000000, - HighSeverity = 0x00000001, - MediumSeverity = 0x00000002, - LowSeverity = 0x00000004, - NotificationSeverity = 0x00000008, - LastSeverity = NotificationSeverity, // private API - AnySeverity = 0xffffffff - }; - Q_DECLARE_FLAGS(Severities, Severity) - - QOpenGLDebugMessage(); - QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage); - - QOpenGLDebugMessage &operator=(const QOpenGLDebugMessage &debugMessage); - QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&other) noexcept { swap(other); return *this; } - ~QOpenGLDebugMessage(); - - void swap(QOpenGLDebugMessage &other) noexcept { qSwap(d, other.d); } - - Source source() const; - Type type() const; - Severity severity() const; - GLuint id() const; - QString message() const; - - static QOpenGLDebugMessage createApplicationMessage(const QString &text, - GLuint id = 0, - Severity severity = NotificationSeverity, - Type type = OtherType); - static QOpenGLDebugMessage createThirdPartyMessage(const QString &text, - GLuint id = 0, - Severity severity = NotificationSeverity, - Type type = OtherType); - - bool operator==(const QOpenGLDebugMessage &debugMessage) const; - inline bool operator!=(const QOpenGLDebugMessage &debugMessage) const { return !operator==(debugMessage); } - -private: - friend class QOpenGLDebugLogger; - friend class QOpenGLDebugLoggerPrivate; - QSharedDataPointer<QOpenGLDebugMessagePrivate> d; -}; - -Q_DECLARE_SHARED(QOpenGLDebugMessage) -Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLDebugMessage::Sources) -Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLDebugMessage::Types) -Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLDebugMessage::Severities) - -#ifndef QT_NO_DEBUG_STREAM -Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QOpenGLDebugMessage &message); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Source source); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Type type); -Q_GUI_EXPORT QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Severity severity); -#endif - -class QOpenGLDebugLoggerPrivate; - -class Q_GUI_EXPORT QOpenGLDebugLogger : public QObject -{ - Q_OBJECT - Q_PROPERTY(LoggingMode loggingMode READ loggingMode) - -public: - enum LoggingMode { - AsynchronousLogging, - SynchronousLogging - }; - Q_ENUM(LoggingMode) - - explicit QOpenGLDebugLogger(QObject *parent = nullptr); - ~QOpenGLDebugLogger(); - - bool initialize(); - - bool isLogging() const; - LoggingMode loggingMode() const; - - qint64 maximumMessageLength() const; - - void pushGroup(const QString &name, - GLuint id = 0, - QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource); - void popGroup(); - - void enableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, - QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, - QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity); - - void enableMessages(const QVector<GLuint> &ids, - QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, - QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType); - - void disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, - QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, - QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity); - - void disableMessages(const QVector<GLuint> &ids, - QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, - QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType); - - QList<QOpenGLDebugMessage> loggedMessages() const; - -public Q_SLOTS: - void logMessage(const QOpenGLDebugMessage &debugMessage); - void startLogging(LoggingMode loggingMode = AsynchronousLogging); - void stopLogging(); - -Q_SIGNALS: - void messageLogged(const QOpenGLDebugMessage &debugMessage); - -private: - Q_DISABLE_COPY(QOpenGLDebugLogger) - Q_DECLARE_PRIVATE(QOpenGLDebugLogger) - Q_PRIVATE_SLOT(d_func(), void _q_contextAboutToBeDestroyed()) -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QOpenGLDebugMessage) - -#endif // QT_NO_OPENGL - -#endif // QOPENGLDEBUG_H diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp deleted file mode 100644 index a569975486..0000000000 --- a/src/gui/opengl/qopenglengineshadermanager.cpp +++ /dev/null @@ -1,898 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopenglengineshadermanager_p.h" -#include "qopenglengineshadersource_p.h" -#include "qopenglpaintengine_p.h" -#include "qopenglshadercache_p.h" - -#include <QtGui/private/qopenglcontext_p.h> -#include <QtCore/qthreadstorage.h> - -#include <algorithm> - -#if defined(QT_DEBUG) -#include <QMetaEnum> -#endif - -// #define QT_GL_SHARED_SHADER_DEBUG - -QT_BEGIN_NAMESPACE - -class QOpenGLEngineSharedShadersResource : public QOpenGLSharedResource -{ -public: - QOpenGLEngineSharedShadersResource(QOpenGLContext *ctx) - : QOpenGLSharedResource(ctx->shareGroup()) - , m_shaders(new QOpenGLEngineSharedShaders(ctx)) - { - } - - ~QOpenGLEngineSharedShadersResource() - { - delete m_shaders; - } - - void invalidateResource() override - { - delete m_shaders; - m_shaders = nullptr; - } - - void freeResource(QOpenGLContext *) override - { - } - - QOpenGLEngineSharedShaders *shaders() const { return m_shaders; } - -private: - QOpenGLEngineSharedShaders *m_shaders; -}; - -class QOpenGLShaderStorage -{ -public: - QOpenGLEngineSharedShaders *shadersForThread(QOpenGLContext *context) { - QOpenGLMultiGroupSharedResource *&shaders = m_storage.localData(); - if (!shaders) - shaders = new QOpenGLMultiGroupSharedResource; - QOpenGLEngineSharedShadersResource *resource = - shaders->value<QOpenGLEngineSharedShadersResource>(context); - return resource ? resource->shaders() : nullptr; - } - -private: - QThreadStorage<QOpenGLMultiGroupSharedResource *> m_storage; -}; - -Q_GLOBAL_STATIC(QOpenGLShaderStorage, qt_shader_storage); - -QOpenGLEngineSharedShaders *QOpenGLEngineSharedShaders::shadersForContext(QOpenGLContext *context) -{ - return qt_shader_storage()->shadersForThread(context); -} - -const char* QOpenGLEngineSharedShaders::qShaderSnippets[] = { - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0 -}; - -QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context) - : blitShaderProg(nullptr) - , simpleShaderProg(nullptr) -{ - -/* - Rather than having the shader source array statically initialised, it is initialised - here instead. This is to allow new shader names to be inserted or existing names moved - around without having to change the order of the glsl strings. It is hoped this will - make future hard-to-find runtime bugs more obvious and generally give more solid code. -*/ - - // Check if the user has requested an OpenGL 3.2 Core Profile or higher - // and if so use GLSL 1.50 core shaders instead of legacy ones. - const QSurfaceFormat &fmt = context->format(); - const bool isCoreProfile = fmt.profile() == QSurfaceFormat::CoreProfile && fmt.version() >= qMakePair(3,2); - - const char** code = qShaderSnippets; // shortcut - - if (isCoreProfile) { - code[MainVertexShader] = qopenglslMainVertexShader_core; - code[MainWithTexCoordsVertexShader] = qopenglslMainWithTexCoordsVertexShader_core; - code[MainWithTexCoordsAndOpacityVertexShader] = qopenglslMainWithTexCoordsAndOpacityVertexShader_core; - - code[UntransformedPositionVertexShader] = qopenglslUntransformedPositionVertexShader_core; - code[PositionOnlyVertexShader] = qopenglslPositionOnlyVertexShader_core; - code[ComplexGeometryPositionOnlyVertexShader] = qopenglslComplexGeometryPositionOnlyVertexShader_core; - code[PositionWithPatternBrushVertexShader] = qopenglslPositionWithPatternBrushVertexShader_core; - code[PositionWithLinearGradientBrushVertexShader] = qopenglslPositionWithLinearGradientBrushVertexShader_core; - code[PositionWithConicalGradientBrushVertexShader] = qopenglslPositionWithConicalGradientBrushVertexShader_core; - code[PositionWithRadialGradientBrushVertexShader] = qopenglslPositionWithRadialGradientBrushVertexShader_core; - code[PositionWithTextureBrushVertexShader] = qopenglslPositionWithTextureBrushVertexShader_core; - code[AffinePositionWithPatternBrushVertexShader] = qopenglslAffinePositionWithPatternBrushVertexShader_core; - code[AffinePositionWithLinearGradientBrushVertexShader] = qopenglslAffinePositionWithLinearGradientBrushVertexShader_core; - code[AffinePositionWithConicalGradientBrushVertexShader] = qopenglslAffinePositionWithConicalGradientBrushVertexShader_core; - code[AffinePositionWithRadialGradientBrushVertexShader] = qopenglslAffinePositionWithRadialGradientBrushVertexShader_core; - code[AffinePositionWithTextureBrushVertexShader] = qopenglslAffinePositionWithTextureBrushVertexShader_core; - - code[MainFragmentShader_MO] = qopenglslMainFragmentShader_MO_core; - code[MainFragmentShader_M] = qopenglslMainFragmentShader_M_core; - code[MainFragmentShader_O] = qopenglslMainFragmentShader_O_core; - code[MainFragmentShader] = qopenglslMainFragmentShader_core; - code[MainFragmentShader_ImageArrays] = qopenglslMainFragmentShader_ImageArrays_core; - - code[ImageSrcFragmentShader] = qopenglslImageSrcFragmentShader_core; - code[ImageSrcWithPatternFragmentShader] = qopenglslImageSrcWithPatternFragmentShader_core; - code[NonPremultipliedImageSrcFragmentShader] = qopenglslNonPremultipliedImageSrcFragmentShader_core; - code[GrayscaleImageSrcFragmentShader] = qopenglslGrayscaleImageSrcFragmentShader_core; - code[AlphaImageSrcFragmentShader] = qopenglslAlphaImageSrcFragmentShader_core; - code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader_core; // Calls "customShader", which must be appended - code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader_core; - - code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_core; - code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader_core; - code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader_core; - code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader_core; - code[RadialGradientBrushSrcFragmentShader] = qopenglslRadialGradientBrushSrcFragmentShader_core; - code[ConicalGradientBrushSrcFragmentShader] = qopenglslConicalGradientBrushSrcFragmentShader_core; - code[ShockingPinkSrcFragmentShader] = qopenglslShockingPinkSrcFragmentShader_core; - - code[NoMaskFragmentShader] = ""; - code[MaskFragmentShader] = qopenglslMaskFragmentShader_core; - code[RgbMaskFragmentShaderPass1] = qopenglslRgbMaskFragmentShaderPass1_core; - code[RgbMaskFragmentShaderPass2] = qopenglslRgbMaskFragmentShaderPass2_core; - code[RgbMaskWithGammaFragmentShader] = ""; //### - } else { - code[MainVertexShader] = qopenglslMainVertexShader; - code[MainWithTexCoordsVertexShader] = qopenglslMainWithTexCoordsVertexShader; - code[MainWithTexCoordsAndOpacityVertexShader] = qopenglslMainWithTexCoordsAndOpacityVertexShader; - - code[UntransformedPositionVertexShader] = qopenglslUntransformedPositionVertexShader; - code[PositionOnlyVertexShader] = qopenglslPositionOnlyVertexShader; - code[ComplexGeometryPositionOnlyVertexShader] = qopenglslComplexGeometryPositionOnlyVertexShader; - code[PositionWithPatternBrushVertexShader] = qopenglslPositionWithPatternBrushVertexShader; - code[PositionWithLinearGradientBrushVertexShader] = qopenglslPositionWithLinearGradientBrushVertexShader; - code[PositionWithConicalGradientBrushVertexShader] = qopenglslPositionWithConicalGradientBrushVertexShader; - code[PositionWithRadialGradientBrushVertexShader] = qopenglslPositionWithRadialGradientBrushVertexShader; - code[PositionWithTextureBrushVertexShader] = qopenglslPositionWithTextureBrushVertexShader; - code[AffinePositionWithPatternBrushVertexShader] = qopenglslAffinePositionWithPatternBrushVertexShader; - code[AffinePositionWithLinearGradientBrushVertexShader] = qopenglslAffinePositionWithLinearGradientBrushVertexShader; - code[AffinePositionWithConicalGradientBrushVertexShader] = qopenglslAffinePositionWithConicalGradientBrushVertexShader; - code[AffinePositionWithRadialGradientBrushVertexShader] = qopenglslAffinePositionWithRadialGradientBrushVertexShader; - code[AffinePositionWithTextureBrushVertexShader] = qopenglslAffinePositionWithTextureBrushVertexShader; - - code[MainFragmentShader_MO] = qopenglslMainFragmentShader_MO; - code[MainFragmentShader_M] = qopenglslMainFragmentShader_M; - code[MainFragmentShader_O] = qopenglslMainFragmentShader_O; - code[MainFragmentShader] = qopenglslMainFragmentShader; - code[MainFragmentShader_ImageArrays] = qopenglslMainFragmentShader_ImageArrays; - - code[ImageSrcFragmentShader] = qopenglslImageSrcFragmentShader; - code[ImageSrcWithPatternFragmentShader] = qopenglslImageSrcWithPatternFragmentShader; - code[NonPremultipliedImageSrcFragmentShader] = qopenglslNonPremultipliedImageSrcFragmentShader; - code[GrayscaleImageSrcFragmentShader] = qopenglslGrayscaleImageSrcFragmentShader; - code[AlphaImageSrcFragmentShader] = qopenglslAlphaImageSrcFragmentShader; - code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader; // Calls "customShader", which must be appended - code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader; - code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader; - code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader; - code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader; - code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader; - code[RadialGradientBrushSrcFragmentShader] = qopenglslRadialGradientBrushSrcFragmentShader; - code[ConicalGradientBrushSrcFragmentShader] = qopenglslConicalGradientBrushSrcFragmentShader; - code[ShockingPinkSrcFragmentShader] = qopenglslShockingPinkSrcFragmentShader; - - code[NoMaskFragmentShader] = ""; - code[MaskFragmentShader] = qopenglslMaskFragmentShader; - code[RgbMaskFragmentShaderPass1] = qopenglslRgbMaskFragmentShaderPass1; - code[RgbMaskFragmentShaderPass2] = qopenglslRgbMaskFragmentShaderPass2; - code[RgbMaskWithGammaFragmentShader] = ""; //### - } - - // The composition shaders are just layout qualifiers and the same - // for all profiles that support them. - code[NoCompositionModeFragmentShader] = ""; - code[MultiplyCompositionModeFragmentShader] = qopenglslMultiplyCompositionModeFragmentShader; - code[ScreenCompositionModeFragmentShader] = qopenglslScreenCompositionModeFragmentShader; - code[OverlayCompositionModeFragmentShader] = qopenglslOverlayCompositionModeFragmentShader; - code[DarkenCompositionModeFragmentShader] = qopenglslDarkenCompositionModeFragmentShader; - code[LightenCompositionModeFragmentShader] = qopenglslLightenCompositionModeFragmentShader; - code[ColorDodgeCompositionModeFragmentShader] = qopenglslColorDodgeCompositionModeFragmentShader; - code[ColorBurnCompositionModeFragmentShader] = qopenglslColorBurnCompositionModeFragmentShader; - code[HardLightCompositionModeFragmentShader] = qopenglslHardLightCompositionModeFragmentShader; - code[SoftLightCompositionModeFragmentShader] = qopenglslSoftLightCompositionModeFragmentShader; - code[DifferenceCompositionModeFragmentShader] = qopenglslDifferenceCompositionModeFragmentShader; - code[ExclusionCompositionModeFragmentShader] = qopenglslExclusionCompositionModeFragmentShader; - -#if defined(QT_DEBUG) - // Check that all the elements have been filled: - for (int i = 0; i < TotalSnippetCount; ++i) { - if (Q_UNLIKELY(!qShaderSnippets[i])) { - qFatal("Shader snippet for %s (#%d) is missing!", - snippetNameStr(SnippetName(i)).constData(), i); - } - } -#endif - - QByteArray vertexSource; - QByteArray fragSource; - - // Compile up the simple shader: -#ifdef Q_OS_WASM - vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]); - vertexSource.append(qShaderSnippets[MainVertexShader]); -#else - vertexSource.append(qShaderSnippets[MainVertexShader]); - vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]); -#endif - fragSource.append(qShaderSnippets[MainFragmentShader]); - fragSource.append(qShaderSnippets[ShockingPinkSrcFragmentShader]); - - simpleShaderProg = new QOpenGLShaderProgram; - - CachedShader simpleShaderCache(fragSource, vertexSource); - - bool inCache = simpleShaderCache.load(simpleShaderProg, context); - - if (!inCache) { - if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource)) - qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile"); - if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) - qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile"); - - simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); - simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); - simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); - simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); - } - - simpleShaderProg->link(); - - if (Q_UNLIKELY(!simpleShaderProg->isLinked())) { - qCritical("Errors linking simple shader: %s", qPrintable(simpleShaderProg->log())); - } else { - if (!inCache) - simpleShaderCache.store(simpleShaderProg, context); - } - - // Compile the blit shader: - vertexSource.clear(); - vertexSource.append(qShaderSnippets[MainWithTexCoordsVertexShader]); - vertexSource.append(qShaderSnippets[UntransformedPositionVertexShader]); - - fragSource.clear(); - fragSource.append(qShaderSnippets[MainFragmentShader]); - fragSource.append(qShaderSnippets[ImageSrcFragmentShader]); - - blitShaderProg = new QOpenGLShaderProgram; - - CachedShader blitShaderCache(fragSource, vertexSource); - - inCache = blitShaderCache.load(blitShaderProg, context); - - if (!inCache) { - if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource)) - qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile"); - if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) - qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile"); - - blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); - blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); - } - - blitShaderProg->link(); - if (Q_UNLIKELY(!blitShaderProg->isLinked())) { - qCritical("Errors linking blit shader: %s", qPrintable(blitShaderProg->log())); - } else { - if (!inCache) - blitShaderCache.store(blitShaderProg, context); - } - -#ifdef QT_GL_SHARED_SHADER_DEBUG - qDebug(" -> QOpenGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); -#endif -} - -QOpenGLEngineSharedShaders::~QOpenGLEngineSharedShaders() -{ -#ifdef QT_GL_SHARED_SHADER_DEBUG - qDebug(" -> ~QOpenGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread()); -#endif - qDeleteAll(cachedPrograms); - cachedPrograms.clear(); - - if (blitShaderProg) { - delete blitShaderProg; - blitShaderProg = nullptr; - } - - if (simpleShaderProg) { - delete simpleShaderProg; - simpleShaderProg = nullptr; - } -} - -#if defined (QT_DEBUG) -QByteArray QOpenGLEngineSharedShaders::snippetNameStr(SnippetName name) -{ - QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("SnippetName")); - return QByteArray(m.valueToKey(name)); -} -#endif - -// The address returned here will only be valid until next time this function is called. -// The program is return bound. -QOpenGLEngineShaderProg *QOpenGLEngineSharedShaders::findProgramInCache(const QOpenGLEngineShaderProg &prog) -{ - for (int i = 0; i < cachedPrograms.size(); ++i) { - QOpenGLEngineShaderProg *cachedProg = cachedPrograms[i]; - if (*cachedProg == prog) { - // Move the program to the top of the list as a poor-man's cache algo - cachedPrograms.move(i, 0); - cachedProg->program->bind(); - return cachedProg; - } - } - - QScopedPointer<QOpenGLEngineShaderProg> newProg; - - do { - QByteArray fragSource; - // Insert the custom stage before the srcPixel shader to work around an ATI driver bug - // where you cannot forward declare a function that takes a sampler as argument. - if (prog.srcPixelFragShader == CustomImageSrcFragmentShader) - fragSource.append(prog.customStageSource); - fragSource.append(qShaderSnippets[prog.mainFragShader]); - fragSource.append(qShaderSnippets[prog.srcPixelFragShader]); - if (prog.compositionFragShader) - fragSource.append(qShaderSnippets[prog.compositionFragShader]); - if (prog.maskFragShader) - fragSource.append(qShaderSnippets[prog.maskFragShader]); - - QByteArray vertexSource; -#ifdef Q_OS_WASM - vertexSource.append(qShaderSnippets[prog.positionVertexShader]); - vertexSource.append(qShaderSnippets[prog.mainVertexShader]); -#else - vertexSource.append(qShaderSnippets[prog.mainVertexShader]); - vertexSource.append(qShaderSnippets[prog.positionVertexShader]); -#endif - QScopedPointer<QOpenGLShaderProgram> shaderProgram(new QOpenGLShaderProgram); - - CachedShader shaderCache(fragSource, vertexSource); - bool inCache = shaderCache.load(shaderProgram.data(), QOpenGLContext::currentContext()); - - if (!inCache) { - if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource)) { - QByteArray description; -#if defined(QT_DEBUG) - description.append("Vertex shader: main="); - description.append(snippetNameStr(prog.mainVertexShader)); - description.append(", position="); - description.append(snippetNameStr(prog.positionVertexShader)); -#endif - qWarning("Warning: \"%s\" failed to compile!", description.constData()); - break; - } - if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) { - QByteArray description; -#if defined(QT_DEBUG) - description.append("Fragment shader: main="); - description.append(snippetNameStr(prog.mainFragShader)); - description.append(", srcPixel="); - description.append(snippetNameStr(prog.srcPixelFragShader)); - if (prog.compositionFragShader) { - description.append(", composition="); - description.append(snippetNameStr(prog.compositionFragShader)); - } - if (prog.maskFragShader) { - description.append(", mask="); - description.append(snippetNameStr(prog.maskFragShader)); - } -#endif - qWarning("Warning: \"%s\" failed to compile!", description.constData()); - break; - } - - // We have to bind the vertex attribute names before the program is linked: - shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); - if (prog.useTextureCoords) - shaderProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); - if (prog.useOpacityAttribute) - shaderProgram->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR); - if (prog.usePmvMatrixAttribute) { - shaderProgram->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR); - shaderProgram->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR); - shaderProgram->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR); - } - } - - newProg.reset(new QOpenGLEngineShaderProg(prog)); - newProg->program = shaderProgram.take(); - - newProg->program->link(); - if (newProg->program->isLinked()) { - if (!inCache) - shaderCache.store(newProg->program, QOpenGLContext::currentContext()); - } else { - QString error; - error = QLatin1String("Shader program failed to link") - + QLatin1String(" Error Log:\n") - + QLatin1String(" ") + newProg->program->log(); - qWarning() << error; - break; - } - - newProg->program->bind(); - - if (newProg->maskFragShader != QOpenGLEngineSharedShaders::NoMaskFragmentShader) { - GLuint location = newProg->program->uniformLocation("maskTexture"); - newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT); - } - - if (cachedPrograms.count() > 30) { - // The cache is full, so delete the last 5 programs in the list. - // These programs will be least used, as a program us bumped to - // the top of the list when it's used. - for (int i = 0; i < 5; ++i) { - delete cachedPrograms.last(); - cachedPrograms.removeLast(); - } - } - - cachedPrograms.insert(0, newProg.data()); - } while (false); - - return newProg.take(); -} - -void QOpenGLEngineSharedShaders::cleanupCustomStage(QOpenGLCustomShaderStage* stage) -{ - auto hasStageAsCustomShaderSouce = [stage](QOpenGLEngineShaderProg *cachedProg) -> bool { - if (cachedProg->customStageSource == stage->source()) { - delete cachedProg; - return true; - } - return false; - }; - cachedPrograms.erase(std::remove_if(cachedPrograms.begin(), cachedPrograms.end(), - hasStageAsCustomShaderSouce), - cachedPrograms.end()); -} - - -QOpenGLEngineShaderManager::QOpenGLEngineShaderManager(QOpenGLContext* context) - : ctx(context), - shaderProgNeedsChanging(true), - complexGeometry(false), - srcPixelType(Qt::NoBrush), - opacityMode(NoOpacity), - maskType(NoMask), - compositionMode(QPainter::CompositionMode_SourceOver), - customSrcStage(nullptr), - currentShaderProg(nullptr) -{ - sharedShaders = QOpenGLEngineSharedShaders::shadersForContext(context); -} - -QOpenGLEngineShaderManager::~QOpenGLEngineShaderManager() -{ - //### - removeCustomStage(); -} - -GLuint QOpenGLEngineShaderManager::getUniformLocation(Uniform id) -{ - if (!currentShaderProg) - return 0; - - QVector<uint> &uniformLocations = currentShaderProg->uniformLocations; - if (uniformLocations.isEmpty()) - uniformLocations.fill(GLuint(-1), NumUniforms); - - const char uniformNames[][26] = { - "imageTexture", - "patternColor", - "globalOpacity", - "depth", - "maskTexture", - "fragmentColor", - "linearData", - "angle", - "halfViewportSize", - "fmp", - "fmp2_m_radius2", - "inverse_2_fmp2_m_radius2", - "sqrfr", - "bradius", - "invertedTextureSize", - "brushTransform", - "brushTexture", - "matrix" - }; - - if (uniformLocations.at(id) == GLuint(-1)) - uniformLocations[id] = currentShaderProg->program->uniformLocation(uniformNames[id]); - - return uniformLocations.at(id); -} - - -void QOpenGLEngineShaderManager::optimiseForBrushTransform(QTransform::TransformationType transformType) -{ - Q_UNUSED(transformType); // Currently ignored -} - -void QOpenGLEngineShaderManager::setDirty() -{ - shaderProgNeedsChanging = true; -} - -void QOpenGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style) -{ - Q_ASSERT(style != Qt::NoBrush); - if (srcPixelType == PixelSrcType(style)) - return; - - srcPixelType = style; - shaderProgNeedsChanging = true; //### -} - -void QOpenGLEngineShaderManager::setSrcPixelType(PixelSrcType type) -{ - if (srcPixelType == type) - return; - - srcPixelType = type; - shaderProgNeedsChanging = true; //### -} - -void QOpenGLEngineShaderManager::setOpacityMode(OpacityMode mode) -{ - if (opacityMode == mode) - return; - - opacityMode = mode; - shaderProgNeedsChanging = true; //### -} - -void QOpenGLEngineShaderManager::setMaskType(MaskType type) -{ - if (maskType == type) - return; - - maskType = type; - shaderProgNeedsChanging = true; //### -} - -void QOpenGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode) -{ - if (compositionMode == mode) - return; - - bool wasAdvanced = compositionMode > QPainter::CompositionMode_Plus; - bool isAdvanced = mode > QPainter::CompositionMode_Plus; - - compositionMode = mode; - shaderProgNeedsChanging = shaderProgNeedsChanging || wasAdvanced || isAdvanced; -} - -void QOpenGLEngineShaderManager::setCustomStage(QOpenGLCustomShaderStage* stage) -{ - if (customSrcStage) - removeCustomStage(); - customSrcStage = stage; - shaderProgNeedsChanging = true; -} - -void QOpenGLEngineShaderManager::removeCustomStage() -{ - if (customSrcStage) - customSrcStage->setInactive(); - customSrcStage = nullptr; - shaderProgNeedsChanging = true; -} - -QOpenGLShaderProgram* QOpenGLEngineShaderManager::currentProgram() -{ - if (currentShaderProg) - return currentShaderProg->program; - else - return sharedShaders->simpleProgram(); -} - -void QOpenGLEngineShaderManager::useSimpleProgram() -{ - sharedShaders->simpleProgram()->bind(); - QOpenGLContextPrivate* ctx_d = ctx->d_func(); - Q_UNUSED(ctx_d); - - QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine); - - active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true); - active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false); - active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false); - - shaderProgNeedsChanging = true; -} - -void QOpenGLEngineShaderManager::useBlitProgram() -{ - sharedShaders->blitProgram()->bind(); - QOpenGLContextPrivate* ctx_d = ctx->d_func(); - QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine); - active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true); - active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, true); - active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false); - shaderProgNeedsChanging = true; -} - -QOpenGLShaderProgram* QOpenGLEngineShaderManager::simpleProgram() -{ - return sharedShaders->simpleProgram(); -} - -QOpenGLShaderProgram* QOpenGLEngineShaderManager::blitProgram() -{ - return sharedShaders->blitProgram(); -} - - - -// Select & use the correct shader program using the current state. -// Returns \c true if program needed changing. -bool QOpenGLEngineShaderManager::useCorrectShaderProg() -{ - if (!shaderProgNeedsChanging) - return false; - - bool useCustomSrc = customSrcStage != nullptr; - if (useCustomSrc && srcPixelType != QOpenGLEngineShaderManager::ImageSrc && srcPixelType != Qt::TexturePattern) { - useCustomSrc = false; - qWarning("QOpenGLEngineShaderManager - Ignoring custom shader stage for non image src"); - } - - QOpenGLEngineShaderProg requiredProgram; - - bool texCoords = false; - - // Choose vertex shader shader position function (which typically also sets - // varyings) and the source pixel (srcPixel) fragment shader function: - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::InvalidSnippetName; - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::InvalidSnippetName; - bool isAffine = brushTransform.isAffine(); - if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) { - if (isAffine) - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::AffinePositionWithPatternBrushVertexShader; - else - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionWithPatternBrushVertexShader; - - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::PatternBrushSrcFragmentShader; - } - else switch (srcPixelType) { - default: - case Qt::NoBrush: - qFatal("QOpenGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set"); - break; - case QOpenGLEngineShaderManager::ImageSrc: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::ImageSrcFragmentShader; - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader; - texCoords = true; - break; - case QOpenGLEngineShaderManager::NonPremultipliedImageSrc: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::NonPremultipliedImageSrcFragmentShader; - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader; - texCoords = true; - break; - case QOpenGLEngineShaderManager::GrayscaleImageSrc: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::GrayscaleImageSrcFragmentShader; - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader; - texCoords = true; - break; - case QOpenGLEngineShaderManager::AlphaImageSrc: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::AlphaImageSrcFragmentShader; - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader; - texCoords = true; - break; - case QOpenGLEngineShaderManager::PatternSrc: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::ImageSrcWithPatternFragmentShader; - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader; - texCoords = true; - break; - case QOpenGLEngineShaderManager::TextureSrcWithPattern: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::TextureBrushSrcWithPatternFragmentShader; - requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader - : QOpenGLEngineSharedShaders::PositionWithTextureBrushVertexShader; - break; - case Qt::SolidPattern: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::SolidBrushSrcFragmentShader; - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader; - break; - case Qt::LinearGradientPattern: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader; - requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader - : QOpenGLEngineSharedShaders::PositionWithLinearGradientBrushVertexShader; - break; - case Qt::ConicalGradientPattern: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::ConicalGradientBrushSrcFragmentShader; - requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader - : QOpenGLEngineSharedShaders::PositionWithConicalGradientBrushVertexShader; - break; - case Qt::RadialGradientPattern: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader; - requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader - : QOpenGLEngineSharedShaders::PositionWithRadialGradientBrushVertexShader; - break; - case Qt::TexturePattern: - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::TextureBrushSrcFragmentShader; - requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader - : QOpenGLEngineSharedShaders::PositionWithTextureBrushVertexShader; - break; - }; - - if (useCustomSrc) { - requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::CustomImageSrcFragmentShader; - requiredProgram.customStageSource = customSrcStage->source(); - } - - const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus; - const bool hasMask = maskType != QOpenGLEngineShaderManager::NoMask; - - // Choose fragment shader main function: - if (opacityMode == AttributeOpacity) { - Q_ASSERT(!hasCompose && !hasMask); - requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_ImageArrays; - } else { - bool useGlobalOpacity = (opacityMode == UniformOpacity); - if (hasMask && useGlobalOpacity) - requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_MO; - if (hasMask && !useGlobalOpacity) - requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_M; - if (!hasMask && useGlobalOpacity) - requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_O; - if (!hasMask && !useGlobalOpacity) - requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader; - } - - if (hasMask) { - if (maskType == PixelMask) { - requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::MaskFragmentShader; - texCoords = true; - } else if (maskType == SubPixelMaskPass1) { - requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskFragmentShaderPass1; - texCoords = true; - } else if (maskType == SubPixelMaskPass2) { - requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskFragmentShaderPass2; - texCoords = true; - } else if (maskType == SubPixelWithGammaMask) { - requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskWithGammaFragmentShader; - texCoords = true; - } else { - qCritical("QOpenGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type"); - } - } else { - requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::NoMaskFragmentShader; - } - - if (hasCompose) { - switch (compositionMode) { - case QPainter::CompositionMode_Multiply: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::MultiplyCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_Screen: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ScreenCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_Overlay: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::OverlayCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_Darken: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::DarkenCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_Lighten: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::LightenCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_ColorDodge: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_ColorBurn: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_HardLight: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::HardLightCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_SoftLight: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::SoftLightCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_Difference: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::DifferenceCompositionModeFragmentShader; - break; - case QPainter::CompositionMode_Exclusion: - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ExclusionCompositionModeFragmentShader; - break; - default: - qWarning("QOpenGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode"); - } - } else { - requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::NoCompositionModeFragmentShader; - } - - // Choose vertex shader main function - if (opacityMode == AttributeOpacity) { - Q_ASSERT(texCoords); - requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader; - } else if (texCoords) { - requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainWithTexCoordsVertexShader; - } else { - requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainVertexShader; - } - requiredProgram.useTextureCoords = texCoords; - requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity); - if (complexGeometry && srcPixelType == Qt::SolidPattern) { - requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::ComplexGeometryPositionOnlyVertexShader; - requiredProgram.usePmvMatrixAttribute = false; - } else { - requiredProgram.usePmvMatrixAttribute = true; - - // Force complexGeometry off, since we currently don't support that mode for - // non-solid brushes - complexGeometry = false; - } - - // At this point, requiredProgram is fully populated so try to find the program in the cache - currentShaderProg = sharedShaders->findProgramInCache(requiredProgram); - - if (currentShaderProg && useCustomSrc) { - customSrcStage->setUniforms(currentShaderProg->program); - } - - // Make sure all the vertex attribute arrays the program uses are enabled (and the ones it - // doesn't use are disabled) - QOpenGLContextPrivate* ctx_d = ctx->d_func(); - QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine); - active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true); - active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, currentShaderProg && currentShaderProg->useTextureCoords); - active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, currentShaderProg && currentShaderProg->useOpacityAttribute); - - shaderProgNeedsChanging = false; - return true; -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopenglengineshadermanager_p.h b/src/gui/opengl/qopenglengineshadermanager_p.h deleted file mode 100644 index 14c79f5de3..0000000000 --- a/src/gui/opengl/qopenglengineshadermanager_p.h +++ /dev/null @@ -1,507 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $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. -// - -/* - VERTEX SHADERS - ============== - - Vertex shaders are specified as multiple (partial) shaders. On desktop, - this works fine. On ES, QOpenGLShader & QOpenGLShaderProgram will make partial - shaders work by concatenating the source in each QOpenGLShader and compiling - it as a single shader. This is abstracted nicely by QOpenGLShaderProgram and - the GL2 engine doesn't need to worry about it. - - Generally, there's two vertex shader objects. The position shaders are - the ones which set gl_Position. There's also two "main" vertex shaders, - one which just calls the position shader and another which also passes - through some texture coordinates from a vertex attribute array to a - varying. These texture coordinates are used for mask position in text - rendering and for the source coordinates in drawImage/drawPixmap. There's - also a "Simple" vertex shader for rendering a solid colour (used to render - into the stencil buffer where the actual colour value is discarded). - - The position shaders for brushes look scary. This is because many of the - calculations which logically belong in the fragment shader have been moved - into the vertex shader to improve performance. This is why the position - calculation is in a separate shader. Not only does it calculate the - position, but it also calculates some data to be passed to the fragment - shader as a varying. It is optimal to move as much of the calculation as - possible into the vertex shader as this is executed less often. - - The varyings passed to the fragment shaders are interpolated (which is - cheap). Unfortunately, GL will apply perspective correction to the - interpolation calusing errors. To get around this, the vertex shader must - apply perspective correction itself and set the w-value of gl_Position to - zero. That way, GL will be tricked into thinking it doesn't need to apply a - perspective correction and use linear interpolation instead (which is what - we want). Of course, if the brush transform is affeine, no perspective - correction is needed and a simpler vertex shader can be used instead. - - So there are the following "main" vertex shaders: - qopenglslMainVertexShader - qopenglslMainWithTexCoordsVertexShader - - And the following position vertex shaders: - qopenglslPositionOnlyVertexShader - qopenglslPositionWithTextureBrushVertexShader - qopenglslPositionWithPatternBrushVertexShader - qopenglslPositionWithLinearGradientBrushVertexShader - qopenglslPositionWithRadialGradientBrushVertexShader - qopenglslPositionWithConicalGradientBrushVertexShader - qopenglslAffinePositionWithTextureBrushVertexShader - qopenglslAffinePositionWithPatternBrushVertexShader - qopenglslAffinePositionWithLinearGradientBrushVertexShader - qopenglslAffinePositionWithRadialGradientBrushVertexShader - qopenglslAffinePositionWithConicalGradientBrushVertexShader - - Leading to 23 possible vertex shaders - - - FRAGMENT SHADERS - ================ - - Fragment shaders are also specified as multiple (partial) shaders. The - different fragment shaders represent the different stages in Qt's fragment - pipeline. There are 1-3 stages in this pipeline: First stage is to get the - fragment's colour value. The next stage is to get the fragment's mask value - (coverage value for anti-aliasing) and the final stage is to blend the - incoming fragment with the background (for composition modes not supported - by GL). - - Of these, the first stage will always be present. If Qt doesn't need to - apply anti-aliasing (because it's off or handled by multisampling) then - the coverage value doesn't need to be applied. (Note: There are two types - of mask, one for regular anti-aliasing and one for sub-pixel anti- - aliasing.) If the composition mode is one which GL supports natively then - the blending stage doesn't need to be applied. - - As eash stage can have multiple implementations, they are abstracted as - GLSL function calls with the following signatures: - - Brushes & image drawing are implementations of "qcolorp vec4 srcPixel()": - qopenglslImageSrcFragShader - qopenglslImageSrcWithPatternFragShader - qopenglslNonPremultipliedImageSrcFragShader - qopenglslSolidBrushSrcFragShader - qopenglslTextureBrushSrcFragShader - qopenglslTextureBrushWithPatternFragShader - qopenglslPatternBrushSrcFragShader - qopenglslLinearGradientBrushSrcFragShader - qopenglslRadialGradientBrushSrcFragShader - qopenglslConicalGradientBrushSrcFragShader - NOTE: It is assumed the colour returned by srcPixel() is pre-multiplied - - Masks are implementations of "qcolorp vec4 applyMask(qcolorp vec4 src)": - qopenglslMaskFragmentShader - qopenglslRgbMaskFragmentShaderPass1 - qopenglslRgbMaskFragmentShaderPass2 - qopenglslRgbMaskWithGammaFragmentShader - - Composition modes are "qcolorp vec4 compose(qcolorp vec4 src)": - qopenglslColorBurnCompositionModeFragmentShader - qopenglslColorDodgeCompositionModeFragmentShader - qopenglslDarkenCompositionModeFragmentShader - qopenglslDifferenceCompositionModeFragmentShader - qopenglslExclusionCompositionModeFragmentShader - qopenglslHardLightCompositionModeFragmentShader - qopenglslLightenCompositionModeFragmentShader - qopenglslMultiplyCompositionModeFragmentShader - qopenglslOverlayCompositionModeFragmentShader - qopenglslScreenCompositionModeFragmentShader - qopenglslSoftLightCompositionModeFragmentShader - - - Note: In the future, some GLSL compilers will support an extension allowing - a new 'color' precision specifier. To support this, qcolorp is used for - all color components so it can be defined to colorp or lowp depending upon - the implementation. - - So there are differnt frament shader main functions, depending on the - number & type of pipelines the fragment needs to go through. - - The choice of which main() fragment shader string to use depends on: - - Use of global opacity - - Brush style (some brushes apply opacity themselves) - - Use & type of mask (TODO: Need to support high quality anti-aliasing & text) - - Use of non-GL Composition mode - - Leading to the following fragment shader main functions: - gl_FragColor = compose(applyMask(srcPixel()*globalOpacity)); - gl_FragColor = compose(applyMask(srcPixel())); - gl_FragColor = applyMask(srcPixel()*globalOpacity); - gl_FragColor = applyMask(srcPixel()); - gl_FragColor = compose(srcPixel()*globalOpacity); - gl_FragColor = compose(srcPixel()); - gl_FragColor = srcPixel()*globalOpacity; - gl_FragColor = srcPixel(); - - Called: - qopenglslMainFragmentShader_CMO - qopenglslMainFragmentShader_CM - qopenglslMainFragmentShader_MO - qopenglslMainFragmentShader_M - qopenglslMainFragmentShader_CO - qopenglslMainFragmentShader_C - qopenglslMainFragmentShader_O - qopenglslMainFragmentShader - - Where: - M = Mask - C = Composition - O = Global Opacity - - - CUSTOM SHADER CODE - ================== - - The use of custom shader code is supported by the engine for drawImage and - drawPixmap calls. This is implemented via hooks in the fragment pipeline. - - The custom shader is passed to the engine as a partial fragment shader - (QOpenGLCustomShaderStage). The shader will implement a pre-defined method name - which Qt's fragment pipeline will call: - - lowp vec4 customShader(lowp sampler2d imageTexture, highp vec2 textureCoords) - - The provided src and srcCoords parameters can be used to sample from the - source image. - - Transformations, clipping, opacity, and composition modes set using QPainter - will be respected when using the custom shader hook. -*/ - -#ifndef QOPENGLENGINE_SHADER_MANAGER_H -#define QOPENGLENGINE_SHADER_MANAGER_H - -#include <QtGui/private/qtguiglobal_p.h> -#include <QOpenGLShader> -#include <QOpenGLShaderProgram> -#include <QPainter> -#include <private/qopenglcontext_p.h> -#include <private/qopenglcustomshaderstage_p.h> - -QT_BEGIN_NAMESPACE - - - -/* -struct QOpenGLEngineCachedShaderProg -{ - QOpenGLEngineCachedShaderProg(QOpenGLEngineShaderManager::ShaderName vertexMain, - QOpenGLEngineShaderManager::ShaderName vertexPosition, - QOpenGLEngineShaderManager::ShaderName fragMain, - QOpenGLEngineShaderManager::ShaderName pixelSrc, - QOpenGLEngineShaderManager::ShaderName mask, - QOpenGLEngineShaderManager::ShaderName composition); - - int cacheKey; - QOpenGLShaderProgram* program; -} -*/ - -static const GLuint QT_VERTEX_COORDS_ATTR = 0; -static const GLuint QT_TEXTURE_COORDS_ATTR = 1; -static const GLuint QT_OPACITY_ATTR = 2; -static const GLuint QT_PMV_MATRIX_1_ATTR = 3; -static const GLuint QT_PMV_MATRIX_2_ATTR = 4; -static const GLuint QT_PMV_MATRIX_3_ATTR = 5; - -class QOpenGLEngineShaderProg; - -class Q_GUI_EXPORT QOpenGLEngineSharedShaders -{ - Q_GADGET -public: - - enum SnippetName { - MainVertexShader, - MainWithTexCoordsVertexShader, - MainWithTexCoordsAndOpacityVertexShader, - - // UntransformedPositionVertexShader must be first in the list: - UntransformedPositionVertexShader, - PositionOnlyVertexShader, - ComplexGeometryPositionOnlyVertexShader, - PositionWithPatternBrushVertexShader, - PositionWithLinearGradientBrushVertexShader, - PositionWithConicalGradientBrushVertexShader, - PositionWithRadialGradientBrushVertexShader, - PositionWithTextureBrushVertexShader, - AffinePositionWithPatternBrushVertexShader, - AffinePositionWithLinearGradientBrushVertexShader, - AffinePositionWithConicalGradientBrushVertexShader, - AffinePositionWithRadialGradientBrushVertexShader, - AffinePositionWithTextureBrushVertexShader, - - // MainFragmentShader_CMO must be first in the list: - MainFragmentShader_MO, - MainFragmentShader_M, - MainFragmentShader_O, - MainFragmentShader, - MainFragmentShader_ImageArrays, - - // ImageSrcFragmentShader must be first in the list:: - ImageSrcFragmentShader, - ImageSrcWithPatternFragmentShader, - NonPremultipliedImageSrcFragmentShader, - GrayscaleImageSrcFragmentShader, - AlphaImageSrcFragmentShader, - CustomImageSrcFragmentShader, - SolidBrushSrcFragmentShader, - TextureBrushSrcFragmentShader, - TextureBrushSrcWithPatternFragmentShader, - PatternBrushSrcFragmentShader, - LinearGradientBrushSrcFragmentShader, - RadialGradientBrushSrcFragmentShader, - ConicalGradientBrushSrcFragmentShader, - ShockingPinkSrcFragmentShader, - - // NoMaskFragmentShader must be first in the list: - NoMaskFragmentShader, - MaskFragmentShader, - RgbMaskFragmentShaderPass1, - RgbMaskFragmentShaderPass2, - RgbMaskWithGammaFragmentShader, - - // NoCompositionModeFragmentShader must be first in the list: - NoCompositionModeFragmentShader, - MultiplyCompositionModeFragmentShader, - ScreenCompositionModeFragmentShader, - OverlayCompositionModeFragmentShader, - DarkenCompositionModeFragmentShader, - LightenCompositionModeFragmentShader, - ColorDodgeCompositionModeFragmentShader, - ColorBurnCompositionModeFragmentShader, - HardLightCompositionModeFragmentShader, - SoftLightCompositionModeFragmentShader, - DifferenceCompositionModeFragmentShader, - ExclusionCompositionModeFragmentShader, - - TotalSnippetCount, InvalidSnippetName - }; -#if defined (QT_DEBUG) - Q_ENUM(SnippetName) - static QByteArray snippetNameStr(SnippetName snippetName); -#endif - -/* - // These allow the ShaderName enum to be used as a cache key - const int mainVertexOffset = 0; - const int positionVertexOffset = (1<<2) - PositionOnlyVertexShader; - const int mainFragOffset = (1<<6) - MainFragmentShader_CMO; - const int srcPixelOffset = (1<<10) - ImageSrcFragmentShader; - const int maskOffset = (1<<14) - NoMaskShader; - const int compositionOffset = (1 << 16) - MultiplyCompositionModeFragmentShader; -*/ - - QOpenGLEngineSharedShaders(QOpenGLContext *context); - ~QOpenGLEngineSharedShaders(); - - QOpenGLShaderProgram *simpleProgram() { return simpleShaderProg; } - QOpenGLShaderProgram *blitProgram() { return blitShaderProg; } - // Compile the program if it's not already in the cache, return the item in the cache. - QOpenGLEngineShaderProg *findProgramInCache(const QOpenGLEngineShaderProg &prog); - // Compile the custom shader if it's not already in the cache, return the item in the cache. - - static QOpenGLEngineSharedShaders *shadersForContext(QOpenGLContext *context); - - // Ideally, this would be static and cleanup all programs in all contexts which - // contain the custom code. Currently it is just a hint and we rely on deleted - // custom shaders being cleaned up by being kicked out of the cache when it's - // full. - void cleanupCustomStage(QOpenGLCustomShaderStage* stage); - -private: - QOpenGLShaderProgram *blitShaderProg; - QOpenGLShaderProgram *simpleShaderProg; - QList<QOpenGLEngineShaderProg*> cachedPrograms; - - static const char* qShaderSnippets[TotalSnippetCount]; -}; - - -class QOpenGLEngineShaderProg -{ -public: - QOpenGLEngineShaderProg() : program(nullptr) {} - - ~QOpenGLEngineShaderProg() { - if (program) - delete program; - } - - QOpenGLEngineSharedShaders::SnippetName mainVertexShader; - QOpenGLEngineSharedShaders::SnippetName positionVertexShader; - QOpenGLEngineSharedShaders::SnippetName mainFragShader; - QOpenGLEngineSharedShaders::SnippetName srcPixelFragShader; - QOpenGLEngineSharedShaders::SnippetName maskFragShader; - QOpenGLEngineSharedShaders::SnippetName compositionFragShader; - - QByteArray customStageSource; //TODO: Decent cache key for custom stages - QOpenGLShaderProgram* program; - - QVector<uint> uniformLocations; - - bool useTextureCoords; - bool useOpacityAttribute; - bool usePmvMatrixAttribute; - - bool operator==(const QOpenGLEngineShaderProg& other) const { - // We don't care about the program - return ( mainVertexShader == other.mainVertexShader && - positionVertexShader == other.positionVertexShader && - mainFragShader == other.mainFragShader && - srcPixelFragShader == other.srcPixelFragShader && - maskFragShader == other.maskFragShader && - compositionFragShader == other.compositionFragShader && - customStageSource == other.customStageSource - ); - } -}; - -class Q_GUI_EXPORT QOpenGLEngineShaderManager : public QObject -{ - Q_OBJECT -public: - QOpenGLEngineShaderManager(QOpenGLContext* context); - ~QOpenGLEngineShaderManager(); - - enum MaskType {NoMask, PixelMask, SubPixelMaskPass1, SubPixelMaskPass2, SubPixelWithGammaMask}; - enum PixelSrcType { - ImageSrc = Qt::TexturePattern+1, - NonPremultipliedImageSrc = Qt::TexturePattern+2, - PatternSrc = Qt::TexturePattern+3, - TextureSrcWithPattern = Qt::TexturePattern+4, - GrayscaleImageSrc = Qt::TexturePattern+5, - AlphaImageSrc = Qt::TexturePattern+6, - }; - - enum Uniform { - ImageTexture, - PatternColor, - GlobalOpacity, - Depth, - MaskTexture, - FragmentColor, - LinearData, - Angle, - HalfViewportSize, - Fmp, - Fmp2MRadius2, - Inverse2Fmp2MRadius2, - SqrFr, - BRadius, - InvertedTextureSize, - BrushTransform, - BrushTexture, - Matrix, - NumUniforms - }; - - enum OpacityMode { - NoOpacity, - UniformOpacity, - AttributeOpacity - }; - - // There are optimizations we can do, depending on the brush transform: - // 1) May not have to apply perspective-correction - // 2) Can use lower precision for matrix - void optimiseForBrushTransform(QTransform::TransformationType transformType); - void setSrcPixelType(Qt::BrushStyle); - void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images - void setOpacityMode(OpacityMode); - void setMaskType(MaskType); - void setCompositionMode(QPainter::CompositionMode); - void setCustomStage(QOpenGLCustomShaderStage* stage); - void removeCustomStage(); - - GLuint getUniformLocation(Uniform id); - - void setDirty(); // someone has manually changed the current shader program - bool useCorrectShaderProg(); // returns true if the shader program needed to be changed - - void useSimpleProgram(); - void useBlitProgram(); - void setHasComplexGeometry(bool hasComplexGeometry) - { - complexGeometry = hasComplexGeometry; - shaderProgNeedsChanging = true; - } - bool hasComplexGeometry() const - { - return complexGeometry; - } - - QOpenGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen - QOpenGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers - QOpenGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer - - QOpenGLEngineSharedShaders* sharedShaders; - -private: - QOpenGLContext* ctx; - bool shaderProgNeedsChanging; - bool complexGeometry; - - // Current state variables which influence the choice of shader: - QTransform brushTransform; - int srcPixelType; - OpacityMode opacityMode; - MaskType maskType; - QPainter::CompositionMode compositionMode; - QOpenGLCustomShaderStage* customSrcStage; - - QOpenGLEngineShaderProg* currentShaderProg; -}; - -QT_END_NAMESPACE - -#endif //QOPENGLENGINE_SHADER_MANAGER_H diff --git a/src/gui/opengl/qopenglengineshadersource_p.h b/src/gui/opengl/qopenglengineshadersource_p.h deleted file mode 100644 index 3ac599b6c2..0000000000 --- a/src/gui/opengl/qopenglengineshadersource_p.h +++ /dev/null @@ -1,970 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $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 QOPENGL_ENGINE_SHADER_SOURCE_H -#define QOPENGL_ENGINE_SHADER_SOURCE_H - -#include <QtGui/private/qtguiglobal_p.h> -#include "qopenglengineshadermanager_p.h" - -QT_BEGIN_NAMESPACE - - -static const char* const qopenglslMainVertexShader = "\n\ - void setPosition(); \n\ - void main(void) \n\ - { \n\ - setPosition(); \n\ - }\n"; - -static const char* const qopenglslMainWithTexCoordsVertexShader = "\n\ - attribute highp vec2 textureCoordArray; \n\ - varying highp vec2 textureCoords; \n\ - void setPosition(); \n\ - void main(void) \n\ - { \n\ - setPosition(); \n\ - textureCoords = textureCoordArray; \n\ - }\n"; - -static const char* const qopenglslMainWithTexCoordsAndOpacityVertexShader = "\n\ - attribute highp vec2 textureCoordArray; \n\ - attribute lowp float opacityArray; \n\ - varying highp vec2 textureCoords; \n\ - varying lowp float opacity; \n\ - void setPosition(); \n\ - void main(void) \n\ - { \n\ - setPosition(); \n\ - textureCoords = textureCoordArray; \n\ - opacity = opacityArray; \n\ - }\n"; - -// NOTE: We let GL do the perspective correction so texture lookups in the fragment -// shader are also perspective corrected. -static const char* const qopenglslPositionOnlyVertexShader = "\n\ - attribute highp vec2 vertexCoordsArray; \n\ - attribute highp vec3 pmvMatrix1; \n\ - attribute highp vec3 pmvMatrix2; \n\ - attribute highp vec3 pmvMatrix3; \n\ - void setPosition(void) \n\ - { \n\ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\ - }\n"; - -static const char* const qopenglslComplexGeometryPositionOnlyVertexShader = "\n\ - uniform highp mat3 matrix; \n\ - attribute highp vec2 vertexCoordsArray; \n\ - void setPosition(void) \n\ - { \n\ - gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\ - } \n"; - -static const char* const qopenglslUntransformedPositionVertexShader = "\n\ - attribute highp vec4 vertexCoordsArray; \n\ - void setPosition(void) \n\ - { \n\ - gl_Position = vertexCoordsArray; \n\ - }\n"; - -// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 -static const char* const qopenglslPositionWithPatternBrushVertexShader = "\n\ - attribute highp vec2 vertexCoordsArray; \n\ - attribute highp vec3 pmvMatrix1; \n\ - attribute highp vec3 pmvMatrix2; \n\ - attribute highp vec3 pmvMatrix3; \n\ - uniform mediump vec2 halfViewportSize; \n\ - uniform highp vec2 invertedTextureSize; \n\ - uniform highp mat3 brushTransform; \n\ - varying highp vec2 patternTexCoords; \n\ - void setPosition(void) \n\ - { \n\ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithPatternBrushVertexShader - = qopenglslPositionWithPatternBrushVertexShader; - -static const char* const qopenglslPatternBrushSrcFragmentShader = "\n\ - uniform sampler2D brushTexture; \n\ - uniform lowp vec4 patternColor; \n\ - varying highp vec2 patternTexCoords;\n\ - lowp vec4 srcPixel() \n\ - { \n\ - return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \n\ - }\n"; - - -// Linear Gradient Brush -static const char* const qopenglslPositionWithLinearGradientBrushVertexShader = "\n\ - attribute highp vec2 vertexCoordsArray; \n\ - attribute highp vec3 pmvMatrix1; \n\ - attribute highp vec3 pmvMatrix2; \n\ - attribute highp vec3 pmvMatrix3; \n\ - uniform mediump vec2 halfViewportSize; \n\ - uniform highp vec3 linearData; \n\ - uniform highp mat3 brushTransform; \n\ - varying mediump float index; \n\ - void setPosition() \n\ - { \n\ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithLinearGradientBrushVertexShader - = qopenglslPositionWithLinearGradientBrushVertexShader; - -static const char* const qopenglslLinearGradientBrushSrcFragmentShader = "\n\ - uniform sampler2D brushTexture; \n\ - varying mediump float index; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - mediump vec2 val = vec2(index, 0.5); \n\ - return texture2D(brushTexture, val); \n\ - }\n"; - - -// Conical Gradient Brush -static const char* const qopenglslPositionWithConicalGradientBrushVertexShader = "\n\ - attribute highp vec2 vertexCoordsArray; \n\ - attribute highp vec3 pmvMatrix1; \n\ - attribute highp vec3 pmvMatrix2; \n\ - attribute highp vec3 pmvMatrix3; \n\ - uniform mediump vec2 halfViewportSize; \n\ - uniform highp mat3 brushTransform; \n\ - varying highp vec2 A; \n\ - void setPosition(void) \n\ - { \n\ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - A = hTexCoords.xy * invertedHTexCoordsZ; \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithConicalGradientBrushVertexShader - = qopenglslPositionWithConicalGradientBrushVertexShader; - -static const char* const qopenglslConicalGradientBrushSrcFragmentShader = "\n\ - #define INVERSE_2PI 0.1591549430918953358 \n\ - uniform sampler2D brushTexture; \n\ - uniform mediump float angle; \n\ - varying highp vec2 A; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - highp float t; \n\ - if (abs(A.y) == abs(A.x)) \n\ - t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\ - else \n\ - t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\ - return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \n\ - }\n"; - - -// Radial Gradient Brush -static const char* const qopenglslPositionWithRadialGradientBrushVertexShader = "\n\ - attribute highp vec2 vertexCoordsArray;\n\ - attribute highp vec3 pmvMatrix1; \n\ - attribute highp vec3 pmvMatrix2; \n\ - attribute highp vec3 pmvMatrix3; \n\ - uniform mediump vec2 halfViewportSize; \n\ - uniform highp mat3 brushTransform; \n\ - uniform highp vec2 fmp; \n\ - uniform mediump vec3 bradius; \n\ - varying highp float b; \n\ - varying highp vec2 A; \n\ - void setPosition(void) \n\ - {\n\ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - A = hTexCoords.xy * invertedHTexCoordsZ; \n\ - b = bradius.x + 2.0 * dot(A, fmp); \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithRadialGradientBrushVertexShader - = qopenglslPositionWithRadialGradientBrushVertexShader; - -static const char* const qopenglslRadialGradientBrushSrcFragmentShader = "\n\ - uniform sampler2D brushTexture; \n\ - uniform highp float fmp2_m_radius2; \n\ - uniform highp float inverse_2_fmp2_m_radius2; \n\ - uniform highp float sqrfr; \n\ - varying highp float b; \n\ - varying highp vec2 A; \n\ - uniform mediump vec3 bradius; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - highp float c = sqrfr-dot(A, A); \n\ - highp float det = b*b - 4.0*fmp2_m_radius2*c; \n\ - lowp vec4 result = vec4(0.0); \n\ - if (det >= 0.0) { \n\ - highp float detSqrt = sqrt(det); \n\ - highp float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\ - if (bradius.y + w * bradius.z >= 0.0) \n\ - result = texture2D(brushTexture, vec2(w, 0.5)); \n\ - } \n\ - return result; \n\ - }\n"; - - -// Texture Brush -static const char* const qopenglslPositionWithTextureBrushVertexShader = "\n\ - attribute highp vec2 vertexCoordsArray; \n\ - attribute highp vec3 pmvMatrix1; \n\ - attribute highp vec3 pmvMatrix2; \n\ - attribute highp vec3 pmvMatrix3; \n\ - uniform mediump vec2 halfViewportSize; \n\ - uniform highp vec2 invertedTextureSize; \n\ - uniform highp mat3 brushTransform; \n\ - varying highp vec2 brushTextureCoords; \n\ - void setPosition(void) \n\ - { \n\ - highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ - mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithTextureBrushVertexShader - = qopenglslPositionWithTextureBrushVertexShader; - -static const char* const qopenglslTextureBrushSrcFragmentShader = "\n\ - varying highp vec2 brushTextureCoords; \n\ - uniform sampler2D brushTexture; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - return texture2D(brushTexture, brushTextureCoords); \n\ - }\n"; - -static const char* const qopenglslTextureBrushSrcWithPatternFragmentShader = "\n\ - varying highp vec2 brushTextureCoords; \n\ - uniform lowp vec4 patternColor; \n\ - uniform sampler2D brushTexture; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \n\ - }\n"; - -// Solid Fill Brush -static const char* const qopenglslSolidBrushSrcFragmentShader = "\n\ - uniform lowp vec4 fragmentColor; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - return fragmentColor; \n\ - }\n"; - -static const char* const qopenglslImageSrcFragmentShader = "\n\ - varying highp vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - lowp vec4 srcPixel() \n\ - { \n" - "return texture2D(imageTexture, textureCoords); \n" - "}\n"; - -static const char* const qopenglslCustomSrcFragmentShader = "\n\ - varying highp vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - return customShader(imageTexture, textureCoords); \n\ - }\n"; - -static const char* const qopenglslImageSrcWithPatternFragmentShader = "\n\ - varying highp vec2 textureCoords; \n\ - uniform lowp vec4 patternColor; \n\ - uniform sampler2D imageTexture; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \n\ - }\n"; - -static const char* const qopenglslNonPremultipliedImageSrcFragmentShader = "\n\ - varying highp vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - lowp vec4 sample = texture2D(imageTexture, textureCoords); \n\ - sample.rgb = sample.rgb * sample.a; \n\ - return sample; \n\ - }\n"; - -static const char* const qopenglslGrayscaleImageSrcFragmentShader = "\n\ - varying highp vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - return texture2D(imageTexture, textureCoords).rrra; \n\ - }\n"; - -static const char* const qopenglslAlphaImageSrcFragmentShader = "\n\ - varying highp vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - lowp vec4 srcPixel() \n\ - { \n\ - return vec4(0, 0, 0, texture2D(imageTexture, textureCoords).r); \n\ - }\n"; - -static const char* const qopenglslShockingPinkSrcFragmentShader = "\n\ - lowp vec4 srcPixel() \n\ - { \n\ - return vec4(0.98, 0.06, 0.75, 1.0); \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader_ImageArrays = "\n\ - varying lowp float opacity; \n\ - lowp vec4 srcPixel(); \n\ - void main() \n\ - { \n\ - gl_FragColor = srcPixel() * opacity; \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader_MO = "\n\ - uniform lowp float globalOpacity; \n\ - lowp vec4 srcPixel(); \n\ - lowp vec4 applyMask(lowp vec4); \n\ - void main() \n\ - { \n\ - gl_FragColor = applyMask(srcPixel()*globalOpacity); \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader_M = "\n\ - lowp vec4 srcPixel(); \n\ - lowp vec4 applyMask(lowp vec4); \n\ - void main() \n\ - { \n\ - gl_FragColor = applyMask(srcPixel()); \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader_O = "\n\ - uniform lowp float globalOpacity; \n\ - lowp vec4 srcPixel(); \n\ - void main() \n\ - { \n\ - gl_FragColor = srcPixel()*globalOpacity; \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader = "\n\ - lowp vec4 srcPixel(); \n\ - void main() \n\ - { \n\ - gl_FragColor = srcPixel(); \n\ - }\n"; - -static const char* const qopenglslMaskFragmentShader = "\n\ - varying highp vec2 textureCoords;\n\ - uniform sampler2D maskTexture;\n\ - lowp vec4 applyMask(lowp vec4 src) \n\ - {\n\ - lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ - return src * mask.a; \n\ - }\n"; - -// For source over with subpixel antialiasing, the final color is calculated per component as follows -// (.a is alpha component, .c is red, green or blue component): -// alpha = src.a * mask.c * opacity -// dest.c = dest.c * (1 - alpha) + src.c * alpha -// -// In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color -// In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one -// -// If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color - -// For source composition with subpixel antialiasing, the final color is calculated per component as follows: -// alpha = src.a * mask.c * opacity -// dest.c = dest.c * (1 - mask.c) + src.c * alpha -// - -static const char* const qopenglslRgbMaskFragmentShaderPass1 = "\n\ - varying highp vec2 textureCoords;\n\ - uniform sampler2D maskTexture;\n\ - lowp vec4 applyMask(lowp vec4 src) \n\ - { \n\ - lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ - return src.a * mask; \n\ - }\n"; - -static const char* const qopenglslRgbMaskFragmentShaderPass2 = "\n\ - varying highp vec2 textureCoords;\n\ - uniform sampler2D maskTexture;\n\ - lowp vec4 applyMask(lowp vec4 src) \n\ - { \n\ - lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\ - return src * mask; \n\ - }\n"; - -static const char* const qopenglslMultiplyCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_multiply) out;\n\ - #endif\n"; - -static const char* const qopenglslScreenCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_screen) out;\n\ - #endif\n"; - -static const char* const qopenglslOverlayCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_overlay) out;\n\ - #endif\n"; - -static const char* const qopenglslDarkenCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_darken) out;\n\ - #endif\n"; - -static const char* const qopenglslLightenCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_lighten) out;\n\ - #endif\n"; - -static const char* const qopenglslColorDodgeCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_colordodge) out;\n\ - #endif\n"; - -static const char* const qopenglslColorBurnCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_colorburn) out;\n\ - #endif\n"; - -static const char* const qopenglslHardLightCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_hardlight) out;\n\ - #endif\n"; - -static const char* const qopenglslSoftLightCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_softlight) out;\n\ - #endif\n"; - -static const char* const qopenglslDifferenceCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_difference) out;\n\ - #endif\n"; - -static const char* const qopenglslExclusionCompositionModeFragmentShader = "\n\ - #ifdef GL_KHR_blend_equation_advanced\n\ - layout(blend_support_exclusion) out;\n\ - #endif\n"; - -/* - Left to implement: - RgbMaskFragmentShader, - RgbMaskWithGammaFragmentShader, -*/ - -/* - OpenGL 3.2+ Core Profile shaders - The following shader snippets are copies of the snippets above - but use the modern GLSL 1.5 keywords. New shaders should make - a snippet for both profiles and add them appropriately in the - shader manager. -*/ -static const char* const qopenglslMainVertexShader_core = - "#version 150 core\n\ - void setPosition(); \n\ - void main(void) \n\ - { \n\ - setPosition(); \n\ - }\n"; - -static const char* const qopenglslMainWithTexCoordsVertexShader_core = - "#version 150 core\n\ - in vec2 textureCoordArray; \n\ - out vec2 textureCoords; \n\ - void setPosition(); \n\ - void main(void) \n\ - { \n\ - setPosition(); \n\ - textureCoords = textureCoordArray; \n\ - }\n"; - -static const char* const qopenglslMainWithTexCoordsAndOpacityVertexShader_core = - "#version 150 core\n\ - in vec2 textureCoordArray; \n\ - in float opacityArray; \n\ - out vec2 textureCoords; \n\ - out float opacity; \n\ - void setPosition(); \n\ - void main(void) \n\ - { \n\ - setPosition(); \n\ - textureCoords = textureCoordArray; \n\ - opacity = opacityArray; \n\ - }\n"; - -// NOTE: We let GL do the perspective correction so texture lookups in the fragment -// shader are also perspective corrected. -static const char* const qopenglslPositionOnlyVertexShader_core = "\n\ - in vec2 vertexCoordsArray; \n\ - in vec3 pmvMatrix1; \n\ - in vec3 pmvMatrix2; \n\ - in vec3 pmvMatrix3; \n\ - void setPosition(void) \n\ - { \n\ - mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\ - }\n"; - -static const char* const qopenglslComplexGeometryPositionOnlyVertexShader_core = "\n\ - in vec2 vertexCoordsArray; \n\ - uniform mat3 matrix; \n\ - void setPosition(void) \n\ - { \n\ - gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\ - } \n"; - -static const char* const qopenglslUntransformedPositionVertexShader_core = "\n\ - in vec4 vertexCoordsArray; \n\ - void setPosition(void) \n\ - { \n\ - gl_Position = vertexCoordsArray; \n\ - }\n"; - -// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125 -static const char* const qopenglslPositionWithPatternBrushVertexShader_core = "\n\ - in vec2 vertexCoordsArray; \n\ - in vec3 pmvMatrix1; \n\ - in vec3 pmvMatrix2; \n\ - in vec3 pmvMatrix3; \n\ - out vec2 patternTexCoords; \n\ - uniform vec2 halfViewportSize; \n\ - uniform vec2 invertedTextureSize; \n\ - uniform mat3 brushTransform; \n\ - void setPosition(void) \n\ - { \n\ - mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\ - float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithPatternBrushVertexShader_core - = qopenglslPositionWithPatternBrushVertexShader_core; - -static const char* const qopenglslPatternBrushSrcFragmentShader_core = "\n\ - in vec2 patternTexCoords;\n\ - uniform sampler2D brushTexture; \n\ - uniform vec4 patternColor; \n\ - vec4 srcPixel() \n\ - { \n\ - return patternColor * (1.0 - texture(brushTexture, patternTexCoords).r); \n\ - }\n"; - - -// Linear Gradient Brush -static const char* const qopenglslPositionWithLinearGradientBrushVertexShader_core = "\n\ - in vec2 vertexCoordsArray; \n\ - in vec3 pmvMatrix1; \n\ - in vec3 pmvMatrix2; \n\ - in vec3 pmvMatrix3; \n\ - out float index; \n\ - uniform vec2 halfViewportSize; \n\ - uniform vec3 linearData; \n\ - uniform mat3 brushTransform; \n\ - void setPosition() \n\ - { \n\ - mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ - float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithLinearGradientBrushVertexShader_core - = qopenglslPositionWithLinearGradientBrushVertexShader_core; - -static const char* const qopenglslLinearGradientBrushSrcFragmentShader_core = "\n\ - uniform sampler2D brushTexture; \n\ - in float index; \n\ - vec4 srcPixel() \n\ - { \n\ - vec2 val = vec2(index, 0.5); \n\ - return texture(brushTexture, val); \n\ - }\n"; - - -// Conical Gradient Brush -static const char* const qopenglslPositionWithConicalGradientBrushVertexShader_core = "\n\ - in vec2 vertexCoordsArray; \n\ - in vec3 pmvMatrix1; \n\ - in vec3 pmvMatrix2; \n\ - in vec3 pmvMatrix3; \n\ - out vec2 A; \n\ - uniform vec2 halfViewportSize; \n\ - uniform mat3 brushTransform; \n\ - void setPosition(void) \n\ - { \n\ - mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ - float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - A = hTexCoords.xy * invertedHTexCoordsZ; \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithConicalGradientBrushVertexShader_core - = qopenglslPositionWithConicalGradientBrushVertexShader_core; - -static const char* const qopenglslConicalGradientBrushSrcFragmentShader_core = "\n\ - #define INVERSE_2PI 0.1591549430918953358 \n\ - in vec2 A; \n\ - uniform sampler2D brushTexture; \n\ - uniform float angle; \n\ - vec4 srcPixel() \n\ - { \n\ - float t; \n\ - if (abs(A.y) == abs(A.x)) \n\ - t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\ - else \n\ - t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\ - return texture(brushTexture, vec2(t - floor(t), 0.5)); \n\ - }\n"; - - -// Radial Gradient Brush -static const char* const qopenglslPositionWithRadialGradientBrushVertexShader_core = "\n\ - in vec2 vertexCoordsArray;\n\ - in vec3 pmvMatrix1; \n\ - in vec3 pmvMatrix2; \n\ - in vec3 pmvMatrix3; \n\ - out float b; \n\ - out vec2 A; \n\ - uniform vec2 halfViewportSize; \n\ - uniform mat3 brushTransform; \n\ - uniform vec2 fmp; \n\ - uniform vec3 bradius; \n\ - void setPosition(void) \n\ - {\n\ - mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ - float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - A = hTexCoords.xy * invertedHTexCoordsZ; \n\ - b = bradius.x + 2.0 * dot(A, fmp); \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithRadialGradientBrushVertexShader_core - = qopenglslPositionWithRadialGradientBrushVertexShader_core; - -static const char* const qopenglslRadialGradientBrushSrcFragmentShader_core = "\n\ - in float b; \n\ - in vec2 A; \n\ - uniform sampler2D brushTexture; \n\ - uniform float fmp2_m_radius2; \n\ - uniform float inverse_2_fmp2_m_radius2; \n\ - uniform float sqrfr; \n\ - uniform vec3 bradius; \n\ - \n\ - vec4 srcPixel() \n\ - { \n\ - float c = sqrfr-dot(A, A); \n\ - float det = b*b - 4.0*fmp2_m_radius2*c; \n\ - vec4 result = vec4(0.0); \n\ - if (det >= 0.0) { \n\ - float detSqrt = sqrt(det); \n\ - float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\ - if (bradius.y + w * bradius.z >= 0.0) \n\ - result = texture(brushTexture, vec2(w, 0.5)); \n\ - } \n\ - return result; \n\ - }\n"; - - -// Texture Brush -static const char* const qopenglslPositionWithTextureBrushVertexShader_core = "\n\ - in vec2 vertexCoordsArray; \n\ - in vec3 pmvMatrix1; \n\ - in vec3 pmvMatrix2; \n\ - in vec3 pmvMatrix3; \n\ - out vec2 brushTextureCoords; \n\ - uniform vec2 halfViewportSize; \n\ - uniform vec2 invertedTextureSize; \n\ - uniform mat3 brushTransform; \n\ - \n\ - void setPosition(void) \n\ - { \n\ - mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\ - vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\ - gl_Position.xy = transformedPos.xy / transformedPos.z; \n\ - vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\ - vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\ - float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\ - gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\ - brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\ - }\n"; - -static const char* const qopenglslAffinePositionWithTextureBrushVertexShader_core - = qopenglslPositionWithTextureBrushVertexShader_core; - -static const char* const qopenglslTextureBrushSrcFragmentShader_core = "\n\ - in vec2 brushTextureCoords; \n\ - uniform sampler2D brushTexture; \n\ - vec4 srcPixel() \n\ - { \n\ - return texture(brushTexture, brushTextureCoords); \n\ - }\n"; - -static const char* const qopenglslTextureBrushSrcWithPatternFragmentShader_core = "\n\ - in vec2 brushTextureCoords; \n\ - uniform vec4 patternColor; \n\ - uniform sampler2D brushTexture; \n\ - vec4 srcPixel() \n\ - { \n\ - return patternColor * (1.0 - texture(brushTexture, brushTextureCoords).r); \n\ - }\n"; - -// Solid Fill Brush -static const char* const qopenglslSolidBrushSrcFragmentShader_core = "\n\ - uniform vec4 fragmentColor; \n\ - vec4 srcPixel() \n\ - { \n\ - return fragmentColor; \n\ - }\n"; - -static const char* const qopenglslImageSrcFragmentShader_core = "\n\ - in vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - vec4 srcPixel() \n\ - { \n\ - return texture(imageTexture, textureCoords); \n\ - }\n"; - -static const char* const qopenglslCustomSrcFragmentShader_core = "\n\ - in vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - vec4 srcPixel() \n\ - { \n\ - return customShader(imageTexture, textureCoords); \n\ - }\n"; - -static const char* const qopenglslImageSrcWithPatternFragmentShader_core = "\n\ - in vec2 textureCoords; \n\ - uniform vec4 patternColor; \n\ - uniform sampler2D imageTexture; \n\ - vec4 srcPixel() \n\ - { \n\ - return patternColor * (1.0 - texture(imageTexture, textureCoords).r); \n\ - }\n"; - -static const char* const qopenglslNonPremultipliedImageSrcFragmentShader_core = "\n\ - in vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - vec4 srcPixel() \n\ - { \n\ - vec4 sample = texture(imageTexture, textureCoords); \n\ - sample.rgb = sample.rgb * sample.a; \n\ - return sample; \n\ - }\n"; - -static const char* const qopenglslGrayscaleImageSrcFragmentShader_core = "\n\ - in vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - vec4 srcPixel() \n\ - { \n\ - return texture(imageTexture, textureCoords).rrra; \n\ - }\n"; - -static const char* const qopenglslAlphaImageSrcFragmentShader_core = "\n\ - in vec2 textureCoords; \n\ - uniform sampler2D imageTexture; \n\ - vec4 srcPixel() \n\ - { \n\ - return vec4(0, 0, 0, texture(imageTexture, textureCoords).r); \n\ - }\n"; - -static const char* const qopenglslShockingPinkSrcFragmentShader_core = "\n\ - vec4 srcPixel() \n\ - { \n\ - return vec4(0.98, 0.06, 0.75, 1.0); \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader_ImageArrays_core = - "#version 150 core\n\ - in float opacity; \n\ - out vec4 fragColor; \n\ - vec4 srcPixel(); \n\ - void main() \n\ - { \n\ - fragColor = srcPixel() * opacity; \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader_MO_core = - "#version 150 core\n\ - out vec4 fragColor; \n\ - uniform float globalOpacity; \n\ - vec4 srcPixel(); \n\ - vec4 applyMask(vec4); \n\ - void main() \n\ - { \n\ - fragColor = applyMask(srcPixel()*globalOpacity); \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader_M_core = - "#version 150 core\n\ - out vec4 fragColor; \n\ - vec4 srcPixel(); \n\ - vec4 applyMask(vec4); \n\ - void main() \n\ - { \n\ - fragColor = applyMask(srcPixel()); \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader_O_core = - "#version 150 core\n\ - out vec4 fragColor; \n\ - uniform float globalOpacity; \n\ - vec4 srcPixel(); \n\ - void main() \n\ - { \n\ - fragColor = srcPixel()*globalOpacity; \n\ - }\n"; - -static const char* const qopenglslMainFragmentShader_core = - "#version 150 core\n\ - out vec4 fragColor; \n\ - vec4 srcPixel(); \n\ - void main() \n\ - { \n\ - fragColor = srcPixel(); \n\ - }\n"; - -static const char* const qopenglslMaskFragmentShader_core = "\n\ - in vec2 textureCoords;\n\ - uniform sampler2D maskTexture;\n\ - vec4 applyMask(vec4 src) \n\ - {\n\ - vec4 mask = texture(maskTexture, textureCoords); \n\ - return src * mask.r; \n\ - }\n"; - -// For source over with subpixel antialiasing, the final color is calculated per component as follows -// (.a is alpha component, .c is red, green or blue component): -// alpha = src.a * mask.c * opacity -// dest.c = dest.c * (1 - alpha) + src.c * alpha -// -// In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color -// In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one -// -// If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color - -// For source composition with subpixel antialiasing, the final color is calculated per component as follows: -// alpha = src.a * mask.c * opacity -// dest.c = dest.c * (1 - mask.c) + src.c * alpha -// - -static const char* const qopenglslRgbMaskFragmentShaderPass1_core = "\n\ - in vec2 textureCoords;\n\ - uniform sampler2D maskTexture;\n\ - vec4 applyMask(vec4 src) \n\ - { \n\ - vec4 mask = texture(maskTexture, textureCoords); \n\ - return src.a * mask; \n\ - }\n"; - -static const char* const qopenglslRgbMaskFragmentShaderPass2_core = "\n\ - in vec2 textureCoords;\n\ - uniform sampler2D maskTexture;\n\ - vec4 applyMask(vec4 src) \n\ - { \n\ - vec4 mask = texture(maskTexture, textureCoords); \n\ - return src * mask; \n\ - }\n"; - -/* - Left to implement: - RgbMaskFragmentShader_core, - RgbMaskWithGammaFragmentShader_core, -*/ - -QT_END_NAMESPACE - -#endif // GLGC_SHADER_SOURCE_H diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp deleted file mode 100644 index 3aa4c0d2e6..0000000000 --- a/src/gui/opengl/qopenglgradientcache.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopenglgradientcache_p.h" -#include <private/qdrawhelper_p.h> -#include <private/qopenglcontext_p.h> -#include <private/qrgba64_p.h> -#include <QtCore/qmutex.h> -#include <QtCore/qrandom.h> -#include "qopenglfunctions.h" -#include "qopenglextensions_p.h" - -#ifndef GL_RGBA16 -#define GL_RGBA16 0x805B -#endif - -QT_BEGIN_NAMESPACE - -class QOpenGL2GradientCacheWrapper -{ -public: - QOpenGL2GradientCache *cacheForContext(QOpenGLContext *context) { - QMutexLocker lock(&m_mutex); - return m_resource.value<QOpenGL2GradientCache>(context); - } - -private: - QOpenGLMultiGroupSharedResource m_resource; - QMutex m_mutex; -}; - -Q_GLOBAL_STATIC(QOpenGL2GradientCacheWrapper, qt_gradient_caches) - -QOpenGL2GradientCache::QOpenGL2GradientCache(QOpenGLContext *ctx) - : QOpenGLSharedResource(ctx->shareGroup()) -{ -} - -QOpenGL2GradientCache::~QOpenGL2GradientCache() -{ - cache.clear(); -} - -QOpenGL2GradientCache *QOpenGL2GradientCache::cacheForContext(QOpenGLContext *context) -{ - return qt_gradient_caches()->cacheForContext(context); -} - -void QOpenGL2GradientCache::invalidateResource() -{ - QMutexLocker lock(&m_mutex); - cache.clear(); -} - -void QOpenGL2GradientCache::freeResource(QOpenGLContext *) -{ - cleanCache(); -} - -void QOpenGL2GradientCache::cleanCache() -{ - QMutexLocker lock(&m_mutex); - QOpenGLGradientColorTableHash::const_iterator it = cache.constBegin(); - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - for (; it != cache.constEnd(); ++it) { - const CacheInfo &cache_info = it.value(); - funcs->glDeleteTextures(1, &cache_info.texId); - } - cache.clear(); -} - -GLuint QOpenGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) -{ - quint64 hash_val = 0; - - const QGradientStops stops = gradient.stops(); - for (int i = 0; i < stops.size() && i <= 2; i++) - hash_val += stops[i].second.rgba(); - - const QMutexLocker lock(&m_mutex); - QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val); - - if (it == cache.constEnd()) - return addCacheElement(hash_val, gradient, opacity); - else { - do { - const CacheInfo &cache_info = it.value(); - if (cache_info.stops == stops && cache_info.opacity == opacity - && cache_info.interpolationMode == gradient.interpolationMode()) - { - return cache_info.texId; - } - ++it; - } while (it != cache.constEnd() && it.key() == hash_val); - // an exact match for these stops and opacity was not found, create new cache - return addCacheElement(hash_val, gradient, opacity); - } -} - - -GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity) -{ - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - if (cache.size() == maxCacheSize()) { - int elem_to_remove = QRandomGenerator::global()->bounded(maxCacheSize()); - quint64 key = cache.keys()[elem_to_remove]; - - // need to call glDeleteTextures on each removed cache entry: - QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(key); - do { - funcs->glDeleteTextures(1, &it.value().texId); - } while (++it != cache.constEnd() && it.key() == key); - cache.remove(key); // may remove more than 1, but OK - } - - CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode()); - funcs->glGenTextures(1, &cache_entry.texId); - funcs->glBindTexture(GL_TEXTURE_2D, cache_entry.texId); - if (static_cast<QOpenGLExtensions *>(funcs)->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats)) { - QRgba64 buffer[1024]; - generateGradientColorTable(gradient, buffer, paletteSize(), opacity); - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, paletteSize(), 1, - 0, GL_RGBA, GL_UNSIGNED_SHORT, buffer); - } else { - uint buffer[1024]; - generateGradientColorTable(gradient, buffer, paletteSize(), opacity); - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - } - return cache.insert(hash_val, cache_entry).value().texId; -} - - -//TODO: Let GL generate the texture using an FBO -void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, qreal opacity) const -{ - int pos = 0; - const QGradientStops s = gradient.stops(); - - bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); - - uint alpha = qRound(opacity * 256); - QRgba64 current_color = combineAlpha256(s[0].second.rgba64(), alpha); - qreal incr = 1.0 / qreal(size); - qreal fpos = 1.5 * incr; - colorTable[pos++] = qPremultiply(current_color); - - while (fpos <= s.first().first) { - colorTable[pos] = colorTable[pos - 1]; - pos++; - fpos += incr; - } - - if (colorInterpolation) - current_color = qPremultiply(current_color); - - const int sLast = s.size() - 1; - for (int i = 0; i < sLast; ++i) { - qreal delta = 1/(s[i+1].first - s[i].first); - QRgba64 next_color = combineAlpha256(s[i + 1].second.rgba64(), alpha); - if (colorInterpolation) - next_color = qPremultiply(next_color); - - while (fpos < s[i+1].first && pos < size) { - int dist = int(256 * ((fpos - s[i].first) * delta)); - int idist = 256 - dist; - if (colorInterpolation) - colorTable[pos] = interpolate256(current_color, idist, next_color, dist); - else - colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist)); - ++pos; - fpos += incr; - } - current_color = next_color; - } - - Q_ASSERT(s.size() > 0); - - QRgba64 last_color = qPremultiply(combineAlpha256(s[sLast].second.rgba64(), alpha)); - for (;pos < size; ++pos) - colorTable[pos] = last_color; - - // Make sure the last color stop is represented at the end of the table - colorTable[size-1] = last_color; -} - -void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const -{ - int pos = 0; - const QGradientStops s = gradient.stops(); - - bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); - - uint alpha = qRound(opacity * 256); - // Qt LIES! It returns ARGB (on little-endian AND on big-endian) - uint current_color = ARGB_COMBINE_ALPHA(s[0].second.rgba(), alpha); - qreal incr = 1.0 / qreal(size); - qreal fpos = 1.5 * incr; - colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color)); - - while (fpos <= s.first().first) { - colorTable[pos] = colorTable[pos - 1]; - pos++; - fpos += incr; - } - - if (colorInterpolation) - current_color = qPremultiply(current_color); - - const int sLast = s.size() - 1; - for (int i = 0; i < sLast; ++i) { - qreal delta = 1/(s[i+1].first - s[i].first); - uint next_color = ARGB_COMBINE_ALPHA(s[i + 1].second.rgba(), alpha); - if (colorInterpolation) - next_color = qPremultiply(next_color); - - while (fpos < s[i+1].first && pos < size) { - int dist = int(256 * ((fpos - s[i].first) * delta)); - int idist = 256 - dist; - if (colorInterpolation) - colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); - else - colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); - ++pos; - fpos += incr; - } - current_color = next_color; - } - - Q_ASSERT(s.size() > 0); - - uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha))); - for (;pos < size; ++pos) - colorTable[pos] = last_color; - - // Make sure the last color stop is represented at the end of the table - colorTable[size-1] = last_color; -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopenglgradientcache_p.h b/src/gui/opengl/qopenglgradientcache_p.h deleted file mode 100644 index 1d34223bdd..0000000000 --- a/src/gui/opengl/qopenglgradientcache_p.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLGRADIENTCACHE_P_H -#define QOPENGLGRADIENTCACHE_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/private/qtguiglobal_p.h> -#include <QMultiHash> -#include <QObject> -#include <private/qopenglcontext_p.h> -#include <QtCore/qmutex.h> -#include <QGradient> -#include <qrgba64.h> - -QT_BEGIN_NAMESPACE - -class QOpenGL2GradientCache : public QOpenGLSharedResource -{ - struct CacheInfo - { - inline CacheInfo(QGradientStops s, qreal op, QGradient::InterpolationMode mode) : - stops(std::move(s)), opacity(op), interpolationMode(mode) {} - - GLuint texId; - QGradientStops stops; - qreal opacity; - QGradient::InterpolationMode interpolationMode; - }; - - typedef QMultiHash<quint64, CacheInfo> QOpenGLGradientColorTableHash; - -public: - static QOpenGL2GradientCache *cacheForContext(QOpenGLContext *context); - - QOpenGL2GradientCache(QOpenGLContext *); - ~QOpenGL2GradientCache(); - - GLuint getBuffer(const QGradient &gradient, qreal opacity); - inline int paletteSize() const { return 1024; } - - void invalidateResource() override; - void freeResource(QOpenGLContext *ctx) override; - -private: - inline int maxCacheSize() const { return 60; } - inline void generateGradientColorTable(const QGradient& gradient, - QRgba64 *colorTable, - int size, qreal opacity) const; - inline void generateGradientColorTable(const QGradient& gradient, - uint *colorTable, - int size, qreal opacity) const; - GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity); - void cleanCache(); - - QOpenGLGradientColorTableHash cache; - QMutex m_mutex; -}; - -QT_END_NAMESPACE - -#endif // QOPENGLGRADIENTCACHE_P_H diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp deleted file mode 100644 index 3920a10467..0000000000 --- a/src/gui/opengl/qopenglpaintdevice.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qopenglpaintdevice.h> -#include <qpaintengine.h> -#include <qthreadstorage.h> - -#include <private/qopenglpaintdevice_p.h> -#include <private/qobject_p.h> -#include <private/qopenglcontext_p.h> -#include <private/qopenglframebufferobject_p.h> -#include <private/qopenglpaintengine_p.h> - -// for qt_defaultDpiX/Y -#include <private/qfont_p.h> - -#include <qopenglfunctions.h> - -QT_BEGIN_NAMESPACE - -/*! - \class QOpenGLPaintDevice - \brief The QOpenGLPaintDevice class enables painting to an OpenGL context using QPainter. - \since 5.0 - \inmodule QtGui - - \ingroup painting-3D - - The QOpenGLPaintDevice uses the \b current QOpenGL context to render - QPainter draw commands. The context is captured upon construction. It - requires support for OpenGL (ES) 2.0 or higher. - - \section1 Performance - - The QOpenGLPaintDevice is almost always hardware accelerated and - has the potential of being much faster than software - rasterization. However, it is more sensitive to state changes, and - therefore requires the drawing commands to be carefully ordered to - achieve optimal performance. - - \section1 Antialiasing and Quality - - Antialiasing in the OpenGL paint engine is done using - multisampling. Most hardware require significantly more memory to - do multisampling and the resulting quality is not on par with the - quality of the software paint engine. The OpenGL paint engine's - strength lies in its performance, not its visual rendering - quality. - - \section1 State Changes - - When painting to a QOpenGLPaintDevice using QPainter, the state of - the current OpenGL context will be altered by the paint engine to - reflect its needs. Applications should not rely upon the OpenGL - state being reset to its original conditions, particularly the - current shader program, OpenGL viewport, texture units, and - drawing modes. - - \section1 Mixing QPainter and OpenGL - - When intermixing QPainter and OpenGL, it is important to notify - QPainter that the OpenGL state may have been cluttered so it can - restore its internal state. This is achieved by calling \l - QPainter::beginNativePainting() before starting the OpenGL - rendering and calling \l QPainter::endNativePainting() after - finishing. - - \sa {OpenGL Window Example} - -*/ - -/*! - Constructs a QOpenGLPaintDevice. - - The QOpenGLPaintDevice is only valid for the current context. - - \sa QOpenGLContext::currentContext() -*/ -QOpenGLPaintDevice::QOpenGLPaintDevice() - : d_ptr(new QOpenGLPaintDevicePrivate(QSize())) -{ -} - -/*! - Constructs a QOpenGLPaintDevice with the given \a size. - - The QOpenGLPaintDevice is only valid for the current context. - - \sa QOpenGLContext::currentContext() -*/ -QOpenGLPaintDevice::QOpenGLPaintDevice(const QSize &size) - : d_ptr(new QOpenGLPaintDevicePrivate(size)) -{ -} - -/*! - Constructs a QOpenGLPaintDevice with the given \a width and \a height. - - The QOpenGLPaintDevice is only valid for the current context. - - \sa QOpenGLContext::currentContext() -*/ -QOpenGLPaintDevice::QOpenGLPaintDevice(int width, int height) - : QOpenGLPaintDevice(QSize(width, height)) -{ -} - -/*! - \internal - */ -QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd) - : d_ptr(&dd) -{ -} - -/*! - Destroys the QOpenGLPaintDevice. -*/ - -QOpenGLPaintDevice::~QOpenGLPaintDevice() -{ - delete d_ptr->engine; -} - -/*! - \fn int QOpenGLPaintDevice::devType() const - \internal - \reimp -*/ - -QOpenGLPaintDevicePrivate::QOpenGLPaintDevicePrivate(const QSize &sz) - : size(sz) - , ctx(QOpenGLContext::currentContext()) - , dpmx(qt_defaultDpiX() * 100. / 2.54) - , dpmy(qt_defaultDpiY() * 100. / 2.54) - , devicePixelRatio(1.0) - , flipped(false) - , engine(nullptr) -{ -} - -QOpenGLPaintDevicePrivate::~QOpenGLPaintDevicePrivate() -{ -} - -class QOpenGLEngineThreadStorage -{ -public: - QPaintEngine *engine() { - QPaintEngine *&localEngine = storage.localData(); - if (!localEngine) - localEngine = new QOpenGL2PaintEngineEx; - return localEngine; - } - -private: - QThreadStorage<QPaintEngine *> storage; -}; - -Q_GLOBAL_STATIC(QOpenGLEngineThreadStorage, qt_opengl_engine) - -/*! - \reimp -*/ - -QPaintEngine *QOpenGLPaintDevice::paintEngine() const -{ - if (d_ptr->engine) - return d_ptr->engine; - - QPaintEngine *engine = qt_opengl_engine()->engine(); - if (engine->isActive() && engine->paintDevice() != this) { - d_ptr->engine = new QOpenGL2PaintEngineEx; - return d_ptr->engine; - } - - return engine; -} - -/*! - Returns the OpenGL context associated with the paint device. -*/ - -QOpenGLContext *QOpenGLPaintDevice::context() const -{ - return d_ptr->ctx; -} - -/*! - Returns the pixel size of the paint device. - - \sa setSize() -*/ - -QSize QOpenGLPaintDevice::size() const -{ - return d_ptr->size; -} - -/*! - Sets the pixel size of the paint device to \a size. - - \sa size() -*/ - -void QOpenGLPaintDevice::setSize(const QSize &size) -{ - d_ptr->size = size; -} - -/*! - Sets the device pixel ratio for the paint device to \a devicePixelRatio. -*/ -void QOpenGLPaintDevice::setDevicePixelRatio(qreal devicePixelRatio) -{ - d_ptr->devicePixelRatio = devicePixelRatio; -} - -/*! - \reimp -*/ - -int QOpenGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const -{ - switch (metric) { - case PdmWidth: - return d_ptr->size.width(); - case PdmHeight: - return d_ptr->size.height(); - case PdmDepth: - return 32; - case PdmWidthMM: - return qRound(d_ptr->size.width() * 1000 / d_ptr->dpmx); - case PdmHeightMM: - return qRound(d_ptr->size.height() * 1000 / d_ptr->dpmy); - case PdmNumColors: - return 0; - case PdmDpiX: - return qRound(d_ptr->dpmx * 0.0254); - case PdmDpiY: - return qRound(d_ptr->dpmy * 0.0254); - case PdmPhysicalDpiX: - return qRound(d_ptr->dpmx * 0.0254); - case PdmPhysicalDpiY: - return qRound(d_ptr->dpmy * 0.0254); - case PdmDevicePixelRatio: - return d_ptr->devicePixelRatio; - case PdmDevicePixelRatioScaled: - return d_ptr->devicePixelRatio * QPaintDevice::devicePixelRatioFScale(); - - default: - qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric); - return 0; - } -} - -/*! - Returns the number of pixels per meter horizontally. - - \sa setDotsPerMeterX() -*/ - -qreal QOpenGLPaintDevice::dotsPerMeterX() const -{ - return d_ptr->dpmx; -} - -/*! - Returns the number of pixels per meter vertically. - - \sa setDotsPerMeterY() -*/ - -qreal QOpenGLPaintDevice::dotsPerMeterY() const -{ - return d_ptr->dpmy; -} - -/*! - Sets the number of pixels per meter horizontally to \a dpmx. - - \sa dotsPerMeterX() -*/ - -void QOpenGLPaintDevice::setDotsPerMeterX(qreal dpmx) -{ - d_ptr->dpmx = dpmx; -} - -/*! - Sets the number of pixels per meter vertically to \a dpmy. - - \sa dotsPerMeterY() -*/ - -void QOpenGLPaintDevice::setDotsPerMeterY(qreal dpmy) -{ - d_ptr->dpmx = dpmy; -} - -/*! - Sets whether painting should be flipped around the Y-axis or not to \a flipped. - - \sa paintFlipped() -*/ -void QOpenGLPaintDevice::setPaintFlipped(bool flipped) -{ - d_ptr->flipped = flipped; -} - -/*! - Returns \c true if painting is flipped around the Y-axis. - - \sa setPaintFlipped() -*/ - -bool QOpenGLPaintDevice::paintFlipped() const -{ - return d_ptr->flipped; -} - -/*! - This virtual method is provided as a callback to allow re-binding a target - frame buffer object or context when different QOpenGLPaintDevice instances - are issuing draw calls alternately. - - \l{QPainter::beginNativePainting()}{beginNativePainting()} will also trigger - this method. - - The default implementation does nothing. -*/ -void QOpenGLPaintDevice::ensureActiveTarget() -{ -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopenglpaintdevice.h b/src/gui/opengl/qopenglpaintdevice.h deleted file mode 100644 index 54118f2926..0000000000 --- a/src/gui/opengl/qopenglpaintdevice.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLPAINTDEVICE_H -#define QOPENGLPAINTDEVICE_H - -#include <QtGui/qtguiglobal.h> - -#ifndef QT_NO_OPENGL - -#include <QtGui/qpaintdevice.h> -#include <QtGui/qopengl.h> -#include <QtGui/qopenglcontext.h> - -QT_BEGIN_NAMESPACE - -class QOpenGLPaintDevicePrivate; - -class Q_GUI_EXPORT QOpenGLPaintDevice : public QPaintDevice -{ - Q_DECLARE_PRIVATE(QOpenGLPaintDevice) -public: - QOpenGLPaintDevice(); - explicit QOpenGLPaintDevice(const QSize &size); - QOpenGLPaintDevice(int width, int height); - ~QOpenGLPaintDevice(); - - int devType() const override { return QInternal::OpenGL; } - QPaintEngine *paintEngine() const override; - - QOpenGLContext *context() const; - QSize size() const; - void setSize(const QSize &size); - void setDevicePixelRatio(qreal devicePixelRatio); - - qreal dotsPerMeterX() const; - qreal dotsPerMeterY() const; - - void setDotsPerMeterX(qreal); - void setDotsPerMeterY(qreal); - - void setPaintFlipped(bool flipped); - bool paintFlipped() const; - - virtual void ensureActiveTarget(); - -protected: - QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd); - int metric(QPaintDevice::PaintDeviceMetric metric) const override; - - Q_DISABLE_COPY(QOpenGLPaintDevice) - QScopedPointer<QOpenGLPaintDevicePrivate> d_ptr; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_OPENGL - -#endif // QOPENGLPAINTDEVICE_H diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp deleted file mode 100644 index b53c9a3eab..0000000000 --- a/src/gui/opengl/qopenglpaintengine.cpp +++ /dev/null @@ -1,2702 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/* - When the active program changes, we need to update it's uniforms. - We could track state for each program and only update stale uniforms - - Could lead to lots of overhead if there's a lot of programs - We could update all the uniforms when the program changes - - Could end up updating lots of uniforms which don't need updating - - Updating uniforms should be cheap, so the overhead of updating up-to-date - uniforms should be minimal. It's also less complex. - - Things which _may_ cause a different program to be used: - - Change in brush/pen style - - Change in painter opacity - - Change in composition mode - - Whenever we set a mode on the shader manager - it needs to tell us if it had - to switch to a different program. - - The shader manager should only switch when we tell it to. E.g. if we set a new - brush style and then switch to transparent painter, we only want it to compile - and use the correct program when we really need it. -*/ - -// #define QT_OPENGL_CACHE_AS_VBOS - -#include "qopenglgradientcache_p.h" -#include "qopengltexturecache_p.h" -#include "qopenglpaintengine_p.h" -#include "qopenglpaintdevice_p.h" - -#include <string.h> //for memcpy -#include <qmath.h> - -#include <private/qopengl_p.h> -#include <private/qopenglcontext_p.h> -#include <private/qopenglextensions_p.h> -#include <private/qpaintengineex_p.h> -#include <QPaintEngine> -#include <private/qpainter_p.h> -#include <private/qfontengine_p.h> -#include <private/qdatabuffer_p.h> -#include <private/qstatictext_p.h> -#include <private/qtriangulator_p.h> - -#include "qopenglengineshadermanager_p.h" -#include "qopengl2pexvertexarray_p.h" -#include "qopengltextureglyphcache_p.h" - -#include <QDebug> - -#ifndef GL_KHR_blend_equation_advanced -#define GL_KHR_blend_equation_advanced 1 -#define GL_MULTIPLY_KHR 0x9294 -#define GL_SCREEN_KHR 0x9295 -#define GL_OVERLAY_KHR 0x9296 -#define GL_DARKEN_KHR 0x9297 -#define GL_LIGHTEN_KHR 0x9298 -#define GL_COLORDODGE_KHR 0x9299 -#define GL_COLORBURN_KHR 0x929A -#define GL_HARDLIGHT_KHR 0x929B -#define GL_SOFTLIGHT_KHR 0x929C -#define GL_DIFFERENCE_KHR 0x929E -#define GL_EXCLUSION_KHR 0x92A0 -#endif /* GL_KHR_blend_equation_advanced */ - -#ifndef GL_KHR_blend_equation_advanced_coherent -#define GL_KHR_blend_equation_advanced_coherent 1 -#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285 -#endif /* GL_KHR_blend_equation_advanced_coherent */ - -QT_BEGIN_NAMESPACE - - -Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert); - -////////////////////////////////// Private Methods ////////////////////////////////////////// - -QOpenGL2PaintEngineExPrivate::~QOpenGL2PaintEngineExPrivate() -{ - delete shaderManager; - - vertexBuffer.destroy(); - texCoordBuffer.destroy(); - opacityBuffer.destroy(); - indexBuffer.destroy(); - vao.destroy(); - - if (elementIndicesVBOId != 0) { - funcs.glDeleteBuffers(1, &elementIndicesVBOId); - elementIndicesVBOId = 0; - } -} - -inline QColor qt_premultiplyColor(QColor c, GLfloat opacity) -{ - qreal alpha = c.alphaF() * opacity; - c.setAlphaF(alpha); - c.setRedF(c.redF() * alpha); - c.setGreenF(c.greenF() * alpha); - c.setBlueF(c.blueF() * alpha); - return c; -} - - -void QOpenGL2PaintEngineExPrivate::setBrush(const QBrush& brush) -{ - if (qbrush_fast_equals(currentBrush, brush)) - return; - - const Qt::BrushStyle newStyle = qbrush_style(brush); - Q_ASSERT(newStyle != Qt::NoBrush); - - currentBrush = brush; - if (!currentBrushImage.isNull()) - currentBrushImage = QImage(); - brushUniformsDirty = true; // All brushes have at least one uniform - - if (newStyle > Qt::SolidPattern) - brushTextureDirty = true; - - if (currentBrush.style() == Qt::TexturePattern - && qHasPixmapTexture(brush) && brush.texture().isQBitmap()) - { - shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::TextureSrcWithPattern); - } else { - shaderManager->setSrcPixelType(newStyle); - } - shaderManager->optimiseForBrushTransform(currentBrush.transform().type()); -} - - -void QOpenGL2PaintEngineExPrivate::useSimpleShader() -{ - shaderManager->useSimpleProgram(); - - if (matrixDirty) - updateMatrix(); -} - -/* - Single entry-point for activating, binding, and setting properties. - - Allows keeping track of (caching) the latest texture unit and bound - texture in a central place, so that we can skip re-binding unless - needed. - - \note Any code or Qt API that internally activates or binds will - not affect the cache used by this function, which means they will - lead to inconsisent state. QPainter::beginNativePainting() takes - care of resetting the cache, so for user–code this is fine, but - internally in the paint engine care must be taken to not call - functions that may activate or bind under our feet. -*/ -template<typename T> -void QOpenGL2PaintEngineExPrivate::updateTexture(GLenum textureUnit, const T &texture, GLenum wrapMode, GLenum filterMode, TextureUpdateMode updateMode) -{ - static const GLenum target = GL_TEXTURE_2D; - - activateTextureUnit(textureUnit); - - GLuint textureId = bindTexture(texture); - - if (updateMode == UpdateIfNeeded && textureId == lastTextureUsed) - return; - - lastTextureUsed = textureId; - - funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode); - funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode); - - funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filterMode); - funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filterMode); -} - -void QOpenGL2PaintEngineExPrivate::activateTextureUnit(GLenum textureUnit) -{ - if (textureUnit != lastTextureUnitUsed) { - funcs.glActiveTexture(GL_TEXTURE0 + textureUnit); - lastTextureUnitUsed = textureUnit; - - // We simplify things by keeping a single cached value of the last - // texture that was bound, instead of one per texture unit. This - // means that switching texture units could potentially mean we - // need a re-bind and corresponding parameter updates. - lastTextureUsed = GLuint(-1); - } -} - -template<> -GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const GLuint &textureId) -{ - if (textureId != lastTextureUsed) - funcs.glBindTexture(GL_TEXTURE_2D, textureId); - - return textureId; -} - -template<> -GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const QImage &image) -{ - return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, image); -} - -template<> -GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const QPixmap &pixmap) -{ - return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap); -} - -template<> -GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const QGradient &gradient) -{ - // We apply global opacity in the fragment shaders, so we always pass 1.0 - // for opacity to the cache. - GLuint textureId = QOpenGL2GradientCache::cacheForContext(ctx)->getBuffer(gradient, 1.0); - - // QOpenGL2GradientCache::getBuffer() may bind and generate a new texture if it - // hasn't been cached yet, but will otherwise return an unbound texture id. To - // be sure that the texture is bound, we unfortunately have to bind again, - // which results in the initial generation of the texture doing two binds. - return bindTexture(textureId); -} - -struct ImageWithBindOptions -{ - const QImage ℑ - QOpenGLTextureUploader::BindOptions options; -}; - -template<> -GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const ImageWithBindOptions &imageWithOptions) -{ - return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, imageWithOptions.image, imageWithOptions.options); -} - -inline static bool isPowerOfTwo(int x) -{ - // Assumption: x >= 1 - return x == (x & -x); -} - -void QOpenGL2PaintEngineExPrivate::updateBrushTexture() -{ - Q_Q(QOpenGL2PaintEngineEx); -// qDebug("QOpenGL2PaintEngineExPrivate::updateBrushTexture()"); - Qt::BrushStyle style = currentBrush.style(); - - bool smoothPixmapTransform = q->state()->renderHints & QPainter::SmoothPixmapTransform; - GLenum filterMode = smoothPixmapTransform ? GL_LINEAR : GL_NEAREST; - - if ( (style >= Qt::Dense1Pattern) && (style <= Qt::DiagCrossPattern) ) { - // Get the image data for the pattern - QImage textureImage = qt_imageForBrush(style, false); - - updateTexture(QT_BRUSH_TEXTURE_UNIT, textureImage, GL_REPEAT, filterMode, ForceUpdate); - } - else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) { - // Gradiant brush: All the gradiants use the same texture - - const QGradient *gradient = currentBrush.gradient(); - - GLenum wrapMode = GL_CLAMP_TO_EDGE; - if (gradient->spread() == QGradient::RepeatSpread || gradient->type() == QGradient::ConicalGradient) - wrapMode = GL_REPEAT; - else if (gradient->spread() == QGradient::ReflectSpread) - wrapMode = GL_MIRRORED_REPEAT; - - updateTexture(QT_BRUSH_TEXTURE_UNIT, *gradient, wrapMode, filterMode, ForceUpdate); - } - else if (style == Qt::TexturePattern) { - currentBrushImage = currentBrush.textureImage(); - - int max_texture_size = ctx->d_func()->maxTextureSize(); - QSize newSize = currentBrushImage.size(); - newSize = newSize.boundedTo(QSize(max_texture_size, max_texture_size)); - if (!QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat)) { - if (!isPowerOfTwo(newSize.width()) || !isPowerOfTwo(newSize.height())) { - newSize.setHeight(qNextPowerOfTwo(newSize.height() - 1)); - newSize.setWidth(qNextPowerOfTwo(newSize.width() - 1)); - } - } - if (currentBrushImage.size() != newSize) - currentBrushImage = currentBrushImage.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - - GLuint wrapMode = GL_REPEAT; - - updateTexture(QT_BRUSH_TEXTURE_UNIT, currentBrushImage, wrapMode, filterMode, ForceUpdate); - } - brushTextureDirty = false; -} - - -void QOpenGL2PaintEngineExPrivate::updateBrushUniforms() -{ -// qDebug("QOpenGL2PaintEngineExPrivate::updateBrushUniforms()"); - Qt::BrushStyle style = currentBrush.style(); - - if (style == Qt::NoBrush) - return; - - QTransform brushQTransform = currentBrush.transform(); - - if (style == Qt::SolidPattern) { - QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::FragmentColor), col); - } - else { - // All other brushes have a transform and thus need the translation point: - QPointF translationPoint; - - if (style <= Qt::DiagCrossPattern) { - QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity); - - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::PatternColor), col); - - QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize); - } - else if (style == Qt::LinearGradientPattern) { - const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush.gradient()); - - QPointF realStart = g->start(); - QPointF realFinal = g->finalStop(); - translationPoint = realStart; - - QPointF l = realFinal - realStart; - - QVector3D linearData( - l.x(), - l.y(), - 1.0f / (l.x() * l.x() + l.y() * l.y()) - ); - - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::LinearData), linearData); - - QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize); - } - else if (style == Qt::ConicalGradientPattern) { - const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush.gradient()); - translationPoint = g->center(); - - GLfloat angle = -qDegreesToRadians(g->angle()); - - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::Angle), angle); - - QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize); - } - else if (style == Qt::RadialGradientPattern) { - const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush.gradient()); - QPointF realCenter = g->center(); - QPointF realFocal = g->focalPoint(); - qreal realRadius = g->centerRadius() - g->focalRadius(); - translationPoint = realFocal; - - QPointF fmp = realCenter - realFocal; - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::Fmp), fmp); - - GLfloat fmp2_m_radius2 = -fmp.x() * fmp.x() - fmp.y() * fmp.y() + realRadius*realRadius; - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::Fmp2MRadius2), fmp2_m_radius2); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::Inverse2Fmp2MRadius2), - GLfloat(1.0 / (2.0*fmp2_m_radius2))); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::SqrFr), - GLfloat(g->focalRadius() * g->focalRadius())); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::BRadius), - GLfloat(2 * (g->centerRadius() - g->focalRadius()) * g->focalRadius()), - g->focalRadius(), - g->centerRadius() - g->focalRadius()); - - QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize); - } - else if (style == Qt::TexturePattern) { - const QPixmap& texPixmap = currentBrush.texture(); - - if (qHasPixmapTexture(currentBrush) && currentBrush.texture().isQBitmap()) { - QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::PatternColor), col); - } - - QSizeF invertedTextureSize(1.0 / texPixmap.width(), 1.0 / texPixmap.height()); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::InvertedTextureSize), invertedTextureSize); - - QVector2D halfViewportSize(width*0.5, height*0.5); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize); - } - else - qWarning("QOpenGL2PaintEngineEx: Unimplemented fill style"); - - const QPointF &brushOrigin = q->state()->brushOrigin; - QTransform matrix = q->state()->matrix; - matrix.translate(brushOrigin.x(), brushOrigin.y()); - - QTransform translate(1, 0, 0, 1, -translationPoint.x(), -translationPoint.y()); - qreal m22 = -1; - qreal dy = height; - if (device->paintFlipped()) { - m22 = 1; - dy = 0; - } - QTransform gl_to_qt(1, 0, 0, m22, 0, dy); - QTransform inv_matrix = gl_to_qt * (brushQTransform * matrix).inverted() * translate; - - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::BrushTransform), inv_matrix); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::BrushTexture), QT_BRUSH_TEXTURE_UNIT); - } - brushUniformsDirty = false; -} - - -// This assumes the shader manager has already setup the correct shader program -void QOpenGL2PaintEngineExPrivate::updateMatrix() -{ -// qDebug("QOpenGL2PaintEngineExPrivate::updateMatrix()"); - - const QTransform& transform = q->state()->matrix; - - // The projection matrix converts from Qt's coordinate system to GL's coordinate system - // * GL's viewport is 2x2, Qt's is width x height - // * GL has +y -> -y going from bottom -> top, Qt is the other way round - // * GL has [0,0] in the center, Qt has it in the top-left - // - // This results in the Projection matrix below, which is multiplied by the painter's - // transformation matrix, as shown below: - // - // Projection Matrix Painter Transform - // ------------------------------------------------ ------------------------ - // | 2.0 / width | 0.0 | -1.0 | | m11 | m21 | dx | - // | 0.0 | -2.0 / height | 1.0 | * | m12 | m22 | dy | - // | 0.0 | 0.0 | 1.0 | | m13 | m23 | m33 | - // ------------------------------------------------ ------------------------ - // - // NOTE: The resultant matrix is also transposed, as GL expects column-major matracies - - const GLfloat wfactor = 2.0f / width; - GLfloat hfactor = -2.0f / height; - - GLfloat dx = transform.dx(); - GLfloat dy = transform.dy(); - - if (device->paintFlipped()) { - hfactor *= -1; - dy -= height; - } - - // Non-integer translates can have strange effects for some rendering operations such as - // anti-aliased text rendering. In such cases, we snap the translate to the pixel grid. - if (snapToPixelGrid && transform.type() == QTransform::TxTranslate) { - // 0.50 needs to rounded down to 0.0 for consistency with raster engine: - dx = std::ceil(dx - 0.5f); - dy = std::ceil(dy - 0.5f); - } - pmvMatrix[0][0] = (wfactor * transform.m11()) - transform.m13(); - pmvMatrix[1][0] = (wfactor * transform.m21()) - transform.m23(); - pmvMatrix[2][0] = (wfactor * dx) - transform.m33(); - pmvMatrix[0][1] = (hfactor * transform.m12()) + transform.m13(); - pmvMatrix[1][1] = (hfactor * transform.m22()) + transform.m23(); - pmvMatrix[2][1] = (hfactor * dy) + transform.m33(); - pmvMatrix[0][2] = transform.m13(); - pmvMatrix[1][2] = transform.m23(); - pmvMatrix[2][2] = transform.m33(); - - // 1/10000 == 0.0001, so we have good enough res to cover curves - // that span the entire widget... - inverseScale = qMax(1 / qMax( qMax(qAbs(transform.m11()), qAbs(transform.m22())), - qMax(qAbs(transform.m12()), qAbs(transform.m21())) ), - qreal(0.0001)); - - matrixDirty = false; - matrixUniformDirty = true; - - // Set the PMV matrix attribute. As we use an attributes rather than uniforms, we only - // need to do this once for every matrix change and persists across all shader programs. - funcs.glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]); - funcs.glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]); - funcs.glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]); - - dasher.setInvScale(inverseScale); - stroker.setInvScale(inverseScale); -} - - -void QOpenGL2PaintEngineExPrivate::updateCompositionMode() -{ - // NOTE: The entire paint engine works on pre-multiplied data - which is why some of these - // composition modes look odd. -// qDebug() << "QOpenGL2PaintEngineExPrivate::updateCompositionMode() - Setting GL composition mode for " << q->state()->composition_mode; - if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::BlendEquationAdvanced)) { - if (q->state()->composition_mode <= QPainter::CompositionMode_Plus) { - funcs.glDisable(GL_BLEND_ADVANCED_COHERENT_KHR); - funcs.glBlendEquation(GL_FUNC_ADD); - } else { - funcs.glEnable(GL_BLEND_ADVANCED_COHERENT_KHR); - } - shaderManager->setCompositionMode(q->state()->composition_mode); - } else { - if (q->state()->composition_mode > QPainter::CompositionMode_Plus) { - qWarning("Unsupported composition mode"); - compositionModeDirty = false; - return; - } - } - switch(q->state()->composition_mode) { - case QPainter::CompositionMode_SourceOver: - funcs.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - break; - case QPainter::CompositionMode_DestinationOver: - funcs.glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE); - break; - case QPainter::CompositionMode_Clear: - funcs.glBlendFunc(GL_ZERO, GL_ZERO); - break; - case QPainter::CompositionMode_Source: - funcs.glBlendFunc(GL_ONE, GL_ZERO); - break; - case QPainter::CompositionMode_Destination: - funcs.glBlendFunc(GL_ZERO, GL_ONE); - break; - case QPainter::CompositionMode_SourceIn: - funcs.glBlendFunc(GL_DST_ALPHA, GL_ZERO); - break; - case QPainter::CompositionMode_DestinationIn: - funcs.glBlendFunc(GL_ZERO, GL_SRC_ALPHA); - break; - case QPainter::CompositionMode_SourceOut: - funcs.glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO); - break; - case QPainter::CompositionMode_DestinationOut: - funcs.glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); - break; - case QPainter::CompositionMode_SourceAtop: - funcs.glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - break; - case QPainter::CompositionMode_DestinationAtop: - funcs.glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA); - break; - case QPainter::CompositionMode_Xor: - funcs.glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - break; - case QPainter::CompositionMode_Plus: - funcs.glBlendFunc(GL_ONE, GL_ONE); - break; - case QPainter::CompositionMode_Multiply: - funcs.glBlendEquation(GL_MULTIPLY_KHR); - break; - case QPainter::CompositionMode_Screen: - funcs.glBlendEquation(GL_SCREEN_KHR); - break; - case QPainter::CompositionMode_Overlay: - funcs.glBlendEquation(GL_OVERLAY_KHR); - break; - case QPainter::CompositionMode_Darken: - funcs.glBlendEquation(GL_DARKEN_KHR); - break; - case QPainter::CompositionMode_Lighten: - funcs.glBlendEquation(GL_LIGHTEN_KHR); - break; - case QPainter::CompositionMode_ColorDodge: - funcs.glBlendEquation(GL_COLORDODGE_KHR); - break; - case QPainter::CompositionMode_ColorBurn: - funcs.glBlendEquation(GL_COLORBURN_KHR); - break; - case QPainter::CompositionMode_HardLight: - funcs.glBlendEquation(GL_HARDLIGHT_KHR); - break; - case QPainter::CompositionMode_SoftLight: - funcs.glBlendEquation(GL_SOFTLIGHT_KHR); - break; - case QPainter::CompositionMode_Difference: - funcs.glBlendEquation(GL_DIFFERENCE_KHR); - break; - case QPainter::CompositionMode_Exclusion: - funcs.glBlendEquation(GL_EXCLUSION_KHR); - break; - default: - qWarning("Unsupported composition mode"); - break; - } - - compositionModeDirty = false; -} - -static inline void setCoords(GLfloat *coords, const QOpenGLRect &rect) -{ - coords[0] = rect.left; - coords[1] = rect.top; - coords[2] = rect.right; - coords[3] = rect.top; - coords[4] = rect.right; - coords[5] = rect.bottom; - coords[6] = rect.left; - coords[7] = rect.bottom; -} - -void QOpenGL2PaintEngineExPrivate::drawTexture(const QOpenGLRect& dest, const QOpenGLRect& src, const QSize &textureSize, bool opaque, bool pattern) -{ - // Setup for texture drawing - currentBrush = noBrush; - - if (snapToPixelGrid) { - snapToPixelGrid = false; - matrixDirty = true; - } - - if (prepareForDraw(opaque)) - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); - - if (pattern) { - QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::PatternColor), col); - } - - GLfloat dx = 1.0 / textureSize.width(); - GLfloat dy = 1.0 / textureSize.height(); - - QOpenGLRect srcTextureRect(src.left*dx, src.top*dy, src.right*dx, src.bottom*dy); - - setCoords(staticVertexCoordinateArray, dest); - setCoords(staticTextureCoordinateArray, srcTextureRect); - - setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true); - setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, true); - - uploadData(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray, 8); - uploadData(QT_TEXTURE_COORDS_ATTR, staticTextureCoordinateArray, 8); - - funcs.glDrawArrays(GL_TRIANGLE_FAN, 0, 4); -} - -void QOpenGL2PaintEngineEx::beginNativePainting() -{ - Q_D(QOpenGL2PaintEngineEx); - ensureActive(); - d->transferMode(BrushDrawingMode); - - d->nativePaintingActive = true; - - d->funcs.glUseProgram(0); - - // Disable all the vertex attribute arrays: - for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) - d->funcs.glDisableVertexAttribArray(i); - -#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_DYNAMIC) - Q_ASSERT(QOpenGLContext::currentContext()); - const QOpenGLContext *ctx = d->ctx; - const QSurfaceFormat &fmt = d->device->context()->format(); - if (fmt.majorVersion() < 3 || (fmt.majorVersion() == 3 && fmt.minorVersion() < 1) - || (fmt.majorVersion() == 3 && fmt.minorVersion() == 1 && ctx->hasExtension(QByteArrayLiteral("GL_ARB_compatibility"))) - || fmt.profile() == QSurfaceFormat::CompatibilityProfile) - { - // be nice to people who mix OpenGL 1.x code with QPainter commands - // by setting modelview and projection matrices to mirror the GL 1 - // paint engine - const QTransform& mtx = state()->matrix; - - float mv_matrix[4][4] = - { - { float(mtx.m11()), float(mtx.m12()), 0, float(mtx.m13()) }, - { float(mtx.m21()), float(mtx.m22()), 0, float(mtx.m23()) }, - { 0, 0, 1, 0 }, - { float(mtx.dx()), float(mtx.dy()), 0, float(mtx.m33()) } - }; - - const QSize sz = d->device->size(); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999); - - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(&mv_matrix[0][0]); - } -#endif // QT_OPENGL_ES_2 - - d->resetGLState(); - - // We don't know what texture units and textures the native painting - // will activate and bind, so we can't assume anything when we return - // from the native painting. - d->lastTextureUnitUsed = QT_UNKNOWN_TEXTURE_UNIT; - d->lastTextureUsed = GLuint(-1); - - d->dirtyStencilRegion = QRect(0, 0, d->width, d->height); - - d->shaderManager->setDirty(); - - d->needsSync = true; -} - -void QOpenGL2PaintEngineExPrivate::resetGLState() -{ - activateTextureUnit(QT_DEFAULT_TEXTURE_UNIT); - - funcs.glDisable(GL_BLEND); - funcs.glDisable(GL_STENCIL_TEST); - funcs.glDisable(GL_DEPTH_TEST); - funcs.glDisable(GL_SCISSOR_TEST); - funcs.glDepthMask(true); - funcs.glDepthFunc(GL_LESS); - funcs.glClearDepthf(1); - funcs.glStencilMask(0xff); - funcs.glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - funcs.glStencilFunc(GL_ALWAYS, 0, 0xff); - setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false); - setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, false); - setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false); - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - // gl_Color, corresponding to vertex attribute 3, may have been changed - float color[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - funcs.glVertexAttrib4fv(3, color); - } - if (vao.isCreated()) { - vao.release(); - funcs.glBindBuffer(GL_ARRAY_BUFFER, 0); - funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } -} - -void QOpenGL2PaintEngineEx::endNativePainting() -{ - Q_D(QOpenGL2PaintEngineEx); - d->needsSync = true; - d->nativePaintingActive = false; -} - -void QOpenGL2PaintEngineEx::invalidateState() -{ - Q_D(QOpenGL2PaintEngineEx); - d->needsSync = true; -} - -bool QOpenGL2PaintEngineEx::isNativePaintingActive() const { - Q_D(const QOpenGL2PaintEngineEx); - return d->nativePaintingActive; -} - -void QOpenGL2PaintEngineExPrivate::transferMode(EngineMode newMode) -{ - if (newMode == mode) - return; - - if (newMode == TextDrawingMode) { - shaderManager->setHasComplexGeometry(true); - } else { - shaderManager->setHasComplexGeometry(false); - } - - if (newMode == ImageDrawingMode) { - uploadData(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray, 8); - uploadData(QT_TEXTURE_COORDS_ATTR, staticTextureCoordinateArray, 8); - } - - if (newMode == ImageArrayDrawingMode || newMode == ImageOpacityArrayDrawingMode) { - uploadData(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data(), vertexCoordinateArray.vertexCount() * 2); - uploadData(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data(), textureCoordinateArray.vertexCount() * 2); - - if (newMode == ImageOpacityArrayDrawingMode) - uploadData(QT_OPACITY_ATTR, (GLfloat*)opacityArray.data(), opacityArray.size()); - } - - // This needs to change when we implement high-quality anti-aliasing... - if (newMode != TextDrawingMode) - shaderManager->setMaskType(QOpenGLEngineShaderManager::NoMask); - - mode = newMode; -} - -struct QOpenGL2PEVectorPathCache -{ -#ifdef QT_OPENGL_CACHE_AS_VBOS - GLuint vbo; - GLuint ibo; -#else - float *vertices; - void *indices; -#endif - int vertexCount; - int indexCount; - GLenum primitiveType; - qreal iscale; - QVertexIndexVector::Type indexType; -}; - -void QOpenGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data) -{ - QOpenGL2PEVectorPathCache *c = (QOpenGL2PEVectorPathCache *) data; -#ifdef QT_OPENGL_CACHE_AS_VBOS - Q_ASSERT(engine->type() == QPaintEngine::OpenGL2); - static_cast<QOpenGL2PaintEngineEx *>(engine)->d_func()->unusedVBOSToClean << c->vbo; - if (c->ibo) - d->unusedIBOSToClean << c->ibo; -#else - Q_UNUSED(engine); - free(c->vertices); - free(c->indices); -#endif - delete c; -} - -// Assumes everything is configured for the brush you want to use -void QOpenGL2PaintEngineExPrivate::fill(const QVectorPath& path) -{ - transferMode(BrushDrawingMode); - - if (snapToPixelGrid) { - snapToPixelGrid = false; - matrixDirty = true; - } - - // Might need to call updateMatrix to re-calculate inverseScale - if (matrixDirty) - updateMatrix(); - - const bool supportsElementIndexUint = funcs.hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint); - - const QPointF* const points = reinterpret_cast<const QPointF*>(path.points()); - - // Check to see if there's any hints - if (path.shape() == QVectorPath::RectangleHint) { - QOpenGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y()); - prepareForDraw(currentBrush.isOpaque()); - composite(rect); - } else if (path.isConvex()) { - - if (path.isCacheable()) { - QVectorPath::CacheEntry *data = path.lookupCacheData(q); - QOpenGL2PEVectorPathCache *cache; - - bool updateCache = false; - - if (data) { - cache = (QOpenGL2PEVectorPathCache *) data->data; - // Check if scale factor is exceeded and regenerate if so... - qreal scaleFactor = cache->iscale / inverseScale; - if (scaleFactor < 0.5 || scaleFactor > 2.0) { -#ifdef QT_OPENGL_CACHE_AS_VBOS - glDeleteBuffers(1, &cache->vbo); - cache->vbo = 0; - Q_ASSERT(cache->ibo == 0); -#else - free(cache->vertices); - Q_ASSERT(cache->indices == nullptr); -#endif - updateCache = true; - } - } else { - cache = new QOpenGL2PEVectorPathCache; - data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath); - updateCache = true; - } - - // Flatten the path at the current scale factor and fill it into the cache struct. - if (updateCache) { - vertexCoordinateArray.clear(); - vertexCoordinateArray.addPath(path, inverseScale, false); - int vertexCount = vertexCoordinateArray.vertexCount(); - int floatSizeInBytes = vertexCount * 2 * sizeof(float); - cache->vertexCount = vertexCount; - cache->indexCount = 0; - cache->primitiveType = GL_TRIANGLE_FAN; - cache->iscale = inverseScale; -#ifdef QT_OPENGL_CACHE_AS_VBOS - funcs.glGenBuffers(1, &cache->vbo); - funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); - funcs.glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW); - cache->ibo = 0; -#else - cache->vertices = (float *) malloc(floatSizeInBytes); - memcpy(cache->vertices, vertexCoordinateArray.data(), floatSizeInBytes); - cache->indices = nullptr; -#endif - } - - prepareForDraw(currentBrush.isOpaque()); -#ifdef QT_OPENGL_CACHE_AS_VBOS - funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); - uploadData(QT_VERTEX_COORD_ATTR, 0, cache->vertexCount); - setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0); -#else - uploadData(QT_VERTEX_COORDS_ATTR, cache->vertices, cache->vertexCount * 2); -#endif - funcs.glDrawArrays(cache->primitiveType, 0, cache->vertexCount); - - } else { - // printf(" - Marking path as cachable...\n"); - // Tag it for later so that if the same path is drawn twice, it is assumed to be static and thus cachable - path.makeCacheable(); - vertexCoordinateArray.clear(); - vertexCoordinateArray.addPath(path, inverseScale, false); - prepareForDraw(currentBrush.isOpaque()); - drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN); - } - - } else { - bool useCache = path.isCacheable(); - if (useCache) { - QRectF bbox = path.controlPointRect(); - // If the path doesn't fit within these limits, it is possible that the triangulation will fail. - useCache &= (bbox.left() > -0x8000 * inverseScale) - && (bbox.right() < 0x8000 * inverseScale) - && (bbox.top() > -0x8000 * inverseScale) - && (bbox.bottom() < 0x8000 * inverseScale); - } - - if (useCache) { - QVectorPath::CacheEntry *data = path.lookupCacheData(q); - QOpenGL2PEVectorPathCache *cache; - - bool updateCache = false; - - if (data) { - cache = (QOpenGL2PEVectorPathCache *) data->data; - // Check if scale factor is exceeded and regenerate if so... - qreal scaleFactor = cache->iscale / inverseScale; - if (scaleFactor < 0.5 || scaleFactor > 2.0) { -#ifdef QT_OPENGL_CACHE_AS_VBOS - glDeleteBuffers(1, &cache->vbo); - glDeleteBuffers(1, &cache->ibo); -#else - free(cache->vertices); - free(cache->indices); -#endif - updateCache = true; - } - } else { - cache = new QOpenGL2PEVectorPathCache; - data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath); - updateCache = true; - } - - // Flatten the path at the current scale factor and fill it into the cache struct. - if (updateCache) { - QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale), 1, supportsElementIndexUint); - cache->vertexCount = polys.vertices.size() / 2; - cache->indexCount = polys.indices.size(); - cache->primitiveType = GL_TRIANGLES; - cache->iscale = inverseScale; - cache->indexType = polys.indices.type(); -#ifdef QT_OPENGL_CACHE_AS_VBOS - funcs.glGenBuffers(1, &cache->vbo); - funcs.glGenBuffers(1, &cache->ibo); - funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); - funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo); - - if (polys.indices.type() == QVertexIndexVector::UnsignedInt) - funcs.glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint32) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW); - else - funcs.glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint16) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW); - - QVarLengthArray<float> vertices(polys.vertices.size()); - for (int i = 0; i < polys.vertices.size(); ++i) - vertices[i] = float(inverseScale * polys.vertices.at(i)); - funcs.glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW); -#else - cache->vertices = (float *) malloc(sizeof(float) * polys.vertices.size()); - if (polys.indices.type() == QVertexIndexVector::UnsignedInt) { - cache->indices = (quint32 *) malloc(sizeof(quint32) * polys.indices.size()); - memcpy(cache->indices, polys.indices.data(), sizeof(quint32) * polys.indices.size()); - } else { - cache->indices = (quint16 *) malloc(sizeof(quint16) * polys.indices.size()); - memcpy(cache->indices, polys.indices.data(), sizeof(quint16) * polys.indices.size()); - } - for (int i = 0; i < polys.vertices.size(); ++i) - cache->vertices[i] = float(inverseScale * polys.vertices.at(i)); -#endif - } - - prepareForDraw(currentBrush.isOpaque()); -#ifdef QT_OPENGL_CACHE_AS_VBOS - funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo); - funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo); - uploadData(QT_VERTEX_COORDS_ATTR, 0, cache->vertexCount); - setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0); - if (cache->indexType == QVertexIndexVector::UnsignedInt) - funcs.glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, 0); - else - funcs.glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, 0); - funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - funcs.glBindBuffer(GL_ARRAY_BUFFER, 0); -#else - uploadData(QT_VERTEX_COORDS_ATTR, cache->vertices, cache->vertexCount * 2); - const GLenum indexValueType = cache->indexType == QVertexIndexVector::UnsignedInt ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; - const bool useIndexVbo = uploadIndexData(cache->indices, indexValueType, cache->indexCount); - funcs.glDrawElements(cache->primitiveType, cache->indexCount, indexValueType, useIndexVbo ? nullptr : cache->indices); -#endif - - } else { - // printf(" - Marking path as cachable...\n"); - // Tag it for later so that if the same path is drawn twice, it is assumed to be static and thus cachable - path.makeCacheable(); - - if (device->context()->format().stencilBufferSize() <= 0) { - // If there is no stencil buffer, triangulate the path instead. - - QRectF bbox = path.controlPointRect(); - // If the path doesn't fit within these limits, it is possible that the triangulation will fail. - bool withinLimits = (bbox.left() > -0x8000 * inverseScale) - && (bbox.right() < 0x8000 * inverseScale) - && (bbox.top() > -0x8000 * inverseScale) - && (bbox.bottom() < 0x8000 * inverseScale); - if (withinLimits) { - QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale), 1, supportsElementIndexUint); - - QVarLengthArray<float> vertices(polys.vertices.size()); - for (int i = 0; i < polys.vertices.size(); ++i) - vertices[i] = float(inverseScale * polys.vertices.at(i)); - - prepareForDraw(currentBrush.isOpaque()); - uploadData(QT_VERTEX_COORDS_ATTR, vertices.constData(), vertices.size()); - const GLenum indexValueType = funcs.hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; - const bool useIndexVbo = uploadIndexData(polys.indices.data(), indexValueType, polys.indices.size()); - funcs.glDrawElements(GL_TRIANGLES, polys.indices.size(), indexValueType, useIndexVbo ? nullptr : polys.indices.data()); - } else { - // We can't handle big, concave painter paths with OpenGL without stencil buffer. - qWarning("Painter path exceeds +/-32767 pixels."); - } - return; - } - - // The path is too complicated & needs the stencil technique - vertexCoordinateArray.clear(); - vertexCoordinateArray.addPath(path, inverseScale, false); - - fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); - - funcs.glStencilMask(0xff); - funcs.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); - - if (q->state()->clipTestEnabled) { - // Pass when high bit is set, replace stencil value with current clip - funcs.glStencilFunc(GL_NOTEQUAL, q->state()->currentClip, GL_STENCIL_HIGH_BIT); - } else if (path.hasWindingFill()) { - // Pass when any bit is set, replace stencil value with 0 - funcs.glStencilFunc(GL_NOTEQUAL, 0, 0xff); - } else { - // Pass when high bit is set, replace stencil value with 0 - funcs.glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT); - } - prepareForDraw(currentBrush.isOpaque()); - - // Stencil the brush onto the dest buffer - composite(vertexCoordinateArray.boundingRect()); - funcs.glStencilMask(0); - updateClipScissorTest(); - } - } -} - - -void QOpenGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data, - int count, - int *stops, - int stopCount, - const QOpenGLRect &bounds, - StencilFillMode mode) -{ - Q_ASSERT(count || stops); - -// qDebug("QOpenGL2PaintEngineExPrivate::fillStencilWithVertexArray()"); - funcs.glStencilMask(0xff); // Enable stencil writes - - if (dirtyStencilRegion.intersects(currentScissorBounds)) { - const QRegion clearRegion = dirtyStencilRegion.intersected(currentScissorBounds); - funcs.glClearStencil(0); // Clear to zero - for (const QRect &rect : clearRegion) { -#ifndef QT_GL_NO_SCISSOR_TEST - setScissor(rect); -#endif - funcs.glClear(GL_STENCIL_BUFFER_BIT); - } - - dirtyStencilRegion -= currentScissorBounds; - -#ifndef QT_GL_NO_SCISSOR_TEST - updateClipScissorTest(); -#endif - } - - funcs.glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes - useSimpleShader(); - funcs.glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d - - if (mode == WindingFillMode) { - Q_ASSERT(stops && !count); - if (q->state()->clipTestEnabled) { - // Flatten clip values higher than current clip, and set high bit to match current clip - funcs.glStencilFunc(GL_LEQUAL, GL_STENCIL_HIGH_BIT | q->state()->currentClip, ~GL_STENCIL_HIGH_BIT); - funcs.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); - composite(bounds); - - funcs.glStencilFunc(GL_EQUAL, GL_STENCIL_HIGH_BIT, GL_STENCIL_HIGH_BIT); - } else if (!stencilClean) { - // Clear stencil buffer within bounding rect - funcs.glStencilFunc(GL_ALWAYS, 0, 0xff); - funcs.glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); - composite(bounds); - } - - // Inc. for front-facing triangle - funcs.glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP); - // Dec. for back-facing "holes" - funcs.glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_DECR_WRAP); - funcs.glStencilMask(~GL_STENCIL_HIGH_BIT); - drawVertexArrays(data, stops, stopCount, GL_TRIANGLE_FAN); - - if (q->state()->clipTestEnabled) { - // Clear high bit of stencil outside of path - funcs.glStencilFunc(GL_EQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT); - funcs.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); - funcs.glStencilMask(GL_STENCIL_HIGH_BIT); - composite(bounds); - } - } else if (mode == OddEvenFillMode) { - funcs.glStencilMask(GL_STENCIL_HIGH_BIT); - funcs.glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit - drawVertexArrays(data, stops, stopCount, GL_TRIANGLE_FAN); - - } else { // TriStripStrokeFillMode - Q_ASSERT(count && !stops); // tristrips generated directly, so no vertexArray or stops - funcs.glStencilMask(GL_STENCIL_HIGH_BIT); -#if 0 - funcs.glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit - setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, data); - funcs.glDrawArrays(GL_TRIANGLE_STRIP, 0, count); -#else - - funcs.glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - if (q->state()->clipTestEnabled) { - funcs.glStencilFunc(GL_LEQUAL, q->state()->currentClip | GL_STENCIL_HIGH_BIT, - ~GL_STENCIL_HIGH_BIT); - } else { - funcs.glStencilFunc(GL_ALWAYS, GL_STENCIL_HIGH_BIT, 0xff); - } - - uploadData(QT_VERTEX_COORDS_ATTR, data, count * 2); - funcs.glDrawArrays(GL_TRIANGLE_STRIP, 0, count); -#endif - } - - // Enable color writes & disable stencil writes - funcs.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); -} - -/* - If the maximum value in the stencil buffer is GL_STENCIL_HIGH_BIT - 1, - restore the stencil buffer to a pristine state. The current clip region - is set to 1, and the rest to 0. -*/ -void QOpenGL2PaintEngineExPrivate::resetClipIfNeeded() -{ - if (maxClip != (GL_STENCIL_HIGH_BIT - 1)) - return; - - Q_Q(QOpenGL2PaintEngineEx); - - useSimpleShader(); - funcs.glEnable(GL_STENCIL_TEST); - funcs.glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - - QRectF bounds = q->state()->matrix.inverted().mapRect(QRectF(0, 0, width, height)); - QOpenGLRect rect(bounds.left(), bounds.top(), bounds.right(), bounds.bottom()); - - // Set high bit on clip region - funcs.glStencilFunc(GL_LEQUAL, q->state()->currentClip, 0xff); - funcs.glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT); - funcs.glStencilMask(GL_STENCIL_HIGH_BIT); - composite(rect); - - // Reset clipping to 1 and everything else to zero - funcs.glStencilFunc(GL_NOTEQUAL, 0x01, GL_STENCIL_HIGH_BIT); - funcs.glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE); - funcs.glStencilMask(0xff); - composite(rect); - - q->state()->currentClip = 1; - q->state()->canRestoreClip = false; - - maxClip = 1; - - funcs.glStencilMask(0x0); - funcs.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); -} - -bool QOpenGL2PaintEngineExPrivate::prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache) -{ - Q_Q(QOpenGL2PaintEngineEx); - - Q_ASSERT(cache.transform().type() <= QTransform::TxScale); - - QTransform &transform = q->state()->matrix; - transform.scale(1.0 / cache.transform().m11(), 1.0 / cache.transform().m22()); - bool ret = prepareForDraw(false); - transform.scale(cache.transform().m11(), cache.transform().m22()); - - return ret; -} - -bool QOpenGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) -{ - if (brushTextureDirty && (mode == TextDrawingMode || mode == BrushDrawingMode)) - updateBrushTexture(); - - if (compositionModeDirty) - updateCompositionMode(); - - if (matrixDirty) - updateMatrix(); - - const bool stateHasOpacity = q->state()->opacity < 0.99f; - if (q->state()->composition_mode == QPainter::CompositionMode_Source - || (q->state()->composition_mode == QPainter::CompositionMode_SourceOver - && srcPixelsAreOpaque && !stateHasOpacity)) - { - funcs.glDisable(GL_BLEND); - } else { - funcs.glEnable(GL_BLEND); - } - - QOpenGLEngineShaderManager::OpacityMode opacityMode; - if (mode == ImageOpacityArrayDrawingMode) { - opacityMode = QOpenGLEngineShaderManager::AttributeOpacity; - } else { - opacityMode = stateHasOpacity ? QOpenGLEngineShaderManager::UniformOpacity - : QOpenGLEngineShaderManager::NoOpacity; - if (stateHasOpacity && (mode != ImageDrawingMode && mode != ImageArrayDrawingMode)) { - // Using a brush - bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) && - (currentBrush.style() <= Qt::DiagCrossPattern); - - if ((currentBrush.style() == Qt::SolidPattern) || brushIsPattern) - opacityMode = QOpenGLEngineShaderManager::NoOpacity; // Global opacity handled by srcPixel shader - } - } - shaderManager->setOpacityMode(opacityMode); - - bool changed = shaderManager->useCorrectShaderProg(); - // If the shader program needs changing, we change it and mark all uniforms as dirty - if (changed) { - // The shader program has changed so mark all uniforms as dirty: - brushUniformsDirty = true; - opacityUniformDirty = true; - matrixUniformDirty = true; - } - - if (brushUniformsDirty && (mode == TextDrawingMode || mode == BrushDrawingMode)) - updateBrushUniforms(); - - if (opacityMode == QOpenGLEngineShaderManager::UniformOpacity && opacityUniformDirty) { - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity); - opacityUniformDirty = false; - } - - if (matrixUniformDirty && shaderManager->hasComplexGeometry()) { - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::Matrix), - pmvMatrix); - matrixUniformDirty = false; - } - - return changed; -} - -void QOpenGL2PaintEngineExPrivate::composite(const QOpenGLRect& boundingRect) -{ - setCoords(staticVertexCoordinateArray, boundingRect); - - uploadData(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray, 8); - funcs.glDrawArrays(GL_TRIANGLE_FAN, 0, 4); -} - -// Draws the vertex array as a set of <vertexArrayStops.size()> triangle fans. -void QOpenGL2PaintEngineExPrivate::drawVertexArrays(const float *data, int *stops, int stopCount, - GLenum primitive) -{ - // Now setup the pointer to the vertex array: - uploadData(QT_VERTEX_COORDS_ATTR, data, stops[stopCount-1] * 2); - - int previousStop = 0; - for (int i=0; i<stopCount; ++i) { - int stop = stops[i]; - - funcs.glDrawArrays(primitive, previousStop, stop - previousStop); - previousStop = stop; - } -} - -/////////////////////////////////// Public Methods ////////////////////////////////////////// - -QOpenGL2PaintEngineEx::QOpenGL2PaintEngineEx() - : QPaintEngineEx(*(new QOpenGL2PaintEngineExPrivate(this))) -{ - gccaps &= ~QPaintEngine::RasterOpModes; -} - -QOpenGL2PaintEngineEx::~QOpenGL2PaintEngineEx() -{ -} - -void QOpenGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush) -{ - Q_D(QOpenGL2PaintEngineEx); - - if (qbrush_style(brush) == Qt::NoBrush) - return; - ensureActive(); - d->setBrush(brush); - d->fill(path); -} - -Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp - - -void QOpenGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) -{ - Q_D(QOpenGL2PaintEngineEx); - - const QBrush &penBrush = qpen_brush(pen); - if (qpen_style(pen) == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush) - return; - - QOpenGL2PaintEngineState *s = state(); - if (qt_pen_is_cosmetic(pen, state()->renderHints) && !qt_scaleForTransform(s->transform(), nullptr)) { - // QTriangulatingStroker class is not meant to support cosmetically sheared strokes. - QPaintEngineEx::stroke(path, pen); - return; - } - - ensureActive(); - d->setBrush(penBrush); - d->stroke(path, pen); -} - -void QOpenGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen) -{ - const QOpenGL2PaintEngineState *s = q->state(); - if (snapToPixelGrid) { - snapToPixelGrid = false; - matrixDirty = true; - } - - const Qt::PenStyle penStyle = qpen_style(pen); - const QBrush &penBrush = qpen_brush(pen); - const bool opaque = penBrush.isOpaque() && s->opacity > 0.99; - - transferMode(BrushDrawingMode); - - // updateMatrix() is responsible for setting the inverse scale on - // the strokers, so we need to call it here and not wait for - // prepareForDraw() down below. - updateMatrix(); - - QRectF clip = q->state()->matrix.inverted().mapRect(q->state()->clipEnabled - ? q->state()->rectangleClip - : QRectF(0, 0, width, height)); - - if (penStyle == Qt::SolidLine) { - stroker.process(path, pen, clip, s->renderHints); - - } else { // Some sort of dash - dasher.process(path, pen, clip, s->renderHints); - - QVectorPath dashStroke(dasher.points(), - dasher.elementCount(), - dasher.elementTypes()); - stroker.process(dashStroke, pen, clip, s->renderHints); - } - - if (!stroker.vertexCount()) - return; - - if (opaque) { - prepareForDraw(opaque); - - uploadData(QT_VERTEX_COORDS_ATTR, stroker.vertices(), stroker.vertexCount()); - funcs.glDrawArrays(GL_TRIANGLE_STRIP, 0, stroker.vertexCount() / 2); - } else { - qreal width = qpen_widthf(pen) / 2; - if (width == 0) - width = 0.5; - qreal extra = pen.joinStyle() == Qt::MiterJoin - ? qMax(pen.miterLimit() * width, width) - : width; - - if (qt_pen_is_cosmetic(pen, q->state()->renderHints)) - extra = extra * inverseScale; - - QRectF bounds = path.controlPointRect().adjusted(-extra, -extra, extra, extra); - - fillStencilWithVertexArray(stroker.vertices(), stroker.vertexCount() / 2, - nullptr, 0, bounds, QOpenGL2PaintEngineExPrivate::TriStripStrokeFillMode); - - funcs.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); - - // Pass when any bit is set, replace stencil value with 0 - funcs.glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT); - prepareForDraw(false); - - // Stencil the brush onto the dest buffer - composite(bounds); - - funcs.glStencilMask(0); - - updateClipScissorTest(); - } -} - -void QOpenGL2PaintEngineEx::penChanged() { } -void QOpenGL2PaintEngineEx::brushChanged() { } -void QOpenGL2PaintEngineEx::brushOriginChanged() { } - -void QOpenGL2PaintEngineEx::opacityChanged() -{ -// qDebug("QOpenGL2PaintEngineEx::opacityChanged()"); - Q_D(QOpenGL2PaintEngineEx); - state()->opacityChanged = true; - - Q_ASSERT(d->shaderManager); - d->brushUniformsDirty = true; - d->opacityUniformDirty = true; -} - -void QOpenGL2PaintEngineEx::compositionModeChanged() -{ -// qDebug("QOpenGL2PaintEngineEx::compositionModeChanged()"); - Q_D(QOpenGL2PaintEngineEx); - state()->compositionModeChanged = true; - d->compositionModeDirty = true; -} - -void QOpenGL2PaintEngineEx::renderHintsChanged() -{ - state()->renderHintsChanged = true; - -#ifndef QT_OPENGL_ES_2 - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGL2PaintEngineEx); -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - if ((state()->renderHints & QPainter::Antialiasing) -#if QT_DEPRECATED_SINCE(5, 14) - || (state()->renderHints & QPainter::HighQualityAntialiasing) -#endif - ) - d->funcs.glEnable(GL_MULTISAMPLE); - else - d->funcs.glDisable(GL_MULTISAMPLE); -QT_WARNING_POP - } -#endif // QT_OPENGL_ES_2 - - Q_D(QOpenGL2PaintEngineEx); - - // This is a somewhat sneaky way of conceptually making the next call to - // updateTexture() use FoceUpdate for the TextureUpdateMode. We need this - // as new render hints may require updating the filter mode. - d->lastTextureUsed = GLuint(-1); - - d->brushTextureDirty = true; -// qDebug("QOpenGL2PaintEngineEx::renderHintsChanged() not implemented!"); -} - -void QOpenGL2PaintEngineEx::transformChanged() -{ - Q_D(QOpenGL2PaintEngineEx); - d->matrixDirty = true; - state()->matrixChanged = true; -} - - -static const QRectF scaleRect(const QRectF &r, qreal sx, qreal sy) -{ - return QRectF(r.x() * sx, r.y() * sy, r.width() * sx, r.height() * sy); -} - -void QOpenGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src) -{ - Q_D(QOpenGL2PaintEngineEx); - QOpenGLContext *ctx = d->ctx; - - // Draw pixmaps that are really images as images since drawImage has - // better handling of non-default image formats. - if (pixmap.paintEngine()->type() == QPaintEngine::Raster && !pixmap.isQBitmap()) - return drawImage(dest, pixmap.toImage(), src); - - int max_texture_size = ctx->d_func()->maxTextureSize(); - if (pixmap.width() > max_texture_size || pixmap.height() > max_texture_size) { - QPixmap scaled = pixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio); - - const qreal sx = scaled.width() / qreal(pixmap.width()); - const qreal sy = scaled.height() / qreal(pixmap.height()); - - drawPixmap(dest, scaled, scaleRect(src, sx, sy)); - return; - } - - ensureActive(); - d->transferMode(ImageDrawingMode); - - GLenum filterMode = state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST; - d->updateTexture(QT_IMAGE_TEXTURE_UNIT, pixmap, GL_CLAMP_TO_EDGE, filterMode); - - bool isBitmap = pixmap.isQBitmap(); - bool isOpaque = !isBitmap && !pixmap.hasAlpha(); - - d->shaderManager->setSrcPixelType(isBitmap ? QOpenGLEngineShaderManager::PatternSrc : QOpenGLEngineShaderManager::ImageSrc); - - QOpenGLRect srcRect(src.left(), src.top(), src.right(), src.bottom()); - d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap); -} - -void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src, - Qt::ImageConversionFlags) -{ - Q_D(QOpenGL2PaintEngineEx); - QOpenGLContext *ctx = d->ctx; - - int max_texture_size = ctx->d_func()->maxTextureSize(); - if (image.width() > max_texture_size || image.height() > max_texture_size) { - QImage scaled = image.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio); - - const qreal sx = scaled.width() / qreal(image.width()); - const qreal sy = scaled.height() / qreal(image.height()); - - drawImage(dest, scaled, scaleRect(src, sx, sy)); - return; - } - - ensureActive(); - d->transferMode(ImageDrawingMode); - - QOpenGLTextureUploader::BindOptions bindOption = QOpenGLTextureUploader::PremultipliedAlphaBindOption; - // Use specialized bind for formats we have specialized shaders for. - switch (image.format()) { - case QImage::Format_RGBA8888: - case QImage::Format_ARGB32: - case QImage::Format_RGBA64: - d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::NonPremultipliedImageSrc); - bindOption = { }; - break; - case QImage::Format_Alpha8: - if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) { - d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::AlphaImageSrc); - bindOption = QOpenGLTextureUploader::UseRedForAlphaAndLuminanceBindOption; - } else - d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); - break; - case QImage::Format_Grayscale8: - case QImage::Format_Grayscale16: - if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) { - d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::GrayscaleImageSrc); - bindOption = QOpenGLTextureUploader::UseRedForAlphaAndLuminanceBindOption; - } else - d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); - break; - default: - d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); - break; - } - - ImageWithBindOptions imageWithOptions = { image, bindOption }; - GLenum filterMode = state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST; - d->updateTexture(QT_IMAGE_TEXTURE_UNIT, imageWithOptions, GL_CLAMP_TO_EDGE, filterMode); - - d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel()); -} - -void QOpenGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) -{ - Q_D(QOpenGL2PaintEngineEx); - - ensureActive(); - - QPainterState *s = state(); - - QFontEngine *fontEngine = textItem->fontEngine(); - if (shouldDrawCachedGlyphs(fontEngine, s->matrix)) { - QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None - ? fontEngine->glyphFormat : d->glyphCacheFormat; - if (glyphFormat == QFontEngine::Format_A32) { - if (d->device->context()->format().alphaBufferSize() > 0 || s->matrix.type() > QTransform::TxTranslate - || (s->composition_mode != QPainter::CompositionMode_Source - && s->composition_mode != QPainter::CompositionMode_SourceOver)) - { - glyphFormat = QFontEngine::Format_A8; - } - } - - d->drawCachedGlyphs(glyphFormat, textItem); - } else { - QPaintEngineEx::drawStaticTextItem(textItem); - } -} - -bool QOpenGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src) -{ - Q_D(QOpenGL2PaintEngineEx); - if (!d->shaderManager) - return false; - - ensureActive(); - d->transferMode(ImageDrawingMode); - - GLenum filterMode = state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST; - d->updateTexture(QT_IMAGE_TEXTURE_UNIT, textureId, GL_CLAMP_TO_EDGE, filterMode); - - d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); - - QOpenGLRect srcRect(src.left(), src.bottom(), src.right(), src.top()); - d->drawTexture(dest, srcRect, size, false); - - return true; -} - -void QOpenGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem) -{ - Q_D(QOpenGL2PaintEngineEx); - - ensureActive(); - QOpenGL2PaintEngineState *s = state(); - - const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); - - QTransform::TransformationType txtype = s->matrix.type(); - - QFontEngine::GlyphFormat glyphFormat = ti.fontEngine->glyphFormat != QFontEngine::Format_None - ? ti.fontEngine->glyphFormat : d->glyphCacheFormat; - - if (glyphFormat == QFontEngine::Format_A32) { - if (d->device->context()->format().alphaBufferSize() > 0 || txtype > QTransform::TxTranslate - || (state()->composition_mode != QPainter::CompositionMode_Source - && state()->composition_mode != QPainter::CompositionMode_SourceOver)) - { - glyphFormat = QFontEngine::Format_A8; - } - } - - if (shouldDrawCachedGlyphs(ti.fontEngine, s->matrix)) { - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix = QTransform::fromTranslate(p.x(), p.y()); - ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - - { - QStaticTextItem staticTextItem; - staticTextItem.setFontEngine(ti.fontEngine); - staticTextItem.glyphs = glyphs.data(); - staticTextItem.numGlyphs = glyphs.size(); - staticTextItem.glyphPositions = positions.data(); - - d->drawCachedGlyphs(glyphFormat, &staticTextItem); - } - return; - } - - QPaintEngineEx::drawTextItem(p, ti); -} - -namespace { - - class QOpenGLStaticTextUserData: public QStaticTextUserData - { - public: - QOpenGLStaticTextUserData() - : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0), cacheSerialNumber(0) - { - } - - ~QOpenGLStaticTextUserData() - { - } - - QSize cacheSize; - QOpenGL2PEXVertexArray vertexCoordinateArray; - QOpenGL2PEXVertexArray textureCoordinateArray; - QFontEngine::GlyphFormat glyphFormat; - int cacheSerialNumber; - }; - -} - - -// #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO - -bool QOpenGL2PaintEngineEx::shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &t) const -{ - // The paint engine does not support projected cached glyph drawing - if (t.type() == QTransform::TxProject) - return false; - - // The font engine might not support filling the glyph cache - // with the given transform applied, in which case we need to - // fall back to the QPainterPath code-path. - if (!fontEngine->supportsTransformation(t)) { - // Except that drawing paths is slow, so for scales between - // 0.5 and 2.0 we leave the glyph cache untransformed and deal - // with the transform ourselves when painting, resulting in - // drawing 1x cached glyphs with a smooth-scale. - float det = t.determinant(); - if (det >= 0.25f && det <= 4.f) { - // Assuming the baseclass still agrees - return QPaintEngineEx::shouldDrawCachedGlyphs(fontEngine, t); - } - - return false; // Fall back to path-drawing - } - - return QPaintEngineEx::shouldDrawCachedGlyphs(fontEngine, t); -} - -void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat, - QStaticTextItem *staticTextItem) -{ - Q_Q(QOpenGL2PaintEngineEx); - - QOpenGL2PaintEngineState *s = q->state(); - - void *cacheKey = ctx; // use context, not the shareGroup() -> the GL glyph cache uses FBOs which may not be shareable - bool recreateVertexArrays = false; - - QTransform glyphCacheTransform; - QFontEngine *fe = staticTextItem->fontEngine(); - if (fe->supportsTransformation(s->matrix)) { - // The font-engine supports rendering glyphs with the current transform, so we - // build a glyph-cache with the scale pre-applied, so that the cache contains - // glyphs with the appropriate resolution in the case of retina displays. - glyphCacheTransform = s->matrix.type() < QTransform::TxRotate ? - QTransform::fromScale(qAbs(s->matrix.m11()), qAbs(s->matrix.m22())) : - QTransform::fromScale( - QVector2D(s->matrix.m11(), s->matrix.m12()).length(), - QVector2D(s->matrix.m21(), s->matrix.m22()).length()); - } - - QOpenGLTextureGlyphCache *cache = - (QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphFormat, glyphCacheTransform); - if (!cache || cache->glyphFormat() != glyphFormat || cache->contextGroup() == nullptr) { - cache = new QOpenGLTextureGlyphCache(glyphFormat, glyphCacheTransform); - fe->setGlyphCache(cacheKey, cache); - recreateVertexArrays = true; - } - - if (staticTextItem->userDataNeedsUpdate) { - recreateVertexArrays = true; - } else if (staticTextItem->userData() == nullptr) { - recreateVertexArrays = true; - } else if (staticTextItem->userData()->type != QStaticTextUserData::OpenGLUserData) { - recreateVertexArrays = true; - } else { - QOpenGLStaticTextUserData *userData = static_cast<QOpenGLStaticTextUserData *>(staticTextItem->userData()); - if (userData->glyphFormat != glyphFormat) { - recreateVertexArrays = true; - } else if (userData->cacheSerialNumber != cache->serialNumber()) { - recreateVertexArrays = true; - } - } - - // We only need to update the cache with new glyphs if we are actually going to recreate the vertex arrays. - // If the cache size has changed, we do need to regenerate the vertices, but we don't need to repopulate the - // cache so this text is performed before we test if the cache size has changed. - if (recreateVertexArrays) { - cache->setPaintEnginePrivate(this); - if (!cache->populate(fe, staticTextItem->numGlyphs, - staticTextItem->glyphs, staticTextItem->glyphPositions)) { - // No space for glyphs in cache. We need to reset it and try again. - cache->clear(); - cache->populate(fe, staticTextItem->numGlyphs, - staticTextItem->glyphs, staticTextItem->glyphPositions); - } - - if (cache->hasPendingGlyphs()) { - // Filling in the glyphs binds and sets parameters, so we need to - // ensure that the glyph cache doesn't mess with whatever unit - // is currently active. Note that the glyph cache internally - // uses the image texture unit for blitting to the cache, while - // we switch between image and mask units when drawing. - static const GLenum glypchCacheTextureUnit = QT_IMAGE_TEXTURE_UNIT; - activateTextureUnit(glypchCacheTextureUnit); - - cache->fillInPendingGlyphs(); - - // We assume the cache can be trusted on which texture was bound - lastTextureUsed = cache->texture(); - - // But since the brush and image texture units are possibly shared - // we may have to re-bind brush textures after filling in the cache. - brushTextureDirty = (QT_BRUSH_TEXTURE_UNIT == glypchCacheTextureUnit); - } - cache->setPaintEnginePrivate(nullptr); - } - - if (cache->width() == 0 || cache->height() == 0) - return; - - if (glyphFormat == QFontEngine::Format_ARGB) - transferMode(ImageArrayDrawingMode); - else - transferMode(TextDrawingMode); - - int margin = fe->glyphMargin(glyphFormat); - - GLfloat dx = 1.0 / cache->width(); - GLfloat dy = 1.0 / cache->height(); - - // Use global arrays by default - QOpenGL2PEXVertexArray *vertexCoordinates = &vertexCoordinateArray; - QOpenGL2PEXVertexArray *textureCoordinates = &textureCoordinateArray; - - if (staticTextItem->useBackendOptimizations) { - QOpenGLStaticTextUserData *userData = nullptr; - - if (staticTextItem->userData() == nullptr - || staticTextItem->userData()->type != QStaticTextUserData::OpenGLUserData) { - - userData = new QOpenGLStaticTextUserData(); - staticTextItem->setUserData(userData); - - } else { - userData = static_cast<QOpenGLStaticTextUserData*>(staticTextItem->userData()); - } - - userData->glyphFormat = glyphFormat; - userData->cacheSerialNumber = cache->serialNumber(); - - // Use cache if backend optimizations is turned on - vertexCoordinates = &userData->vertexCoordinateArray; - textureCoordinates = &userData->textureCoordinateArray; - - QSize size(cache->width(), cache->height()); - if (userData->cacheSize != size) { - recreateVertexArrays = true; - userData->cacheSize = size; - } - } - - if (recreateVertexArrays) { - vertexCoordinates->clear(); - textureCoordinates->clear(); - - bool supportsSubPixelPositions = fe->supportsSubPixelPositions(); - for (int i=0; i<staticTextItem->numGlyphs; ++i) { - QFixed subPixelPosition; - if (supportsSubPixelPositions) - subPixelPosition = fe->subPixelPositionForX(staticTextItem->glyphPositions[i].x); - - QTextureGlyphCache::GlyphAndSubPixelPosition glyph(staticTextItem->glyphs[i], subPixelPosition); - - const QTextureGlyphCache::Coord &c = cache->coords[glyph]; - if (c.isNull()) - continue; - - int x = qFloor(staticTextItem->glyphPositions[i].x.toReal() * cache->transform().m11()) + c.baseLineX - margin; - int y = qRound(staticTextItem->glyphPositions[i].y.toReal() * cache->transform().m22()) - c.baseLineY - margin; - - vertexCoordinates->addQuad(QRectF(x, y, c.w, c.h)); - textureCoordinates->addQuad(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy)); - } - - staticTextItem->userDataNeedsUpdate = false; - } - - int numGlyphs = vertexCoordinates->vertexCount() / 4; - if (numGlyphs == 0) - return; - - if (elementIndices.size() < numGlyphs*6) { - Q_ASSERT(elementIndices.size() % 6 == 0); - int j = elementIndices.size() / 6 * 4; - while (j < numGlyphs*4) { - elementIndices.append(j + 0); - elementIndices.append(j + 0); - elementIndices.append(j + 1); - elementIndices.append(j + 2); - elementIndices.append(j + 3); - elementIndices.append(j + 3); - - j += 4; - } - -#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) - if (elementIndicesVBOId == 0) - funcs.glGenBuffers(1, &elementIndicesVBOId); - - funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId); - funcs.glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementIndices.size() * sizeof(GLushort), - elementIndices.constData(), GL_STATIC_DRAW); -#endif - } else { -#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) - funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId); -#endif - } - - if (glyphFormat != QFontEngine::Format_ARGB || recreateVertexArrays) { - uploadData(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data(), vertexCoordinates->vertexCount() * 2); - uploadData(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data(), textureCoordinates->vertexCount() * 2); - } - - if (!snapToPixelGrid) { - snapToPixelGrid = true; - matrixDirty = true; - } - - QBrush pensBrush = q->state()->pen.brush(); - setBrush(pensBrush); - - if (glyphFormat == QFontEngine::Format_A32) { - - // Subpixel antialiasing without gamma correction - - QPainter::CompositionMode compMode = q->state()->composition_mode; - Q_ASSERT(compMode == QPainter::CompositionMode_Source - || compMode == QPainter::CompositionMode_SourceOver); - - shaderManager->setMaskType(QOpenGLEngineShaderManager::SubPixelMaskPass1); - - if (pensBrush.style() == Qt::SolidPattern) { - // Solid patterns can get away with only one pass. - QColor c = pensBrush.color(); - qreal oldOpacity = q->state()->opacity; - if (compMode == QPainter::CompositionMode_Source) { - c = qt_premultiplyColor(c, q->state()->opacity); - q->state()->opacity = 1; - opacityUniformDirty = true; - } - - compositionModeDirty = false; // I can handle this myself, thank you very much - prepareForCachedGlyphDraw(*cache); - - // prepareForCachedGlyphDraw() have set the opacity on the current shader, so the opacity state can now be reset. - if (compMode == QPainter::CompositionMode_Source) { - q->state()->opacity = oldOpacity; - opacityUniformDirty = true; - } - - funcs.glEnable(GL_BLEND); - funcs.glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR); - funcs.glBlendColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); - } else { - // Other brush styles need two passes. - - qreal oldOpacity = q->state()->opacity; - if (compMode == QPainter::CompositionMode_Source) { - q->state()->opacity = 1; - opacityUniformDirty = true; - pensBrush = Qt::white; - setBrush(pensBrush); - } - - compositionModeDirty = false; // I can handle this myself, thank you very much - prepareForCachedGlyphDraw(*cache); - funcs.glEnable(GL_BLEND); - funcs.glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - - updateTexture(QT_MASK_TEXTURE_UNIT, cache->texture(), GL_REPEAT, GL_NEAREST, ForceUpdate); - -#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) - funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0); -#else - const bool useIndexVbo = uploadIndexData(elementIndices.data(), GL_UNSIGNED_SHORT, 6 * numGlyphs); - funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, useIndexVbo ? nullptr : elementIndices.data()); -#endif - - shaderManager->setMaskType(QOpenGLEngineShaderManager::SubPixelMaskPass2); - - if (compMode == QPainter::CompositionMode_Source) { - q->state()->opacity = oldOpacity; - opacityUniformDirty = true; - pensBrush = q->state()->pen.brush(); - setBrush(pensBrush); - } - - compositionModeDirty = false; - prepareForCachedGlyphDraw(*cache); - funcs.glEnable(GL_BLEND); - funcs.glBlendFunc(GL_ONE, GL_ONE); - } - compositionModeDirty = true; - } else if (glyphFormat == QFontEngine::Format_ARGB) { - currentBrush = noBrush; - shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc); - if (prepareForCachedGlyphDraw(*cache)) - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); - } else { - // Grayscale/mono glyphs - - shaderManager->setMaskType(QOpenGLEngineShaderManager::PixelMask); - prepareForCachedGlyphDraw(*cache); - } - - GLenum textureUnit = QT_MASK_TEXTURE_UNIT; - if (glyphFormat == QFontEngine::Format_ARGB) - textureUnit = QT_IMAGE_TEXTURE_UNIT; - - QOpenGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate) ? - QOpenGLTextureGlyphCache::Linear : QOpenGLTextureGlyphCache::Nearest; - - GLenum glFilterMode = filterMode == QOpenGLTextureGlyphCache::Linear ? GL_LINEAR : GL_NEAREST; - - TextureUpdateMode updateMode = UpdateIfNeeded; - if (cache->filterMode() != filterMode) { - updateMode = ForceUpdate; - cache->setFilterMode(filterMode); - } - - updateTexture(textureUnit, cache->texture(), GL_REPEAT, glFilterMode, updateMode); - -#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) - funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0); - funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -#else - const bool useIndexVbo = uploadIndexData(elementIndices.data(), GL_UNSIGNED_SHORT, 6 * numGlyphs); - funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, useIndexVbo ? nullptr : elementIndices.data()); -#endif -} - -void QOpenGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, - QPainter::PixmapFragmentHints hints) -{ - Q_D(QOpenGL2PaintEngineEx); - // Use fallback for extended composition modes. - if (state()->composition_mode > QPainter::CompositionMode_Plus) { - QPaintEngineEx::drawPixmapFragments(fragments, fragmentCount, pixmap, hints); - return; - } - - ensureActive(); - int max_texture_size = d->ctx->d_func()->maxTextureSize(); - if (pixmap.width() > max_texture_size || pixmap.height() > max_texture_size) { - QPixmap scaled = pixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio); - d->drawPixmapFragments(fragments, fragmentCount, scaled, hints); - } else { - d->drawPixmapFragments(fragments, fragmentCount, pixmap, hints); - } -} - - -void QOpenGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragment *fragments, - int fragmentCount, const QPixmap &pixmap, - QPainter::PixmapFragmentHints hints) -{ - GLfloat dx = 1.0f / pixmap.size().width(); - GLfloat dy = 1.0f / pixmap.size().height(); - - vertexCoordinateArray.clear(); - textureCoordinateArray.clear(); - opacityArray.reset(); - - if (snapToPixelGrid) { - snapToPixelGrid = false; - matrixDirty = true; - } - - bool allOpaque = true; - - for (int i = 0; i < fragmentCount; ++i) { - qreal s = 0; - qreal c = 1; - if (fragments[i].rotation != 0) { - s = qFastSin(qDegreesToRadians(fragments[i].rotation)); - c = qFastCos(qDegreesToRadians(fragments[i].rotation)); - } - - qreal right = 0.5 * fragments[i].scaleX * fragments[i].width; - qreal bottom = 0.5 * fragments[i].scaleY * fragments[i].height; - QOpenGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c); - QOpenGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c); - - vertexCoordinateArray.addVertex(bottomRight.x + fragments[i].x, bottomRight.y + fragments[i].y); - vertexCoordinateArray.addVertex(-bottomLeft.x + fragments[i].x, -bottomLeft.y + fragments[i].y); - vertexCoordinateArray.addVertex(-bottomRight.x + fragments[i].x, -bottomRight.y + fragments[i].y); - vertexCoordinateArray.addVertex(-bottomRight.x + fragments[i].x, -bottomRight.y + fragments[i].y); - vertexCoordinateArray.addVertex(bottomLeft.x + fragments[i].x, bottomLeft.y + fragments[i].y); - vertexCoordinateArray.addVertex(bottomRight.x + fragments[i].x, bottomRight.y + fragments[i].y); - - QOpenGLRect src(fragments[i].sourceLeft * dx, fragments[i].sourceTop * dy, - (fragments[i].sourceLeft + fragments[i].width) * dx, - (fragments[i].sourceTop + fragments[i].height) * dy); - - textureCoordinateArray.addVertex(src.right, src.bottom); - textureCoordinateArray.addVertex(src.right, src.top); - textureCoordinateArray.addVertex(src.left, src.top); - textureCoordinateArray.addVertex(src.left, src.top); - textureCoordinateArray.addVertex(src.left, src.bottom); - textureCoordinateArray.addVertex(src.right, src.bottom); - - qreal opacity = fragments[i].opacity * q->state()->opacity; - opacityArray << opacity << opacity << opacity << opacity << opacity << opacity; - allOpaque &= (opacity >= 0.99f); - } - - transferMode(ImageOpacityArrayDrawingMode); - - GLenum filterMode = q->state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST; - updateTexture(QT_IMAGE_TEXTURE_UNIT, pixmap, GL_CLAMP_TO_EDGE, filterMode); - - bool isBitmap = pixmap.isQBitmap(); - bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque; - - // Setup for texture drawing - currentBrush = noBrush; - shaderManager->setSrcPixelType(isBitmap ? QOpenGLEngineShaderManager::PatternSrc - : QOpenGLEngineShaderManager::ImageSrc); - if (prepareForDraw(isOpaque)) - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT); - - if (isBitmap) { - QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity); - shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::PatternColor), col); - } - - funcs.glDrawArrays(GL_TRIANGLES, 0, 6 * fragmentCount); -} - -bool QOpenGL2PaintEngineEx::begin(QPaintDevice *pdev) -{ - Q_D(QOpenGL2PaintEngineEx); - - Q_ASSERT(pdev->devType() == QInternal::OpenGL); - d->device = static_cast<QOpenGLPaintDevice*>(pdev); - - if (!d->device) - return false; - - d->device->ensureActiveTarget(); - - if (d->device->context() != QOpenGLContext::currentContext() || !d->device->context()) { - qWarning("QPainter::begin(): QOpenGLPaintDevice's context needs to be current"); - return false; - } - - if (d->ctx != QOpenGLContext::currentContext() - || (d->ctx && QOpenGLContext::currentContext() && d->ctx->format() != QOpenGLContext::currentContext()->format())) { - d->vertexBuffer.destroy(); - d->texCoordBuffer.destroy(); - d->opacityBuffer.destroy(); - d->indexBuffer.destroy(); - d->vao.destroy(); - } - - d->ctx = QOpenGLContext::currentContext(); - d->ctx->d_func()->active_engine = this; - - QOpenGLPaintDevicePrivate::get(d->device)->beginPaint(); - - d->funcs.initializeOpenGLFunctions(); - - // Generate a new Vertex Array Object if we don't have one already. We can - // only hit the VAO-based path when using a core profile context. This is - // because while non-core contexts can support VAOs via extensions, legacy - // components like the QtOpenGL module do not know about VAOs. There are - // still tests for QGL-QOpenGL paint engine interoperability, so keep the - // status quo for now, and avoid introducing a VAO in non-core contexts. - const bool needsVAO = d->ctx->format().profile() == QSurfaceFormat::CoreProfile - && d->ctx->format().version() >= qMakePair(3, 2); - if (needsVAO && !d->vao.isCreated()) { - bool created = d->vao.create(); - - // If we managed to create it then we have a profile that supports VAOs - if (created) { - d->vao.bind(); - - // Generate a new Vertex Buffer Object if we don't have one already - if (!d->vertexBuffer.isCreated()) { - d->vertexBuffer.create(); - // Set its usage to StreamDraw, we will use this buffer only a few times before refilling it - d->vertexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); - } - if (!d->texCoordBuffer.isCreated()) { - d->texCoordBuffer.create(); - d->texCoordBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); - } - if (!d->opacityBuffer.isCreated()) { - d->opacityBuffer.create(); - d->opacityBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); - } - if (!d->indexBuffer.isCreated()) { - d->indexBuffer.create(); - d->indexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); - } - } - } - - for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) - d->vertexAttributeArraysEnabledState[i] = false; - - const QSize sz = d->device->size(); - d->width = sz.width(); - d->height = sz.height(); - d->mode = BrushDrawingMode; - d->brushTextureDirty = true; - d->brushUniformsDirty = true; - d->matrixUniformDirty = true; - d->matrixDirty = true; - d->compositionModeDirty = true; - d->opacityUniformDirty = true; - d->needsSync = true; - d->useSystemClip = !systemClip().isEmpty(); - d->currentBrush = QBrush(); - - d->dirtyStencilRegion = QRect(0, 0, d->width, d->height); - d->stencilClean = true; - - d->shaderManager = new QOpenGLEngineShaderManager(d->ctx); - - d->funcs.glDisable(GL_STENCIL_TEST); - d->funcs.glDisable(GL_DEPTH_TEST); - d->funcs.glDisable(GL_SCISSOR_TEST); - - d->glyphCacheFormat = QFontEngine::Format_A8; - -#ifndef QT_OPENGL_ES_2 - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - d->funcs.glDisable(GL_MULTISAMPLE); - d->glyphCacheFormat = QFontEngine::Format_A32; - d->multisamplingAlwaysEnabled = false; - } else -#endif // QT_OPENGL_ES_2 - { - // OpenGL ES can't switch MSAA off, so if the gl paint device is - // multisampled, it's always multisampled. - d->multisamplingAlwaysEnabled = d->device->context()->format().samples() > 1; - } - - return true; -} - -bool QOpenGL2PaintEngineEx::end() -{ - Q_D(QOpenGL2PaintEngineEx); - - QOpenGLPaintDevicePrivate::get(d->device)->endPaint(); - - QOpenGLContext *ctx = d->ctx; - d->funcs.glUseProgram(0); - d->transferMode(BrushDrawingMode); - - ctx->d_func()->active_engine = nullptr; - - d->resetGLState(); - - delete d->shaderManager; - d->shaderManager = nullptr; - d->currentBrush = QBrush(); - -#ifdef QT_OPENGL_CACHE_AS_VBOS - if (!d->unusedVBOSToClean.isEmpty()) { - glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData()); - d->unusedVBOSToClean.clear(); - } - if (!d->unusedIBOSToClean.isEmpty()) { - glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData()); - d->unusedIBOSToClean.clear(); - } -#endif - - return false; -} - -void QOpenGL2PaintEngineEx::ensureActive() -{ - Q_D(QOpenGL2PaintEngineEx); - QOpenGLContext *ctx = d->ctx; - - if (d->vao.isCreated()) - d->vao.bind(); - - if (isActive() && ctx->d_func()->active_engine != this) { - ctx->d_func()->active_engine = this; - d->needsSync = true; - } - - if (d->needsSync) { - d->device->ensureActiveTarget(); - - d->transferMode(BrushDrawingMode); - d->funcs.glViewport(0, 0, d->width, d->height); - d->needsSync = false; - d->shaderManager->setDirty(); - d->syncGlState(); - for (int i = 0; i < 3; ++i) - d->vertexAttribPointers[i] = (GLfloat*)-1; // Assume the pointers are clobbered - setState(state()); - } -} - -void QOpenGL2PaintEngineExPrivate::updateClipScissorTest() -{ - Q_Q(QOpenGL2PaintEngineEx); - if (q->state()->clipTestEnabled) { - funcs.glEnable(GL_STENCIL_TEST); - funcs.glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT); - } else { - funcs.glDisable(GL_STENCIL_TEST); - funcs.glStencilFunc(GL_ALWAYS, 0, 0xff); - } - -#ifdef QT_GL_NO_SCISSOR_TEST - currentScissorBounds = QRect(0, 0, width, height); -#else - QRect bounds = q->state()->rectangleClip; - if (!q->state()->clipEnabled) { - if (useSystemClip) - bounds = systemClip.boundingRect(); - else - bounds = QRect(0, 0, width, height); - } else { - if (useSystemClip) - bounds = bounds.intersected(systemClip.boundingRect()); - else - bounds = bounds.intersected(QRect(0, 0, width, height)); - } - - currentScissorBounds = bounds; - - if (bounds == QRect(0, 0, width, height)) { - funcs.glDisable(GL_SCISSOR_TEST); - } else { - funcs.glEnable(GL_SCISSOR_TEST); - setScissor(bounds); - } -#endif -} - -void QOpenGL2PaintEngineExPrivate::setScissor(const QRect &rect) -{ - const int left = rect.left(); - const int width = rect.width(); - int bottom = height - (rect.top() + rect.height()); - if (device->paintFlipped()) { - bottom = rect.top(); - } - const int height = rect.height(); - - funcs.glScissor(left, bottom, width, height); -} - -void QOpenGL2PaintEngineEx::clipEnabledChanged() -{ - Q_D(QOpenGL2PaintEngineEx); - - state()->clipChanged = true; - - if (painter()->hasClipping()) - d->regenerateClip(); - else - d->systemStateChanged(); -} - -void QOpenGL2PaintEngineExPrivate::clearClip(uint value) -{ - dirtyStencilRegion -= currentScissorBounds; - - funcs.glStencilMask(0xff); - funcs.glClearStencil(value); - funcs.glClear(GL_STENCIL_BUFFER_BIT); - funcs.glStencilMask(0x0); - - q->state()->needsClipBufferClear = false; -} - -void QOpenGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) -{ - transferMode(BrushDrawingMode); - - if (snapToPixelGrid) { - snapToPixelGrid = false; - matrixDirty = true; - } - - if (matrixDirty) - updateMatrix(); - - stencilClean = false; - - const bool singlePass = !path.hasWindingFill() - && (((q->state()->currentClip == maxClip - 1) && q->state()->clipTestEnabled) - || q->state()->needsClipBufferClear); - const uint referenceClipValue = q->state()->needsClipBufferClear ? 1 : q->state()->currentClip; - - if (q->state()->needsClipBufferClear) - clearClip(1); - - if (path.isEmpty()) { - funcs.glEnable(GL_STENCIL_TEST); - funcs.glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT); - return; - } - - if (q->state()->clipTestEnabled) - funcs.glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT); - else - funcs.glStencilFunc(GL_ALWAYS, 0, 0xff); - - vertexCoordinateArray.clear(); - vertexCoordinateArray.addPath(path, inverseScale, false); - - if (!singlePass) - fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); - - funcs.glColorMask(false, false, false, false); - funcs.glEnable(GL_STENCIL_TEST); - useSimpleShader(); - - if (singlePass) { - // Under these conditions we can set the new stencil value in a single - // pass, by using the current value and the "new value" as the toggles - - funcs.glStencilFunc(GL_LEQUAL, referenceClipValue, ~GL_STENCIL_HIGH_BIT); - funcs.glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT); - funcs.glStencilMask(value ^ referenceClipValue); - - drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN); - } else { - funcs.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); - funcs.glStencilMask(0xff); - - if (!q->state()->clipTestEnabled && path.hasWindingFill()) { - // Pass when any clip bit is set, set high bit - funcs.glStencilFunc(GL_NOTEQUAL, GL_STENCIL_HIGH_BIT, ~GL_STENCIL_HIGH_BIT); - composite(vertexCoordinateArray.boundingRect()); - } - - // Pass when high bit is set, replace stencil value with new clip value - funcs.glStencilFunc(GL_NOTEQUAL, value, GL_STENCIL_HIGH_BIT); - - composite(vertexCoordinateArray.boundingRect()); - } - - funcs.glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT); - funcs.glStencilMask(0); - - funcs.glColorMask(true, true, true, true); -} - -void QOpenGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) -{ -// qDebug("QOpenGL2PaintEngineEx::clip()"); - Q_D(QOpenGL2PaintEngineEx); - - state()->clipChanged = true; - - ensureActive(); - - if (op == Qt::ReplaceClip) { - op = Qt::IntersectClip; - if (d->hasClipOperations()) { - d->systemStateChanged(); - state()->canRestoreClip = false; - } - } - -#ifndef QT_GL_NO_SCISSOR_TEST - if (!path.isEmpty() && op == Qt::IntersectClip && (path.shape() == QVectorPath::RectangleHint)) { - const QPointF* const points = reinterpret_cast<const QPointF*>(path.points()); - QRectF rect(points[0], points[2]); - - if (state()->matrix.type() <= QTransform::TxScale - || (state()->matrix.type() == QTransform::TxRotate - && qFuzzyIsNull(state()->matrix.m11()) - && qFuzzyIsNull(state()->matrix.m22()))) - { - state()->rectangleClip = state()->rectangleClip.intersected(state()->matrix.mapRect(rect).toRect()); - d->updateClipScissorTest(); - return; - } - } -#endif - - const QRect pathRect = state()->matrix.mapRect(path.controlPointRect()).toAlignedRect(); - - switch (op) { - case Qt::NoClip: - if (d->useSystemClip) { - state()->clipTestEnabled = true; - state()->currentClip = 1; - } else { - state()->clipTestEnabled = false; - } - state()->rectangleClip = QRect(0, 0, d->width, d->height); - state()->canRestoreClip = false; - d->updateClipScissorTest(); - break; - case Qt::IntersectClip: - state()->rectangleClip = state()->rectangleClip.intersected(pathRect); - d->updateClipScissorTest(); - d->resetClipIfNeeded(); - ++d->maxClip; - d->writeClip(path, d->maxClip); - state()->currentClip = d->maxClip; - state()->clipTestEnabled = true; - break; - default: - break; - } -} - -void QOpenGL2PaintEngineExPrivate::regenerateClip() -{ - systemStateChanged(); - replayClipOperations(); -} - -void QOpenGL2PaintEngineExPrivate::systemStateChanged() -{ - Q_Q(QOpenGL2PaintEngineEx); - - q->state()->clipChanged = true; - - if (systemClip.isEmpty()) { - useSystemClip = false; - } else { - if (q->paintDevice()->devType() == QInternal::Widget && currentClipDevice) { - //QWidgetPrivate *widgetPrivate = qt_widget_private(static_cast<QWidget *>(currentClipDevice)->window()); - //useSystemClip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter; - useSystemClip = true; - } else { - useSystemClip = true; - } - } - - q->state()->clipTestEnabled = false; - q->state()->needsClipBufferClear = true; - - q->state()->currentClip = 1; - maxClip = 1; - - q->state()->rectangleClip = useSystemClip ? systemClip.boundingRect() : QRect(0, 0, width, height); - updateClipScissorTest(); - - if (systemClip.rectCount() == 1) { - if (systemClip.boundingRect() == QRect(0, 0, width, height)) - useSystemClip = false; -#ifndef QT_GL_NO_SCISSOR_TEST - // scissoring takes care of the system clip - return; -#endif - } - - if (useSystemClip) { - clearClip(0); - - QPainterPath path; - path.addRegion(systemClip); - - q->state()->currentClip = 0; - writeClip(qtVectorPathForPath(q->state()->matrix.inverted().map(path)), 1); - q->state()->currentClip = 1; - q->state()->clipTestEnabled = true; - } -} - -void QOpenGL2PaintEngineEx::setState(QPainterState *new_state) -{ - // qDebug("QOpenGL2PaintEngineEx::setState()"); - - Q_D(QOpenGL2PaintEngineEx); - - QOpenGL2PaintEngineState *s = static_cast<QOpenGL2PaintEngineState *>(new_state); - QOpenGL2PaintEngineState *old_state = state(); - - QPaintEngineEx::setState(s); - - if (s->isNew) { - // Newly created state object. The call to setState() - // will either be followed by a call to begin(), or we are - // setting the state as part of a save(). - s->isNew = false; - return; - } - - // Setting the state as part of a restore(). - - if (old_state == s || old_state->renderHintsChanged) - renderHintsChanged(); - - if (old_state == s || old_state->matrixChanged) - d->matrixDirty = true; - - if (old_state == s || old_state->compositionModeChanged) - d->compositionModeDirty = true; - - if (old_state == s || old_state->opacityChanged) - d->opacityUniformDirty = true; - - if (old_state == s || old_state->clipChanged) { - if (old_state && old_state != s && old_state->canRestoreClip) { - d->updateClipScissorTest(); - d->funcs.glDepthFunc(GL_LEQUAL); - } else { - d->regenerateClip(); - } - } -} - -QPainterState *QOpenGL2PaintEngineEx::createState(QPainterState *orig) const -{ - if (orig) - const_cast<QOpenGL2PaintEngineEx *>(this)->ensureActive(); - - QOpenGL2PaintEngineState *s; - if (!orig) - s = new QOpenGL2PaintEngineState(); - else - s = new QOpenGL2PaintEngineState(*static_cast<QOpenGL2PaintEngineState *>(orig)); - - s->matrixChanged = false; - s->compositionModeChanged = false; - s->opacityChanged = false; - s->renderHintsChanged = false; - s->clipChanged = false; - - return s; -} - -QOpenGL2PaintEngineState::QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other) - : QPainterState(other) -{ - isNew = true; - needsClipBufferClear = other.needsClipBufferClear; - clipTestEnabled = other.clipTestEnabled; - currentClip = other.currentClip; - canRestoreClip = other.canRestoreClip; - rectangleClip = other.rectangleClip; -} - -QOpenGL2PaintEngineState::QOpenGL2PaintEngineState() -{ - isNew = true; - needsClipBufferClear = true; - clipTestEnabled = false; - canRestoreClip = true; -} - -QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState() -{ -} - -void QOpenGL2PaintEngineExPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled) -{ - Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT); - - if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled) - funcs.glDisableVertexAttribArray(arrayIndex); - - if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled) - funcs.glEnableVertexAttribArray(arrayIndex); - - vertexAttributeArraysEnabledState[arrayIndex] = enabled; -} - -void QOpenGL2PaintEngineExPrivate::syncGlState() -{ - for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) { - if (vertexAttributeArraysEnabledState[i]) - funcs.glEnableVertexAttribArray(i); - else - funcs.glDisableVertexAttribArray(i); - } -} - - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopenglpaintengine_p.h b/src/gui/opengl/qopenglpaintengine_p.h deleted file mode 100644 index 81f17572b2..0000000000 --- a/src/gui/opengl/qopenglpaintengine_p.h +++ /dev/null @@ -1,396 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLPAINTENGINE_P_H -#define QOPENGLPAINTENGINE_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/private/qtguiglobal_p.h> -#include <QDebug> - -#include <qopenglpaintdevice.h> - -#include <private/qpaintengineex_p.h> -#include <private/qopenglengineshadermanager_p.h> -#include <private/qopengl2pexvertexarray_p.h> -#include <private/qfontengine_p.h> -#include <private/qdatabuffer_p.h> -#include <private/qtriangulatingstroker_p.h> - -#include <private/qopenglextensions_p.h> - -#include <QOpenGLVertexArrayObject> -#include <QOpenGLBuffer> - -enum EngineMode { - ImageDrawingMode, - TextDrawingMode, - BrushDrawingMode, - ImageArrayDrawingMode, - ImageOpacityArrayDrawingMode -}; - -QT_BEGIN_NAMESPACE - -#define GL_STENCIL_HIGH_BIT GLuint(0x80) -#define QT_UNKNOWN_TEXTURE_UNIT GLuint(-1) -#define QT_DEFAULT_TEXTURE_UNIT GLuint(0) -#define QT_BRUSH_TEXTURE_UNIT GLuint(0) -#define QT_IMAGE_TEXTURE_UNIT GLuint(0) //Can be the same as brush texture unit -#define QT_MASK_TEXTURE_UNIT GLuint(1) -#define QT_BACKGROUND_TEXTURE_UNIT GLuint(2) - -class QOpenGL2PaintEngineExPrivate; - -class QOpenGL2PaintEngineState : public QPainterState -{ -public: - QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other); - QOpenGL2PaintEngineState(); - ~QOpenGL2PaintEngineState(); - - uint isNew : 1; - uint needsClipBufferClear : 1; - uint clipTestEnabled : 1; - uint canRestoreClip : 1; - uint matrixChanged : 1; - uint compositionModeChanged : 1; - uint opacityChanged : 1; - uint renderHintsChanged : 1; - uint clipChanged : 1; - uint currentClip : 8; - - QRect rectangleClip; -}; - -class Q_GUI_EXPORT QOpenGL2PaintEngineEx : public QPaintEngineEx -{ - Q_DECLARE_PRIVATE(QOpenGL2PaintEngineEx) -public: - QOpenGL2PaintEngineEx(); - ~QOpenGL2PaintEngineEx(); - - bool begin(QPaintDevice *device) override; - void ensureActive(); - bool end() override; - - virtual void clipEnabledChanged() override; - virtual void penChanged() override; - virtual void brushChanged() override; - virtual void brushOriginChanged() override; - virtual void opacityChanged() override; - virtual void compositionModeChanged() override; - virtual void renderHintsChanged() override; - virtual void transformChanged() override; - - virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override; - virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, - QPainter::PixmapFragmentHints hints) override; - virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, - Qt::ImageConversionFlags flags = Qt::AutoColor) override; - virtual void drawTextItem(const QPointF &p, const QTextItem &textItem) override; - virtual void fill(const QVectorPath &path, const QBrush &brush) override; - virtual void stroke(const QVectorPath &path, const QPen &pen) override; - virtual void clip(const QVectorPath &path, Qt::ClipOperation op) override; - - virtual void drawStaticTextItem(QStaticTextItem *textItem) override; - - bool drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); - - Type type() const override { return OpenGL2; } - - virtual void setState(QPainterState *s) override; - virtual QPainterState *createState(QPainterState *orig) const override; - inline QOpenGL2PaintEngineState *state() { - return static_cast<QOpenGL2PaintEngineState *>(QPaintEngineEx::state()); - } - inline const QOpenGL2PaintEngineState *state() const { - return static_cast<const QOpenGL2PaintEngineState *>(QPaintEngineEx::state()); - } - - void beginNativePainting() override; - void endNativePainting() override; - - void invalidateState(); - - void setRenderTextActive(bool); - - bool isNativePaintingActive() const; - bool requiresPretransformedGlyphPositions(QFontEngine *, const QTransform &) const override { return false; } - bool shouldDrawCachedGlyphs(QFontEngine *, const QTransform &) const override; - -private: - Q_DISABLE_COPY_MOVE(QOpenGL2PaintEngineEx) - - friend class QOpenGLEngineShaderManager; -}; - -// This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's -// all the GL2 engine uses: -#define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3 - -class QOpenGL2PaintEngineExPrivate : public QPaintEngineExPrivate -{ - Q_DECLARE_PUBLIC(QOpenGL2PaintEngineEx) -public: - enum StencilFillMode { - OddEvenFillMode, - WindingFillMode, - TriStripStrokeFillMode - }; - - QOpenGL2PaintEngineExPrivate(QOpenGL2PaintEngineEx *q_ptr) : - q(q_ptr), - shaderManager(nullptr), - width(0), height(0), - ctx(nullptr), - useSystemClip(true), - elementIndicesVBOId(0), - opacityArray(0), - snapToPixelGrid(false), - nativePaintingActive(false), - inverseScale(1), - lastTextureUnitUsed(QT_UNKNOWN_TEXTURE_UNIT), - vertexBuffer(QOpenGLBuffer::VertexBuffer), - texCoordBuffer(QOpenGLBuffer::VertexBuffer), - opacityBuffer(QOpenGLBuffer::VertexBuffer), - indexBuffer(QOpenGLBuffer::IndexBuffer) - { } - - ~QOpenGL2PaintEngineExPrivate(); - - void updateBrushTexture(); - void updateBrushUniforms(); - void updateMatrix(); - void updateCompositionMode(); - - enum TextureUpdateMode { UpdateIfNeeded, ForceUpdate }; - template<typename T> - void updateTexture(GLenum textureUnit, const T &texture, GLenum wrapMode, GLenum filterMode, TextureUpdateMode updateMode = UpdateIfNeeded); - template<typename T> - GLuint bindTexture(const T &texture); - void activateTextureUnit(GLenum textureUnit); - - void resetGLState(); - - // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points, - // however writeClip can also be thought of as en entry point as it does similar things. - void fill(const QVectorPath &path); - void stroke(const QVectorPath &path, const QPen &pen); - void drawTexture(const QOpenGLRect& dest, const QOpenGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); - void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, - QPainter::PixmapFragmentHints hints); - void drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat, QStaticTextItem *staticTextItem); - - // Calls glVertexAttributePointer if the pointer has changed - inline void uploadData(unsigned int arrayIndex, const GLfloat *data, GLuint count); - inline bool uploadIndexData(const void *data, GLenum indexValueType, GLuint count); - - // draws whatever is in the vertex array: - void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive); - void drawVertexArrays(QOpenGL2PEXVertexArray &vertexArray, GLenum primitive) { - drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive); - } - - // Composites the bounding rect onto dest buffer: - void composite(const QOpenGLRect& boundingRect); - - // Calls drawVertexArrays to render into stencil buffer: - void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QOpenGLRect &bounds, StencilFillMode mode); - void fillStencilWithVertexArray(QOpenGL2PEXVertexArray& vertexArray, bool useWindingFill) { - fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(), - vertexArray.boundingRect(), - useWindingFill ? WindingFillMode : OddEvenFillMode); - } - - void setBrush(const QBrush& brush); - void transferMode(EngineMode newMode); - bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed - bool prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache); - inline void useSimpleShader(); - inline GLuint location(const QOpenGLEngineShaderManager::Uniform uniform) { - return shaderManager->getUniformLocation(uniform); - } - - void clearClip(uint value); - void writeClip(const QVectorPath &path, uint value); - void resetClipIfNeeded(); - - void updateClipScissorTest(); - void setScissor(const QRect &rect); - void regenerateClip(); - void systemStateChanged() override; - - void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true); - void syncGlState(); - - static QOpenGLEngineShaderManager* shaderManagerForEngine(QOpenGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; } - static QOpenGL2PaintEngineExPrivate *getData(QOpenGL2PaintEngineEx *engine) { return engine->d_func(); } - static void cleanupVectorPath(QPaintEngineEx *engine, void *data); - - QOpenGLExtensions funcs; - - QOpenGL2PaintEngineEx* q; - QOpenGLEngineShaderManager* shaderManager; - QOpenGLPaintDevice* device; - int width, height; - QOpenGLContext *ctx; - EngineMode mode; - QFontEngine::GlyphFormat glyphCacheFormat; - - bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT]; - - // Dirty flags - bool matrixDirty; // Implies matrix uniforms are also dirty - bool compositionModeDirty; - bool brushTextureDirty; - bool brushUniformsDirty; - bool opacityUniformDirty; - bool matrixUniformDirty; - - bool stencilClean; // Has the stencil not been used for clipping so far? - bool useSystemClip; - QRegion dirtyStencilRegion; - QRect currentScissorBounds; - uint maxClip; - - QBrush currentBrush; // May not be the state's brush! - const QBrush noBrush; - - QImage currentBrushImage; - - QOpenGL2PEXVertexArray vertexCoordinateArray; - QOpenGL2PEXVertexArray textureCoordinateArray; - QVector<GLushort> elementIndices; - GLuint elementIndicesVBOId; - QDataBuffer<GLfloat> opacityArray; - GLfloat staticVertexCoordinateArray[8]; - GLfloat staticTextureCoordinateArray[8]; - - bool snapToPixelGrid; - bool nativePaintingActive; - GLfloat pmvMatrix[3][3]; - GLfloat inverseScale; - - GLenum lastTextureUnitUsed; - GLuint lastTextureUsed; - - QOpenGLVertexArrayObject vao; - QOpenGLBuffer vertexBuffer; - QOpenGLBuffer texCoordBuffer; - QOpenGLBuffer opacityBuffer; - QOpenGLBuffer indexBuffer; - - bool needsSync; - bool multisamplingAlwaysEnabled; - - QTriangulatingStroker stroker; - QDashedStrokeProcessor dasher; - - QVector<GLuint> unusedVBOSToClean; - QVector<GLuint> unusedIBOSToClean; - - const GLfloat *vertexAttribPointers[3]; -}; - - -void QOpenGL2PaintEngineExPrivate::uploadData(unsigned int arrayIndex, const GLfloat *data, GLuint count) -{ - Q_ASSERT(arrayIndex < 3); - - // If a vertex array object is created we have a profile that supports them - // and we will upload the data via a QOpenGLBuffer. Otherwise we will use - // the legacy way of uploading the data via glVertexAttribPointer. - if (vao.isCreated()) { - if (arrayIndex == QT_VERTEX_COORDS_ATTR) { - vertexBuffer.bind(); - vertexBuffer.allocate(data, count * sizeof(float)); - } - if (arrayIndex == QT_TEXTURE_COORDS_ATTR) { - texCoordBuffer.bind(); - texCoordBuffer.allocate(data, count * sizeof(float)); - } - if (arrayIndex == QT_OPACITY_ATTR) { - opacityBuffer.bind(); - opacityBuffer.allocate(data, count * sizeof(float)); - } - if (arrayIndex == QT_OPACITY_ATTR) - funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, nullptr); - else - funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, nullptr); - } else { - // If we already uploaded the data we don't have to do it again - if (data == vertexAttribPointers[arrayIndex]) - return; - - // Store the data in cache and upload it to the graphics card. - vertexAttribPointers[arrayIndex] = data; - if (arrayIndex == QT_OPACITY_ATTR) - funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, data); - else - funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, data); - } -} - -bool QOpenGL2PaintEngineExPrivate::uploadIndexData(const void *data, GLenum indexValueType, GLuint count) -{ - // Follow the uploadData() logic: VBOs are used only when VAO support is available. - // Otherwise the legacy client-side pointer path is used. - if (vao.isCreated()) { - Q_ASSERT(indexValueType == GL_UNSIGNED_SHORT || indexValueType == GL_UNSIGNED_INT); - indexBuffer.bind(); - indexBuffer.allocate(data, count * (indexValueType == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32))); - return true; - } - return false; -} - -QT_END_NAMESPACE - -#endif diff --git a/src/gui/opengl/qopenglpixeltransferoptions.cpp b/src/gui/opengl/qopenglpixeltransferoptions.cpp deleted file mode 100644 index b0d953d76b..0000000000 --- a/src/gui/opengl/qopenglpixeltransferoptions.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopenglpixeltransferoptions.h" -#include <QSharedData> - -QT_BEGIN_NAMESPACE - -/*! - * \class QOpenGLPixelTransferOptions - * - * \brief The QOpenGLPixelTransferOptions class describes the pixel storage - * modes that affect the unpacking of pixels during texture upload. - */ - -/*! - * \fn QOpenGLPixelTransferOptions & QOpenGLPixelTransferOptions::operator=(QOpenGLPixelTransferOptions &&other) - * \internal - */ - -/*! - * \fn void QOpenGLPixelTransferOptions::swap(QOpenGLPixelTransferOptions &other) - * \internal - */ - -class QOpenGLPixelTransferOptionsData : public QSharedData -{ -public: - QOpenGLPixelTransferOptionsData() - : alignment(4) - , skipImages(0) - , skipRows(0) - , skipPixels(0) - , imageHeight(0) - , rowLength(0) - , lsbFirst(false) - , swapBytes(false) - {} - - int alignment; - int skipImages; - int skipRows; - int skipPixels; - int imageHeight; - int rowLength; - bool lsbFirst; - bool swapBytes; -}; - -/*! - * Constructs a new QOpenGLPixelTransferOptions instance with the default settings. - */ -QOpenGLPixelTransferOptions::QOpenGLPixelTransferOptions() - : data(new QOpenGLPixelTransferOptionsData) -{ -} - -/*! - * \internal - */ -QOpenGLPixelTransferOptions::QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &rhs) - : data(rhs.data) -{ -} - -/*! - * \internal - */ -QOpenGLPixelTransferOptions &QOpenGLPixelTransferOptions::operator=(const QOpenGLPixelTransferOptions &rhs) -{ - if (this != &rhs) - data.operator=(rhs.data); - return *this; -} - -/*! - * Destructor. - */ -QOpenGLPixelTransferOptions::~QOpenGLPixelTransferOptions() -{ -} - -/*! - * Sets the \a alignment requirements for each pixel row. Corresponds to \c GL_UNPACK_ALIGNMENT. - * The default value is 4, as specified by OpenGL. - */ -void QOpenGLPixelTransferOptions::setAlignment(int alignment) -{ - data->alignment = alignment; -} - -/*! - * \return the current alignment requirement for each pixel row. - */ -int QOpenGLPixelTransferOptions::alignment() const -{ - return data->alignment; -} - -/*! - * Sets the number of images that are skipped to \a skipImages. - * Corresponds to \c GL_UNPACK_SKIP_IMAGES. Equivalent to incrementing the pointer - * passed to QOpenGLTexture::setData(). The default value is 0. - */ -void QOpenGLPixelTransferOptions::setSkipImages(int skipImages) -{ - data->skipImages = skipImages; -} - -/*! - * \return the number of images that are skipped. - */ -int QOpenGLPixelTransferOptions::skipImages() const -{ - return data->skipImages; -} - -/*! - * Sets the number of rows that are skipped to \a skipRows. - * Corresponds to \c GL_UNPACK_SKIP_ROWS. Equivalent to incrementing the pointer - * passed to QOpenGLTexture::setData(). The default value is 0. - */ -void QOpenGLPixelTransferOptions::setSkipRows(int skipRows) -{ - data->skipRows = skipRows; -} - -/*! - * \return the number of rows that are skipped. - */ -int QOpenGLPixelTransferOptions::skipRows() const -{ - return data->skipRows; -} - -/*! - * Sets the number of pixels that are skipped to \a skipPixels. - * Corresponds to \c GL_UNPACK_SKIP_PIXELS. Equivalent to incrementing the pointer - * passed to QOpenGLTexture::setData(). The default value is 0. - */ -void QOpenGLPixelTransferOptions::setSkipPixels(int skipPixels) -{ - data->skipPixels = skipPixels; -} - -/*! - * \return the number of pixels that are skipped. - */ -int QOpenGLPixelTransferOptions::skipPixels() const -{ - return data->skipPixels; -} - -/*! - * Sets the image height for 3D textures to \a imageHeight. - * Corresponds to \c GL_UNPACK_IMAGE_HEIGHT. - * The default value is 0. - */ -void QOpenGLPixelTransferOptions::setImageHeight(int imageHeight) -{ - data->imageHeight = imageHeight; -} - -/*! - * \return the currently set image height. - */ -int QOpenGLPixelTransferOptions::imageHeight() const -{ - return data->imageHeight; -} - -/*! - * Sets the number of pixels in a row to \a rowLength. - * Corresponds to \c GL_UNPACK_ROW_LENGTH. - * The default value is 0. - */ -void QOpenGLPixelTransferOptions::setRowLength(int rowLength) -{ - data->rowLength = rowLength; -} - -/*! - * \return the currently set row length. - */ -int QOpenGLPixelTransferOptions::rowLength() const -{ - return data->rowLength; -} - -/*! - * \a lsbFirst specifies if bits within a byte are ordered from least to most significat. - * The default value is \c false, meaning that the first bit in each byte is the - * most significant one. This is significant for bitmap data only. - * Corresponds to \c GL_UNPACK_LSB_FIRST. - */ -void QOpenGLPixelTransferOptions::setLeastSignificantByteFirst(bool lsbFirst) -{ - data->lsbFirst = lsbFirst; -} - -/*! - * \return \c true if bits within a byte are ordered from least to most significant. - */ -bool QOpenGLPixelTransferOptions::isLeastSignificantBitFirst() const -{ - return data->lsbFirst; -} - -/*! - * \a swapBytes specifies if the byte ordering for multibyte components is reversed. - * The default value is \c false. - * Corresponds to \c GL_UNPACK_SWAP_BYTES. - */ -void QOpenGLPixelTransferOptions::setSwapBytesEnabled(bool swapBytes) -{ - data->swapBytes = swapBytes; -} - -/*! - * \return \c true if the byte ordering for multibyte components is reversed. - */ -bool QOpenGLPixelTransferOptions::isSwapBytesEnabled() const -{ - return data->swapBytes; -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopenglpixeltransferoptions.h b/src/gui/opengl/qopenglpixeltransferoptions.h deleted file mode 100644 index 195543ae90..0000000000 --- a/src/gui/opengl/qopenglpixeltransferoptions.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLPIXELUPLOADOPTIONS_H -#define QOPENGLPIXELUPLOADOPTIONS_H - -#include <QtGui/qtguiglobal.h> - -#if !defined(QT_NO_OPENGL) - -#include <QtCore/QSharedDataPointer> - -QT_BEGIN_NAMESPACE - -class QOpenGLPixelTransferOptionsData; - -class Q_GUI_EXPORT QOpenGLPixelTransferOptions -{ -public: - QOpenGLPixelTransferOptions(); - QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &); - QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) noexcept - { swap(other); return *this; } - QOpenGLPixelTransferOptions &operator=(const QOpenGLPixelTransferOptions &); - ~QOpenGLPixelTransferOptions(); - - void swap(QOpenGLPixelTransferOptions &other) noexcept - { data.swap(other.data); } - - void setAlignment(int alignment); - int alignment() const; - - void setSkipImages(int skipImages); - int skipImages() const; - - void setSkipRows(int skipRows); - int skipRows() const; - - void setSkipPixels(int skipPixels); - int skipPixels() const; - - void setImageHeight(int imageHeight); - int imageHeight() const; - - void setRowLength(int rowLength); - int rowLength() const; - - void setLeastSignificantByteFirst(bool lsbFirst); - bool isLeastSignificantBitFirst() const; - - void setSwapBytesEnabled(bool swapBytes); - bool isSwapBytesEnabled() const; - -private: - QSharedDataPointer<QOpenGLPixelTransferOptionsData> data; -}; - -Q_DECLARE_SHARED(QOpenGLPixelTransferOptions) - -QT_END_NAMESPACE - -#endif // QT_NO_OPENGL - -#endif // QOPENGLPIXELUPLOADOPTIONS_H diff --git a/src/gui/opengl/qopenglqueryhelper_p.h b/src/gui/opengl/qopenglqueryhelper_p.h deleted file mode 100644 index ad91ca9f96..0000000000 --- a/src/gui/opengl/qopenglqueryhelper_p.h +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLQUERYHELPER_P_H -#define QOPENGLQUERYHELPER_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/private/qtguiglobal_p.h> - -#if !defined(QT_OPENGL_ES_2) - -#include <QtGui/QOpenGLContext> - -QT_BEGIN_NAMESPACE - -// Helper class used by QOpenGLTimerQuery and later will be used by -// QOpenGLOcclusionQuery -class QOpenGLQueryHelper -{ -public: - QOpenGLQueryHelper(QOpenGLContext *context) - : GetQueryObjectuiv(nullptr), - GetQueryObjectiv(nullptr), - GetQueryiv(nullptr), - EndQuery(nullptr), - BeginQuery(nullptr), - IsQuery(nullptr), - DeleteQueries(nullptr), - GenQueries(nullptr), - GetInteger64v(nullptr), - GetQueryObjectui64v(nullptr), - GetQueryObjecti64v(nullptr), - QueryCounter(nullptr) - { - Q_ASSERT(context); - - // Core in OpenGL >=1.5 - GetQueryObjectuiv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint *)>(context->getProcAddress("glGetQueryObjectuiv")); - GetQueryObjectiv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint *)>(context->getProcAddress("glGetQueryObjectiv")); - GetQueryiv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLenum , GLint *)>(context->getProcAddress("glGetQueryiv")); - EndQuery = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum )>(context->getProcAddress("glEndQuery")); - BeginQuery = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLuint )>(context->getProcAddress("glBeginQuery")); - IsQuery = reinterpret_cast<GLboolean (QOPENGLF_APIENTRYP)(GLuint )>(context->getProcAddress("glIsQuery")); - DeleteQueries = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *)>(context->getProcAddress("glDeleteQueries")); - GenQueries = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , GLuint *)>(context->getProcAddress("glGenQueries")); - - // Core in OpenGL >=3.2 - GetInteger64v = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint64 *)>(context->getProcAddress("glGetInteger64v")); - - // Core in OpenGL >=3.3 / ARB_timer_query - GetQueryObjectui64v = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint64 *)>(context->getProcAddress("glGetQueryObjectui64v")); - GetQueryObjecti64v = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint64 *)>(context->getProcAddress("glGetQueryObjecti64v")); - QueryCounter = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum )>(context->getProcAddress("glQueryCounter")); - } - - inline void glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) - { - GetQueryObjectuiv(id, pname, params); - } - - inline void glGetQueryObjectiv(GLuint id, GLenum pname, GLint *params) - { - GetQueryObjectiv(id, pname, params); - } - - inline void glGetQueryiv(GLenum target, GLenum pname, GLint *params) - { - GetQueryiv(target, pname, params); - } - - inline void glEndQuery(GLenum target) - { - EndQuery(target); - } - - inline void glBeginQuery(GLenum target, GLuint id) - { - BeginQuery(target, id); - } - - inline GLboolean glIsQuery(GLuint id) - { - return IsQuery(id); - } - - inline void glDeleteQueries(GLsizei n, const GLuint *ids) - { - DeleteQueries(n, ids); - } - - inline void glGenQueries(GLsizei n, GLuint *ids) - { - GenQueries(n, ids); - } - - inline void glGetInteger64v(GLenum pname, GLint64 *params) - { - GetInteger64v(pname, params); - } - - inline void glGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params) - { - GetQueryObjectui64v(id, pname, params); - } - - inline void glGetQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params) - { - GetQueryObjecti64v(id, pname, params); - } - - inline void glQueryCounter(GLuint id, GLenum target) - { - QueryCounter(id, target); - } - -private: - // Core in OpenGL >=1.5 - void (QOPENGLF_APIENTRYP GetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params); - void (QOPENGLF_APIENTRYP GetQueryObjectiv)(GLuint id, GLenum pname, GLint *params); - void (QOPENGLF_APIENTRYP GetQueryiv)(GLenum target, GLenum pname, GLint *params); - void (QOPENGLF_APIENTRYP EndQuery)(GLenum target); - void (QOPENGLF_APIENTRYP BeginQuery)(GLenum target, GLuint id); - GLboolean (QOPENGLF_APIENTRYP IsQuery)(GLuint id); - void (QOPENGLF_APIENTRYP DeleteQueries)(GLsizei n, const GLuint *ids); - void (QOPENGLF_APIENTRYP GenQueries)(GLsizei n, GLuint *ids); - - // Core in OpenGL >=3.2 - void (QOPENGLF_APIENTRYP GetInteger64v)(GLenum pname, GLint64 *params); - - // Core in OpenGL >=3.3 and provided by ARB_timer_query - void (QOPENGLF_APIENTRYP GetQueryObjectui64v)(GLuint id, GLenum pname, GLuint64 *params); - void (QOPENGLF_APIENTRYP GetQueryObjecti64v)(GLuint id, GLenum pname, GLint64 *params); - void (QOPENGLF_APIENTRYP QueryCounter)(GLuint id, GLenum target); -}; - -QT_END_NAMESPACE - -#endif - -#endif // QOPENGLQUERYHELPER_P_H diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp deleted file mode 100644 index cf4a8dee8d..0000000000 --- a/src/gui/opengl/qopengltexture.cpp +++ /dev/null @@ -1,4986 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopengltexture.h" -#include "qopengltexture_p.h" -#include "qopengltexturehelper_p.h" -#include "qopenglfunctions.h" -#include <QtGui/qcolor.h> -#include <QtGui/qopenglcontext.h> -#include <QtCore/qdebug.h> -#include <private/qobject_p.h> -#include <private/qopenglcontext_p.h> - -QT_BEGIN_NAMESPACE - -//this is to work around GL_TEXTURE_WRAP_R_OES which also has 0x8072 as value -#if !defined(GL_TEXTURE_WRAP_R) - #define GL_TEXTURE_WRAP_R 0x8072 -#endif - -QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarget, - QOpenGLTexture *qq) - : q_ptr(qq), - context(nullptr), - target(textureTarget), - textureId(0), - format(QOpenGLTexture::NoFormat), - formatClass(QOpenGLTexture::NoFormatClass), - requestedMipLevels(1), - mipLevels(-1), - layers(1), - faces(1), - samples(0), - fixedSamplePositions(true), - baseLevel(0), - maxLevel(1000), - depthStencilMode(QOpenGLTexture::DepthMode), - comparisonFunction(QOpenGLTexture::CompareLessEqual), - comparisonMode(QOpenGLTexture::CompareNone), - minFilter(QOpenGLTexture::Nearest), - magFilter(QOpenGLTexture::Nearest), - maxAnisotropy(1.0f), - minLevelOfDetail(-1000.0f), - maxLevelOfDetail(1000.0f), - levelOfDetailBias(0.0f), - textureView(false), - autoGenerateMipMaps(true), - storageAllocated(false), - texFuncs(nullptr), - functions(nullptr) -{ - dimensions[0] = dimensions[1] = dimensions[2] = 1; - - switch (target) { - case QOpenGLTexture::Target1D: - bindingTarget = QOpenGLTexture::BindingTarget1D; - break; - case QOpenGLTexture::Target1DArray: - bindingTarget = QOpenGLTexture::BindingTarget1DArray; - break; - case QOpenGLTexture::Target2D: - bindingTarget = QOpenGLTexture::BindingTarget2D; - break; - case QOpenGLTexture::Target2DArray: - bindingTarget = QOpenGLTexture::BindingTarget2DArray; - break; - case QOpenGLTexture::Target3D: - bindingTarget = QOpenGLTexture::BindingTarget3D; - break; - case QOpenGLTexture::TargetCubeMap: - bindingTarget = QOpenGLTexture::BindingTargetCubeMap; - faces = 6; - break; - case QOpenGLTexture::TargetCubeMapArray: - bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray; - faces = 6; - break; - case QOpenGLTexture::Target2DMultisample: - bindingTarget = QOpenGLTexture::BindingTarget2DMultisample; - break; - case QOpenGLTexture::Target2DMultisampleArray: - bindingTarget = QOpenGLTexture::BindingTarget2DMultisampleArray; - break; - case QOpenGLTexture::TargetRectangle: - bindingTarget = QOpenGLTexture::BindingTargetRectangle; - break; - case QOpenGLTexture::TargetBuffer: - bindingTarget = QOpenGLTexture::BindingTargetBuffer; - break; - } - - swizzleMask[0] = QOpenGLTexture::RedValue; - swizzleMask[1] = QOpenGLTexture::GreenValue; - swizzleMask[2] = QOpenGLTexture::BlueValue; - swizzleMask[3] = QOpenGLTexture::AlphaValue; - - wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle - ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat; -} - -QOpenGLTexturePrivate::~QOpenGLTexturePrivate() -{ - destroy(); -} - -void QOpenGLTexturePrivate::initializeOpenGLFunctions() -{ - // If we already have a functions object, there is nothing to do - if (texFuncs) - return; - - // See if the context already has a suitable resource we can use. - // If not create a functions object and add it to the context in case - // others wish to use it too - texFuncs = context->textureFunctions(); - if (!texFuncs) { - texFuncs = new QOpenGLTextureHelper(context); - context->setTextureFunctions(texFuncs); - } -} - -bool QOpenGLTexturePrivate::create() -{ - if (textureId != 0) - return true; - - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (!ctx) { - qWarning("Requires a valid current OpenGL context.\n" - "Texture has not been created"); - return false; - } - context = ctx; - functions = ctx->functions(); - - // Resolve any functions we will need based upon context version and create the texture - initializeOpenGLFunctions(); - - // What features do we have? - QOpenGLTexture::Feature feature = QOpenGLTexture::ImmutableStorage; - while (feature != QOpenGLTexture::MaxFeatureFlag) { - if (QOpenGLTexture::hasFeature(feature)) - features |= feature; - feature = static_cast<QOpenGLTexture::Feature>(feature << 1); - } - - functions->glGenTextures(1, &textureId); - return textureId != 0; -} - -void QOpenGLTexturePrivate::destroy() -{ - if (!textureId) { - // not created or already destroyed - return; - } - QOpenGLContext *currentContext = QOpenGLContext::currentContext(); - if (!currentContext) { - qWarning("QOpenGLTexturePrivate::destroy() called without a current context.\n" - "Texture has not been destroyed"); - return; - } - if (!QOpenGLContext::areSharing(currentContext, context)) { - - qWarning("QOpenGLTexturePrivate::destroy() called but texture context %p" - " is not shared with current context %p.\n" - "Texture has not been destroyed", - static_cast<const void *>(context), - static_cast<const void *>(currentContext)); - return; - } - - functions->glDeleteTextures(1, &textureId); - - context = nullptr; - functions = nullptr; - textureId = 0; - format = QOpenGLTexture::NoFormat; - formatClass = QOpenGLTexture::NoFormatClass; - requestedMipLevels = 1; - mipLevels = -1; - layers = 1; - faces = 1; - samples = 0; - fixedSamplePositions = true, - baseLevel = 0; - maxLevel = 1000; - depthStencilMode = QOpenGLTexture::DepthMode; - minFilter = QOpenGLTexture::Nearest; - magFilter = QOpenGLTexture::Nearest; - maxAnisotropy = 1.0f; - minLevelOfDetail = -1000.0f; - maxLevelOfDetail = 1000.0f; - levelOfDetailBias = 0.0f; - textureView = false; - autoGenerateMipMaps = true; - storageAllocated = false; - texFuncs = nullptr; - - swizzleMask[0] = QOpenGLTexture::RedValue; - swizzleMask[1] = QOpenGLTexture::GreenValue; - swizzleMask[2] = QOpenGLTexture::BlueValue; - swizzleMask[3] = QOpenGLTexture::AlphaValue; - - wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle - ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat; -} - -void QOpenGLTexturePrivate::bind() -{ - functions->glBindTexture(target, textureId); -} - -void QOpenGLTexturePrivate::bind(uint unit, QOpenGLTexture::TextureUnitReset reset) -{ - GLint oldTextureUnit = 0; - if (reset == QOpenGLTexture::ResetTextureUnit) - functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit); - - texFuncs->glActiveTexture(GL_TEXTURE0 + unit); - functions->glBindTexture(target, textureId); - - if (reset == QOpenGLTexture::ResetTextureUnit) - texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit); -} - -void QOpenGLTexturePrivate::release() -{ - functions->glBindTexture(target, 0); -} - -void QOpenGLTexturePrivate::release(uint unit, QOpenGLTexture::TextureUnitReset reset) -{ - GLint oldTextureUnit = 0; - if (reset == QOpenGLTexture::ResetTextureUnit) - functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit); - - texFuncs->glActiveTexture(GL_TEXTURE0 + unit); - functions->glBindTexture(target, 0); - - if (reset == QOpenGLTexture::ResetTextureUnit) - texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit); -} - -bool QOpenGLTexturePrivate::isBound() const -{ - GLint boundTextureId = 0; - functions->glGetIntegerv(bindingTarget, &boundTextureId); - return (static_cast<GLuint>(boundTextureId) == textureId); -} - -bool QOpenGLTexturePrivate::isBound(uint unit) const -{ - GLint oldTextureUnit = 0; - functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit); - - GLint boundTextureId = 0; - texFuncs->glActiveTexture(GL_TEXTURE0 + unit); - functions->glGetIntegerv(bindingTarget, &boundTextureId); - bool result = (static_cast<GLuint>(boundTextureId) == textureId); - - texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit); - return result; -} - -int QOpenGLTexturePrivate::evaluateMipLevels() const -{ - switch (target) { - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::Target3D: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - return qMin(maximumMipLevelCount(), qMax(1, requestedMipLevels)); - - case QOpenGLTexture::TargetRectangle: - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - case QOpenGLTexture::TargetBuffer: - default: - return 1; - } -} - -static bool isSizedTextureFormat(QOpenGLTexture::TextureFormat internalFormat) -{ - switch (internalFormat) { - case QOpenGLTexture::NoFormat: - return false; - - case QOpenGLTexture::R8_UNorm: - case QOpenGLTexture::RG8_UNorm: - case QOpenGLTexture::RGB8_UNorm: - case QOpenGLTexture::RGBA8_UNorm: - case QOpenGLTexture::R16_UNorm: - case QOpenGLTexture::RG16_UNorm: - case QOpenGLTexture::RGB16_UNorm: - case QOpenGLTexture::RGBA16_UNorm: - case QOpenGLTexture::R8_SNorm: - case QOpenGLTexture::RG8_SNorm: - case QOpenGLTexture::RGB8_SNorm: - case QOpenGLTexture::RGBA8_SNorm: - case QOpenGLTexture::R16_SNorm: - case QOpenGLTexture::RG16_SNorm: - case QOpenGLTexture::RGB16_SNorm: - case QOpenGLTexture::RGBA16_SNorm: - case QOpenGLTexture::R8U: - case QOpenGLTexture::RG8U: - case QOpenGLTexture::RGB8U: - case QOpenGLTexture::RGBA8U: - case QOpenGLTexture::R16U: - case QOpenGLTexture::RG16U: - case QOpenGLTexture::RGB16U: - case QOpenGLTexture::RGBA16U: - case QOpenGLTexture::R32U: - case QOpenGLTexture::RG32U: - case QOpenGLTexture::RGB32U: - case QOpenGLTexture::RGBA32U: - case QOpenGLTexture::R8I: - case QOpenGLTexture::RG8I: - case QOpenGLTexture::RGB8I: - case QOpenGLTexture::RGBA8I: - case QOpenGLTexture::R16I: - case QOpenGLTexture::RG16I: - case QOpenGLTexture::RGB16I: - case QOpenGLTexture::RGBA16I: - case QOpenGLTexture::R32I: - case QOpenGLTexture::RG32I: - case QOpenGLTexture::RGB32I: - case QOpenGLTexture::RGBA32I: - case QOpenGLTexture::R16F: - case QOpenGLTexture::RG16F: - case QOpenGLTexture::RGB16F: - case QOpenGLTexture::RGBA16F: - case QOpenGLTexture::R32F: - case QOpenGLTexture::RG32F: - case QOpenGLTexture::RGB32F: - case QOpenGLTexture::RGBA32F: - case QOpenGLTexture::RGB9E5: - case QOpenGLTexture::RG11B10F: - case QOpenGLTexture::RG3B2: - case QOpenGLTexture::R5G6B5: - case QOpenGLTexture::RGB5A1: - case QOpenGLTexture::RGBA4: - case QOpenGLTexture::RGB10A2: - - case QOpenGLTexture::D16: - case QOpenGLTexture::D24: - case QOpenGLTexture::D32: - case QOpenGLTexture::D32F: - - case QOpenGLTexture::D24S8: - case QOpenGLTexture::D32FS8X24: - - case QOpenGLTexture::S8: - - case QOpenGLTexture::RGB_DXT1: - case QOpenGLTexture::RGBA_DXT1: - case QOpenGLTexture::RGBA_DXT3: - case QOpenGLTexture::RGBA_DXT5: - case QOpenGLTexture::R_ATI1N_UNorm: - case QOpenGLTexture::R_ATI1N_SNorm: - case QOpenGLTexture::RG_ATI2N_UNorm: - case QOpenGLTexture::RG_ATI2N_SNorm: - case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT: - case QOpenGLTexture::RGB_BP_SIGNED_FLOAT: - case QOpenGLTexture::RGB_BP_UNorm: - case QOpenGLTexture::SRGB8: - case QOpenGLTexture::SRGB8_Alpha8: - case QOpenGLTexture::SRGB_DXT1: - case QOpenGLTexture::SRGB_Alpha_DXT1: - case QOpenGLTexture::SRGB_Alpha_DXT3: - case QOpenGLTexture::SRGB_Alpha_DXT5: - case QOpenGLTexture::SRGB_BP_UNorm: - case QOpenGLTexture::R11_EAC_UNorm: - case QOpenGLTexture::R11_EAC_SNorm: - case QOpenGLTexture::RG11_EAC_UNorm: - case QOpenGLTexture::RG11_EAC_SNorm: - case QOpenGLTexture::RGB8_ETC2: - case QOpenGLTexture::SRGB8_ETC2: - case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2: - case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2: - case QOpenGLTexture::RGBA8_ETC2_EAC: - case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC: - case QOpenGLTexture::RGBA_ASTC_4x4: - case QOpenGLTexture::RGBA_ASTC_5x4: - case QOpenGLTexture::RGBA_ASTC_5x5: - case QOpenGLTexture::RGBA_ASTC_6x5: - case QOpenGLTexture::RGBA_ASTC_6x6: - case QOpenGLTexture::RGBA_ASTC_8x5: - case QOpenGLTexture::RGBA_ASTC_8x6: - case QOpenGLTexture::RGBA_ASTC_8x8: - case QOpenGLTexture::RGBA_ASTC_10x5: - case QOpenGLTexture::RGBA_ASTC_10x6: - case QOpenGLTexture::RGBA_ASTC_10x8: - case QOpenGLTexture::RGBA_ASTC_10x10: - case QOpenGLTexture::RGBA_ASTC_12x10: - case QOpenGLTexture::RGBA_ASTC_12x12: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12: - return true; - - case QOpenGLTexture::RGB8_ETC1: - return false; - - case QOpenGLTexture::DepthFormat: - case QOpenGLTexture::AlphaFormat: - - case QOpenGLTexture::RGBFormat: - case QOpenGLTexture::RGBAFormat: - - case QOpenGLTexture::LuminanceFormat: - - case QOpenGLTexture::LuminanceAlphaFormat: - return false; - } - - Q_UNREACHABLE(); - return false; -} - -static bool isTextureTargetMultisample(QOpenGLTexture::Target target) -{ - switch (target) { - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::Target3D: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - return false; - - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - return true; - - case QOpenGLTexture::TargetRectangle: - case QOpenGLTexture::TargetBuffer: - return false; - } - - Q_UNREACHABLE(); - return false; -} - -bool QOpenGLTexturePrivate::isUsingImmutableStorage() const -{ - // Use immutable storage whenever possible, falling back to mutable - // Note that if multisample textures are not supported at all, we'll still fail into - // the mutable storage allocation - return isSizedTextureFormat(format) - && (isTextureTargetMultisample(target) - ? features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage) - : features.testFlag(QOpenGLTexture::ImmutableStorage)); -} - -void QOpenGLTexturePrivate::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType) -{ - // Resolve the actual number of mipmap levels we can use - mipLevels = evaluateMipLevels(); - - if (isUsingImmutableStorage()) - allocateImmutableStorage(); - else - allocateMutableStorage(pixelFormat, pixelType); -} - -static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat) -{ - switch (internalFormat) { - case QOpenGLTexture::NoFormat: - return QOpenGLTexture::NoSourceFormat; - - case QOpenGLTexture::R8_UNorm: - return QOpenGLTexture::Red; - - case QOpenGLTexture::RG8_UNorm: - return QOpenGLTexture::RG; - - case QOpenGLTexture::RGB8_UNorm: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RGBA8_UNorm: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::R16_UNorm: - return QOpenGLTexture::Red; - - case QOpenGLTexture::RG16_UNorm: - return QOpenGLTexture::RG; - - case QOpenGLTexture::RGB16_UNorm: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RGBA16_UNorm: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::R8_SNorm: - return QOpenGLTexture::Red; - - case QOpenGLTexture::RG8_SNorm: - return QOpenGLTexture::RG; - - case QOpenGLTexture::RGB8_SNorm: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RGBA8_SNorm: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::R16_SNorm: - return QOpenGLTexture::Red; - - case QOpenGLTexture::RG16_SNorm: - return QOpenGLTexture::RG; - - case QOpenGLTexture::RGB16_SNorm: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RGBA16_SNorm: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::R8U: - return QOpenGLTexture::Red_Integer; - - case QOpenGLTexture::RG8U: - return QOpenGLTexture::RG_Integer; - - case QOpenGLTexture::RGB8U: - return QOpenGLTexture::RGB_Integer; - - case QOpenGLTexture::RGBA8U: - return QOpenGLTexture::RGBA_Integer; - - case QOpenGLTexture::R16U: - return QOpenGLTexture::Red_Integer; - - case QOpenGLTexture::RG16U: - return QOpenGLTexture::RG_Integer; - - case QOpenGLTexture::RGB16U: - return QOpenGLTexture::RGB_Integer; - - case QOpenGLTexture::RGBA16U: - return QOpenGLTexture::RGBA_Integer; - - case QOpenGLTexture::R32U: - return QOpenGLTexture::Red_Integer; - - case QOpenGLTexture::RG32U: - return QOpenGLTexture::RG_Integer; - - case QOpenGLTexture::RGB32U: - return QOpenGLTexture::RGB_Integer; - - case QOpenGLTexture::RGBA32U: - return QOpenGLTexture::RGBA_Integer; - - case QOpenGLTexture::R8I: - return QOpenGLTexture::Red_Integer; - - case QOpenGLTexture::RG8I: - return QOpenGLTexture::RG_Integer; - - case QOpenGLTexture::RGB8I: - return QOpenGLTexture::RGB_Integer; - - case QOpenGLTexture::RGBA8I: - return QOpenGLTexture::RGBA_Integer; - - case QOpenGLTexture::R16I: - return QOpenGLTexture::Red_Integer; - - case QOpenGLTexture::RG16I: - return QOpenGLTexture::RG_Integer; - - case QOpenGLTexture::RGB16I: - return QOpenGLTexture::RGB_Integer; - - case QOpenGLTexture::RGBA16I: - return QOpenGLTexture::RGBA_Integer; - - case QOpenGLTexture::R32I: - return QOpenGLTexture::Red_Integer; - - case QOpenGLTexture::RG32I: - return QOpenGLTexture::RG_Integer; - - case QOpenGLTexture::RGB32I: - return QOpenGLTexture::RGB_Integer; - - case QOpenGLTexture::RGBA32I: - return QOpenGLTexture::RGBA_Integer; - - case QOpenGLTexture::R16F: - return QOpenGLTexture::Red; - - case QOpenGLTexture::RG16F: - return QOpenGLTexture::RG; - - case QOpenGLTexture::RGB16F: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RGBA16F: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::R32F: - return QOpenGLTexture::Red; - - case QOpenGLTexture::RG32F: - return QOpenGLTexture::RG; - - case QOpenGLTexture::RGB32F: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RGBA32F: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::RGB9E5: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RG11B10F: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RG3B2: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::R5G6B5: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RGB5A1: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::RGBA4: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::RGB10A2: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::D16: - case QOpenGLTexture::D24: - case QOpenGLTexture::D32: - case QOpenGLTexture::D32F: - return QOpenGLTexture::Depth; - - case QOpenGLTexture::D24S8: - case QOpenGLTexture::D32FS8X24: - return QOpenGLTexture::DepthStencil; - - case QOpenGLTexture::S8: - return QOpenGLTexture::Stencil; - - case QOpenGLTexture::RGB_DXT1: - case QOpenGLTexture::RGBA_DXT1: - case QOpenGLTexture::RGBA_DXT3: - case QOpenGLTexture::RGBA_DXT5: - case QOpenGLTexture::R_ATI1N_UNorm: - case QOpenGLTexture::R_ATI1N_SNorm: - case QOpenGLTexture::RG_ATI2N_UNorm: - case QOpenGLTexture::RG_ATI2N_SNorm: - case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT: - case QOpenGLTexture::RGB_BP_SIGNED_FLOAT: - case QOpenGLTexture::RGB_BP_UNorm: - case QOpenGLTexture::SRGB8: - case QOpenGLTexture::SRGB8_Alpha8: - case QOpenGLTexture::SRGB_DXT1: - case QOpenGLTexture::SRGB_Alpha_DXT1: - case QOpenGLTexture::SRGB_Alpha_DXT3: - case QOpenGLTexture::SRGB_Alpha_DXT5: - case QOpenGLTexture::SRGB_BP_UNorm: - case QOpenGLTexture::RGB8_ETC1: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::R11_EAC_UNorm: - case QOpenGLTexture::R11_EAC_SNorm: - return QOpenGLTexture::Red; - - case QOpenGLTexture::RG11_EAC_UNorm: - case QOpenGLTexture::RG11_EAC_SNorm: - return QOpenGLTexture::RG; - - case QOpenGLTexture::RGB8_ETC2: - case QOpenGLTexture::SRGB8_ETC2: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2: - case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::RGBA8_ETC2_EAC: - case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::RGBA_ASTC_4x4: - case QOpenGLTexture::RGBA_ASTC_5x4: - case QOpenGLTexture::RGBA_ASTC_5x5: - case QOpenGLTexture::RGBA_ASTC_6x5: - case QOpenGLTexture::RGBA_ASTC_6x6: - case QOpenGLTexture::RGBA_ASTC_8x5: - case QOpenGLTexture::RGBA_ASTC_8x6: - case QOpenGLTexture::RGBA_ASTC_8x8: - case QOpenGLTexture::RGBA_ASTC_10x5: - case QOpenGLTexture::RGBA_ASTC_10x6: - case QOpenGLTexture::RGBA_ASTC_10x8: - case QOpenGLTexture::RGBA_ASTC_10x10: - case QOpenGLTexture::RGBA_ASTC_12x10: - case QOpenGLTexture::RGBA_ASTC_12x12: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::DepthFormat: - return QOpenGLTexture::Depth; - - case QOpenGLTexture::AlphaFormat: - return QOpenGLTexture::Alpha; - - case QOpenGLTexture::RGBFormat: - return QOpenGLTexture::RGB; - - case QOpenGLTexture::RGBAFormat: - return QOpenGLTexture::RGBA; - - case QOpenGLTexture::LuminanceFormat: - return QOpenGLTexture::Luminance; - - case QOpenGLTexture::LuminanceAlphaFormat: - return QOpenGLTexture::LuminanceAlpha; - } - - Q_UNREACHABLE(); - return QOpenGLTexture::NoSourceFormat; -} - -static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat) -{ - switch (internalFormat) { - case QOpenGLTexture::NoFormat: - return QOpenGLTexture::NoPixelType; - - case QOpenGLTexture::R8_UNorm: - case QOpenGLTexture::RG8_UNorm: - case QOpenGLTexture::RGB8_UNorm: - case QOpenGLTexture::RGBA8_UNorm: - case QOpenGLTexture::R16_UNorm: - case QOpenGLTexture::RG16_UNorm: - case QOpenGLTexture::RGB16_UNorm: - case QOpenGLTexture::RGBA16_UNorm: - return QOpenGLTexture::UInt8; - - case QOpenGLTexture::R8_SNorm: - case QOpenGLTexture::RG8_SNorm: - case QOpenGLTexture::RGB8_SNorm: - case QOpenGLTexture::RGBA8_SNorm: - case QOpenGLTexture::R16_SNorm: - case QOpenGLTexture::RG16_SNorm: - case QOpenGLTexture::RGB16_SNorm: - case QOpenGLTexture::RGBA16_SNorm: - return QOpenGLTexture::Int8; - - case QOpenGLTexture::R8U: - case QOpenGLTexture::RG8U: - case QOpenGLTexture::RGB8U: - case QOpenGLTexture::RGBA8U: - case QOpenGLTexture::R16U: - case QOpenGLTexture::RG16U: - case QOpenGLTexture::RGB16U: - case QOpenGLTexture::RGBA16U: - case QOpenGLTexture::R32U: - case QOpenGLTexture::RG32U: - case QOpenGLTexture::RGB32U: - case QOpenGLTexture::RGBA32U: - return QOpenGLTexture::UInt8; - - case QOpenGLTexture::R8I: - case QOpenGLTexture::RG8I: - case QOpenGLTexture::RGB8I: - case QOpenGLTexture::RGBA8I: - case QOpenGLTexture::R16I: - case QOpenGLTexture::RG16I: - case QOpenGLTexture::RGB16I: - case QOpenGLTexture::RGBA16I: - case QOpenGLTexture::R32I: - case QOpenGLTexture::RG32I: - case QOpenGLTexture::RGB32I: - case QOpenGLTexture::RGBA32I: - return QOpenGLTexture::Int8; - - case QOpenGLTexture::R16F: - case QOpenGLTexture::RG16F: - case QOpenGLTexture::RGB16F: - case QOpenGLTexture::RGBA16F: - return QOpenGLTexture::Float16; - - case QOpenGLTexture::R32F: - case QOpenGLTexture::RG32F: - case QOpenGLTexture::RGB32F: - case QOpenGLTexture::RGBA32F: - return QOpenGLTexture::Float32; - - case QOpenGLTexture::RGB9E5: - return QOpenGLTexture::UInt16_RGB5A1_Rev; - - case QOpenGLTexture::RG11B10F: - return QOpenGLTexture::UInt32_RG11B10F; - - case QOpenGLTexture::RG3B2: - return QOpenGLTexture::UInt8_RG3B2; - - case QOpenGLTexture::R5G6B5: - return QOpenGLTexture::UInt16_R5G6B5; - - case QOpenGLTexture::RGB5A1: - return QOpenGLTexture::UInt16_RGB5A1; - - case QOpenGLTexture::RGBA4: - return QOpenGLTexture::UInt16_RGBA4; - - case QOpenGLTexture::RGB10A2: - return QOpenGLTexture::UInt32_RGB10A2; - - case QOpenGLTexture::D16: - return QOpenGLTexture::UInt16; - - case QOpenGLTexture::D24: - case QOpenGLTexture::D32: - return QOpenGLTexture::UInt32; - - case QOpenGLTexture::D32F: - return QOpenGLTexture::Float32; - - case QOpenGLTexture::D24S8: - return QOpenGLTexture::UInt32_D24S8; - - case QOpenGLTexture::D32FS8X24: - return QOpenGLTexture::Float32_D32_UInt32_S8_X24; - - case QOpenGLTexture::S8: - return QOpenGLTexture::UInt8; - - case QOpenGLTexture::RGB_DXT1: - case QOpenGLTexture::RGBA_DXT1: - case QOpenGLTexture::RGBA_DXT3: - case QOpenGLTexture::RGBA_DXT5: - case QOpenGLTexture::R_ATI1N_UNorm: - case QOpenGLTexture::R_ATI1N_SNorm: - case QOpenGLTexture::RG_ATI2N_UNorm: - case QOpenGLTexture::RG_ATI2N_SNorm: - case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT: - case QOpenGLTexture::RGB_BP_SIGNED_FLOAT: - case QOpenGLTexture::RGB_BP_UNorm: - case QOpenGLTexture::SRGB8: - case QOpenGLTexture::SRGB8_Alpha8: - case QOpenGLTexture::SRGB_DXT1: - case QOpenGLTexture::SRGB_Alpha_DXT1: - case QOpenGLTexture::SRGB_Alpha_DXT3: - case QOpenGLTexture::SRGB_Alpha_DXT5: - case QOpenGLTexture::SRGB_BP_UNorm: - case QOpenGLTexture::R11_EAC_UNorm: - case QOpenGLTexture::R11_EAC_SNorm: - case QOpenGLTexture::RG11_EAC_UNorm: - case QOpenGLTexture::RG11_EAC_SNorm: - case QOpenGLTexture::RGB8_ETC2: - case QOpenGLTexture::SRGB8_ETC2: - case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2: - case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2: - case QOpenGLTexture::RGBA8_ETC2_EAC: - case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC: - case QOpenGLTexture::RGB8_ETC1: - case QOpenGLTexture::RGBA_ASTC_4x4: - case QOpenGLTexture::RGBA_ASTC_5x4: - case QOpenGLTexture::RGBA_ASTC_5x5: - case QOpenGLTexture::RGBA_ASTC_6x5: - case QOpenGLTexture::RGBA_ASTC_6x6: - case QOpenGLTexture::RGBA_ASTC_8x5: - case QOpenGLTexture::RGBA_ASTC_8x6: - case QOpenGLTexture::RGBA_ASTC_8x8: - case QOpenGLTexture::RGBA_ASTC_10x5: - case QOpenGLTexture::RGBA_ASTC_10x6: - case QOpenGLTexture::RGBA_ASTC_10x8: - case QOpenGLTexture::RGBA_ASTC_10x10: - case QOpenGLTexture::RGBA_ASTC_12x10: - case QOpenGLTexture::RGBA_ASTC_12x12: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12: - return QOpenGLTexture::UInt8; - - case QOpenGLTexture::DepthFormat: - return QOpenGLTexture::UInt32; - - case QOpenGLTexture::AlphaFormat: - case QOpenGLTexture::RGBFormat: - case QOpenGLTexture::RGBAFormat: - case QOpenGLTexture::LuminanceFormat: - case QOpenGLTexture::LuminanceAlphaFormat: - return QOpenGLTexture::UInt8; - } - - Q_UNREACHABLE(); - return QOpenGLTexture::NoPixelType; -} - -static bool isCompressedFormat(QOpenGLTexture::TextureFormat internalFormat) -{ - switch (internalFormat) { - case QOpenGLTexture::NoFormat: - - case QOpenGLTexture::R8_UNorm: - case QOpenGLTexture::RG8_UNorm: - case QOpenGLTexture::RGB8_UNorm: - case QOpenGLTexture::RGBA8_UNorm: - case QOpenGLTexture::R16_UNorm: - case QOpenGLTexture::RG16_UNorm: - case QOpenGLTexture::RGB16_UNorm: - case QOpenGLTexture::RGBA16_UNorm: - case QOpenGLTexture::R8_SNorm: - case QOpenGLTexture::RG8_SNorm: - case QOpenGLTexture::RGB8_SNorm: - case QOpenGLTexture::RGBA8_SNorm: - case QOpenGLTexture::R16_SNorm: - case QOpenGLTexture::RG16_SNorm: - case QOpenGLTexture::RGB16_SNorm: - case QOpenGLTexture::RGBA16_SNorm: - case QOpenGLTexture::R8U: - case QOpenGLTexture::RG8U: - case QOpenGLTexture::RGB8U: - case QOpenGLTexture::RGBA8U: - case QOpenGLTexture::R16U: - case QOpenGLTexture::RG16U: - case QOpenGLTexture::RGB16U: - case QOpenGLTexture::RGBA16U: - case QOpenGLTexture::R32U: - case QOpenGLTexture::RG32U: - case QOpenGLTexture::RGB32U: - case QOpenGLTexture::RGBA32U: - case QOpenGLTexture::R8I: - case QOpenGLTexture::RG8I: - case QOpenGLTexture::RGB8I: - case QOpenGLTexture::RGBA8I: - case QOpenGLTexture::R16I: - case QOpenGLTexture::RG16I: - case QOpenGLTexture::RGB16I: - case QOpenGLTexture::RGBA16I: - case QOpenGLTexture::R32I: - case QOpenGLTexture::RG32I: - case QOpenGLTexture::RGB32I: - case QOpenGLTexture::RGBA32I: - case QOpenGLTexture::R16F: - case QOpenGLTexture::RG16F: - case QOpenGLTexture::RGB16F: - case QOpenGLTexture::RGBA16F: - case QOpenGLTexture::R32F: - case QOpenGLTexture::RG32F: - case QOpenGLTexture::RGB32F: - case QOpenGLTexture::RGBA32F: - case QOpenGLTexture::RGB9E5: - case QOpenGLTexture::RG11B10F: - case QOpenGLTexture::RG3B2: - case QOpenGLTexture::R5G6B5: - case QOpenGLTexture::RGB5A1: - case QOpenGLTexture::RGBA4: - case QOpenGLTexture::RGB10A2: - - case QOpenGLTexture::D16: - case QOpenGLTexture::D24: - case QOpenGLTexture::D32: - case QOpenGLTexture::D32F: - - case QOpenGLTexture::D24S8: - case QOpenGLTexture::D32FS8X24: - - case QOpenGLTexture::S8: - return false; - - case QOpenGLTexture::RGB_DXT1: - case QOpenGLTexture::RGBA_DXT1: - case QOpenGLTexture::RGBA_DXT3: - case QOpenGLTexture::RGBA_DXT5: - case QOpenGLTexture::R_ATI1N_UNorm: - case QOpenGLTexture::R_ATI1N_SNorm: - case QOpenGLTexture::RG_ATI2N_UNorm: - case QOpenGLTexture::RG_ATI2N_SNorm: - case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT: - case QOpenGLTexture::RGB_BP_SIGNED_FLOAT: - case QOpenGLTexture::RGB_BP_UNorm: - case QOpenGLTexture::SRGB8: - case QOpenGLTexture::SRGB8_Alpha8: - case QOpenGLTexture::SRGB_DXT1: - case QOpenGLTexture::SRGB_Alpha_DXT1: - case QOpenGLTexture::SRGB_Alpha_DXT3: - case QOpenGLTexture::SRGB_Alpha_DXT5: - case QOpenGLTexture::SRGB_BP_UNorm: - case QOpenGLTexture::R11_EAC_UNorm: - case QOpenGLTexture::R11_EAC_SNorm: - case QOpenGLTexture::RG11_EAC_UNorm: - case QOpenGLTexture::RG11_EAC_SNorm: - case QOpenGLTexture::RGB8_ETC2: - case QOpenGLTexture::SRGB8_ETC2: - case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2: - case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2: - case QOpenGLTexture::RGBA8_ETC2_EAC: - case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC: - case QOpenGLTexture::RGB8_ETC1: - case QOpenGLTexture::RGBA_ASTC_4x4: - case QOpenGLTexture::RGBA_ASTC_5x4: - case QOpenGLTexture::RGBA_ASTC_5x5: - case QOpenGLTexture::RGBA_ASTC_6x5: - case QOpenGLTexture::RGBA_ASTC_6x6: - case QOpenGLTexture::RGBA_ASTC_8x5: - case QOpenGLTexture::RGBA_ASTC_8x6: - case QOpenGLTexture::RGBA_ASTC_8x8: - case QOpenGLTexture::RGBA_ASTC_10x5: - case QOpenGLTexture::RGBA_ASTC_10x6: - case QOpenGLTexture::RGBA_ASTC_10x8: - case QOpenGLTexture::RGBA_ASTC_10x10: - case QOpenGLTexture::RGBA_ASTC_12x10: - case QOpenGLTexture::RGBA_ASTC_12x12: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12: - return true; - - case QOpenGLTexture::DepthFormat: - case QOpenGLTexture::AlphaFormat: - case QOpenGLTexture::RGBFormat: - case QOpenGLTexture::RGBAFormat: - case QOpenGLTexture::LuminanceFormat: - case QOpenGLTexture::LuminanceAlphaFormat: - return false; - } - - Q_UNREACHABLE(); - return false; -} - -void QOpenGLTexturePrivate::allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType) -{ - // There is no way to allocate mutable storage for compressed textures in in - // versions older than OpenGL 3.1 and OpenGL ES 3.0, because the older specs - // do not mandate accepting null data pointers for glCompressedTexImage*D, - // unlike glTexImage*D (which in turn does not accept compressed formats). - if (isCompressedFormat(format)) { - storageAllocated = true; - return; - } - - switch (target) { - case QOpenGLTexture::TargetBuffer: - // Buffer textures get their storage from an external OpenGL buffer - qWarning("Buffer textures do not allocate storage"); - return; - - case QOpenGLTexture::Target1D: - if (features.testFlag(QOpenGLTexture::Texture1D)) { - for (int level = 0; level < mipLevels; ++level) - texFuncs->glTextureImage1D(textureId, target, bindingTarget, level, format, - mipLevelSize(level, dimensions[0]), - 0, - pixelFormat, pixelType, nullptr); - } else { - qWarning("1D textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target1DArray: - if (features.testFlag(QOpenGLTexture::Texture1D) - && features.testFlag(QOpenGLTexture::TextureArrays)) { - for (int level = 0; level < mipLevels; ++level) - texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format, - mipLevelSize(level, dimensions[0]), - layers, - 0, - pixelFormat, pixelType, nullptr); - } else { - qWarning("1D array textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target2D: - case QOpenGLTexture::TargetRectangle: - for (int level = 0; level < mipLevels; ++level) - texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format, - mipLevelSize(level, dimensions[0]), - mipLevelSize(level, dimensions[1]), - 0, - pixelFormat, pixelType, nullptr); - break; - - case QOpenGLTexture::TargetCubeMap: { - // Cubemaps are the odd one out. We have to allocate storage for each - // face and miplevel using the special cubemap face targets rather than - // GL_TARGET_CUBEMAP. - const QOpenGLTexture::CubeMapFace faceTargets[] = { - QOpenGLTexture::CubeMapPositiveX, QOpenGLTexture::CubeMapNegativeX, - QOpenGLTexture::CubeMapPositiveY, QOpenGLTexture::CubeMapNegativeY, - QOpenGLTexture::CubeMapPositiveZ, QOpenGLTexture::CubeMapNegativeZ - }; - - for (int faceTarget = 0; faceTarget < 6; ++faceTarget) { - for (int level = 0; level < mipLevels; ++level) { - texFuncs->glTextureImage2D(textureId, faceTargets[faceTarget], bindingTarget, - level, format, - mipLevelSize(level, dimensions[0]), - mipLevelSize(level, dimensions[1]), - 0, - pixelFormat, pixelType, nullptr); - } - } - break; - } - - case QOpenGLTexture::Target2DArray: - if (features.testFlag(QOpenGLTexture::TextureArrays)) { - for (int level = 0; level < mipLevels; ++level) - texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format, - mipLevelSize(level, dimensions[0]), - mipLevelSize(level, dimensions[1]), - layers, - 0, - pixelFormat, pixelType, nullptr); - } else { - qWarning("Array textures are not supported"); - return; - } - break; - - case QOpenGLTexture::TargetCubeMapArray: - // Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter - if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) { - for (int level = 0; level < mipLevels; ++level) - texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format, - mipLevelSize(level, dimensions[0]), - mipLevelSize(level, dimensions[1]), - 6 * layers, - 0, - pixelFormat, pixelType, nullptr); - } else { - qWarning("Cubemap Array textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target3D: - if (features.testFlag(QOpenGLTexture::Texture3D)) { - for (int level = 0; level < mipLevels; ++level) - texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format, - mipLevelSize(level, dimensions[0]), - mipLevelSize(level, dimensions[1]), - mipLevelSize(level, dimensions[2]), - 0, - pixelFormat, pixelType, nullptr); - } else { - qWarning("3D textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target2DMultisample: - if (features.testFlag(QOpenGLTexture::TextureMultisample)) { - texFuncs->glTextureImage2DMultisample(textureId, target, bindingTarget, samples, format, - dimensions[0], dimensions[1], - fixedSamplePositions); - } else { - qWarning("Multisample textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target2DMultisampleArray: - if (features.testFlag(QOpenGLTexture::TextureMultisample) - && features.testFlag(QOpenGLTexture::TextureArrays)) { - texFuncs->glTextureImage3DMultisample(textureId, target, bindingTarget, samples, format, - dimensions[0], dimensions[1], layers, - fixedSamplePositions); - } else { - qWarning("Multisample array textures are not supported"); - return; - } - break; - } - - storageAllocated = true; -} - -void QOpenGLTexturePrivate::allocateImmutableStorage() -{ - switch (target) { - case QOpenGLTexture::TargetBuffer: - // Buffer textures get their storage from an external OpenGL buffer - qWarning("Buffer textures do not allocate storage"); - return; - - case QOpenGLTexture::Target1D: - if (features.testFlag(QOpenGLTexture::Texture1D)) { - texFuncs->glTextureStorage1D(textureId, target, bindingTarget, mipLevels, format, - dimensions[0]); - } else { - qWarning("1D textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target1DArray: - if (features.testFlag(QOpenGLTexture::Texture1D) - && features.testFlag(QOpenGLTexture::TextureArrays)) { - texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format, - dimensions[0], layers); - } else { - qWarning("1D array textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target2D: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetRectangle: - texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format, - dimensions[0], dimensions[1]); - break; - - case QOpenGLTexture::Target2DArray: - if (features.testFlag(QOpenGLTexture::TextureArrays)) { - texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format, - dimensions[0], dimensions[1], layers); - } else { - qWarning("Array textures are not supported"); - return; - } - break; - - case QOpenGLTexture::TargetCubeMapArray: - // Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter - if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) { - texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format, - dimensions[0], dimensions[1], 6 * layers); - } else { - qWarning("Cubemap Array textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target3D: - if (features.testFlag(QOpenGLTexture::Texture3D)) { - texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format, - dimensions[0], dimensions[1], dimensions[2]); - } else { - qWarning("3D textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target2DMultisample: - if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)) { - texFuncs->glTextureStorage2DMultisample(textureId, target, bindingTarget, samples, format, - dimensions[0], dimensions[1], - fixedSamplePositions); - } else { - qWarning("Multisample textures are not supported"); - return; - } - break; - - case QOpenGLTexture::Target2DMultisampleArray: - if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage) - && features.testFlag(QOpenGLTexture::TextureArrays)) { - texFuncs->glTextureStorage3DMultisample(textureId, target, bindingTarget, samples, format, - dimensions[0], dimensions[1], layers, - fixedSamplePositions); - } else { - qWarning("Multisample array textures are not supported"); - return; - } - break; - } - - storageAllocated = true; -} - -void QOpenGLTexturePrivate::setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, - QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - switch (target) { - case QOpenGLTexture::Target1D: - Q_UNUSED(layer); - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel, - 0, mipLevelSize( mipLevel, dimensions[0] ), - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target1DArray: - Q_UNUSED(cubeFace); - texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel, - 0, layer, - mipLevelSize(mipLevel, dimensions[0]), - layerCount, - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target2D: - Q_UNUSED(layer); - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel, - 0, 0, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target2DArray: - Q_UNUSED(cubeFace); - texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel, - 0, 0, layer, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - layerCount, - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target3D: - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel, - 0, 0, layer, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - mipLevelSize(mipLevel, dimensions[2]), - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::TargetCubeMap: - Q_UNUSED(layer); - Q_UNUSED(layerCount); - texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel, - 0, 0, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::TargetCubeMapArray: { - int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX; - int layerFace = 6 * layer + faceIndex; - texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel, - 0, 0, layerFace, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - layerCount, - sourceFormat, sourceType, data, options); - break; - } - - case QOpenGLTexture::TargetRectangle: - Q_UNUSED(mipLevel); - Q_UNUSED(layer); - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0, - 0, 0, - dimensions[0], - dimensions[1], - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - case QOpenGLTexture::TargetBuffer: - // We don't upload pixel data for these targets - qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload"); - break; - } - - // If requested perform automatic mip map generation - if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) { - Q_Q(QOpenGLTexture); - q->generateMipMaps(); - } -} - -void QOpenGLTexturePrivate::setData(int xOffset, int yOffset, int zOffset, int width, int height, int depth, - int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, - QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - switch (target) { - case QOpenGLTexture::Target1D: - Q_UNUSED(layer); - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - Q_UNUSED(yOffset); - Q_UNUSED(zOffset); - Q_UNUSED(height); - Q_UNUSED(depth); - texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel, - xOffset, width, - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target1DArray: - Q_UNUSED(cubeFace); - Q_UNUSED(yOffset); - Q_UNUSED(zOffset); - Q_UNUSED(height); - Q_UNUSED(depth); - texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel, - xOffset, layer, - width, - layerCount, - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target2D: - Q_UNUSED(layer); - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - Q_UNUSED(zOffset); - Q_UNUSED(depth); - texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel, - xOffset, yOffset, - width, height, - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target2DArray: - Q_UNUSED(cubeFace); - Q_UNUSED(zOffset); - Q_UNUSED(depth); - texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel, - xOffset, yOffset, layer, - width, height, layerCount, - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target3D: - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel, - xOffset, yOffset, zOffset, - width, height, depth, - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::TargetCubeMap: - Q_UNUSED(layer); - Q_UNUSED(layerCount); - Q_UNUSED(zOffset); - Q_UNUSED(depth); - texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel, - xOffset, yOffset, - width, height, - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::TargetCubeMapArray: { - Q_UNUSED(zOffset); - Q_UNUSED(depth); - int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX; - int layerFace = 6 * layer + faceIndex; - texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel, - xOffset, yOffset, layerFace, - width, height, - layerCount, - sourceFormat, sourceType, data, options); - break; - } - - case QOpenGLTexture::TargetRectangle: - Q_UNUSED(mipLevel); - Q_UNUSED(layer); - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - Q_UNUSED(zOffset); - Q_UNUSED(depth); - texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0, - xOffset, yOffset, - width, height, - sourceFormat, sourceType, data, options); - break; - - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - case QOpenGLTexture::TargetBuffer: - // We don't upload pixel data for these targets - qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload"); - break; - } - - // If requested perform automatic mip map generation - if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) { - Q_Q(QOpenGLTexture); - q->generateMipMaps(); - } -} - - -void QOpenGLTexturePrivate::setCompressedData(int mipLevel, int layer, int layerCount, - QOpenGLTexture::CubeMapFace cubeFace, - int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options) -{ - if (!isCompressedFormat(format)) { - qWarning("Cannot set compressed data for non-compressed format 0x%x", format); - return; - } - - const bool needsFullSpec = !isUsingImmutableStorage(); // was allocateStorage() a no-op? - - switch (target) { - case QOpenGLTexture::Target1D: - Q_UNUSED(layer); - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - if (needsFullSpec) { - texFuncs->glCompressedTextureImage1D(textureId, target, bindingTarget, mipLevel, - format, - mipLevelSize(mipLevel, dimensions[0]), - 0, dataSize, data, options); - } else { - texFuncs->glCompressedTextureSubImage1D(textureId, target, bindingTarget, mipLevel, - 0, mipLevelSize( mipLevel, dimensions[0] ), - format, dataSize, data, options); - } - break; - - case QOpenGLTexture::Target1DArray: - Q_UNUSED(cubeFace); - if (!needsFullSpec) { - texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel, - 0, layer, - mipLevelSize(mipLevel, dimensions[0]), - layerCount, - format, dataSize, data, options); - } - break; - - case QOpenGLTexture::Target2D: - Q_UNUSED(layer); - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - if (needsFullSpec) { - texFuncs->glCompressedTextureImage2D(textureId, target, bindingTarget, mipLevel, - format, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - 0, dataSize, data, options); - } else { - texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel, - 0, 0, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - format, dataSize, data, options); - } - break; - - case QOpenGLTexture::Target2DArray: - Q_UNUSED(cubeFace); - if (!needsFullSpec) { - texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel, - 0, 0, layer, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - layerCount, - format, dataSize, data, options); - } - break; - - case QOpenGLTexture::Target3D: - Q_UNUSED(cubeFace); - Q_UNUSED(layerCount); - if (needsFullSpec) { - texFuncs->glCompressedTextureImage3D(textureId, target, bindingTarget, mipLevel, - format, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - mipLevelSize(mipLevel, dimensions[2]), - 0, dataSize, data, options); - } else { - texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel, - 0, 0, layer, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - mipLevelSize(mipLevel, dimensions[2]), - format, dataSize, data, options); - } - break; - - case QOpenGLTexture::TargetCubeMap: - Q_UNUSED(layer); - Q_UNUSED(layerCount); - if (needsFullSpec) { - texFuncs->glCompressedTextureImage2D(textureId, cubeFace, bindingTarget, mipLevel, - format, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - 0, dataSize, data, options); - } else { - texFuncs->glCompressedTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel, - 0, 0, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - format, dataSize, data, options); - } - break; - - case QOpenGLTexture::TargetCubeMapArray: { - int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX; - int layerFace = 6 * layer + faceIndex; - if (!needsFullSpec) { - texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel, - 0, 0, layerFace, - mipLevelSize(mipLevel, dimensions[0]), - mipLevelSize(mipLevel, dimensions[1]), - layerCount, - format, dataSize, data, options); - } - break; - } - - case QOpenGLTexture::TargetRectangle: - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - case QOpenGLTexture::TargetBuffer: - // We don't upload pixel data for these targets - qWarning("QOpenGLTexture::setCompressedData(): Texture target does not support pixel data upload"); - break; - } - - // If requested perform automatic mip map generation - if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) { - Q_Q(QOpenGLTexture); - q->generateMipMaps(); - } -} - -void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::WrapMode mode) -{ - switch (target) { - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::TargetBuffer: - wrapModes[0] = mode; - texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode); - break; - - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - case QOpenGLTexture::TargetRectangle: - wrapModes[0] = wrapModes[1] = mode; - texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode); - texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode); - break; - - case QOpenGLTexture::Target3D: - wrapModes[0] = wrapModes[1] = wrapModes[2] = mode; - texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode); - texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode); - texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_R, mode); - break; - } -} - -void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode) -{ - switch (target) { - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::TargetBuffer: - switch (direction) { - case QOpenGLTexture::DirectionS: - wrapModes[0] = mode; - texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode); - break; - - case QOpenGLTexture::DirectionT: - case QOpenGLTexture::DirectionR: - qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target"); - break; - } - break; - - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - case QOpenGLTexture::TargetRectangle: - switch (direction) { - case QOpenGLTexture::DirectionS: - wrapModes[0] = mode; - texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode); - break; - - case QOpenGLTexture::DirectionT: - wrapModes[1] = mode; - texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode); - break; - - case QOpenGLTexture::DirectionR: - qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target"); - break; - } - break; - - case QOpenGLTexture::Target3D: - switch (direction) { - case QOpenGLTexture::DirectionS: - wrapModes[0] = mode; - texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode); - break; - - case QOpenGLTexture::DirectionT: - wrapModes[1] = mode; - texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode); - break; - - case QOpenGLTexture::DirectionR: - wrapModes[2] = mode; - texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode); - break; - } - break; - } -} - -QOpenGLTexture::WrapMode QOpenGLTexturePrivate::wrapMode(QOpenGLTexture::CoordinateDirection direction) const -{ - switch (target) { - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::TargetBuffer: - switch (direction) { - case QOpenGLTexture::DirectionS: - return wrapModes[0]; - - case QOpenGLTexture::DirectionT: - case QOpenGLTexture::DirectionR: - qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target"); - return QOpenGLTexture::Repeat; - } - break; - - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - case QOpenGLTexture::TargetRectangle: - switch (direction) { - case QOpenGLTexture::DirectionS: - return wrapModes[0]; - - case QOpenGLTexture::DirectionT: - return wrapModes[1]; - - case QOpenGLTexture::DirectionR: - qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target"); - return QOpenGLTexture::Repeat; - } - break; - - case QOpenGLTexture::Target3D: - switch (direction) { - case QOpenGLTexture::DirectionS: - return wrapModes[0]; - - case QOpenGLTexture::DirectionT: - return wrapModes[1]; - - case QOpenGLTexture::DirectionR: - return wrapModes[2]; - } - break; - } - // Should never get here - Q_ASSERT(false); - return QOpenGLTexture::Repeat; -} - -QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target viewTarget, - QOpenGLTexture::TextureFormat viewFormat, - int minimumMipmapLevel, int maximumMipmapLevel, - int minimumLayer, int maximumLayer) const -{ - // Do sanity checks - see http://www.opengl.org/wiki/GLAPI/glTextureView - - // Check the targets are compatible - bool viewTargetCompatible = false; - switch (target) { - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target1DArray: - viewTargetCompatible = (viewTarget == QOpenGLTexture::Target1D - || viewTarget == QOpenGLTexture::Target1DArray); - break; - - - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target2DArray: - viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2D - || viewTarget == QOpenGLTexture::Target2DArray); - break; - - case QOpenGLTexture::Target3D: - viewTargetCompatible = (viewTarget == QOpenGLTexture::Target3D); - break; - - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetCubeMap - || viewTarget == QOpenGLTexture::Target2D - || viewTarget == QOpenGLTexture::Target2DArray - || viewTarget == QOpenGLTexture::TargetCubeMapArray); - break; - - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2DMultisample - || viewTarget == QOpenGLTexture::Target2DMultisampleArray); - break; - - case QOpenGLTexture::TargetRectangle: - viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetRectangle); - break; - - case QOpenGLTexture::TargetBuffer: - // Cannot be used with texture views - break; - } - - if (!viewTargetCompatible) { - qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view targets"); - return nullptr; - } - - // Check the formats are compatible - bool viewFormatCompatible = false; - switch (formatClass) { - case QOpenGLTexture::NoFormatClass: - break; - - case QOpenGLTexture::FormatClass_128Bit: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA32F - || viewFormat == QOpenGLTexture::RGBA32U - || viewFormat == QOpenGLTexture::RGBA32I); - break; - - case QOpenGLTexture::FormatClass_96Bit: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB32F - || viewFormat == QOpenGLTexture::RGB32U - || viewFormat == QOpenGLTexture::RGB32I); - break; - - case QOpenGLTexture::FormatClass_64Bit: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA16F - || viewFormat == QOpenGLTexture::RG32F - || viewFormat == QOpenGLTexture::RGBA16U - || viewFormat == QOpenGLTexture::RG32U - || viewFormat == QOpenGLTexture::RGBA16I - || viewFormat == QOpenGLTexture::RG32I - || viewFormat == QOpenGLTexture::RGBA16_UNorm - || viewFormat == QOpenGLTexture::RGBA16_SNorm); - break; - - case QOpenGLTexture::FormatClass_48Bit: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB16_UNorm - || viewFormat == QOpenGLTexture::RGB16_SNorm - || viewFormat == QOpenGLTexture::RGB16F - || viewFormat == QOpenGLTexture::RGB16U - || viewFormat == QOpenGLTexture::RGB16I); - break; - - case QOpenGLTexture::FormatClass_32Bit: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RG16F - || viewFormat == QOpenGLTexture::RG11B10F - || viewFormat == QOpenGLTexture::R32F - || viewFormat == QOpenGLTexture::RGB10A2 - || viewFormat == QOpenGLTexture::RGBA8U - || viewFormat == QOpenGLTexture::RG16U - || viewFormat == QOpenGLTexture::R32U - || viewFormat == QOpenGLTexture::RGBA8I - || viewFormat == QOpenGLTexture::RG16I - || viewFormat == QOpenGLTexture::R32I - || viewFormat == QOpenGLTexture::RGBA8_UNorm - || viewFormat == QOpenGLTexture::RG16_UNorm - || viewFormat == QOpenGLTexture::RGBA8_SNorm - || viewFormat == QOpenGLTexture::RG16_SNorm - || viewFormat == QOpenGLTexture::SRGB8_Alpha8 - || viewFormat == QOpenGLTexture::RGB9E5); - break; - - case QOpenGLTexture::FormatClass_24Bit: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB8_UNorm - || viewFormat == QOpenGLTexture::RGB8_SNorm - || viewFormat == QOpenGLTexture::SRGB8 - || viewFormat == QOpenGLTexture::RGB8U - || viewFormat == QOpenGLTexture::RGB8I); - break; - - case QOpenGLTexture::FormatClass_16Bit: - viewFormatCompatible = (viewFormat == QOpenGLTexture::R16F - || viewFormat == QOpenGLTexture::RG8U - || viewFormat == QOpenGLTexture::R16U - || viewFormat == QOpenGLTexture::RG8I - || viewFormat == QOpenGLTexture::R16I - || viewFormat == QOpenGLTexture::RG8_UNorm - || viewFormat == QOpenGLTexture::R16_UNorm - || viewFormat == QOpenGLTexture::RG8_SNorm - || viewFormat == QOpenGLTexture::R16_SNorm); - break; - - case QOpenGLTexture::FormatClass_8Bit: - viewFormatCompatible = (viewFormat == QOpenGLTexture::R8U - || viewFormat == QOpenGLTexture::R8I - || viewFormat == QOpenGLTexture::R8_UNorm - || viewFormat == QOpenGLTexture::R8_SNorm); - break; - - case QOpenGLTexture::FormatClass_RGTC1_R: - viewFormatCompatible = (viewFormat == QOpenGLTexture::R_ATI1N_UNorm - || viewFormat == QOpenGLTexture::R_ATI1N_SNorm); - break; - - case QOpenGLTexture::FormatClass_RGTC2_RG: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RG_ATI2N_UNorm - || viewFormat == QOpenGLTexture::RG_ATI2N_SNorm); - break; - - case QOpenGLTexture::FormatClass_BPTC_Unorm: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNorm - || viewFormat == QOpenGLTexture::SRGB_BP_UNorm); - break; - - case QOpenGLTexture::FormatClass_BPTC_Float: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT - || viewFormat == QOpenGLTexture::RGB_BP_SIGNED_FLOAT); - break; - - case QOpenGLTexture::FormatClass_S3TC_DXT1_RGB: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_DXT1 - || viewFormat == QOpenGLTexture::SRGB_DXT1); - break; - - case QOpenGLTexture::FormatClass_S3TC_DXT1_RGBA: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT1 - || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT1); - break; - - case QOpenGLTexture::FormatClass_S3TC_DXT3_RGBA: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT3 - || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT3); - break; - - case QOpenGLTexture::FormatClass_S3TC_DXT5_RGBA: - viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT5 - || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT5); - break; - - case QOpenGLTexture::FormatClass_Unique: - viewFormatCompatible = (viewFormat == format); - break; - } - - if (!viewFormatCompatible) { - qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view formats"); - return nullptr; - } - - - // Create a view - QOpenGLTexture *view = new QOpenGLTexture(viewTarget); - view->setFormat(viewFormat); - view->create(); - view->d_ptr->textureView = true; - texFuncs->glTextureView(view->textureId(), viewTarget, textureId, viewFormat, - minimumMipmapLevel, maximumMipmapLevel - minimumMipmapLevel + 1, - minimumLayer, maximumLayer - minimumLayer + 1); - return view; -} - - -/*! - \class QOpenGLTexture - \inmodule QtGui - \since 5.2 - \wrapper - \brief The QOpenGLTexture class encapsulates an OpenGL texture object. - - QOpenGLTexture makes it easy to work with OpenGL textures and the myriad features - and targets that they offer depending upon the capabilities of your OpenGL implementation. - - The typical usage pattern for QOpenGLTexture is - \list - \li Instantiate the object specifying the texture target type - \li Set properties that affect the storage requirements e.g. storage format, dimensions - \li Allocate the server-side storage - \li Optionally upload pixel data - \li Optionally set any additional properties e.g. filtering and border options - \li Render with texture or render to texture - \endlist - - In the common case of simply using a QImage as the source of texture pixel data - most of the above steps are performed automatically. - - \code - // Prepare texture - QOpenGLTexture *texture = new QOpenGLTexture(QImage(fileName).mirrored()); - texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - ... - // Render with texture - texture->bind(); - glDrawArrays(...); - \endcode - - Note that the QImage is mirrored vertically to account for the fact that - OpenGL and QImage use opposite directions for the y axis. Another option - would be to transform your texture coordinates. -*/ - -/*! - \enum QOpenGLTexture::Filter - This enum defines the filtering parameters for a QOpenGLTexture object. - \value Nearest Equivalent to GL_NEAREST - \value Linear Equivalent to GL_LINEAR - \value NearestMipMapNearest Equivalent to GL_NEAREST_MIPMAP_NEAREST - \value NearestMipMapLinear Equivalent to GL_NEAREST_MIPMAP_LINEAR - \value LinearMipMapNearest Equivalent to GL_LINEAR_MIPMAP_NEAREST - \value LinearMipMapLinear Equivalent to GL_LINEAR_MIPMAP_LINEAR -*/ - -/*! - \enum QOpenGLTexture::Target - This enum defines the texture target of a QOpenGLTexture object. - - \value Target1D A 1-dimensional texture. - Equivalent to GL_TEXTURE_1D. - \value Target1DArray An array of 1-dimensional textures. - Equivalent to GL_TEXTURE_1D_ARRAY - \value Target2D A 2-dimensional texture. - Equivalent to GL_TEXTURE_2D - \value Target2DArray An array of 1-dimensional textures. - Equivalent to GL_TEXTURE_2D_ARRAY - \value Target3D A 3-dimensional texture. - Equivalent to GL_TEXTURE_3D - \value TargetCubeMap A cubemap texture. - Equivalent to GL_TEXTURE_CUBE_MAP - \value TargetCubeMapArray An array of cubemap textures. - Equivalent to GL_TEXTURE_CUBE_MAP_ARRAY - \value Target2DMultisample A 2-dimensional texture with multisample support. - Equivalent to GL_TEXTURE_2D_MULTISAMPLE - \value Target2DMultisampleArray An array of 2-dimensional textures with multisample support. - Equivalent to GL_TEXTURE_2D_MULTISAMPLE_ARRAY - \value TargetRectangle A rectangular 2-dimensional texture. - Equivalent to GL_TEXTURE_RECTANGLE - \value TargetBuffer A texture with data from an OpenGL buffer object. - Equivalent to GL_TEXTURE_BUFFER -*/ - -/*! - \enum QOpenGLTexture::BindingTarget - This enum defines the possible binding targets of texture units. - - \value BindingTarget1D Equivalent to GL_TEXTURE_BINDING_1D - \value BindingTarget1DArray Equivalent to GL_TEXTURE_BINDING_1D_ARRAY - \value BindingTarget2D Equivalent to GL_TEXTURE_BINDING_2D - \value BindingTarget2DArray Equivalent to GL_TEXTURE_BINDING_2D_ARRAY - \value BindingTarget3D Equivalent to GL_TEXTURE_BINDING_3D - \value BindingTargetCubeMap Equivalent to GL_TEXTURE_BINDING_CUBE_MAP - \value BindingTargetCubeMapArray Equivalent to GL_TEXTURE_BINDING_CUBE_MAP_ARRAY - \value BindingTarget2DMultisample Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE - \value BindingTarget2DMultisampleArray Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY - \value BindingTargetRectangle Equivalent to GL_TEXTURE_BINDING_RECTANGLE - \value BindingTargetBuffer Equivalent to GL_TEXTURE_BINDING_BUFFER -*/ - -/*! - \enum QOpenGLTexture::MipMapGeneration - This enum defines the options to control mipmap generation. - - \value GenerateMipMaps Mipmaps should be generated - \value DontGenerateMipMaps Mipmaps should not be generated -*/ - -/*! - \enum QOpenGLTexture::TextureUnitReset - This enum defines options ot control texture unit activation. - - \value ResetTextureUnit The previous active texture unit will be reset - \value DontResetTextureUnit The previous active texture unit will not be rest -*/ - -/*! - \enum QOpenGLTexture::TextureFormat - This enum defines the possible texture formats. Depending upon your OpenGL - implementation only a subset of these may be supported. - - \value NoFormat Equivalent to GL_NONE - - \value R8_UNorm Equivalent to GL_R8 - \value RG8_UNorm Equivalent to GL_RG8 - \value RGB8_UNorm Equivalent to GL_RGB8 - \value RGBA8_UNorm Equivalent to GL_RGBA8 - - \value R16_UNorm Equivalent to GL_R16 - \value RG16_UNorm Equivalent to GL_RG16 - \value RGB16_UNorm Equivalent to GL_RGB16 - \value RGBA16_UNorm Equivalent to GL_RGBA16 - - \value R8_SNorm Equivalent to GL_R8_SNORM - \value RG8_SNorm Equivalent to GL_RG8_SNORM - \value RGB8_SNorm Equivalent to GL_RGB8_SNORM - \value RGBA8_SNorm Equivalent to GL_RGBA8_SNORM - - \value R16_SNorm Equivalent to GL_R16_SNORM - \value RG16_SNorm Equivalent to GL_RG16_SNORM - \value RGB16_SNorm Equivalent to GL_RGB16_SNORM - \value RGBA16_SNorm Equivalent to GL_RGBA16_SNORM - - \value R8U Equivalent to GL_R8UI - \value RG8U Equivalent to GL_RG8UI - \value RGB8U Equivalent to GL_RGB8UI - \value RGBA8U Equivalent to GL_RGBA8UI - - \value R16U Equivalent to GL_R16UI - \value RG16U Equivalent to GL_RG16UI - \value RGB16U Equivalent to GL_RGB16UI - \value RGBA16U Equivalent to GL_RGBA16UI - - \value R32U Equivalent to GL_R32UI - \value RG32U Equivalent to GL_RG32UI - \value RGB32U Equivalent to GL_RGB32UI - \value RGBA32U Equivalent to GL_RGBA32UI - - \value R8I Equivalent to GL_R8I - \value RG8I Equivalent to GL_RG8I - \value RGB8I Equivalent to GL_RGB8I - \value RGBA8I Equivalent to GL_RGBA8I - - \value R16I Equivalent to GL_R16I - \value RG16I Equivalent to GL_RG16I - \value RGB16I Equivalent to GL_RGB16I - \value RGBA16I Equivalent to GL_RGBA16I - - \value R32I Equivalent to GL_R32I - \value RG32I Equivalent to GL_RG32I - \value RGB32I Equivalent to GL_RGB32I - \value RGBA32I Equivalent to GL_RGBA32I - - \value R16F Equivalent to GL_R16F - \value RG16F Equivalent to GL_RG16F - \value RGB16F Equivalent to GL_RGB16F - \value RGBA16F Equivalent to GL_RGBA16F - - \value R32F Equivalent to GL_R32F - \value RG32F Equivalent to GL_RG32F - \value RGB32F Equivalent to GL_RGB32F - \value RGBA32F Equivalent to GL_RGBA32F - - \value RGB9E5 Equivalent to GL_RGB9_E5 - \value RG11B10F Equivalent to GL_R11F_G11F_B10F - \value RG3B2 Equivalent to GL_R3_G3_B2 - \value R5G6B5 Equivalent to GL_RGB565 - \value RGB5A1 Equivalent to GL_RGB5_A1 - \value RGBA4 Equivalent to GL_RGBA4 - \value RGB10A2 Equivalent to GL_RGB10_A2UI - - \value D16 Equivalent to GL_DEPTH_COMPONENT16 - \value D24 Equivalent to GL_DEPTH_COMPONENT24 - \value D24S8 Equivalent to GL_DEPTH24_STENCIL8 - \value D32 Equivalent to GL_DEPTH_COMPONENT32 - \value D32F Equivalent to GL_DEPTH_COMPONENT32F - \value D32FS8X24 Equivalent to GL_DEPTH32F_STENCIL8 - \value S8 Equivalent to GL_STENCIL_INDEX8. Introduced in Qt 5.4 - - \value RGB_DXT1 Equivalent to GL_COMPRESSED_RGB_S3TC_DXT1_EXT - \value RGBA_DXT1 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT1_EXT - \value RGBA_DXT3 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT3_EXT - \value RGBA_DXT5 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT5_EXT - \value R_ATI1N_UNorm Equivalent to GL_COMPRESSED_RED_RGTC1 - \value R_ATI1N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RED_RGTC1 - \value RG_ATI2N_UNorm Equivalent to GL_COMPRESSED_RG_RGTC2 - \value RG_ATI2N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG_RGTC2 - \value RGB_BP_UNSIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB - \value RGB_BP_SIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB - \value RGB_BP_UNorm Equivalent to GL_COMPRESSED_RGBA_BPTC_UNORM_ARB - \value R11_EAC_UNorm Equivalent to GL_COMPRESSED_R11_EAC - \value R11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_R11_EAC - \value RG11_EAC_UNorm Equivalent to GL_COMPRESSED_RG11_EAC - \value RG11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG11_EAC - \value RGB8_ETC2 Equivalent to GL_COMPRESSED_RGB8_ETC2 - \value SRGB8_ETC2 Equivalent to GL_COMPRESSED_SRGB8_ETC2 - \value RGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 - \value SRGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 - \value RGBA8_ETC2_EAC Equivalent to GL_COMPRESSED_RGBA8_ETC2_EAC - \value SRGB8_Alpha8_ETC2_EAC Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC - \value RGB8_ETC1 Equivalent to GL_ETC1_RGB8_OES - \value RGBA_ASTC_4x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_4x4_KHR - \value RGBA_ASTC_5x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x4_KHR - \value RGBA_ASTC_5x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x5_KHR - \value RGBA_ASTC_6x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x5_KHR - \value RGBA_ASTC_6x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x6_KHR - \value RGBA_ASTC_8x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x5_KHR - \value RGBA_ASTC_8x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x6_KHR - \value RGBA_ASTC_8x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x8_KHR - \value RGBA_ASTC_10x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x5_KHR - \value RGBA_ASTC_10x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x6_KHR - \value RGBA_ASTC_10x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x8_KHR - \value RGBA_ASTC_10x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x10_KHR - \value RGBA_ASTC_12x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x10_KHR - \value RGBA_ASTC_12x12 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x12_KHR - \value SRGB8_Alpha8_ASTC_4x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR - \value SRGB8_Alpha8_ASTC_5x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR - \value SRGB8_Alpha8_ASTC_5x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR - \value SRGB8_Alpha8_ASTC_6x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR - \value SRGB8_Alpha8_ASTC_6x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR - \value SRGB8_Alpha8_ASTC_8x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR - \value SRGB8_Alpha8_ASTC_8x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR - \value SRGB8_Alpha8_ASTC_8x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR - \value SRGB8_Alpha8_ASTC_10x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR - \value SRGB8_Alpha8_ASTC_10x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR - \value SRGB8_Alpha8_ASTC_10x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR - \value SRGB8_Alpha8_ASTC_10x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR - \value SRGB8_Alpha8_ASTC_12x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR - \value SRGB8_Alpha8_ASTC_12x12 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR - - \value SRGB8 Equivalent to GL_SRGB8 - \value SRGB8_Alpha8 Equivalent to GL_SRGB8_ALPHA8 - \value SRGB_DXT1 Equivalent to GL_COMPRESSED_SRGB_S3TC_DXT1_EXT - \value SRGB_Alpha_DXT1 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT - \value SRGB_Alpha_DXT3 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT - \value SRGB_Alpha_DXT5 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT - \value SRGB_BP_UNorm Equivalent to GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB - - \value DepthFormat Equivalent to GL_DEPTH_COMPONENT (only OpenGL ES 3 or ES 2 with OES_depth_texture) - \value AlphaFormat Equivalent to GL_ALPHA (OpenGL ES 2 only) - \value RGBFormat Equivalent to GL_RGB (OpenGL ES 2 only) - \value RGBAFormat Equivalent to GL_RGBA (OpenGL ES 2 only) - \value LuminanceFormat Equivalent to GL_LUMINANCE (OpenGL ES 2 only) - \value LuminanceAlphaFormat Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only) -*/ - -/*! - \enum QOpenGLTexture::CubeMapFace - This enum defines the possible CubeMap faces. - - \value CubeMapPositiveX Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_X - \value CubeMapNegativeX Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_X - \value CubeMapPositiveY Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Y - \value CubeMapNegativeY Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - \value CubeMapPositiveZ Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Z - \value CubeMapNegativeZ Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Z -*/ - -/*! - \enum QOpenGLTexture::PixelFormat - This enum defines the possible client-side pixel formats for a pixel - transfer operation. - - \value NoSourceFormat Equivalent to GL_NONE - \value Red Equivalent to GL_RED - \value RG Equivalent to GL_RG - \value RGB Equivalent to GL_RGB - \value BGR Equivalent to GL_BGR - \value RGBA Equivalent to GL_RGBA - \value BGRA Equivalent to GL_BGRA - \value Red_Integer Equivalent to GL_RED_INTEGER - \value RG_Integer Equivalent to GL_RG_INTEGER - \value RGB_Integer Equivalent to GL_RGB_INTEGER - \value BGR_Integer Equivalent to GL_BGR_INTEGER - \value RGBA_Integer Equivalent to GL_RGBA_INTEGER - \value BGRA_Integer Equivalent to GL_BGRA_INTEGER - \value Stencil Equivalent to GL_STENCIL_INDEX. Introduced in Qt 5.4 - \value Depth Equivalent to GL_DEPTH_COMPONENT - \value DepthStencil Equivalent to GL_DEPTH_STENCIL - \value Alpha Equivalent to GL_ALPHA (OpenGL ES 2 only) - \value Luminance Equivalent to GL_LUMINANCE (OpenGL ES 2 only) - \value LuminanceAlpha Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only) - -*/ - -/*! - \enum QOpenGLTexture::PixelType - This enum defines the possible pixel data types for a pixel transfer operation - - \value NoPixelType Equivalent to GL_NONE - \value Int8 Equivalent to GL_BYTE - \value UInt8 Equivalent to GL_UNSIGNED_BYTE - \value Int16 Equivalent to GL_SHORT - \value UInt16 Equivalent to GL_UNSIGNED_SHORT - \value Int32 Equivalent to GL_INT - \value UInt32 Equivalent to GL_UNSIGNED_INT - \value Float16 Equivalent to GL_HALF_FLOAT - \value Float16OES Equivalent to GL_HALF_FLOAT_OES - \value Float32 Equivalent to GL_FLOAT - \value UInt32_RGB9_E5 Equivalent to GL_UNSIGNED_INT_5_9_9_9_REV - \value UInt32_RG11B10F Equivalent to GL_UNSIGNED_INT_10F_11F_11F_REV - \value UInt8_RG3B2 Equivalent to GL_UNSIGNED_BYTE_3_3_2 - \value UInt8_RG3B2_Rev Equivalent to GL_UNSIGNED_BYTE_2_3_3_REV - \value UInt16_RGB5A1 Equivalent to GL_UNSIGNED_SHORT_5_5_5_1 - \value UInt16_RGB5A1_Rev Equivalent to GL_UNSIGNED_SHORT_1_5_5_5_REV - \value UInt16_R5G6B5 Equivalent to GL_UNSIGNED_SHORT_5_6_5 - \value UInt16_R5G6B5_Rev Equivalent to GL_UNSIGNED_SHORT_5_6_5_REV - \value UInt16_RGBA4 Equivalent to GL_UNSIGNED_SHORT_4_4_4_4 - \value UInt16_RGBA4_Rev Equivalent to GL_UNSIGNED_SHORT_4_4_4_4_REV - \value UInt32_RGBA8 Equivalent to GL_UNSIGNED_INT_8_8_8_8 - \value UInt32_RGBA8_Rev Equivalent to GL_UNSIGNED_INT_8_8_8_8_REV - \value UInt32_RGB10A2 Equivalent to GL_UNSIGNED_INT_10_10_10_2 - \value UInt32_RGB10A2_Rev Equivalent to GL_UNSIGNED_INT_2_10_10_10_REV - \value UInt32_D24S8 Equivalent to GL_UNSIGNED_INT_24_8. Introduced in Qt 5.4 - \value Float32_D32_UInt32_S8_X24 Equivalent to GL_FLOAT_32_UNSIGNED_INT_24_8_REV. Introduced in Qt 5.4 -*/ - -/*! - \enum QOpenGLTexture::Feature - This enum defines the OpenGL texture-related features that can be tested for. - - \value ImmutableStorage Support for immutable texture storage - \value ImmutableMultisampleStorage Support for immutable texture storage with - multisample targets - \value TextureRectangle Support for the GL_TEXTURE_RECTANGLE target - \value TextureArrays Support for texture targets with array layers - \value Texture3D Support for the 3 dimensional texture target - \value TextureMultisample Support for texture targets that have multisample capabilities - \value TextureBuffer Support for textures that use OpenGL buffer objects - as their data source - \value TextureCubeMapArrays Support for cubemap array texture target - \value Swizzle Support for texture component swizzle masks - \value StencilTexturing Support for stencil texturing (i.e. looking up depth or stencil - components of a combined depth/stencil format texture in GLSL shaders). - \value AnisotropicFiltering Support for anisotropic texture filtering - \value NPOTTextures Basic support for non-power-of-two textures - \value NPOTTextureRepeat Full support for non-power-of-two textures including texture - repeat modes - \value Texture1D Support for the 1 dimensional texture target - \value TextureComparisonOperators Support for texture comparison operators - \value TextureMipMapLevel Support for setting the base and maximum mipmap levels -*/ - -/*! - \enum QOpenGLTexture::SwizzleComponent - This enum defines the texture color components that can be assigned a swizzle mask. - - \value SwizzleRed The red component. Equivalent to GL_TEXTURE_SWIZZLE_R - \value SwizzleGreen The green component. Equivalent to GL_TEXTURE_SWIZZLE_G - \value SwizzleBlue The blue component. Equivalent to GL_TEXTURE_SWIZZLE_B - \value SwizzleAlpha The alpha component. Equivalent to GL_TEXTURE_SWIZZLE_A -*/ - -/*! - \enum QOpenGLTexture::SwizzleValue - This enum defines the possible mask values for texture swizzling. - - \value RedValue Maps the component to the red channel. Equivalent to GL_RED - \value GreenValue Maps the component to the green channel. Equivalent to GL_GREEN - \value BlueValue Maps the component to the blue channel. Equivalent to GL_BLUE - \value AlphaValue Maps the component to the alpha channel. Equivalent to GL_ALPHA - \value ZeroValue Maps the component to a fixed value of 0. Equivalent to GL_ZERO - \value OneValue Maps the component to a fixed value of 1. Equivalent to GL_ONE -*/ - -/*! - \enum QOpenGLTexture::WrapMode - This enum defines the possible texture coordinate wrapping modes. - - \value Repeat Texture coordinate is repeated. Equivalent to GL_REPEAT - \value MirroredRepeat Texture coordinate is reflected about 0 and 1. Equivalent to GL_MIRRORED_REPEAT - \value ClampToEdge Clamps the texture coordinates to [0,1]. Equivalent to GL_CLAMP_TO_EDGE - \value ClampToBorder As for ClampToEdge but also blends samples at 0 and 1 with a - fixed border color. Equivalent to GL_CLAMP_TO_BORDER -*/ - -/*! - \enum QOpenGLTexture::CoordinateDirection - This enum defines the possible texture coordinate directions - - \value DirectionS The horizontal direction. Equivalent to GL_TEXTURE_WRAP_S - \value DirectionT The vertical direction. Equivalent to GL_TEXTURE_WRAP_T - \value DirectionR The depth direction. Equivalent to GL_TEXTURE_WRAP_R -*/ - -/*! - Creates a QOpenGLTexture object that can later be bound to \a target. - - This does not create the underlying OpenGL texture object. Therefore, - construction using this constructor does not require a valid current - OpenGL context. -*/ -QOpenGLTexture::QOpenGLTexture(Target target) - : d_ptr(new QOpenGLTexturePrivate(target, this)) -{ -} - -/*! - Creates a QOpenGLTexture object that can later be bound to the 2D texture - target and contains the pixel data contained in \a image. If you wish - to have a chain of mipmaps generated then set \a genMipMaps to \c true (this - is the default). - - This does create the underlying OpenGL texture object. Therefore, - construction using this constructor does require a valid current - OpenGL context. -*/ -QOpenGLTexture::QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps) - : QOpenGLTexture(QOpenGLTexture::Target2D) -{ - setData(image, genMipMaps); -} - -QOpenGLTexture::~QOpenGLTexture() -{ -} - -/*! - Returns the binding target of this texture. - - \since 5.4 -*/ -QOpenGLTexture::Target QOpenGLTexture::target() const -{ - Q_D(const QOpenGLTexture); - return d->target; -} - -/*! - Creates the underlying OpenGL texture object. This requires a current valid - OpenGL context. If the texture object already exists, this function does - nothing. - - Once the texture object is created you can obtain the object - name from the textureId() function. This may be useful if you wish to make - some raw OpenGL calls related to this texture. - - Normally it should not be necessary to call this function directly as all - functions that set properties of the texture object implicitly call create() - on your behalf. - - Returns \c true if the creation succeeded, otherwise returns \c false. - - \sa destroy(), isCreated(), textureId() -*/ -bool QOpenGLTexture::create() -{ - Q_D(QOpenGLTexture); - return d->create(); -} - -/*! - Destroys the underlying OpenGL texture object. This requires a current valid - OpenGL context. - - \sa create(), isCreated(), textureId() -*/ -void QOpenGLTexture::destroy() -{ - Q_D(QOpenGLTexture); - return d->destroy(); -} - -/*! - Returns \c true if the underlying OpenGL texture object has been created. - - \sa create(), destroy(), textureId() -*/ -bool QOpenGLTexture::isCreated() const -{ - Q_D(const QOpenGLTexture); - return d->textureId != 0; -} - -/*! - Returns the name of the underlying OpenGL texture object or 0 if it has - not yet been created. - - \sa create(), destroy(), isCreated() -*/ -GLuint QOpenGLTexture::textureId() const -{ - Q_D(const QOpenGLTexture); - return d->textureId; -} - -/*! - Binds this texture to the currently active texture unit ready for - rendering. Note that you do not need to bind QOpenGLTexture objects - in order to modify them as the implementation makes use of the - EXT_direct_state_access extension where available and simulates it - where it is not. - - \sa release() -*/ -void QOpenGLTexture::bind() -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->bind(); -} - -/*! - Binds this texture to texture unit \a unit ready for - rendering. Note that you do not need to bind QOpenGLTexture objects - in order to modify them as the implementation makes use of the - EXT_direct_state_access extension where available and simulates it - where it is not. - - If parameter \a reset is \c true then this function will restore - the active unit to the texture unit that was active upon entry. - - \sa release() -*/ -void QOpenGLTexture::bind(uint unit, TextureUnitReset reset) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->bind(unit, reset); -} - -/*! - Unbinds this texture from the currently active texture unit. - - \sa bind() -*/ -void QOpenGLTexture::release() -{ - Q_D(QOpenGLTexture); - d->release(); -} - -/*! - Unbinds this texture from texture unit \a unit. - - If parameter \a reset is \c true then this function - will restore the active unit to the texture unit that was active - upon entry. -*/ -void QOpenGLTexture::release(uint unit, TextureUnitReset reset) -{ - Q_D(QOpenGLTexture); - d->release(unit, reset); -} - -/*! - Returns \c true if this texture is bound to the corresponding target - of the currently active texture unit. - - \sa bind(), release() -*/ -bool QOpenGLTexture::isBound() const -{ - Q_D(const QOpenGLTexture); - Q_ASSERT(d->textureId); - return d->isBound(); -} - -/*! - Returns \c true if this texture is bound to the corresponding target - of texture unit \a unit. - - \sa bind(), release() -*/ -bool QOpenGLTexture::isBound(uint unit) -{ - Q_D(const QOpenGLTexture); - Q_ASSERT(d->textureId); - return d->isBound(unit); -} - -/*! - Returns the textureId of the texture that is bound to the \a target - of the currently active texture unit. -*/ -GLuint QOpenGLTexture::boundTextureId(BindingTarget target) -{ - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (!ctx) { - qWarning("QOpenGLTexture::boundTextureId() requires a valid current context"); - return 0; - } - - GLint textureId = 0; - ctx->functions()->glGetIntegerv(target, &textureId); - return static_cast<GLuint>(textureId); -} - -/*! - Returns the textureId of the texture that is bound to the \a target - of the texture unit \a unit. -*/ -GLuint QOpenGLTexture::boundTextureId(uint unit, BindingTarget target) -{ - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (!ctx) { - qWarning("QOpenGLTexture::boundTextureId() requires a valid current context"); - return 0; - } - - QOpenGLFunctions *funcs = ctx->functions(); - funcs->initializeOpenGLFunctions(); - - GLint oldTextureUnit = 0; - funcs->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit); - - funcs->glActiveTexture(unit); - GLint textureId = 0; - funcs->glGetIntegerv(target, &textureId); - funcs->glActiveTexture(oldTextureUnit); - - return static_cast<GLuint>(textureId); -} - -/*! - Sets the format of this texture object to \a format. This function - must be called before texture storage is allocated. - - Note that all formats may not be supported. The exact set of supported - formats is dependent upon your OpenGL implementation and version. - - \sa format(), allocateStorage() -*/ -void QOpenGLTexture::setFormat(TextureFormat format) -{ - Q_D(QOpenGLTexture); - d->create(); - if (isStorageAllocated()) { - qWarning("QOpenGLTexture::setFormat(): Cannot change format once storage has been allocated"); - return; - } - - d->format = format; - - switch (format) { - case NoFormat: - d->formatClass = NoFormatClass; - break; - - case RGBA32F: - case RGBA32U: - case RGBA32I: - d->formatClass = FormatClass_128Bit; - break; - - case RGB32F: - case RGB32U: - case RGB32I: - d->formatClass = FormatClass_96Bit; - break; - - case RGBA16F: - case RG32F: - case RGBA16U: - case RG32U: - case RGBA16I: - case RG32I: - case RGBA16_UNorm: - case RGBA16_SNorm: - d->formatClass = FormatClass_64Bit; - break; - - case RGB16_UNorm: - case RGB16_SNorm: - case RGB16F: - case RGB16U: - case RGB16I: - d->formatClass = FormatClass_48Bit; - break; - - case RG16F: - case RG11B10F: - case R32F: - case RGB10A2: - case RGBA8U: - case RG16U: - case R32U: - case RGBA8I: - case RG16I: - case R32I: - case RGBA8_UNorm: - case RG16_UNorm: - case RGBA8_SNorm: - case RG16_SNorm: - case SRGB8_Alpha8: - case RGB9E5: - d->formatClass = FormatClass_32Bit; - break; - - case RGB8_UNorm: - case RGB8_SNorm: - case SRGB8: - case RGB8U: - case RGB8I: - d->formatClass = FormatClass_24Bit; - break; - - case R16F: - case RG8U: - case R16U: - case RG8I: - case R16I: - case RG8_UNorm: - case R16_UNorm: - case RG8_SNorm: - case R16_SNorm: - d->formatClass = FormatClass_16Bit; - break; - - case R8U: - case R8I: - case R8_UNorm: - case R8_SNorm: - d->formatClass = FormatClass_8Bit; - break; - - case R_ATI1N_UNorm: - case R_ATI1N_SNorm: - d->formatClass = FormatClass_RGTC1_R; - break; - - case RG_ATI2N_UNorm: - case RG_ATI2N_SNorm: - d->formatClass = FormatClass_RGTC2_RG; - break; - - case RGB_BP_UNorm: - case SRGB_BP_UNorm: - d->formatClass = FormatClass_BPTC_Unorm; - break; - - case RGB_BP_UNSIGNED_FLOAT: - case RGB_BP_SIGNED_FLOAT: - d->formatClass = FormatClass_BPTC_Float; - break; - - case RGB_DXT1: - case SRGB_DXT1: - d->formatClass = FormatClass_S3TC_DXT1_RGB; - break; - - case RGBA_DXT1: - case SRGB_Alpha_DXT1: - d->formatClass = FormatClass_S3TC_DXT1_RGBA; - break; - - case RGBA_DXT3: - case SRGB_Alpha_DXT3: - d->formatClass = FormatClass_S3TC_DXT3_RGBA; - break; - - case RGBA_DXT5: - case SRGB_Alpha_DXT5: - d->formatClass = FormatClass_S3TC_DXT5_RGBA; - break; - - case QOpenGLTexture::R11_EAC_UNorm: - case QOpenGLTexture::R11_EAC_SNorm: - case QOpenGLTexture::RG11_EAC_UNorm: - case QOpenGLTexture::RG11_EAC_SNorm: - case QOpenGLTexture::RGB8_ETC2: - case QOpenGLTexture::SRGB8_ETC2: - case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2: - case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2: - case QOpenGLTexture::RGBA8_ETC2_EAC: - case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC: - case QOpenGLTexture::RGB8_ETC1: - case RG3B2: - case R5G6B5: - case RGB5A1: - case RGBA4: - case D16: - case D24: - case D24S8: - case D32: - case D32F: - case D32FS8X24: - case S8: - case DepthFormat: - case AlphaFormat: - case RGBFormat: - case RGBAFormat: - case LuminanceFormat: - case LuminanceAlphaFormat: - case QOpenGLTexture::RGBA_ASTC_4x4: - case QOpenGLTexture::RGBA_ASTC_5x4: - case QOpenGLTexture::RGBA_ASTC_5x5: - case QOpenGLTexture::RGBA_ASTC_6x5: - case QOpenGLTexture::RGBA_ASTC_6x6: - case QOpenGLTexture::RGBA_ASTC_8x5: - case QOpenGLTexture::RGBA_ASTC_8x6: - case QOpenGLTexture::RGBA_ASTC_8x8: - case QOpenGLTexture::RGBA_ASTC_10x5: - case QOpenGLTexture::RGBA_ASTC_10x6: - case QOpenGLTexture::RGBA_ASTC_10x8: - case QOpenGLTexture::RGBA_ASTC_10x10: - case QOpenGLTexture::RGBA_ASTC_12x10: - case QOpenGLTexture::RGBA_ASTC_12x12: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10: - case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12: - d->formatClass = FormatClass_Unique; - break; - } -} - -/*! - Returns the format of this texture object. - - \sa setFormat() -*/ -QOpenGLTexture::TextureFormat QOpenGLTexture::format() const -{ - Q_D(const QOpenGLTexture); - return d->format; -} - -static bool isNpot(int width, int height = 1, int depth = 1) -{ - return width & (width-1) || height & (height-1) || depth & (depth-1); -} - -/*! - Sets the dimensions of this texture object to \a width, - \a height, and \a depth. The default for each dimension is 1. - The maximum allowable texture size is dependent upon your OpenGL - implementation. Allocating storage for a texture less than the - maximum size can still fail if your system is low on resources. - - If a non-power-of-two \a width, \a height or \a depth is provided and your - OpenGL implementation doesn't have support for repeating non-power-of-two - textures, then the wrap mode is automatically set to ClampToEdge. - - \sa width(), height(), depth() -*/ -void QOpenGLTexture::setSize(int width, int height, int depth) -{ - Q_D(QOpenGLTexture); - d->create(); - if (isStorageAllocated()) { - qWarning("Cannot resize a texture that already has storage allocated.\n" - "To do so, destroy() the texture and then create() and setSize()"); - return; - } - - if (isNpot(width, height, depth) && !hasFeature(Feature::NPOTTextureRepeat) && d->target != Target::TargetRectangle) - d->setWrapMode(WrapMode::ClampToEdge); - - switch (d->target) { - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::TargetBuffer: - d->dimensions[0] = width; - Q_UNUSED(height); - Q_UNUSED(depth); - break; - - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::TargetRectangle: - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - d->dimensions[0] = width; - d->dimensions[1] = height; - Q_UNUSED(depth); - break; - - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - if (width != height) - qWarning("QAbstractOpenGLTexture::setSize(): Cube map textures must be square"); - d->dimensions[0] = d->dimensions[1] = width; - Q_UNUSED(depth); - break; - - case QOpenGLTexture::Target3D: - d->dimensions[0] = width; - d->dimensions[1] = height; - d->dimensions[2] = depth; - break; - } -} - -/*! - Returns the width of a 1D, 2D or 3D texture. - - \sa height(), depth(), setSize() -*/ -int QOpenGLTexture::width() const -{ - Q_D(const QOpenGLTexture); - return d->dimensions[0]; -} - -/*! - Returns the height of a 2D or 3D texture. - - \sa width(), depth(), setSize() -*/ -int QOpenGLTexture::height() const -{ - Q_D(const QOpenGLTexture); - return d->dimensions[1]; -} - -/*! - Returns the depth of a 3D texture. - - \sa width(), height(), setSize() -*/ -int QOpenGLTexture::depth() const -{ - Q_D(const QOpenGLTexture); - return d->dimensions[2]; -} - -/*! - For texture targets that support mipmaps, this function - sets the requested number of mipmap \a levels to allocate storage - for. This function should be called before storage is allocated - for the texture. - - If the texture target does not support mipmaps this function - has no effect. - - \sa mipLevels(), maximumMipLevels(), isStorageAllocated() -*/ -void QOpenGLTexture::setMipLevels(int levels) -{ - Q_D(QOpenGLTexture); - d->create(); - if (isStorageAllocated()) { - qWarning("Cannot set mip levels on a texture that already has storage allocated.\n" - "To do so, destroy() the texture and then create() and setMipLevels()"); - return; - } - - switch (d->target) { - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - case QOpenGLTexture::Target3D: - d->requestedMipLevels = levels; - break; - - case QOpenGLTexture::TargetBuffer: - case QOpenGLTexture::TargetRectangle: - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - qWarning("QAbstractOpenGLTexture::setMipLevels(): This texture target does not support mipmaps"); - break; - } -} - -/*! - Returns the number of mipmap levels for this texture. If storage - has not yet been allocated for this texture it returns the - requested number of mipmap levels. - - \sa setMipLevels(), maximumMipLevels(), isStorageAllocated() -*/ -int QOpenGLTexture::mipLevels() const -{ - Q_D(const QOpenGLTexture); - return isStorageAllocated() ? d->mipLevels : d->requestedMipLevels; -} - -/*! - Returns the maximum number of mipmap levels that this texture - can have given the current dimensions. - - \sa setMipLevels(), mipLevels(), setSize() -*/ -int QOpenGLTexture::maximumMipLevels() const -{ - Q_D(const QOpenGLTexture); - return d->maximumMipLevelCount(); -} - -/*! - Sets the number of array \a layers to allocate storage for. This - function should be called before storage is allocated for the texture. - - For targets that do not support array layers this function has - no effect. - - \sa layers(), isStorageAllocated() -*/ -void QOpenGLTexture::setLayers(int layers) -{ - Q_D(QOpenGLTexture); - d->create(); - if (isStorageAllocated()) { - qWarning("Cannot set layers on a texture that already has storage allocated.\n" - "To do so, destroy() the texture and then create() and setLayers()"); - return; - } - - switch (d->target) { - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::TargetCubeMapArray: - case QOpenGLTexture::Target2DMultisampleArray: - d->layers = layers; - break; - - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target3D: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetBuffer: - case QOpenGLTexture::TargetRectangle: - case QOpenGLTexture::Target2DMultisample: - qWarning("Texture target does not support array layers"); - break; - } -} - -/*! - Returns the number of array layers for this texture. If - storage has not yet been allocated for this texture then - this function returns the requested number of array layers. - - For texture targets that do not support array layers this - will return 1. - - \sa setLayers(), isStorageAllocated() -*/ -int QOpenGLTexture::layers() const -{ - Q_D(const QOpenGLTexture); - return d->layers; -} - -/*! - Returns the number of faces for this texture. For cubemap - and cubemap array type targets this will be 6. - - For non-cubemap type targets this will return 1. -*/ -int QOpenGLTexture::faces() const -{ - Q_D(const QOpenGLTexture); - return d->faces; -} - -/*! - Sets the number of \a samples to allocate storage for when rendering to - a multisample capable texture target. This function should - be called before storage is allocated for the texture. - - For targets that do not support multisampling this function has - no effect. - - \sa samples(), isStorageAllocated() -*/ -void QOpenGLTexture::setSamples(int samples) -{ - Q_D(QOpenGLTexture); - d->create(); - if (isStorageAllocated()) { - qWarning("Cannot set sample count on a texture that already has storage allocated.\n" - "To do so, destroy() the texture and then create() and setSamples()"); - return; - } - - switch (d->target) { - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - d->samples = samples; - break; - - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target3D: - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - case QOpenGLTexture::TargetBuffer: - case QOpenGLTexture::TargetRectangle: - - qWarning("Texture target does not support multisampling"); - break; - } -} - -/*! - Returns the number of multisample sample points for this texture. - If storage has not yet been allocated for this texture then - this function returns the requested number of samples. - - For texture targets that do not support multisampling this - will return 0. - - \sa setSamples(), isStorageAllocated() -*/ -int QOpenGLTexture::samples() const -{ - Q_D(const QOpenGLTexture); - return d->samples; -} - -/*! - Sets whether the sample positions and number of samples used with - a multisample capable texture target to \a fixed. If set to \c true - the sample positions and number of samples used are the same for - all texels in the image and will not depend upon the image size or - internal format. This function should be called before storage is allocated - for the texture. - - For targets that do not support multisampling this function has - no effect. - - The default value is \c true. - - \sa isFixedSamplePositions(), isStorageAllocated() -*/ -void QOpenGLTexture::setFixedSamplePositions(bool fixed) -{ - Q_D(QOpenGLTexture); - d->create(); - if (isStorageAllocated()) { - qWarning("Cannot set sample positions on a texture that already has storage allocated.\n" - "To do so, destroy() the texture and then create() and setFixedSamplePositions()"); - return; - } - - switch (d->target) { - case QOpenGLTexture::Target2DMultisample: - case QOpenGLTexture::Target2DMultisampleArray: - d->fixedSamplePositions = fixed; - break; - - case QOpenGLTexture::Target1D: - case QOpenGLTexture::Target2D: - case QOpenGLTexture::Target3D: - case QOpenGLTexture::Target1DArray: - case QOpenGLTexture::Target2DArray: - case QOpenGLTexture::TargetCubeMap: - case QOpenGLTexture::TargetCubeMapArray: - case QOpenGLTexture::TargetBuffer: - case QOpenGLTexture::TargetRectangle: - - qWarning("Texture target does not support multisampling"); - break; - } -} - -/*! - Returns whether this texture uses a fixed pattern of multisample - samples. If storage has not yet been allocated for this texture then - this function returns the requested fixed sample position setting. - - For texture targets that do not support multisampling this - will return \c true. - - \sa setFixedSamplePositions(), isStorageAllocated() -*/ -bool QOpenGLTexture::isFixedSamplePositions() const -{ - Q_D(const QOpenGLTexture); - return d->fixedSamplePositions; -} - -/*! - Allocates server-side storage for this texture object taking - into account, the format, dimensions, mipmap levels, array - layers and cubemap faces. - - Once storage has been allocated it is no longer possible to change - these properties. - - If supported QOpenGLTexture makes use of immutable texture - storage. - - Once storage has been allocated for the texture then pixel data - can be uploaded via one of the setData() overloads. - - \note If immutable texture storage is not available, - then a default pixel format and pixel type will be used to - create the mutable storage. You can use the other - allocateStorage() overload to specify exactly the pixel format - and the pixel type to use when allocating mutable storage; - this is particulary useful under certain OpenGL ES implementations - (notably, OpenGL ES 2), where the pixel format and the pixel type - used at allocation time must perfectly match the format - and the type passed to any subsequent setData() call. - - \sa isStorageAllocated(), setData() -*/ -void QOpenGLTexture::allocateStorage() -{ - Q_D(QOpenGLTexture); - if (d->create()) { - const QOpenGLTexture::PixelFormat pixelFormat = pixelFormatCompatibleWithInternalFormat(d->format); - const QOpenGLTexture::PixelType pixelType = pixelTypeCompatibleWithInternalFormat(d->format); - d->allocateStorage(pixelFormat, pixelType); - } -} - -/*! - \since 5.5 - - Allocates server-side storage for this texture object taking - into account, the format, dimensions, mipmap levels, array - layers and cubemap faces. - - Once storage has been allocated it is no longer possible to change - these properties. - - If supported QOpenGLTexture makes use of immutable texture - storage. However, if immutable texture storage is not available, - then the specified \a pixelFormat and \a pixelType will be used - to allocate mutable storage; note that in certain OpenGL implementations - (notably, OpenGL ES 2) they must perfectly match the format - and the type passed to any subsequent setData() call. - - Once storage has been allocated for the texture then pixel data - can be uploaded via one of the setData() overloads. - - \sa isStorageAllocated(), setData() -*/ -void QOpenGLTexture::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType) -{ - Q_D(QOpenGLTexture); - if (d->create()) - d->allocateStorage(pixelFormat, pixelType); -} - -/*! - Returns \c true if server-side storage for this texture as been - allocated. - - The texture format, dimensions, mipmap levels and array layers - cannot be altered once storage ihas been allocated. - - \sa allocateStorage(), setSize(), setMipLevels(), setLayers(), setFormat() -*/ -bool QOpenGLTexture::isStorageAllocated() const -{ - Q_D(const QOpenGLTexture); - return d->storageAllocated; -} - -/*! - Attempts to create a texture view onto this texture. A texture - view is somewhat analogous to a view in SQL in that it presents - a restricted or reinterpreted view of the original data. Texture - views do not allocate any more server-side storage, insted relying - on the storage buffer of the source texture. - - Texture views are only available when using immutable storage. For - more information on texture views see - http://www.opengl.org/wiki/Texture_Storage#Texture_views. - - The \a target argument specifies the target to use for the view. - Only some targets can be used depending upon the target of the original - target. For e.g. a view onto a Target1DArray texture can specify - either Target1DArray or Target1D but for the latter the number of - array layers specified with \a minimumLayer and \a maximumLayer must - be exactly 1. - - Simpliar constraints apply for the \a viewFormat. See the above link - and the specification for more details. - - The \a minimumMipmapLevel, \a maximumMipmapLevel, \a minimumLayer, - and \a maximumLayer arguments serve to restrict the parts of the - texture accessible by the texture view. - - If creation of the texture view fails this function will return - 0. If the function succeeds it will return a pointer to a new - QOpenGLTexture object that will return \c true from its isTextureView() - function. - - \sa isTextureView() -*/ -QOpenGLTexture *QOpenGLTexture::createTextureView(Target target, - TextureFormat viewFormat, - int minimumMipmapLevel, int maximumMipmapLevel, - int minimumLayer, int maximumLayer) const -{ - Q_D(const QOpenGLTexture); - if (!isStorageAllocated()) { - qWarning("Cannot set create a texture view of a texture that does not have storage allocated."); - return nullptr; - } - Q_ASSERT(maximumMipmapLevel >= minimumMipmapLevel); - Q_ASSERT(maximumLayer >= minimumLayer); - return d->createTextureView(target, viewFormat, - minimumMipmapLevel, maximumMipmapLevel, - minimumLayer, maximumLayer); -} - -/*! - Returns \c true if this texture object is actually a view onto another - texture object. - - \sa createTextureView() -*/ -bool QOpenGLTexture::isTextureView() const -{ - Q_D(const QOpenGLTexture); - Q_ASSERT(d->textureId); - return d->textureView; -} - -/*! - Uploads pixel \a data for this texture object \a mipLevel, array \a layer, and \a cubeFace. - Storage must have been allocated before uploading pixel data. Some overloads of setData() - will set appropriate dimensions, mipmap levels, and array layers and then allocate storage - for you if they have enough information to do so. This will be noted in the function - documentation. - - The structure of the pixel data pointed to by \a data is specified by \a sourceFormat - and \a sourceType. The pixel data upload can optionally be controlled by \a options. - - If using a compressed format() then you should use setCompressedData() instead of this - function. - - \since 5.3 - \sa setCompressedData() -*/ -void QOpenGLTexture::setData(int mipLevel, int layer, CubeMapFace cubeFace, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - if (!isStorageAllocated()) { - qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocateStorage() before this function"); - return; - } - d->setData(mipLevel, layer, 1, cubeFace, sourceFormat, sourceType, data, options); -} - -/*! - \since 5.9 - \overload - - Parameter \a layerCount is the number of layers in a texture array - that are being uploaded/populated by this call. -*/ -void QOpenGLTexture::setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType, const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - if (!isStorageAllocated()) { - qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocateStorage() before this function"); - return; - } - d->setData(mipLevel, layer, layerCount, cubeFace, sourceFormat, sourceType, data, options); -} - -/*! - \since 5.3 - \overload -*/ -void QOpenGLTexture::setData(int mipLevel, int layer, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options); -} - -/*! - \since 5.3 - \overload -*/ -void QOpenGLTexture::setData(int mipLevel, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options); -} - -/*! - \since 5.3 - \overload -*/ -void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options); -} - -/*! - \since 5.14 - \overload - - This overload is to be used to update a part of the texture. Parameters \a - xOffset, \a yOffset, \a zOffset specify the texel offsets within the - texture. Parameters \a width, \a height and \a depth specify the dimensions - of the sub image. - - The structure of the pixel data pointed to by \a data is specified by \a - sourceFormat and \a sourceType. The pixel data upload can optionally be - controlled by \a options. -*/ -void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(xOffset, yOffset, zOffset, - width, height, depth, - 0, 0, 1, - QOpenGLTexture::CubeMapPositiveX, sourceFormat, - sourceType, data, options); -} - -/*! - \since 5.14 - \overload - - This overload is to be used to update a part of the texture. Parameters \a - xOffset, \a yOffset, \a zOffset specify the texel offsets within the - texture. Parameters \a width, \a height and \a depth specify the dimensions - of the sub image. The mip map level the sub image we want to - update is specified with \a mipLevel. - - The structure of the pixel data pointed to by \a data is specified by \a - sourceFormat and \a sourceType. The pixel data upload can optionally be - controlled by \a options. -*/ -void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, - int mipLevel, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(xOffset, yOffset, zOffset, - width, height, depth, - mipLevel, 0, 1, - QOpenGLTexture::CubeMapPositiveX, sourceFormat, - sourceType, data, options); -} - -/*! - \since 5.14 - \overload - - This overload is to be used to update a part of the texture. Parameters \a - xOffset, \a yOffset, \a zOffset specify the texel offsets within the - texture. Parameters \a width, \a height and \a depth specify the dimensions - of the sub image. The mip map level and layerof the sub image we want to - update are specified with \a mipLevel and \a layer. - - The structure of the pixel data pointed to by \a data is specified by \a - sourceFormat and \a sourceType. The pixel data upload can optionally be - controlled by \a options. -*/ -void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, - int mipLevel, int layer, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(xOffset, yOffset, zOffset, - width, height, depth, - mipLevel, layer, 1, - QOpenGLTexture::CubeMapPositiveX, sourceFormat, - sourceType, data, options); -} - -/*! - \since 5.14 - \overload - - This overload is to be used to update a part of the texture. Parameters \a - xOffset, \a yOffset, \a zOffset specify the texel offsets within the - texture. Parameters \a width, \a height and \a depth specify the dimensions - of the sub image.The mip map level, layer and cube map face of the sub - image we want to update are specified with \a mipLevel, \a layer and \a - face. - - The structure of the pixel data pointed to by \a data is specified by \a - sourceFormat and \a sourceType. The pixel data upload can optionally be - controlled by \a options. -*/ -void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, - int mipLevel, int layer, - CubeMapFace face, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(xOffset, yOffset, zOffset, - width, height, depth, - mipLevel, layer, 1, - face, sourceFormat, - sourceType, data, options); -} - -/*! - \since 5.14 - \overload - - This overload is to be used to update a part of the texture. Parameters \a - xOffset, \a yOffset, \a zOffset specify the texel offsets within the - texture. Parameters \a width, \a height and \a depth specify the dimensions - of the sub image.The mip map level, starting layer, cube map face and - number of layers of the sub image we want to update are specified with \a - mipLevel, \a layer, \a face and \a layerCount. - - The structure of the pixel data pointed to by \a data is specified by \a - sourceFormat and \a sourceType. The pixel data upload can optionally be - controlled by \a options. -*/ -void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, - int mipLevel, int layer, - CubeMapFace face, int layerCount, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(xOffset, yOffset, zOffset, - width, height, depth, - mipLevel, layer, layerCount, - face, sourceFormat, - sourceType, data, options); -} - -#if QT_DEPRECATED_SINCE(5, 3) -/*! - \obsolete - \overload - - \sa setCompressedData() -*/ -void QOpenGLTexture::setData(int mipLevel, int layer, CubeMapFace cubeFace, - PixelFormat sourceFormat, PixelType sourceType, - void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - if (!isStorageAllocated()) { - qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocateStorage() before this function"); - return; - } - d->setData(mipLevel, layer, 1, cubeFace, sourceFormat, sourceType, data, options); -} - -/*! - \obsolete - \overload -*/ -void QOpenGLTexture::setData(int mipLevel, int layer, - PixelFormat sourceFormat, PixelType sourceType, - void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options); -} - -/*! - \obsolete - \overload -*/ -void QOpenGLTexture::setData(int mipLevel, - PixelFormat sourceFormat, PixelType sourceType, - void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options); -} - -/*! - \obsolete - \overload -*/ -void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType, - void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options); -} -#endif - -/*! - This overload of setData() will allocate storage for you. - The pixel data is contained in \a image. Mipmaps are generated by default. - Set \a genMipMaps to \l DontGenerateMipMaps to turn off mipmap generation. - - \overload -*/ -void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps) -{ - QOpenGLContext *context = QOpenGLContext::currentContext(); - if (!context) { - qWarning("QOpenGLTexture::setData() requires a valid current context"); - return; - } - - if (image.isNull()) { - qWarning("QOpenGLTexture::setData() tried to set a null image"); - return; - } - - if (context->isOpenGLES() && context->format().majorVersion() < 3) - setFormat(QOpenGLTexture::RGBAFormat); - else - setFormat(QOpenGLTexture::RGBA8_UNorm); - - setSize(image.width(), image.height()); - setMipLevels(genMipMaps == GenerateMipMaps ? maximumMipLevels() : 1); - allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8); - - // Upload pixel data and generate mipmaps - QImage glImage = image.convertToFormat(QImage::Format_RGBA8888); - QOpenGLPixelTransferOptions uploadOptions; - uploadOptions.setAlignment(1); - setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, glImage.constBits(), &uploadOptions); -} - -/*! - Uploads compressed pixel \a data to \a mipLevel, array \a layer, and \a cubeFace. - The pixel transfer can optionally be controlled with \a options. The \a dataSize - argument should specify the size of the data pointed to by \a data. - - If not using a compressed format() then you should use setData() instead of this - function. - - \since 5.3 -*/ -void QOpenGLTexture::setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace, - int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - if (!isStorageAllocated()) { - qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocateStorage() before this function"); - return; - } - d->setCompressedData(mipLevel, layer, 1, cubeFace, dataSize, data, options); -} - -/*! - \since 5.9 - \overload - - Parameter \a layerCount is the number of layers in a texture array - that are being uploaded/populated by this call. -*/ -void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, int dataSize, const void *data, const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - if (!isStorageAllocated()) { - qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocateStorage() before this function"); - return; - } - d->setCompressedData(mipLevel, layer, layerCount, cubeFace, dataSize, data, options); -} - -/*! - \overload -*/ -void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setCompressedData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options); -} - -/*! - \overload -*/ -void QOpenGLTexture::setCompressedData(int mipLevel, int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setCompressedData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options); -} - -/*! - \overload -*/ -void QOpenGLTexture::setCompressedData(int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setCompressedData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options); -} - -#if QT_DEPRECATED_SINCE(5, 3) -/*! - \obsolete - \overload -*/ -void QOpenGLTexture::setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace, - int dataSize, void *data, - const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - if (!isStorageAllocated()) { - qWarning("Cannot set data on a texture that does not have storage allocated.\n" - "To do so call allocateStorage() before this function"); - return; - } - d->setCompressedData(mipLevel, layer, 1, cubeFace, dataSize, data, options); -} - -/*! - \obsolete - \overload -*/ -void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int dataSize, void *data, - const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setCompressedData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options); -} - -/*! - \obsolete - \overload -*/ -void QOpenGLTexture::setCompressedData(int mipLevel, int dataSize, void *data, - const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setCompressedData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options); -} - -/*! - \obsolete - \overload -*/ -void QOpenGLTexture::setCompressedData(int dataSize, void *data, - const QOpenGLPixelTransferOptions * const options) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->textureId); - d->setCompressedData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options); -} -#endif - -/*! - Returns \c true if your OpenGL implementation and version supports the texture - feature \a feature. -*/ -bool QOpenGLTexture::hasFeature(Feature feature) -{ - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (!ctx) { - qWarning("QOpenGLTexture::hasFeature() requires a valid current context"); - return false; - } - - QSurfaceFormat f = ctx->format(); - - bool supported = false; - -#if !defined(QT_OPENGL_ES_2) - if (!ctx->isOpenGLES()) { - switch (feature) { - case ImmutableMultisampleStorage: - supported = f.version() >= qMakePair(4, 3) - || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage_multisample")); - break; - - case TextureBuffer: - supported = f.version() >= qMakePair(3, 0) - || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_buffer_object")); - break; - - case StencilTexturing: - supported = f.version() >= qMakePair(4, 3) - || ctx->hasExtension(QByteArrayLiteral("GL_ARB_stencil_texturing")); - break; - - case ImmutableStorage: - supported = f.version() >= qMakePair(4, 2) - || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage")) - || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage")); - break; - - case TextureCubeMapArrays: - supported = f.version() >= qMakePair(4, 0) - || ctx->hasExtension(QByteArrayLiteral("ARB_texture_cube_map_array")); - break; - - case Swizzle: - supported = f.version() >= qMakePair(3, 3) - || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_swizzle")); - break; - - case TextureMultisample: - supported = f.version() >= qMakePair(3, 2) - || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_multisample")); - break; - - case TextureArrays: - supported = f.version() >= qMakePair(3, 0) - || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_array")); - break; - - case TextureRectangle: - supported = f.version() >= qMakePair(2, 1) - || ctx->hasExtension(QByteArrayLiteral("ARB_texture_rectangle")); - break; - - case Texture3D: - supported = f.version() >= qMakePair(1, 3); - break; - - case AnisotropicFiltering: - supported = ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic")); - break; - - case NPOTTextures: - case NPOTTextureRepeat: - supported = ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two")); - break; - - case Texture1D: - supported = f.version() >= qMakePair(1, 1); - break; - - case TextureComparisonOperators: - // GL 1.4 and GL_ARB_shadow alone support only LEQUAL and GEQUAL; - // since we're talking about history anyhow avoid to be extra pedantic - // in the feature set, and simply claim supported if we have the full set of operators - // (which has been added into 1.5 / GL_EXT_shadow_funcs). - supported = f.version() >= qMakePair(1, 5) - || (ctx->hasExtension(QByteArrayLiteral("GL_ARB_shadow")) - && ctx->hasExtension(QByteArrayLiteral("GL_EXT_shadow_funcs"))); - break; - - case TextureMipMapLevel: - supported = f.version() >= qMakePair(1, 2); - break; - - case MaxFeatureFlag: - break; - } - } - - if (ctx->isOpenGLES()) -#endif - { - const char *renderer = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_RENDERER)); - switch (feature) { - case ImmutableStorage: - supported = (f.version() >= qMakePair(3, 0) || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage"))) - && !(renderer && strstr(renderer, "Mali")); // do not use on Mali: QTBUG-45106 - break; - - case ImmutableMultisampleStorage: - supported = f.version() >= qMakePair(3, 1); - break; - - case TextureRectangle: - break; - - case TextureArrays: - supported = f.version() >= qMakePair(3, 0); - break; - - case Texture3D: - supported = f.version() >= qMakePair(3, 0) - || ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_3D")); - break; - - case TextureMultisample: - supported = f.version() >= qMakePair(3, 1); - break; - - case TextureBuffer: - break; - - case TextureCubeMapArrays: - break; - - case Swizzle: - supported = f.version() >= qMakePair(3, 0); - break; - - case StencilTexturing: - break; - - case AnisotropicFiltering: - supported = ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic")); - break; - - case NPOTTextures: - case NPOTTextureRepeat: - supported = f.version() >= qMakePair(3,0) - || ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_npot")) - || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two")); - break; - - case Texture1D: - break; - - case TextureComparisonOperators: - supported = f.version() >= qMakePair(3, 0) - || ctx->hasExtension(QByteArrayLiteral("GL_EXT_shadow_samplers")); - break; - - case TextureMipMapLevel: - supported = f.version() >= qMakePair(3, 0); - break; - - case MaxFeatureFlag: - break; - } - } - - return supported; -} - -/*! - Sets the base mipmap level used for all texture lookups with this texture to \a baseLevel. - - \note This function has no effect on Qt built for OpenGL ES 2. - \sa mipBaseLevel(), setMipMaxLevel(), setMipLevelRange() -*/ -void QOpenGLTexture::setMipBaseLevel(int baseLevel) -{ - Q_D(QOpenGLTexture); - d->create(); - if (!d->features.testFlag(TextureMipMapLevel)) { - qWarning("QOpenGLTexture::setMipBaseLevel: requires OpenGL >= 1.2 or OpenGL ES >= 3.0"); - return; - } - Q_ASSERT(d->textureId); - Q_ASSERT(d->texFuncs); - Q_ASSERT(baseLevel <= d->maxLevel); - d->baseLevel = baseLevel; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BASE_LEVEL, baseLevel); -} - -/*! - Returns the mipmap base level used for all texture lookups with this texture. - The default is 0. - - \sa setMipBaseLevel(), mipMaxLevel(), mipLevelRange() -*/ -int QOpenGLTexture::mipBaseLevel() const -{ - Q_D(const QOpenGLTexture); - return d->baseLevel; -} - -/*! - Sets the maximum mipmap level used for all texture lookups with this texture to \a maxLevel. - - \note This function has no effect on Qt built for OpenGL ES 2. - \sa mipMaxLevel(), setMipBaseLevel(), setMipLevelRange() -*/ -void QOpenGLTexture::setMipMaxLevel(int maxLevel) -{ - Q_D(QOpenGLTexture); - d->create(); - if (!d->features.testFlag(TextureMipMapLevel)) { - qWarning("QOpenGLTexture::setMipMaxLevel: requires OpenGL >= 1.2 or OpenGL ES >= 3.0"); - return; - } - Q_ASSERT(d->textureId); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->baseLevel <= maxLevel); - d->maxLevel = maxLevel; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LEVEL, maxLevel); -} - -/*! - Returns the mipmap maximum level used for all texture lookups with this texture. - - \sa setMipMaxLevel(), mipBaseLevel(), mipLevelRange() -*/ -int QOpenGLTexture::mipMaxLevel() const -{ - Q_D(const QOpenGLTexture); - return d->maxLevel; -} - -/*! - Sets the range of mipmap levels that can be used for texture lookups with this texture - to range from \a baseLevel to \a maxLevel. - - \note This function has no effect on Qt built for OpenGL ES 2. - \sa setMipBaseLevel(), setMipMaxLevel(), mipLevelRange() -*/ -void QOpenGLTexture::setMipLevelRange(int baseLevel, int maxLevel) -{ - Q_D(QOpenGLTexture); - d->create(); - if (!d->features.testFlag(TextureMipMapLevel)) { - qWarning("QOpenGLTexture::setMipLevelRange: requires OpenGL >= 1.2 or OpenGL ES >= 3.0"); - return; - } - Q_ASSERT(d->textureId); - Q_ASSERT(d->texFuncs); - Q_ASSERT(baseLevel <= maxLevel); - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BASE_LEVEL, baseLevel); - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LEVEL, maxLevel); -} - -/*! - Returns the range of mipmap levels that can be used for texture lookups with this texture. - - \sa mipBaseLevel(), mipMaxLevel() -*/ -QPair<int, int> QOpenGLTexture::mipLevelRange() const -{ - Q_D(const QOpenGLTexture); - return qMakePair(d->baseLevel, d->maxLevel); -} - -/*! - If \a enabled is \c true, enables automatic mipmap generation for this texture object - to occur whenever the level 0 mipmap data is set via setData(). - - The automatic mipmap generation is enabled by default. - - \note Mipmap generation is not supported for compressed textures with OpenGL ES 2.0. - - \sa isAutoMipMapGenerationEnabled(), generateMipMaps() -*/ -void QOpenGLTexture::setAutoMipMapGenerationEnabled(bool enabled) -{ - Q_D(QOpenGLTexture); - d->autoGenerateMipMaps = enabled; -} - -/*! - Returns whether auto mipmap generation is enabled for this texture object. - - \sa setAutoMipMapGenerationEnabled(), generateMipMaps() -*/ -bool QOpenGLTexture::isAutoMipMapGenerationEnabled() const -{ - Q_D(const QOpenGLTexture); - return d->autoGenerateMipMaps; -} - -/*! - Generates mipmaps for this texture object from mipmap level 0. If you are - using a texture target and filtering option that requires mipmaps and you - have disabled automatic mipmap generation then you need to call this function - or the overload to create the mipmap chain. - - \note Mipmap generation is not supported for compressed textures with OpenGL ES. - - \sa setAutoMipMapGenerationEnabled(), setMipLevels(), mipLevels() -*/ -void QOpenGLTexture::generateMipMaps() -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - if (isCompressedFormat(d->format)) { - if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) - if (ctx->isOpenGLES()) - return; - } - d->texFuncs->glGenerateTextureMipmap(d->textureId, d->target, d->bindingTarget); -} - -/*! - Generates mipmaps for this texture object from mipmap level \a baseLevel. If you are - using a texture target and filtering option that requires mipmaps and you - have disabled automatic mipmap generation then you need to call this function - or the overload to create the mipmap chain. - - The generation of mipmaps to above \a baseLevel is achieved by setting the mipmap - base level to \a baseLevel and then generating the mipmap chain. If \a resetBaseLevel - is \c true, then the baseLevel of the texture will be reset to its previous value. - - \sa setAutoMipMapGenerationEnabled(), setMipLevels(), mipLevels() -*/ -void QOpenGLTexture::generateMipMaps(int baseLevel, bool resetBaseLevel) -{ - Q_D(QOpenGLTexture); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - if (isCompressedFormat(d->format)) { - if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) - if (ctx->isOpenGLES()) - return; - } - int oldBaseLevel; - if (resetBaseLevel) - oldBaseLevel = mipBaseLevel(); - setMipBaseLevel(baseLevel); - d->texFuncs->glGenerateTextureMipmap(d->textureId, d->target, d->bindingTarget); - if (resetBaseLevel) - setMipBaseLevel(oldBaseLevel); -} - -/*! - GLSL shaders are able to reorder the components of the vec4 returned by texture - functions. It is also desirable to be able to control this reordering from CPU - side code. This is made possible by swizzle masks since OpenGL 3.3. - - Each component of the texture can be mapped to one of the SwizzleValue options. - - This function maps \a component to the output \a value. - - \note This function has no effect on Mac and Qt built for OpenGL ES 2. - \sa swizzleMask() -*/ -void QOpenGLTexture::setSwizzleMask(SwizzleComponent component, SwizzleValue value) -{ -#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - if (!d->features.testFlag(Swizzle)) { - qWarning("QOpenGLTexture::setSwizzleMask() requires OpenGL >= 3.3"); - return; - } - d->swizzleMask[component - SwizzleRed] = value; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, component, value); - return; - } -#else - Q_UNUSED(component); - Q_UNUSED(value); -#endif - qWarning("QOpenGLTexture: Texture swizzling is not supported"); -} - -/*! - Parameters \a {r}, \a {g}, \a {b}, and \a {a} are values used for setting - the colors red, green, blue, and the alpha value. - \overload -*/ -void QOpenGLTexture::setSwizzleMask(SwizzleValue r, SwizzleValue g, - SwizzleValue b, SwizzleValue a) -{ -#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - if (!d->features.testFlag(Swizzle)) { - qWarning("QOpenGLTexture::setSwizzleMask() requires OpenGL >= 3.3"); - return; - } - GLint swizzleMask[] = {GLint(r), GLint(g), GLint(b), GLint(a)}; - d->swizzleMask[0] = r; - d->swizzleMask[1] = g; - d->swizzleMask[2] = b; - d->swizzleMask[3] = a; - d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - return; - } -#else - Q_UNUSED(r); - Q_UNUSED(g); - Q_UNUSED(b); - Q_UNUSED(a); -#endif - qWarning("QOpenGLTexture: Texture swizzling is not supported"); -} - -/*! - Returns the swizzle mask for texture \a component. -*/ -QOpenGLTexture::SwizzleValue QOpenGLTexture::swizzleMask(SwizzleComponent component) const -{ - Q_D(const QOpenGLTexture); - return d->swizzleMask[component - SwizzleRed]; -} - -/*! - \enum QOpenGLTexture::DepthStencilMode - \since 5.4 - This enum specifies which component of a depth/stencil texture is - accessed when the texture is sampled. - - \value DepthMode Equivalent to GL_DEPTH_COMPONENT. - \value StencilMode Equivalent to GL_STENCIL_INDEX. -*/ - -/*! - If using a texture that has a combined depth/stencil format this function sets - which component of the texture is accessed to \a mode. - - When the parameter is set to DepthMode, then accessing it from the - shader will access the depth component as a single float, as normal. But when - the parameter is set to StencilMode, the shader will access the stencil component. - - \note This function has no effect on Mac and Qt built for OpenGL ES 2. - \since 5.4 - \sa depthStencilMode() -*/ -void QOpenGLTexture::setDepthStencilMode(QOpenGLTexture::DepthStencilMode mode) -{ -#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - if (!d->features.testFlag(StencilTexturing)) { - qWarning("QOpenGLTexture::setDepthStencilMode() requires OpenGL >= 4.3 or GL_ARB_stencil_texturing"); - return; - } - d->depthStencilMode = mode; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_DEPTH_STENCIL_TEXTURE_MODE, mode); - return; - } -#else - Q_UNUSED(mode); -#endif - qWarning("QOpenGLTexture: DepthStencil Mode is not supported"); -} - -/*! - Returns the depth stencil mode for textures using a combined depth/stencil format. - - \since 5.4 - \sa setDepthStencilMode() -*/ -QOpenGLTexture::DepthStencilMode QOpenGLTexture::depthStencilMode() const -{ - Q_D(const QOpenGLTexture); - return d->depthStencilMode; -} - -/*! - \enum QOpenGLTexture::ComparisonFunction - \since 5.5 - This enum specifies which comparison operator is used when texture comparison - is enabled on this texture. - - \value CompareLessEqual Equivalent to GL_LEQUAL. - \value CompareGreaterEqual Equivalent to GL_GEQUAL. - \value CompareLess Equivalent to GL_LESS. - \value CompareGreater Equivalent to GL_GREATER. - \value CompareEqual Equivalent to GL_EQUAL. - \value CommpareNotEqual Equivalent to GL_NOTEQUAL. - \value CompareAlways Equivalent to GL_ALWAYS. - \value CompareNever Equivalent to GL_NEVER. - -*/ - -/*! - \since 5.5 - - Sets the texture comparison function on this texture to \a function. The texture - comparison function is used by shadow samplers when sampling a depth texture. - - \sa comparisonFunction() -*/ -void QOpenGLTexture::setComparisonFunction(QOpenGLTexture::ComparisonFunction function) -{ - Q_D(QOpenGLTexture); - d->create(); - if (!d->features.testFlag(TextureComparisonOperators)) { - qWarning("QOpenGLTexture::setComparisonFunction: requires OpenGL >= 1.5 or OpenGL ES >= 3.0"); - return; - } - d->comparisonFunction = function; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_COMPARE_FUNC, function); -} - -/*! - \since 5.5 - - Returns the texture comparison operator set on this texture. By default, a - texture has a CompareLessEqual comparison function. - - \sa setComparisonFunction() -*/ -QOpenGLTexture::ComparisonFunction QOpenGLTexture::comparisonFunction() const -{ - Q_D(const QOpenGLTexture); - return d->comparisonFunction; -} - -/*! - \enum QOpenGLTexture::ComparisonMode - \since 5.5 - This enum specifies which comparison mode is used when sampling this texture. - - \value CompareRefToTexture Equivalent to GL_COMPARE_REF_TO_TEXTURE. - \value CompareNone Equivalent to GL_NONE. -*/ - -/*! - \since 5.5 - - Sets the texture comparison mode on this texture to \a mode. The texture - comparison mode is used by shadow samplers when sampling a depth texture. - - \sa comparisonMode() -*/ -void QOpenGLTexture::setComparisonMode(QOpenGLTexture::ComparisonMode mode) -{ - Q_D(QOpenGLTexture); - d->create(); - if (!d->features.testFlag(TextureComparisonOperators)) { - qWarning("QOpenGLTexture::setComparisonMode: requires OpenGL >= 1.5 or OpenGL ES >= 3.0"); - return; - } - d->comparisonMode = mode; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_COMPARE_MODE, mode); -} - -/*! - \since 5.5 - - Returns the texture comparison mode set on this texture. By default, a - texture has a CompareNone comparison mode (i.e. comparisons are disabled). - - \sa setComparisonMode() -*/ -QOpenGLTexture::ComparisonMode QOpenGLTexture::comparisonMode() const -{ - Q_D(const QOpenGLTexture); - return d->comparisonMode; -} - -/*! - Sets the filter used for minification to \a filter. - - \sa minificationFilter(), setMagnificationFilter(), setMinMagFilters() -*/ -void QOpenGLTexture::setMinificationFilter(QOpenGLTexture::Filter filter) -{ - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - d->minFilter = filter; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_FILTER, filter); -} - -/*! - Returns the minification filter. - - \sa setMinificationFilter() -*/ -QOpenGLTexture::Filter QOpenGLTexture::minificationFilter() const -{ - Q_D(const QOpenGLTexture); - return d->minFilter; -} - -/*! - Sets the magnification filter to \a filter. - - \sa magnificationFilter(), setMinificationFilter(), setMinMagFilters() -*/ -void QOpenGLTexture::setMagnificationFilter(QOpenGLTexture::Filter filter) -{ - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - d->magFilter = filter; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAG_FILTER, filter); -} - -/*! - Returns the magnification filter. - - \sa setMagnificationFilter() -*/ -QOpenGLTexture::Filter QOpenGLTexture::magnificationFilter() const -{ - Q_D(const QOpenGLTexture); - return d->magFilter; -} - -/*! - Sets the minification filter to \a minificationFilter and the magnification filter - to \a magnificationFilter. - - \sa minMagFilters(), setMinificationFilter(), setMagnificationFilter() -*/ -void QOpenGLTexture::setMinMagFilters(QOpenGLTexture::Filter minificationFilter, - QOpenGLTexture::Filter magnificationFilter) -{ - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - d->minFilter = minificationFilter; - d->magFilter = magnificationFilter; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_FILTER, minificationFilter); - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAG_FILTER, magnificationFilter); -} - -/*! - Returns the current minification and magnification filters. - - \sa setMinMagFilters() -*/ -QPair<QOpenGLTexture::Filter, QOpenGLTexture::Filter> QOpenGLTexture::minMagFilters() const -{ - Q_D(const QOpenGLTexture); - return QPair<QOpenGLTexture::Filter, QOpenGLTexture::Filter>(d->minFilter, d->magFilter); -} - -/*! - If your OpenGL implementation supports the GL_EXT_texture_filter_anisotropic extension - this function sets the maximum anisotropy level to \a anisotropy. - - \sa maximumAnisotropy() -*/ -void QOpenGLTexture::setMaximumAnisotropy(float anisotropy) -{ - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - if (!d->features.testFlag(AnisotropicFiltering)) { - qWarning("QOpenGLTexture::setMaximumAnisotropy() requires GL_EXT_texture_filter_anisotropic"); - return; - } - d->maxAnisotropy = anisotropy; - d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy); -} - -/*! - Returns the maximum level of anisotropy to be accounted for when performing texture lookups. - This requires the GL_EXT_texture_filter_anisotropic extension. - - \sa setMaximumAnisotropy() -*/ -float QOpenGLTexture::maximumAnisotropy() const -{ - Q_D(const QOpenGLTexture); - return d->maxAnisotropy; -} - -/*! - Sets the wrap (or repeat mode) for all texture dimentions to \a mode. - - \sa wrapMode() -*/ -void QOpenGLTexture::setWrapMode(QOpenGLTexture::WrapMode mode) -{ - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - d->setWrapMode(mode); -} - -/*! - Holds the texture dimension \a direction. - \overload -*/ -void QOpenGLTexture::setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode) -{ - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - d->setWrapMode(direction, mode); -} - -/*! - Returns the wrap mode for the texture dimension \a direction. - - \sa setWrapMode() -*/ -QOpenGLTexture::WrapMode QOpenGLTexture::wrapMode(QOpenGLTexture::CoordinateDirection direction) const -{ - Q_D(const QOpenGLTexture); - return d->wrapMode(direction); -} - -/*! - Sets the border color of the texture to \a color. - - \note This function has no effect on Mac and Qt built for OpenGL ES 2. - \sa borderColor() -*/ -void QOpenGLTexture::setBorderColor(QColor color) -{ - setBorderColor(static_cast<float>(color.redF()), static_cast<float>(color.greenF()), - static_cast<float>(color.blueF()), static_cast<float>(color.alphaF())); -} - -/*! - Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and \a {a} to the - alpha value. - \overload -*/ -void QOpenGLTexture::setBorderColor(float r, float g, float b, float a) -{ -#if !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - float values[4]; - values[0] = r; - values[1] = g; - values[2] = b; - values[3] = a; - d->borderColor.clear(); - for (int i = 0; i < 4; ++i) - d->borderColor.append(QVariant(values[i])); - d->texFuncs->glTextureParameterfv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values); - return; - } -#else - Q_UNUSED(r); - Q_UNUSED(g); - Q_UNUSED(b); - Q_UNUSED(a); -#endif - qWarning("QOpenGLTexture: Border color is not supported"); -} - -/*! - Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and the alpha - value to \a {a}. - \overload -*/ -void QOpenGLTexture::setBorderColor(int r, int g, int b, int a) -{ -#if !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - int values[4]; - values[0] = r; - values[1] = g; - values[2] = b; - values[3] = a; - d->borderColor.clear(); - for (int i = 0; i < 4; ++i) - d->borderColor.append(QVariant(values[i])); - d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values); - return; - } -#else - Q_UNUSED(r); - Q_UNUSED(g); - Q_UNUSED(b); - Q_UNUSED(a); -#endif - qWarning("QOpenGLTexture: Border color is not supported"); - - // TODO Handle case of using glTextureParameterIiv() based on format -} - -/*! - Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and the alpha - value to \a {a}. - \overload -*/ -void QOpenGLTexture::setBorderColor(uint r, uint g, uint b, uint a) -{ -#if !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - int values[4]; - values[0] = int(r); - values[1] = int(g); - values[2] = int(b); - values[3] = int(a); - d->borderColor.clear(); - for (int i = 0; i < 4; ++i) - d->borderColor.append(QVariant(values[i])); - d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values); - return; - } -#else - Q_UNUSED(r); - Q_UNUSED(g); - Q_UNUSED(b); - Q_UNUSED(a); -#endif - qWarning("QOpenGLTexture: Border color is not supported"); - - // TODO Handle case of using glTextureParameterIuiv() based on format -} - -/*! - Returns the borderColor of this texture. - - \sa setBorderColor() -*/ -QColor QOpenGLTexture::borderColor() const -{ - Q_D(const QOpenGLTexture); - QColor c(0.0f, 0.0f, 0.0f, 0.0f); - if (!d->borderColor.isEmpty()) { - c.setRedF(d->borderColor.at(0).toFloat()); - c.setGreenF(d->borderColor.at(1).toFloat()); - c.setBlueF(d->borderColor.at(2).toFloat()); - c.setAlphaF(d->borderColor.at(3).toFloat()); - } - return c; -} - -/*! - Writes the texture border color into the first four elements - of the array pointed to by \a border. - - \sa setBorderColor() -*/ -void QOpenGLTexture::borderColor(float *border) const -{ - Q_D(const QOpenGLTexture); - Q_ASSERT(border); - if (d->borderColor.isEmpty()) { - for (int i = 0; i < 4; ++i) - border[i] = 0.0f; - } else { - for (int i = 0; i < 4; ++i) - border[i] = d->borderColor.at(i).toFloat(); - } -} - -/*! - Writes the texture border color into the first four elements - of the array pointed to by \a border. - - \overload -*/ -void QOpenGLTexture::borderColor(int *border) const -{ - Q_D(const QOpenGLTexture); - Q_ASSERT(border); - if (d->borderColor.isEmpty()) { - for (int i = 0; i < 4; ++i) - border[i] = 0; - } else { - for (int i = 0; i < 4; ++i) - border[i] = d->borderColor.at(i).toInt(); - } -} - -/*! - Writes the texture border color into the first four elements - of the array pointed to by \a border. - - \overload -*/ -void QOpenGLTexture::borderColor(unsigned int *border) const -{ - Q_D(const QOpenGLTexture); - Q_ASSERT(border); - if (d->borderColor.isEmpty()) { - for (int i = 0; i < 4; ++i) - border[i] = 0; - } else { - for (int i = 0; i < 4; ++i) - border[i] = d->borderColor.at(i).toUInt(); - } -} - -/*! - Sets the minimum level of detail to \a value. This limits the selection of highest - resolution mipmap (lowest mipmap level). The default value is -1000. - - \note This function has no effect on Qt built for OpenGL ES 2. - \sa minimumLevelOfDetail(), setMaximumLevelOfDetail(), setLevelOfDetailRange() -*/ -void QOpenGLTexture::setMinimumLevelOfDetail(float value) -{ -#if !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - Q_ASSERT(value < d->maxLevelOfDetail); - d->minLevelOfDetail = value; - d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_LOD, value); - return; - } -#else - Q_UNUSED(value); -#endif - qWarning("QOpenGLTexture: Detail level is not supported"); -} - -/*! - Returns the minimum level of detail parameter. - - \sa setMinimumLevelOfDetail(), maximumLevelOfDetail(), levelOfDetailRange() -*/ -float QOpenGLTexture::minimumLevelOfDetail() const -{ - Q_D(const QOpenGLTexture); - return d->minLevelOfDetail; -} - -/*! - Sets the maximum level of detail to \a value. This limits the selection of lowest - resolution mipmap (highest mipmap level). The default value is 1000. - - \note This function has no effect on Qt built for OpenGL ES 2. - \sa maximumLevelOfDetail(), setMinimumLevelOfDetail(), setLevelOfDetailRange() -*/ -void QOpenGLTexture::setMaximumLevelOfDetail(float value) -{ -#if !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - Q_ASSERT(value > d->minLevelOfDetail); - d->maxLevelOfDetail = value; - d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LOD, value); - return; - } -#else - Q_UNUSED(value); -#endif - qWarning("QOpenGLTexture: Detail level is not supported"); -} - -/*! - Returns the maximum level of detail parameter. - - \sa setMaximumLevelOfDetail(), minimumLevelOfDetail(), levelOfDetailRange() -*/ -float QOpenGLTexture::maximumLevelOfDetail() const -{ - Q_D(const QOpenGLTexture); - return d->maxLevelOfDetail; -} - -/*! - Sets the minimum level of detail parameters to \a min and the maximum level - to \a max. - \note This function has no effect on Qt built for OpenGL ES 2. - \sa levelOfDetailRange(), setMinimumLevelOfDetail(), setMaximumLevelOfDetail() -*/ -void QOpenGLTexture::setLevelOfDetailRange(float min, float max) -{ -#if !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - Q_ASSERT(min < max); - d->minLevelOfDetail = min; - d->maxLevelOfDetail = max; - d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_LOD, min); - d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LOD, max); - return; - } -#else - Q_UNUSED(min); - Q_UNUSED(max); -#endif - qWarning("QOpenGLTexture: Detail level is not supported"); -} - -/*! - Returns the minimum and maximum level of detail parameters. - - \sa setLevelOfDetailRange(), minimumLevelOfDetail(), maximumLevelOfDetail() -*/ -QPair<float, float> QOpenGLTexture::levelOfDetailRange() const -{ - Q_D(const QOpenGLTexture); - return qMakePair(d->minLevelOfDetail, d->maxLevelOfDetail); -} - -/*! - Sets the level of detail bias to \a bias. - Level of detail bias affects the point at which mipmapping levels change. - Increasing values for level of detail bias makes the overall images blurrier - or smoother. Decreasing values make the overall images sharper. - - \note This function has no effect on Qt built for OpenGL ES 2. - \sa levelofDetailBias() -*/ -void QOpenGLTexture::setLevelofDetailBias(float bias) -{ -#if !defined(QT_OPENGL_ES_2) - if (!QOpenGLContext::currentContext()->isOpenGLES()) { - Q_D(QOpenGLTexture); - d->create(); - Q_ASSERT(d->texFuncs); - Q_ASSERT(d->textureId); - d->levelOfDetailBias = bias; - d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_LOD_BIAS, bias); - return; - } -#else - Q_UNUSED(bias); -#endif - qWarning("QOpenGLTexture: Detail level is not supported"); -} - -/*! - Returns the level of detail bias parameter. - - \sa setLevelofDetailBias() -*/ -float QOpenGLTexture::levelofDetailBias() const -{ - Q_D(const QOpenGLTexture); - return d->levelOfDetailBias; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug debug, const QOpenGLTexture *t) -{ - QDebugStateSaver saver(debug); - debug.nospace(); - debug << "QOpenGLTexture("; - if (t) { - const QOpenGLTexturePrivate *d = t->d_ptr.data(); - debug << d->target << ", bindingTarget=" << d->bindingTarget - << ", size=[" << d->dimensions[0] - << ", " << d->dimensions[1]; - if (d->target == QOpenGLTexture::Target3D) - debug << ", " << d->dimensions[2]; - debug << "], format=" << d->format << ", formatClass=" << d->formatClass; - if (t->isCreated()) - debug << ", textureId=" << d->textureId; - if (t->isBound()) - debug << ", [bound]"; - if (t->isTextureView()) - debug << ", [view]"; - if (d->fixedSamplePositions) - debug << ", [fixedSamplePositions]"; - debug << ", mipLevels=" << d->requestedMipLevels << ", layers=" << d->layers - << ", faces=" << d->faces << ", samples=" << d->samples - << ", depthStencilMode=" << d->depthStencilMode << ", comparisonFunction=" - << d->comparisonFunction << ", comparisonMode=" << d->comparisonMode - << ", features=" << d->features << ", minificationFilter=" << d->minFilter - << ", magnificationFilter=" << d->magFilter << ", wrapMode=" << d->wrapModes[0]; - } else { - debug << '0'; - } - debug << ')'; - return debug; -} -#endif // QT_NO_DEBUG_STREAM - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h deleted file mode 100644 index 7d984babc8..0000000000 --- a/src/gui/opengl/qopengltexture.h +++ /dev/null @@ -1,663 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLABSTRACTTEXTURE_H -#define QOPENGLABSTRACTTEXTURE_H - -#include <QtGui/qtguiglobal.h> - -#ifndef QT_NO_OPENGL - -#include <QtGui/qopengl.h> -#include <QtGui/qimage.h> -#include <QtCore/QScopedPointer> - -QT_BEGIN_NAMESPACE - -class QDebug; -class QOpenGLTexturePrivate; -class QOpenGLPixelTransferOptions; - -class Q_GUI_EXPORT QOpenGLTexture -{ - Q_GADGET -public: - enum Target { - Target1D = 0x0DE0, // GL_TEXTURE_1D - Target1DArray = 0x8C18, // GL_TEXTURE_1D_ARRAY - Target2D = 0x0DE1, // GL_TEXTURE_2D - Target2DArray = 0x8C1A, // GL_TEXTURE_2D_ARRAY - Target3D = 0x806F, // GL_TEXTURE_3D - TargetCubeMap = 0x8513, // GL_TEXTURE_CUBE_MAP - TargetCubeMapArray = 0x9009, // GL_TEXTURE_CUBE_MAP_ARRAY - Target2DMultisample = 0x9100, // GL_TEXTURE_2D_MULTISAMPLE - Target2DMultisampleArray = 0x9102, // GL_TEXTURE_2D_MULTISAMPLE_ARRAY - TargetRectangle = 0x84F5, // GL_TEXTURE_RECTANGLE - TargetBuffer = 0x8C2A // GL_TEXTURE_BUFFER - }; - Q_ENUM(Target) - - enum BindingTarget { - BindingTarget1D = 0x8068, // GL_TEXTURE_BINDING_1D - BindingTarget1DArray = 0x8C1C, // GL_TEXTURE_BINDING_1D_ARRAY - BindingTarget2D = 0x8069, // GL_TEXTURE_BINDING_2D - BindingTarget2DArray = 0x8C1D, // GL_TEXTURE_BINDING_2D_ARRAY - BindingTarget3D = 0x806A, // GL_TEXTURE_BINDING_3D - BindingTargetCubeMap = 0x8514, // GL_TEXTURE_BINDING_CUBE_MAP - BindingTargetCubeMapArray = 0x900A, // GL_TEXTURE_BINDING_CUBE_MAP_ARRAY - BindingTarget2DMultisample = 0x9104, // GL_TEXTURE_BINDING_2D_MULTISAMPLE - BindingTarget2DMultisampleArray = 0x9105, // GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY - BindingTargetRectangle = 0x84F6, // GL_TEXTURE_BINDING_RECTANGLE - BindingTargetBuffer = 0x8C2C // GL_TEXTURE_BINDING_BUFFER - }; - Q_ENUM(BindingTarget) - - enum MipMapGeneration { - GenerateMipMaps, - DontGenerateMipMaps - }; - Q_ENUM(MipMapGeneration) - - enum TextureUnitReset { - ResetTextureUnit, - DontResetTextureUnit - }; - Q_ENUM(TextureUnitReset) - - enum TextureFormat { - NoFormat = 0, // GL_NONE - - // Unsigned normalized formats - R8_UNorm = 0x8229, // GL_R8 - RG8_UNorm = 0x822B, // GL_RG8 - RGB8_UNorm = 0x8051, // GL_RGB8 - RGBA8_UNorm = 0x8058, // GL_RGBA8 - - R16_UNorm = 0x822A, // GL_R16 - RG16_UNorm = 0x822C, // GL_RG16 - RGB16_UNorm = 0x8054, // GL_RGB16 - RGBA16_UNorm = 0x805B, // GL_RGBA16 - - // Signed normalized formats - R8_SNorm = 0x8F94, // GL_R8_SNORM - RG8_SNorm = 0x8F95, // GL_RG8_SNORM - RGB8_SNorm = 0x8F96, // GL_RGB8_SNORM - RGBA8_SNorm = 0x8F97, // GL_RGBA8_SNORM - - R16_SNorm = 0x8F98, // GL_R16_SNORM - RG16_SNorm = 0x8F99, // GL_RG16_SNORM - RGB16_SNorm = 0x8F9A, // GL_RGB16_SNORM - RGBA16_SNorm = 0x8F9B, // GL_RGBA16_SNORM - - // Unsigned integer formats - R8U = 0x8232, // GL_R8UI - RG8U = 0x8238, // GL_RG8UI - RGB8U = 0x8D7D, // GL_RGB8UI - RGBA8U = 0x8D7C, // GL_RGBA8UI - - R16U = 0x8234, // GL_R16UI - RG16U = 0x823A, // GL_RG16UI - RGB16U = 0x8D77, // GL_RGB16UI - RGBA16U = 0x8D76, // GL_RGBA16UI - - R32U = 0x8236, // GL_R32UI - RG32U = 0x823C, // GL_RG32UI - RGB32U = 0x8D71, // GL_RGB32UI - RGBA32U = 0x8D70, // GL_RGBA32UI - - // Signed integer formats - R8I = 0x8231, // GL_R8I - RG8I = 0x8237, // GL_RG8I - RGB8I = 0x8D8F, // GL_RGB8I - RGBA8I = 0x8D8E, // GL_RGBA8I - - R16I = 0x8233, // GL_R16I - RG16I = 0x8239, // GL_RG16I - RGB16I = 0x8D89, // GL_RGB16I - RGBA16I = 0x8D88, // GL_RGBA16I - - R32I = 0x8235, // GL_R32I - RG32I = 0x823B, // GL_RG32I - RGB32I = 0x8D83, // GL_RGB32I - RGBA32I = 0x8D82, // GL_RGBA32I - - // Floating point formats - R16F = 0x822D, // GL_R16F - RG16F = 0x822F, // GL_RG16F - RGB16F = 0x881B, // GL_RGB16F - RGBA16F = 0x881A, // GL_RGBA16F - - R32F = 0x822E, // GL_R32F - RG32F = 0x8230, // GL_RG32F - RGB32F = 0x8815, // GL_RGB32F - RGBA32F = 0x8814, // GL_RGBA32F - - // Packed formats - RGB9E5 = 0x8C3D, // GL_RGB9_E5 - RG11B10F = 0x8C3A, // GL_R11F_G11F_B10F - RG3B2 = 0x2A10, // GL_R3_G3_B2 - R5G6B5 = 0x8D62, // GL_RGB565 - RGB5A1 = 0x8057, // GL_RGB5_A1 - RGBA4 = 0x8056, // GL_RGBA4 - RGB10A2 = 0x906F, // GL_RGB10_A2UI - - // Depth formats - D16 = 0x81A5, // GL_DEPTH_COMPONENT16 - D24 = 0x81A6, // GL_DEPTH_COMPONENT24 - D24S8 = 0x88F0, // GL_DEPTH24_STENCIL8 - D32 = 0x81A7, // GL_DEPTH_COMPONENT32 - D32F = 0x8CAC, // GL_DEPTH_COMPONENT32F - D32FS8X24 = 0x8CAD, // GL_DEPTH32F_STENCIL8 - S8 = 0x8D48, // GL_STENCIL_INDEX8 - - // Compressed formats - RGB_DXT1 = 0x83F0, // GL_COMPRESSED_RGB_S3TC_DXT1_EXT - RGBA_DXT1 = 0x83F1, // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT - RGBA_DXT3 = 0x83F2, // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT - RGBA_DXT5 = 0x83F3, // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT - R_ATI1N_UNorm = 0x8DBB, // GL_COMPRESSED_RED_RGTC1 - R_ATI1N_SNorm = 0x8DBC, // GL_COMPRESSED_SIGNED_RED_RGTC1 - RG_ATI2N_UNorm = 0x8DBD, // GL_COMPRESSED_RG_RGTC2 - RG_ATI2N_SNorm = 0x8DBE, // GL_COMPRESSED_SIGNED_RG_RGTC2 - RGB_BP_UNSIGNED_FLOAT = 0x8E8F, // GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB - RGB_BP_SIGNED_FLOAT = 0x8E8E, // GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB - RGB_BP_UNorm = 0x8E8C, // GL_COMPRESSED_RGBA_BPTC_UNORM_ARB - R11_EAC_UNorm = 0x9270, // GL_COMPRESSED_R11_EAC - R11_EAC_SNorm = 0x9271, // GL_COMPRESSED_SIGNED_R11_EAC - RG11_EAC_UNorm = 0x9272, // GL_COMPRESSED_RG11_EAC - RG11_EAC_SNorm = 0x9273, // GL_COMPRESSED_SIGNED_RG11_EAC - RGB8_ETC2 = 0x9274, // GL_COMPRESSED_RGB8_ETC2 - SRGB8_ETC2 = 0x9275, // GL_COMPRESSED_SRGB8_ETC2 - RGB8_PunchThrough_Alpha1_ETC2 = 0x9276, // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 - SRGB8_PunchThrough_Alpha1_ETC2 = 0x9277, // GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 - RGBA8_ETC2_EAC = 0x9278, // GL_COMPRESSED_RGBA8_ETC2_EAC - SRGB8_Alpha8_ETC2_EAC = 0x9279, // GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC - RGB8_ETC1 = 0x8D64, // GL_ETC1_RGB8_OES - RGBA_ASTC_4x4 = 0x93B0, // GL_COMPRESSED_RGBA_ASTC_4x4_KHR - RGBA_ASTC_5x4 = 0x93B1, // GL_COMPRESSED_RGBA_ASTC_5x4_KHR - RGBA_ASTC_5x5 = 0x93B2, // GL_COMPRESSED_RGBA_ASTC_5x5_KHR - RGBA_ASTC_6x5 = 0x93B3, // GL_COMPRESSED_RGBA_ASTC_6x5_KHR - RGBA_ASTC_6x6 = 0x93B4, // GL_COMPRESSED_RGBA_ASTC_6x6_KHR - RGBA_ASTC_8x5 = 0x93B5, // GL_COMPRESSED_RGBA_ASTC_8x5_KHR - RGBA_ASTC_8x6 = 0x93B6, // GL_COMPRESSED_RGBA_ASTC_8x6_KHR - RGBA_ASTC_8x8 = 0x93B7, // GL_COMPRESSED_RGBA_ASTC_8x8_KHR - RGBA_ASTC_10x5 = 0x93B8, // GL_COMPRESSED_RGBA_ASTC_10x5_KHR - RGBA_ASTC_10x6 = 0x93B9, // GL_COMPRESSED_RGBA_ASTC_10x6_KHR - RGBA_ASTC_10x8 = 0x93BA, // GL_COMPRESSED_RGBA_ASTC_10x8_KHR - RGBA_ASTC_10x10 = 0x93BB, // GL_COMPRESSED_RGBA_ASTC_10x10_KHR - RGBA_ASTC_12x10 = 0x93BC, // GL_COMPRESSED_RGBA_ASTC_12x10_KHR - RGBA_ASTC_12x12 = 0x93BD, // GL_COMPRESSED_RGBA_ASTC_12x12_KHR - SRGB8_Alpha8_ASTC_4x4 = 0x93D0, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR - SRGB8_Alpha8_ASTC_5x4 = 0x93D1, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR - SRGB8_Alpha8_ASTC_5x5 = 0x93D2, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR - SRGB8_Alpha8_ASTC_6x5 = 0x93D3, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR - SRGB8_Alpha8_ASTC_6x6 = 0x93D4, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR - SRGB8_Alpha8_ASTC_8x5 = 0x93D5, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR - SRGB8_Alpha8_ASTC_8x6 = 0x93D6, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR - SRGB8_Alpha8_ASTC_8x8 = 0x93D7, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR - SRGB8_Alpha8_ASTC_10x5 = 0x93D8, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR - SRGB8_Alpha8_ASTC_10x6 = 0x93D9, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR - SRGB8_Alpha8_ASTC_10x8 = 0x93DA, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR - SRGB8_Alpha8_ASTC_10x10 = 0x93DB, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR - SRGB8_Alpha8_ASTC_12x10 = 0x93DC, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR - SRGB8_Alpha8_ASTC_12x12 = 0x93DD, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR - - // sRGB formats - SRGB8 = 0x8C41, // GL_SRGB8 - SRGB8_Alpha8 = 0x8C43, // GL_SRGB8_ALPHA8 - SRGB_DXT1 = 0x8C4C, // GL_COMPRESSED_SRGB_S3TC_DXT1_EXT - SRGB_Alpha_DXT1 = 0x8C4D, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT - SRGB_Alpha_DXT3 = 0x8C4E, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT - SRGB_Alpha_DXT5 = 0x8C4F, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT - SRGB_BP_UNorm = 0x8E8D, // GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB - - // ES 2 formats - DepthFormat = 0x1902, // GL_DEPTH_COMPONENT - AlphaFormat = 0x1906, // GL_ALPHA - RGBFormat = 0x1907, // GL_RGB - RGBAFormat = 0x1908, // GL_RGBA - LuminanceFormat = 0x1909, // GL_LUMINANCE - LuminanceAlphaFormat = 0x190A - - }; - Q_ENUM(TextureFormat) - - // This is not used externally yet but is reserved to allow checking of - // compatibility between texture formats -#ifndef Q_QDOC - enum TextureFormatClass { - NoFormatClass, - FormatClass_128Bit, - FormatClass_96Bit, - FormatClass_64Bit, - FormatClass_48Bit, - FormatClass_32Bit, - FormatClass_24Bit, - FormatClass_16Bit, - FormatClass_8Bit, - FormatClass_RGTC1_R, - FormatClass_RGTC2_RG, - FormatClass_BPTC_Unorm, - FormatClass_BPTC_Float, - FormatClass_S3TC_DXT1_RGB, - FormatClass_S3TC_DXT1_RGBA, - FormatClass_S3TC_DXT3_RGBA, - FormatClass_S3TC_DXT5_RGBA, - FormatClass_Unique - }; -#endif - - enum CubeMapFace { - CubeMapPositiveX = 0x8515, // GL_TEXTURE_CUBE_MAP_POSITIVE_X - CubeMapNegativeX = 0x8516, // GL_TEXTURE_CUBE_MAP_NEGATIVE_X - CubeMapPositiveY = 0x8517, // GL_TEXTURE_CUBE_MAP_POSITIVE_Y - CubeMapNegativeY = 0x8518, // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - CubeMapPositiveZ = 0x8519, // GL_TEXTURE_CUBE_MAP_POSITIVE_Z - CubeMapNegativeZ = 0x851A // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - }; - Q_ENUM(CubeMapFace) - - enum PixelFormat { - NoSourceFormat = 0, // GL_NONE - Red = 0x1903, // GL_RED - RG = 0x8227, // GL_RG - RGB = 0x1907, // GL_RGB - BGR = 0x80E0, // GL_BGR - RGBA = 0x1908, // GL_RGBA - BGRA = 0x80E1, // GL_BGRA - Red_Integer = 0x8D94, // GL_RED_INTEGER - RG_Integer = 0x8228, // GL_RG_INTEGER - RGB_Integer = 0x8D98, // GL_RGB_INTEGER - BGR_Integer = 0x8D9A, // GL_BGR_INTEGER - RGBA_Integer = 0x8D99, // GL_RGBA_INTEGER - BGRA_Integer = 0x8D9B, // GL_BGRA_INTEGER - Stencil = 0x1901, // GL_STENCIL_INDEX - Depth = 0x1902, // GL_DEPTH_COMPONENT - DepthStencil = 0x84F9, // GL_DEPTH_STENCIL - Alpha = 0x1906, // GL_ALPHA - Luminance = 0x1909, // GL_LUMINANCE - LuminanceAlpha = 0x190A // GL_LUMINANCE_ALPHA - }; - Q_ENUM(PixelFormat) - - enum PixelType { - NoPixelType = 0, // GL_NONE - Int8 = 0x1400, // GL_BYTE - UInt8 = 0x1401, // GL_UNSIGNED_BYTE - Int16 = 0x1402, // GL_SHORT - UInt16 = 0x1403, // GL_UNSIGNED_SHORT - Int32 = 0x1404, // GL_INT - UInt32 = 0x1405, // GL_UNSIGNED_INT - Float16 = 0x140B, // GL_HALF_FLOAT - Float16OES = 0x8D61, // GL_HALF_FLOAT_OES - Float32 = 0x1406, // GL_FLOAT - UInt32_RGB9_E5 = 0x8C3E, // GL_UNSIGNED_INT_5_9_9_9_REV - UInt32_RG11B10F = 0x8C3B, // GL_UNSIGNED_INT_10F_11F_11F_REV - UInt8_RG3B2 = 0x8032, // GL_UNSIGNED_BYTE_3_3_2 - UInt8_RG3B2_Rev = 0x8362, // GL_UNSIGNED_BYTE_2_3_3_REV - UInt16_RGB5A1 = 0x8034, // GL_UNSIGNED_SHORT_5_5_5_1 - UInt16_RGB5A1_Rev = 0x8366, // GL_UNSIGNED_SHORT_1_5_5_5_REV - UInt16_R5G6B5 = 0x8363, // GL_UNSIGNED_SHORT_5_6_5 - UInt16_R5G6B5_Rev = 0x8364, // GL_UNSIGNED_SHORT_5_6_5_REV - UInt16_RGBA4 = 0x8033, // GL_UNSIGNED_SHORT_4_4_4_4 - UInt16_RGBA4_Rev = 0x8365, // GL_UNSIGNED_SHORT_4_4_4_4_REV - UInt32_RGBA8 = 0x8035, // GL_UNSIGNED_INT_8_8_8_8 - UInt32_RGBA8_Rev = 0x8367, // GL_UNSIGNED_INT_8_8_8_8_REV - UInt32_RGB10A2 = 0x8036, // GL_UNSIGNED_INT_10_10_10_2 - UInt32_RGB10A2_Rev = 0x8368, // GL_UNSIGNED_INT_2_10_10_10_REV - UInt32_D24S8 = 0x84FA, // GL_UNSIGNED_INT_24_8 - Float32_D32_UInt32_S8_X24 = 0x8DAD // GL_FLOAT_32_UNSIGNED_INT_24_8_REV - }; - Q_ENUM(PixelType) - - enum SwizzleComponent { - SwizzleRed = 0x8E42, // GL_TEXTURE_SWIZZLE_R - SwizzleGreen = 0x8E43, // GL_TEXTURE_SWIZZLE_G - SwizzleBlue = 0x8E44, // GL_TEXTURE_SWIZZLE_B - SwizzleAlpha = 0x8E45 // GL_TEXTURE_SWIZZLE_A - }; - Q_ENUM(SwizzleComponent) - - enum SwizzleValue { - RedValue = 0x1903, // GL_RED - GreenValue = 0x1904, // GL_GREEN - BlueValue = 0x1905, // GL_BLUE - AlphaValue = 0x1906, // GL_ALPHA - ZeroValue = 0, // GL_ZERO - OneValue = 1 // GL_ONE - }; - Q_ENUM(SwizzleValue) - - enum WrapMode { - Repeat = 0x2901, // GL_REPEAT - MirroredRepeat = 0x8370, // GL_MIRRORED_REPEAT - ClampToEdge = 0x812F, // GL_CLAMP_TO_EDGE - ClampToBorder = 0x812D // GL_CLAMP_TO_BORDER - }; - Q_ENUM(WrapMode) - - enum CoordinateDirection { - DirectionS = 0x2802, // GL_TEXTURE_WRAP_S - DirectionT = 0x2803, // GL_TEXTURE_WRAP_T - DirectionR = 0x8072 // GL_TEXTURE_WRAP_R - }; - Q_ENUM(CoordinateDirection) - - // Features - enum Feature { - ImmutableStorage = 0x00000001, - ImmutableMultisampleStorage = 0x00000002, - TextureRectangle = 0x00000004, - TextureArrays = 0x00000008, - Texture3D = 0x00000010, - TextureMultisample = 0x00000020, - TextureBuffer = 0x00000040, - TextureCubeMapArrays = 0x00000080, - Swizzle = 0x00000100, - StencilTexturing = 0x00000200, - AnisotropicFiltering = 0x00000400, - NPOTTextures = 0x00000800, - NPOTTextureRepeat = 0x00001000, - Texture1D = 0x00002000, - TextureComparisonOperators = 0x00004000, - TextureMipMapLevel = 0x00008000, -#ifndef Q_QDOC - MaxFeatureFlag = 0x00010000 -#endif - }; - Q_DECLARE_FLAGS(Features, Feature) - Q_ENUM(Feature) - - explicit QOpenGLTexture(Target target); - explicit QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps = GenerateMipMaps); - ~QOpenGLTexture(); - - Target target() const; - - // Creation and destruction - bool create(); - void destroy(); - bool isCreated() const; - GLuint textureId() const; - - // Binding and releasing - void bind(); - void bind(uint unit, TextureUnitReset reset = DontResetTextureUnit); - void release(); - void release(uint unit, TextureUnitReset reset = DontResetTextureUnit); - - bool isBound() const; - bool isBound(uint unit); - static GLuint boundTextureId(BindingTarget target); - static GLuint boundTextureId(uint unit, BindingTarget target); - - // Storage allocation - void setFormat(TextureFormat format); - TextureFormat format() const; - void setSize(int width, int height = 1, int depth = 1); - int width() const; - int height() const; - int depth() const; - void setMipLevels(int levels); - int mipLevels() const; - int maximumMipLevels() const; - void setLayers(int layers); - int layers() const; - int faces() const; - void setSamples(int samples); - int samples() const; - void setFixedSamplePositions(bool fixed); - bool isFixedSamplePositions() const; - void allocateStorage(); - void allocateStorage(PixelFormat pixelFormat, PixelType pixelType); - bool isStorageAllocated() const; - - QOpenGLTexture *createTextureView(Target target, - TextureFormat viewFormat, - int minimumMipmapLevel, int maximumMipmapLevel, - int minimumLayer, int maximumLayer) const; - bool isTextureView() const; - - // Pixel transfer - // ### Qt 6: remove the non-const void * overloads -#if QT_DEPRECATED_SINCE(5, 3) - QT_DEPRECATED void setData(int mipLevel, int layer, CubeMapFace cubeFace, - PixelFormat sourceFormat, PixelType sourceType, - void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - QT_DEPRECATED void setData(int mipLevel, int layer, - PixelFormat sourceFormat, PixelType sourceType, - void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - QT_DEPRECATED void setData(int mipLevel, - PixelFormat sourceFormat, PixelType sourceType, - void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - QT_DEPRECATED void setData(PixelFormat sourceFormat, PixelType sourceType, - void *data, const QOpenGLPixelTransferOptions * const options = nullptr); -#endif // QT_DEPRECATED_SINCE(5, 3) - - void setData(int mipLevel, int layer, CubeMapFace cubeFace, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - void setData(int mipLevel, int layer, int layerCount, CubeMapFace cubeFace, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - void setData(int mipLevel, int layer, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - void setData(int mipLevel, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - void setData(PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - - void setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - void setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, int mipLevel, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - void setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, - int mipLevel, int layer, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - void setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, - int mipLevel, int layer, - CubeMapFace cubeFace, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - void setData(int xOffset, int yOffset, int zOffset, - int width, int height, int depth, - int mipLevel, int layer, - CubeMapFace cubeFace, int layerCount, - PixelFormat sourceFormat, PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options = nullptr); - - // Compressed data upload - // ### Qt 6: remove the non-const void * overloads -#if QT_DEPRECATED_SINCE(5, 3) - QT_DEPRECATED void setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace, - int dataSize, void *data, - const QOpenGLPixelTransferOptions * const options = nullptr); - QT_DEPRECATED void setCompressedData(int mipLevel, int layer, - int dataSize, void *data, - const QOpenGLPixelTransferOptions * const options = nullptr); - QT_DEPRECATED void setCompressedData(int mipLevel, int dataSize, void *data, - const QOpenGLPixelTransferOptions * const options = nullptr); - QT_DEPRECATED void setCompressedData(int dataSize, void *data, - const QOpenGLPixelTransferOptions * const options = nullptr); -#endif // QT_DEPRECATED_SINCE(5, 3) - - void setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace, - int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options = nullptr); - void setCompressedData(int mipLevel, int layer, int layerCount, CubeMapFace cubeFace, - int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options = nullptr); - void setCompressedData(int mipLevel, int layer, - int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options = nullptr); - void setCompressedData(int mipLevel, int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options = nullptr); - void setCompressedData(int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options = nullptr); - - // Helpful overloads for setData - void setData(const QImage& image, MipMapGeneration genMipMaps = GenerateMipMaps); - - static bool hasFeature(Feature feature); - - // Texture Parameters - void setMipBaseLevel(int baseLevel); - int mipBaseLevel() const; - void setMipMaxLevel(int maxLevel); - int mipMaxLevel() const; - void setMipLevelRange(int baseLevel, int maxLevel); - QPair<int, int> mipLevelRange() const; - - void setAutoMipMapGenerationEnabled(bool enabled); - bool isAutoMipMapGenerationEnabled() const; - - void generateMipMaps(); - void generateMipMaps(int baseLevel, bool resetBaseLevel = true); - - void setSwizzleMask(SwizzleComponent component, SwizzleValue value); - void setSwizzleMask(SwizzleValue r, SwizzleValue g, - SwizzleValue b, SwizzleValue a); - SwizzleValue swizzleMask(SwizzleComponent component) const; - - enum DepthStencilMode { - DepthMode = 0x1902, // GL_DEPTH_COMPONENT - StencilMode = 0x1901 // GL_STENCIL_INDEX - }; - Q_ENUM(DepthStencilMode) - - void setDepthStencilMode(DepthStencilMode mode); - DepthStencilMode depthStencilMode() const; - - enum ComparisonFunction { - CompareLessEqual = 0x0203, // GL_LEQUAL - CompareGreaterEqual = 0x0206, // GL_GEQUAL - CompareLess = 0x0201, // GL_LESS - CompareGreater = 0x0204, // GL_GREATER - CompareEqual = 0x0202, // GL_EQUAL - CommpareNotEqual = 0x0205, // GL_NOTEQUAL - CompareAlways = 0x0207, // GL_ALWAYS - CompareNever = 0x0200 // GL_NEVER - }; - Q_ENUM(ComparisonFunction) - - void setComparisonFunction(ComparisonFunction function); - ComparisonFunction comparisonFunction() const; - - enum ComparisonMode { - CompareRefToTexture = 0x884E, // GL_COMPARE_REF_TO_TEXTURE - CompareNone = 0x0000 // GL_NONE - }; - - void setComparisonMode(ComparisonMode mode); - ComparisonMode comparisonMode() const; - - // Sampling Parameters - enum Filter { - Nearest = 0x2600, // GL_NEAREST - Linear = 0x2601, // GL_LINEAR - NearestMipMapNearest = 0x2700, // GL_NEAREST_MIPMAP_NEAREST - NearestMipMapLinear = 0x2702, // GL_NEAREST_MIPMAP_LINEAR - LinearMipMapNearest = 0x2701, // GL_LINEAR_MIPMAP_NEAREST - LinearMipMapLinear = 0x2703 // GL_LINEAR_MIPMAP_LINEAR - }; - Q_ENUM(Filter) - - void setMinificationFilter(Filter filter); - Filter minificationFilter() const; - void setMagnificationFilter(Filter filter); - Filter magnificationFilter() const; - void setMinMagFilters(Filter minificationFilter, - Filter magnificationFilter); - QPair<Filter, Filter> minMagFilters() const; - void setMaximumAnisotropy(float anisotropy); - float maximumAnisotropy() const; - - void setWrapMode(WrapMode mode); - void setWrapMode(CoordinateDirection direction, WrapMode mode); - WrapMode wrapMode(CoordinateDirection direction) const; - - void setBorderColor(QColor color); - void setBorderColor(float r, float g, float b, float a); - void setBorderColor(int r, int g, int b, int a); - void setBorderColor(uint r, uint g, uint b, uint a); - - QColor borderColor() const; - void borderColor(float *border) const; - void borderColor(int *border) const; - void borderColor(unsigned int *border) const; - - void setMinimumLevelOfDetail(float value); - float minimumLevelOfDetail() const; - void setMaximumLevelOfDetail(float value); - float maximumLevelOfDetail() const; - void setLevelOfDetailRange(float min, float max); - QPair<float, float> levelOfDetailRange() const; - void setLevelofDetailBias(float bias); - float levelofDetailBias() const; - -#ifndef QT_NO_DEBUG_STREAM - friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QOpenGLTexture *t); -#endif - -private: - Q_DISABLE_COPY(QOpenGLTexture) - Q_DECLARE_PRIVATE(QOpenGLTexture) - QScopedPointer<QOpenGLTexturePrivate> d_ptr; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLTexture::Features) - -#ifndef QT_NO_DEBUG_STREAM -Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QOpenGLTexture *t); -#endif - -QT_END_NAMESPACE - -#endif // QT_NO_OPENGL - -#endif // QOPENGLABSTRACTTEXTURE_H diff --git a/src/gui/opengl/qopengltexture_p.h b/src/gui/opengl/qopengltexture_p.h deleted file mode 100644 index 9f3457ad0a..0000000000 --- a/src/gui/opengl/qopengltexture_p.h +++ /dev/null @@ -1,184 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QABSTRACTOPENGLTEXTURE_P_H -#define QABSTRACTOPENGLTEXTURE_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. -// - -#ifndef QT_NO_OPENGL - -#include <QtGui/private/qtguiglobal_p.h> -#include "private/qobject_p.h" -#include "qopengltexture.h" -#include "qopengl.h" - -#include <cmath> - -namespace { -inline double qLog2(const double x) -{ - return std::log(x) / std::log(2.0); -} -} - -QT_BEGIN_NAMESPACE - -class QOpenGLContext; -class QOpenGLTextureHelper; -class QOpenGLFunctions; - -class QOpenGLTexturePrivate -{ -public: - QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarget, - QOpenGLTexture *qq); - ~QOpenGLTexturePrivate(); - - Q_DECLARE_PUBLIC(QOpenGLTexture) - - void resetFuncs(QOpenGLTextureHelper *funcs); - void initializeOpenGLFunctions(); - - bool create(); - void destroy(); - - void bind(); - void bind(uint unit, QOpenGLTexture::TextureUnitReset reset = QOpenGLTexture::DontResetTextureUnit); - void release(); - void release(uint unit, QOpenGLTexture::TextureUnitReset reset = QOpenGLTexture::DontResetTextureUnit); - bool isBound() const; - bool isBound(uint unit) const; - - void allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType); - void allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType); - void allocateImmutableStorage(); - void setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, - QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options); - void setData(int xOffset, int yOffset, int zOffset, int width, int height, int depth, - int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, - QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType, - const void *data, const QOpenGLPixelTransferOptions * const options); - void setCompressedData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, - int dataSize, const void *data, - const QOpenGLPixelTransferOptions * const options); - - - void setWrapMode(QOpenGLTexture::WrapMode mode); - void setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode); - QOpenGLTexture::WrapMode wrapMode(QOpenGLTexture::CoordinateDirection direction) const; - - QOpenGLTexture *createTextureView(QOpenGLTexture::Target target, QOpenGLTexture::TextureFormat viewFormat, - int minimumMipmapLevel, int maximumMipmapLevel, - int minimumLayer, int maximumLayer) const; - - int evaluateMipLevels() const; - - inline int maximumMipLevelCount() const - { - return 1 + std::floor(qLog2(qMax(dimensions[0], qMax(dimensions[1], dimensions[2])))); - } - - static inline int mipLevelSize(int mipLevel, int baseLevelSize) - { - return std::floor(double(qMax(1, baseLevelSize >> mipLevel))); - } - - bool isUsingImmutableStorage() const; - - QOpenGLTexture *q_ptr; - QOpenGLContext *context; - QOpenGLTexture::Target target; - QOpenGLTexture::BindingTarget bindingTarget; - GLuint textureId; - QOpenGLTexture::TextureFormat format; - QOpenGLTexture::TextureFormatClass formatClass; - int dimensions[3]; - int requestedMipLevels; - int mipLevels; - int layers; - int faces; - - int samples; - bool fixedSamplePositions; - - int baseLevel; - int maxLevel; - - QOpenGLTexture::SwizzleValue swizzleMask[4]; - QOpenGLTexture::DepthStencilMode depthStencilMode; - QOpenGLTexture::ComparisonFunction comparisonFunction; - QOpenGLTexture::ComparisonMode comparisonMode; - - QOpenGLTexture::Filter minFilter; - QOpenGLTexture::Filter magFilter; - float maxAnisotropy; - QOpenGLTexture::WrapMode wrapModes[3]; - QVariantList borderColor; - float minLevelOfDetail; - float maxLevelOfDetail; - float levelOfDetailBias; - - bool textureView; - bool autoGenerateMipMaps; - bool storageAllocated; - - QOpenGLTextureHelper *texFuncs; - QOpenGLFunctions *functions; - - QOpenGLTexture::Features features; -}; - -QT_END_NAMESPACE - -#undef Q_CALL_MEMBER_FUNCTION - -#endif // QT_NO_OPENGL - -#endif // QABSTRACTOPENGLTEXTURE_P_H diff --git a/src/gui/opengl/qopengltexturecache.cpp b/src/gui/opengl/qopengltexturecache.cpp deleted file mode 100644 index ef07dbe109..0000000000 --- a/src/gui/opengl/qopengltexturecache.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopengltexturecache_p.h" -#include "qopengltextureuploader_p.h" -#include <qmath.h> -#include <qopenglfunctions.h> -#include <private/qimagepixmapcleanuphooks_p.h> -#include <qpa/qplatformpixmap.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(256 * 1024) // 256 MB cache -{ -} - -QOpenGLTextureCache::~QOpenGLTextureCache() -{ -} - -GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &pixmap, QOpenGLTextureUploader::BindOptions options) -{ - if (pixmap.isNull()) - return 0; - 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 && entry->options() == options) { - context->functions()->glBindTexture(GL_TEXTURE_2D, entry->id()); - return entry->id(); - } - } - - GLuint id = bindTexture(context, key, pixmap.toImage(), options); - if (id > 0) - QImagePixmapCleanupHooks::enableCleanupHooks(pixmap); - - return id; -} - -GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image, QOpenGLTextureUploader::BindOptions options) -{ - if (image.isNull()) - return 0; - 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 && entry->options() == options) { - context->functions()->glBindTexture(GL_TEXTURE_2D, entry->id()); - return entry->id(); - } - } - - QImage img = image; - if (!context->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)) - options |= QOpenGLTextureUploader::PowerOfTwoBindOption; - - GLuint id = bindTexture(context, key, img, options); - if (id > 0) - QImagePixmapCleanupHooks::enableCleanupHooks(image); - - return id; -} - -GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, QOpenGLTextureUploader::BindOptions options) -{ - GLuint id; - QOpenGLFunctions *funcs = context->functions(); - funcs->glGenTextures(1, &id); - funcs->glBindTexture(GL_TEXTURE_2D, id); - - int cost = QOpenGLTextureUploader::textureImage(GL_TEXTURE_2D, image, options); - - m_cache.insert(key, new QOpenGLCachedTexture(id, options, context), cost / 1024); - - 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 *funcs, GLuint id) -{ - funcs->glDeleteTextures(1, &id); -} - -QOpenGLCachedTexture::QOpenGLCachedTexture(GLuint id, QOpenGLTextureUploader::BindOptions options, QOpenGLContext *context) : m_options(options) -{ - 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 deleted file mode 100644 index 88ef06e744..0000000000 --- a/src/gui/opengl/qopengltexturecache_p.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $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 <QtGui/private/qtguiglobal_p.h> -#include <QHash> -#include <QObject> -#include <QCache> -#include <private/qopenglcontext_p.h> -#include <private/qopengltextureuploader_p.h> -#include <QtCore/qmutex.h> - -QT_BEGIN_NAMESPACE - -class QOpenGLCachedTexture; - -class Q_GUI_EXPORT QOpenGLTextureCache : public QOpenGLSharedResource -{ -public: - static QOpenGLTextureCache *cacheForContext(QOpenGLContext *context); - - QOpenGLTextureCache(QOpenGLContext *); - ~QOpenGLTextureCache(); - - GLuint bindTexture(QOpenGLContext *context, const QPixmap &pixmap, - QOpenGLTextureUploader::BindOptions options = QOpenGLTextureUploader::PremultipliedAlphaBindOption); - GLuint bindTexture(QOpenGLContext *context, const QImage &image, - QOpenGLTextureUploader::BindOptions options = QOpenGLTextureUploader::PremultipliedAlphaBindOption); - - void invalidate(qint64 key); - - void invalidateResource() override; - void freeResource(QOpenGLContext *ctx) override; - -private: - GLuint bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, QOpenGLTextureUploader::BindOptions options); - - QMutex m_mutex; - QCache<quint64, QOpenGLCachedTexture> m_cache; -}; - -class QOpenGLCachedTexture -{ -public: - QOpenGLCachedTexture(GLuint id, QOpenGLTextureUploader::BindOptions options, QOpenGLContext *context); - ~QOpenGLCachedTexture() { m_resource->free(); } - - GLuint id() const { return m_resource->id(); } - QOpenGLTextureUploader::BindOptions options() const { return m_options; } - -private: - QOpenGLSharedResourceGuard *m_resource; - QOpenGLTextureUploader::BindOptions m_options; -}; - -QT_END_NAMESPACE - -#endif - diff --git a/src/gui/opengl/qopengltextureglyphcache.cpp b/src/gui/opengl/qopengltextureglyphcache.cpp deleted file mode 100644 index 41027d26e0..0000000000 --- a/src/gui/opengl/qopengltextureglyphcache.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopengltextureglyphcache_p.h" -#include "qopenglpaintengine_p.h" -#include "private/qopenglengineshadersource_p.h" -#include "qopenglextensions_p.h" -#include <qrgb.h> -#include <private/qdrawhelper_p.h> - -QT_BEGIN_NAMESPACE - - -static int next_qopengltextureglyphcache_serial_number() -{ - static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0); - return 1 + serial.fetchAndAddRelaxed(1); -} - -QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix, const QColor &color) - : QImageTextureGlyphCache(format, matrix, color) - , m_textureResource(nullptr) - , pex(nullptr) - , m_blitProgram(nullptr) - , m_filterMode(Nearest) - , m_serialNumber(next_qopengltextureglyphcache_serial_number()) - , m_buffer(QOpenGLBuffer::VertexBuffer) -{ -#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG - qDebug(" -> QOpenGLTextureGlyphCache() %p for context %p.", this, QOpenGLContext::currentContext()); -#endif - m_vertexCoordinateArray[0] = -1.0f; - m_vertexCoordinateArray[1] = -1.0f; - m_vertexCoordinateArray[2] = 1.0f; - m_vertexCoordinateArray[3] = -1.0f; - m_vertexCoordinateArray[4] = 1.0f; - m_vertexCoordinateArray[5] = 1.0f; - m_vertexCoordinateArray[6] = -1.0f; - m_vertexCoordinateArray[7] = 1.0f; - - m_textureCoordinateArray[0] = 0.0f; - m_textureCoordinateArray[1] = 0.0f; - m_textureCoordinateArray[2] = 1.0f; - m_textureCoordinateArray[3] = 0.0f; - m_textureCoordinateArray[4] = 1.0f; - m_textureCoordinateArray[5] = 1.0f; - m_textureCoordinateArray[6] = 0.0f; - m_textureCoordinateArray[7] = 1.0f; -} - -QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache() -{ -#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG - qDebug(" -> ~QOpenGLTextureGlyphCache() %p.", this); -#endif - clear(); -} - -#if !defined(QT_OPENGL_ES_2) -static inline bool isCoreProfile() -{ - return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile; -} -#endif - -void QOpenGLTextureGlyphCache::createTextureData(int width, int height) -{ - QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); - if (ctx == nullptr) { - qWarning("QOpenGLTextureGlyphCache::createTextureData: Called with no context"); - return; - } - - // create in QImageTextureGlyphCache baseclass is meant to be called - // only to create the initial image and does not preserve the content, - // so we don't call when this function is called from resize. - if (ctx->d_func()->workaround_brokenFBOReadBack && image().isNull()) - QImageTextureGlyphCache::createTextureData(width, height); - - // Make the lower glyph texture size 16 x 16. - if (width < 16) - width = 16; - if (height < 16) - height = 16; - - if (m_textureResource && !m_textureResource->m_texture) { - delete m_textureResource; - m_textureResource = nullptr; - } - - if (!m_textureResource) - m_textureResource = new QOpenGLGlyphTexture(ctx); - - QOpenGLFunctions *funcs = ctx->functions(); - funcs->glGenTextures(1, &m_textureResource->m_texture); - funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); - - m_textureResource->m_width = width; - m_textureResource->m_height = height; - - if (m_format == QFontEngine::Format_A32 || m_format == QFontEngine::Format_ARGB) { - QVarLengthArray<uchar> data(width * height * 4); - for (int i = 0; i < data.size(); ++i) - data[i] = 0; - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); - } else { - QVarLengthArray<uchar> data(width * height); - for (int i = 0; i < data.size(); ++i) - data[i] = 0; -#if !defined(QT_OPENGL_ES_2) - const GLint internalFormat = isCoreProfile() ? GL_R8 : GL_ALPHA; - const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA; -#else - const GLint internalFormat = GL_ALPHA; - const GLenum format = GL_ALPHA; -#endif - funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, &data[0]); - } - - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - m_filterMode = Nearest; - - if (!m_buffer.isCreated()) { - m_buffer.create(); - m_buffer.bind(); - static GLfloat buf[sizeof(m_vertexCoordinateArray) + sizeof(m_textureCoordinateArray)]; - memcpy(buf, m_vertexCoordinateArray, sizeof(m_vertexCoordinateArray)); - memcpy(buf + (sizeof(m_vertexCoordinateArray) / sizeof(GLfloat)), - m_textureCoordinateArray, - sizeof(m_textureCoordinateArray)); - m_buffer.allocate(buf, sizeof(buf)); - m_buffer.release(); - } - - if (!m_vao.isCreated()) - m_vao.create(); -} - -void QOpenGLTextureGlyphCache::setupVertexAttribs() -{ - m_buffer.bind(); - m_blitProgram->setAttributeBuffer(int(QT_VERTEX_COORDS_ATTR), GL_FLOAT, 0, 2); - m_blitProgram->setAttributeBuffer(int(QT_TEXTURE_COORDS_ATTR), GL_FLOAT, sizeof(m_vertexCoordinateArray), 2); - m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); - m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); - m_buffer.release(); -} - -static void load_glyph_image_to_texture(QOpenGLContext *ctx, - QImage &img, - GLuint texture, - int tx, int ty) -{ - QOpenGLFunctions *funcs = ctx->functions(); - - const int imgWidth = img.width(); - const int imgHeight = img.height(); - - if (img.format() == QImage::Format_Mono) { - img = img.convertToFormat(QImage::Format_Grayscale8); - } else if (img.depth() == 32) { - if (img.format() == QImage::Format_RGB32 - // We need to make the alpha component equal to the average of the RGB values. - // This is needed when drawing sub-pixel antialiased text on translucent targets. -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - || img.format() == QImage::Format_ARGB32_Premultiplied -#else - || (img.format() == QImage::Format_ARGB32_Premultiplied - && ctx->isOpenGLES()) -#endif - ) { - for (int y = 0; y < imgHeight; ++y) { - QRgb *src = (QRgb *) img.scanLine(y); - for (int x = 0; x < imgWidth; ++x) { - int r = qRed(src[x]); - int g = qGreen(src[x]); - int b = qBlue(src[x]); - int avg; - if (img.format() == QImage::Format_RGB32) - avg = (r + g + b + 1) / 3; // "+1" for rounding. - else // Format_ARGB_Premultiplied - avg = qAlpha(src[x]); - - src[x] = qRgba(r, g, b, avg); - // swizzle the bits to accommodate for the GL_RGBA upload. -#if Q_BYTE_ORDER != Q_BIG_ENDIAN - if (ctx->isOpenGLES()) -#endif - src[x] = ARGB2RGBA(src[x]); - } - } - } - } - - funcs->glBindTexture(GL_TEXTURE_2D, texture); - if (img.depth() == 32) { -#ifdef QT_OPENGL_ES_2 - GLenum fmt = GL_RGBA; -#else - GLenum fmt = ctx->isOpenGLES() ? GL_RGBA : GL_BGRA; -#endif // QT_OPENGL_ES_2 - -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - fmt = GL_RGBA; -#endif - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, imgWidth, imgHeight, fmt, GL_UNSIGNED_BYTE, img.constBits()); - } else { - // The scanlines in image are 32-bit aligned, even for mono or 8-bit formats. This - // is good because it matches the default of 4 bytes for GL_UNPACK_ALIGNMENT. -#if !defined(QT_OPENGL_ES_2) - const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA; -#else - const GLenum format = GL_ALPHA; -#endif - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, imgWidth, imgHeight, format, GL_UNSIGNED_BYTE, img.constBits()); - } -} - -static void load_glyph_image_region_to_texture(QOpenGLContext *ctx, - const QImage &srcImg, - int x, int y, - int w, int h, - GLuint texture, - int tx, int ty) -{ - Q_ASSERT(x + w <= srcImg.width() && y + h <= srcImg.height()); - - QImage img; - if (x != 0 || y != 0 || w != srcImg.width() || h != srcImg.height()) - img = srcImg.copy(x, y, w, h); - else - img = srcImg; - - load_glyph_image_to_texture(ctx, img, texture, tx, ty); -} - -void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height) -{ - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (ctx == nullptr) { - qWarning("QOpenGLTextureGlyphCache::resizeTextureData: Called with no context"); - return; - } - - QOpenGLFunctions *funcs = ctx->functions(); - GLint oldFbo; - funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFbo); - - int oldWidth = m_textureResource->m_width; - int oldHeight = m_textureResource->m_height; - - // Make the lower glyph texture size 16 x 16. - if (width < 16) - width = 16; - if (height < 16) - height = 16; - - GLuint oldTexture = m_textureResource->m_texture; - createTextureData(width, height); - - if (ctx->d_func()->workaround_brokenFBOReadBack) { - QImageTextureGlyphCache::resizeTextureData(width, height); - load_glyph_image_region_to_texture(ctx, image(), 0, 0, qMin(oldWidth, width), qMin(oldHeight, height), - m_textureResource->m_texture, 0, 0); - return; - } - - // ### the QTextureGlyphCache API needs to be reworked to allow - // ### resizeTextureData to fail - - funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo); - - GLuint tmp_texture; - funcs->glGenTextures(1, &tmp_texture); - funcs->glBindTexture(GL_TEXTURE_2D, tmp_texture); - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, - GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - m_filterMode = Nearest; - funcs->glBindTexture(GL_TEXTURE_2D, 0); - funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, tmp_texture, 0); - - funcs->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - funcs->glBindTexture(GL_TEXTURE_2D, oldTexture); - - if (pex != nullptr) - pex->transferMode(BrushDrawingMode); - - funcs->glDisable(GL_STENCIL_TEST); - funcs->glDisable(GL_DEPTH_TEST); - funcs->glDisable(GL_SCISSOR_TEST); - funcs->glDisable(GL_BLEND); - - funcs->glViewport(0, 0, oldWidth, oldHeight); - - QOpenGLShaderProgram *blitProgram = nullptr; - if (pex == nullptr) { - if (m_blitProgram == nullptr) { - m_blitProgram = new QOpenGLShaderProgram; - const bool isCoreProfile = ctx->format().profile() == QSurfaceFormat::CoreProfile; - - { - QString source; -#ifdef Q_OS_WASM - source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader)); - source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader)); -#else - source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader)); - source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader)); -#endif - m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, source); - } - - { - QString source; -#ifdef Q_OS_WASM - source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader)); - source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader)); -#else - source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader)); - source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader)); -#endif - m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, source); - } - - m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); - m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); - - m_blitProgram->link(); - - if (m_vao.isCreated()) { - m_vao.bind(); - setupVertexAttribs(); - } - } - - if (m_vao.isCreated()) - m_vao.bind(); - else - setupVertexAttribs(); - - m_blitProgram->bind(); - blitProgram = m_blitProgram; - - } else { - pex->uploadData(QT_VERTEX_COORDS_ATTR, m_vertexCoordinateArray, 8); - pex->uploadData(QT_TEXTURE_COORDS_ATTR, m_textureCoordinateArray, 8); - - pex->shaderManager->useBlitProgram(); - blitProgram = pex->shaderManager->blitProgram(); - } - - blitProgram->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT); - - funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); - - funcs->glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); - - funcs->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, 0); - funcs->glDeleteTextures(1, &tmp_texture); - funcs->glDeleteTextures(1, &oldTexture); - - funcs->glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)oldFbo); - - if (pex != nullptr) { - funcs->glViewport(0, 0, pex->width, pex->height); - pex->updateClipScissorTest(); - } else { - if (m_vao.isCreated()) { - m_vao.release(); - } else { - m_blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); - m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); - } - } -} - -void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) -{ - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (ctx == nullptr) { - qWarning("QOpenGLTextureGlyphCache::fillTexture: Called with no context"); - return; - } - - if (ctx->d_func()->workaround_brokenFBOReadBack) { - QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition); - load_glyph_image_region_to_texture(ctx, image(), c.x, c.y, c.w, c.h, m_textureResource->m_texture, c.x, c.y); - return; - } - - QImage mask = textureMapForGlyph(glyph, subPixelPosition); - load_glyph_image_to_texture(ctx, mask, m_textureResource->m_texture, c.x, c.y); -} - -int QOpenGLTextureGlyphCache::glyphPadding() const -{ - return 1; -} - -int QOpenGLTextureGlyphCache::maxTextureWidth() const -{ - QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); - if (ctx == nullptr) - return QImageTextureGlyphCache::maxTextureWidth(); - else - return ctx->d_func()->maxTextureSize(); -} - -int QOpenGLTextureGlyphCache::maxTextureHeight() const -{ - QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); - if (ctx == nullptr) - return QImageTextureGlyphCache::maxTextureHeight(); - - if (ctx->d_func()->workaround_brokenTexSubImage) - return qMin(1024, ctx->d_func()->maxTextureSize()); - else - return ctx->d_func()->maxTextureSize(); -} - -void QOpenGLTextureGlyphCache::clear() -{ - if (m_textureResource) - m_textureResource->free(); - m_textureResource = nullptr; - - delete m_blitProgram; - m_blitProgram = nullptr; - - m_w = 0; - m_h = 0; - m_cx = 0; - m_cy = 0; - m_currentRowHeight = 0; - coords.clear(); -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengltextureglyphcache_p.h b/src/gui/opengl/qopengltextureglyphcache_p.h deleted file mode 100644 index 4bea4a463a..0000000000 --- a/src/gui/opengl/qopengltextureglyphcache_p.h +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLTEXTUREGLYPHCACHE_P_H -#define QOPENGLTEXTUREGLYPHCACHE_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/private/qtguiglobal_p.h> -#include <private/qtextureglyphcache_p.h> -#include <private/qopenglcontext_p.h> -#include <qopenglshaderprogram.h> -#include <qopenglfunctions.h> -#include <qopenglbuffer.h> -#include <qopenglvertexarrayobject.h> - -// #define QT_GL_TEXTURE_GLYPH_CACHE_DEBUG - -QT_BEGIN_NAMESPACE - -class QOpenGL2PaintEngineExPrivate; - -class QOpenGLGlyphTexture : public QOpenGLSharedResource -{ -public: - explicit QOpenGLGlyphTexture(QOpenGLContext *ctx) - : QOpenGLSharedResource(ctx->shareGroup()) - , m_width(0) - , m_height(0) - { - if (!ctx->d_func()->workaround_brokenFBOReadBack) - QOpenGLFunctions(ctx).glGenFramebuffers(1, &m_fbo); - -#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG - qDebug(" -> QOpenGLGlyphTexture() %p for context %p.", this, ctx); -#endif - } - - void freeResource(QOpenGLContext *context) override - { - QOpenGLContext *ctx = context; -#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG - qDebug("~QOpenGLGlyphTexture() %p for context %p.", this, ctx); -#endif - if (!ctx->d_func()->workaround_brokenFBOReadBack) - ctx->functions()->glDeleteFramebuffers(1, &m_fbo); - if (m_width || m_height) - ctx->functions()->glDeleteTextures(1, &m_texture); - } - - void invalidateResource() override - { - m_texture = 0; - m_fbo = 0; - m_width = 0; - m_height = 0; - } - - GLuint m_texture; - GLuint m_fbo; - int m_width; - int m_height; -}; - -class Q_GUI_EXPORT QOpenGLTextureGlyphCache : public QImageTextureGlyphCache -{ -public: - QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat glyphFormat, const QTransform &matrix, const QColor &color = QColor()); - ~QOpenGLTextureGlyphCache(); - - virtual void createTextureData(int width, int height) override; - virtual void resizeTextureData(int width, int height) override; - virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) override; - virtual int glyphPadding() const override; - virtual int maxTextureWidth() const override; - virtual int maxTextureHeight() const override; - - inline GLuint texture() const { - QOpenGLTextureGlyphCache *that = const_cast<QOpenGLTextureGlyphCache *>(this); - QOpenGLGlyphTexture *glyphTexture = that->m_textureResource; - return glyphTexture ? glyphTexture->m_texture : 0; - } - - inline int width() const { - QOpenGLTextureGlyphCache *that = const_cast<QOpenGLTextureGlyphCache *>(this); - QOpenGLGlyphTexture *glyphTexture = that->m_textureResource; - return glyphTexture ? glyphTexture->m_width : 0; - } - inline int height() const { - QOpenGLTextureGlyphCache *that = const_cast<QOpenGLTextureGlyphCache *>(this); - QOpenGLGlyphTexture *glyphTexture = that->m_textureResource; - return glyphTexture ? glyphTexture->m_height : 0; - } - - inline void setPaintEnginePrivate(QOpenGL2PaintEngineExPrivate *p) { pex = p; } - - inline const QOpenGLContextGroup *contextGroup() const { return m_textureResource ? m_textureResource->group() : nullptr; } - - inline int serialNumber() const { return m_serialNumber; } - - enum FilterMode { - Nearest, - Linear - }; - FilterMode filterMode() const { return m_filterMode; } - void setFilterMode(FilterMode m) { m_filterMode = m; } - - void clear(); - - QOpenGL2PaintEngineExPrivate *paintEnginePrivate() const - { - return pex; - } - -private: - void setupVertexAttribs(); - - QOpenGLGlyphTexture *m_textureResource; - - QOpenGL2PaintEngineExPrivate *pex; - QOpenGLShaderProgram *m_blitProgram; - FilterMode m_filterMode; - - GLfloat m_vertexCoordinateArray[8]; - GLfloat m_textureCoordinateArray[8]; - - int m_serialNumber; - - QOpenGLBuffer m_buffer; - QOpenGLVertexArrayObject m_vao; -}; - -QT_END_NAMESPACE - -#endif // QOPENGLTEXTUREGLYPHCACHE_P_H - diff --git a/src/gui/opengl/qopengltexturehelper.cpp b/src/gui/opengl/qopengltexturehelper.cpp deleted file mode 100644 index 6709edc4e2..0000000000 --- a/src/gui/opengl/qopengltexturehelper.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopengltexturehelper_p.h" - -#include <QOpenGLContext> -#include <private/qopenglextensions_p.h> - -QT_BEGIN_NAMESPACE - -QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context) -{ - functions = context->functions(); - // Resolve EXT_direct_state_access entry points if present. - - // However, disable it on some systems where DSA is known to be unreliable. - bool allowDSA = true; - const char *renderer = reinterpret_cast<const char *>(context->functions()->glGetString(GL_RENDERER)); - // QTBUG-40653, QTBUG-44988 - if (renderer && strstr(renderer, "AMD Radeon HD")) - allowDSA = false; - - if (allowDSA && !context->isOpenGLES() - && context->hasExtension(QByteArrayLiteral("GL_EXT_direct_state_access"))) { - TextureParameteriEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , GLint )>(context->getProcAddress("glTextureParameteriEXT")); - TextureParameterivEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , const GLint *)>(context->getProcAddress("glTextureParameterivEXT")); - TextureParameterfEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , GLfloat )>(context->getProcAddress("glTextureParameterfEXT")); - TextureParameterfvEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , const GLfloat *)>(context->getProcAddress("glTextureParameterfvEXT")); - GenerateTextureMipmapEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum )>(context->getProcAddress("glGenerateTextureMipmapEXT")); - TextureStorage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLsizei )>(context->getProcAddress("glTextureStorage3DEXT")); - TextureStorage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei , GLsizei )>(context->getProcAddress("glTextureStorage2DEXT")); - TextureStorage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei )>(context->getProcAddress("glTextureStorage1DEXT")); - TextureStorage3DMultisampleEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTextureStorage3DMultisampleEXT")); - TextureStorage2DMultisampleEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTextureStorage2DMultisampleEXT")); - TextureImage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureImage3DEXT")); - TextureImage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureImage2DEXT")); - TextureImage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureImage1DEXT")); - TextureSubImage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureSubImage3DEXT")); - TextureSubImage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureSubImage2DEXT")); - TextureSubImage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureSubImage1DEXT")); - CompressedTextureSubImage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureSubImage1DEXT")); - CompressedTextureSubImage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureSubImage2DEXT")); - CompressedTextureSubImage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureSubImage3DEXT")); - CompressedTextureImage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureImage1DEXT")); - CompressedTextureImage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureImage2DEXT")); - CompressedTextureImage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureImage3DEXT")); - - // Use the real DSA functions - TextureParameteri = &QOpenGLTextureHelper::dsa_TextureParameteri; - TextureParameteriv = &QOpenGLTextureHelper::dsa_TextureParameteriv; - TextureParameterf = &QOpenGLTextureHelper::dsa_TextureParameterf; - TextureParameterfv = &QOpenGLTextureHelper::dsa_TextureParameterfv; - GenerateTextureMipmap = &QOpenGLTextureHelper::dsa_GenerateTextureMipmap; - TextureStorage3D = &QOpenGLTextureHelper::dsa_TextureStorage3D; - TextureStorage2D = &QOpenGLTextureHelper::dsa_TextureStorage2D; - TextureStorage1D = &QOpenGLTextureHelper::dsa_TextureStorage1D; - TextureStorage3DMultisample = &QOpenGLTextureHelper::dsa_TextureStorage3DMultisample; - TextureStorage2DMultisample = &QOpenGLTextureHelper::dsa_TextureStorage2DMultisample; - TextureImage3D = &QOpenGLTextureHelper::dsa_TextureImage3D; - TextureImage2D = &QOpenGLTextureHelper::dsa_TextureImage2D; - TextureImage1D = &QOpenGLTextureHelper::dsa_TextureImage1D; - TextureSubImage3D = &QOpenGLTextureHelper::dsa_TextureSubImage3D; - TextureSubImage2D = &QOpenGLTextureHelper::dsa_TextureSubImage2D; - TextureSubImage1D = &QOpenGLTextureHelper::dsa_TextureSubImage1D; - CompressedTextureSubImage1D = &QOpenGLTextureHelper::dsa_CompressedTextureSubImage1D; - CompressedTextureSubImage2D = &QOpenGLTextureHelper::dsa_CompressedTextureSubImage2D; - CompressedTextureSubImage3D = &QOpenGLTextureHelper::dsa_CompressedTextureSubImage3D; - CompressedTextureImage1D = &QOpenGLTextureHelper::dsa_CompressedTextureImage1D; - CompressedTextureImage2D = &QOpenGLTextureHelper::dsa_CompressedTextureImage2D; - CompressedTextureImage3D = &QOpenGLTextureHelper::dsa_CompressedTextureImage3D; - } else { - // Use our own DSA emulation - TextureParameteri = &QOpenGLTextureHelper::qt_TextureParameteri; - TextureParameteriv = &QOpenGLTextureHelper::qt_TextureParameteriv; - TextureParameterf = &QOpenGLTextureHelper::qt_TextureParameterf; - TextureParameterfv = &QOpenGLTextureHelper::qt_TextureParameterfv; - GenerateTextureMipmap = &QOpenGLTextureHelper::qt_GenerateTextureMipmap; - TextureStorage3D = &QOpenGLTextureHelper::qt_TextureStorage3D; - TextureStorage2D = &QOpenGLTextureHelper::qt_TextureStorage2D; - TextureStorage1D = &QOpenGLTextureHelper::qt_TextureStorage1D; - TextureStorage3DMultisample = &QOpenGLTextureHelper::qt_TextureStorage3DMultisample; - TextureStorage2DMultisample = &QOpenGLTextureHelper::qt_TextureStorage2DMultisample; - TextureImage3D = &QOpenGLTextureHelper::qt_TextureImage3D; - TextureImage2D = &QOpenGLTextureHelper::qt_TextureImage2D; - TextureImage1D = &QOpenGLTextureHelper::qt_TextureImage1D; - TextureSubImage3D = &QOpenGLTextureHelper::qt_TextureSubImage3D; - TextureSubImage2D = &QOpenGLTextureHelper::qt_TextureSubImage2D; - TextureSubImage1D = &QOpenGLTextureHelper::qt_TextureSubImage1D; - CompressedTextureSubImage1D = &QOpenGLTextureHelper::qt_CompressedTextureSubImage1D; - CompressedTextureSubImage2D = &QOpenGLTextureHelper::qt_CompressedTextureSubImage2D; - CompressedTextureSubImage3D = &QOpenGLTextureHelper::qt_CompressedTextureSubImage3D; - CompressedTextureImage1D = &QOpenGLTextureHelper::qt_CompressedTextureImage1D; - CompressedTextureImage2D = &QOpenGLTextureHelper::qt_CompressedTextureImage2D; - CompressedTextureImage3D = &QOpenGLTextureHelper::qt_CompressedTextureImage3D; - } - - // Some DSA functions are part of NV_texture_multisample instead - if (!context->isOpenGLES() - && context->hasExtension(QByteArrayLiteral("GL_NV_texture_multisample"))) { - TextureImage3DMultisampleNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLint , GLsizei , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTextureImage3DMultisampleNV")); - TextureImage2DMultisampleNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLint , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTextureImage2DMultisampleNV")); - - TextureImage3DMultisample = &QOpenGLTextureHelper::dsa_TextureImage3DMultisample; - TextureImage2DMultisample = &QOpenGLTextureHelper::dsa_TextureImage2DMultisample; - } else { - TextureImage3DMultisample = &QOpenGLTextureHelper::qt_TextureImage3DMultisample; - TextureImage2DMultisample = &QOpenGLTextureHelper::qt_TextureImage2DMultisample; - } - -#if defined(QT_OPENGL_ES_2) - // Here we are targeting OpenGL ES 2.0+ only. This is likely using EGL, where, - // similarly to WGL, non-extension functions (i.e. any function that is part of the - // GLES spec) *may* not be queried via eglGetProcAddress. - - // OpenGL 1.0 - TexImage1D = 0; - - // OpenGL 1.1 - TexSubImage1D = 0; - - // OpenGL 1.3 - GetCompressedTexImage = 0; - CompressedTexSubImage1D = 0; - CompressedTexSubImage2D = ::glCompressedTexSubImage2D; - CompressedTexImage1D = 0; - CompressedTexImage2D = ::glCompressedTexImage2D; - ActiveTexture = ::glActiveTexture; - - // OpenGL 3.0 - GenerateMipmap = ::glGenerateMipmap; - - // OpenGL 3.2 - TexImage3DMultisample = 0; - TexImage2DMultisample = 0; - - // OpenGL 4.2 - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (ctx->format().majorVersion() >= 3) { - // OpenGL ES 3.0+ has immutable storage for 2D and 3D at least. - QOpenGLExtraFunctionsPrivate *extra = static_cast<QOpenGLExtensions *>(context->extraFunctions())->d(); - TexStorage3D = extra->f.TexStorage3D; - TexStorage2D = extra->f.TexStorage2D; - } else { - TexStorage3D = 0; - TexStorage2D = 0; - } - TexStorage1D = 0; - - // OpenGL 4.3 - TexStorage3DMultisample = 0; - TexStorage2DMultisample = 0; - TexBufferRange = 0; - TextureView = 0; - - // OpenGL ES 3.1+ has TexStorage2DMultisample - if (ctx->format().version() >= qMakePair(3, 1)) { - QOpenGLExtraFunctionsPrivate *extra = static_cast<QOpenGLExtensions *>(context->extraFunctions())->d(); - TexStorage2DMultisample = extra->f.TexStorage2DMultisample; - } - -#endif - - if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_OES_texture_3D"))) { - TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*)>(context->getProcAddress("glTexImage3DOES")); - TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*)>(context->getProcAddress("glTexSubImage3DOES")); - CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*)>(context->getProcAddress("glCompressedTexImage3DOES")); - CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*)>(context->getProcAddress("glCompressedTexSubImage3DOES")); - } else { - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (ctx->isOpenGLES() && ctx->format().majorVersion() >= 3) { - // OpenGL ES 3.0+ has glTexImage3D. - QOpenGLExtraFunctionsPrivate *extra = static_cast<QOpenGLExtensions *>(context->extraFunctions())->d(); - TexImage3D = extra->f.TexImage3D; - TexSubImage3D = extra->f.TexSubImage3D; - CompressedTexImage3D = extra->f.CompressedTexImage3D; - CompressedTexSubImage3D = extra->f.CompressedTexSubImage3D; - } else { - // OpenGL 1.2 - TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTexImage3D")); - TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTexSubImage3D")); - - // OpenGL 1.3 - CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexImage3D")); - CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexSubImage3D")); - } - } - -#ifndef QT_OPENGL_ES_2 - // OpenGL 1.0 and 1.1 - TexImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTexImage1D")); - TexSubImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTexSubImage1D"));\ - - // OpenGL 1.3 - GetCompressedTexImage = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLvoid *)>(context->getProcAddress("glGetCompressedTexImage")); - CompressedTexSubImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexSubImage1D")); - CompressedTexSubImage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexSubImage2D")); - CompressedTexImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexImage1D")); - CompressedTexImage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexImage2D")); - ActiveTexture = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum )>(context->getProcAddress("glActiveTexture")); - - // OpenGL 3.0 - GenerateMipmap = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum )>(context->getProcAddress("glGenerateMipmap")); - - // OpenGL 3.2 - TexImage3DMultisample = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLint , GLsizei , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTexImage3DMultisample")); - TexImage2DMultisample = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLint , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTexImage2DMultisample")); - - // OpenGL 4.2 - TexStorage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLsizei )>(context->getProcAddress("glTexStorage3D")); - TexStorage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei , GLsizei )>(context->getProcAddress("glTexStorage2D")); - TexStorage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei )>(context->getProcAddress("glTexStorage1D")); - - // OpenGL 4.3 - TexStorage3DMultisample = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTexStorage3DMultisample")); - TexStorage2DMultisample = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTexStorage2DMultisample")); - TexBufferRange = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLenum , GLuint , GLintptr , GLsizeiptr )>(context->getProcAddress("glTexBufferRange")); - TextureView = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint , GLenum , GLuint , GLuint , GLuint , GLuint )>(context->getProcAddress("glTextureView")); -#endif -} - -void QOpenGLTextureHelper::dsa_TextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param) -{ - Q_UNUSED(bindingTarget); - TextureParameteriEXT(texture, target, pname, param); -} - -void QOpenGLTextureHelper::dsa_TextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params) -{ - Q_UNUSED(bindingTarget); - TextureParameterivEXT(texture, target, pname, params); -} - -void QOpenGLTextureHelper::dsa_TextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param) -{ - Q_UNUSED(bindingTarget); - TextureParameterfEXT(texture, target, pname, param); -} - -void QOpenGLTextureHelper::dsa_TextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params) -{ - Q_UNUSED(bindingTarget); - TextureParameterfvEXT(texture, target, pname, params); -} - -void QOpenGLTextureHelper::dsa_GenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget) -{ - Q_UNUSED(bindingTarget); - GenerateTextureMipmapEXT(texture, target); -} - -void QOpenGLTextureHelper::dsa_TextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth) -{ - Q_UNUSED(bindingTarget); - TextureStorage3DEXT(texture, target, levels, internalFormat, width, height, depth); -} - -void QOpenGLTextureHelper::dsa_TextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height) -{ - Q_UNUSED(bindingTarget); - TextureStorage2DEXT(texture, target, levels, internalFormat, width, height); -} - -void QOpenGLTextureHelper::dsa_TextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width) -{ - Q_UNUSED(bindingTarget); - TextureStorage1DEXT(texture, target, levels, internalFormat, width); -} - -void QOpenGLTextureHelper::dsa_TextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations) -{ - Q_UNUSED(bindingTarget); - TextureStorage3DMultisampleEXT(texture, target, samples, internalFormat, width, height, depth, fixedSampleLocations); -} - -void QOpenGLTextureHelper::dsa_TextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations) -{ - Q_UNUSED(bindingTarget); - TextureStorage2DMultisampleEXT(texture, target, samples, internalFormat, width, height, fixedSampleLocations); -} - -void QOpenGLTextureHelper::dsa_TextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) -{ - Q_UNUSED(bindingTarget); - TextureImage3DEXT(texture, target, level, internalFormat, width, height, depth, border, format, type, pixels); -} - -void QOpenGLTextureHelper::dsa_TextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) -{ - Q_UNUSED(bindingTarget); - TextureImage2DEXT(texture, target, level, internalFormat, width, height, border, format, type, pixels); -} - -void QOpenGLTextureHelper::dsa_TextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels) -{ - Q_UNUSED(bindingTarget); - TextureImage1DEXT(texture, target, level, internalFormat, width, border, format, type, pixels); -} - -void QOpenGLTextureHelper::dsa_TextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) -{ - Q_UNUSED(bindingTarget); - TextureSubImage3DEXT(texture, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); -} - -void QOpenGLTextureHelper::dsa_TextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) -{ - Q_UNUSED(bindingTarget); - TextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, type, pixels); -} - -void QOpenGLTextureHelper::dsa_TextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels) -{ - Q_UNUSED(bindingTarget); - TextureSubImage1DEXT(texture, target, level, xoffset, width, format, type, pixels); -} - -void QOpenGLTextureHelper::dsa_TextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations) -{ - Q_UNUSED(bindingTarget); - TextureImage3DMultisampleNV(texture, target, samples, internalFormat, width, height, depth, fixedSampleLocations); -} - -void QOpenGLTextureHelper::dsa_TextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations) -{ - Q_UNUSED(bindingTarget); - TextureImage2DMultisampleNV(texture, target, samples, internalFormat, width, height, fixedSampleLocations); -} - -void QOpenGLTextureHelper::dsa_CompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits) -{ - Q_UNUSED(bindingTarget); - CompressedTextureSubImage1DEXT(texture, target, level, xoffset, width, format, imageSize, bits); -} - -void QOpenGLTextureHelper::dsa_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits) -{ - Q_UNUSED(bindingTarget); - CompressedTextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, imageSize, bits); -} - -void QOpenGLTextureHelper::dsa_CompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits) -{ - Q_UNUSED(bindingTarget); - CompressedTextureSubImage3DEXT(texture, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits); -} - -void QOpenGLTextureHelper::dsa_CompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits) -{ - Q_UNUSED(bindingTarget); - CompressedTextureImage1DEXT(texture, target, level, internalFormat, width, border, imageSize, bits); -} - -void QOpenGLTextureHelper::dsa_CompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits) -{ - Q_UNUSED(bindingTarget); - CompressedTextureImage2DEXT(texture, target, level, internalFormat, width, height, border, imageSize, bits); -} - -void QOpenGLTextureHelper::dsa_CompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits) -{ - Q_UNUSED(bindingTarget); - CompressedTextureImage3DEXT(texture, target, level, internalFormat, width, height, depth, border, imageSize, bits); -} - -namespace { - -class TextureBinder -{ -public: - TextureBinder(QOpenGLFunctions *functions, GLuint texture, GLenum target, GLenum bindingTarget) - : m_functions(functions) - { - // For cubemaps we can't use the standard DSA emulation as it is illegal to - // try to bind a texture to one of the cubemap face targets. So we force the - // target and binding target to the cubemap values in this case. - switch (target) { - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - bindingTarget = GL_TEXTURE_BINDING_CUBE_MAP; - m_target = GL_TEXTURE_CUBE_MAP; - break; - - default: - m_target = target; - break; - } - - m_functions->glGetIntegerv(bindingTarget, &m_oldTexture); - m_functions->glBindTexture(m_target, texture); - } - - ~TextureBinder() - { - m_functions->glBindTexture(m_target, m_oldTexture); - } - -private: - QOpenGLFunctions *m_functions; - GLenum m_target; - GLint m_oldTexture; -}; - -} // namespace - -void QOpenGLTextureHelper::qt_TextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - functions->glTexParameteri(target, pname, param); -} - -void QOpenGLTextureHelper::qt_TextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - functions->glTexParameteriv(target, pname, params); -} - -void QOpenGLTextureHelper::qt_TextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - functions->glTexParameterf(target, pname, param); -} - -void QOpenGLTextureHelper::qt_TextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - functions->glTexParameterfv(target, pname, params); -} - -void QOpenGLTextureHelper::qt_GenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - functions->glGenerateMipmap(target); -} - -void QOpenGLTextureHelper::qt_TextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexStorage3D(target, levels, internalFormat, width, height, depth); -} - -void QOpenGLTextureHelper::qt_TextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexStorage2D(target, levels, internalFormat, width, height); -} - -void QOpenGLTextureHelper::qt_TextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexStorage1D(target, levels, internalFormat, width); -} - -void QOpenGLTextureHelper::qt_TextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexStorage3DMultisample(target, samples, internalFormat, width, height, depth, fixedSampleLocations); -} - -void QOpenGLTextureHelper::qt_TextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexStorage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations); -} - -void QOpenGLTextureHelper::qt_TextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels); -} - -void QOpenGLTextureHelper::qt_TextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - functions->glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels); -} - -void QOpenGLTextureHelper::qt_TextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexImage1D(target, level, internalFormat, width, border, format, type, pixels); -} - -void QOpenGLTextureHelper::qt_TextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); -} - -void QOpenGLTextureHelper::qt_TextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - functions->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); -} - -void QOpenGLTextureHelper::qt_TextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexSubImage1D(target, level, xoffset, width, format, type, pixels); -} - -void QOpenGLTextureHelper::qt_TextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexImage3DMultisample(target, samples, internalFormat, width, height, depth, fixedSampleLocations); -} - -void QOpenGLTextureHelper::qt_TextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glTexImage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations); -} - -void QOpenGLTextureHelper::qt_CompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, bits); -} - -void QOpenGLTextureHelper::qt_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, bits); -} - -void QOpenGLTextureHelper::qt_CompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits); -} - -void QOpenGLTextureHelper::qt_CompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glCompressedTexImage1D(target, level, internalFormat, width, border, imageSize, bits); -} - -void QOpenGLTextureHelper::qt_CompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glCompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, bits); -} - -void QOpenGLTextureHelper::qt_CompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits) -{ - TextureBinder binder(functions, texture, target, bindingTarget); - glCompressedTexImage3D(target, level, internalFormat, width, height, depth, border, imageSize, bits); -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengltexturehelper_p.h b/src/gui/opengl/qopengltexturehelper_p.h deleted file mode 100644 index 62d0125daf..0000000000 --- a/src/gui/opengl/qopengltexturehelper_p.h +++ /dev/null @@ -1,797 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QOPENGLTEXTUREHELPER_P_H -#define QOPENGLTEXTUREHELPER_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/private/qtguiglobal_p.h> - -#ifndef QT_NO_OPENGL - -#include "qopengl.h" -#include "qopenglpixeltransferoptions.h" -#include "qopengltexture.h" -#include "qopenglfunctions.h" - -QT_BEGIN_NAMESPACE - -// Constants for OpenGL and OpenGL ES 3.0+ which are not available with OpenGL ES 2.0. -#ifndef GL_TEXTURE_BASE_LEVEL -#define GL_TEXTURE_BASE_LEVEL 0x813C -#endif -#ifndef GL_TEXTURE_MAX_LEVEL -#define GL_TEXTURE_MAX_LEVEL 0x813D -#endif -#ifndef GL_TEXTURE_COMPARE_MODE -#define GL_TEXTURE_COMPARE_MODE 0x884C -#endif -#ifndef GL_TEXTURE_COMPARE_FUNC -#define GL_TEXTURE_COMPARE_FUNC 0x884D -#endif - -// use GL_APICALL only on Android + __clang__ -#if !defined(Q_OS_ANDROID) || !defined(__clang__) -# undef GL_APICALL -# define GL_APICALL -#elif !defined(GL_APICALL) -# define GL_APICALL -#endif - -class QOpenGLContext; - -class QOpenGLTextureHelper -{ -public: - QOpenGLTextureHelper(QOpenGLContext *context); - - // DSA-like API. Will either use real DSA or our emulation - inline void glTextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param) - { - (this->*TextureParameteri)(texture, target, bindingTarget, pname, param); - } - - inline void glTextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params) - { - (this->*TextureParameteriv)(texture, target, bindingTarget, pname, params); - } - - inline void glTextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param) - { - (this->*TextureParameterf)(texture, target, bindingTarget, pname, param); - } - - inline void glTextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params) - { - (this->*TextureParameterfv)(texture, target, bindingTarget, pname, params); - } - - inline void glGenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget) - { - (this->*GenerateTextureMipmap)(texture, target, bindingTarget); - } - - inline void glTextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth) - { - (this->*TextureStorage3D)(texture, target, bindingTarget, levels, internalFormat, width, height, depth); - } - - inline void glTextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, - GLsizei width, GLsizei height) - { - (this->*TextureStorage2D)(texture, target, bindingTarget, levels, internalFormat, width, height); - } - - inline void glTextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, - GLsizei width) - { - (this->*TextureStorage1D)(texture, target, bindingTarget, levels, internalFormat, width); - } - - inline void glTextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations) - { - (this->*TextureStorage3DMultisample)(texture, target, bindingTarget, samples, internalFormat, width, height, depth, fixedSampleLocations); - } - - inline void glTextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, - GLsizei width, GLsizei height, GLboolean fixedSampleLocations) - { - (this->*TextureStorage2DMultisample)(texture, target, bindingTarget, samples, internalFormat, width, height, fixedSampleLocations); - } - - inline void glTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) - { - (this->*TextureImage3D)(texture, target, bindingTarget, level, internalFormat, width, height, depth, border, format, type, pixels); - } - - inline void glTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) - { - (this->*TextureImage2D)(texture, target, bindingTarget, level, internalFormat, width, height, border, format, type, pixels); - } - - inline void glTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels) - { - (this->*TextureImage1D)(texture, target, bindingTarget, level, internalFormat, width, border, format, type, pixels); - } - - inline void glTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = nullptr) - { - if (options) { - QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions(); - setPixelUploadOptions(*options); - (this->*TextureSubImage3D)(texture, target, bindingTarget, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); - setPixelUploadOptions(oldOptions); - } else { - (this->*TextureSubImage3D)(texture, target, bindingTarget, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); - } - } - - inline void glTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, GLenum format, GLenum type, - const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = nullptr) - { - if (options) { - QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions(); - setPixelUploadOptions(*options); - (this->*TextureSubImage2D)(texture, target, bindingTarget, level, xoffset, yoffset, width, height, format, type, pixels); - setPixelUploadOptions(oldOptions); - } else { - (this->*TextureSubImage2D)(texture, target, bindingTarget, level, xoffset, yoffset, width, height, format, type, pixels); - } - } - - inline void glTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, - GLsizei width, GLenum format, GLenum type, - const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = nullptr) - { - if (options) { - QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions(); - setPixelUploadOptions(*options); - (this->*TextureSubImage1D)(texture, target, bindingTarget, level, xoffset, width, format, type, pixels); - setPixelUploadOptions(oldOptions); - } else { - (this->*TextureSubImage1D)(texture, target, bindingTarget, level, xoffset, width, format, type, pixels); - } - } - - inline void glTextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, - GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations) - { - (this->*TextureImage3DMultisample)(texture, target, bindingTarget, samples, internalFormat, width, height, depth, fixedSampleLocations); - } - - inline void glTextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, - GLsizei width, GLsizei height, GLboolean fixedSampleLocations) - { - (this->*TextureImage2DMultisample)(texture, target, bindingTarget, samples, internalFormat, width, height, fixedSampleLocations); - } - - inline void glCompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLsizei width, - GLenum format, GLsizei imageSize, const GLvoid *bits, - const QOpenGLPixelTransferOptions * const options = nullptr) - { - if (options) { - QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions(); - setPixelUploadOptions(*options); - (this->*CompressedTextureSubImage1D)(texture, target, bindingTarget, level, xoffset, width, format, imageSize, bits); - setPixelUploadOptions(oldOptions); - } else { - (this->*CompressedTextureSubImage1D)(texture, target, bindingTarget, level, xoffset, width, format, imageSize, bits); - } - } - - inline void glCompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, const GLvoid *bits, - const QOpenGLPixelTransferOptions * const options = nullptr) - { - if (options) { - QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions(); - setPixelUploadOptions(*options); - (this->*CompressedTextureSubImage2D)(texture, target, bindingTarget, level, xoffset, yoffset, width, height, format, imageSize, bits); - setPixelUploadOptions(oldOptions); - } else { - (this->*CompressedTextureSubImage2D)(texture, target, bindingTarget, level, xoffset, yoffset, width, height, format, imageSize, bits); - } - } - - inline void glCompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const GLvoid *bits, - const QOpenGLPixelTransferOptions * const options = nullptr) - { - if (options) { - QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions(); - setPixelUploadOptions(*options); - (this->*CompressedTextureSubImage3D)(texture, target, bindingTarget, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits); - setPixelUploadOptions(oldOptions); - } else { - (this->*CompressedTextureSubImage3D)(texture, target, bindingTarget, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits); - } - } - - inline void glCompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLenum internalFormat, GLsizei width, - GLint border, GLsizei imageSize, const GLvoid *bits, - const QOpenGLPixelTransferOptions * const options = nullptr) - { - if (options) { - QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions(); - setPixelUploadOptions(*options); - (this->*CompressedTextureImage1D)(texture, target, bindingTarget, level, internalFormat, width, border, imageSize, bits); - setPixelUploadOptions(oldOptions); - } else { - (this->*CompressedTextureImage1D)(texture, target, bindingTarget, level, internalFormat, width, border, imageSize, bits); - } - } - - inline void glCompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLenum internalFormat, GLsizei width, GLsizei height, - GLint border, GLsizei imageSize, const GLvoid *bits, - const QOpenGLPixelTransferOptions * const options = nullptr) - - { - if (options) { - QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions(); - setPixelUploadOptions(*options); - (this->*CompressedTextureImage2D)(texture, target, bindingTarget, level, internalFormat, width, height, border, imageSize, bits); - setPixelUploadOptions(oldOptions); - } else { - (this->*CompressedTextureImage2D)(texture, target, bindingTarget, level, internalFormat, width, height, border, imageSize, bits); - } - } - - inline void glCompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLsizei imageSize, const GLvoid *bits, - const QOpenGLPixelTransferOptions * const options = nullptr) - { - if (options) { - QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions(); - setPixelUploadOptions(*options); - (this->*CompressedTextureImage3D)(texture, target, bindingTarget, level, internalFormat, width, height, depth, border, imageSize, bits); - setPixelUploadOptions(oldOptions); - } else { - (this->*CompressedTextureImage3D)(texture, target, bindingTarget, level, internalFormat, width, height, depth, border, imageSize, bits); - } - } - -private: - // DSA wrapper (so we can use pointer to member function as switch) - void dsa_TextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param); - - void dsa_TextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params); - - void dsa_TextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param); - - void dsa_TextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params); - - void dsa_GenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget); - - void dsa_TextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth); - - void dsa_TextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, - GLsizei width, GLsizei height); - - void dsa_TextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, - GLsizei width); - - void dsa_TextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); - - void dsa_TextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, - GLsizei width, GLsizei height, GLboolean fixedSampleLocations); - - void dsa_TextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - - void dsa_TextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - - void dsa_TextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - - void dsa_TextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); - - void dsa_TextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); - - void dsa_TextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, - GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); - - void dsa_TextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, - GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); - - void dsa_TextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, - GLsizei width, GLsizei height, GLboolean fixedSampleLocations); - - void dsa_CompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLsizei width, - GLenum format, GLsizei imageSize, const GLvoid *bits); - - void dsa_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, const GLvoid *bits); - - void dsa_CompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const GLvoid *bits); - - void dsa_CompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLenum internalFormat, GLsizei width, - GLint border, GLsizei imageSize, const GLvoid *bits); - - void dsa_CompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLenum internalFormat, GLsizei width, GLsizei height, - GLint border, GLsizei imageSize, const GLvoid *bits); - - void dsa_CompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLsizei imageSize, const GLvoid *bits); - - // DSA emulation API - void qt_TextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param); - - void qt_TextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params); - - void qt_TextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param); - - void qt_TextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params); - - void qt_GenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget); - - void qt_TextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth); - - void qt_TextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, - GLenum internalFormat, GLsizei width, GLsizei height); - - void qt_TextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, - GLenum internalFormat, GLsizei width); - - void qt_TextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, - GLenum internalFormat, GLsizei width, GLsizei height, - GLsizei depth, GLboolean fixedSampleLocations); - - void qt_TextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, - GLenum internalFormat, GLsizei width, GLsizei height, - GLboolean fixedSampleLocations); - - void qt_TextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, - const GLvoid *pixels); - - void qt_TextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, - const GLvoid *pixels); - - void qt_TextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLint border, GLenum format, GLenum type, - const GLvoid *pixels); - - void qt_TextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const GLvoid *pixels); - - void qt_TextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid *pixels); - - void qt_TextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLsizei width, - GLenum format, GLenum type, const GLvoid *pixels); - - void qt_TextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, - GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, - GLboolean fixedSampleLocations); - - void qt_TextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, - GLint internalFormat, GLsizei width, GLsizei height, - GLboolean fixedSampleLocations); - - void qt_CompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLsizei width, GLenum format, - GLsizei imageSize, const GLvoid *bits); - - void qt_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, const GLvoid *bits); - - void qt_CompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const GLvoid *bits); - - void qt_CompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLint border, - GLsizei imageSize, const GLvoid *bits); - - void qt_CompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLsizei height, GLint border, - GLsizei imageSize, const GLvoid *bits); - - void qt_CompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth, GLint border, - GLsizei imageSize, const GLvoid *bits); - -public: - // Raw OpenGL functions, resolved and used by our DSA-like static functions if no EXT_direct_state_access is available - - // OpenGL 1.0 - inline void glTexImage1D(GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLint border, - GLenum format, GLenum type, const GLvoid *pixels) - { - TexImage1D(target, level, internalFormat, width, border, format, type, pixels); - } - - // OpenGL 1.1 - inline void glTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, - GLenum format, GLenum type, const GLvoid *pixels) - { - TexSubImage1D(target, level, xoffset, width, format, type, pixels); - } - - // OpenGL 1.2 - inline void glTexImage3D(GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLsizei height, GLsizei depth, GLint border, - GLenum format, GLenum type, const GLvoid *pixels) - { - TexImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels); - } - - inline void glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) - { - TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); - } - - // OpenGL 1.3 - inline void glGetCompressedTexImage(GLenum target, GLint level, GLvoid *img) - { - GetCompressedTexImage(target, level, img); - } - - inline void glCompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, - GLenum format, GLsizei imageSize, const GLvoid *data) - { - CompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data); - } - - inline void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) - { - CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); - } - - inline void glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) - { - CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); - } - - inline void glCompressedTexImage1D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, - GLint border, GLsizei imageSize, const GLvoid *data) - { - CompressedTexImage1D(target, level, internalFormat, width, border, imageSize, data); - } - - inline void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, - GLint border, GLsizei imageSize, const GLvoid *data) - { - CompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, data); - } - - inline void glCompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLsizei imageSize, const GLvoid *data) - { - CompressedTexImage3D(target, level, internalFormat, width, height, depth, border, imageSize, data); - } - - inline void glActiveTexture(GLenum texture) - { - ActiveTexture(texture); - } - - // OpenGL 3.0 - inline void glGenerateMipmap(GLenum target) - { - GenerateMipmap(target); - } - - // OpenGL 3.2 - inline void glTexImage3DMultisample(GLenum target, GLsizei samples, GLint internalFormat, - GLsizei width, GLsizei height, GLsizei depth, - GLboolean fixedSampleLocations) - { - TexImage3DMultisample(target, samples, internalFormat, width, height, depth, fixedSampleLocations); - } - - inline void glTexImage2DMultisample(GLenum target, GLsizei samples, GLint internalFormat, - GLsizei width, GLsizei height, - GLboolean fixedSampleLocations) - { - TexImage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations); - } - - // OpenGL 4.2 - inline void glTexStorage3D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth) - { - TexStorage3D(target, levels, internalFormat, width, height, depth); - } - - inline void glTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height) - { - TexStorage2D(target, levels, internalFormat, width, height); - } - - inline void glTexStorage1D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width) - { - TexStorage1D(target, levels, internalFormat, width); - } - - // OpenGL 4.3 - inline void glTexStorage3DMultisample(GLenum target, GLsizei samples, GLenum internalFormat, - GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations) - { - TexStorage3DMultisample(target, samples, internalFormat, width, height, depth, fixedSampleLocations); - } - - inline void glTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalFormat, - GLsizei width, GLsizei height, GLboolean fixedSampleLocations) - { - TexStorage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations); - } - - inline void glTexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer, - GLintptr offset, GLsizeiptr size) - { - TexBufferRange(target, internalFormat, buffer, offset, size); - } - - inline void glTextureView(GLuint texture, GLenum target, GLuint origTexture, GLenum internalFormat, - GLuint minLevel, GLuint numLevels, GLuint minLayer, GLuint numLayers) - { - TextureView(texture, target, origTexture, internalFormat, minLevel, numLevels, minLayer, numLayers); - } - - // Helper functions - inline QOpenGLPixelTransferOptions savePixelUploadOptions() - { - QOpenGLPixelTransferOptions options; - int val = 0; - functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &val); - options.setAlignment(val); -#if !defined(QT_OPENGL_ES_2) - functions->glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &val); - options.setSkipImages(val); - functions->glGetIntegerv(GL_UNPACK_SKIP_ROWS, &val); - options.setSkipRows(val); - functions->glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &val); - options.setSkipPixels(val); - functions->glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &val); - options.setImageHeight(val); - functions->glGetIntegerv(GL_UNPACK_ROW_LENGTH, &val); - options.setRowLength(val); - GLboolean b = GL_FALSE; - functions->glGetBooleanv(GL_UNPACK_LSB_FIRST, &b); - options.setLeastSignificantByteFirst(b); - functions->glGetBooleanv(GL_UNPACK_SWAP_BYTES, &b); - options.setSwapBytesEnabled(b); -#endif - return options; - } - - inline void setPixelUploadOptions(const QOpenGLPixelTransferOptions &options) - { - functions->glPixelStorei(GL_UNPACK_ALIGNMENT, options.alignment()); -#if !defined(QT_OPENGL_ES_2) - functions->glPixelStorei(GL_UNPACK_SKIP_IMAGES, options.skipImages()); - functions->glPixelStorei(GL_UNPACK_SKIP_ROWS, options.skipRows()); - functions->glPixelStorei(GL_UNPACK_SKIP_PIXELS, options.skipPixels()); - functions->glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, options.imageHeight()); - functions->glPixelStorei(GL_UNPACK_ROW_LENGTH, options.rowLength()); - functions->glPixelStorei(GL_UNPACK_LSB_FIRST, options.isLeastSignificantBitFirst()); - functions->glPixelStorei(GL_UNPACK_SWAP_BYTES, options.isSwapBytesEnabled()); -#endif - } - - QOpenGLFunctions *functions; -private: - // Typedefs and pointers to member functions used to switch between EXT_direct_state_access and our own emulated DSA. - // The argument match the corresponding GL function, but there's an extra "GLenum bindingTarget" which gets used with - // the DSA emulation -- it contains the right GL_BINDING_TEXTURE_X to use. - typedef void (QOpenGLTextureHelper::*TextureParameteriMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param); - typedef void (QOpenGLTextureHelper::*TextureParameterivMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params); - typedef void (QOpenGLTextureHelper::*TextureParameterfMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param); - typedef void (QOpenGLTextureHelper::*TextureParameterfvMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params); - typedef void (QOpenGLTextureHelper::*GenerateTextureMipmapMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget); - typedef void (QOpenGLTextureHelper::*TextureStorage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth); - typedef void (QOpenGLTextureHelper::*TextureStorage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height); - typedef void (QOpenGLTextureHelper::*TextureStorage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width); - typedef void (QOpenGLTextureHelper::*TextureStorage3DMultisampleMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); - typedef void (QOpenGLTextureHelper::*TextureStorage2DMultisampleMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); - typedef void (QOpenGLTextureHelper::*TextureImage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - typedef void (QOpenGLTextureHelper::*TextureImage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - typedef void (QOpenGLTextureHelper::*TextureImage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - typedef void (QOpenGLTextureHelper::*TextureSubImage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); - typedef void (QOpenGLTextureHelper::*TextureSubImage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); - typedef void (QOpenGLTextureHelper::*TextureSubImage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); - typedef void (QOpenGLTextureHelper::*TextureImage3DMultisampleMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); - typedef void (QOpenGLTextureHelper::*TextureImage2DMultisampleMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); - typedef void (QOpenGLTextureHelper::*CompressedTextureSubImage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits); - typedef void (QOpenGLTextureHelper::*CompressedTextureSubImage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits); - typedef void (QOpenGLTextureHelper::*CompressedTextureSubImage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits); - typedef void (QOpenGLTextureHelper::*CompressedTextureImage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits); - typedef void (QOpenGLTextureHelper::*CompressedTextureImage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits); - typedef void (QOpenGLTextureHelper::*CompressedTextureImage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits); - - - TextureParameteriMemberFunc TextureParameteri; - TextureParameterivMemberFunc TextureParameteriv; - TextureParameterfMemberFunc TextureParameterf; - TextureParameterfvMemberFunc TextureParameterfv; - GenerateTextureMipmapMemberFunc GenerateTextureMipmap; - TextureStorage3DMemberFunc TextureStorage3D; - TextureStorage2DMemberFunc TextureStorage2D; - TextureStorage1DMemberFunc TextureStorage1D; - TextureStorage3DMultisampleMemberFunc TextureStorage3DMultisample; - TextureStorage2DMultisampleMemberFunc TextureStorage2DMultisample; - TextureImage3DMemberFunc TextureImage3D; - TextureImage2DMemberFunc TextureImage2D; - TextureImage1DMemberFunc TextureImage1D; - TextureSubImage3DMemberFunc TextureSubImage3D; - TextureSubImage2DMemberFunc TextureSubImage2D; - TextureSubImage1DMemberFunc TextureSubImage1D; - TextureImage3DMultisampleMemberFunc TextureImage3DMultisample; - TextureImage2DMultisampleMemberFunc TextureImage2DMultisample; - CompressedTextureSubImage1DMemberFunc CompressedTextureSubImage1D; - CompressedTextureSubImage2DMemberFunc CompressedTextureSubImage2D; - CompressedTextureSubImage3DMemberFunc CompressedTextureSubImage3D; - CompressedTextureImage1DMemberFunc CompressedTextureImage1D; - CompressedTextureImage2DMemberFunc CompressedTextureImage2D; - CompressedTextureImage3DMemberFunc CompressedTextureImage3D; - - // Raw function pointers for core and DSA functions - - // EXT_direct_state_access used when DSA is available - void (QOPENGLF_APIENTRYP TextureParameteriEXT)(GLuint texture, GLenum target, GLenum pname, GLint param); - void (QOPENGLF_APIENTRYP TextureParameterivEXT)(GLuint texture, GLenum target, GLenum pname, const GLint *params); - void (QOPENGLF_APIENTRYP TextureParameterfEXT)(GLuint texture, GLenum target, GLenum pname, GLfloat param); - void (QOPENGLF_APIENTRYP TextureParameterfvEXT)(GLuint texture, GLenum target, GLenum pname, const GLfloat *params); - void (QOPENGLF_APIENTRYP GenerateTextureMipmapEXT)(GLuint texture, GLenum target); - void (QOPENGLF_APIENTRYP TextureStorage3DEXT)(GLuint texture, GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth); - void (QOPENGLF_APIENTRYP TextureStorage2DEXT)(GLuint texture, GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height); - void (QOPENGLF_APIENTRYP TextureStorage1DEXT)(GLuint texture, GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width); - void (QOPENGLF_APIENTRYP TextureStorage3DMultisampleEXT)(GLuint texture, GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); - void (QOPENGLF_APIENTRYP TextureStorage2DMultisampleEXT)(GLuint texture, GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); - void (QOPENGLF_APIENTRYP TextureImage3DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - void (QOPENGLF_APIENTRYP TextureImage2DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - void (QOPENGLF_APIENTRYP TextureImage1DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - void (QOPENGLF_APIENTRYP TextureSubImage3DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); - void (QOPENGLF_APIENTRYP TextureSubImage2DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); - void (QOPENGLF_APIENTRYP TextureSubImage1DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); - void (QOPENGLF_APIENTRYP CompressedTextureSubImage1DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits); - void (QOPENGLF_APIENTRYP CompressedTextureSubImage2DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits); - void (QOPENGLF_APIENTRYP CompressedTextureSubImage3DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits); - void (QOPENGLF_APIENTRYP CompressedTextureImage1DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits); - void (QOPENGLF_APIENTRYP CompressedTextureImage2DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits); - void (QOPENGLF_APIENTRYP CompressedTextureImage3DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits); - - - // Plus some missing ones that are in the NV_texture_multisample extension instead - void (QOPENGLF_APIENTRYP TextureImage3DMultisampleNV)(GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); - void (QOPENGLF_APIENTRYP TextureImage2DMultisampleNV)(GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); - - // OpenGL 1.0 - void (QOPENGLF_APIENTRYP TexImage1D)(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - - // OpenGL 1.1 - void (QOPENGLF_APIENTRYP TexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); - - // OpenGL 1.2 - void (QOPENGLF_APIENTRYP TexImage3D)(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); - void (QOPENGLF_APIENTRYP TexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); - - // OpenGL 1.3 - void (QOPENGLF_APIENTRYP GetCompressedTexImage)(GLenum target, GLint level, GLvoid *img); - void (QOPENGLF_APIENTRYP CompressedTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); - GL_APICALL void (QOPENGLF_APIENTRYP CompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); - void (QOPENGLF_APIENTRYP CompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); - void (QOPENGLF_APIENTRYP CompressedTexImage1D)(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); - GL_APICALL void (QOPENGLF_APIENTRYP CompressedTexImage2D)(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); - void (QOPENGLF_APIENTRYP CompressedTexImage3D)(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); - GL_APICALL void (QOPENGLF_APIENTRYP ActiveTexture)(GLenum texture); - - // OpenGL 3.0 - GL_APICALL void (QOPENGLF_APIENTRYP GenerateMipmap)(GLenum target); - - // OpenGL 3.2 - void (QOPENGLF_APIENTRYP TexImage3DMultisample)(GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); - void (QOPENGLF_APIENTRYP TexImage2DMultisample)(GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); - - // OpenGL 4.2 - void (QOPENGLF_APIENTRYP TexStorage3D)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth); - void (QOPENGLF_APIENTRYP TexStorage2D)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height); - void (QOPENGLF_APIENTRYP TexStorage1D)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width); - - // OpenGL 4.3 - void (QOPENGLF_APIENTRYP TexStorage3DMultisample)(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations); - void (QOPENGLF_APIENTRYP TexStorage2DMultisample)(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); - void (QOPENGLF_APIENTRYP TexBufferRange)(GLenum target, GLenum internalFormat, GLuint buffer, GLintptr offset, GLsizeiptr size); - void (QOPENGLF_APIENTRYP TextureView)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); -}; - -QT_END_NAMESPACE - -#undef Q_CALL_MEMBER_FUNCTION - -#endif // QT_NO_OPENGL - -#endif // QOPENGLTEXTUREHELPER_P_H diff --git a/src/gui/opengl/qopengltextureuploader.cpp b/src/gui/opengl/qopengltextureuploader.cpp deleted file mode 100644 index 9e393bc47a..0000000000 --- a/src/gui/opengl/qopengltextureuploader.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopengltextureuploader_p.h" - -#include <qimage.h> -#include <qmath.h> -#include <qopenglfunctions.h> -#include <private/qopenglcontext_p.h> -#include <private/qopenglextensions_p.h> - -#ifndef GL_RED -#define GL_RED 0x1903 -#endif - -#ifndef GL_GREEN -#define GL_GREEN 0x1904 -#endif - -#ifndef GL_BLUE -#define GL_BLUE 0x1905 -#endif - -#ifndef GL_RGB10_A2 -#define GL_RGB10_A2 0x8059 -#endif - -#ifndef GL_RGBA16 -#define GL_RGBA16 0x805B -#endif - -#ifndef GL_BGR -#define GL_BGR 0x80E0 -#endif - -#ifndef GL_BGRA -#define GL_BGRA 0x80E1 -#endif - -#ifndef GL_UNSIGNED_INT_8_8_8_8_REV -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#endif - -#ifndef GL_UNSIGNED_INT_2_10_10_10_REV -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#endif - -#ifndef GL_TEXTURE_SWIZZLE_R -#define GL_TEXTURE_SWIZZLE_R 0x8E42 -#endif - -#ifndef GL_TEXTURE_SWIZZLE_G -#define GL_TEXTURE_SWIZZLE_G 0x8E43 -#endif - -#ifndef GL_TEXTURE_SWIZZLE_B -#define GL_TEXTURE_SWIZZLE_B 0x8E44 -#endif - -#ifndef GL_TEXTURE_SWIZZLE_A -#define GL_TEXTURE_SWIZZLE_A 0x8E45 -#endif - -#ifndef GL_SRGB -#define GL_SRGB 0x8C40 -#endif -#ifndef GL_SRGB_ALPHA -#define GL_SRGB_ALPHA 0x8C42 -#endif - -QT_BEGIN_NAMESPACE - -qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &image, QOpenGLTextureUploader::BindOptions options, QSize maxSize) -{ - QOpenGLContext *context = QOpenGLContext::currentContext(); - QOpenGLExtensions *funcs = static_cast<QOpenGLExtensions*>(context->functions()); - - QImage tx; - GLenum externalFormat; - GLenum internalFormat; - GLuint pixelType; - QImage::Format targetFormat = QImage::Format_Invalid; - const bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2); - const bool isOpenGLES3orBetter = context->isOpenGLES() && context->format().majorVersion() >= 3; - const bool sRgbBinding = (options & SRgbBindOption); - Q_ASSERT(isOpenGL12orBetter || context->isOpenGLES()); - Q_ASSERT((options & (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption)) != (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption)); - - switch (image.format()) { - case QImage::Format_RGB32: - case QImage::Format_ARGB32: - case QImage::Format_ARGB32_Premultiplied: - if (isOpenGL12orBetter) { - externalFormat = GL_BGRA; - internalFormat = GL_RGBA; - pixelType = GL_UNSIGNED_INT_8_8_8_8_REV; -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - // Without GL_UNSIGNED_INT_8_8_8_8_REV, BGRA only matches ARGB on little endian: - } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat) && !sRgbBinding) { - // The GL_EXT_texture_format_BGRA8888 extension requires the internal format to match the external. - externalFormat = internalFormat = GL_BGRA; - pixelType = GL_UNSIGNED_BYTE; - } else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) { - // Is only allowed as an external format like OpenGL. - externalFormat = GL_BGRA; - internalFormat = GL_RGBA; - pixelType = GL_UNSIGNED_BYTE; -#endif - } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) { -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_BLUE); - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_RED); -#else - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_GREEN); - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, GL_BLUE); - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_ALPHA); - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, GL_RED); -#endif - externalFormat = internalFormat = GL_RGBA; - pixelType = GL_UNSIGNED_BYTE; - } else { - // No support for direct ARGB32 upload. - break; - } - targetFormat = image.format(); - break; - case QImage::Format_BGR30: - case QImage::Format_A2BGR30_Premultiplied: - if (sRgbBinding) { - // Always needs conversion - break; - } else if (isOpenGL12orBetter || isOpenGLES3orBetter) { - pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; - externalFormat = GL_RGBA; - internalFormat = GL_RGB10_A2; - targetFormat = image.format(); - } - break; - case QImage::Format_RGB30: - case QImage::Format_A2RGB30_Premultiplied: - if (sRgbBinding) { - // Always needs conversion - break; - } else if (isOpenGL12orBetter) { - pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; - externalFormat = GL_BGRA; - internalFormat = GL_RGB10_A2; - targetFormat = image.format(); - } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) { - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_RED); - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_BLUE); - pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; - externalFormat = GL_RGBA; - internalFormat = GL_RGB10_A2; - targetFormat = image.format(); - } - break; - case QImage::Format_RGB444: - case QImage::Format_RGB555: - case QImage::Format_RGB16: - if (isOpenGL12orBetter || context->isOpenGLES()) { - externalFormat = internalFormat = GL_RGB; - pixelType = GL_UNSIGNED_SHORT_5_6_5; - targetFormat = QImage::Format_RGB16; - } - break; - case QImage::Format_RGB666: - case QImage::Format_RGB888: - externalFormat = internalFormat = GL_RGB; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = QImage::Format_RGB888; - break; - case QImage::Format_BGR888: - if (isOpenGL12orBetter) { - externalFormat = GL_BGR; - internalFormat = GL_RGB; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = QImage::Format_BGR888; - } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) { - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_RED); - funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_BLUE); - externalFormat = internalFormat = GL_RGB; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = QImage::Format_BGR888; - } - break; - case QImage::Format_RGBX8888: - case QImage::Format_RGBA8888: - case QImage::Format_RGBA8888_Premultiplied: - externalFormat = internalFormat = GL_RGBA; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = image.format(); - break; - case QImage::Format_RGBX64: - case QImage::Format_RGBA64: - case QImage::Format_RGBA64_Premultiplied: - externalFormat = internalFormat = GL_RGBA; - if (isOpenGL12orBetter || (context->isOpenGLES() && context->format().majorVersion() >= 3)) - internalFormat = GL_RGBA16; - pixelType = GL_UNSIGNED_SHORT; - targetFormat = image.format(); - break; - case QImage::Format_Indexed8: - if (sRgbBinding) { - // Always needs conversion - break; - } else if (options & UseRedForAlphaAndLuminanceBindOption) { - externalFormat = internalFormat = GL_RED; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = image.format(); - } - break; - case QImage::Format_Alpha8: - if (sRgbBinding) { - // Always needs conversion - break; - } else if (options & UseRedForAlphaAndLuminanceBindOption) { - externalFormat = internalFormat = GL_RED; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = image.format(); - } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) { - externalFormat = internalFormat = GL_ALPHA; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = image.format(); - } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) { - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ALPHA); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ZERO); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ZERO); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ZERO); - externalFormat = internalFormat = GL_RED; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = image.format(); - } - break; - case QImage::Format_Grayscale8: - if (sRgbBinding) { - // Always needs conversion - break; - } else if (options & UseRedForAlphaAndLuminanceBindOption) { - externalFormat = internalFormat = GL_RED; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = image.format(); - } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) { - externalFormat = internalFormat = GL_LUMINANCE; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = image.format(); - } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) { - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE); - externalFormat = internalFormat = GL_RED; - pixelType = GL_UNSIGNED_BYTE; - targetFormat = image.format(); - } - break; - case QImage::Format_Grayscale16: - if (sRgbBinding) { - // Always needs conversion - break; - } else if (options & UseRedForAlphaAndLuminanceBindOption) { - externalFormat = internalFormat = GL_RED; - pixelType = GL_UNSIGNED_SHORT; - targetFormat = image.format(); - } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) { - externalFormat = internalFormat = GL_LUMINANCE; - pixelType = GL_UNSIGNED_SHORT; - targetFormat = image.format(); - } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) { - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE); - externalFormat = internalFormat = GL_RED; - pixelType = GL_UNSIGNED_SHORT; - targetFormat = image.format(); - } - break; - default: - break; - } - - // If no direct upload was detected above, convert to RGBA8888 and upload that - if (targetFormat == QImage::Format_Invalid) { - externalFormat = internalFormat = GL_RGBA; - pixelType = GL_UNSIGNED_BYTE; - if (!image.hasAlphaChannel()) - targetFormat = QImage::Format_RGBX8888; - else - targetFormat = QImage::Format_RGBA8888; - } - - if (options & PremultipliedAlphaBindOption) { - if (targetFormat == QImage::Format_ARGB32) - targetFormat = QImage::Format_ARGB32_Premultiplied; - else if (targetFormat == QImage::Format_RGBA8888) - targetFormat = QImage::Format_RGBA8888_Premultiplied; - else if (targetFormat == QImage::Format_RGBA64) - targetFormat = QImage::Format_RGBA64_Premultiplied; - } else { - if (targetFormat == QImage::Format_ARGB32_Premultiplied) - targetFormat = QImage::Format_ARGB32; - else if (targetFormat == QImage::Format_RGBA8888_Premultiplied) - targetFormat = QImage::Format_RGBA8888; - else if (targetFormat == QImage::Format_RGBA64_Premultiplied) - targetFormat = QImage::Format_RGBA64; - } - - if (sRgbBinding) { - Q_ASSERT(internalFormat == GL_RGBA || internalFormat == GL_RGB); - if (image.hasAlphaChannel()) - internalFormat = GL_SRGB_ALPHA; - else - internalFormat = GL_SRGB; - } - - if (image.format() != targetFormat) - tx = image.convertToFormat(targetFormat); - else - tx = image; - - QSize newSize = tx.size(); - if (!maxSize.isEmpty()) - newSize = newSize.boundedTo(maxSize); - if (options & PowerOfTwoBindOption) { - newSize.setWidth(qNextPowerOfTwo(newSize.width() - 1)); - newSize.setHeight(qNextPowerOfTwo(newSize.height() - 1)); - } - - if (newSize != tx.size()) - tx = tx.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - - // Handle cases where the QImage is actually a sub image of its image data: - qsizetype naturalBpl = ((qsizetype(tx.width()) * tx.depth() + 31) >> 5) << 2; - if (tx.bytesPerLine() != naturalBpl) - tx = tx.copy(tx.rect()); - - funcs->glTexImage2D(target, 0, internalFormat, tx.width(), tx.height(), 0, externalFormat, pixelType, tx.constBits()); - - qsizetype cost = qint64(tx.width()) * tx.height() * tx.depth() / 8; - - return cost; -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengltextureuploader_p.h b/src/gui/opengl/qopengltextureuploader_p.h deleted file mode 100644 index 0dcf709d7e..0000000000 --- a/src/gui/opengl/qopengltextureuploader_p.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $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 QOPENGLTEXTUREUPLOADER_P_H -#define QOPENGLTEXTUREUPLOADER_P_H - -#include <QtCore/qsize.h> -#include <QtGui/private/qtguiglobal_p.h> -#include <QtGui/private/qopenglcontext_p.h> - -QT_BEGIN_NAMESPACE - -class QImage; - -class Q_GUI_EXPORT QOpenGLTextureUploader -{ -public: - enum BindOption { - NoBindOption = 0x0000, - PremultipliedAlphaBindOption = 0x0001, - UseRedForAlphaAndLuminanceBindOption = 0x0002, - SRgbBindOption = 0x0004, - PowerOfTwoBindOption = 0x0008 - }; - Q_DECLARE_FLAGS(BindOptions, BindOption) - Q_FLAGS(BindOptions) - - static qsizetype textureImage(GLenum target, const QImage &image, BindOptions options, QSize maxSize = QSize()); - -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLTextureUploader::BindOptions) - -QT_END_NAMESPACE - -#endif - diff --git a/src/gui/opengl/qopengltimerquery.cpp b/src/gui/opengl/qopengltimerquery.cpp deleted file mode 100644 index a4e10b42f7..0000000000 --- a/src/gui/opengl/qopengltimerquery.cpp +++ /dev/null @@ -1,880 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qopengltimerquery.h" - -#include "qopenglqueryhelper_p.h" -#include <QtCore/private/qobject_p.h> -#include <QtGui/QOpenGLContext> -#include <QtGui/QOpenGLFunctions> - -QT_BEGIN_NAMESPACE - -// Helper class used as fallback if OpenGL <3.3 is being used with EXT_timer_query -class QExtTimerQueryHelper -{ -public: - QExtTimerQueryHelper(QOpenGLContext *context) - { - Q_ASSERT(context); - GetQueryObjectui64vEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint64EXT *)>(context->getProcAddress("glGetQueryObjectui64vEXT")); - GetQueryObjecti64vEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint64EXT *)>(context->getProcAddress("glGetQueryObjecti64vEXT")); - } - - inline void glGetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params) - { - GetQueryObjectui64vEXT(id, pname, params); - } - - inline void glGetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params) - { - GetQueryObjecti64vEXT(id, pname, params); - } - -private: - void (QOPENGLF_APIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT *params); - void (QOPENGLF_APIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT *params); -}; - -class QOpenGLTimerQueryPrivate : public QObjectPrivate -{ -public: - QOpenGLTimerQueryPrivate() - : QObjectPrivate(), - context(nullptr), - ext(nullptr), - timeInterval(0), - timer(0) - { - } - - ~QOpenGLTimerQueryPrivate() - { - delete core; - delete ext; - } - - bool create(); - void destroy(); - void begin(); - void end(); - GLuint64 waitForTimeStamp() const; - void recordTimestamp(); - bool isResultAvailable() const; - GLuint64 result() const; - - // There are several cases we must handle: - // OpenGL >=3.3 includes timer queries as a core feature - // ARB_timer_query has same functionality as above. Requires OpenGL 3.2 - // EXT_timer_query offers limited support. Can be used with OpenGL >=1.5 - // - // Note that some implementations (OS X) provide OpenGL 3.2 but do not expose the - // ARB_timer_query extension. In such situations we must also be able to handle - // using the EXT_timer_query extension with any version of OpenGL. - // - // OpenGL 1.5 or above contains the generic query API and OpenGL 3.3 and - // ARB_timer_query provide the 64-bit query API. These are wrapped by - // QOpenGLQueryHelper. All we need to handle in addition is the EXT_timer_query - // case and to take care not to call the Core/ARB functions when we only - // have EXT_timer_query available. - QOpenGLContext *context; - QOpenGLQueryHelper *core; - QExtTimerQueryHelper *ext; - mutable GLuint64 timeInterval; - GLuint timer; -}; - -bool QOpenGLTimerQueryPrivate::create() -{ - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - - if (timer && context == ctx) - return true; - - context = ctx; - if (!context) { - qWarning("A current OpenGL context is required to create timer query objects"); - return false; - } - - if (context->isOpenGLES()) { - qWarning("QOpenGLTimerQuery: Not supported on OpenGL ES"); - return false; - } - - // Resolve the functions provided by OpenGL 1.5 and OpenGL 3.3 or ARB_timer_query - core = new QOpenGLQueryHelper(context); - - // Check to see if we also need to resolve the functions for EXT_timer_query - QSurfaceFormat f = context->format(); - if (f.version() <= qMakePair<int, int>(3, 2) - && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query")) - && context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) { - ext = new QExtTimerQueryHelper(context); - } else if (f.version() <= qMakePair<int, int>(3, 2) - && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query")) - && !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) { - qWarning("QOpenGLTimerQuery requires one of:\n" - " OpenGL 3.3 or newer,\n" - " OpenGL 3.2 and the ARB_timer_query extension\n" - " or the EXT_timer query extension"); - return false; - } - - core->glGenQueries(1, &timer); - return (timer != 0); -} - -void QOpenGLTimerQueryPrivate::destroy() -{ - if (!timer) - return; - - core->glDeleteQueries(1, &timer); - timer = 0; - context = nullptr; -} - -// GL_TIME_ELAPSED_EXT is not defined on OS X 10.6 -#if !defined(GL_TIME_ELAPSED_EXT) -#define GL_TIME_ELAPSED_EXT 0x88BF -#endif - -// GL_TIME_ELAPSED is not defined on OS X 10.7 or 10.8 yet -#if !defined(GL_TIME_ELAPSED) -#define GL_TIME_ELAPSED GL_TIME_ELAPSED_EXT -#endif - -void QOpenGLTimerQueryPrivate::begin() -{ - core->glBeginQuery(GL_TIME_ELAPSED, timer); -} - -void QOpenGLTimerQueryPrivate::end() -{ - core->glEndQuery(GL_TIME_ELAPSED); -} - -void QOpenGLTimerQueryPrivate::recordTimestamp() -{ - // Don't call glQueryCounter if we only have EXT_timer_query -#if defined(GL_TIMESTAMP) - if (!ext) - core->glQueryCounter(timer, GL_TIMESTAMP); - else - qWarning("QOpenGLTimerQuery::recordTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query"); -#else - qWarning("QOpenGLTimerQuery::recordTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query"); -#endif -} - -GLuint64 QOpenGLTimerQueryPrivate::waitForTimeStamp() const -{ - GLint64 tmp = 0; -#if defined(GL_TIMESTAMP) - if (!ext) - core->glGetInteger64v(GL_TIMESTAMP, &tmp); - else - qWarning("QOpenGLTimerQuery::waitForTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query"); -#else - qWarning("QOpenGLTimerQuery::waitForTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query"); -#endif - GLuint64 timestamp(tmp); - return timestamp; -} - -bool QOpenGLTimerQueryPrivate::isResultAvailable() const -{ - GLuint available = GL_FALSE; - core->glGetQueryObjectuiv(timer, GL_QUERY_RESULT_AVAILABLE, &available); - return available; -} - -GLuint64 QOpenGLTimerQueryPrivate::result() const -{ - if (!ext) - core->glGetQueryObjectui64v(timer, GL_QUERY_RESULT, &timeInterval); - else - ext->glGetQueryObjectui64vEXT(timer, GL_QUERY_RESULT, &timeInterval); - return timeInterval; -} - -/*! - \class QOpenGLTimerQuery - \brief The QOpenGLTimerQuery class wraps an OpenGL timer query object. - \inmodule QtGui - \since 5.1 - \ingroup painting-3D - - OpenGL timer query objects are OpenGL managed resources to measure the - execution times of sequences of OpenGL commands on the GPU. - - OpenGL offers various levels of support for timer queries, depending on - the version of OpenGL you have and the presence of the ARB_timer_query or - EXT_timer_query extensions. The support can be summarized as: - - \list - \li OpenGL >=3.3 offers full support for all timer query functionality. - \li OpenGL 3.2 with the ARB_timer_query extension offers full support - for all timer query functionality. - \li OpenGL <=3.2 with the EXT_timer_query extension offers limited support - in that the timestamp of the GPU cannot be queried. Places where this - impacts functions provided by Qt classes will be highlighted in the - function documentation. - \li OpenGL ES 2 (and OpenGL ES 3) do not provide any support for OpenGL - timer queries. - \endlist - - OpenGL represents time with a granularity of 1 nanosecond (1e-9 seconds). As a - consequence of this, 32-bit integers would only give a total possible duration - of approximately 4 seconds, which would not be difficult to exceed in poorly - performing or lengthy operations. OpenGL therefore uses 64 bit integer types - to represent times. A GLuint64 variable has enough width to contain a duration - of hundreds of years, which is plenty for real-time rendering needs. - - As with the other Qt OpenGL classes, QOpenGLTimerQuery has a create() - function to create the underlying OpenGL object. This is to allow the developer to - ensure that there is a valid current OpenGL context at the time. - - Once created, timer queries can be issued in one of several ways. The simplest - method is to delimit a block of commands with calls to begin() and end(). This - instructs OpenGL to measure the time taken from completing all commands issued - prior to begin() until the completion of all commands issued prior to end(). - - At the end of a frame we can retrieve the results by calling waitForResult(). - As this function's name implies, it blocks CPU execution until OpenGL notifies - that the timer query result is available. To avoid blocking, you can check - if the query result is available by calling isResultAvailable(). Note that - modern GPUs are deeply pipelined and query results may not become available for - between 1-5 frames after they were issued. - - Note that OpenGL does not permit nesting or interleaving of multiple timer queries - using begin() and end(). Using multiple timer queries and recordTimestamp() avoids - this limitation. When using recordTimestamp() the result can be obtained at - some later time using isResultAvailable() and waitForResult(). Qt provides the - convenience class QOpenGLTimeMonitor that helps with using multiple query objects. - - \sa QOpenGLTimeMonitor -*/ - -/*! - Creates a QOpenGLTimerQuery instance with the given \a parent. You must call create() - with a valid OpenGL context before using. -*/ -QOpenGLTimerQuery::QOpenGLTimerQuery(QObject *parent) - : QObject(*new QOpenGLTimerQueryPrivate, parent) -{ -} - -/*! - Destroys the QOpenGLTimerQuery and the underlying OpenGL resource. -*/ -QOpenGLTimerQuery::~QOpenGLTimerQuery() -{ - QOpenGLContext* ctx = QOpenGLContext::currentContext(); - - Q_D(QOpenGLTimerQuery); - QOpenGLContext *oldContext = nullptr; - if (d->context != ctx) { - oldContext = ctx; - if (d->context->makeCurrent(oldContext->surface())) { - ctx = d->context; - } else { - qWarning("QOpenGLTimerQuery::~QOpenGLTimerQuery() failed to make query objects's context current"); - ctx = nullptr; - } - } - - if (ctx) - destroy(); - - if (oldContext) { - if (!oldContext->makeCurrent(oldContext->surface())) - qWarning("QOpenGLTimerQuery::~QOpenGLTimerQuery() failed to restore current context"); - } -} - -/*! - Creates the underlying OpenGL timer query object. There must be a valid OpenGL context - that supports query objects current for this function to succeed. - - Returns \c true if the OpenGL timer query object was successfully created. -*/ -bool QOpenGLTimerQuery::create() -{ - Q_D(QOpenGLTimerQuery); - return d->create(); -} - -/*! - Destroys the underlying OpenGL timer query object. The context that was current when - create() was called must be current when calling this function. -*/ -void QOpenGLTimerQuery::destroy() -{ - Q_D(QOpenGLTimerQuery); - d->destroy(); -} - -/*! - Returns \c true if the underlying OpenGL query object has been created. If this - returns \c true and the associated OpenGL context is current, then you are able to issue - queries with this object. -*/ -bool QOpenGLTimerQuery::isCreated() const -{ - Q_D(const QOpenGLTimerQuery); - return (d->timer != 0); -} - -/*! - Returns the id of the underlying OpenGL query object. -*/ -GLuint QOpenGLTimerQuery::objectId() const -{ - Q_D(const QOpenGLTimerQuery); - return d->timer; -} - -/*! - Marks the start point in the OpenGL command queue for a sequence of commands to - be timed by this query object. - - This is useful for simple use-cases. Usually it is better to use recordTimestamp(). - - \sa end(), isResultAvailable(), waitForResult(), recordTimestamp() -*/ -void QOpenGLTimerQuery::begin() -{ - Q_D(QOpenGLTimerQuery); - d->begin(); -} - -/*! - Marks the end point in the OpenGL command queue for a sequence of commands to - be timed by this query object. - - This is useful for simple use-cases. Usually it is better to use recordTimestamp(). - - \sa begin(), isResultAvailable(), waitForResult(), recordTimestamp() -*/ -void QOpenGLTimerQuery::end() -{ - Q_D(QOpenGLTimerQuery); - d->end(); -} - -/*! - Places a marker in the OpenGL command queue for the GPU to record the timestamp - when this marker is reached by the GPU. This function is non-blocking and the - result will become available at some later time. - - The availability of the result can be checked with isResultAvailable(). The result - can be fetched with waitForResult() which will block if the result is not yet - available. - - \sa waitForResult(), isResultAvailable(), begin(), end() -*/ -void QOpenGLTimerQuery::recordTimestamp() -{ - Q_D(QOpenGLTimerQuery); - return d->recordTimestamp(); -} - -/*! - Returns the current timestamp of the GPU when all previously issued OpenGL - commands have been received but not necessarily executed by the GPU. - - This function blocks until the result is returned. - - \sa recordTimestamp() -*/ -GLuint64 QOpenGLTimerQuery::waitForTimestamp() const -{ - Q_D(const QOpenGLTimerQuery); - return d->waitForTimeStamp(); -} - -/*! - Returns \c true if the OpenGL timer query result is available. - - This function is non-blocking and ideally should be used to check for the - availability of the query result before calling waitForResult(). - - \sa waitForResult() -*/ -bool QOpenGLTimerQuery::isResultAvailable() const -{ - Q_D(const QOpenGLTimerQuery); - return d->isResultAvailable(); -} - -/*! - Returns the result of the OpenGL timer query. - - This function will block until the result is made available by OpenGL. It is - recommended to call isResultAvailable() to ensure that the result is available - to avoid unnecessary blocking and stalling. - - \sa isResultAvailable() -*/ -GLuint64 QOpenGLTimerQuery::waitForResult() const -{ - Q_D(const QOpenGLTimerQuery); - return d->result(); -} - - -class QOpenGLTimeMonitorPrivate : public QObjectPrivate -{ -public: - QOpenGLTimeMonitorPrivate() - : QObjectPrivate(), - timers(), - timeSamples(), - context(nullptr), - core(nullptr), - ext(nullptr), - requestedSampleCount(2), - currentSample(-1), - timerQueryActive(false) - { - } - - ~QOpenGLTimeMonitorPrivate() - { - delete core; - delete ext; - } - - bool create(); - void destroy(); - void recordSample(); - bool isResultAvailable() const; - QVector<GLuint64> samples() const; - QVector<GLuint64> intervals() const; - void reset(); - - QVector<GLuint> timers; - mutable QVector<GLuint64> timeSamples; - - QOpenGLContext *context; - QOpenGLQueryHelper *core; - QExtTimerQueryHelper *ext; - - int requestedSampleCount; - int currentSample; - mutable bool timerQueryActive; -}; - -bool QOpenGLTimeMonitorPrivate::create() -{ - if (!timers.isEmpty() && timers.at(0) != 0 && timers.size() == requestedSampleCount) - return true; - - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (context && context != ctx) { - qWarning("QTimeMonitor: Attempting to use different OpenGL context to recreate timers.\n" - "Please call destroy() first or use the same context to previously create"); - return false; - } - - context = ctx; - if (!context) { - qWarning("A current OpenGL context is required to create timer query objects"); - return false; - } - - // Resize the vectors that hold the timers and the recorded samples - timers.resize(requestedSampleCount); - timeSamples.resize(requestedSampleCount); - - // Resolve the functions provided by OpenGL 1.5 and OpenGL 3.3 or ARB_timer_query - core = new QOpenGLQueryHelper(context); - - // Check to see if we also need to resolve the functions for EXT_timer_query - QSurfaceFormat f = context->format(); - if (f.version() <= qMakePair<int, int>(3, 2) - && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query")) - && context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) { - ext = new QExtTimerQueryHelper(context); - } else if (f.version() <= qMakePair<int, int>(3, 2) - && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query")) - && !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) { - qWarning("QOpenGLTimeMonitor requires one of:\n" - " OpenGL 3.3 or newer,\n" - " OpenGL 3.2 and the ARB_timer_query extension\n" - " or the EXT_timer query extension"); - return false; - } - - core->glGenQueries(requestedSampleCount, timers.data()); - return (timers.at(0) != 0); -} - -void QOpenGLTimeMonitorPrivate::destroy() -{ - if (timers.isEmpty() || timers.at(0) == 0) - return; - - core->glDeleteQueries(timers.size(), timers.data()); - timers.clear(); - delete core; - core = nullptr; - delete ext; - ext = nullptr; - context = nullptr; -} - -void QOpenGLTimeMonitorPrivate::recordSample() -{ - // Use glQueryCounter() and GL_TIMESTAMP where available. - // Otherwise, simulate it with glBeginQuery()/glEndQuery() - if (!ext) { -#if defined(GL_TIMESTAMP) - core->glQueryCounter(timers.at(++currentSample), GL_TIMESTAMP); -#endif - } else { - if (currentSample == -1) { - core->glBeginQuery(GL_TIME_ELAPSED_EXT, timers.at(++currentSample)); - timerQueryActive = true; - } else if (currentSample < timers.size() - 1) { - core->glEndQuery(GL_TIME_ELAPSED_EXT); - core->glBeginQuery(GL_TIME_ELAPSED_EXT, timers.at(++currentSample)); - } else { - if (timerQueryActive) { - core->glEndQuery(GL_TIME_ELAPSED_EXT); - timerQueryActive = false; - } - } - } -} - -bool QOpenGLTimeMonitorPrivate::isResultAvailable() const -{ - // The OpenGL spec says that if a query result is ready then the results of all queries - // of the same type issued before it must also be ready. Therefore we only need to check - // the availability of the result for the last issued query - GLuint available = GL_FALSE; - core->glGetQueryObjectuiv(timers.at(currentSample), GL_QUERY_RESULT_AVAILABLE, &available); - return available; -} - -QVector<GLuint64> QOpenGLTimeMonitorPrivate::samples() const -{ - // For the Core and ARB options just ask for the timestamp for each timer query. - // For the EXT implementation we cannot obtain timestamps so we defer any result - // collection to the intervals() function - if (!ext) { - for (int i = 0; i <= currentSample; ++i) - core->glGetQueryObjectui64v(timers.at(i), GL_QUERY_RESULT, &timeSamples[i]); - } else { - qWarning("QOpenGLTimeMonitor::samples() requires OpenGL >=3.3\n" - "or OpenGL 3.2 and GL_ARB_timer_query"); - } - return timeSamples; -} - -QVector<GLuint64> QOpenGLTimeMonitorPrivate::intervals() const -{ - QVector<GLuint64> intervals(timers.size() - 1); - if (!ext) { - // Obtain the timestamp samples and calculate the interval durations - const QVector<GLuint64> timeStamps = samples(); - for (int i = 0; i < intervals.size(); ++i) - intervals[i] = timeStamps[i+1] - timeStamps[i]; - } else { - // Stop the last timer if needed - if (timerQueryActive) { - core->glEndQuery(GL_TIME_ELAPSED_EXT); - timerQueryActive = false; - } - - // Obtain the results from all timers apart from the redundant last one. In this - // case the results actually are the intervals not timestamps - for (int i = 0; i < currentSample; ++i) - ext->glGetQueryObjectui64vEXT(timers.at(i), GL_QUERY_RESULT, &intervals[i]); - } - - return intervals; -} - -void QOpenGLTimeMonitorPrivate::reset() -{ - currentSample = -1; - timeSamples.fill(0); -} - - -/*! - \class QOpenGLTimeMonitor - \brief The QOpenGLTimeMonitor class wraps a sequence of OpenGL timer query objects. - \inmodule QtGui - \since 5.1 - \ingroup painting-3D - - The QOpenGLTimeMonitor class is a convenience wrapper around a collection of OpenGL - timer query objects used to measure intervals of time on the GPU to the level of - granularity required by your rendering application. - - The OpenGL timer queries objects are queried in sequence to record the GPU - timestamps at positions of interest in your rendering code. Once the results for - all issues timer queries become available, the results can be fetched and - QOpenGLTimerMonitor will calculate the recorded time intervals for you. - - The typical use case of this class is to either profile your application's rendering - algorithms or to adjust those algorithms in real-time for dynamic performance/quality - balancing. - - Prior to using QOpenGLTimeMonitor in your rendering function you should set the - required number of sample points that you wish to record by calling setSamples(). Note - that measuring N sample points will produce N-1 time intervals. Once you have set the - number of sample points, call the create() function with a valid current OpenGL context - to create the necessary query timer objects. These steps are usually performed just - once in an initialization function. - - Use the recordSample() function to delimit blocks of code containing OpenGL commands - that you wish to time. You can check availability of the resulting time - samples and time intervals with isResultAvailable(). The calculated time intervals and - the raw timestamp samples can be retrieved with the blocking waitForIntervals() and - waitForSamples() functions respectively. - - After retrieving the results and before starting a new round of taking samples - (for example, in the next frame) be sure to call the reset() function which will clear - the cached results and reset the timer index back to the first timer object. - - \sa QOpenGLTimerQuery -*/ - -/*! - Creates a QOpenGLTimeMonitor instance with the given \a parent. You must call create() - with a valid OpenGL context before using. - - \sa setSampleCount(), create() -*/ -QOpenGLTimeMonitor::QOpenGLTimeMonitor(QObject *parent) - : QObject(*new QOpenGLTimeMonitorPrivate, parent) -{ -} - -/*! - Destroys the QOpenGLTimeMonitor and any underlying OpenGL resources. -*/ -QOpenGLTimeMonitor::~QOpenGLTimeMonitor() -{ - QOpenGLContext* ctx = QOpenGLContext::currentContext(); - - Q_D(QOpenGLTimeMonitor); - QOpenGLContext *oldContext = nullptr; - if (d->context != ctx) { - oldContext = ctx; - if (d->context->makeCurrent(oldContext->surface())) { - ctx = d->context; - } else { - qWarning("QOpenGLTimeMonitor::~QOpenGLTimeMonitor() failed to make time monitor's context current"); - ctx = nullptr; - } - } - - if (ctx) - destroy(); - - if (oldContext) { - if (!oldContext->makeCurrent(oldContext->surface())) - qWarning("QOpenGLTimeMonitor::~QOpenGLTimeMonitor() failed to restore current context"); - } -} - -/*! - Sets the number of sample points to \a sampleCount. After setting the number - of samples with this function, you must call create() to instantiate the underlying - OpenGL timer query objects. - - The new \a sampleCount must be at least 2. - - \sa sampleCount(), create(), recordSample() -*/ -void QOpenGLTimeMonitor::setSampleCount(int sampleCount) -{ - // We need at least 2 samples to get an interval - if (sampleCount < 2) - return; - Q_D(QOpenGLTimeMonitor); - d->requestedSampleCount = sampleCount; -} - -/*! - Returns the number of sample points that have been requested with - setSampleCount(). If create was successfully called following setSampleCount(), - then the value returned will be the actual number of sample points - that can be used. - - The default value for sample count is 2, leading to the measurement of a - single interval. - - \sa setSampleCount() -*/ -int QOpenGLTimeMonitor::sampleCount() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->requestedSampleCount; -} - -/*! - Instantiate sampleCount() OpenGL timer query objects that will be used - to track the amount of time taken to execute OpenGL commands between - successive calls to recordSample(). - - Returns \c true if the OpenGL timer query objects could be created. - - \sa destroy(), setSampleCount(), recordSample() -*/ -bool QOpenGLTimeMonitor::create() -{ - Q_D(QOpenGLTimeMonitor); - return d->create(); -} - -/*! - Destroys any OpenGL timer query objects used within this instance. - - \sa create() -*/ -void QOpenGLTimeMonitor::destroy() -{ - Q_D(QOpenGLTimeMonitor); - d->destroy(); -} - -/*! - Returns \c true if the underlying OpenGL query objects have been created. If this - returns \c true and the associated OpenGL context is current, then you are able to record - time samples with this object. -*/ -bool QOpenGLTimeMonitor::isCreated() const -{ - Q_D(const QOpenGLTimeMonitor); - return (!d->timers.isEmpty() && d->timers.at(0) != 0); -} - -/*! - Returns a QVector containing the object Ids of the OpenGL timer query objects. -*/ -QVector<GLuint> QOpenGLTimeMonitor::objectIds() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->timers; -} - -/*! - Issues an OpenGL timer query at this point in the OpenGL command queue. Calling this - function in a sequence in your application's rendering function, will build up - details of the GPU time taken to execute the OpenGL commands between successive - calls to this function. - - \sa setSampleCount(), isResultAvailable(), waitForSamples(), waitForIntervals() -*/ -int QOpenGLTimeMonitor::recordSample() -{ - Q_D(QOpenGLTimeMonitor); - d->recordSample(); - return d->currentSample; -} - -/*! - Returns \c true if the OpenGL timer query results are available. - - \sa waitForSamples(), waitForIntervals() -*/ -bool QOpenGLTimeMonitor::isResultAvailable() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->isResultAvailable(); -} - -/*! - Returns a QVector containing the GPU timestamps taken with recordSample(). - - This function will block until OpenGL indicates the results are available. It - is recommended to check the availability of the result prior to calling this - function with isResultAvailable(). - - \note This function only works on systems that have OpenGL >=3.3 or the - ARB_timer_query extension. See QOpenGLTimerQuery for more details. - - \sa waitForIntervals(), isResultAvailable() -*/ -QVector<GLuint64> QOpenGLTimeMonitor::waitForSamples() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->samples(); -} - -/*! - Returns a QVector containing the time intervals delimited by the calls to - recordSample(). The resulting vector will contain one fewer element as - this represents the intervening intervals rather than the actual timestamp - samples. - - This function will block until OpenGL indicates the results are available. It - is recommended to check the availability of the result prior to calling this - function with isResultAvailable(). - - \sa waitForSamples(), isResultAvailable() -*/ -QVector<GLuint64> QOpenGLTimeMonitor::waitForIntervals() const -{ - Q_D(const QOpenGLTimeMonitor); - return d->intervals(); -} - -/*! - Resets the time monitor ready for use in another frame of rendering. Call - this once you have obtained the previous results and before calling - recordSample() for the first time on the next frame. - - \sa recordSample() -*/ -void QOpenGLTimeMonitor::reset() -{ - Q_D(QOpenGLTimeMonitor); - d->reset(); -} - -QT_END_NAMESPACE diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 917706e8cf..e544fce70e 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -855,18 +855,6 @@ QColor::QColor(Spec spec) noexcept */ /*! - Returns the name of the color in the format "#RRGGBB"; i.e. a "#" - character followed by three two-digit hexadecimal numbers. - - \sa setNamedColor() -*/ - -QString QColor::name() const -{ - return name(HexRgb); -} - -/*! \since 5.2 Returns the name of the color in the specified \a format. @@ -1086,6 +1074,7 @@ void QColor::setHsvF(qreal h, qreal s, qreal v, qreal a) || (v < qreal(0.0) || v > qreal(1.0)) || (a < qreal(0.0) || a > qreal(1.0))) { qWarning("QColor::setHsvF: HSV parameters out of range"); + invalidate(); return; } @@ -1198,7 +1187,8 @@ void QColor::setHslF(qreal h, qreal s, qreal l, qreal a) || (s < qreal(0.0) || s > qreal(1.0)) || (l < qreal(0.0) || l > qreal(1.0)) || (a < qreal(0.0) || a > qreal(1.0))) { - qWarning("QColor::setHsvF: HSV parameters out of range"); + qWarning("QColor::setHslF: HSL parameters out of range"); + invalidate(); return; } @@ -1224,7 +1214,7 @@ void QColor::setHslF(qreal h, qreal s, qreal l, qreal a) void QColor::setHsl(int h, int s, int l, int a) { if (h < -1 || (uint)s > 255 || (uint)l > 255 || (uint)a > 255) { - qWarning("QColor::setHsv: HSV parameters out of range"); + qWarning("QColor::setHsl: HSL parameters out of range"); invalidate(); return; } @@ -2626,16 +2616,6 @@ QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a) } /*! - \obsolete - - Use the \c const overload instead. -*/ -void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a) -{ - const_cast<const QColor *>(this)->getCmyk(c, m, y, k, a); -} - -/*! Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the cyan, magenta, yellow, black, and alpha-channel (transparency) components of the color's CMYK value. @@ -2665,16 +2645,6 @@ void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a) const } /*! - \obsolete - - Use the \c const overload instead. -*/ -void QColor::getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a) -{ - const_cast<const QColor *>(this)->getCmykF(c, m, y, k, a); -} - -/*! Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the cyan, magenta, yellow, black, and alpha-channel (transparency) components of the color's CMYK value. @@ -2719,6 +2689,7 @@ void QColor::setCmyk(int c, int m, int y, int k, int a) || k < 0 || k > 255 || a < 0 || a > 255) { qWarning("QColor::setCmyk: CMYK parameters out of range"); + invalidate(); return; } @@ -2748,6 +2719,7 @@ void QColor::setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a) || k < qreal(0.0) || k > qreal(1.0) || a < qreal(0.0) || a > qreal(1.0)) { qWarning("QColor::setCmykF: CMYK parameters out of range"); + invalidate(); return; } @@ -2920,18 +2892,6 @@ QColor QColor::dark(int factor) const noexcept } #endif -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) -/*! - Assigns a copy of \a color to this color, and returns a reference to it. -*/ -QColor &QColor::operator=(const QColor &color) noexcept -{ - cspec = color.cspec; - ct.argb = color.ct.argb; - return *this; -} -#endif - /*! \overload Assigns a copy of \a color and returns a reference to this color. */ diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h index 0189f4e5f1..ad624e6b60 100644 --- a/src/gui/painting/qcolor.h +++ b/src/gui/painting/qcolor.h @@ -46,6 +46,8 @@ #include <QtCore/qstringlist.h> #include <QtGui/qrgba64.h> +#include <limits.h> + QT_BEGIN_NAMESPACE @@ -87,24 +89,11 @@ public: inline QColor(QLatin1String name); QColor(Spec spec) noexcept; -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - // ### Qt 6: remove all of these, the trivial ones are fine. - Q_DECL_CONSTEXPR QColor(const QColor &color) noexcept - : cspec(color.cspec), ct(color.ct) - {} - Q_DECL_CONSTEXPR QColor(QColor &&other) noexcept : cspec(other.cspec), ct(other.ct) {} - QColor &operator=(QColor &&other) noexcept - { cspec = other.cspec; ct = other.ct; return *this; } - QColor &operator=(const QColor &) noexcept; -#endif // Qt < 6 - QColor &operator=(Qt::GlobalColor color) noexcept; bool isValid() const noexcept; - // ### Qt 6: merge overloads - QString name() const; - QString name(NameFormat format) const; + QString name(NameFormat format = HexRgb) const; #if QT_STRINGVIEW_LEVEL < 2 void setNamedColor(const QString& name); @@ -180,11 +169,9 @@ public: qreal yellowF() const noexcept; qreal blackF() const noexcept; - void getCmyk(int *c, int *m, int *y, int *k, int *a = nullptr); // ### Qt 6: remove void getCmyk(int *c, int *m, int *y, int *k, int *a = nullptr) const; void setCmyk(int c, int m, int y, int k, int a = 255); - void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = nullptr); // ### Qt 6: remove void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = nullptr) const; void setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0); diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp index 14d7047bb6..a175b591dd 100644 --- a/src/gui/painting/qdrawhelper_ssse3.cpp +++ b/src/gui/painting/qdrawhelper_ssse3.cpp @@ -197,7 +197,7 @@ void qt_memfill24_ssse3(quint24 *dest, quint24 color, qsizetype count) quint24 *end = dest + count; constexpr uchar x = 2, y = 1, z = 0; - Q_DECL_ALIGN(__m128i) static const uchar + alignas(__m128i) static const uchar shuffleMask[16 + 1] = { x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y }; __m128i mval1 = _mm_shuffle_epi8(m, _mm_load_si128(reinterpret_cast<const __m128i *>(shuffleMask))); diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 089aadc3f7..1244ea6709 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -434,14 +434,14 @@ public: QImage::Format prepare(QImage *image); - uchar *scanLine(int y) { Q_ASSERT(y>=0); Q_ASSERT(y<m_height); return m_buffer + y * qsizetype(bytes_per_line); } + uchar *scanLine(int y) { Q_ASSERT(y>=0); Q_ASSERT(y<m_height); return m_buffer + y * bytes_per_line; } int width() const { return m_width; } int height() const { return m_height; } - int bytesPerLine() const { return bytes_per_line; } + qsizetype bytesPerLine() const { return bytes_per_line; } int bytesPerPixel() const { return bytes_per_pixel; } template<typename T> - int stride() { return bytes_per_line / sizeof(T); } + int stride() { return static_cast<int>(bytes_per_line / sizeof(T)); } uchar *buffer() const { return m_buffer; } @@ -456,7 +456,7 @@ public: private: int m_width; int m_height; - int bytes_per_line; + qsizetype bytes_per_line; int bytes_per_pixel; uchar *m_buffer; }; diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index 80b092f177..63e6b48e4f 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -49,7 +49,6 @@ QT_BEGIN_NAMESPACE class QStringList; -template <class T> class QList; struct QFontDef; class QFontEngine; diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp index e00f9d058c..d636bca510 100644 --- a/src/gui/text/qfontengine_qpf2.cpp +++ b/src/gui/text/qfontengine_qpf2.cpp @@ -168,7 +168,7 @@ const QFontEngineQPF2::Glyph *QFontEngineQPF2::findGlyph(glyph_t g) const bool QFontEngineQPF2::verifyHeader(const uchar *data, int size) { - VERIFY(quintptr(data) % Q_ALIGNOF(Header) == 0); + VERIFY(quintptr(data) % alignof(Header) == 0); VERIFY(size >= int(sizeof(Header))); const Header *header = reinterpret_cast<const Header *>(data); if (header->magic[0] != 'Q' diff --git a/src/gui/text/qtextoption.h b/src/gui/text/qtextoption.h index 8b57278633..a90d73dc43 100644 --- a/src/gui/text/qtextoption.h +++ b/src/gui/text/qtextoption.h @@ -48,8 +48,6 @@ QT_BEGIN_NAMESPACE - -template <typename T> class QList; struct QTextOptionPrivate; class Q_GUI_EXPORT QTextOption diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp index 4af5e47f8f..2b81d34848 100644 --- a/src/gui/util/qgridlayoutengine.cpp +++ b/src/gui/util/qgridlayoutengine.cpp @@ -960,7 +960,7 @@ void QGridLayoutEngine::insertItem(QGridLayoutItem *item, int index) { maybeExpandGrid(item->lastRow(), item->lastColumn()); - if (index == -1) + if (index < 0 || index >= q_items.size()) q_items.append(item); else q_items.insert(index, item); diff --git a/src/gui/util/qtexturefiledata.cpp b/src/gui/util/qtexturefiledata.cpp index 41cbd1b15a..3c8130c229 100644 --- a/src/gui/util/qtexturefiledata.cpp +++ b/src/gui/util/qtexturefiledata.cpp @@ -38,11 +38,7 @@ ****************************************************************************/ #include "qtexturefiledata_p.h" -#include <QMetaEnum> #include <QSize> -#if QT_CONFIG(opengl) -#include <QOpenGLTexture> -#endif QT_BEGIN_NAMESPACE @@ -247,13 +243,7 @@ void QTextureFileData::setLogName(const QByteArray &name) static QByteArray glFormatName(quint32 fmt) { - const char *id = nullptr; -#if QT_CONFIG(opengl) - id = QMetaEnum::fromType<QOpenGLTexture::TextureFormat>().valueToKey(fmt); -#endif - QByteArray res(id ? id : "(?)"); - res += " [0x" + QByteArray::number(fmt, 16).rightJustified(4, '0') + ']'; - return res; + return QByteArray("0x" + QByteArray::number(fmt, 16).rightJustified(4, '0')); } QDebug operator<<(QDebug dbg, const QTextureFileData &d) |