summaryrefslogtreecommitdiffstats
path: root/src/opengl/gl2paintengineex
diff options
context:
space:
mode:
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>2019-11-29 11:49:28 +0100
committerJohan Klokkhammer Helsing <johan.helsing@qt.io>2019-12-11 11:53:15 +0100
commitf08038fca79b0828da11fbf35f4165d6efa4de2f (patch)
treec10331ef7c2f79f968a45b4dcb25609b594f27cf /src/opengl/gl2paintengineex
parentbef74b6c3a0a9c8649ea8eb333d80015f76863e4 (diff)
Remove deprecated QGL* classes
Removes QGL paths in sub-attaq and chip examples. The boxes example depended on QGL and has been removed. The corresponding module and test directories for the opengl module are now empty, but has been left there so we can move the QOpenGL* classes there. [ChangeLog][QtOpenGL] The deprecated QGL* classes have been removed. Fixes: QTBUG-74408 Change-Id: I52f56409af8f6901359462a7ba162103d051fe3d Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/opengl/gl2paintengineex')
-rw-r--r--src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp173
-rw-r--r--src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h167
-rw-r--r--src/opengl/gl2paintengineex/qglcustomshaderstage.cpp137
-rw-r--r--src/opengl/gl2paintengineex/qglcustomshaderstage_p.h86
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp875
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h508
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h523
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache.cpp225
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache_p.h103
-rw-r--r--src/opengl/gl2paintengineex/qglshadercache_p.h86
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp2515
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h334
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp414
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h171
14 files changed, 0 insertions, 6317 deletions
diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp b/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp
deleted file mode 100644
index 979ea19fee..0000000000
--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray.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 QtOpenGL 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 "qgl2pexvertexarray_p.h"
-
-#include <private/qbezier_p.h>
-
-QT_BEGIN_NAMESPACE
-
-void QGL2PEXVertexArray::clear()
-{
- vertexArray.reset();
- vertexArrayStops.reset();
- boundingRectDirty = true;
-}
-
-
-QGLRect QGL2PEXVertexArray::boundingRect() const
-{
- if (boundingRectDirty)
- return QGLRect(0.0, 0.0, 0.0, 0.0);
- else
- return QGLRect(minX, minY, maxX, maxY);
-}
-
-void QGL2PEXVertexArray::addClosingLine(int index)
-{
- QPointF point(vertexArray.at(index));
- if (point != QPointF(vertexArray.last()))
- vertexArray.add(point);
-}
-
-void QGL2PEXVertexArray::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 QGL2PEXVertexArray::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 QGL2PEXVertexArray::lineToArray(const GLfloat x, const GLfloat y)
-{
- vertexArray.add(QGLPoint(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/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
deleted file mode 100644
index 5c95268790..0000000000
--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 QGL2PEXVERTEXARRAY_P_H
-#define QGL2PEXVERTEXARRAY_P_H
-
-#include <QRectF>
-
-#include <private/qdatabuffer_p.h>
-#include <private/qvectorpath_p.h>
-#include <private/qgl_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QGLPoint
-{
-public:
- QGLPoint(GLfloat new_x, GLfloat new_y) :
- x(new_x), y(new_y) {};
-
- QGLPoint(const QPointF &p) :
- x(p.x()), y(p.y()) {};
-
- QGLPoint(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 QGLRect
-{
- QGLRect(const QRectF &r)
- : left(r.left()), top(r.top()), right(r.right()), bottom(r.bottom()) {}
-
- QGLRect(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 QGL2PEXVertexArray
-{
-public:
- QGL2PEXVertexArray() :
- 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 << QGLPoint(left, top)
- << QGLPoint(right, top)
- << QGLPoint(right, bottom)
- << QGLPoint(right, bottom)
- << QGLPoint(left, bottom)
- << QGLPoint(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 << QGLPoint(left, top)
- << QGLPoint(right, top)
- << QGLPoint(left, bottom)
- << QGLPoint(right, bottom);
-
- }
-
- inline void addVertex(const GLfloat x, const GLfloat y)
- {
- vertexArray.add(QGLPoint(x, y));
- }
-
- void addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline = true);
- void clear();
-
- QGLPoint* data() {return vertexArray.data();}
- int *stops() const { return vertexArrayStops.data(); }
- int stopCount() const { return vertexArrayStops.size(); }
- QGLRect boundingRect() const;
-
- int vertexCount() const { return vertexArray.size(); }
-
- void lineToArray(const GLfloat x, const GLfloat y);
-
-private:
- QDataBuffer<QGLPoint> 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/opengl/gl2paintengineex/qglcustomshaderstage.cpp b/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp
deleted file mode 100644
index 7d6d4595ba..0000000000
--- a/src/opengl/gl2paintengineex/qglcustomshaderstage.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 QtOpenGL 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 "qglcustomshaderstage_p.h"
-#include "qglengineshadermanager_p.h"
-#include "qpaintengineex_opengl2_p.h"
-#include <private/qpainter_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QGLCustomShaderStagePrivate
-{
-public:
- QGLCustomShaderStagePrivate() :
- m_manager(0) {}
-
- QPointer<QGLEngineShaderManager> m_manager;
- QByteArray m_source;
-};
-
-
-
-
-QGLCustomShaderStage::QGLCustomShaderStage()
- : d_ptr(new QGLCustomShaderStagePrivate)
-{
-}
-
-QGLCustomShaderStage::~QGLCustomShaderStage()
-{
- Q_D(QGLCustomShaderStage);
- if (d->m_manager) {
- d->m_manager->removeCustomStage();
- d->m_manager->sharedShaders->cleanupCustomStage(this);
- }
- delete d_ptr;
-}
-
-void QGLCustomShaderStage::setUniformsDirty()
-{
- Q_D(QGLCustomShaderStage);
- if (d->m_manager)
- d->m_manager->setDirty(); // ### Probably a bit overkill!
-}
-
-bool QGLCustomShaderStage::setOnPainter(QPainter* p)
-{
- Q_D(QGLCustomShaderStage);
- if (p->paintEngine()->type() != QPaintEngine::OpenGL2) {
- qWarning("QGLCustomShaderStage::setOnPainter() - paint engine not OpenGL2");
- return false;
- }
- if (d->m_manager)
- qWarning("Custom shader is already set on a painter");
-
- QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx*>(p->paintEngine());
- d->m_manager = QGL2PaintEngineExPrivate::shaderManagerForEngine(engine);
- Q_ASSERT(d->m_manager);
-
- d->m_manager->setCustomStage(this);
- return true;
-}
-
-void QGLCustomShaderStage::removeFromPainter(QPainter* p)
-{
- Q_D(QGLCustomShaderStage);
- if (p->paintEngine()->type() != QPaintEngine::OpenGL2)
- return;
-
- QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx*>(p->paintEngine());
- d->m_manager = QGL2PaintEngineExPrivate::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(0);
- d->m_manager = 0;
-}
-
-QByteArray QGLCustomShaderStage::source() const
-{
- Q_D(const QGLCustomShaderStage);
- return d->m_source;
-}
-
-// Called by the shader manager if another custom shader is attached or
-// the manager is deleted
-void QGLCustomShaderStage::setInactive()
-{
- Q_D(QGLCustomShaderStage);
- d->m_manager = 0;
-}
-
-void QGLCustomShaderStage::setSource(const QByteArray& s)
-{
- Q_D(QGLCustomShaderStage);
- d->m_source = s;
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h b/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h
deleted file mode 100644
index 77421ebdd3..0000000000
--- a/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 QGL_CUSTOM_SHADER_STAGE_H
-#define QGL_CUSTOM_SHADER_STAGE_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 <QGLShaderProgram>
-
-QT_BEGIN_NAMESPACE
-
-
-class QGLCustomShaderStagePrivate;
-class Q_OPENGL_EXPORT QGLCustomShaderStage
-{
- Q_DECLARE_PRIVATE(QGLCustomShaderStage)
-public:
- QGLCustomShaderStage();
- virtual ~QGLCustomShaderStage();
- virtual void setUniforms(QGLShaderProgram*) {}
-
- void setUniformsDirty();
-
- bool setOnPainter(QPainter*);
- void removeFromPainter(QPainter*);
- QByteArray source() const;
-
- void setInactive();
-protected:
- void setSource(const QByteArray&);
-
-private:
- QGLCustomShaderStagePrivate* d_ptr;
-};
-
-
-QT_END_NAMESPACE
-
-
-#endif
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
deleted file mode 100644
index 47e8531959..0000000000
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ /dev/null
@@ -1,875 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 "qglengineshadermanager_p.h"
-#include "qglengineshadersource_p.h"
-#include "qpaintengineex_opengl2_p.h"
-#include "qglshadercache_p.h"
-
-#include <QtGui/private/qopenglcontext_p.h>
-
-#if defined(QT_DEBUG)
-#include <QMetaEnum>
-#endif
-
-#include <algorithm>
-
-// #define QT_GL_SHARED_SHADER_DEBUG
-
-QT_BEGIN_NAMESPACE
-
-class QGLEngineSharedShadersResource : public QOpenGLSharedResource
-{
-public:
- QGLEngineSharedShadersResource(QOpenGLContext *ctx)
- : QOpenGLSharedResource(ctx->shareGroup())
- , m_shaders(new QGLEngineSharedShaders(QGLContext::fromOpenGLContext(ctx)))
- {
- }
-
- ~QGLEngineSharedShadersResource()
- {
- delete m_shaders;
- }
-
- void invalidateResource() override
- {
- delete m_shaders;
- m_shaders = 0;
- }
-
- void freeResource(QOpenGLContext *) override
- {
- }
-
- QGLEngineSharedShaders *shaders() const { return m_shaders; }
-
-private:
- QGLEngineSharedShaders *m_shaders;
-};
-
-class QGLShaderStorage
-{
-public:
- QGLEngineSharedShaders *shadersForThread(const QGLContext *context) {
- QOpenGLMultiGroupSharedResource *&shaders = m_storage.localData();
- if (!shaders)
- shaders = new QOpenGLMultiGroupSharedResource;
- QGLEngineSharedShadersResource *resource =
- shaders->value<QGLEngineSharedShadersResource>(context->contextHandle());
- return resource ? resource->shaders() : 0;
- }
-
-private:
- QThreadStorage<QOpenGLMultiGroupSharedResource *> m_storage;
-};
-
-Q_GLOBAL_STATIC(QGLShaderStorage, qt_shader_storage);
-
-QGLEngineSharedShaders *QGLEngineSharedShaders::shadersForContext(const QGLContext *context)
-{
- return qt_shader_storage()->shadersForThread(context);
-}
-
-const char* QGLEngineSharedShaders::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
-};
-
-QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
- : blitShaderProg(0)
- , simpleShaderProg(0)
-{
-
-/*
- 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.
-*/
- static bool snippetsPopulated = false;
- if (!snippetsPopulated) {
-
- const char** code = qShaderSnippets; // shortcut
-
- code[MainVertexShader] = qglslMainVertexShader;
- code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader;
- code[MainWithTexCoordsAndOpacityVertexShader] = qglslMainWithTexCoordsAndOpacityVertexShader;
-
- code[UntransformedPositionVertexShader] = qglslUntransformedPositionVertexShader;
- code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader;
- code[ComplexGeometryPositionOnlyVertexShader] = qglslComplexGeometryPositionOnlyVertexShader;
- code[PositionWithPatternBrushVertexShader] = qglslPositionWithPatternBrushVertexShader;
- code[PositionWithLinearGradientBrushVertexShader] = qglslPositionWithLinearGradientBrushVertexShader;
- code[PositionWithConicalGradientBrushVertexShader] = qglslPositionWithConicalGradientBrushVertexShader;
- code[PositionWithRadialGradientBrushVertexShader] = qglslPositionWithRadialGradientBrushVertexShader;
- code[PositionWithTextureBrushVertexShader] = qglslPositionWithTextureBrushVertexShader;
- code[AffinePositionWithPatternBrushVertexShader] = qglslAffinePositionWithPatternBrushVertexShader;
- code[AffinePositionWithLinearGradientBrushVertexShader] = qglslAffinePositionWithLinearGradientBrushVertexShader;
- code[AffinePositionWithConicalGradientBrushVertexShader] = qglslAffinePositionWithConicalGradientBrushVertexShader;
- code[AffinePositionWithRadialGradientBrushVertexShader] = qglslAffinePositionWithRadialGradientBrushVertexShader;
- code[AffinePositionWithTextureBrushVertexShader] = qglslAffinePositionWithTextureBrushVertexShader;
-
- code[MainFragmentShader_CMO] = qglslMainFragmentShader_CMO;
- code[MainFragmentShader_CM] = qglslMainFragmentShader_CM;
- code[MainFragmentShader_MO] = qglslMainFragmentShader_MO;
- code[MainFragmentShader_M] = qglslMainFragmentShader_M;
- code[MainFragmentShader_CO] = qglslMainFragmentShader_CO;
- code[MainFragmentShader_C] = qglslMainFragmentShader_C;
- code[MainFragmentShader_O] = qglslMainFragmentShader_O;
- code[MainFragmentShader] = qglslMainFragmentShader;
- code[MainFragmentShader_ImageArrays] = qglslMainFragmentShader_ImageArrays;
-
- code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader;
- code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader;
- code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader;
- code[CustomImageSrcFragmentShader] = qglslCustomSrcFragmentShader; // Calls "customShader", which must be appended
- code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader;
- if (!context->contextHandle()->isOpenGLES())
- code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader_desktop;
- else
- code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader_ES;
- code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader;
- code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader;
- code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader;
- code[RadialGradientBrushSrcFragmentShader] = qglslRadialGradientBrushSrcFragmentShader;
- code[ConicalGradientBrushSrcFragmentShader] = qglslConicalGradientBrushSrcFragmentShader;
- code[ShockingPinkSrcFragmentShader] = qglslShockingPinkSrcFragmentShader;
-
- code[NoMaskFragmentShader] = "";
- code[MaskFragmentShader] = qglslMaskFragmentShader;
- code[RgbMaskFragmentShaderPass1] = qglslRgbMaskFragmentShaderPass1;
- code[RgbMaskFragmentShaderPass2] = qglslRgbMaskFragmentShaderPass2;
- code[RgbMaskWithGammaFragmentShader] = ""; //###
-
- code[NoCompositionModeFragmentShader] = "";
- code[MultiplyCompositionModeFragmentShader] = ""; //###
- code[ScreenCompositionModeFragmentShader] = ""; //###
- code[OverlayCompositionModeFragmentShader] = ""; //###
- code[DarkenCompositionModeFragmentShader] = ""; //###
- code[LightenCompositionModeFragmentShader] = ""; //###
- code[ColorDodgeCompositionModeFragmentShader] = ""; //###
- code[ColorBurnCompositionModeFragmentShader] = ""; //###
- code[HardLightCompositionModeFragmentShader] = ""; //###
- code[SoftLightCompositionModeFragmentShader] = ""; //###
- code[DifferenceCompositionModeFragmentShader] = ""; //###
- code[ExclusionCompositionModeFragmentShader] = ""; //###
-
-#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
- snippetsPopulated = true;
- }
-
- QGLShader* fragShader;
- QGLShader* vertexShader;
- QByteArray vertexSource;
- QByteArray fragSource;
-
- // Compile up the simple shader:
- vertexSource.append(qShaderSnippets[MainVertexShader]);
- vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]);
-
- fragSource.append(qShaderSnippets[MainFragmentShader]);
- fragSource.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
-
- simpleShaderProg = new QGLShaderProgram(context, 0);
-
- CachedShader simpleShaderCache(fragSource, vertexSource);
-
- bool inCache = simpleShaderCache.load(simpleShaderProg, context);
-
- if (!inCache) {
- vertexShader = new QGLShader(QGLShader::Vertex, context, 0);
- shaders.append(vertexShader);
- if (!vertexShader->compileSourceCode(vertexSource))
- qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
-
- fragShader = new QGLShader(QGLShader::Fragment, context, 0);
- shaders.append(fragShader);
- if (!fragShader->compileSourceCode(fragSource))
- qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
-
- simpleShaderProg->addShader(vertexShader);
- simpleShaderProg->addShader(fragShader);
-
- 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 QGLShaderProgram(context, 0);
-
- CachedShader blitShaderCache(fragSource, vertexSource);
-
- inCache = blitShaderCache.load(blitShaderProg, context);
-
- if (!inCache) {
- vertexShader = new QGLShader(QGLShader::Vertex, context, 0);
- shaders.append(vertexShader);
- if (!vertexShader->compileSourceCode(vertexSource))
- qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
-
- fragShader = new QGLShader(QGLShader::Fragment, context, 0);
- shaders.append(fragShader);
- if (!fragShader->compileSourceCode(fragSource))
- qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
-
- blitShaderProg->addShader(vertexShader);
- blitShaderProg->addShader(fragShader);
-
- 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(" -> QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread());
-#endif
-}
-
-QGLEngineSharedShaders::~QGLEngineSharedShaders()
-{
-#ifdef QT_GL_SHARED_SHADER_DEBUG
- qDebug(" -> ~QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread());
-#endif
- qDeleteAll(shaders);
- shaders.clear();
-
- qDeleteAll(cachedPrograms);
- cachedPrograms.clear();
-
- if (blitShaderProg) {
- delete blitShaderProg;
- blitShaderProg = 0;
- }
-
- if (simpleShaderProg) {
- delete simpleShaderProg;
- simpleShaderProg = 0;
- }
-}
-
-#if defined (QT_DEBUG)
-QByteArray QGLEngineSharedShaders::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.
-QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog)
-{
- for (int i = 0; i < cachedPrograms.size(); ++i) {
- QGLEngineShaderProg *cachedProg = cachedPrograms.at(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<QGLEngineShaderProg> 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;
- vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
- vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
-
- QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram);
-
- CachedShader shaderCache(fragSource, vertexSource);
- bool inCache = shaderCache.load(shaderProgram.data(), QGLContext::currentContext());
-
- if (!inCache) {
-
- QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment));
- QByteArray description;
-#if defined(QT_DEBUG)
- // Name the shader for easier debugging
- 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));
- }
- fragShader->setObjectName(QString::fromLatin1(description));
-#endif
- if (!fragShader->compileSourceCode(fragSource)) {
- qWarning() << "Warning:" << description << "failed to compile!";
- break;
- }
-
- QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex));
-#if defined(QT_DEBUG)
- // Name the shader for easier debugging
- description.clear();
- description.append("Vertex shader: main=");
- description.append(snippetNameStr(prog.mainVertexShader));
- description.append(", position=");
- description.append(snippetNameStr(prog.positionVertexShader));
- vertexShader->setObjectName(QString::fromLatin1(description));
-#endif
- if (!vertexShader->compileSourceCode(vertexSource)) {
- qWarning() << "Warning:" << description << "failed to compile!";
- break;
- }
-
- shaders.append(vertexShader.data());
- shaders.append(fragShader.data());
- shaderProgram->addShader(vertexShader.take());
- shaderProgram->addShader(fragShader.take());
-
- // 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 QGLEngineShaderProg(prog));
- newProg->program = shaderProgram.take();
-
- newProg->program->link();
- if (newProg->program->isLinked()) {
- if (!inCache)
- shaderCache.store(newProg->program, QGLContext::currentContext());
- } else {
- QString error;
- error = QLatin1String("Shader program failed to link,");
-#if defined(QT_DEBUG)
- QLatin1String br("\n");
- error += QLatin1String("\n Shaders Used:\n");
- for (int i = 0; i < newProg->program->shaders().count(); ++i) {
- QGLShader *shader = newProg->program->shaders().at(i);
- error += QLatin1String(" ") + shader->objectName() + QLatin1String(": \n")
- + QLatin1String(shader->sourceCode()) + br;
- }
-#endif
- error += QLatin1String(" Error Log:\n")
- + QLatin1String(" ") + newProg->program->log();
- qWarning() << error;
- break;
- }
-
- newProg->program->bind();
-
- if (newProg->maskFragShader != QGLEngineSharedShaders::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 QGLEngineSharedShaders::cleanupCustomStage(QGLCustomShaderStage* stage)
-{
- auto hasStageAsCustomShaderSouce = [stage](QGLEngineShaderProg *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());
-}
-
-
-QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
- : ctx(context),
- shaderProgNeedsChanging(true),
- complexGeometry(false),
- srcPixelType(Qt::NoBrush),
- opacityMode(NoOpacity),
- maskType(NoMask),
- compositionMode(QPainter::CompositionMode_SourceOver),
- customSrcStage(0),
- currentShaderProg(0)
-{
- sharedShaders = QGLEngineSharedShaders::shadersForContext(context);
-}
-
-QGLEngineShaderManager::~QGLEngineShaderManager()
-{
- //###
- removeCustomStage();
-}
-
-GLuint QGLEngineShaderManager::getUniformLocation(Uniform id)
-{
- if (!currentShaderProg)
- return 0;
-
- QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
- if (uniformLocations.isEmpty())
- uniformLocations.fill(GLuint(-1), NumUniforms);
-
- static const char *const uniformNames[] = {
- "imageTexture",
- "patternColor",
- "globalOpacity",
- "depth",
- "maskTexture",
- "fragmentColor",
- "linearData",
- "angle",
- "halfViewportSize",
- "fmp",
- "fmp2_m_radius2",
- "inverse_2_fmp2_m_radius2",
- "sqrfr",
- "bradius",
- "invertedTextureSize",
- "brushTransform",
- "brushTexture",
- "matrix",
- "translateZ"
- };
-
- if (uniformLocations.at(id) == GLuint(-1))
- uniformLocations[id] = currentShaderProg->program->uniformLocation(uniformNames[id]);
-
- return uniformLocations.at(id);
-}
-
-
-void QGLEngineShaderManager::optimiseForBrushTransform(QTransform::TransformationType transformType)
-{
- Q_UNUSED(transformType); // Currently ignored
-}
-
-void QGLEngineShaderManager::setDirty()
-{
- shaderProgNeedsChanging = true;
-}
-
-void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
-{
- Q_ASSERT(style != Qt::NoBrush);
- if (srcPixelType == PixelSrcType(style))
- return;
-
- srcPixelType = style;
- shaderProgNeedsChanging = true; //###
-}
-
-void QGLEngineShaderManager::setSrcPixelType(PixelSrcType type)
-{
- if (srcPixelType == type)
- return;
-
- srcPixelType = type;
- shaderProgNeedsChanging = true; //###
-}
-
-void QGLEngineShaderManager::setOpacityMode(OpacityMode mode)
-{
- if (opacityMode == mode)
- return;
-
- opacityMode = mode;
- shaderProgNeedsChanging = true; //###
-}
-
-void QGLEngineShaderManager::setMaskType(MaskType type)
-{
- if (maskType == type)
- return;
-
- maskType = type;
- shaderProgNeedsChanging = true; //###
-}
-
-void QGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode)
-{
- if (compositionMode == mode)
- return;
-
- compositionMode = mode;
- shaderProgNeedsChanging = true; //###
-}
-
-void QGLEngineShaderManager::setCustomStage(QGLCustomShaderStage* stage)
-{
- if (customSrcStage)
- removeCustomStage();
- customSrcStage = stage;
- shaderProgNeedsChanging = true;
-}
-
-void QGLEngineShaderManager::removeCustomStage()
-{
- if (customSrcStage)
- customSrcStage->setInactive();
- customSrcStage = 0;
- shaderProgNeedsChanging = true;
-}
-
-QGLShaderProgram* QGLEngineShaderManager::currentProgram()
-{
- if (currentShaderProg)
- return currentShaderProg->program;
- else
- return sharedShaders->simpleProgram();
-}
-
-void QGLEngineShaderManager::useSimpleProgram()
-{
- sharedShaders->simpleProgram()->bind();
- QGLContextPrivate* ctx_d = ctx->d_func();
- ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
- ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false);
- ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
- shaderProgNeedsChanging = true;
-}
-
-void QGLEngineShaderManager::useBlitProgram()
-{
- sharedShaders->blitProgram()->bind();
- QGLContextPrivate* ctx_d = ctx->d_func();
- ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
- ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, true);
- ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
- shaderProgNeedsChanging = true;
-}
-
-QGLShaderProgram* QGLEngineShaderManager::simpleProgram()
-{
- return sharedShaders->simpleProgram();
-}
-
-QGLShaderProgram* QGLEngineShaderManager::blitProgram()
-{
- return sharedShaders->blitProgram();
-}
-
-
-
-// Select & use the correct shader program using the current state.
-// Returns \c true if program needed changing.
-bool QGLEngineShaderManager::useCorrectShaderProg()
-{
- if (!shaderProgNeedsChanging)
- return false;
-
- bool useCustomSrc = customSrcStage != 0;
- if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc && srcPixelType != Qt::TexturePattern) {
- useCustomSrc = false;
- qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src");
- }
-
- QGLEngineShaderProg 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 = QGLEngineSharedShaders::InvalidSnippetName;
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::InvalidSnippetName;
- bool isAffine = brushTransform.isAffine();
- if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) {
- if (isAffine)
- requiredProgram.positionVertexShader = QGLEngineSharedShaders::AffinePositionWithPatternBrushVertexShader;
- else
- requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionWithPatternBrushVertexShader;
-
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::PatternBrushSrcFragmentShader;
- }
- else switch (srcPixelType) {
- default:
- case Qt::NoBrush:
- qFatal("QGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set");
- break;
- case QGLEngineShaderManager::ImageSrc:
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcFragmentShader;
- requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
- texCoords = true;
- break;
- case QGLEngineShaderManager::NonPremultipliedImageSrc:
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::NonPremultipliedImageSrcFragmentShader;
- requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
- texCoords = true;
- break;
- case QGLEngineShaderManager::PatternSrc:
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcWithPatternFragmentShader;
- requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
- texCoords = true;
- break;
- case QGLEngineShaderManager::TextureSrcWithPattern:
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcWithPatternFragmentShader;
- requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
- : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
- break;
- case Qt::SolidPattern:
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::SolidBrushSrcFragmentShader;
- requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
- break;
- case Qt::LinearGradientPattern:
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader;
- requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader
- : QGLEngineSharedShaders::PositionWithLinearGradientBrushVertexShader;
- break;
- case Qt::ConicalGradientPattern:
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ConicalGradientBrushSrcFragmentShader;
- requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader
- : QGLEngineSharedShaders::PositionWithConicalGradientBrushVertexShader;
- break;
- case Qt::RadialGradientPattern:
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader;
- requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader
- : QGLEngineSharedShaders::PositionWithRadialGradientBrushVertexShader;
- break;
- case Qt::TexturePattern:
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcFragmentShader;
- requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
- : QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
- break;
- };
-
- if (useCustomSrc) {
- requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::CustomImageSrcFragmentShader;
- requiredProgram.customStageSource = customSrcStage->source();
- }
-
- const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus;
- const bool hasMask = maskType != QGLEngineShaderManager::NoMask;
-
- // Choose fragment shader main function:
- if (opacityMode == AttributeOpacity) {
- Q_ASSERT(!hasCompose && !hasMask);
- requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_ImageArrays;
- } else {
- bool useGlobalOpacity = (opacityMode == UniformOpacity);
- if (hasCompose && hasMask && useGlobalOpacity)
- requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CMO;
- if (hasCompose && hasMask && !useGlobalOpacity)
- requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CM;
- if (!hasCompose && hasMask && useGlobalOpacity)
- requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_MO;
- if (!hasCompose && hasMask && !useGlobalOpacity)
- requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_M;
- if (hasCompose && !hasMask && useGlobalOpacity)
- requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CO;
- if (hasCompose && !hasMask && !useGlobalOpacity)
- requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_C;
- if (!hasCompose && !hasMask && useGlobalOpacity)
- requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_O;
- if (!hasCompose && !hasMask && !useGlobalOpacity)
- requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader;
- }
-
- if (hasMask) {
- if (maskType == PixelMask) {
- requiredProgram.maskFragShader = QGLEngineSharedShaders::MaskFragmentShader;
- texCoords = true;
- } else if (maskType == SubPixelMaskPass1) {
- requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass1;
- texCoords = true;
- } else if (maskType == SubPixelMaskPass2) {
- requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass2;
- texCoords = true;
- } else if (maskType == SubPixelWithGammaMask) {
- requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskWithGammaFragmentShader;
- texCoords = true;
- } else {
- qCritical("QGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
- }
- } else {
- requiredProgram.maskFragShader = QGLEngineSharedShaders::NoMaskFragmentShader;
- }
-
- if (hasCompose) {
- switch (compositionMode) {
- case QPainter::CompositionMode_Multiply:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::MultiplyCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_Screen:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::ScreenCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_Overlay:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::OverlayCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_Darken:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::DarkenCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_Lighten:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::LightenCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_ColorDodge:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_ColorBurn:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_HardLight:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::HardLightCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_SoftLight:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::SoftLightCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_Difference:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::DifferenceCompositionModeFragmentShader;
- break;
- case QPainter::CompositionMode_Exclusion:
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::ExclusionCompositionModeFragmentShader;
- break;
- default:
- qWarning("QGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
- }
- } else {
- requiredProgram.compositionFragShader = QGLEngineSharedShaders::NoCompositionModeFragmentShader;
- }
-
- // Choose vertex shader main function
- if (opacityMode == AttributeOpacity) {
- Q_ASSERT(texCoords);
- requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader;
- } else if (texCoords) {
- requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsVertexShader;
- } else {
- requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainVertexShader;
- }
- requiredProgram.useTextureCoords = texCoords;
- requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
- if (complexGeometry && srcPixelType == Qt::SolidPattern) {
- requiredProgram.positionVertexShader = QGLEngineSharedShaders::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)
- QGLContextPrivate* ctx_d = ctx->d_func();
- ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
- ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, currentShaderProg && currentShaderProg->useTextureCoords);
- ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, currentShaderProg && currentShaderProg->useOpacityAttribute);
-
- shaderProgNeedsChanging = false;
- return true;
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
deleted file mode 100644
index d23b3ad550..0000000000
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ /dev/null
@@ -1,508 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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, QGLShader & QGLShaderProgram will make partial
- shaders work by concatenating the source in each QGLShader and compiling
- it as a single shader. This is abstracted nicely by QGLShaderProgram 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:
- qglslMainVertexShader
- qglslMainWithTexCoordsVertexShader
-
- And the following position vertex shaders:
- qglslPositionOnlyVertexShader
- qglslPositionWithTextureBrushVertexShader
- qglslPositionWithPatternBrushVertexShader
- qglslPositionWithLinearGradientBrushVertexShader
- qglslPositionWithRadialGradientBrushVertexShader
- qglslPositionWithConicalGradientBrushVertexShader
- qglslAffinePositionWithTextureBrushVertexShader
- qglslAffinePositionWithPatternBrushVertexShader
- qglslAffinePositionWithLinearGradientBrushVertexShader
- qglslAffinePositionWithRadialGradientBrushVertexShader
- qglslAffinePositionWithConicalGradientBrushVertexShader
-
- 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()":
- qglslImageSrcFragShader
- qglslImageSrcWithPatternFragShader
- qglslNonPremultipliedImageSrcFragShader
- qglslSolidBrushSrcFragShader
- qglslTextureBrushSrcFragShader
- qglslTextureBrushWithPatternFragShader
- qglslPatternBrushSrcFragShader
- qglslLinearGradientBrushSrcFragShader
- qglslRadialGradientBrushSrcFragShader
- qglslConicalGradientBrushSrcFragShader
- NOTE: It is assumed the colour returned by srcPixel() is pre-multiplied
-
- Masks are implementations of "qcolorp vec4 applyMask(qcolorp vec4 src)":
- qglslMaskFragmentShader
- qglslRgbMaskFragmentShaderPass1
- qglslRgbMaskFragmentShaderPass2
- qglslRgbMaskWithGammaFragmentShader
-
- Composition modes are "qcolorp vec4 compose(qcolorp vec4 src)":
- qglslColorBurnCompositionModeFragmentShader
- qglslColorDodgeCompositionModeFragmentShader
- qglslDarkenCompositionModeFragmentShader
- qglslDifferenceCompositionModeFragmentShader
- qglslExclusionCompositionModeFragmentShader
- qglslHardLightCompositionModeFragmentShader
- qglslLightenCompositionModeFragmentShader
- qglslMultiplyCompositionModeFragmentShader
- qglslOverlayCompositionModeFragmentShader
- qglslScreenCompositionModeFragmentShader
- qglslSoftLightCompositionModeFragmentShader
-
-
- 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:
- qglslMainFragmentShader_CMO
- qglslMainFragmentShader_CM
- qglslMainFragmentShader_MO
- qglslMainFragmentShader_M
- qglslMainFragmentShader_CO
- qglslMainFragmentShader_C
- qglslMainFragmentShader_O
- qglslMainFragmentShader
-
- 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
- (QGLCustomShaderStage). 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 QGLENGINE_SHADER_MANAGER_H
-#define QGLENGINE_SHADER_MANAGER_H
-
-#include <QGLShader>
-#include <QGLShaderProgram>
-#include <QPainter>
-#include <private/qgl_p.h>
-#include <private/qglcustomshaderstage_p.h>
-
-QT_BEGIN_NAMESPACE
-
-
-
-/*
-struct QGLEngineCachedShaderProg
-{
- QGLEngineCachedShaderProg(QGLEngineShaderManager::ShaderName vertexMain,
- QGLEngineShaderManager::ShaderName vertexPosition,
- QGLEngineShaderManager::ShaderName fragMain,
- QGLEngineShaderManager::ShaderName pixelSrc,
- QGLEngineShaderManager::ShaderName mask,
- QGLEngineShaderManager::ShaderName composition);
-
- int cacheKey;
- QGLShaderProgram* 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 QGLEngineShaderProg;
-
-class Q_OPENGL_EXPORT QGLEngineSharedShaders
-{
- 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_CMO,
- MainFragmentShader_CM,
- MainFragmentShader_MO,
- MainFragmentShader_M,
- MainFragmentShader_CO,
- MainFragmentShader_C,
- MainFragmentShader_O,
- MainFragmentShader,
- MainFragmentShader_ImageArrays,
-
- // ImageSrcFragmentShader must be first in the list::
- ImageSrcFragmentShader,
- ImageSrcWithPatternFragmentShader,
- NonPremultipliedImageSrcFragmentShader,
- 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_ENUMS(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;
-*/
-
- QGLEngineSharedShaders(const QGLContext *context);
- ~QGLEngineSharedShaders();
-
- QGLShaderProgram *simpleProgram() { return simpleShaderProg; }
- QGLShaderProgram *blitProgram() { return blitShaderProg; }
- // Compile the program if it's not already in the cache, return the item in the cache.
- QGLEngineShaderProg *findProgramInCache(const QGLEngineShaderProg &prog);
- // Compile the custom shader if it's not already in the cache, return the item in the cache.
-
- static QGLEngineSharedShaders *shadersForContext(const QGLContext *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(QGLCustomShaderStage* stage);
-
-private:
- QGLShaderProgram *blitShaderProg;
- QGLShaderProgram *simpleShaderProg;
- QList<QGLEngineShaderProg*> cachedPrograms;
- QList<QGLShader *> shaders;
-
- static const char* qShaderSnippets[TotalSnippetCount];
-};
-
-
-class QGLEngineShaderProg
-{
-public:
- QGLEngineShaderProg() : program(nullptr) {}
-
- ~QGLEngineShaderProg() {
- if (program)
- delete program;
- }
-
- QGLEngineSharedShaders::SnippetName mainVertexShader;
- QGLEngineSharedShaders::SnippetName positionVertexShader;
- QGLEngineSharedShaders::SnippetName mainFragShader;
- QGLEngineSharedShaders::SnippetName srcPixelFragShader;
- QGLEngineSharedShaders::SnippetName maskFragShader;
- QGLEngineSharedShaders::SnippetName compositionFragShader;
-
- QByteArray customStageSource; //TODO: Decent cache key for custom stages
- QGLShaderProgram* program;
-
- QVector<uint> uniformLocations;
-
- bool useTextureCoords;
- bool useOpacityAttribute;
- bool usePmvMatrixAttribute;
-
- bool operator==(const QGLEngineShaderProg& 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_OPENGL_EXPORT QGLEngineShaderManager : public QObject
-{
- Q_OBJECT
-public:
- QGLEngineShaderManager(QGLContext* context);
- ~QGLEngineShaderManager();
-
- 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
- };
-
- enum Uniform {
- ImageTexture,
- PatternColor,
- GlobalOpacity,
- Depth,
- MaskTexture,
- FragmentColor,
- LinearData,
- Angle,
- HalfViewportSize,
- Fmp,
- Fmp2MRadius2,
- Inverse2Fmp2MRadius2,
- SqrFr,
- BRadius,
- InvertedTextureSize,
- BrushTransform,
- BrushTexture,
- Matrix,
- TranslateZ,
- 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(QGLCustomShaderStage* 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;
- }
-
- QGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen
- QGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers
- QGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer
-
- QGLEngineSharedShaders* sharedShaders;
-
-private:
- QGLContext* 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;
- QGLCustomShaderStage* customSrcStage;
-
- QGLEngineShaderProg* currentShaderProg;
-};
-
-QT_END_NAMESPACE
-
-#endif //QGLENGINE_SHADER_MANAGER_H
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
deleted file mode 100644
index a667af9b96..0000000000
--- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h
+++ /dev/null
@@ -1,523 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 QGL_ENGINE_SHADER_SOURCE_H
-#define QGL_ENGINE_SHADER_SOURCE_H
-
-#include "qglengineshadermanager_p.h"
-
-QT_BEGIN_NAMESPACE
-
-
-
-static const char* const qglslMainVertexShader = "\n\
- void setPosition(); \n\
- void main(void) \n\
- { \n\
- setPosition(); \n\
- }\n";
-
-static const char* const qglslMainWithTexCoordsVertexShader = "\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 qglslMainWithTexCoordsAndOpacityVertexShader = "\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 qglslPositionOnlyVertexShader = "\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 qglslComplexGeometryPositionOnlyVertexShader = "\n\
- uniform highp mat3 matrix; \n\
- uniform highp float translateZ; \n\
- attribute highp vec2 vertexCoordsArray; \n\
- void setPosition(void) \n\
- { \n\
- vec3 v = matrix * vec3(vertexCoordsArray, 1.0); \n\
- vec4 vz = mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, translateZ, 1) * vec4(v, 1.0); \n\
- gl_Position = vec4(vz.xyz, 1.0);\n\
- } \n";
-
-static const char* const qglslUntransformedPositionVertexShader = "\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 qglslPositionWithPatternBrushVertexShader = "\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 qglslAffinePositionWithPatternBrushVertexShader
- = qglslPositionWithPatternBrushVertexShader;
-
-static const char* const qglslPatternBrushSrcFragmentShader = "\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 qglslPositionWithLinearGradientBrushVertexShader = "\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 qglslAffinePositionWithLinearGradientBrushVertexShader
- = qglslPositionWithLinearGradientBrushVertexShader;
-
-static const char* const qglslLinearGradientBrushSrcFragmentShader = "\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 qglslPositionWithConicalGradientBrushVertexShader = "\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 qglslAffinePositionWithConicalGradientBrushVertexShader
- = qglslPositionWithConicalGradientBrushVertexShader;
-
-static const char* const qglslConicalGradientBrushSrcFragmentShader = "\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 qglslPositionWithRadialGradientBrushVertexShader = "\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 qglslAffinePositionWithRadialGradientBrushVertexShader
- = qglslPositionWithRadialGradientBrushVertexShader;
-
-static const char* const qglslRadialGradientBrushSrcFragmentShader = "\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 qglslPositionWithTextureBrushVertexShader = "\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 qglslAffinePositionWithTextureBrushVertexShader
- = qglslPositionWithTextureBrushVertexShader;
-
-// OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead,
-// we emulate GL_REPEAT by only taking the fractional part of the texture coords.
-// TODO: Special case POT textures which don't need this emulation
-static const char* const qglslTextureBrushSrcFragmentShader_ES = "\n\
- varying highp vec2 brushTextureCoords; \n\
- uniform sampler2D brushTexture; \n\
- lowp vec4 srcPixel() { \n\
- return texture2D(brushTexture, fract(brushTextureCoords)); \n\
- }\n";
-
-static const char* const qglslTextureBrushSrcFragmentShader_desktop = "\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 qglslTextureBrushSrcWithPatternFragmentShader = "\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 qglslSolidBrushSrcFragmentShader = "\n\
- uniform lowp vec4 fragmentColor; \n\
- lowp vec4 srcPixel() \n\
- { \n\
- return fragmentColor; \n\
- }\n";
-
-static const char* const qglslImageSrcFragmentShader = "\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 qglslCustomSrcFragmentShader = "\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 qglslImageSrcWithPatternFragmentShader = "\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 qglslNonPremultipliedImageSrcFragmentShader = "\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 qglslShockingPinkSrcFragmentShader = "\n\
- lowp vec4 srcPixel() \n\
- { \n\
- return vec4(0.98, 0.06, 0.75, 1.0); \n\
- }\n";
-
-static const char* const qglslMainFragmentShader_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 qglslMainFragmentShader_CMO = "\n\
- uniform lowp float globalOpacity; \n\
- lowp vec4 srcPixel(); \n\
- lowp vec4 applyMask(lowp vec4); \n\
- lowp vec4 compose(lowp vec4); \n\
- void main() \n\
- { \n\
- gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \n\
- }\n";
-
-static const char* const qglslMainFragmentShader_CM = "\n\
- lowp vec4 srcPixel(); \n\
- lowp vec4 applyMask(lowp vec4); \n\
- lowp vec4 compose(lowp vec4); \n\
- void main() \n\
- { \n\
- gl_FragColor = applyMask(compose(srcPixel())); \n\
- }\n";
-
-static const char* const qglslMainFragmentShader_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 qglslMainFragmentShader_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 qglslMainFragmentShader_CO = "\n\
- uniform lowp float globalOpacity; \n\
- lowp vec4 srcPixel(); \n\
- lowp vec4 compose(lowp vec4); \n\
- void main() \n\
- { \n\
- gl_FragColor = compose(srcPixel()*globalOpacity); \n\
- }\n";
-
-static const char* const qglslMainFragmentShader_C = "\n\
- lowp vec4 srcPixel(); \n\
- lowp vec4 compose(lowp vec4); \n\
- void main() \n\
- { \n\
- gl_FragColor = compose(srcPixel()); \n\
- }\n";
-
-static const char* const qglslMainFragmentShader_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 qglslMainFragmentShader = "\n\
- lowp vec4 srcPixel(); \n\
- void main() \n\
- { \n\
- gl_FragColor = srcPixel(); \n\
- }\n";
-
-static const char* const qglslMaskFragmentShader = "\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 qglslRgbMaskFragmentShaderPass1 = "\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 qglslRgbMaskFragmentShaderPass2 = "\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";
-
-/*
- Left to implement:
- RgbMaskFragmentShader,
- RgbMaskWithGammaFragmentShader,
-
- MultiplyCompositionModeFragmentShader,
- ScreenCompositionModeFragmentShader,
- OverlayCompositionModeFragmentShader,
- DarkenCompositionModeFragmentShader,
- LightenCompositionModeFragmentShader,
- ColorDodgeCompositionModeFragmentShader,
- ColorBurnCompositionModeFragmentShader,
- HardLightCompositionModeFragmentShader,
- SoftLightCompositionModeFragmentShader,
- DifferenceCompositionModeFragmentShader,
- ExclusionCompositionModeFragmentShader,
-*/
-
-QT_END_NAMESPACE
-
-#endif // GLGC_SHADER_SOURCE_H
diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp
deleted file mode 100644
index fc5e236ca6..0000000000
--- a/src/opengl/gl2paintengineex/qglgradientcache.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 "qglgradientcache_p.h"
-#include <private/qdrawhelper_p.h>
-#include <private/qgl_p.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qrandom.h>
-
-QT_BEGIN_NAMESPACE
-
-class QGL2GradientCacheWrapper
-{
-public:
- QGL2GradientCache *cacheForContext(const QGLContext *context) {
- QMutexLocker lock(&m_mutex);
- return m_resource.value<QGL2GradientCache>(context->contextHandle());
- }
-
-private:
- QOpenGLMultiGroupSharedResource m_resource;
- QMutex m_mutex;
-};
-
-Q_GLOBAL_STATIC(QGL2GradientCacheWrapper, qt_gradient_caches)
-
-QGL2GradientCache::QGL2GradientCache(QOpenGLContext *ctx)
- : QOpenGLSharedResource(ctx->shareGroup())
-{
-}
-
-QGL2GradientCache::~QGL2GradientCache()
-{
- cache.clear();
-}
-
-QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context)
-{
- return qt_gradient_caches()->cacheForContext(context);
-}
-
-void QGL2GradientCache::invalidateResource()
-{
- QMutexLocker lock(&m_mutex);
- cache.clear();
-}
-
-void QGL2GradientCache::freeResource(QOpenGLContext *)
-{
- cleanCache();
-}
-
-void QGL2GradientCache::cleanCache()
-{
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
- QMutexLocker lock(&m_mutex);
- QGLGradientColorTableHash::const_iterator it = cache.constBegin();
- for (; it != cache.constEnd(); ++it) {
- const CacheInfo &cache_info = it.value();
- funcs->glDeleteTextures(1, &cache_info.texId);
- }
- cache.clear();
-}
-
-GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity)
-{
- QMutexLocker lock(&m_mutex);
- 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();
-
- QGLGradientColorTableHash::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 QGL2GradientCache::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:
- QGLGradientColorTableHash::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());
- uint buffer[1024];
- generateGradientColorTable(gradient, buffer, paletteSize(), opacity);
- funcs->glGenTextures(1, &cache_entry.texId);
- funcs->glBindTexture(GL_TEXTURE_2D, cache_entry.texId);
- 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;
-}
-
-
-// GL's expects pixels in RGBA (when using GL_RGBA), bin-endian (ABGR on x86).
-// Qt always stores in ARGB reguardless of the byte-order the mancine uses.
-static inline uint qtToGlColor(uint c)
-{
- uint o;
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- o = (c & 0xff00ff00) // alpha & green already in the right place
- | ((c >> 16) & 0x000000ff) // red
- | ((c << 16) & 0x00ff0000); // blue
-#else //Q_BIG_ENDIAN
- o = (c << 8)
- | ((c >> 24) & 0x000000ff);
-#endif // Q_BYTE_ORDER
- return o;
-}
-
-//TODO: Let GL generate the texture using an FBO
-void QGL2GradientCache::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++] = qtToGlColor(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] = qtToGlColor(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
- else
- colorTable[pos] = qtToGlColor(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 = qtToGlColor(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/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/gl2paintengineex/qglgradientcache_p.h
deleted file mode 100644
index 3c9da982e9..0000000000
--- a/src/opengl/gl2paintengineex/qglgradientcache_p.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 QGLGRADIENTCACHE_P_H
-#define QGLGRADIENTCACHE_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 <QMultiHash>
-#include <QObject>
-#include <QtOpenGL/QtOpenGL>
-#include <private/qgl_p.h>
-#include <QtCore/qmutex.h>
-
-QT_BEGIN_NAMESPACE
-
-class QGL2GradientCache : public QOpenGLSharedResource
-{
- struct CacheInfo
- {
- inline CacheInfo(QGradientStops s, qreal op, QGradient::InterpolationMode mode) :
- stops(s), opacity(op), interpolationMode(mode) {}
-
- GLuint texId;
- QGradientStops stops;
- qreal opacity;
- QGradient::InterpolationMode interpolationMode;
- };
-
- typedef QMultiHash<quint64, CacheInfo> QGLGradientColorTableHash;
-
-public:
- static QGL2GradientCache *cacheForContext(const QGLContext *context);
-
- QGL2GradientCache(QOpenGLContext *);
- ~QGL2GradientCache();
-
- 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,
- uint *colorTable,
- int size, qreal opacity) const;
- GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity);
- void cleanCache();
-
- QGLGradientColorTableHash cache;
- QMutex m_mutex;
-};
-
-QT_END_NAMESPACE
-
-#endif // QGLGRADIENTCACHE_P_H
diff --git a/src/opengl/gl2paintengineex/qglshadercache_p.h b/src/opengl/gl2paintengineex/qglshadercache_p.h
deleted file mode 100644
index 4204e3e256..0000000000
--- a/src/opengl/gl2paintengineex/qglshadercache_p.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 QGLSHADERCACHE_P_H
-#define QGLSHADERCACHE_P_H
-
-#include <QtCore/qglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-
-class QGLShaderProgram;
-class QGLContext;
-
-class CachedShader
-{
-public:
- inline CachedShader(const QByteArray &, const QByteArray &)
- {}
-
- inline bool isCached()
- {
- return false;
- }
-
- inline bool load(QGLShaderProgram *, const QGLContext *)
- {
- return false;
- }
-
- inline bool store(QGLShaderProgram *, const QGLContext *)
- {
- return false;
- }
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
deleted file mode 100644
index 2546f6dc13..0000000000
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ /dev/null
@@ -1,2515 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 "qglgradientcache_p.h"
-#include "qpaintengineex_opengl2_p.h"
-
-#include <string.h> //for memcpy
-#include <qmath.h>
-
-#include <private/qgl_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 <QtGui/private/qtriangulator_p.h>
-
-#include "qglengineshadermanager_p.h"
-#include "qgl2pexvertexarray_p.h"
-#include "qtextureglyphcache_gl_p.h"
-
-#include <QDebug>
-
-#ifndef QT_OPENGL_ES_2
-# include <qopenglfunctions_1_1.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-
-
-Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
-
-////////////////////////////////// Private Methods //////////////////////////////////////////
-
-QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate()
-{
- delete shaderManager;
-
- while (pathCaches.size()) {
- QVectorPath::CacheEntry *e = *(pathCaches.constBegin());
- e->cleanup(e->engine, e->data);
- e->data = 0;
- e->engine = 0;
- }
-
- if (elementIndicesVBOId != 0) {
- glDeleteBuffers(1, &elementIndicesVBOId);
- elementIndicesVBOId = 0;
- }
-}
-
-void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id)
-{
-// glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit?
- if (id != GLuint(-1) && id == lastTextureUsed)
- return;
-
- lastTextureUsed = id;
-
- if (smoothPixmapTransform) {
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- } else {
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
- glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
-}
-
-
-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 QGL2PaintEngineExPrivate::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 (!currentBrushPixmap.isNull())
- currentBrushPixmap = QPixmap();
- 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(QGLEngineShaderManager::TextureSrcWithPattern);
- } else {
- shaderManager->setSrcPixelType(newStyle);
- }
- shaderManager->optimiseForBrushTransform(currentBrush.transform().type());
-}
-
-
-void QGL2PaintEngineExPrivate::useSimpleShader()
-{
- shaderManager->useSimpleProgram();
-
- if (matrixDirty)
- updateMatrix();
-}
-
-// ####TODO Properly #ifdef this class to use #define symbols actually defined
-// by OpenGL/ES includes
-#ifndef GL_MIRRORED_REPEAT_IBM
-#define GL_MIRRORED_REPEAT_IBM 0x8370
-#endif
-
-void QGL2PaintEngineExPrivate::updateBrushTexture()
-{
- Q_Q(QGL2PaintEngineEx);
-// qDebug("QGL2PaintEngineExPrivate::updateBrushTexture()");
- Qt::BrushStyle style = currentBrush.style();
-
- if ( (style >= Qt::Dense1Pattern) && (style <= Qt::DiagCrossPattern) ) {
- // Get the image data for the pattern
- QImage texImage = qt_imageForBrush(style, false);
-
- glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption);
- updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
- }
- else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
- // Gradiant brush: All the gradiants use the same texture
-
- const QGradient* g = currentBrush.gradient();
-
- // We apply global opacity in the fragment shaders, so we always pass 1.0
- // for opacity to the cache.
- GLuint texId = QGL2GradientCache::cacheForContext(ctx)->getBuffer(*g, 1.0);
-
- glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- glBindTexture(GL_TEXTURE_2D, texId);
-
- if (g->spread() == QGradient::RepeatSpread || g->type() == QGradient::ConicalGradient)
- updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
- else if (g->spread() == QGradient::ReflectSpread)
- updateTextureFilter(GL_TEXTURE_2D, GL_MIRRORED_REPEAT_IBM, q->state()->renderHints & QPainter::SmoothPixmapTransform);
- else
- updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform);
- }
- else if (style == Qt::TexturePattern) {
- currentBrushPixmap = currentBrush.texture();
-
- int max_texture_size = ctx->d_func()->maxTextureSize();
- if (currentBrushPixmap.width() > max_texture_size || currentBrushPixmap.height() > max_texture_size)
- currentBrushPixmap = currentBrushPixmap.scaled(max_texture_size, max_texture_size, Qt::KeepAspectRatio);
-
- GLuint wrapMode = GL_REPEAT;
- if (ctx->contextHandle()->isOpenGLES()) {
- // OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead,
- // we emulate GL_REPEAT by only taking the fractional part of the texture coords
- // in the qopenglslTextureBrushSrcFragmentShader program.
- wrapMode = GL_CLAMP_TO_EDGE;
- }
-
- glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
- QGLTexture *tex = ctx->d_func()->bindTexture(currentBrushPixmap, GL_TEXTURE_2D, GL_RGBA,
- QGLContext::InternalBindOption |
- QGLContext::CanFlipNativePixmapBindOption);
- updateTextureFilter(GL_TEXTURE_2D, wrapMode, q->state()->renderHints & QPainter::SmoothPixmapTransform);
- textureInvertedY = tex->options & QGLContext::InvertedYBindOption ? -1 : 1;
- }
- brushTextureDirty = false;
-}
-
-
-void QGL2PaintEngineExPrivate::updateBrushUniforms()
-{
-// qDebug("QGL2PaintEngineExPrivate::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(QGLEngineShaderManager::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(QGLEngineShaderManager::PatternColor), col);
-
- QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::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(QGLEngineShaderManager::LinearData), linearData);
-
- QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::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(QGLEngineShaderManager::Angle), angle);
-
- QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::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(QGLEngineShaderManager::Fmp), fmp);
-
- GLfloat fmp2_m_radius2 = -fmp.x() * fmp.x() - fmp.y() * fmp.y() + realRadius*realRadius;
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Fmp2MRadius2), fmp2_m_radius2);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Inverse2Fmp2MRadius2),
- GLfloat(1.0 / (2.0*fmp2_m_radius2)));
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::SqrFr),
- GLfloat(g->focalRadius() * g->focalRadius()));
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::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(QGLEngineShaderManager::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(QGLEngineShaderManager::PatternColor), col);
- }
-
- QSizeF invertedTextureSize(1.0 / texPixmap.width(), 1.0 / texPixmap.height());
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::InvertedTextureSize), invertedTextureSize);
-
- QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
- }
- else
- qWarning("QGL2PaintEngineEx: 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->isFlipped()) {
- m22 = 1;
- dy = 0;
- }
- QTransform gl_to_qt(1, 0, 0, m22, 0, dy);
- QTransform inv_matrix;
- if (style == Qt::TexturePattern && textureInvertedY == -1)
- inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush.texture().height()) * brushQTransform * matrix).inverted() * translate;
- else
- inv_matrix = gl_to_qt * (brushQTransform * matrix).inverted() * translate;
-
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BrushTransform), inv_matrix);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BrushTexture), QT_BRUSH_TEXTURE_UNIT);
- }
- brushUniformsDirty = false;
-}
-
-
-// This assumes the shader manager has already setup the correct shader program
-void QGL2PaintEngineExPrivate::updateMatrix()
-{
-// qDebug("QGL2PaintEngineExPrivate::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->isFlipped()) {
- 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.
- glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]);
- glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]);
- glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]);
-
- dasher.setInvScale(inverseScale);
- stroker.setInvScale(inverseScale);
-}
-
-
-void QGL2PaintEngineExPrivate::updateCompositionMode()
-{
- // NOTE: The entire paint engine works on pre-multiplied data - which is why some of these
- // composition modes look odd.
-// qDebug() << "QGL2PaintEngineExPrivate::updateCompositionMode() - Setting GL composition mode for " << q->state()->composition_mode;
- switch(q->state()->composition_mode) {
- case QPainter::CompositionMode_SourceOver:
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- break;
- case QPainter::CompositionMode_DestinationOver:
- glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
- break;
- case QPainter::CompositionMode_Clear:
- glBlendFunc(GL_ZERO, GL_ZERO);
- break;
- case QPainter::CompositionMode_Source:
- glBlendFunc(GL_ONE, GL_ZERO);
- break;
- case QPainter::CompositionMode_Destination:
- glBlendFunc(GL_ZERO, GL_ONE);
- break;
- case QPainter::CompositionMode_SourceIn:
- glBlendFunc(GL_DST_ALPHA, GL_ZERO);
- break;
- case QPainter::CompositionMode_DestinationIn:
- glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
- break;
- case QPainter::CompositionMode_SourceOut:
- glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);
- break;
- case QPainter::CompositionMode_DestinationOut:
- glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
- break;
- case QPainter::CompositionMode_SourceAtop:
- glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- break;
- case QPainter::CompositionMode_DestinationAtop:
- glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA);
- break;
- case QPainter::CompositionMode_Xor:
- glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- break;
- case QPainter::CompositionMode_Plus:
- glBlendFunc(GL_ONE, GL_ONE);
- break;
- default:
- qWarning("Unsupported composition mode");
- break;
- }
-
- compositionModeDirty = false;
-}
-
-static inline void setCoords(GLfloat *coords, const QGLRect &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 QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern)
-{
- // Setup for texture drawing
- currentBrush = noBrush;
- shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
-
- if (snapToPixelGrid) {
- snapToPixelGrid = false;
- matrixDirty = true;
- }
-
- if (prepareForDraw(opaque))
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
-
- if (pattern) {
- QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
- }
-
- GLfloat dx = 1.0 / textureSize.width();
- GLfloat dy = 1.0 / textureSize.height();
-
- QGLRect srcTextureRect(src.left*dx, src.top*dy, src.right*dx, src.bottom*dy);
-
- setCoords(staticVertexCoordinateArray, dest);
- setCoords(staticTextureCoordinateArray, srcTextureRect);
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-}
-
-void QGL2PaintEngineEx::beginNativePainting()
-{
- Q_D(QGL2PaintEngineEx);
- ensureActive();
- d->transferMode(BrushDrawingMode);
-
- d->nativePaintingActive = true;
-
- d->glUseProgram(0);
-
- // Disable all the vertex attribute arrays:
- for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
- d->glDisableVertexAttribArray(i);
-
-#ifndef QT_OPENGL_ES_2
- if (!d->ctx->contextHandle()->isOpenGLES()) {
- const QGLContext *ctx = d->ctx;
- const QGLFormat &fmt = d->device->format();
- if (fmt.majorVersion() < 3 || (fmt.majorVersion() == 3 && fmt.minorVersion() < 1)
- || (fmt.majorVersion() == 3 && fmt.minorVersion() == 1 && ctx->contextHandle()->hasExtension(QByteArrayLiteral("GL_ARB_compatibility")))
- || fmt.profile() == QGLFormat::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();
-
- QOpenGLFunctions_1_1 *gl1funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_1>();
- gl1funcs->initializeOpenGLFunctions();
-
- gl1funcs->glMatrixMode(GL_PROJECTION);
- gl1funcs->glLoadIdentity();
- gl1funcs->glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999);
-
- gl1funcs->glMatrixMode(GL_MODELVIEW);
- gl1funcs->glLoadMatrixf(&mv_matrix[0][0]);
- }
- }
-#endif
-
- d->lastTextureUsed = GLuint(-1);
- d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
- d->resetGLState();
-
- d->shaderManager->setDirty();
-
- d->needsSync = true;
-}
-
-void QGL2PaintEngineExPrivate::resetGLState()
-{
- glDisable(GL_BLEND);
- glActiveTexture(GL_TEXTURE0);
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
- glDepthMask(true);
- glDepthFunc(GL_LESS);
- glClearDepthf(1);
- glStencilMask(0xff);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glStencilFunc(GL_ALWAYS, 0, 0xff);
- ctx->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false);
- ctx->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, false);
- ctx->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
-#ifndef QT_OPENGL_ES_2
- if (!ctx->contextHandle()->isOpenGLES()) {
- // gl_Color, corresponding to vertex attribute 3, may have been changed
- float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
- glVertexAttrib4fv(3, color);
- }
-#endif
-}
-
-bool QGL2PaintEngineExPrivate::resetOpenGLContextActiveEngine()
-{
- QOpenGLContext *guiGlContext = ctx->contextHandle();
- QOpenGLContextPrivate *guiGlContextPrivate =
- guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
-
- if (guiGlContextPrivate && guiGlContextPrivate->active_engine) {
- ctx->d_func()->refreshCurrentFbo();
- guiGlContextPrivate->active_engine = 0;
- return true;
- }
-
- return false;
-}
-
-void QGL2PaintEngineEx::endNativePainting()
-{
- Q_D(QGL2PaintEngineEx);
- d->needsSync = true;
- d->nativePaintingActive = false;
-}
-
-void QGL2PaintEngineEx::invalidateState()
-{
- Q_D(QGL2PaintEngineEx);
- d->needsSync = true;
-}
-
-bool QGL2PaintEngineEx::isNativePaintingActive() const {
- Q_D(const QGL2PaintEngineEx);
- return d->nativePaintingActive;
-}
-
-bool QGL2PaintEngineEx::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 QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
-{
- if (newMode == mode)
- return;
-
- if (mode == TextDrawingMode || mode == ImageDrawingMode || mode == ImageArrayDrawingMode) {
- lastTextureUsed = GLuint(-1);
- }
-
- if (newMode == TextDrawingMode) {
- shaderManager->setHasComplexGeometry(true);
- } else {
- shaderManager->setHasComplexGeometry(false);
- }
-
- if (newMode == ImageDrawingMode) {
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray);
- setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, staticTextureCoordinateArray);
- }
-
- if (newMode == ImageArrayDrawingMode) {
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data());
- setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data());
- setVertexAttributePointer(QT_OPACITY_ATTR, (GLfloat*)opacityArray.data());
- }
-
- // This needs to change when we implement high-quality anti-aliasing...
- if (newMode != TextDrawingMode)
- shaderManager->setMaskType(QGLEngineShaderManager::NoMask);
-
- mode = newMode;
-}
-
-struct QGL2PEVectorPathCache
-{
-#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 QGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data)
-{
- QGL2PEVectorPathCache *c = (QGL2PEVectorPathCache *) data;
-#ifdef QT_OPENGL_CACHE_AS_VBOS
- Q_ASSERT(engine->type() == QPaintEngine::OpenGL2);
- static_cast<QGL2PaintEngineEx *>(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 QGL2PaintEngineExPrivate::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 QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
-
- // Check to see if there's any hints
- if (path.shape() == QVectorPath::RectangleHint) {
- QGLRect 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);
- QGL2PEVectorPathCache *cache;
-
- bool updateCache = false;
-
- if (data) {
- cache = (QGL2PEVectorPathCache *) data->data;
- // Check if scale factor is exceeded for curved paths and generate curves if so...
- if (path.isCurved()) {
- 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 == 0);
-#endif
- updateCache = true;
- }
- }
- } else {
- cache = new QGL2PEVectorPathCache;
- 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
- glGenBuffers(1, &cache->vbo);
- glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
- 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 = 0;
-#endif
- }
-
- prepareForDraw(currentBrush.isOpaque());
-#ifdef QT_OPENGL_CACHE_AS_VBOS
- glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0);
-#else
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, cache->vertices);
-#endif
- 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);
- QGL2PEVectorPathCache *cache;
-
- bool updateCache = false;
-
- if (data) {
- cache = (QGL2PEVectorPathCache *) data->data;
- // Check if scale factor is exceeded for curved paths and generate curves if so...
- if (path.isCurved()) {
- 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 QGL2PEVectorPathCache;
- 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));
- 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
- glGenBuffers(1, &cache->vbo);
- glGenBuffers(1, &cache->ibo);
- glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo);
-
- if (polys.indices.type() == QVertexIndexVector::UnsignedInt)
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint32) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW);
- else
- 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));
- 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
- glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo);
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0);
- if (cache->indexType == QVertexIndexVector::UnsignedInt)
- glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, 0);
- else
- glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-#else
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, cache->vertices);
- if (cache->indexType == QVertexIndexVector::UnsignedInt)
- glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, (qint32 *)cache->indices);
- else
- glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, (qint16 *)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->format().stencil()) {
- // 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));
-
- 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());
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, vertices.constData());
- if (polys.indices.type() == QVertexIndexVector::UnsignedInt)
- glDrawElements(GL_TRIANGLES, polys.indices.size(), GL_UNSIGNED_INT, polys.indices.data());
- else
- glDrawElements(GL_TRIANGLES, polys.indices.size(), GL_UNSIGNED_SHORT, 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());
-
- glStencilMask(0xff);
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
-
- if (q->state()->clipTestEnabled) {
- // Pass when high bit is set, replace stencil value with current clip
- 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
- glStencilFunc(GL_NOTEQUAL, 0, 0xff);
- } else {
- // Pass when high bit is set, replace stencil value with 0
- glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
- }
- prepareForDraw(currentBrush.isOpaque());
-
- // Stencil the brush onto the dest buffer
- composite(vertexCoordinateArray.boundingRect());
- glStencilMask(0);
- updateClipScissorTest();
- }
- }
-}
-
-
-void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data,
- int count,
- int *stops,
- int stopCount,
- const QGLRect &bounds,
- StencilFillMode mode)
-{
- Q_ASSERT(count || stops);
-
-// qDebug("QGL2PaintEngineExPrivate::fillStencilWithVertexArray()");
- glStencilMask(0xff); // Enable stencil writes
-
- if (dirtyStencilRegion.intersects(currentScissorBounds)) {
- const QRegion clearRegion = dirtyStencilRegion.intersected(currentScissorBounds);
- glClearStencil(0); // Clear to zero
- for (const QRect &rect : clearRegion) {
-#ifndef QT_GL_NO_SCISSOR_TEST
- setScissor(rect);
-#endif
- glClear(GL_STENCIL_BUFFER_BIT);
- }
-
- dirtyStencilRegion -= currentScissorBounds;
-
-#ifndef QT_GL_NO_SCISSOR_TEST
- updateClipScissorTest();
-#endif
- }
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
- useSimpleShader();
- 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
- glStencilFunc(GL_LEQUAL, GL_STENCIL_HIGH_BIT | q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
- composite(bounds);
-
- glStencilFunc(GL_EQUAL, GL_STENCIL_HIGH_BIT, GL_STENCIL_HIGH_BIT);
- } else if (!stencilClean) {
- // Clear stencil buffer within bounding rect
- glStencilFunc(GL_ALWAYS, 0, 0xff);
- glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
- composite(bounds);
- }
-
- // Inc. for front-facing triangle
- glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP);
- // Dec. for back-facing "holes"
- glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_DECR_WRAP);
- glStencilMask(~GL_STENCIL_HIGH_BIT);
- drawVertexArrays(data, stops, stopCount, GL_TRIANGLE_FAN);
-
- if (q->state()->clipTestEnabled) {
- // Clear high bit of stencil outside of path
- glStencilFunc(GL_EQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
- glStencilMask(GL_STENCIL_HIGH_BIT);
- composite(bounds);
- }
- } else if (mode == OddEvenFillMode) {
- glStencilMask(GL_STENCIL_HIGH_BIT);
- 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
- glStencilMask(GL_STENCIL_HIGH_BIT);
-#if 0
- glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, data);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
-#else
-
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- if (q->state()->clipTestEnabled) {
- glStencilFunc(GL_LEQUAL, q->state()->currentClip | GL_STENCIL_HIGH_BIT,
- ~GL_STENCIL_HIGH_BIT);
- } else {
- glStencilFunc(GL_ALWAYS, GL_STENCIL_HIGH_BIT, 0xff);
- }
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, data);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
-#endif
- }
-
- // Enable color writes & disable stencil writes
- 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 QGL2PaintEngineExPrivate::resetClipIfNeeded()
-{
- if (maxClip != (GL_STENCIL_HIGH_BIT - 1))
- return;
-
- Q_Q(QGL2PaintEngineEx);
-
- useSimpleShader();
- glEnable(GL_STENCIL_TEST);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- QRectF bounds = q->state()->matrix.inverted().mapRect(QRectF(0, 0, width, height));
- QGLRect rect(bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
-
- // Set high bit on clip region
- glStencilFunc(GL_LEQUAL, q->state()->currentClip, 0xff);
- glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT);
- glStencilMask(GL_STENCIL_HIGH_BIT);
- composite(rect);
-
- // Reset clipping to 1 and everything else to zero
- glStencilFunc(GL_NOTEQUAL, 0x01, GL_STENCIL_HIGH_BIT);
- glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE);
- glStencilMask(0xff);
- composite(rect);
-
- q->state()->currentClip = 1;
- q->state()->canRestoreClip = false;
-
- maxClip = 1;
-
- glStencilMask(0x0);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-}
-
-bool QGL2PaintEngineExPrivate::prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache)
-{
- Q_Q(QGL2PaintEngineEx);
-
- 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 QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
-{
- if (brushTextureDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
- 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))
- {
- glDisable(GL_BLEND);
- } else {
- glEnable(GL_BLEND);
- }
-
- QGLEngineShaderManager::OpacityMode opacityMode;
- if (mode == ImageArrayDrawingMode) {
- opacityMode = QGLEngineShaderManager::AttributeOpacity;
- } else {
- opacityMode = stateHasOpacity ? QGLEngineShaderManager::UniformOpacity
- : QGLEngineShaderManager::NoOpacity;
- if (stateHasOpacity && (mode != ImageDrawingMode)) {
- // Using a brush
- bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) &&
- (currentBrush.style() <= Qt::DiagCrossPattern);
-
- if ((currentBrush.style() == Qt::SolidPattern) || brushIsPattern)
- opacityMode = QGLEngineShaderManager::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;
- translateZUniformDirty = true;
- }
-
- if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
- updateBrushUniforms();
-
- if (opacityMode == QGLEngineShaderManager::UniformOpacity && opacityUniformDirty) {
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity);
- opacityUniformDirty = false;
- }
-
- if (matrixUniformDirty && shaderManager->hasComplexGeometry()) {
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Matrix),
- pmvMatrix);
- matrixUniformDirty = false;
- }
-
- if (translateZUniformDirty && shaderManager->hasComplexGeometry()) {
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::TranslateZ),
- translateZ);
- translateZUniformDirty = false;
- }
-
- return changed;
-}
-
-void QGL2PaintEngineExPrivate::composite(const QGLRect& boundingRect)
-{
- setCoords(staticVertexCoordinateArray, boundingRect);
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-}
-
-// Draws the vertex array as a set of <vertexArrayStops.size()> triangle fans.
-void QGL2PaintEngineExPrivate::drawVertexArrays(const float *data, int *stops, int stopCount,
- GLenum primitive)
-{
- // Now setup the pointer to the vertex array:
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, data);
-
- int previousStop = 0;
- for (int i=0; i<stopCount; ++i) {
- int stop = stops[i];
-/*
- qDebug("Drawing triangle fan for vertecies %d -> %d:", previousStop, stop-1);
- for (int i=previousStop; i<stop; ++i)
- qDebug(" %02d: [%.2f, %.2f]", i, vertexArray.data()[i].x, vertexArray.data()[i].y);
-*/
- glDrawArrays(primitive, previousStop, stop - previousStop);
- previousStop = stop;
- }
-}
-
-/////////////////////////////////// Public Methods //////////////////////////////////////////
-
-QGL2PaintEngineEx::QGL2PaintEngineEx()
- : QPaintEngineEx(*(new QGL2PaintEngineExPrivate(this)))
-{
-}
-
-QGL2PaintEngineEx::~QGL2PaintEngineEx()
-{
-}
-
-void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
-{
- Q_D(QGL2PaintEngineEx);
-
- 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 QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
-{
- Q_D(QGL2PaintEngineEx);
-
- const QBrush &penBrush = qpen_brush(pen);
- if (qpen_style(pen) == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush)
- return;
-
- QGL2PaintEngineState *s = state();
- if (qt_pen_is_cosmetic(pen, s->renderHints) && !qt_scaleForTransform(s->transform(), 0)) {
- // QTriangulatingStroker class is not meant to support cosmetically sheared strokes.
- QPaintEngineEx::stroke(path, pen);
- return;
- }
-
- ensureActive();
- d->setBrush(penBrush);
- d->stroke(path, pen);
-}
-
-void QGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen)
-{
- const QGL2PaintEngineState *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);
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, stroker.vertices());
- glDrawArrays(GL_TRIANGLE_STRIP, 0, stroker.vertexCount() / 2);
-
-// QBrush b(Qt::green);
-// d->setBrush(&b);
-// d->prepareForDraw(true);
-// glDrawArrays(GL_LINE_STRIP, 0, d->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, s->renderHints))
- extra = extra * inverseScale;
-
- QRectF bounds = path.controlPointRect().adjusted(-extra, -extra, extra, extra);
-
- fillStencilWithVertexArray(stroker.vertices(), stroker.vertexCount() / 2,
- 0, 0, bounds, QGL2PaintEngineExPrivate::TriStripStrokeFillMode);
-
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
-
- // Pass when any bit is set, replace stencil value with 0
- glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
- prepareForDraw(false);
-
- // Stencil the brush onto the dest buffer
- composite(bounds);
-
- glStencilMask(0);
-
- updateClipScissorTest();
- }
-}
-
-void QGL2PaintEngineEx::penChanged() { }
-void QGL2PaintEngineEx::brushChanged() { }
-void QGL2PaintEngineEx::brushOriginChanged() { }
-
-void QGL2PaintEngineEx::opacityChanged()
-{
-// qDebug("QGL2PaintEngineEx::opacityChanged()");
- Q_D(QGL2PaintEngineEx);
- state()->opacityChanged = true;
-
- Q_ASSERT(d->shaderManager);
- d->brushUniformsDirty = true;
- d->opacityUniformDirty = true;
-}
-
-void QGL2PaintEngineEx::compositionModeChanged()
-{
-// qDebug("QGL2PaintEngineEx::compositionModeChanged()");
- Q_D(QGL2PaintEngineEx);
- state()->compositionModeChanged = true;
- d->compositionModeDirty = true;
-}
-
-void QGL2PaintEngineEx::renderHintsChanged()
-{
- Q_D(QGL2PaintEngineEx);
- state()->renderHintsChanged = true;
-
-#if !defined(QT_OPENGL_ES_2)
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- if (!d->ctx->contextHandle()->isOpenGLES()) {
- if ((state()->renderHints & QPainter::Antialiasing)
-#if QT_DEPRECATED_SINCE(5, 14)
- || (state()->renderHints & QPainter::HighQualityAntialiasing)
-#endif
- )
- d->glEnable(GL_MULTISAMPLE);
- else
- d->glDisable(GL_MULTISAMPLE);
- }
-QT_WARNING_POP
-#endif
-
- d->lastTextureUsed = GLuint(-1);
- d->brushTextureDirty = true;
-// qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!");
-}
-
-void QGL2PaintEngineEx::transformChanged()
-{
- Q_D(QGL2PaintEngineEx);
- 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 QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src)
-{
- Q_D(QGL2PaintEngineEx);
- QGLContext *ctx = d->ctx;
-
- 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);
-
- QGLContext::BindOptions bindOptions = QGLContext::InternalBindOption|QGLContext::CanFlipNativePixmapBindOption;
-#ifdef QGL_USE_TEXTURE_POOL
- bindOptions |= QGLContext::TemporarilyCachedBindOption;
-#endif
-
- d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QGLTexture *texture =
- ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, bindOptions);
-
- GLfloat top = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.top()) : src.top();
- GLfloat bottom = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.bottom()) : src.bottom();
- QGLRect srcRect(src.left(), top, src.right(), bottom);
-
- bool isBitmap = pixmap.isQBitmap();
- bool isOpaque = !isBitmap && !pixmap.hasAlpha();
-
- d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
- d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap);
-
- if (texture->options&QGLContext::TemporarilyCachedBindOption) {
- // pixmap was temporarily cached as a QImage texture by pooling system
- // and should be destroyed immediately
- QGLTextureCache::instance()->remove(ctx, texture->id);
- }
-}
-
-void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src,
- Qt::ImageConversionFlags)
-{
- Q_D(QGL2PaintEngineEx);
- QGLContext *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);
-
- d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
-
- QGLContext::BindOptions bindOptions = QGLContext::InternalBindOption;
-#ifdef QGL_USE_TEXTURE_POOL
- bindOptions |= QGLContext::TemporarilyCachedBindOption;
-#endif
-
- QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, bindOptions);
- GLuint id = texture->id;
-
- d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- state()->renderHints & QPainter::SmoothPixmapTransform, id);
- d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel());
-
- if (texture->options&QGLContext::TemporarilyCachedBindOption) {
- // image was temporarily cached by texture pooling system
- // and should be destroyed immediately
- QGLTextureCache::instance()->remove(ctx, texture->id);
- }
-}
-
-void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem)
-{
- Q_D(QGL2PaintEngineEx);
-
- ensureActive();
-
- QPainterState *s = state();
-
- // don't try to cache huge fonts or vastly transformed fonts
- 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 (!QGLFramebufferObject::hasOpenGLFramebufferObjects()
- || d->device->alphaRequested() || 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 QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src)
-{
- Q_D(QGL2PaintEngineEx);
- if (!d->shaderManager)
- return false;
-
- ensureActive();
- d->transferMode(ImageDrawingMode);
-
- d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- d->glBindTexture(GL_TEXTURE_2D, textureId);
-
- QGLRect srcRect(src.left(), src.bottom(), src.right(), src.top());
-
- d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- state()->renderHints & QPainter::SmoothPixmapTransform, textureId);
- d->drawTexture(dest, srcRect, size, false);
- return true;
-}
-
-void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem)
-{
- Q_D(QGL2PaintEngineEx);
-
- ensureActive();
- QGL2PaintEngineState *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 (!QGLFramebufferObject::hasOpenGLFramebufferObjects()
- || d->device->alphaRequested() || 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;
- QGL2PEXVertexArray vertexCoordinateArray;
- QGL2PEXVertexArray textureCoordinateArray;
- QFontEngine::GlyphFormat glyphFormat;
- int cacheSerialNumber;
- };
-
-}
-
-
-// #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO
-
-void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat,
- QStaticTextItem *staticTextItem)
-{
- Q_Q(QGL2PaintEngineEx);
-
- QGL2PaintEngineState *s = q->state();
-
- void *cacheKey = const_cast<QGLContext *>(QGLContextPrivate::contextGroup(ctx)->context());
- 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());
- }
-
- QGLTextureGlyphCache *cache =
- (QGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphFormat, glyphCacheTransform);
- if (!cache || cache->glyphFormat() != glyphFormat || cache->contextGroup() == 0) {
- cache = new QGLTextureGlyphCache(glyphFormat, glyphCacheTransform);
- fe->setGlyphCache(cacheKey, cache);
- recreateVertexArrays = true;
- }
-
- if (staticTextItem->userDataNeedsUpdate) {
- recreateVertexArrays = true;
- } else if (staticTextItem->userData() == 0) {
- 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);
- }
- cache->fillInPendingGlyphs();
- }
-
- if (cache->width() == 0 || cache->height() == 0)
- return;
-
- transferMode(TextDrawingMode);
-
- int margin = fe->glyphMargin(glyphFormat);
-
- GLfloat dx = 1.0 / cache->width();
- GLfloat dy = 1.0 / cache->height();
-
- // Use global arrays by default
- QGL2PEXVertexArray *vertexCoordinates = &vertexCoordinateArray;
- QGL2PEXVertexArray *textureCoordinates = &textureCoordinateArray;
-
- if (staticTextItem->useBackendOptimizations) {
- QOpenGLStaticTextUserData *userData = 0;
-
- if (staticTextItem->userData() == 0
- || 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)
- glGenBuffers(1, &elementIndicesVBOId);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementIndices.size() * sizeof(GLushort),
- elementIndices.constData(), GL_STATIC_DRAW);
-#endif
- } else {
-#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId);
-#endif
- }
-
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data());
- setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data());
-
- 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(QGLEngineShaderManager::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;
- }
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
- 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);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
-
- glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
- glBindTexture(GL_TEXTURE_2D, cache->texture());
- updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
-
-#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
- glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
-#else
- glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
-#endif
-
- shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass2);
-
- if (compMode == QPainter::CompositionMode_Source) {
- q->state()->opacity = oldOpacity;
- opacityUniformDirty = true;
- pensBrush = q->state()->pen.brush();
- setBrush(pensBrush);
- }
-
- compositionModeDirty = false;
- prepareForCachedGlyphDraw(*cache);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
- }
- compositionModeDirty = true;
- } else {
- // Grayscale/mono glyphs
-
- shaderManager->setMaskType(QGLEngineShaderManager::PixelMask);
- prepareForCachedGlyphDraw(*cache);
- }
-
- QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest;
- if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) {
-
- glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
- if (lastMaskTextureUsed != cache->texture()) {
- glBindTexture(GL_TEXTURE_2D, cache->texture());
- lastMaskTextureUsed = cache->texture();
- }
-
- if (cache->filterMode() != filterMode) {
- if (filterMode == QGLTextureGlyphCache::Linear) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- } else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
- cache->setFilterMode(filterMode);
- }
- }
-
-#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
- glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-#else
- glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
-#endif
-}
-
-void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
- QPainter::PixmapFragmentHints hints)
-{
- Q_D(QGL2PaintEngineEx);
- // 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 QGL2PaintEngineExPrivate::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;
- QGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c);
- QGLPoint 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);
-
- QGLRect 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);
- }
-
- glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA,
- QGLContext::InternalBindOption
- | QGLContext::CanFlipNativePixmapBindOption);
-
- if (texture->options & QGLContext::InvertedYBindOption) {
- // Flip texture y-coordinate.
- QGLPoint *data = textureCoordinateArray.data();
- for (int i = 0; i < 6 * fragmentCount; ++i)
- data[i].y = 1 - data[i].y;
- }
-
- transferMode(ImageArrayDrawingMode);
-
- bool isBitmap = pixmap.isQBitmap();
- bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque;
-
- updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- q->state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
-
- // Setup for texture drawing
- currentBrush = noBrush;
- shaderManager->setSrcPixelType(isBitmap ? QGLEngineShaderManager::PatternSrc
- : QGLEngineShaderManager::ImageSrc);
- if (prepareForDraw(isOpaque))
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
-
- if (isBitmap) {
- QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
- }
-
- glDrawArrays(GL_TRIANGLES, 0, 6 * fragmentCount);
-}
-
-bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
-{
- Q_D(QGL2PaintEngineEx);
-
-// qDebug("QGL2PaintEngineEx::begin()");
- if (pdev->devType() == QInternal::OpenGL)
- d->device = static_cast<QGLPaintDevice*>(pdev);
- else
- d->device = QGLPaintDevice::getDevice(pdev);
-
- if (!d->device)
- return false;
-
- d->ctx = d->device->context();
- d->ctx->d_ptr->active_engine = this;
-
- d->resetOpenGLContextActiveEngine();
-
- 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->translateZUniformDirty = true;
- d->needsSync = true;
- d->useSystemClip = !systemClip().isEmpty();
- d->currentBrush = QBrush();
-
- d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
- d->stencilClean = true;
-
- // Calling begin paint should make the correct context current. So, any
- // code which calls into GL or otherwise needs a current context *must*
- // go after beginPaint:
- d->device->beginPaint();
-
- d->initializeOpenGLFunctions();
-
- d->shaderManager = new QGLEngineShaderManager(d->ctx);
-
- d->glDisable(GL_STENCIL_TEST);
- d->glDisable(GL_DEPTH_TEST);
- d->glDisable(GL_SCISSOR_TEST);
-
-#if !defined(QT_OPENGL_ES_2)
- if (!d->ctx->contextHandle()->isOpenGLES())
- d->glDisable(GL_MULTISAMPLE);
-#endif
-
- d->glyphCacheFormat = QFontEngine::Format_A8;
-
-#if !defined(QT_OPENGL_ES_2)
- if (!d->ctx->contextHandle()->isOpenGLES()) {
- d->glyphCacheFormat = QFontEngine::Format_A32;
- d->multisamplingAlwaysEnabled = false;
- } else {
- d->multisamplingAlwaysEnabled = d->device->format().sampleBuffers();
- }
-#else
- // OpenGL ES can't switch MSAA off, so if the gl paint device is
- // multisampled, it's always multisampled.
- d->multisamplingAlwaysEnabled = d->device->format().sampleBuffers();
-#endif
-
- return true;
-}
-
-bool QGL2PaintEngineEx::end()
-{
- Q_D(QGL2PaintEngineEx);
-
- QGLContext *ctx = d->ctx;
- d->glUseProgram(0);
- d->transferMode(BrushDrawingMode);
- d->device->endPaint();
-
- ctx->d_ptr->active_engine = 0;
- ctx->makeCurrent();
- d->resetOpenGLContextActiveEngine();
- d->resetGLState();
-
- delete d->shaderManager;
- d->shaderManager = 0;
- d->currentBrush = QBrush();
-
-#ifdef QT_OPENGL_CACHE_AS_VBOS
- if (!d->unusedVBOSToClean.isEmpty()) {
- d->glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData());
- d->unusedVBOSToClean.clear();
- }
- if (!d->unusedIBOSToClean.isEmpty()) {
- d->glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData());
- d->unusedIBOSToClean.clear();
- }
-#endif
-
- return false;
-}
-
-void QGL2PaintEngineEx::ensureActive()
-{
- Q_D(QGL2PaintEngineEx);
- QGLContext *ctx = d->ctx;
-
- if (isActive() && (ctx->d_ptr->active_engine != this || d->resetOpenGLContextActiveEngine())) {
- ctx->d_ptr->active_engine = this;
- d->needsSync = true;
- }
-
- d->device->ensureActiveTarget();
-
- if (d->needsSync) {
- d->transferMode(BrushDrawingMode);
- d->glViewport(0, 0, d->width, d->height);
- d->needsSync = false;
- d->lastMaskTextureUsed = 0;
- d->shaderManager->setDirty();
- d->ctx->d_func()->syncGlState();
- for (int i = 0; i < 3; ++i)
- d->vertexAttribPointers[i] = (GLfloat*)-1; // Assume the pointers are clobbered
- setState(state());
- }
-}
-
-void QGL2PaintEngineExPrivate::updateClipScissorTest()
-{
- Q_Q(QGL2PaintEngineEx);
- if (q->state()->clipTestEnabled) {
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
- } else {
- glDisable(GL_STENCIL_TEST);
- 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)) {
- glDisable(GL_SCISSOR_TEST);
- } else {
- glEnable(GL_SCISSOR_TEST);
- setScissor(bounds);
- }
-#endif
-}
-
-void QGL2PaintEngineExPrivate::setScissor(const QRect &rect)
-{
- const int left = rect.left();
- const int width = rect.width();
- int bottom = height - (rect.top() + rect.height());
- if (device->isFlipped()) {
- bottom = rect.top();
- }
- const int height = rect.height();
-
- glScissor(left, bottom, width, height);
-}
-
-void QGL2PaintEngineEx::clipEnabledChanged()
-{
- Q_D(QGL2PaintEngineEx);
-
- state()->clipChanged = true;
-
- if (painter()->hasClipping())
- d->regenerateClip();
- else
- d->systemStateChanged();
-}
-
-void QGL2PaintEngineExPrivate::clearClip(uint value)
-{
- dirtyStencilRegion -= currentScissorBounds;
-
- glStencilMask(0xff);
- glClearStencil(value);
- glClear(GL_STENCIL_BUFFER_BIT);
- glStencilMask(0x0);
-
- q->state()->needsClipBufferClear = false;
-}
-
-void QGL2PaintEngineExPrivate::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()) {
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT);
- return;
- }
-
- if (q->state()->clipTestEnabled)
- glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
- else
- glStencilFunc(GL_ALWAYS, 0, 0xff);
-
- vertexCoordinateArray.clear();
- vertexCoordinateArray.addPath(path, inverseScale, false);
-
- if (!singlePass)
- fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
-
- glColorMask(false, false, false, false);
- 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
-
- glStencilFunc(GL_LEQUAL, referenceClipValue, ~GL_STENCIL_HIGH_BIT);
- glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT);
- glStencilMask(value ^ referenceClipValue);
-
- drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
- } else {
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
- glStencilMask(0xff);
-
- if (!q->state()->clipTestEnabled && path.hasWindingFill()) {
- // Pass when any clip bit is set, set high bit
- 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
- glStencilFunc(GL_NOTEQUAL, value, GL_STENCIL_HIGH_BIT);
-
- composite(vertexCoordinateArray.boundingRect());
- }
-
- glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT);
- glStencilMask(0);
-
- glColorMask(true, true, true, true);
-}
-
-void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
-{
-// qDebug("QGL2PaintEngineEx::clip()");
- Q_D(QGL2PaintEngineEx);
-
- 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 QGL2PaintEngineExPrivate::regenerateClip()
-{
- systemStateChanged();
- replayClipOperations();
-}
-
-void QGL2PaintEngineExPrivate::systemStateChanged()
-{
- Q_Q(QGL2PaintEngineEx);
-
- 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;
- } 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 QGL2PaintEngineEx::setTranslateZ(GLfloat z)
-{
- Q_D(QGL2PaintEngineEx);
- if (d->translateZ != z) {
- d->translateZ = z;
- d->translateZUniformDirty = true;
- }
-}
-
-void QGL2PaintEngineEx::setState(QPainterState *new_state)
-{
- // qDebug("QGL2PaintEngineEx::setState()");
-
- Q_D(QGL2PaintEngineEx);
-
- QGL2PaintEngineState *s = static_cast<QGL2PaintEngineState *>(new_state);
- QGL2PaintEngineState *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->glDepthFunc(GL_LEQUAL);
- } else {
- d->regenerateClip();
- }
- }
-}
-
-QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const
-{
- if (orig)
- const_cast<QGL2PaintEngineEx *>(this)->ensureActive();
-
- QGL2PaintEngineState *s;
- if (!orig)
- s = new QGL2PaintEngineState();
- else
- s = new QGL2PaintEngineState(*static_cast<QGL2PaintEngineState *>(orig));
-
- s->matrixChanged = false;
- s->compositionModeChanged = false;
- s->opacityChanged = false;
- s->renderHintsChanged = false;
- s->clipChanged = false;
-
- return s;
-}
-
-QGL2PaintEngineState::QGL2PaintEngineState(QGL2PaintEngineState &other)
- : QPainterState(other)
-{
- isNew = true;
- needsClipBufferClear = other.needsClipBufferClear;
- clipTestEnabled = other.clipTestEnabled;
- currentClip = other.currentClip;
- canRestoreClip = other.canRestoreClip;
- rectangleClip = other.rectangleClip;
-}
-
-QGL2PaintEngineState::QGL2PaintEngineState()
-{
- isNew = true;
- needsClipBufferClear = true;
- clipTestEnabled = false;
- canRestoreClip = true;
-}
-
-QGL2PaintEngineState::~QGL2PaintEngineState()
-{
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
deleted file mode 100644
index 762aac2f65..0000000000
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 QPAINTENGINEEX_OPENGL2_P_H
-#define QPAINTENGINEEX_OPENGL2_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 <QDebug>
-
-#include <private/qpaintengineex_p.h>
-#include <private/qglengineshadermanager_p.h>
-#include <private/qgl2pexvertexarray_p.h>
-#include <private/qglpaintdevice_p.h>
-#include <private/qfontengine_p.h>
-#include <private/qdatabuffer_p.h>
-#include <private/qtriangulatingstroker_p.h>
-#include <private/qopenglextensions_p.h>
-
-enum EngineMode {
- ImageDrawingMode,
- TextDrawingMode,
- BrushDrawingMode,
- ImageArrayDrawingMode
-};
-
-QT_BEGIN_NAMESPACE
-
-#define GL_STENCIL_HIGH_BIT GLuint(0x80)
-#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 QGL2PaintEngineExPrivate;
-
-
-class QGL2PaintEngineState : public QPainterState
-{
-public:
- QGL2PaintEngineState(QGL2PaintEngineState &other);
- QGL2PaintEngineState();
- ~QGL2PaintEngineState();
-
- 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_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx
-{
- Q_DECLARE_PRIVATE(QGL2PaintEngineEx)
-public:
- QGL2PaintEngineEx();
- ~QGL2PaintEngineEx();
-
- 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 QGL2PaintEngineState *state() {
- return static_cast<QGL2PaintEngineState *>(QPaintEngineEx::state());
- }
- inline const QGL2PaintEngineState *state() const {
- return static_cast<const QGL2PaintEngineState *>(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;
-
- void setTranslateZ(GLfloat z);
-
-private:
- Q_DISABLE_COPY_MOVE(QGL2PaintEngineEx)
-};
-
-class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate, protected QOpenGLExtensions
-{
- Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
-public:
- enum StencilFillMode {
- OddEvenFillMode,
- WindingFillMode,
- TriStripStrokeFillMode
- };
-
- QGL2PaintEngineExPrivate(QGL2PaintEngineEx *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),
- lastMaskTextureUsed(0),
- translateZ(0)
- { }
-
- ~QGL2PaintEngineExPrivate();
-
- void updateBrushTexture();
- void updateBrushUniforms();
- void updateMatrix();
- void updateCompositionMode();
- void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1));
-
- void resetGLState();
- bool resetOpenGLContextActiveEngine();
-
- // 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 QGLRect& dest, const QGLRect& 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 setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer);
-
- // draws whatever is in the vertex array:
- void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive);
- void drawVertexArrays(QGL2PEXVertexArray &vertexArray, GLenum primitive) {
- drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive);
- }
-
- // Composites the bounding rect onto dest buffer:
- void composite(const QGLRect& boundingRect);
-
- // Calls drawVertexArrays to render into stencil buffer:
- void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QGLRect &bounds, StencilFillMode mode);
- void fillStencilWithVertexArray(QGL2PEXVertexArray& 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 QGLEngineShaderManager::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;
-
-
- static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
- static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); }
- static void cleanupVectorPath(QPaintEngineEx *engine, void *data);
-
-
- QGL2PaintEngineEx* q;
- QGLEngineShaderManager* shaderManager;
- QGLPaintDevice* device;
- int width, height;
- QGLContext *ctx;
- EngineMode mode;
- QFontEngine::GlyphFormat glyphCacheFormat;
-
- // Dirty flags
- bool matrixDirty; // Implies matrix uniforms are also dirty
- bool compositionModeDirty;
- bool brushTextureDirty;
- bool brushUniformsDirty;
- bool opacityUniformDirty;
- bool matrixUniformDirty;
- bool translateZUniformDirty;
-
- 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;
-
- QPixmap currentBrushPixmap;
-
- QGL2PEXVertexArray vertexCoordinateArray;
- QGL2PEXVertexArray 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;
-
- GLuint lastTextureUsed;
- GLuint lastMaskTextureUsed;
-
- bool needsSync;
- bool multisamplingAlwaysEnabled;
-
- GLfloat depthRange[2];
-
- float textureInvertedY;
-
- QTriangulatingStroker stroker;
- QDashedStrokeProcessor dasher;
-
- QSet<QVectorPath::CacheEntry *> pathCaches;
- QVector<GLuint> unusedVBOSToClean;
- QVector<GLuint> unusedIBOSToClean;
-
- const GLfloat *vertexAttribPointers[3];
-
- GLfloat translateZ;
-};
-
-
-void QGL2PaintEngineExPrivate::setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer)
-{
- Q_ASSERT(arrayIndex < 3);
- if (pointer == vertexAttribPointers[arrayIndex])
- return;
-
- vertexAttribPointers[arrayIndex] = pointer;
- if (arrayIndex == QT_OPACITY_ATTR)
- glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, pointer);
- else
- glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, pointer);
-}
-
-QT_END_NAMESPACE
-
-#endif // QPAINTENGINEEX_OPENGL2_P_H
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
deleted file mode 100644
index d5ce4efd1a..0000000000
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ /dev/null
@@ -1,414 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 "qtextureglyphcache_gl_p.h"
-#include "qpaintengineex_opengl2_p.h"
-#include "qglfunctions.h"
-#include "private/qglengineshadersource_p.h"
-
-QT_BEGIN_NAMESPACE
-
-
-static int next_qgltextureglyphcache_serial_number()
-{
- static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
- return 1 + serial.fetchAndAddRelaxed(1);
-}
-
-QGLTextureGlyphCache::QGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix)
- : QImageTextureGlyphCache(format, matrix)
- , m_textureResource(0)
- , pex(0)
- , m_blitProgram(0)
- , m_filterMode(Nearest)
- , m_serialNumber(next_qgltextureglyphcache_serial_number())
-{
-#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
- qDebug(" -> QGLTextureGlyphCache() %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;
-}
-
-QGLTextureGlyphCache::~QGLTextureGlyphCache()
-{
-#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
- qDebug(" -> ~QGLTextureGlyphCache() %p.", this);
-#endif
- delete m_blitProgram;
- if (m_textureResource)
- m_textureResource->free();
-}
-
-void QGLTextureGlyphCache::createTextureData(int width, int height)
-{
- QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
- if (ctx == 0) {
- qWarning("QGLTextureGlyphCache::createTextureData: Called with no context");
- return;
- }
- QOpenGLFunctions *funcs = ctx->contextHandle()->functions();
-
- // 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 ((!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->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 = 0;
- }
-
- if (!m_textureResource)
- m_textureResource = new QGLGlyphTexture(ctx);
-
- 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) {
- 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;
- funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, 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;
-}
-
-void QGLTextureGlyphCache::resizeTextureData(int width, int height)
-{
- QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
- if (ctx == 0) {
- qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context");
- return;
- }
- QOpenGLFunctions *funcs = ctx->contextHandle()->functions();
-
- 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 (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->workaround_brokenFBOReadBack) {
- QImageTextureGlyphCache::resizeTextureData(width, height);
- Q_ASSERT(image().depth() == 8);
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits());
- funcs->glDeleteTextures(1, &oldTexture);
- return;
- }
-
- // ### the QTextureGlyphCache API needs to be reworked to allow
- // ### resizeTextureData to fail
-
- ctx->d_ptr->refreshCurrentFbo();
-
- 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, NULL);
- 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 != 0)
- 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);
-
- QGLShaderProgram *blitProgram = 0;
- if (pex == 0) {
- if (m_blitProgram == 0) {
- m_blitProgram = new QGLShaderProgram(ctx);
-
- {
- QString source;
- source.append(QLatin1String(qglslMainWithTexCoordsVertexShader));
- source.append(QLatin1String(qglslUntransformedPositionVertexShader));
-
- QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, m_blitProgram);
- vertexShader->compileSourceCode(source);
-
- m_blitProgram->addShader(vertexShader);
- }
-
- {
- QString source;
- source.append(QLatin1String(qglslMainFragmentShader));
- source.append(QLatin1String(qglslImageSrcFragmentShader));
-
- QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, m_blitProgram);
- fragmentShader->compileSourceCode(source);
-
- m_blitProgram->addShader(fragmentShader);
- }
-
- m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
- m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
-
- m_blitProgram->link();
- }
-
- funcs->glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_vertexCoordinateArray);
- funcs->glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_textureCoordinateArray);
-
- m_blitProgram->bind();
- m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
- m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
- m_blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR));
-
- blitProgram = m_blitProgram;
-
- } else {
- pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, m_vertexCoordinateArray);
- pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, m_textureCoordinateArray);
-
- 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, ctx->d_ptr->current_fbo);
-
- if (pex != 0) {
- funcs->glViewport(0, 0, pex->width, pex->height);
- pex->updateClipScissorTest();
- }
-}
-
-void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition)
-{
- QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
- if (ctx == 0) {
- qWarning("QGLTextureGlyphCache::fillTexture: Called with no context");
- return;
- }
- QOpenGLFunctions *funcs = ctx->contextHandle()->functions();
-
- if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->workaround_brokenFBOReadBack) {
- QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition);
-
- funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
- const QImage &texture = image();
- const uchar *bits = texture.constBits();
- bits += c.y * texture.bytesPerLine() + c.x;
- for (int i=0; i<c.h; ++i) {
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits);
- bits += texture.bytesPerLine();
- }
- return;
- }
-
- QImage mask = textureMapForGlyph(glyph, subPixelPosition);
- const int maskWidth = mask.width();
- const int maskHeight = mask.height();
-
- if (mask.format() == QImage::Format_Mono) {
- mask = mask.convertToFormat(QImage::Format_Indexed8);
- for (int y = 0; y < maskHeight; ++y) {
- uchar *src = (uchar *) mask.scanLine(y);
- for (int x = 0; x < maskWidth; ++x)
- src[x] = -src[x]; // convert 0 and 1 into 0 and 255
- }
- } else if (mask.depth() == 32) {
- // Make the alpha component equal to the average of the RGB values.
- // This is needed when drawing sub-pixel antialiased text on translucent targets.
- for (int y = 0; y < maskHeight; ++y) {
- quint32 *src = (quint32 *) mask.scanLine(y);
- for (int x = 0; x < maskWidth; ++x) {
- int r = qRed(src[x]);
- int g = qGreen(src[x]);
- int b = qBlue(src[x]);
- int avg;
- if (mask.format() == QImage::Format_RGB32)
- avg = (r + g + b + 1) / 3; // "+1" for rounding.
- else // Format_ARGB_Premultiplied
- avg = qAlpha(src[x]);
- if (ctx->contextHandle()->isOpenGLES()) {
- // swizzle the bits to accommodate for the GL_RGBA upload.
- src[x] = (avg << 24) | (r << 0) | (g << 8) | (b << 16);
- } else {
- src[x] = (src[x] & 0x00ffffff) | (avg << 24);
- }
- }
- }
- }
-
- funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
- if (mask.depth() == 32) {
- GLenum format = GL_RGBA;
-#if !defined(QT_OPENGL_ES_2)
- if (!ctx->contextHandle()->isOpenGLES())
- format = GL_BGRA;
-#endif
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, format, GL_UNSIGNED_BYTE, mask.bits());
- } else {
- // glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is
- // not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista
- // and nVidia GeForce 8500GT. GL_UNPACK_ALIGNMENT is set to four bytes, 'mask' has a
- // multiple of four bytes per line, and most of the glyph shows up correctly in the
- // texture, which makes me think that this is a driver bug.
- // One workaround is to make sure the mask width is a multiple of four bytes, for instance
- // by converting it to a format with four bytes per pixel. Another is to copy one line at a
- // time.
-
- if (!ctx->d_ptr->workaround_brokenAlphaTexSubImage_init) {
- // don't know which driver versions exhibit this bug, so be conservative for now
- const QByteArray vendorString(reinterpret_cast<const char*>(funcs->glGetString(GL_VENDOR)));
- ctx->d_ptr->workaround_brokenAlphaTexSubImage = vendorString.indexOf("NVIDIA") >= 0;
- ctx->d_ptr->workaround_brokenAlphaTexSubImage_init = true;
- }
-
- if (ctx->d_ptr->workaround_brokenAlphaTexSubImage) {
- for (int i = 0; i < maskHeight; ++i)
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i));
- } else {
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
- }
- }
-}
-
-int QGLTextureGlyphCache::glyphPadding() const
-{
- return 1;
-}
-
-int QGLTextureGlyphCache::maxTextureWidth() const
-{
- QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
- if (ctx == 0)
- return QImageTextureGlyphCache::maxTextureWidth();
- else
- return ctx->d_ptr->maxTextureSize();
-}
-
-int QGLTextureGlyphCache::maxTextureHeight() const
-{
- QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
- if (ctx == 0)
- return QImageTextureGlyphCache::maxTextureHeight();
-
- if (ctx->d_ptr->workaround_brokenTexSubImage)
- return qMin(1024, ctx->d_ptr->maxTextureSize());
- else
- return ctx->d_ptr->maxTextureSize();
-}
-
-void QGLTextureGlyphCache::clear()
-{
- m_textureResource->free();
- m_textureResource = 0;
-
- m_w = 0;
- m_h = 0;
- m_cx = 0;
- m_cy = 0;
- m_currentRowHeight = 0;
- coords.clear();
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
deleted file mode 100644
index 7c12ce8998..0000000000
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL 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 QTEXTUREGLYPHCACHE_GL_P_H
-#define QTEXTUREGLYPHCACHE_GL_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 <private/qtextureglyphcache_p.h>
-#include <private/qgl_p.h>
-#include <qglshaderprogram.h>
-#include <qglframebufferobject.h>
-#include <qopenglfunctions.h>
-
-// #define QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
-
-QT_BEGIN_NAMESPACE
-
-class QGL2PaintEngineExPrivate;
-
-struct QGLGlyphTexture : public QOpenGLSharedResource
-{
- QGLGlyphTexture(const QGLContext *ctx)
- : QOpenGLSharedResource(ctx->contextHandle()->shareGroup())
- , m_fbo(0)
- , m_width(0)
- , m_height(0)
- {
- if (ctx && QGLFramebufferObject::hasOpenGLFramebufferObjects() && !ctx->d_ptr->workaround_brokenFBOReadBack)
- ctx->contextHandle()->functions()->glGenFramebuffers(1, &m_fbo);
-
-#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
- qDebug(" -> QGLGlyphTexture() %p for context %p.", this, ctx);
-#endif
- }
-
- void freeResource(QOpenGLContext *context) override
- {
- const QGLContext *ctx = QGLContext::fromOpenGLContext(context);
-#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
- qDebug("~QGLGlyphTexture() %p for context %p.", this, ctx);
-#else
- Q_UNUSED(ctx);
-#endif
- if (ctx && m_fbo)
- ctx->contextHandle()->functions()->glDeleteFramebuffers(1, &m_fbo);
- if (m_width || m_height)
- ctx->contextHandle()->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_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache
-{
-public:
- QGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix);
- ~QGLTextureGlyphCache();
-
- 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 {
- QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
- QGLGlyphTexture *glyphTexture = that->m_textureResource;
- return glyphTexture ? glyphTexture->m_texture : 0;
- }
-
- inline int width() const {
- QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
- QGLGlyphTexture *glyphTexture = that->m_textureResource;
- return glyphTexture ? glyphTexture->m_width : 0;
- }
- inline int height() const {
- QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
- QGLGlyphTexture *glyphTexture = that->m_textureResource;
- return glyphTexture ? glyphTexture->m_height : 0;
- }
-
- inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *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();
-
-private:
- QGLGlyphTexture *m_textureResource;
-
- QGL2PaintEngineExPrivate *pex;
- QGLShaderProgram *m_blitProgram;
- FilterMode m_filterMode;
-
- GLfloat m_vertexCoordinateArray[8];
- GLfloat m_textureCoordinateArray[8];
-
- int m_serialNumber;
-};
-
-QT_END_NAMESPACE
-
-#endif
-